{"version":3,"file":"salaxy-lib-ng1.umd.cjs","sources":["../../../@salaxy/ng1/ts/ajax/AjaxNg1.ts","../../../@salaxy/ng1/ts/controllers/bases/WizardController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/CustomerOnboardingController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/WorkerOnboardingController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/HouseholdOnboardingController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/CompanyOnboardingController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/SigningController.ts","../../../@salaxy/ng1/ts/controllers/account/onboarding/SignatureController.ts","../../../@salaxy/ng1/ts/controllers/bases/CrudControllerBase.ts","../../../@salaxy/ng1/ts/controllers/account/AccountAuthorizationController.ts","../../../@salaxy/ng1/ts/controllers/account/CertificateController.ts","../../../node_modules/.pnpm/angular@1.8.3/node_modules/angular/angular.js","../../../node_modules/.pnpm/angular@1.8.3/node_modules/angular/index.js","../../../@salaxy/ng1/ts/controllers/bases/ApiCrudObjectController.ts","../../../@salaxy/ng1/ts/controllers/bases/ApiCrudObjectControllerBindings.ts","../../../@salaxy/ng1/ts/controllers/bases/ListControllerBase.ts","../../../@salaxy/ng1/ts/controllers/bases/ListControllerBaseBindings.ts","../../../@salaxy/ng1/ts/controllers/bases/ODataHelperController.ts","../../../@salaxy/ng1/ts/controllers/bases/ODataQueryController.ts","../../../@salaxy/ng1/ts/controllers/account/CertificateCrudController.ts","../../../@salaxy/ng1/ts/services/ui/model/EditDialogKnownActions.ts","../../../@salaxy/ng1/ts/services/ui/model/EditDialogParameters.ts","../../../@salaxy/ng1/ts/services/ui/model/EditDialogResult.ts","../../../@salaxy/ng1/ts/services/ui/AlertService.ts","../../../node_modules/.pnpm/@progress+pako-esm@1.0.1/node_modules/@progress/pako-esm/dist/pako-esm5.js","../../../node_modules/.pnpm/@progress+jszip-esm@1.0.3/node_modules/@progress/jszip-esm/dist/jszip-esm5.js","../../../node_modules/.pnpm/file-saver@2.0.5/node_modules/file-saver/dist/FileSaver.min.js","../../../@salaxy/ng1/ts/services/ui/ExcelHelpers.ts","../../../@salaxy/ng1/ts/services/ui/FileService.ts","../../../@salaxy/ng1/ts/services/ui/GravatarHelpers.ts","../../../@salaxy/ng1/ts/services/ui/JsonSchemaService.ts","../../../@salaxy/ng1/ts/helpers/AppInsightExceptionTracking.ts","../../../@salaxy/ng1/ts/helpers/CalendarHelper.ts","../../../@salaxy/ng1/ts/helpers/sitemap_PersonLeafs.ts","../../../@salaxy/ng1/ts/helpers/sitemap_Company.ts","../../../@salaxy/ng1/ts/helpers/SitemapHelper.ts","../../../@salaxy/ng1/ts/helpers/CurrentRoute.ts","../../../@salaxy/ng1/ts/helpers/PromisePolyfill.ts","../../../@salaxy/ng1/ts/helpers/RouteHelperProvider.ts","../../../@salaxy/ng1/ts/helpers/RRuleFinnish.ts","../../../@salaxy/ng1/ts/services/ui/NaviService.ts","../../../@salaxy/ng1/ts/services/ui/UiCrudHelpers.ts","../../../@salaxy/ng1/ts/services/ui/UiHelpers.ts","../../../@salaxy/ng1/ts/services/ui/WizardService.ts","../../../@salaxy/ng1/ts/services/BaseService.ts","../../../@salaxy/ng1/ts/services/AuthorizedAccountService.ts","../../../@salaxy/ng1/ts/services/CacheService.ts","../../../@salaxy/ng1/ts/services/CertificateService.ts","../../../@salaxy/ng1/ts/services/CredentialService.ts","../../../@salaxy/ng1/ts/controllers/calc/PayrollLogic.ts","../../../@salaxy/ng1/ts/services/InvoicesService.ts","../../../@salaxy/ng1/ts/services/OnboardingService.ts","../../../@salaxy/ng1/ts/services/PartnerService.ts","../../../@salaxy/ng1/ts/services/ReportsService.ts","../../../@salaxy/ng1/ts/services/RowTypeService.ts","../../../@salaxy/ng1/ts/services/SessionService.ts","../../../@salaxy/ng1/ts/services/SettingsService.ts","../../../@salaxy/ng1/ts/services/SignatureService.ts","../../../@salaxy/ng1/ts/services/UiTranslatorService.ts","../../../@salaxy/ng1/ts/services/UploadService.ts","../../../@salaxy/ng1/ts/services/UsecasesService.ts","../../../@salaxy/ng1/ts/services/UserSettingsService.ts","../../../@salaxy/ng1/ts/services/VarmaPensionService.ts","../../../@salaxy/ng1/ts/services/WorkflowService.ts","../../../@salaxy/ng1/ts/controllers/account/CredentialController.ts","../../../@salaxy/ng1/ts/controllers/account/EmbeddedUiController.ts","../../../@salaxy/ng1/ts/controllers/account/PartnerController.ts","../../../@salaxy/ng1/ts/controllers/account/SessionController.ts","../../../@salaxy/ng1/ts/controllers/account/CompanyAccountController.ts","../../../@salaxy/ng1/ts/controllers/calc/2022/CalcEmploymentController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalculationCrudController.ts","../../../@salaxy/ng1/ts/controllers/calc/2022/Calculator2022Controller.ts","../../../@salaxy/ng1/ts/controllers/calc/salary-bases/SalaryBasesController.ts","../../../node_modules/.pnpm/@kurkle+color@0.3.2/node_modules/@kurkle/color/dist/color.esm.js","../../../node_modules/.pnpm/chart.js@4.4.2/node_modules/chart.js/dist/chunks/helpers.segment.js","../../../node_modules/.pnpm/chart.js@4.4.2/node_modules/chart.js/dist/chart.js","../../../@salaxy/ng1/ts/controllers/calc/CalcChartController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcHouseholdUsecaseController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalculatorSection.ts","../../../@salaxy/ng1/ts/controllers/calc/CalculatorSections.ts","../../../@salaxy/ng1/ts/controllers/calc/Calculator2019Controller.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcIrRowsController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcReportController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcReportsController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcReportsDisplayController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcRowTypeController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcWorktimeController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcRowDimensionInputController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcRows2019Controller.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcSharingReceiptActionController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcsIrRowsController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalculatorPanels.ts","../../../@salaxy/ng1/ts/controllers/calc/CreditTransferController.ts","../../../@salaxy/ng1/ts/controllers/calc/PayrollCrudController.ts","../../../@salaxy/ng1/ts/controllers/calc/Payroll4CrudController.ts","../../../@salaxy/ng1/ts/controllers/calc/PaymentController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalculationEditorController.ts","../../../@salaxy/ng1/ts/controllers/calc/CostAccountingController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcCostAccountingController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcRowCostAccountingController.ts","../../../@salaxy/ng1/ts/controllers/calc/PalkkausPersonalPaymentOverviewController.ts","../../../@salaxy/ng1/ts/controllers/calc/SalaryDateKindController.ts","../../../@salaxy/ng1/ts/controllers/calc/CalcLeavesController.ts","../../../@salaxy/ng1/ts/controllers/communications/ContactInfoController.ts","../../../@salaxy/ng1/ts/controllers/communications/MessageThreadCrudController.ts","../../../@salaxy/ng1/ts/controllers/communications/OmapalkkaController.ts","../../../@salaxy/ng1/ts/controllers/communications/VarmaBannerController.ts","../../../@salaxy/ng1/ts/controllers/communications/WelcomeController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/_InputBase.ts","../../../@salaxy/ng1/ts/controllers/form-controls/DatepickerController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/DatepickerPopupController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/DateRangeController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/FormGroupController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputAccountingTargetController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputBooleanController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputEnumController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputCredentialController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputDurationController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputIncomeTypeController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputNumberController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputOccupationTypeController.ts","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/weekday.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/helpers.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/dateutil.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterresult.js","../../../node_modules/.pnpm/tslib@2.6.2/node_modules/tslib/tslib.es6.mjs","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/callbackiterresult.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/nlp/i18n.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/nlp/totext.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/nlp/parsetext.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/types.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/nlp/index.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/datetime.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/parseoptions.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/parsestring.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/datewithzone.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/optionstostring.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/cache.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/masks.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterinfo/yearinfo.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterinfo/monthinfo.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterinfo/easter.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterinfo/index.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iter/poslist.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iter/index.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/rrule.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/iterset.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/rrulestr.js","../../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/rruleset.js","../../../@salaxy/ng1/ts/controllers/form-controls/InputRruleController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/ValidationSummaryController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputTimeController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputHolidayMultipliersController.ts","../../../@salaxy/ng1/ts/controllers/form-controls/InputHolidayRowTypeController.ts","../../../@salaxy/ng1/ts/controllers/helpers/ActionButtonController.ts","../../../@salaxy/ng1/ts/controllers/helpers/AlertController.ts","../../../@salaxy/ng1/ts/controllers/helpers/AvatarController.ts","../../../@salaxy/ng1/ts/controllers/helpers/BatchProcessController.ts","../../../@salaxy/ng1/ts/controllers/helpers/CalendarController.ts","../../../node_modules/.pnpm/chartjs-plugin-annotation@3.0.1_chart.js@4.4.2/node_modules/chartjs-plugin-annotation/dist/chartjs-plugin-annotation.esm.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/dayjs.min.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/plugin/customParseFormat.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/plugin/advancedFormat.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/plugin/quarterOfYear.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/plugin/localizedFormat.js","../../../node_modules/.pnpm/dayjs@1.11.10/node_modules/dayjs/plugin/isoWeek.js","../../../node_modules/.pnpm/chartjs-adapter-dayjs-4@1.0.4_chart.js@4.4.2_dayjs@1.11.10/node_modules/chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm.js","../../../@salaxy/ng1/ts/controllers/helpers/ChartController.ts","../../../@salaxy/ng1/ts/controllers/helpers/JsonFormatterController.ts","../../../@salaxy/ng1/ts/controllers/helpers/NaviController.ts","../../../@salaxy/ng1/ts/controllers/helpers/SpinnerController.ts","../../../@salaxy/ng1/ts/controllers/helpers/TabController.ts","../../../@salaxy/ng1/ts/controllers/helpers/TabsController.ts","../../../@salaxy/ng1/ts/controllers/helpers/UiTranslatorController.ts","../../../@salaxy/ng1/ts/controllers/helpers/ODataActionsController.ts","../../../@salaxy/ng1/ts/controllers/helpers/ImportController.ts","../../../@salaxy/ng1/ts/controllers/helpers/ExportController.ts","../../../node_modules/.pnpm/tabulator-tables@5.6.1/node_modules/tabulator-tables/dist/js/tabulator_esm.js","../../../@salaxy/ng1/ts/controllers/helpers/import/DataImportControllerBase.ts","../../../@salaxy/ng1/ts/controllers/helpers/import/CompanyImportController.ts","../../../@salaxy/ng1/ts/controllers/helpers/import/CalcImportController.ts","../../../@salaxy/ng1/ts/controllers/helpers/import/ImportStagingController.ts","../../../@salaxy/ng1/ts/controllers/helpers/import/WorkerImportController.ts","../../../@salaxy/ng1/ts/controllers/invoices/CustomerInvoiceCrudController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoiceCrudController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoicesCreateController.ts","../../../@salaxy/ng1/ts/controllers/invoices/PaymentChannelController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoiceToolsController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoiceSepaController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoiceReportController.ts","../../../@salaxy/ng1/ts/controllers/invoices/CompanyInvoicesController.ts","../../../@salaxy/ng1/ts/controllers/invoices/InvoiceAlertsController.ts","../../../@salaxy/ng1/ts/controllers/modals/EditDialogController.ts","../../../@salaxy/ng1/ts/controllers/modals/ModalGenericDialogController.ts","../../../@salaxy/ng1/ts/controllers/personal/CalcSharingController.ts","../../../@salaxy/ng1/ts/controllers/personal/EmployerListController.ts","../../../@salaxy/ng1/ts/controllers/personal/EmployerReportController.ts","../../../@salaxy/ng1/ts/controllers/personal/EmployerSelectController.ts","../../../@salaxy/ng1/ts/controllers/personal/HouseholdDeductionReportController.ts","../../../@salaxy/ng1/ts/controllers/personal/HouseholdYearCrudController.ts","../../../@salaxy/ng1/ts/controllers/personal/PersonAccountController.ts","../../../@salaxy/ng1/ts/controllers/personal/WorkerReportController.ts","../../../@salaxy/ng1/ts/controllers/personal/TimesheetWorkerDemoController.ts","../../../@salaxy/ng1/ts/controllers/personal/WorkerTimerController.ts","../../../@salaxy/ng1/ts/controllers/personal/WorkerHourlyReportController.ts","../../../@salaxy/ng1/ts/controllers/personal/WorkerExpenseReportController.ts","../../../@salaxy/ng1/ts/controllers/records/RecordsController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingReportCrudController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingReportQueryController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingReportRowsController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingReportToolsController.ts","../../../@salaxy/ng1/ts/controllers/report/IrEarningsPaymentCrudController.ts","../../../@salaxy/ng1/ts/controllers/report/IrPayerSummaryCrudController.ts","../../../@salaxy/ng1/ts/controllers/report/ReportsController.ts","../../../@salaxy/ng1/ts/controllers/report/SalaryReportCrudController.ts","../../../@salaxy/ng1/ts/controllers/report/PayCertificateController.ts","../../../@salaxy/ng1/ts/controllers/report/ConfigurableGridReportControllerBase.ts","../../../@salaxy/ng1/ts/controllers/report/CalculationReportController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingRowReportController.ts","../../../@salaxy/ng1/ts/controllers/report/SummaryReportDisplayController.ts","../../../@salaxy/ng1/ts/controllers/report/SummaryReportController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingReportDisplayController.ts","../../../@salaxy/ng1/ts/controllers/report/WorkerSummaryReportController.ts","../../../@salaxy/ng1/ts/controllers/report/WorkerSummaryReportDisplayController.ts","../../../@salaxy/ng1/ts/controllers/report/HolidayReportController.ts","../../../@salaxy/ng1/ts/controllers/report/SalarySlipDownloadController.ts","../../../@salaxy/ng1/ts/controllers/report/AccountingHolidayPayDebtReportQueryController.ts","../../../@salaxy/ng1/ts/controllers/report/HolidayPayReportQueryController.ts","../../../@salaxy/ng1/ts/controllers/report/SummaryReportQueryController.ts","../../../@salaxy/ng1/ts/controllers/settings/AccountantController.ts","../../../@salaxy/ng1/ts/controllers/settings/AccountingChannelSettingsController.ts","../../../@salaxy/ng1/ts/controllers/settings/AccountingTargetCrudController.ts","../../../@salaxy/ng1/ts/controllers/settings/CompanySettingsController.ts","../../../@salaxy/ng1/ts/controllers/settings/InsuranceWizardController.ts","../../../@salaxy/ng1/ts/controllers/settings/OwnerSettingsController.ts","../../../@salaxy/ng1/ts/controllers/settings/PaymentChannelSettingsController.ts","../../../@salaxy/ng1/ts/controllers/settings/RowTypesSettingsController.ts","../../../@salaxy/ng1/ts/controllers/settings/ServiceModelCrudController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxyCodeEditorController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxyFormController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxyFormElementController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxyGridController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxyInputController.ts","../../../@salaxy/ng1/ts/controllers/sxy-form/SxySchemaEditorController.ts","../../../@salaxy/ng1/ts/controllers/sxy-table/SxyTableController.ts","../../../@salaxy/ng1/ts/controllers/test/AccountResetController.ts","../../../@salaxy/ng1/ts/controllers/test/SmokeTestController.ts","../../../@salaxy/ng1/ts/controllers/test/ReferenceObjectCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/AbsencePeriodsController.ts","../../../@salaxy/ng1/ts/controllers/worker/EmploymentCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/EmploymentTaxcardsController.ts","../../../@salaxy/ng1/ts/controllers/worker/EmploymentWizardController.ts","../../../@salaxy/ng1/ts/controllers/worker/HolidayYearAccrualController.ts","../../../@salaxy/ng1/ts/controllers/worker/HolidayYearCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/HolidayYearHolidaysController.ts","../../../@salaxy/ng1/ts/controllers/worker/HolidayYearPaidController.ts","../../../@salaxy/ng1/ts/controllers/worker/MyTaxcardsController.ts","../../../@salaxy/ng1/ts/controllers/worker/TaxcardManualEditController.ts","../../../@salaxy/ng1/ts/controllers/worker/TaxcardCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/TaxcardIncomeLogController.ts","../../../@salaxy/ng1/ts/controllers/worker/WorkerAbsencesCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/WorkerAccountCrudController.ts","../../../@salaxy/ng1/ts/controllers/worker/WorkerAssureController.ts","../../../@salaxy/ng1/ts/controllers/workflow/CalendarEventsCrudController.ts","../../../@salaxy/ng1/ts/controllers/workflow/CalendarOccurencesController.ts","../../../@salaxy/ng1/ts/controllers/workflow/DatasetsCrudController.ts","../../../@salaxy/ng1/ts/controllers/workflow/UsecasesCrudController.ts","../../../@salaxy/ng1/ts/controllers/workflow/WorkflowController.ts","../../../@salaxy/ng1/ts/controllers/workflow/WorkflowBadgeController.ts","../../../@salaxy/ng1/ts/components/_ComponentBase.ts","../../../@salaxy/ng1/ts/components/account/AccountInfo.ts","../../../@salaxy/ng1/ts/components/account/AssurePartner.ts","../../../@salaxy/ng1/ts/components/account/AuthCard.ts","../../../@salaxy/ng1/ts/components/account/AuthorizedAccounts.ts","../../../@salaxy/ng1/ts/components/account/AuthorizingAccounts.ts","../../../@salaxy/ng1/ts/components/account/Certificates.ts","../../../@salaxy/ng1/ts/components/account/Credentials.ts","../../../@salaxy/ng1/ts/components/account/LanguageSelector.ts","../../../@salaxy/ng1/ts/components/account/LoginButton.ts","../../../@salaxy/ng1/ts/components/account/Signing.ts","../../../@salaxy/ng1/ts/components/account/UserInfo.ts","../../../@salaxy/ng1/ts/components/account/AccountAvatarEdit.ts","../../../@salaxy/ng1/ts/components/account/AccountContactEdit.ts","../../../@salaxy/ng1/ts/components/calc/2022/CalcEmployment.ts","../../../@salaxy/ng1/ts/components/calc/2022/CalcRowsEditor.ts","../../../@salaxy/ng1/ts/components/calc/2022/CalcUsecase.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollDetails.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollDetailsList.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollEdit.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollList.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollSelectList.ts","../../../@salaxy/ng1/ts/components/calc/payroll/PayrollDetailsSelectList.ts","../../../@salaxy/ng1/ts/components/calc/rows/CalcIrRows.ts","../../../@salaxy/ng1/ts/components/calc/rows/CalcRows2019Editor.ts","../../../@salaxy/ng1/ts/components/calc/rows/CalcRowCostAccounting.ts","../../../@salaxy/ng1/ts/components/calc/rows/CalcRowDimensionInput.ts","../../../@salaxy/ng1/ts/components/calc/rows/CalcsIrRows.ts","../../../@salaxy/ng1/ts/components/calc/Calc.ts","../../../@salaxy/ng1/ts/components/calc/CalcChart.ts","../../../@salaxy/ng1/ts/components/calc/CalcDashboard.ts","../../../@salaxy/ng1/ts/components/calc/CalcList.ts","../../../@salaxy/ng1/ts/components/calc/CalcNewIntro.ts","../../../@salaxy/ng1/ts/components/calc/CalcReport.ts","../../../@salaxy/ng1/ts/components/calc/CalcReports.ts","../../../@salaxy/ng1/ts/components/calc/CalcResults.ts","../../../@salaxy/ng1/ts/components/calc/CalcRowType.ts","../../../@salaxy/ng1/ts/components/calc/CalcSharingReceiptAction.ts","../../../@salaxy/ng1/ts/components/calc/CalcLeaves.ts","../../../@salaxy/ng1/ts/components/calc/CalcWorkerInfo.ts","../../../@salaxy/ng1/ts/components/calc/CalcWorktime.ts","../../../@salaxy/ng1/ts/components/calc/PayButton.ts","../../../@salaxy/ng1/ts/components/calc/CalcEditor.ts","../../../@salaxy/ng1/ts/components/calc/CalcCostAccounting.ts","../../../@salaxy/ng1/ts/components/calc/CostAccounting.ts","../../../@salaxy/ng1/ts/components/calc/SalaryDateKindButton.ts","../../../@salaxy/ng1/ts/components/communications/ContactInfo.ts","../../../@salaxy/ng1/ts/components/communications/MessageThread.ts","../../../@salaxy/ng1/ts/components/communications/VarmaBanner.ts","../../../@salaxy/ng1/ts/components/communications/Welcome.ts","../../../@salaxy/ng1/ts/components/communications/workerMessages/HourlyReport.ts","../../../@salaxy/ng1/ts/components/communications/workerMessages/Timer.ts","../../../@salaxy/ng1/ts/components/communications/workerMessages/ExpenseReport.ts","../../../@salaxy/ng1/ts/components/communications/MessageThreadList.ts","../../../@salaxy/ng1/ts/components/form-controls/Datepicker.ts","../../../@salaxy/ng1/ts/components/form-controls/DatepickerPopup.ts","../../../@salaxy/ng1/ts/components/form-controls/DateRange.ts","../../../@salaxy/ng1/ts/components/form-controls/FormGroup.ts","../../../@salaxy/ng1/ts/components/form-controls/Input.ts","../../../@salaxy/ng1/ts/components/form-controls/InputBoolean.ts","../../../@salaxy/ng1/ts/components/form-controls/InputEnum.ts","../../../@salaxy/ng1/ts/components/form-controls/InputCredential.ts","../../../@salaxy/ng1/ts/components/form-controls/InputDuration.ts","../../../@salaxy/ng1/ts/components/form-controls/InputIncomeType.ts","../../../@salaxy/ng1/ts/components/form-controls/InputNumber.ts","../../../@salaxy/ng1/ts/components/form-controls/InputRrule.ts","../../../@salaxy/ng1/ts/components/form-controls/InputOccupationType.ts","../../../@salaxy/ng1/ts/components/form-controls/Textarea.ts","../../../@salaxy/ng1/ts/components/form-controls/ValidationSummary.ts","../../../@salaxy/ng1/ts/components/form-controls/InputAccountingTarget.ts","../../../@salaxy/ng1/ts/components/form-controls/InputTime.ts","../../../@salaxy/ng1/ts/components/form-controls/InputHolidayRowType.ts","../../../@salaxy/ng1/ts/components/form-controls/InputHolidayMultipliers.ts","../../../@salaxy/ng1/ts/components/helpers/ActionButton.ts","../../../@salaxy/ng1/ts/components/helpers/Alert.ts","../../../@salaxy/ng1/ts/components/helpers/Avatar.ts","../../../@salaxy/ng1/ts/components/helpers/Calendar.ts","../../../@salaxy/ng1/ts/components/helpers/Chart.ts","../../../@salaxy/ng1/ts/components/helpers/DataMapper.ts","../../../@salaxy/ng1/ts/components/helpers/JsonFormatter.ts","../../../@salaxy/ng1/ts/components/helpers/NaviSitemap.ts","../../../@salaxy/ng1/ts/components/helpers/NaviStarterLayout.ts","../../../@salaxy/ng1/ts/components/helpers/Spinner.ts","../../../@salaxy/ng1/ts/components/helpers/Tab.ts","../../../@salaxy/ng1/ts/components/helpers/Tabs.ts","../../../@salaxy/ng1/ts/components/helpers/UiTranslator.ts","../../../@salaxy/ng1/ts/components/helpers/import/DataImportComponentBase.ts","../../../@salaxy/ng1/ts/components/helpers/import/CalcImport.ts","../../../@salaxy/ng1/ts/components/helpers/import/CompanyImport.ts","../../../@salaxy/ng1/ts/components/helpers/import/ImportStaging.ts","../../../@salaxy/ng1/ts/components/helpers/import/WorkerImport.ts","../../../@salaxy/ng1/ts/components/invoices/CreditTransfer.ts","../../../@salaxy/ng1/ts/components/invoices/InvoiceEdit.ts","../../../@salaxy/ng1/ts/components/invoices/InvoiceList.ts","../../../@salaxy/ng1/ts/components/invoices/InvoicePreview.ts","../../../@salaxy/ng1/ts/components/invoices/InvoicesCreate.ts","../../../@salaxy/ng1/ts/components/invoices/PaymentChannelInvoicePreview.ts","../../../@salaxy/ng1/ts/components/invoices/InvoiceTools.ts","../../../@salaxy/ng1/ts/components/invoices/InvoiceReport.ts","../../../@salaxy/ng1/ts/components/invoices/CompanyInvoices.ts","../../../@salaxy/ng1/ts/components/invoices/InvoiceAlerts.ts","../../../@salaxy/ng1/ts/components/obsolete/WorkerAssure.ts","../../../@salaxy/ng1/ts/components/odata/OdataFooter.ts","../../../@salaxy/ng1/ts/components/odata/OdataTable.ts","../../../@salaxy/ng1/ts/components/odata/OdataActions.ts","../../../@salaxy/ng1/ts/components/personal/AccountAuthorizationPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountAvatarEditPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountContactEditPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountDetailsPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountDetailsEditPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountInfoPerson.ts","../../../@salaxy/ng1/ts/components/personal/AccountInsuranceEditPerson.ts","../../../@salaxy/ng1/ts/components/personal/EmployerList.ts","../../../@salaxy/ng1/ts/components/personal/EmployerReport.ts","../../../@salaxy/ng1/ts/components/personal/EmployerSelect.ts","../../../@salaxy/ng1/ts/components/personal/CalcHouseholdUsecase.ts","../../../@salaxy/ng1/ts/components/personal/CalcSharing.ts","../../../@salaxy/ng1/ts/components/personal/CalcSharingInfo.ts","../../../@salaxy/ng1/ts/components/personal/HouseholdDeductionReport.ts","../../../@salaxy/ng1/ts/components/personal/WorkerReport.ts","../../../@salaxy/ng1/ts/components/personal/HouseholdYearList.ts","../../../@salaxy/ng1/ts/components/personal/HouseholdYearDetails.ts","../../../@salaxy/ng1/ts/components/report/AccountingReportList.ts","../../../@salaxy/ng1/ts/components/report/AccountingReportQuery.ts","../../../@salaxy/ng1/ts/components/report/AccountingReportRows.ts","../../../@salaxy/ng1/ts/components/report/AccountingReportTools.ts","../../../@salaxy/ng1/ts/components/report/AccountingReportViewer.ts","../../../@salaxy/ng1/ts/components/report/CalculationReport.ts","../../../@salaxy/ng1/ts/components/report/HolidayReport.ts","../../../@salaxy/ng1/ts/components/report/IrEarningsPayment.ts","../../../@salaxy/ng1/ts/components/report/IrEarningsPaymentList.ts","../../../@salaxy/ng1/ts/components/report/IrPayerSummary.ts","../../../@salaxy/ng1/ts/components/report/IrPayerSummaryList.ts","../../../@salaxy/ng1/ts/components/report/PayCertificate.ts","../../../@salaxy/ng1/ts/components/report/ReportList.ts","../../../@salaxy/ng1/ts/components/report/SalaryReportList.ts","../../../@salaxy/ng1/ts/components/report/AccountingRowReport.ts","../../../@salaxy/ng1/ts/components/report/SummaryReport.ts","../../../@salaxy/ng1/ts/components/report/WorkerSummaryReport.ts","../../../@salaxy/ng1/ts/components/report/AccountingHolidayPayDebtReportQuery.ts","../../../@salaxy/ng1/ts/components/report/HolidayPayReportQuery.ts","../../../@salaxy/ng1/ts/components/report/SummaryReportQuery.ts","../../../@salaxy/ng1/ts/components/settings/Accountant.ts","../../../@salaxy/ng1/ts/components/settings/AccountingSettings.ts","../../../@salaxy/ng1/ts/components/settings/AccountingTargetDetails.ts","../../../@salaxy/ng1/ts/components/settings/AccountingTargetSettings.ts","../../../@salaxy/ng1/ts/components/settings/CostAccountingSettings.ts","../../../@salaxy/ng1/ts/components/settings/HolidaySettings.ts","../../../@salaxy/ng1/ts/components/settings/Insurance.ts","../../../@salaxy/ng1/ts/components/settings/InsuranceSettings.ts","../../../@salaxy/ng1/ts/components/settings/OwnerSettings.ts","../../../@salaxy/ng1/ts/components/settings/PaymentChannelSettings.ts","../../../@salaxy/ng1/ts/components/settings/PaymentSettings.ts","../../../@salaxy/ng1/ts/components/settings/ProSettings.ts","../../../@salaxy/ng1/ts/components/settings/RowTypesSettings.ts","../../../@salaxy/ng1/ts/components/settings/ServiceModelDetails.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyAlert.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyCodeEditor.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyFieldset.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyForm.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyGrid.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxyInput.ts","../../../@salaxy/ng1/ts/components/sxy-form/SxySchemaEditor.ts","../../../@salaxy/ng1/ts/components/sxy-table/SxyTable.ts","../../../@salaxy/ng1/ts/components/test/AccountReset.ts","../../../@salaxy/ng1/ts/components/test/SmokeTest.ts","../../../@salaxy/ng1/ts/components/worker/holidays/HolidayYearAccrual.ts","../../../@salaxy/ng1/ts/components/worker/holidays/HolidayYearHolidays.ts","../../../@salaxy/ng1/ts/components/worker/holidays/HolidayYearPaid.ts","../../../@salaxy/ng1/ts/components/worker/holidays/WorkerHolidays.ts","../../../@salaxy/ng1/ts/components/worker/taxcard/EmploymentTaxcards.ts","../../../@salaxy/ng1/ts/components/worker/taxcard/TaxcardDetails.ts","../../../@salaxy/ng1/ts/components/worker/taxcard/TaxcardIncomeLog.ts","../../../@salaxy/ng1/ts/components/worker/taxcard/TaxcardManualEdit.ts","../../../@salaxy/ng1/ts/components/worker/taxcard/TaxCardsList.ts","../../../@salaxy/ng1/ts/components/worker/AbsencePeriods.ts","../../../@salaxy/ng1/ts/components/worker/EmploymentDetails.ts","../../../@salaxy/ng1/ts/components/worker/WorkerAbsences.ts","../../../@salaxy/ng1/ts/components/worker/WorkerDetails.ts","../../../@salaxy/ng1/ts/components/worker/EmploymentList.ts","../../../@salaxy/ng1/ts/components/workflow/CalendarEventDetails.ts","../../../@salaxy/ng1/ts/components/workflow/DatasetDetails.ts","../../../@salaxy/ng1/ts/components/workflow/UsecaseDetails.ts","../../../@salaxy/ng1/ts/components/workflow/Records.ts","../../../@salaxy/ng1/ts/components/workflow/WorkflowButtons.ts","../../../@salaxy/ng1/ts/components/workflow/WorkflowReopen.ts","../../../@salaxy/ng1/ts/components/workflow/WorkflowBadge.ts","../../../@salaxy/ng1/ts/components/_ComponentsRegistration.ts","../../../node_modules/.pnpm/angular-route@1.8.3/node_modules/angular-route/angular-route.js","../../../node_modules/.pnpm/angular-route@1.8.3/node_modules/angular-route/index.js","../../../node_modules/.pnpm/angular-i18n@1.8.3/node_modules/angular-i18n/angular-locale_fi.js","../../../node_modules/.pnpm/angular-ui-bootstrap@2.5.6/node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js","../../../node_modules/.pnpm/angular-ui-bootstrap@2.5.6/node_modules/angular-ui-bootstrap/index.js","../../../node_modules/.pnpm/angular-sanitize@1.8.3/node_modules/angular-sanitize/angular-sanitize.js","../../../node_modules/.pnpm/angular-sanitize@1.8.3/node_modules/angular-sanitize/index.js","../../../node_modules/.pnpm/ng-file-upload@12.2.13/node_modules/ng-file-upload/dist/ng-file-upload-all.js","../../../node_modules/.pnpm/ng-file-upload@12.2.13/node_modules/ng-file-upload/index.js","../../../node_modules/.pnpm/angular-translate@2.19.1/node_modules/angular-translate/dist/angular-translate.js","../../../@salaxy/ng1/ts/controllers/_ControllersRegistration.ts","../../../@salaxy/ng1/ts/directives/AppendNodeDirective.ts","../../../@salaxy/ng1/ts/directives/Bs5.ts","../../../@salaxy/ng1/ts/directives/EnumParserFunctions.ts","../../../@salaxy/ng1/ts/directives/IfRoleDirective.ts","../../../@salaxy/ng1/ts/directives/IfSitemapDirective.ts","../../../@salaxy/ng1/ts/directives/LoaderDirective.ts","../../../@salaxy/ng1/ts/directives/OrderbyDirective.ts","../../../@salaxy/ng1/ts/directives/ValidatorFunctions.ts","../../../@salaxy/ng1/ts/directives/DatepickerInputValidationDirective.ts","../../../node_modules/.pnpm/marked@12.0.2/node_modules/marked/lib/marked.esm.js","../../../@salaxy/ng1/ts/directives/HtmlDirective.ts","../../../@salaxy/ng1/ts/directives/TextDirective.ts","../../../@salaxy/ng1/ts/directives/_DirectivesRegistration.ts","../../../@salaxy/ng1/ts/filters/FilterFunctions.ts","../../../@salaxy/ng1/ts/filters/_FiltersRegistration.ts","../../../@salaxy/ng1/ts/interceptors/LoaderInterceptor.ts","../../../@salaxy/ng1/ts/interceptors/TemplateInterceptor.ts","../../../@salaxy/ng1/ts/services/_ServicesRegistration.ts","../../../@salaxy/ng1/ts/components/_NgComponents.ts","../../../@salaxy/ng1/ts/templates/bootstrap.ts","../../../@salaxy/ng1/ts/web-personal/PersonalWebLegacyController.ts","../../../@salaxy/ng1/ts/web-personal/PersonalWebSiteMap.ts","../../../@salaxy/ng1/ts/web-personal/module-registration.ts"],"sourcesContent":["import { IQService } from \"angular\";\r\n\r\nimport { Ajax, Config, Configs, Cookies, Token } from \"@salaxy/core\";\r\n\r\n/**\r\n * The $http access to the server methods: GET, POST and DELETE\r\n * with different return types and authentication / error events.\r\n */\r\nexport class AjaxNg1 implements Ajax {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$http\", \"$q\"];\r\n\r\n    /** Alert service for ajax. */\r\n    public static alertService: any;\r\n\r\n   /**\r\n    * By default (true) the token is set to salaxy-token -cookie.\r\n    * Disable cookies with this flag.\r\n    */\r\n    public useCookie = true;\r\n\r\n    /**\r\n     * By default credentials are not used in http-calls.\r\n     * Enable credentials with this flag.\r\n     */\r\n    public useCredentials = false;\r\n\r\n    /**\r\n     * The server address - root of the server\r\n     * This is settable field. Will probably be changed to a configuration object in the final version.\r\n     */\r\n    public serverAddress = \"https://test-api.salaxy.com\";\r\n\r\n    private token: string;\r\n\r\n    /**\r\n     * Creates a new instance of AjaxNg1\r\n     * @param $http - Angular http\r\n     * @param $q - Angular q\r\n     * @param config - Optional config containing keys which override the corresponding global Config keys.\r\n     */\r\n    constructor(private $http: angular.IHttpService, private $q: IQService, config: Config = null) {\r\n\r\n      const globalConfig = Configs.current;\r\n\r\n      if (globalConfig || config) {\r\n        // apiServer\r\n        const apiServer = config?.apiServer ?? globalConfig.apiServer;\r\n        if (apiServer) {\r\n          this.serverAddress = apiServer;\r\n        }\r\n\r\n        // useCredentials\r\n        const useCredentials = config?.useCredentials ?? globalConfig.useCredentials;\r\n        if (useCredentials != null) {\r\n          this.useCredentials = useCredentials;\r\n        }\r\n\r\n        // useCookie\r\n        const useCookie = config?.useCookie ?? globalConfig.useCookie;\r\n        if (useCookie != null) {\r\n          this.useCookie = useCookie;\r\n        }\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Gets the API address with version information. E.g. 'https://test-api.salaxy.com/v03/api'.\r\n     * Default version, as of writing 2.0\r\n     */\r\n    public getApiAddress(): string {\r\n        return this.serverAddress + \"/v03/api\";\r\n    }\r\n\r\n    /** Gets the Server address that is used as bases to the HTML queries. E.g. 'https://test-api.salaxy.com' */\r\n    public getServerAddress(): string {\r\n        return this.serverAddress;\r\n    }\r\n\r\n    /**\r\n     * Gets a JSON-message from server using the API\r\n     * @param method The API method is the url path after the api version segments (e.g. '/v03/api')\r\n     * and starts with a forward slash, e.g. '/calculator/new'.\r\n     * @returns A Promise with result data. Standard Promise rejection to be used for error handling.\r\n     */\r\n    public getJSON(method: string): Promise<any> {\r\n\r\n        const request: any = {}; // angular.IRequestConfig\r\n\r\n        const token: string = this.getCurrentToken();\r\n        if (token) {\r\n            request.headers = { Authorization: \"Bearer \" + token };\r\n        }\r\n\r\n        request.url = this.getUrl(method);\r\n        request.method = \"GET\";\r\n        request.responseType = \"json\";\r\n        request.withCredentials = (token) ? false : this.useCredentials;\r\n\r\n        return this.$http(request).then(\r\n            (response) => response.data,\r\n            (error: any) => {\r\n                return this.handleError(error);\r\n            }) as any;\r\n    }\r\n\r\n    /**\r\n     * Gets a HTML-message from server using the API\r\n     * @param method - The API method is the url path after the api version segments (e.g. '/v03/api')\r\n     * and starts with a forward slash, e.g. '/calculator/new'.\r\n     * @returns A Promise with result data. Standard Promise rejection to be used for error handling.\r\n     */\r\n    public getHTML(method: string): Promise<string> {\r\n\r\n        const request: any = {}; // angular.IRequestConfig\r\n\r\n        const token: string = this.getCurrentToken();\r\n        if (token) {\r\n            request.headers = { Authorization: \"Bearer \" + token };\r\n        }\r\n\r\n        request.url = this.getUrl(method);\r\n        request.method = \"GET\";\r\n        request.responseType = \"text\";\r\n        request.withCredentials = (token) ? false : this.useCredentials;\r\n\r\n        return (this.$http(request).then(\r\n            (response) => {\r\n                return response.data;\r\n            },\r\n            (error: any) => {\r\n                return this.handleError(error);\r\n            }) as any\r\n        );\r\n    }\r\n\r\n    /**\r\n     * POSTS data to server and receives back a JSON-message.\r\n     * @param method - The API method is the url path after the api version segments (e.g. '/v03/api')\r\n     * and starts with a forward slash, e.g. '/calculator/new'.\r\n     * @param data - The data that is posted to the server.\r\n     * @returns A Promise with result data. Standard Promise rejection to be used for error handling.\r\n     */\r\n    public postJSON(method: string, data: any): Promise<any> {\r\n\r\n        const request: any = {}; // angular.IRequestConfig\r\n\r\n        const token: string = this.getCurrentToken();\r\n        if (token) {\r\n            request.headers = { Authorization: \"Bearer \" + token };\r\n        }\r\n\r\n        request.url = this.getUrl(method);\r\n        request.method = \"POST\";\r\n        request.data = data;\r\n        request.responseType = \"json\";\r\n        request.withCredentials = (token) ? false : this.useCredentials;\r\n\r\n        return (this.$http(request).then(\r\n            (response) => response.data,\r\n            (error: any) => {\r\n                return this.handleError(error);\r\n            }) as any\r\n        );\r\n    }\r\n\r\n    /**\r\n     * POSTS data to server and receives back HTML.\r\n     * @param method - The API method is the url path after the api version segments (e.g. '/v03/api')\r\n     * and starts with a forward slash, e.g. '/calculator/new'.\r\n     * @param data - The data that is posted to the server.\r\n     * @returns A Promise with result data. Standard Promise rejection to be used for error handling.\r\n     */\r\n    public postHTML(method: string, data: any): Promise<string> {\r\n\r\n        const request: any = {}; // angular.IRequestConfig\r\n\r\n        const token: string = this.getCurrentToken();\r\n        if (token) {\r\n            request.headers = { Authorization: \"Bearer \" + token };\r\n        }\r\n\r\n        request.url = this.getUrl(method);\r\n        request.method = \"POST\";\r\n        request.data = data;\r\n        request.responseType = \"text\";\r\n        request.withCredentials = (token) ? false : this.useCredentials;\r\n\r\n        return (this.$http(request).then(\r\n            (response) => response.data,\r\n            (error: any) => {\r\n                return this.handleError(error);\r\n            }) as any\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Sends a DELETE-message to server using the API\r\n     * @param method - The API method is the url path after the api version segments (e.g. '/v03/api')\r\n     * and starts with a forward slash, e.g. '/calculator/new'.\r\n     * @returns A Promise with result data. Standard Promise rejection to be used for error handling.\r\n     */\r\n    public remove(method: string): Promise<any> {\r\n\r\n        const request: any = {}; // angular.IRequestConfig\r\n\r\n        const token: string = this.getCurrentToken();\r\n        if (token) {\r\n            request.headers = { Authorization: \"Bearer \" + token };\r\n        }\r\n\r\n        request.url = this.getUrl(method);\r\n        request.method = \"DELETE\";\r\n        request.responseType = \"json\";\r\n        request.withCredentials = (token) ? false : this.useCredentials;\r\n\r\n        return (this.$http(request).then(\r\n            (response) => {\r\n                return response.data;\r\n            },\r\n            (error: any) => {\r\n                return this.handleError(error);\r\n            }) as any\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Gets the current token.\r\n     * Will check the salaxy-token cookie if the token is persisted there\r\n     */\r\n    public getCurrentToken(): string {\r\n        if (!this.token && this.useCookie) {\r\n            this.token = new Cookies().get(\"salaxy-token\") || \"\";\r\n        }\r\n        return this.token;\r\n    }\r\n\r\n    /** Gets the status of the current token. */\r\n    public getTokenStatus(): \"noToken\" | \"ok\" | \"expired\" | \"invalid\" {\r\n      const token = this.getCurrentToken();\r\n      return Token.validate(token);\r\n    }\r\n\r\n    /**\r\n     * Sets the current token. Persists it to cookie until the browser window\r\n     * @param token - the authentication token to persist.\r\n     */\r\n    public setCurrentToken(token: string | null): void {\r\n        if (this.useCookie) {\r\n            new Cookies().setCookie(\"salaxy-token\", token || \"\");\r\n        }\r\n        this.token = token;\r\n    }\r\n\r\n    /** If missing, append the API server address to the given url method string */\r\n    private getUrl(method: string): string {\r\n      if (!method || method.trim() === \"\") {\r\n        return null;\r\n      }\r\n      if (method.toLowerCase().startsWith(\"http\")) {\r\n        return method;\r\n      }\r\n      if (method.toLowerCase().startsWith(\"/v\")) {\r\n        return this.getServerAddress() + method;\r\n      }\r\n      return this.getApiAddress() + method;\r\n    }\r\n\r\n    private handleError(errorThrown: any): Promise<any> {\r\n        let msg: string;\r\n        if (errorThrown) {\r\n            if (errorThrown.data && errorThrown.data.messageHtml) {\r\n                msg = `<b>${errorThrown.data.error}:</b><br/>${errorThrown.data.messageHtml}`;\r\n            } else if (errorThrown.data && errorThrown.data.message) {\r\n                msg = errorThrown.data.message;\r\n            } else {\r\n                msg = `HTTP error: ${errorThrown.statusText} (${errorThrown.status})`;\r\n            }\r\n        } else {\r\n            msg = \"Unexpected error in HTTP request\";\r\n        }\r\n        if (AjaxNg1.alertService) {\r\n            if (AjaxNg1.alertService.catchError) {\r\n                return AjaxNg1.alertService.catchError(errorThrown);\r\n            } else {\r\n                AjaxNg1.alertService.addError(msg);\r\n            }\r\n        }\r\n        return this.$q.reject(errorThrown) as any;\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { WizardService, WizardStep } from \"../../services\";\r\n\r\n/**\r\n * A generic Wizard controller for rendering the Wizard UI\r\n */\r\nexport class WizardController implements angular.IController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$scope\", \"WizardService\", \"data\"];\r\n\r\n    /** Styling classes for columns. */\r\n    public colWidthClasses = [\"col-sm-12\", \"col-sm-12\", \"col-sm-6\", \"col-sm-4\", \"col-sm-3\", \"col-sm-fifth\", \"col-sm-2\"];\r\n\r\n    /** Path for the view that is shown in the wizard */\r\n    public viewPath: string;\r\n\r\n    /** Path to the buttons view that is shown in the footer of the wizard */\r\n    public buttonsView?: string;\r\n\r\n    /**\r\n     * Creates a new WizardController\r\n     * @param $scope - The Angular scope\r\n     * @param wizardService - Maintains the state of the wizard\r\n     * @param data - Any data to the controller\r\n     * @ignore\r\n     */\r\n    constructor(\r\n        protected $scope: angular.IScope,\r\n        protected wizardService: WizardService,\r\n        protected data: any = null,\r\n    ) {\r\n    }\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit() {\r\n        //\r\n    }\r\n\r\n    /** Gets all the steps in the Wizard */\r\n    public get steps(): WizardStep[] {\r\n        return this.wizardService.getSteps();\r\n    }\r\n\r\n    /** Gets the number of the currently active step */\r\n    public get step(): number {\r\n        return this.wizardService.activeStepNumber;\r\n    }\r\n    /** Sets the number of the currently active step */\r\n    public set step(stepNumber: number) {\r\n        this.wizardService.activeStepNumber = stepNumber;\r\n    }\r\n\r\n    /** The currently selected step object */\r\n    public get currentStep(): WizardStep {\r\n        return this.wizardService.getCurrentStepObject();\r\n    }\r\n\r\n    /** Active styling properties */\r\n    public get style() {\r\n        return {\r\n            colWidthClass: this.colWidthClasses[this.steps.length],\r\n        };\r\n    }\r\n\r\n    /** Returns true if goNext is enabled  */\r\n    public get canGoNext(): boolean {\r\n        if (this.steps.length > this.step) {\r\n            if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n\r\n    /** Returns true if goNext is enabled  */\r\n    public get canGoPrevious(): boolean {\r\n        if (this.step > 1 && !this.steps[this.step - 2].disabled) {\r\n            return true;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Navigates to the next step if possible\r\n     */\r\n    public goNext() {\r\n        if (this.canGoNext) {\r\n            this.step++;\r\n        }\r\n    }\r\n\r\n    /** Navigates to the previous step if possible */\r\n    public goPrevious() {\r\n        if (this.canGoPrevious) {\r\n            this.step--;\r\n        }\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, Configs, Onboarding, PensionCompany,  SettingsLogic} from \"@salaxy/core\";\r\n\r\nimport { WizardController } from \"../../bases/WizardController\";\r\n\r\nimport { AuthorizedAccountService, OnboardingService, SessionService, WizardService, WizardStep } from \"../../../services\";\r\n\r\n/**\r\n * Wizard for Creating a new Palkkaus.fi company account by accountant\r\n */\r\nexport class CustomerOnboardingController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"OnboardingService\", \"SessionService\", \"AuthorizedAccountService\", \"AjaxNg1\", \"$location\", \"data\"];\r\n\r\n  /** Form data validity */\r\n  public formDataValidity: boolean;\r\n\r\n  /** If true, step is proceeding */\r\n  public isStepProceeding = false;\r\n\r\n  /** Copy indicator */\r\n  public linkCopied = false;\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    wizardService: WizardService,\r\n    private onboardingService: OnboardingService,\r\n    private sessionService: SessionService,\r\n    private authorizedAccountService: AuthorizedAccountService,\r\n    private ajax: Ajax,\r\n    private $location: angular.ILocationService,\r\n    data: any,\r\n  ) {\r\n    super($scope, wizardService, data);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.wizardService.setSteps(this.getWizardSteps());\r\n    if (this.model &&\r\n      this.model.company.resolvedId &&\r\n      this.model.signature.personalId != null) {\r\n      this.wizardService.activeStepNumber = this.wizardService.getSteps().length;\r\n      // suomi.fi-->\r\n      // } else if (this.model && this.model.signature.isProcura) {\r\n      //   this.wizardService.activeStepNumber = 2;\r\n      // <--suomi.fi\r\n    } else {\r\n      this.wizardService.activeStepNumber = 1;\r\n    }\r\n  }\r\n\r\n  /** Company wizard configuration */\r\n  public getWizardSteps(): WizardStep[] {\r\n    const steps: WizardStep[] = [];\r\n    steps.push(\r\n      {\r\n        title: \"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.title\",\r\n        heading: \"\",\r\n        intro: \"\",\r\n        view: \"salaxy-components/modals/onboarding/customer/user.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/customer/user-buttons.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.title\",\r\n        heading: \"\",\r\n        intro: \"\",\r\n        view: \"salaxy-components/modals/onboarding/customer/company.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/customer/buttons.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.title\",\r\n        heading: \"\",\r\n        intro: \"\",\r\n        view: \"salaxy-components/modals/onboarding/customer/company-legal.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/customer/buttons.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.title\",\r\n        heading: \"\",\r\n        intro: \"\",\r\n        view: \"salaxy-components/modals/onboarding/customer/insurance.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/customer/commit-buttons.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.CustomerOnboardingComponent.stepInviteCompany.title\",\r\n        heading: \"\",\r\n        intro: \"\",\r\n        view: \"salaxy-components/modals/onboarding/customer/finish.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/customer/finish-buttons.html\",\r\n      });\r\n    return steps;\r\n  }\r\n\r\n  /**\r\n   * The onboarding model is provided by the onboarding service.\r\n   *\r\n   */\r\n  public get model(): Onboarding {\r\n    return this.onboardingService.model;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible and saves the data.\r\n   */\r\n  public goNext() {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.save().then(() => {\r\n      super.goNext();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Navigates to the previous step if possible and saves the data.\r\n   */\r\n  public goPrevious() {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.save().then(() => {\r\n      super.goPrevious();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /** Returns true if user can go forward in wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity) {\r\n          return true;\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Sharing link for singing. */\r\n  public get signingLink(): string {\r\n    if (!this.model) {\r\n      return \"\";\r\n    }\r\n    return Configs.current.wwwServer + \"/share/signing/\" + encodeURIComponent(this.model.owner) + \"/\" + this.model.id;\r\n  }\r\n\r\n  /** Sharing link for authorization mail. */\r\n  public get sharingLink(): string {\r\n    if (!this.model) {\r\n      return \"\";\r\n    }\r\n    return Configs.current.wwwServer + \"/share/authorization/\" + encodeURIComponent(this.model.owner) + \"/\" + this.model.id;\r\n  }\r\n\r\n  /** Copies link to clipboard */\r\n  public copyLink(link: string) {\r\n    (navigator as any).clipboard.writeText(link);\r\n    this.linkCopied = true;\r\n  }\r\n\r\n  /** Mailto-link with sharing link. */\r\n  public get mailtoLink(): string {\r\n    if (!this.model || !this.model.person) {\r\n      return \"\";\r\n    }\r\n    let link = \"mailto:\";\r\n    link += this.model.person.contact.email;\r\n    link += \"?subject=\" + encodeURIComponent(\"Palkkaus.fi-palvelun valtakirjan allekirjoitus\");\r\n\r\n    let body = \"Hei \" + this.model.person.firstName + \" \" + this.model.person.lastName + \",\\n\\n\";\r\n    body += \"Olemme ottamassa käyttöön Palkkaus.fi-palvelun yrityksesi palkanmaksuun.\";\r\n    body += \" Jotta he voivat hoitaa kaikki viranomaisvelvoitteet, tarvitaan allekirjoitus sinulta.\";\r\n    body += \" Se hoituu helposti pankkitunnuksilla seuraamalla tätä linkkiä: \";\r\n    body += this.sharingLink + \". \\n\\n\";\r\n    body += \"Ystävällisin terveisin, \\n\";\r\n    body += this.sessionService.getAvatar().displayName;\r\n    link += \"&body=\" + encodeURIComponent(body);\r\n    return link;\r\n  }\r\n\r\n  /**\r\n   * Existing company alert.\r\n   */\r\n  public get existingCompanyAlert(): boolean {\r\n    const currentAccountId = this.sessionService.session?.currentAccount?.id;\r\n    // existing account in the system and is different than current account\r\n    return this.model?.company?.resolvedId &&\r\n           this.model.company.resolvedId != currentAccountId;\r\n  }\r\n\r\n  /**\r\n   * Proceeds to company selection in e-authorization service.\r\n   */\r\n  public goToCompanySelection(): void {\r\n\r\n    /*  suomi.fi-->\r\n    const rawUrl = this.$location.url();\r\n    let baseUrl = this.$location.absUrl();\r\n    if (rawUrl.length > 1) {\r\n      baseUrl = baseUrl.substring(0, baseUrl.indexOf(rawUrl));\r\n    }\r\n    baseUrl = baseUrl.replace(/\\/$/, \"\");\r\n    const accessToken = this.ajax.getCurrentToken();\r\n    const token = accessToken ? `${encodeURIComponent(accessToken)}` : \"\";\r\n    const cancelUrl = `${baseUrl}/onboarding/customer/${this.model.id}${token ? \"&ob_token=\" + token : \"\"}`;\r\n    const successUrl = `${baseUrl}/onboarding/customer/${this.model.id}${token ? \"&ob_token=\" + token : \"\"}`;\r\n    this.save().then(() => {\r\n      window.location.assign(`${this.ajax.getServerAddress()}/Onboarding/CompanySelection?OnboardingId=${encodeURIComponent(this.model.id)}&SuccessUrl=${encodeURIComponent(successUrl)}&CancelUrl=${encodeURIComponent(cancelUrl)}${token ? \"&access_token=\" + token : \"\"}`);\r\n    });\r\n     <--suomi.fi*/\r\n    this.model.company.doYtjUpdate = true;\r\n    this.goNext();\r\n  }\r\n\r\n  /** Commit onboarding */\r\n  public commit(): void {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.model.signature.email = this.model.person.contact.email;\r\n    this.model.signature.telephone = this.model.person.contact.telephone;\r\n    this.model.signature.personName = (this.model.person.firstName + \" \" + this.model.person.lastName).trim();\r\n\r\n    this.onboardingService.commit().then(() => {\r\n      // refresh authorizing accounts\r\n      this.authorizedAccountService.reloadAuthorizingAccounts();\r\n      super.goNext();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /** Sets pension fields (defaults) after user input. */\r\n  public checkPensionCompanySelection() {\r\n\r\n    if (!this.model.products.pension.isPensionContractDone) {\r\n      this.model.products.pension.pensionCompany = PensionCompany.None;\r\n      this.model.products.pension.pensionContractNumber = null;\r\n    }\r\n    const pensionCompany = this.model.products.pension.pensionCompany;\r\n    if (this.model.products.pension.isPensionContractDone && pensionCompany === PensionCompany.Varma) {\r\n      this.model.products.pension.isPendingContract = false;\r\n    }\r\n    // If the company is one that Palkkaus.fi/Salaxy does not have a process with, user is forced to take care of pension themselves\r\n    if (pensionCompany === PensionCompany.Veritas ||\r\n      pensionCompany === PensionCompany.Apteekkien ||\r\n      pensionCompany === PensionCompany.Verso ||\r\n      pensionCompany === PensionCompany.Valio ||\r\n      (pensionCompany ?? \"\").startsWith(\"keva\") ||\r\n      pensionCompany === PensionCompany.Other) {\r\n      this.model.products.pension.isPensionSelfHandling = true;\r\n    }\r\n    // Check if pending contract\r\n    if (this.model.products.pension.isPendingContract) {\r\n      this.model.products.pension.isPensionSelfHandling = false;\r\n    }\r\n  }\r\n\r\n  /** Sets insurance fields (defaults) after user input. */\r\n  public checkInsuranceCompanySelection() {\r\n    if (!this.model.products.insurance.isInsuranceContractDone) {\r\n      this.model.products.insurance.insuranceCompany = null;\r\n      this.model.products.insurance.insuranceContractNumber = null;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Saves the data to server\r\n   */\r\n  public save(): Promise<Onboarding> {\r\n    return this.onboardingService.save();\r\n  }\r\n\r\n  /**\r\n   * Sets the pension contract number as a test number according to the selected company.\r\n   */\r\n  public setPensionNumberForTest() {\r\n    this.model.products.pension.pensionContractNumber = SettingsLogic.getPensionNumberForTest(this.model.products.pension.pensionCompany);\r\n  }\r\n\r\n  /**\r\n   * Launches the wizard.\r\n   * @param accountId Optional account id.\r\n   */\r\n  public launch(accountId: string = null): Promise<any> {\r\n    return this.onboardingService.launchCustomerOnboarding(accountId);\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiValidationError, Onboarding } from \"@salaxy/core\";\r\n\r\nimport { OnboardingService, SessionService, UiHelpers, WizardService, WizardStep } from \"../../../services\";\r\n\r\nimport { WizardController } from \"../../bases/WizardController\";\r\n\r\n/**\r\n * Wizard for Creating a new Palkkaus.fi-account (worker)\r\n */\r\nexport class WorkerOnboardingController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"OnboardingService\", \"SessionService\", \"UiHelpers\"];\r\n\r\n  /** Worker wizard configuration */\r\n  public wizardSteps: WizardStep[] = [\r\n    {\r\n      title: \"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.title\",\r\n      heading: \"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.heading\",\r\n      intro: \"\",\r\n      active: true,\r\n      view: \"salaxy-components/modals/onboarding/worker/user-info.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/worker/firstPageButtons.html\",\r\n    },\r\n    /*\r\n    {\r\n      title: \"SALAXY.NG1.WorkerOnboardingComponent.stepPhoneNumberVerify.title\",\r\n      heading: \"SALAXY.NG1.WorkerOnboardingComponent.stepPhoneNumberVerify.heading\",\r\n      intro: \"SALAXY.NG1.WorkerOnboardingComponent.stepPhoneNumberVerify.intro\",\r\n      view: \"salaxy-components/modals/onboarding/worker/phonenumber-verify.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/worker/phoneNumberVerifyButtons.html\",\r\n    },\r\n    */\r\n    {\r\n      title: \"SALAXY.NG1.WorkerOnboardingComponent.stepContract.stepTitle\",\r\n      heading: \"SALAXY.NG1.WorkerOnboardingComponent.stepContract.heading\",\r\n      intro: \"SALAXY.NG1.WorkerOnboardingComponent.stepContract.intro\",\r\n      view: \"salaxy-components/modals/onboarding/worker/contract-worker.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/worker/contractButtons.html\",\r\n    },\r\n  ];\r\n\r\n  /**\r\n   * Field to expose forms validity state.\r\n   */\r\n  public formDataValidity: boolean;\r\n\r\n  /** If true, step is proceeding */\r\n  public isStepProceeding = false;\r\n\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    wizardService: WizardService,\r\n    private onboardingService: OnboardingService,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    super($scope, wizardService);\r\n  }\r\n\r\n   /**\r\n    * Implement IController\r\n    */\r\n   public $onInit() {\r\n    this.wizardService.setSteps(this.wizardSteps);\r\n    this.wizardService.activeStepNumber = 1;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible and saves the data.\r\n   */\r\n  public goNext(): Promise<boolean> {\r\n    if (this.isStepProceeding) {\r\n      return Promise.resolve(false);\r\n    }\r\n    this.isStepProceeding = true;\r\n    return this.save().then(() => {\r\n      super.goNext();\r\n      this.isStepProceeding = false;\r\n      return true;\r\n    }).catch((reason) => {\r\n      this.isStepProceeding = false;\r\n      return false;\r\n    });\r\n  }\r\n\r\n  /** Returns true if user can go forward in wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity) {\r\n          /* if (this.model.validation.isOfficialIdUnique == true){ */\r\n          return true;\r\n          /* } */\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Runs a check function before going forward */\r\n\r\n  public goNextIf(checkFunction: (goNext: () => Promise<boolean>) => void) {\r\n    checkFunction(() => this.goNext());\r\n  }\r\n\r\n  /**\r\n   * Navigates to the previous step if possible and saves the data.\r\n   */\r\n  public goPrevious() {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.save().then(() => {\r\n      super.goPrevious();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Saves the data to server\r\n   */\r\n  public save(): Promise<Onboarding> {\r\n    this.model.signature.email = this.model.person.contact.email;\r\n    this.model.signature.telephone = this.model.person.contact.telephone;\r\n    this.model.signature.personName = (this.model.person.firstName + \" \" + this.model.person.lastName).trim();\r\n    return this.onboardingService.save();\r\n  }\r\n\r\n  /**\r\n   * Returns signing url.\r\n   */\r\n  public get vismaSignUrl(): string {\r\n    // HACK: Get rid of this: Use this.model.signature.digitalSignature.auth_service instead.\r\n    const method = (this.model.signature as any).method;\r\n    return this.onboardingService.getDigitalSignUrl(method);\r\n  }\r\n\r\n  /**\r\n   * The onboarding model is provided by the onboarding service.\r\n   */\r\n  public get model(): Onboarding {\r\n    return this.onboardingService.model;\r\n  }\r\n\r\n  /** Returns the PDF preview address for the authorization pdf. */\r\n  public getPdfPreviewAddress() {\r\n    return this.onboardingService.getPdfPreviewAddress();\r\n  }\r\n\r\n  /**\r\n   * Returns validation error for key if exists.\r\n   * @param key - Validation error key.\r\n   */\r\n  public getValidationError(key: string): ApiValidationError {\r\n    if (this.model && this.model.validation) {\r\n      return this.model.validation.errors.find((x) => x.key === key);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Resets validation error for key if exists.\r\n   * @param key - Validation error key.\r\n   */\r\n  public removeValidationError(key: string): void {\r\n    if (this.model && this.model.validation) {\r\n      (this.model.validation as any).errors = this.model.validation.errors.filter((x) => x.key !== key);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Checks if the given string is other identifier than Finnish Personal Identification Number\r\n   * @param ssn given social security number\r\n   */\r\n  public isOtherIdentifier(ssn: string){\r\n\r\n    /** 8th character is 9 */\r\n    const regex = /^.{7}[9]/;\r\n    return regex.test((ssn || \"\").trim());\r\n  }\r\n\r\n  /**\r\n   * Launches the wizard.\r\n   * @param id Optional onboarding id.\r\n   */\r\n  public launch(id: string = null): Promise<any> {\r\n    return this.onboardingService.launchWorkerOnboarding(id);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiValidationError, Onboarding } from \"@salaxy/core\";\r\n\r\nimport { OnboardingService, SessionService, WizardService, WizardStep } from \"../../../services\";\r\nimport { WizardController } from \"../../bases/WizardController\";\r\n\r\n/**\r\n * Wizard for Creating a new Palkkaus.fi-account for a household.\r\n */\r\nexport class HouseholdOnboardingController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"OnboardingService\", \"SessionService\", \"data\"];\r\n\r\n  /** Household wizard configuration */\r\n  public wizardSteps: WizardStep[] = [\r\n    {\r\n      title: \"Käyttäjän tiedot\",\r\n      heading: \"Tervetuloa, Palkkamyllyyn!\",\r\n      intro: `Palkkamyllyn tarjoaa Rakennusliitto ry, joka toimii henkilötietojen käsittelijänä ja vastaa myös asiakaspalvelusta.\\n\\nPalvelun tuottajana, teknisenä toteuttajana ja myös henkilötietojen käsittelijä toimii Suomen Palkanlaskenta Oy (Palkkaus.fi).`,\r\n      active: true,\r\n      view: \"salaxy-components/modals/onboarding/household/wizard_index.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/household/firstPageButtons.html\",\r\n    },\r\n    /*\r\n    {\r\n      title: \"Puhelinnumero\",\r\n      heading: \"Puhelinnumero\",\r\n      intro: \"Puhelinnumeroa tarvitsemme yhteydenpitoa varten. Jos rekisteröit Siirto-palvelussa olevan puhelinnumeron, voit maksaa ja vastaanottaa palkkoja mobiilimaksuilla. Vahvistamme antamasi numeron.\",\r\n      view: \"salaxy-components/modals/onboarding/household/phoneNumber.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/household/phoneNumberButtons.html\",\r\n    },\r\n    {\r\n      title: \"Puhelinnumeron vahvistaminen\",\r\n      heading: \"Puhelinnumeron vahvistaminen\",\r\n      intro: \"Olemme lähettäneet sinulle SMS-viestin varmistaaksemme numerosi. Syötä viestissä oleva vahvistuskoodi tähän.\",\r\n      view: \"salaxy-components/modals/onboarding/household/phoneNumberVerify.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/household/phoneNumberVerifyButtons.html\",\r\n    },\r\n    */\r\n    {\r\n      title: \"Palkanmaksun tiedot\",\r\n      heading: \"Palkanmaksun tiedot\",\r\n      view: \"salaxy-components/modals/onboarding/household/household.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/household/householdButtons.html\",\r\n    },\r\n    {\r\n      title: \"Palvelusopimus\",\r\n      heading: \"Palvelusopimus ja valtuutus\",\r\n      view: \"salaxy-components/modals/onboarding/household/contract.html\",\r\n      buttonsView: \"salaxy-components/modals/onboarding/household/contractButtons.html\",\r\n    },\r\n  ];\r\n\r\n  /**\r\n   * Field to expose forms validity state.\r\n   */\r\n  public formDataValidity: boolean;\r\n\r\n  /** If true, step is proceeding */\r\n  public isStepProceeding = false;\r\n\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    wizardService: WizardService,\r\n    private onboardingService: OnboardingService,\r\n    private sessionService: SessionService,\r\n    data: any,\r\n  ) {\r\n    super($scope, wizardService, data);\r\n  }\r\n\r\n   /**\r\n    * Implement IController\r\n    */\r\n  public $onInit() {\r\n    this.wizardService.setSteps(this.wizardSteps);\r\n    this.wizardService.activeStepNumber = 1;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible and saves the data.\r\n   */\r\n  public goNext(): Promise<boolean> {\r\n    if (this.isStepProceeding) {\r\n      return Promise.resolve(false);\r\n    }\r\n    this.isStepProceeding = true;\r\n    return this.save().then(() => {\r\n      super.goNext();\r\n      this.isStepProceeding = false;\r\n      return true;\r\n    }).catch((reason) => {\r\n      this.isStepProceeding = false;\r\n      return false;\r\n    });\r\n  }\r\n\r\n  /** Returns true if user can go forward in wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity) {\r\n          /* if (this.model.validation.isOfficialIdUnique == true){ */\r\n          return true;\r\n          /* } */\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Runs a check function before going forward */\r\n\r\n  public goNextIf(checkFunction: (goNext: () => Promise<boolean>) => void) {\r\n    checkFunction(() => this.goNext());\r\n  }\r\n\r\n  /**\r\n   * Navigates to the previous step if possible and saves the data.\r\n   */\r\n  public goPrevious() {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.save().then(() => {\r\n      super.goPrevious();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Saves the data to server\r\n   */\r\n  public save(): Promise<Onboarding> {\r\n    this.model.signature.email = this.model.person.contact.email;\r\n    this.model.signature.telephone = this.model.person.contact.telephone;\r\n    this.model.signature.personName = (this.model.person.firstName + \" \" + this.model.person.lastName).trim();\r\n    return this.onboardingService.save();\r\n  }\r\n\r\n  /**\r\n   * Returns signing url.\r\n   */\r\n  public get vismaSignUrl(): string {\r\n    // HACK: Get rid of this: Use this.model.signature.digitalSignature.auth_service instead.\r\n    const method = (this.model.signature as any).method;\r\n    return this.onboardingService.getDigitalSignUrl(method);\r\n  }\r\n\r\n  /**\r\n   * The onboarding model is provided by the onboarding service.\r\n   */\r\n  public get model(): Onboarding {\r\n    return this.onboardingService.model;\r\n  }\r\n\r\n  /** Returns the PDF preview address for the authorization pdf. */\r\n  public getPdfPreviewAddress() {\r\n    return this.onboardingService.getPdfPreviewAddress();\r\n  }\r\n\r\n  /**\r\n   * Returns validation error for key if exists.\r\n   * @param key - Validation error key.\r\n   */\r\n  public getValidationError(key: string): ApiValidationError {\r\n    if (this.model && this.model.validation) {\r\n      return this.model.validation.errors.find((x) => x.key === key);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Resets validation error for key if exists.\r\n   * @param key - Validation error key.\r\n   */\r\n  public removeValidationError(key: string): void {\r\n    if (this.model && this.model.validation) {\r\n      (this.model.validation as any).errors = this.model.validation.errors.filter((x) => x.key !== key);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Launches the wizard.\r\n   * @param id Optional onboarding id.\r\n   */\r\n  public launch(id: string = null): Promise<any> {\r\n    return this.onboardingService.launchHouseholdOnboarding(id);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, ApiValidationError, Onboarding, Role, Translations } from \"@salaxy/core\";\r\n\r\nimport { OnboardingService, SessionService, WizardService, WizardStep, UiHelpers } from \"../../../services\";\r\nimport { WizardController } from \"../../bases/WizardController\";\r\n\r\n/**\r\n * Wizard for creating a new Palkkaus.fi-account for a company.\r\n */\r\nexport class CompanyOnboardingController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"OnboardingService\", \"SessionService\", \"AjaxNg1\", \"$location\", \"data\", \"UiHelpers\"];\r\n\r\n  /**\r\n   * Field to expose forms validity state.\r\n   */\r\n  public formDataValidity: boolean;\r\n\r\n  /** If true, step is proceeding */\r\n  public isStepProceeding = false;\r\n\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    wizardService: WizardService,\r\n    private onboardingService: OnboardingService,\r\n    private sessionService: SessionService,\r\n    private ajax: Ajax,\r\n    private $location: angular.ILocationService,\r\n    data: any,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    super($scope, wizardService, data);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n\r\n    this.wizardService.setSteps(this.getWizardSteps());\r\n    if (this.model && this.model.signature.isProcura) {\r\n      this.wizardService.activeStepNumber = 3;\r\n    } else {\r\n      this.wizardService.activeStepNumber = 1;\r\n    }\r\n  }\r\n\r\n  /** Company wizard configuration */\r\n  public getWizardSteps(): WizardStep[] {\r\n    const steps: WizardStep[] = [];\r\n    steps.push(\r\n      {\r\n        title: \"SALAXY.NG1.CompanyOnboardingComponent.step1.title\",\r\n        intro: \"SALAXY.NG1.CompanyOnboardingComponent.step1.intro\",\r\n        active: true,\r\n        view: \"salaxy-components/modals/onboarding/company/wizard_index.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/company/firstPageButtons.html\",\r\n      });\r\n    if (this.showCompanySelection) {\r\n      steps.push(\r\n        {\r\n          title: \"SALAXY.NG1.CompanyOnboardingComponent.stepSuomiFi.title\",\r\n          intro: \"SALAXY.NG1.CompanyOnboardingComponent.stepSuomiFi.intro\",\r\n          view: \"salaxy-components/modals/onboarding/company/suomifi.html\",\r\n          buttonsView: \"salaxy-components/modals/onboarding/company/suomifiButtons.html\",\r\n        });\r\n    }\r\n    steps.push(\r\n      {\r\n        title: \"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.title\",\r\n        intro: \"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.intro\",\r\n        view: \"salaxy-components/modals/onboarding/company/company.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/company/defaultWizardButtons.html\",\r\n      },\r\n      /*\r\n      {\r\n        title: \"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.title\",\r\n        view: \"salaxy-components/modals/onboarding/company/company-legal.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/company/defaultWizardButtons.html\",\r\n      },\r\n      */\r\n      {\r\n        title: \"SALAXY.NG1.CompanyOnboardingComponent.stepContract.title\",\r\n        view: \"salaxy-components/modals/onboarding/company/contract.html\",\r\n        buttonsView: \"salaxy-components/modals/onboarding/company/contractButtons.html\",\r\n      },\r\n    );\r\n    return steps;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible and saves the data.\r\n   */\r\n  public goNext(): Promise<boolean> {\r\n    if (this.isStepProceeding) {\r\n      return Promise.resolve(false);\r\n    }\r\n    this.isStepProceeding = true;\r\n    return this.save().then(() => {\r\n      super.goNext();\r\n      this.isStepProceeding = false;\r\n      return true;\r\n    }).catch((reason) => {\r\n      this.isStepProceeding = false;\r\n      return false;\r\n    });\r\n  }\r\n\r\n  /** Returns true if user can go forward in wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity) {\r\n          /* if (this.model.validation.isOfficialIdUnique == true){ */\r\n          return true;\r\n          /* } */\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the previous step if possible and saves the data.\r\n   */\r\n  public goPrevious() {\r\n    if (this.isStepProceeding) {\r\n      return;\r\n    }\r\n    this.isStepProceeding = true;\r\n    this.save().then(() => {\r\n      super.goPrevious();\r\n      this.isStepProceeding = false;\r\n    })\r\n      .catch((reason) => {\r\n        this.isStepProceeding = false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Saves the data to server\r\n   */\r\n  public save(): Promise<Onboarding> {\r\n    this.model.signature.email = this.model.person.contact.email;\r\n    this.model.signature.telephone = this.model.person.contact.telephone;\r\n    this.model.signature.personName = (this.model.person.firstName + \" \" + this.model.person.lastName).trim();\r\n    return this.onboardingService.save();\r\n  }\r\n\r\n  /**\r\n   * Returns signing url.\r\n   */\r\n  public get vismaSignUrl(): string {\r\n    return this.onboardingService.getDigitalSignUrl();\r\n  }\r\n\r\n  /**\r\n   * The onboarding model is provided by the onboarding service.\r\n   */\r\n  public get model(): Onboarding {\r\n    return this.onboardingService.model;\r\n  }\r\n\r\n  /** IF true, the Suomi.fi company selection is used. */\r\n  public get showCompanySelection(): boolean {\r\n\r\n    const isAccountant = this.model &&\r\n    this.model.company &&\r\n     this.model.company.roles &&\r\n     this.model.company.roles.some( (r) => ( r === Role.Accountant || r === Role.AccountantCandidate));\r\n\r\n    return isAccountant;\r\n  }\r\n\r\n  /** Returns the PDF preview address for the authorization pdf. */\r\n  public getPdfPreviewAddress() {\r\n    return this.onboardingService.getPdfPreviewAddress();\r\n  }\r\n\r\n  /**\r\n   * Existing company alert.\r\n   */\r\n  public get existingCompanyAlert(): boolean {\r\n    const currentAccountId = this.sessionService.session?.currentAccount?.id;\r\n    // existing account in the system and is different than current account\r\n    return this.model?.company?.resolvedId &&\r\n           this.model.company.resolvedId != currentAccountId;\r\n  }\r\n\r\n  /** Go to suomi fi ypa */\r\n  public goToSuomifi() {\r\n\r\n    const rawUrl = this.$location.url();\r\n    let baseUrl = this.$location.absUrl();\r\n    if (rawUrl.length > 1) {\r\n      baseUrl = baseUrl.substring(0, baseUrl.indexOf(rawUrl));\r\n    }\r\n    baseUrl = baseUrl.replace(/\\/$/, \"\").trim();\r\n\r\n    const accessToken = this.ajax.getCurrentToken();\r\n    const token = accessToken ? `${encodeURIComponent(accessToken)}` : \"\";\r\n    const urlParam = ( baseUrl.indexOf(\"&\") >= 0 || baseUrl.indexOf(\"?\") >= 0) ? \"&url=\" : \"\";\r\n    const cancelUrl = `${baseUrl}${urlParam}/onboarding/company/${this.model.id}${token ? \"&ob_token=\" + token : \"\"}`;\r\n    const successUrl = `${baseUrl}${urlParam}/onboarding/company/${this.model.id}${token ? \"&ob_token=\" + token : \"\"}`;\r\n    this.save().then(() => {\r\n      window.location.assign(`${this.ajax.getServerAddress()}/Onboarding/CompanySelection?OnboardingId=${encodeURIComponent(this.model.id)}&Language=${encodeURIComponent(Translations.getLanguage())}&SuccessUrl=${encodeURIComponent(successUrl)}&CancelUrl=${encodeURIComponent(cancelUrl)}${token ? \"&access_token=\" + token : \"\"}`);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Launches the wizard.\r\n   * @param id Optional onboarding id.\r\n   */\r\n  public launch(id: string = null): Promise<any> {\r\n    return this.onboardingService.launchCompanyOnboarding(id);\r\n  }\r\n\r\n  /**\r\n   * Sets the company's business id, clears the YTJ search results fetches other company info's via YTJ search and saves\r\n   * @param businessId The business id that is set as the company's business id\r\n   */\r\n  public chooseBusinessId(businessId) {\r\n    this.model.company.businessId = businessId;\r\n    this.model.company.ytjSearch = null;\r\n    this.searchYtj();\r\n  }\r\n\r\n  /**\r\n   * Sets the DoYtjUpdate flag to true and saves.\r\n   * @param searchType - If true, sets the business ID to null\r\n   * Use this option to force a YTJ name search, even if there already is something written in business ID field.\r\n   */\r\n  public searchYtj(searchType?: \"businessId\" | \"name\") {\r\n    // Clear company's type and address\r\n    this.model.company.companyType = null;\r\n    this.model.company.contact.street = null;\r\n    this.model.company.contact.city = null;\r\n    this.model.company.contact.postalCode = null;\r\n    // Clear previous YTJ search results\r\n    this.model.company.ytjSearch = null;\r\n    // Prepare for YTJ search\r\n    this.model.company.doYtjUpdate = true;\r\n    if (searchType === \"name\") {\r\n      this.model.company.businessId = null;\r\n    }\r\n    if (searchType === \"businessId\") {\r\n\r\n      this.model.company.name = null;\r\n    }\r\n\r\n    this.save();\r\n  }\r\n\r\n  /**\r\n   * Returns validation error for key if exists.\r\n   * @param key - Validation error key.\r\n   */\r\n  public getValidationError(key: string): ApiValidationError {\r\n    if (this.model && this.model.validation) {\r\n      return this.model.validation.errors.find((x) => x.key === key);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Opens wizard as modal dialog */\r\n  public openSigningWizardDialog(onBoardingId = null): Promise<any> {\r\n    const skin = this.sessionService.getCurrentCss();\r\n    const origin = this.sessionService.getOrigin();\r\n    const url =  origin + (skin ?\r\n      `popup.html#settings/signing?skin=${skin}&lang=${Translations.getLanguage()}&id=${this.onboardingService.model?.id ?? \"\"}#access_token=${this.ajax.getCurrentToken()}` :\r\n      `popup.html#settings/signing?lang=${Translations.getLanguage()}&id=${this.onboardingService.model?.id ?? \"\"}#access_token=${this.ajax.getCurrentToken()}`);\r\n    return this.uiHelpers.showExternalDialog(onBoardingId, url , { id: onBoardingId, origin }, {width: 1080, height: 800}).then( (result) => {\r\n      if (result?.action != \"cancel\") {\r\n        return this.checkSession();\r\n      } else {\r\n        return;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Launches company wizard. */\r\n  public launchSigningWizard() {\r\n    const data =  this.readTokenFromUrl(this.$location.absUrl(), \"data=\");\r\n    const id = JSON.parse(atob(decodeURIComponent(data)))?.id;\r\n    const origin = JSON.parse(atob(decodeURIComponent(data)))?.origin;\r\n    return this.onboardingService.getOnboardingData(id).then( () => {\r\n      const skin = this.sessionService.getCurrentCss();\r\n      this.onboardingService.model.ui.successUrl = origin + (skin ?\r\n        `popup.html#settings/signing-success?skin=${skin}&lang=${Translations.getLanguage()}&id=${this.onboardingService.model?.id ?? \"\"}#access_token=${this.ajax.getCurrentToken()}` :\r\n        `popup.html#settings/signing-success?lang=${Translations.getLanguage()}&id=${this.onboardingService.model?.id ?? \"\"}#access_token=${this.ajax.getCurrentToken()}`);\r\n      this.onboardingService.model.ui.cancelUrl = this.onboardingService.model.ui.successUrl.replace(\"/signing-success?\", \"/signing-cancel?\");\r\n      return this.onboardingService.save().then( () => {\r\n        return this.onboardingService.launchCompanyOnboarding(this.onboardingService.model.id);\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Reloads the current session*/\r\n  public checkSession(): Promise<any> {\r\n    return this.sessionService.checkSession();\r\n  }\r\n\r\n  private readTokenFromUrl(url: string, key: string): string {\r\n    // shoud use regex...\r\n    const start = url.toLowerCase().indexOf(key);\r\n    if (start >= 0) {\r\n      const end = url.indexOf(\"&\", start);\r\n      return end >= 0\r\n        ? url.substring(start + key.length, end)\r\n        : url.substring(start + key.length);\r\n    }\r\n    return null;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, Language, Onboarding, Translations, WebSiteUserRole } from \"@salaxy/core\";\r\n\r\nimport { OnboardingService, SessionService, SignatureMethod, SignatureService, UiHelpers } from \"../../../services\";\r\n\r\n/**\r\n * Controller for showing the signing user interface for unsigned account.\r\n */\r\nexport class SigningController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"OnboardingService\", \"SessionService\", \"SignatureService\", \"$sce\", \"UiHelpers\", \"AjaxNg1\", \"$timeout\"];\r\n\r\n  /** If true (typically default), the signing person is also the contact person for the company */\r\n  public isContactPersonSigner: boolean;\r\n\r\n  /** If true, shows the component even if the Signing is already OK. Typically used only in test. */\r\n  public showAlways: boolean;\r\n\r\n  /** If true, component shows success popup */\r\n  public showInPopup = false;\r\n\r\n  /**\r\n   * Will be true if the component has done authentication and determines that signature is already OK\r\n   * If true, the component is not shown to the end user unless showAlways is set true.\r\n   */\r\n  public isSigningOk: boolean;\r\n\r\n  /** True when the session is available (auth) AND the signature is required. */\r\n  public isSigningRequired: boolean;\r\n\r\n  /** URL for the PDF preview. Changes when saved, to assure that PDF is not cached.  */\r\n  public pdfPreviewUrl: string;\r\n\r\n  /** Binding for button, which calls startDigitalSignature(). */\r\n  public isSigninStarted = false;\r\n\r\n  constructor(\r\n    private $scope: angular.IScope,\r\n    private onboardingService: OnboardingService,\r\n    private sessionService: SessionService,\r\n    private signatureService: SignatureService,\r\n    private $sce: angular.ISCEService,\r\n    private uiHelpers: UiHelpers,\r\n    private ajax: Ajax,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    this.init();\r\n\r\n    this.sessionService.subscribe(this.$scope, () => {\r\n      this.init();\r\n    });\r\n    this.isContactPersonSigner = true;\r\n  };\r\n\r\n  /** Saves the current onboarding model. */\r\n  public save(): Promise<Onboarding> {\r\n    if (this.isContactPersonSigner) {\r\n      this.model.company.contact.email = this.model.signature.email;\r\n      this.model.company.contact.telephone = this.model.signature.telephone;\r\n    }\r\n    return this.onboardingService.save()\r\n      .then((onboarding) => {\r\n        this.pdfPreviewUrl = null;\r\n        return onboarding;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * The onboarding model is provided by the onboarding service.\r\n   */\r\n  public get model(): Onboarding {\r\n    if (this.onboardingService.model?.company) {\r\n      this.onboardingService.model.company.language = Translations.getLanguage() as Language;\r\n    }\r\n    if (this.onboardingService.model?.person) {\r\n      this.onboardingService.model.person.language = Translations.getLanguage() as Language;\r\n    }\r\n    return this.onboardingService.model;\r\n  }\r\n\r\n  /** Returns the PDF preview address for the authorization pdf. */\r\n  public getPdfPreviewAddress() {\r\n    if (!this.pdfPreviewUrl && this.model?.id) {\r\n      this.pdfPreviewUrl = this.$sce.trustAsResourceUrl(this.onboardingService.getPdfPreviewAddress(true) + \"&t=\" + new Date().getTime() + \"&language=\" + this.model.company.language);\r\n    }\r\n    return this.pdfPreviewUrl;\r\n  }\r\n\r\n  /**\r\n   * Starts Visma sign\r\n   * If this.showInPopup is false, saves the model and starts the signature.\r\n   * If this.showInPopup is true, saves the model, starts the signature and then opens success dialog.\r\n   * @param authMethod Method of authentication (bank selection).\r\n   * Only used for Persons (Telia methods), ignored for companies.\r\n   */\r\n  public startDigitalSignature(authMethod: string) {\r\n    this.isSigninStarted = true;\r\n    if (this.showInPopup) {\r\n      this.save().then(() => {\r\n        let skin = this.sessionService.getCurrentCss() || \"\";\r\n        if (skin) {\r\n          skin = `skin=${skin}&`;\r\n        }\r\n\r\n        const successUrl = this.sessionService.getOrigin() +\r\n          `popup.html#settings/signing-success?${skin}lang=${Translations.getLanguage()}&id=${this.onboardingService.model?.id ?? \"\"}#access_token=${this.ajax.getCurrentToken()}`;\r\n        const url = this.onboardingService.getDigitalSignUrl(authMethod, null, null, successUrl, successUrl.replace(\"/signing-success?\", \"/signing-cancel?\") );\r\n        // To prevent double-clicking\r\n        this.$timeout(() => this.isSigninStarted = false, 2000);\r\n        return this.uiHelpers.showExternalDialog(\"vismaSignPopup\", url, {}, { width: 1080, height: 800 })\r\n          .then((result) => {\r\n            if (result?.action != \"cancel\") {\r\n              return this.sessionService.checkSession();\r\n            } else {\r\n              return;\r\n            }\r\n          });\r\n      });\r\n    } else {\r\n      this.uiHelpers.showLoading(\"SALAXY.NG1.SigningComponent.dialog.header\", `Siirrytään allekirjoitukseen (${authMethod})`);\r\n      // Saving is needed mainly for potential changes in name, e-mail and phone. AuthService, signerPersonalId and successUrl are passed in URL.\r\n      this.save().then(() => {\r\n        window.top.location.href = this.onboardingService.getDigitalSignUrl(authMethod);\r\n      });\r\n    }\r\n  }\r\n\r\n  /** List of supported Signature methods */\r\n  public get methods() {\r\n    return this.signatureService.getMethods();\r\n  }\r\n\r\n  /**\r\n   * Returns the SignatureMethod for given value.\r\n   * @param value - value for SignatureMethod, e.g. tupas-nordea.\r\n   */\r\n  public getMethod(value: string): SignatureMethod {\r\n    const arr = this.methods.filter((x) => x.value === value);\r\n    if (arr.length > 0) {\r\n      return arr[0];\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private init() {\r\n    this.isSigningOk = this.sessionService.isSigningOk();\r\n    this.pdfPreviewUrl = null;\r\n    this.isSigningRequired = !this.sessionService.isSigningOk();\r\n    if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n      const accountId = this.sessionService.session.currentAccount.id;\r\n      if (this.onboardingService.model && this.onboardingService.model.company.resolvedId === accountId) {\r\n        return;\r\n      }\r\n\r\n      // reset before get\r\n      this.onboardingService.model = null;\r\n      this.onboardingService.id = null;\r\n      this.onboardingService.getOnboardingDataForAccount(this.sessionService.session.currentAccount.id).then(() => {\r\n        if (this.onboardingService.model) {\r\n          this.onboardingService.model.signature.isPep = null;\r\n          this.onboardingService.model.company.ownership.isRequiredTracking = null;\r\n          if (!this.onboardingService.model.id) {\r\n            this.onboardingService.save();\r\n          }\r\n          return;\r\n        } else {\r\n          this.onboardingService.model = {\r\n            accountType: WebSiteUserRole.Company,\r\n            signature: {},\r\n          };\r\n          this.onboardingService.save();\r\n        }\r\n      });\r\n    }\r\n  }\r\n}\r\n\r\n","import angular from \"angular\";\r\n\r\nimport { SignatureMethod, SignatureService } from \"../../../services\";\r\n\r\n/**\r\n * Handles user interaction for Digital Signature\r\n */\r\nexport class SignatureController implements angular.IController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\r\n        \"SignatureService\",\r\n    ];\r\n\r\n    /**\r\n     * Creates a new SignatureController\r\n     * @param signatureService - Service that handles the communication to the server\r\n     * @ignore\r\n     */\r\n    constructor(private signatureService: SignatureService) {\r\n    }\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit = () => {\r\n        //\r\n    };\r\n\r\n    /**\r\n     * Legacy list of supported Visma Sign Signature methods.\r\n     */\r\n    public get methods() {\r\n        return this.getMethods(\"tupas\");\r\n    }\r\n\r\n    /**\r\n     * List of supported Signature methods\r\n     * @param methodGroup - Method group \"telia\" for Telia Tunnistus and \"tupas\" for Visma Sign. Default is \"tupas\".\r\n     */\r\n    public getMethods(methodGroup: \"tupas\" | \"telia\" = \"tupas\") {\r\n        return this.signatureService.getMethods(methodGroup);\r\n    }\r\n\r\n    /**\r\n     * Returns the SignatureMethod for given value.\r\n     * @param value - value for SignatureMethod, e.g. tupas-nordea.\r\n     */\r\n    public getMethod(value: string): SignatureMethod {\r\n        return this.signatureService.getMethods(\"tupas\").find( (x) => x.value === value)\r\n        ?? this.signatureService.getMethods(\"telia\").find( (x) => x.value === value);\r\n    }\r\n}\r\n","import { IService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Base class for CRUD controllers of legacy service model: BaseService<T> / IService<T>.\r\n * Most new implementations should use the new API CRUD model instead.\r\n * However, this service model may still be the right choice in certain circumstances where the editable data should be\r\n * cached or is already in session (like account data).\r\n */\r\nexport class CrudControllerBase<T> implements angular.IController {\r\n\r\n    /**\r\n     * Bindings for the component which uses CRUD controller.\r\n     */\r\n    public static crudBindings = {\r\n\r\n        /**\r\n         * Function that is called when user selects an item in the list.\r\n         * The selected item is the parameter of the function call.\r\n         * @example <salaxy-payroll-list on-list-select=\"$ctrl.myCustomSelectFunc(item)\"></salaxy-payroll-list>\r\n         */\r\n        onListSelect: \"&\",\r\n\r\n        /**\r\n         * Function that is called when an item is deleted.\r\n         * The event is intended for user interface logic after delete (promise resolve)\r\n         * and potentially when waiting for server to respond (from function call until promise resolve).\r\n         * It is not meant for delete validation and/or for preventing deletion.\r\n         * If onDelete is not specified, the browser is redirected to listUrl if specified.\r\n         * @example <salaxy-payroll-list on-delete=\"$ctrl.resetUiAfterDeleteFunc\"></salaxy-payroll-list>\r\n         */\r\n        onDelete: \"&\",\r\n\r\n        /**\r\n         * Function that is called after a new item has been created.\r\n         * At this point, the item has been created, but not yet selected as current.\r\n         * If onCreateNew is not specified the browser is redirected to detailsUrl if specified and if not, only current item is set.\r\n         * @example <salaxy-payroll-list on-create-new=\"$ctrl.startMyCustomWizardFunc\"></salaxy-payroll-list>\r\n         */\r\n        onCreateNew: \"&\",\r\n\r\n        /**\r\n         * URL to which the component navigates when an item is clicked.\r\n         * The \"id\" or \"rowIndex\" property of the selected item is added to the URL.\r\n         * URL is ignored if onListSelect is set. In this case, you may navigate yourself in that method.\r\n         * @example <salaxy-payroll-list details-url=\"/myCustomRoute/\"></salaxy-payroll-list>\r\n         */\r\n        detailsUrl: \"@\",\r\n\r\n        /**\r\n         * URL for the list view. At the moment, if specified, the browser is redirected here after delete.\r\n         * @example\r\n         * <!-- Main worker list is in the front page in this case -->\r\n         * <salaxy-employment-details list-url=\"/home\"></salaxy-employment-details>\r\n         */\r\n        listUrl: \"@\",\r\n    };\r\n\r\n    /**\r\n     * For list-controls, this is the URL for item select event\r\n     * as well as the URL where a new item is edited. Basically showing the Details view.\r\n     * For more control, use onListSelect or onCreateNew events.\r\n     * @example <salaxy-payroll-list details-url=\"/myCustomRoute/\"></salaxy-payroll-list>\r\n     */\r\n    public detailsUrl: string;\r\n\r\n    /**\r\n     * URL for the list view. At the moment, if specified, the browser is redirected here after delete.\r\n     * @example\r\n     * <!-- Main worker list is in the front page in this case -->\r\n     * <salaxy-employment-details list-url=\"/home\"></salaxy-employment-details>\r\n     */\r\n    public listUrl: string;\r\n\r\n    /**\r\n     * Angular ng-model **if** the controller is bound to model using ng-model attribute.\r\n     */\r\n    public model: angular.INgModelController;\r\n\r\n    /**\r\n     * Function that is called when an item is deleted.\r\n     * The event is intended for user interface logic after delete (promise resolve)\r\n     * and potentially when waiting for server to respond (from function call until promise resolve).\r\n     * It is not meant for delete validation and/or for preventing deletion.\r\n     * If onDelete is not specified, the browser is redirected to listUrl if specified.\r\n     * NOTE: the deleteResult should basically always be  Promise<true> or promise failure. Promise<false> does not really make sense here.\r\n     * @example <salaxy-payroll-list on-delete=\"$ctrl.resetUiAfterDeleteFunc(deleteResult)\"></salaxy-payroll-list>\r\n     */\r\n    public onDelete: (eventData: {\r\n      /** The deleteResult should basically always be  Promise<true> or promise failure. Promise<false> does not really make sense here. */\r\n      deleteResult: Promise<boolean>,\r\n    }) => Promise<boolean>;\r\n\r\n    /**\r\n     * Function that is called after a new item has been created.\r\n     * At this point, the item has been created, but not yet selected as current.\r\n     * If onCreateNew is not specified the browser is redirected to detailsUrl if specified and if not, only current item is set.\r\n     * @example <salaxy-payroll-list on-create-new=\"$ctrl.startMyCustomWizardFunc(item)\"></salaxy-payroll-list>\r\n     */\r\n    public onCreateNew: (eventData: {\r\n      /** New item which was created. */\r\n       item: T,\r\n      }) => void;\r\n\r\n    /**\r\n     * For list-controls, this is the function of on-list-select event.\r\n     * If onListSelect is not specified, the browser is redirected to detailsUrl if specified.\r\n     * If detailsUrl is not specified, only current item is set.\r\n     * @example <salaxy-payroll-list on-list-select=\"$ctrl.myCustomSelectFunc(item)\"></salaxy-payroll-list>\r\n     */\r\n    public onListSelect: (eventData: {\r\n      /** The selected item. */\r\n      item: T,\r\n    }) => void;\r\n\r\n    /**\r\n     * Creates a new CrudControllerBase.\r\n     * @param crudService The the BaseService instance that is used for communicating to server.\r\n     * @param $location Angular.js Location service that is used for navigation. Especially the list views.\r\n     * @param $attrs Angular.js Attisbutes for determining whether events have been bound to.\r\n     * @param uiHelpers - Salaxy ui helpers service.\r\n     */\r\n    constructor(\r\n        protected crudService: IService<T>,\r\n        protected $location: angular.ILocationService,\r\n        protected $attrs: angular.IAttributes,\r\n        protected uiHelpers: UiHelpers,\r\n    ) {\r\n        if (!crudService) {\r\n            throw new Error(\"crudService is undefined in CrudControllerBase\");\r\n        }\r\n        if (!$location) {\r\n            throw new Error(\"$location is undefined in CrudControllerBase\");\r\n        }\r\n        if (!uiHelpers) {\r\n            throw new Error(\"uiHelpers is undefined in CrudControllerBase\");\r\n        }\r\n        if (!$attrs) {\r\n            throw new Error(\"$attrs is undefined in CrudControllerBase\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Implement IController by providing onInit method.\r\n     * We currently do nothing here, but if you override this function,\r\n     * you should call this method in base class for future compatibility.\r\n     */\r\n    public $onInit() {\r\n        // No init code at the moment, we may add later if necessary.\r\n    }\r\n\r\n    /** Gets the Current selected item. */\r\n    public get current(): T {\r\n      if (this.getBindingMode() === \"model\") {\r\n        return this.model.$viewValue;\r\n      }\r\n      return this.crudService.current;\r\n    }\r\n\r\n    /** Gets the list of all CRUD objects listed. */\r\n    public get list(): T[] {\r\n        return this.crudService.list;\r\n    }\r\n\r\n    /**\r\n     * Creates a new item. The item is not saved in this process yet.\r\n     * Item is set as current unless onCreateNew is specified => Then you are responsible for doing it yourself.\r\n     * If detailsUrl is specified, the browser is redirectedted there.\r\n     * Current item is set also in this case (as opposed to listSelect) because the new item does not yet have an id\r\n     * and passing it in current item is the only way using router.\r\n     * Use onCreateNew event or crudService.getBlank() if you do not want to set the current item.\r\n     * @param newItem Specify the new item if you want to initialize it with specific values.\r\n     * In most cases, you should let the system create it with defaults.\r\n     */\r\n    public createNew(newItem: T = null): T {\r\n        if (!newItem) {\r\n            newItem = this.crudService.getBlank();\r\n        }\r\n        if (this.$attrs.onCreateNew) {\r\n            this.onCreateNew({ item: newItem });\r\n        } else {\r\n            this.setCurrent(newItem);\r\n            if (this.detailsUrl) {\r\n                // unique fraction is required for page refresh, if the list and details are in the same page.\r\n                this.$location.url(this.detailsUrl + \"new#\" + (new Date()).getTime());\r\n            }\r\n        }\r\n        return newItem;\r\n    }\r\n\r\n    /** Copies the current item and sets it as the new current */\r\n    public copyCurrent(): void {\r\n        if (this.current) {\r\n            this.setCurrent(this.crudService.copyAsNew(this.current));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Creates a copy of a given item and sets it as current\r\n     * unless onCreateNew is specified => Then you are responsible for doing it yourself.\r\n     * If detailsUrl is specified, the browser is redirectedted there.\r\n     * Current item is set also in this case (as opposed to listSelect) because the new item does not yet have an id\r\n     * and passing it in current item is the only way using router.\r\n     * Use onCreateNew event or crudService.copyAsNew() if you do not want to set the current item.\r\n     * @param copySource The item to copy as new.\r\n     * @returns The new item that is created.\r\n     */\r\n    public copyAsNew(copySource: T): T {\r\n        const copy = this.crudService.copyAsNew(copySource);\r\n        return this.createNew(copy);\r\n    }\r\n\r\n    /**\r\n     * Creates a copy of a given item and sets it as current\r\n     * unless onCreateNew is specified => Then you are responsible for doing it yourself.\r\n     * If detailsUrl is specified, the browser is redirectedted there.\r\n     * Current item is set also in this case (as opposed to listSelect) because the new item does not yet have an id\r\n     * and passing it in current item is the only way using router.\r\n     * Use onCreateNew event or crudService.copyAsNew() if you do not want to set the current item.\r\n     * @param copySourceId The id of the item to copy as new.\r\n     * @returns The new item that is created.\r\n     */\r\n    public copyIdAsNew = (copySourceId: string): T => {\r\n      const copySource = this.list.find( (x) => (x as any).id === copySourceId);\r\n      if (copySource) {\r\n        return this.copyAsNew(copySource);\r\n      }\r\n      return null;\r\n    };\r\n\r\n    /**\r\n     * Mode for data binding is \"singleton\" by default.\r\n     * This means that this.current is bound to crudService.current.\r\n     * If ng-model is defined for the component (this.ngModelController),\r\n     * this.current is bound to ngModelController view value (as with form controls).\r\n     */\r\n    public getBindingMode(): \"model\" | \"singleton\" {\r\n      return this.model ? \"model\" : \"singleton\";\r\n    }\r\n\r\n    /** Called by the view when the item is clicked. */\r\n    public listSelect = (selectedItem: T) => {\r\n        if (this.$attrs.onListSelect) {\r\n            this.onListSelect({ item: selectedItem });\r\n        } else if (this.detailsUrl) {\r\n            this.$location.url(this.detailsUrl + ((selectedItem as any).id || (selectedItem as any).rowIndex));\r\n        } else {\r\n            this.setCurrent(selectedItem);\r\n        }\r\n    };\r\n\r\n    /** Called by the view when the item (id) is clicked. */\r\n    public listSelectId = (selectedItemId: string) => {\r\n      const selectedItem = this.list.find( (x) => (x as any).id === selectedItemId );\r\n      if (selectedItem) {\r\n        this.listSelect(selectedItem);\r\n      }\r\n    };\r\n\r\n    /** Saves the current item. */\r\n    public saveCurrent(): Promise<T> {\r\n      return this.crudService.saveCurrent();\r\n    }\r\n\r\n    /**\r\n     * Sets the current item: Either to ng-model view value or crudService.setCurrent().\r\n     * @param item The item to set as Current.\r\n     */\r\n    public setCurrent(item: T) {\r\n      if (this.getBindingMode() === \"model\") {\r\n        this.model.$setViewValue(item);\r\n      } else {\r\n        this.crudService.setCurrent(item);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Shows the \"Are you sure?\" dialog and if user clicks OK, deletes the item.\r\n     * Cancels the started payment for the payroll too.\r\n     * @param id Identifier of the item to be deleted.\r\n     * @param confirmMessage Optional custom message for the confirm dialog.\r\n     * If not specified, a generic message is shown.\r\n     * If set to boolean false, the confirm message is not shown at all.\r\n     * @returns Promise that resolves to true if the item is deleted.\r\n     * False, if user cancels and fails if the deletion fails.\r\n     */\r\n    public delete = (id: string, confirmMessage?: string): Promise<boolean> => {\r\n      return this.uiHelpers.showConfirm(confirmMessage || \"SALAXY.NG1.ApiCrudObjectComponent.deleteDialog\")\r\n          .then((result: boolean) => {\r\n              if (result) {\r\n                  if (this.$attrs.onDelete) {\r\n                      return this.onDelete({ deleteResult: this.deleteNoConfirm(id)});\r\n                  }\r\n                  if (this.listUrl) {\r\n                      this.$location.url(this.listUrl);\r\n                  }\r\n                  return this.deleteNoConfirm(id);\r\n              } else {\r\n                  return Promise.resolve(false);\r\n              }\r\n          });\r\n    };\r\n\r\n    /**\r\n     * Deletes an item without showing the confirm dialog.\r\n     * The method shows the \"Please wait...\" loader, but does not call onDelete\r\n     * or move the browser to listUrl. The caller should take care\r\n     * of the UX actions after delete if necessary.\r\n     * @param id Identifier of the item to be deleted.\r\n     * @returns Promise that resolves to true (never false). Fails if the deletion fails.\r\n     */\r\n    public deleteNoConfirm(id: string): Promise<boolean> {\r\n        const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n        return this.crudService.delete(id).then(() => {\r\n            loading.dismiss();\r\n            return true;\r\n        });\r\n    }\r\n\r\n}\r\n","import { Ajax, AuthorizedAvatar, CompanyAccount, PersonAccount } from \"@salaxy/core\";\r\n\r\nimport { AuthorizedAccountService, SessionService, UiHelpers } from \"../../services\";\r\nimport { CrudControllerBase } from \"../bases/CrudControllerBase\";\r\n\r\n/**\r\n * Handles user interaction for viewing and modifying authorized and authorizing accounts.\r\n */\r\nexport class AccountAuthorizationController extends CrudControllerBase<AuthorizedAvatar> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AuthorizedAccountService\",\r\n    \"$location\",\r\n    \"$attrs\",\r\n    \"UiHelpers\",\r\n    \"SessionService\",\r\n    \"AjaxNg1\",\r\n  ];\r\n\r\n   /** If true, the switch will be disabled and its value cannot be changed by clicking/toggling it */\r\n   public disabled: boolean;\r\n\r\n  constructor(\r\n    private authorizedAccountService: AuthorizedAccountService,\r\n    $location: angular.ILocationService,\r\n    $attrs: angular.IAttributes,\r\n    uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n    private ajax: Ajax,\r\n  ) {\r\n    super(authorizedAccountService, $location, $attrs, uiHelpers);\r\n  }\r\n\r\n\r\n\r\n  /**\r\n   * Returns the list of Integration partner sites available and the status of each partner.\r\n   */\r\n  public get partnerIntegrationSites() {\r\n    return this.authorizedAccountService.getPartnerIntegrationSiteList();\r\n  }\r\n\r\n  /**\r\n   * Gets a specific partner site for the current user\r\n   * @param id Identifier of the site\r\n   */\r\n  public getPartnerSite(id: string) {\r\n\r\n    return this.authorizedAccountService.getPartnerSite(id);\r\n  }\r\n\r\n  /**\r\n   * Returns the current partner site\r\n   */\r\n  public get currentPartnerSite() {\r\n    return this.authorizedAccountService.getCurrentPartnerSite();\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for adding / removing authorizations from known partners that\r\n   * frequently require authorizations. These are typically integrated software\r\n   * that are added without Primary Partner flag.\r\n   * @param id - The id of the partner site for which the dialog is shown.\r\n   */\r\n  public showPartnerSiteDialog(id: string) {\r\n    const partnerSite = this.getPartnerSite(id);\r\n    this.authorizedAccountService.setCurrentPartnerSite(partnerSite);\r\n    this.uiHelpers.showDialog(\"salaxy-components/modals/account/Authorization.html\", \"AccountAuthorizationController\");\r\n  }\r\n\r\n    /** Toggles the authorization option and makes the corresponding api call. */\r\n    public switchAuthorization() {\r\n      const partnerSite =  this.currentPartnerSite;\r\n      if (this.disabled !== true && !partnerSite.disabled) {\r\n        if (partnerSite.enabled == false && partnerSite.accountId) {\r\n          console.debug(\"delete\");\r\n          this.authorizedAccountService.delete(partnerSite.accountId);\r\n        } else if (partnerSite.enabled == true && partnerSite.accountId) {\r\n          console.debug(\"save\");\r\n          const authorizedAccount = this.authorizedAccountService.getBlank();\r\n          authorizedAccount.id = partnerSite.accountId;\r\n          this.authorizedAccountService.save(authorizedAccount);\r\n        }\r\n      }\r\n    }\r\n  /**\r\n   * Returns the authorizing accounts for the current account\r\n   */\r\n  public get authorizingAccounts(): (PersonAccount | CompanyAccount)[] {\r\n    return this.authorizedAccountService.getAuthorizingAccounts();\r\n  }\r\n\r\n  /** Deletes the account. Only in test. */\r\n  public deleteAccount(accountId: string) {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin, tiliä ei voi palauttaa?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.ajax.remove(\"/accounts/authorizingAccount/\" + accountId).then(() => {\r\n            this.authorizedAccountService.reloadAuthorizingAccounts().then(() => {\r\n              loading.dismiss();\r\n            });\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for adding any new authorized account.\r\n   */\r\n  public showAuthorizedAccountAddDialog() {\r\n    super.createNew();\r\n    this.uiHelpers.showDialog(\"salaxy-components/modals/account/AuthorizedAccountAdd.html\", \"AccountAuthorizationController\");\r\n  }\r\n\r\n  /** Adds authorized account */\r\n  public saveCurrent(callback: (avatar: AuthorizedAvatar) => void = null): Promise<AuthorizedAvatar> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return super.saveCurrent().then((avatar: AuthorizedAvatar) => {\r\n      loading.dismiss();\r\n      if (callback) {\r\n        callback(avatar);\r\n      }\r\n      return avatar;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Adds access token to url.\r\n   * @param accountId - Account id to login as.\r\n   */\r\n  public getLoginAsUrl(accountId): string {\r\n\r\n    let url = this.ajax.getServerAddress() + \"/Security/LoginAs/\" + accountId;\r\n    url = url + \"?access_token=\" + encodeURIComponent(this.ajax.getCurrentToken());\r\n    return url;\r\n  }\r\n\r\n  /**\r\n   * Checks whether the user is in a given role\r\n   * @param role - One of the known roles\r\n   */\r\n  public isInRole(role: any): boolean {\r\n    return this.sessionService.isInRole(role);\r\n  }\r\n\r\n}\r\n","import { Certificate, Certificates, InputEnumOption, IssuedCertificate, Translations } from \"@salaxy/core\";\r\n\r\nimport { CertificateService, UiHelpers } from \"../../services\";\r\nimport { CrudControllerBase } from \"../bases/CrudControllerBase\";\r\n\r\n/** Certificate controller for listing certificate, revoking and requesting a new certificate. */\r\nexport class CertificateController extends CrudControllerBase<Certificate> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"CertificateService\", \"$location\", \"$attrs\", \"UiHelpers\", \"Certificates\"];\r\n\r\n  constructor(\r\n    private certificateService: CertificateService,\r\n    $location: angular.ILocationService,\r\n    $attrs: angular.IAttributes,\r\n    uiHelpers: UiHelpers,\r\n    private certificateApi: Certificates,\r\n  ) {\r\n    super(certificateService, $location, $attrs, uiHelpers);\r\n  }\r\n\r\n  /** Creates a new certificate */\r\n  public createNew(): Certificate {\r\n    super.createNew();\r\n    this.current.title = Translations.get(\"SALAXY.NG1.CertificatesComponent.newCertificate\");\r\n    return this.current;\r\n  }\r\n\r\n  public result: {\r\n    /** Certificate file as blob. */\r\n    blob: Blob;\r\n    /** Certificate file as text. */\r\n    text: string;\r\n    /** Certificate thumbprint. */\r\n    thumbprint: string;\r\n  } = undefined;\r\n\r\n  /** Certificate format (id) */\r\n  public certFormat: \"pfx\" | \"pem\" = \"pfx\";\r\n\r\n  /** Returns the metadata for the certFrmat */\r\n  public get currentCertFormat() {\r\n    return this.certFormats.find((f) => f.value === this.certFormat) || this.certFormats[0];\r\n  }\r\n\r\n  /** Avilabe certificate formats */\r\n  public certFormats: InputEnumOption[] = [\r\n    {\r\n      value: \"pfx\",\r\n      text: \"Windows-sertifikaatti (pfx / pkcs12)\",\r\n      ui: {\r\n        mime: \"application/x-pkcs12\",\r\n        suffix: \"pfx\",\r\n      }\r\n    }, {\r\n      value: \"pem\",\r\n      text: \"Yleinen sertifikaatti (zip / pem)\",\r\n      ui: {\r\n        mime: \"application/zip\",\r\n        suffix: \"zip\",\r\n      },\r\n    },\r\n  ];\r\n\r\n  /**\r\n   * Shows a dialog for adding nw certificate.\r\n   */\r\n  public showCertificateAddDialog() {\r\n    this.createNew();\r\n    this.uiHelpers.showDialog(\"salaxy-components/modals/account/CertificateAdd.html\", \"CertificateController\");\r\n  }\r\n\r\n  /** Creates a new certificate */\r\n  public createCert(): void {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    if (this.certFormat === \"pem\") {\r\n      this.certificateApi.issuePemCertificate(this.current).then((certificate: IssuedCertificate) => {\r\n        this.result = {\r\n          blob: this.uiHelpers.bytes2Blob(certificate.bytes, this.currentCertFormat.ui.mime),\r\n          text: certificate.cert + \"\\n\\n\" + certificate.key,\r\n          thumbprint: certificate.thumbprint,\r\n        };\r\n        loading.dismiss();\r\n      });\r\n    } else {\r\n      super.saveCurrent().then((certificate: Certificate) => {\r\n        this.result = {\r\n          blob: this.uiHelpers.bytes2Blob(certificate.bytes, this.currentCertFormat.ui.mime),\r\n          text: certificate.bytes,\r\n          thumbprint: certificate.thumbprint,\r\n        };\r\n        loading.dismiss();\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Downloads current.blob as pfx and sets current.id as name\r\n   */\r\n  public downloadCertFile() {\r\n    this.uiHelpers.downloadFile(this.result.blob, `${this.result.thumbprint}.${this.currentCertFormat.ui.suffix}`);\r\n  }\r\n}\r\n","/**\n * @license AngularJS v1.8.3\n * (c) 2010-2020 Google LLC. http://angularjs.org\n * License: MIT\n */\n(function(window) {'use strict';\n\n/* exported\n  minErrConfig,\n  errorHandlingConfig,\n  isValidObjectMaxDepth\n*/\n\nvar minErrConfig = {\n  objectMaxDepth: 5,\n  urlErrorParamsEnabled: true\n};\n\n/**\n * @ngdoc function\n * @name angular.errorHandlingConfig\n * @module ng\n * @kind function\n *\n * @description\n * Configure several aspects of error handling in AngularJS if used as a setter or return the\n * current configuration if used as a getter. The following options are supported:\n *\n * - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.\n *\n * Omitted or undefined options will leave the corresponding configuration values unchanged.\n *\n * @param {Object=} config - The configuration object. May only contain the options that need to be\n *     updated. Supported keys:\n *\n * * `objectMaxDepth`  **{Number}** - The max depth for stringifying objects. Setting to a\n *   non-positive or non-numeric value, removes the max depth limit.\n *   Default: 5\n *\n * * `urlErrorParamsEnabled`  **{Boolean}** - Specifies whether the generated error url will\n *   contain the parameters of the thrown error. Disabling the parameters can be useful if the\n *   generated error url is very long.\n *\n *   Default: true. When used without argument, it returns the current value.\n */\nfunction errorHandlingConfig(config) {\n  if (isObject(config)) {\n    if (isDefined(config.objectMaxDepth)) {\n      minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;\n    }\n    if (isDefined(config.urlErrorParamsEnabled) && isBoolean(config.urlErrorParamsEnabled)) {\n      minErrConfig.urlErrorParamsEnabled = config.urlErrorParamsEnabled;\n    }\n  } else {\n    return minErrConfig;\n  }\n}\n\n/**\n * @private\n * @param {Number} maxDepth\n * @return {boolean}\n */\nfunction isValidObjectMaxDepth(maxDepth) {\n  return isNumber(maxDepth) && maxDepth > 0;\n}\n\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * AngularJS. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace'). Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n *   error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n  ErrorConstructor = ErrorConstructor || Error;\n\n  var url = 'https://errors.angularjs.org/1.8.3/';\n  var regex = url.replace('.', '\\\\.') + '[\\\\s\\\\S]*';\n  var errRegExp = new RegExp(regex, 'g');\n\n  return function() {\n    var code = arguments[0],\n      template = arguments[1],\n      message = '[' + (module ? module + ':' : '') + code + '] ',\n      templateArgs = sliceArgs(arguments, 2).map(function(arg) {\n        return toDebugString(arg, minErrConfig.objectMaxDepth);\n      }),\n      paramPrefix, i;\n\n    // A minErr message has two parts: the message itself and the url that contains the\n    // encoded message.\n    // The message's parameters can contain other error messages which also include error urls.\n    // To prevent the messages from getting too long, we strip the error urls from the parameters.\n\n    message += template.replace(/\\{\\d+\\}/g, function(match) {\n      var index = +match.slice(1, -1);\n\n      if (index < templateArgs.length) {\n        return templateArgs[index].replace(errRegExp, '');\n      }\n\n      return match;\n    });\n\n    message += '\\n' + url + (module ? module + '/' : '') + code;\n\n    if (minErrConfig.urlErrorParamsEnabled) {\n      for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {\n        message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]);\n      }\n    }\n\n    return new ErrorConstructor(message);\n  };\n}\n\n/* We need to tell ESLint what variables are being exported */\n/* exported\n  angular,\n  msie,\n  jqLite,\n  jQuery,\n  slice,\n  splice,\n  push,\n  toString,\n  minErrConfig,\n  errorHandlingConfig,\n  isValidObjectMaxDepth,\n  ngMinErr,\n  angularModule,\n  uid,\n  REGEX_STRING_REGEXP,\n  VALIDITY_STATE_PROPERTY,\n\n  lowercase,\n  uppercase,\n  nodeName_,\n  isArrayLike,\n  forEach,\n  forEachSorted,\n  reverseParams,\n  nextUid,\n  setHashKey,\n  extend,\n  toInt,\n  inherit,\n  merge,\n  noop,\n  identity,\n  valueFn,\n  isUndefined,\n  isDefined,\n  isObject,\n  isBlankObject,\n  isString,\n  isNumber,\n  isNumberNaN,\n  isDate,\n  isError,\n  isArray,\n  isFunction,\n  isRegExp,\n  isWindow,\n  isScope,\n  isFile,\n  isFormData,\n  isBlob,\n  isBoolean,\n  isPromiseLike,\n  trim,\n  escapeForRegexp,\n  isElement,\n  makeMap,\n  includes,\n  arrayRemove,\n  copy,\n  simpleCompare,\n  equals,\n  csp,\n  jq,\n  concat,\n  sliceArgs,\n  bind,\n  toJsonReplacer,\n  toJson,\n  fromJson,\n  convertTimezoneToLocal,\n  timezoneToOffset,\n  addDateMinutes,\n  startingTag,\n  tryDecodeURIComponent,\n  parseKeyValue,\n  toKeyValue,\n  encodeUriSegment,\n  encodeUriQuery,\n  angularInit,\n  bootstrap,\n  getTestability,\n  snake_case,\n  bindJQuery,\n  assertArg,\n  assertArgFn,\n  assertNotHasOwnProperty,\n  getter,\n  getBlockNodes,\n  hasOwnProperty,\n  createMap,\n  stringify,\n  UNSAFE_restoreLegacyJqLiteXHTMLReplacement,\n\n  NODE_TYPE_ELEMENT,\n  NODE_TYPE_ATTRIBUTE,\n  NODE_TYPE_TEXT,\n  NODE_TYPE_COMMENT,\n  NODE_TYPE_DOCUMENT,\n  NODE_TYPE_DOCUMENT_FRAGMENT\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @installation\n * @description\n *\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @private\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\n\n/**\n * @private\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    splice            = [].splice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    getPrototypeOf    = Object.getPrototypeOf,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    uid               = 0;\n\n// Support: IE 9-11 only\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = window.document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n\n  // `null`, `undefined` and `window` are not array-like\n  if (obj == null || isWindow(obj)) return false;\n\n  // arrays, strings and jQuery/jqLite objects are array like\n  // * jqLite is either the jQuery or jqLite constructor function\n  // * we have to check the existence of jqLite first as this method is called\n  //   via the forEach method when constructing the jqLite object in the first place\n  if (isArray(obj) || isString(obj) || (jqLite && obj instanceof jqLite)) return true;\n\n  // Support: iOS 8.2 (not reproducible in simulator)\n  // \"length\" in obj used to prevent JIT error (gh-11508)\n  var length = 'length' in Object(obj) && obj.length;\n\n  // NodeList objects (with `item` method) and\n  // other objects with suitable length characteristics are array-like\n  return isNumber(length) && (length >= 0 && (length - 1) in obj || typeof obj.item === 'function');\n\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n  var key, length;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        if (key !== 'prototype' && key !== 'length' && key !== 'name' && obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      var isPrimitive = typeof obj !== 'object';\n      for (key = 0, length = obj.length; key < length; key++) {\n        if (isPrimitive || key in obj) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context, obj);\n    } else if (isBlankObject(obj)) {\n      // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty\n      for (key in obj) {\n        iterator.call(context, obj[key], key, obj);\n      }\n    } else if (typeof obj.hasOwnProperty === 'function') {\n      // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    } else {\n      // Slow path for objects which do not have a method `hasOwnProperty`\n      for (key in obj) {\n        if (hasOwnProperty.call(obj, key)) {\n          iterator.call(context, obj[key], key, obj);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = Object.keys(obj).sort();\n  for (var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) {iteratorFn(key, value);};\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n  return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  } else {\n    delete obj.$$hashKey;\n  }\n}\n\n\nfunction baseExtend(dst, objs, deep) {\n  var h = dst.$$hashKey;\n\n  for (var i = 0, ii = objs.length; i < ii; ++i) {\n    var obj = objs[i];\n    if (!isObject(obj) && !isFunction(obj)) continue;\n    var keys = Object.keys(obj);\n    for (var j = 0, jj = keys.length; j < jj; j++) {\n      var key = keys[j];\n      var src = obj[key];\n\n      if (deep && isObject(src)) {\n        if (isDate(src)) {\n          dst[key] = new Date(src.valueOf());\n        } else if (isRegExp(src)) {\n          dst[key] = new RegExp(src);\n        } else if (src.nodeName) {\n          dst[key] = src.cloneNode(true);\n        } else if (isElement(src)) {\n          dst[key] = src.clone();\n        } else {\n          if (key !== '__proto__') {\n            if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};\n            baseExtend(dst[key], [src], true);\n          }\n        }\n      } else {\n        dst[key] = src;\n      }\n    }\n  }\n\n  setHashKey(dst, h);\n  return dst;\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n *\n * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use\n * {@link angular.merge} for this.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  return baseExtend(dst, slice.call(arguments, 1), false);\n}\n\n\n/**\n* @ngdoc function\n* @name angular.merge\n* @module ng\n* @kind function\n*\n* @description\n* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.\n*\n* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source\n* objects, performing a deep copy.\n*\n* @deprecated\n* sinceVersion=\"1.6.5\"\n* This function is deprecated, but will not be removed in the 1.x lifecycle.\n* There are edge cases (see {@link angular.merge#known-issues known issues}) that are not\n* supported by this function. We suggest using another, similar library for all-purpose merging,\n* such as [lodash's merge()](https://lodash.com/docs/4.17.4#merge).\n*\n* @knownIssue\n* This is a list of (known) object types that are not handled correctly by this function:\n* - [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob)\n* - [`MediaStream`](https://developer.mozilla.org/docs/Web/API/MediaStream)\n* - [`CanvasGradient`](https://developer.mozilla.org/docs/Web/API/CanvasGradient)\n* - AngularJS {@link $rootScope.Scope scopes};\n*\n* `angular.merge` also does not support merging objects with circular references.\n*\n* @param {Object} dst Destination object.\n* @param {...Object} src Source object(s).\n* @returns {Object} Reference to `dst`.\n*/\nfunction merge(dst) {\n  return baseExtend(dst, slice.call(arguments, 1), true);\n}\n\n\n\nfunction toInt(str) {\n  return parseInt(str, 10);\n}\n\nvar isNumberNaN = Number.isNaN || function isNumberNaN(num) {\n  // eslint-disable-next-line no-self-compare\n  return num !== num;\n};\n\n\nfunction inherit(parent, extra) {\n  return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n   function transformer(transformationFn, value) {\n     return (transformationFn || angular.identity)(value);\n   };\n\n   // E.g.\n   function getResult(fn, input) {\n     return (fn || angular.identity)(input);\n   };\n\n   getResult(function(n) { return n * 2; }, 21);   // returns 42\n   getResult(null, 21);                            // returns 21\n   getResult(undefined, 21);                       // returns 21\n   ```\n *\n * @param {*} value to be returned.\n * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function valueRef() {return value;};}\n\nfunction hasCustomToString(obj) {\n  return isFunction(obj.toString) && obj.toString !== toString;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n  // http://jsperf.com/isobject4\n  return value !== null && typeof value === 'object';\n}\n\n\n/**\n * Determine if a value is an object with a null prototype\n *\n * @returns {boolean} True if `value` is an `Object` with a null prototype\n */\nfunction isBlankObject(value) {\n  return value !== null && typeof value === 'object' && !getPrototypeOf(value);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * This includes the \"special\" numbers `NaN`, `+Infinity` and `-Infinity`.\n *\n * If you wish to exclude these then you can use the native\n * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)\n * method.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nfunction isArray(arr) {\n  return Array.isArray(arr) || arr instanceof Array;\n}\n\n/**\n * @description\n * Determines if a reference is an `Error`.\n * Loosely based on https://www.npmjs.com/package/iserror\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Error`.\n */\nfunction isError(value) {\n  var tag = toString.call(value);\n  switch (tag) {\n    case '[object Error]': return true;\n    case '[object Exception]': return true;\n    case '[object DOMException]': return true;\n    default: return value instanceof Error;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n  return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar TYPED_ARRAY_REGEXP = /^\\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array]$/;\nfunction isTypedArray(value) {\n  return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));\n}\n\nfunction isArrayBuffer(obj) {\n  return toString.call(obj) === '[object ArrayBuffer]';\n}\n\n\nvar trim = function(value) {\n  return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n  return s\n    .replace(/([-()[\\]{}+?*.$^|,:#<!\\\\])/g, '\\\\$1')\n    // eslint-disable-next-line no-control-regex\n    .replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // We are a direct element.\n    || (node.prop && node.attr && node.find)));  // We have an on and find method part of jQuery API.\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(','), i;\n  for (i = 0; i < items.length; i++) {\n    obj[items[i]] = true;\n  }\n  return obj;\n}\n\n\nfunction nodeName_(element) {\n  return lowercase(element.nodeName || (element[0] && element[0].nodeName));\n}\n\nfunction includes(array, obj) {\n  return Array.prototype.indexOf.call(array, obj) !== -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = array.indexOf(value);\n  if (index >= 0) {\n    array.splice(index, 1);\n  }\n  return index;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array. This functions is used\n * internally, mostly in the change-detection code. It is not intended as an all-purpose copy\n * function, and has several limitations (see below).\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to `destination` an exception will be thrown.\n *\n * <br />\n *\n * <div class=\"alert alert-warning\">\n *   Only enumerable properties are taken into account. Non-enumerable properties (both on `source`\n *   and on `destination`) will be ignored.\n * </div>\n *\n * <div class=\"alert alert-warning\">\n *   `angular.copy` does not check if destination and source are of the same type. It's the\n *   developer's responsibility to make sure they are compatible.\n * </div>\n *\n * @knownIssue\n * This is a non-exhaustive list of object types / features that are not handled correctly by\n * `angular.copy`. Note that since this functions is used by the change detection code, this\n * means binding or watching objects of these types (or that include these types) might not work\n * correctly.\n * - [`File`](https://developer.mozilla.org/docs/Web/API/File)\n * - [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\n * - [`ImageData`](https://developer.mozilla.org/docs/Web/API/ImageData)\n * - [`MediaStream`](https://developer.mozilla.org/docs/Web/API/MediaStream)\n * - [`Set`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Set)\n * - [`WeakMap`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)\n * - [`getter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)/\n *   [`setter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)\n *\n * @param {*} source The source that will be used to make a copy. Can be any type, including\n *     primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If provided,\n *     must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n  <example module=\"copyExample\" name=\"angular-copy\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form novalidate class=\"simple-form\">\n          <label>Name: <input type=\"text\" ng-model=\"user.name\" /></label><br />\n          <label>Age:  <input type=\"number\" ng-model=\"user.age\" /></label><br />\n          Gender: <label><input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male</label>\n                  <label><input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female</label><br />\n          <button ng-click=\"reset()\">RESET</button>\n          <button ng-click=\"update(user)\">SAVE</button>\n        </form>\n        <pre>form = {{user | json}}</pre>\n        <pre>leader = {{leader | json}}</pre>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      // Module: copyExample\n      angular.\n        module('copyExample', []).\n        controller('ExampleController', ['$scope', function($scope) {\n          $scope.leader = {};\n\n          $scope.reset = function() {\n            // Example with 1 argument\n            $scope.user = angular.copy($scope.leader);\n          };\n\n          $scope.update = function(user) {\n            // Example with 2 arguments\n            angular.copy(user, $scope.leader);\n          };\n\n          $scope.reset();\n        }]);\n    </file>\n  </example>\n */\nfunction copy(source, destination, maxDepth) {\n  var stackSource = [];\n  var stackDest = [];\n  maxDepth = isValidObjectMaxDepth(maxDepth) ? maxDepth : NaN;\n\n  if (destination) {\n    if (isTypedArray(destination) || isArrayBuffer(destination)) {\n      throw ngMinErr('cpta', 'Can\\'t copy! TypedArray destination cannot be mutated.');\n    }\n    if (source === destination) {\n      throw ngMinErr('cpi', 'Can\\'t copy! Source and destination are identical.');\n    }\n\n    // Empty the destination object\n    if (isArray(destination)) {\n      destination.length = 0;\n    } else {\n      forEach(destination, function(value, key) {\n        if (key !== '$$hashKey') {\n          delete destination[key];\n        }\n      });\n    }\n\n    stackSource.push(source);\n    stackDest.push(destination);\n    return copyRecurse(source, destination, maxDepth);\n  }\n\n  return copyElement(source, maxDepth);\n\n  function copyRecurse(source, destination, maxDepth) {\n    maxDepth--;\n    if (maxDepth < 0) {\n      return '...';\n    }\n    var h = destination.$$hashKey;\n    var key;\n    if (isArray(source)) {\n      for (var i = 0, ii = source.length; i < ii; i++) {\n        destination.push(copyElement(source[i], maxDepth));\n      }\n    } else if (isBlankObject(source)) {\n      // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty\n      for (key in source) {\n        destination[key] = copyElement(source[key], maxDepth);\n      }\n    } else if (source && typeof source.hasOwnProperty === 'function') {\n      // Slow path, which must rely on hasOwnProperty\n      for (key in source) {\n        if (source.hasOwnProperty(key)) {\n          destination[key] = copyElement(source[key], maxDepth);\n        }\n      }\n    } else {\n      // Slowest path --- hasOwnProperty can't be called as a method\n      for (key in source) {\n        if (hasOwnProperty.call(source, key)) {\n          destination[key] = copyElement(source[key], maxDepth);\n        }\n      }\n    }\n    setHashKey(destination, h);\n    return destination;\n  }\n\n  function copyElement(source, maxDepth) {\n    // Simple values\n    if (!isObject(source)) {\n      return source;\n    }\n\n    // Already copied values\n    var index = stackSource.indexOf(source);\n    if (index !== -1) {\n      return stackDest[index];\n    }\n\n    if (isWindow(source) || isScope(source)) {\n      throw ngMinErr('cpws',\n        'Can\\'t copy! Making copies of Window or Scope instances is not supported.');\n    }\n\n    var needsRecurse = false;\n    var destination = copyType(source);\n\n    if (destination === undefined) {\n      destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));\n      needsRecurse = true;\n    }\n\n    stackSource.push(source);\n    stackDest.push(destination);\n\n    return needsRecurse\n      ? copyRecurse(source, destination, maxDepth)\n      : destination;\n  }\n\n  function copyType(source) {\n    switch (toString.call(source)) {\n      case '[object Int8Array]':\n      case '[object Int16Array]':\n      case '[object Int32Array]':\n      case '[object Float32Array]':\n      case '[object Float64Array]':\n      case '[object Uint8Array]':\n      case '[object Uint8ClampedArray]':\n      case '[object Uint16Array]':\n      case '[object Uint32Array]':\n        return new source.constructor(copyElement(source.buffer), source.byteOffset, source.length);\n\n      case '[object ArrayBuffer]':\n        // Support: IE10\n        if (!source.slice) {\n          // If we're in this case we know the environment supports ArrayBuffer\n          /* eslint-disable no-undef */\n          var copied = new ArrayBuffer(source.byteLength);\n          new Uint8Array(copied).set(new Uint8Array(source));\n          /* eslint-enable */\n          return copied;\n        }\n        return source.slice(0);\n\n      case '[object Boolean]':\n      case '[object Number]':\n      case '[object String]':\n      case '[object Date]':\n        return new source.constructor(source.valueOf());\n\n      case '[object RegExp]':\n        var re = new RegExp(source.source, source.toString().match(/[^/]*$/)[0]);\n        re.lastIndex = source.lastIndex;\n        return re;\n\n      case '[object Blob]':\n        return new source.constructor([source], {type: source.type});\n    }\n\n    if (isFunction(source.cloneNode)) {\n      return source.cloneNode(true);\n    }\n  }\n}\n\n\n// eslint-disable-next-line no-self-compare\nfunction simpleCompare(a, b) { return a === b || (a !== a && b !== b); }\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n *\n * @example\n   <example module=\"equalsExample\" name=\"equalsExample\">\n     <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <form novalidate>\n          <h3>User 1</h3>\n          Name: <input type=\"text\" ng-model=\"user1.name\">\n          Age: <input type=\"number\" ng-model=\"user1.age\">\n\n          <h3>User 2</h3>\n          Name: <input type=\"text\" ng-model=\"user2.name\">\n          Age: <input type=\"number\" ng-model=\"user2.age\">\n\n          <div>\n            <br/>\n            <input type=\"button\" value=\"Compare\" ng-click=\"compare()\">\n          </div>\n          User 1: <pre>{{user1 | json}}</pre>\n          User 2: <pre>{{user2 | json}}</pre>\n          Equal: <pre>{{result}}</pre>\n        </form>\n      </div>\n    </file>\n    <file name=\"script.js\">\n        angular.module('equalsExample', []).controller('ExampleController', ['$scope', function($scope) {\n          $scope.user1 = {};\n          $scope.user2 = {};\n          $scope.compare = function() {\n            $scope.result = angular.equals($scope.user1, $scope.user2);\n          };\n        }]);\n    </file>\n  </example>\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  // eslint-disable-next-line no-self-compare\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 === t2 && t1 === 'object') {\n    if (isArray(o1)) {\n      if (!isArray(o2)) return false;\n      if ((length = o1.length) === o2.length) {\n        for (key = 0; key < length; key++) {\n          if (!equals(o1[key], o2[key])) return false;\n        }\n        return true;\n      }\n    } else if (isDate(o1)) {\n      if (!isDate(o2)) return false;\n      return simpleCompare(o1.getTime(), o2.getTime());\n    } else if (isRegExp(o1)) {\n      if (!isRegExp(o2)) return false;\n      return o1.toString() === o2.toString();\n    } else {\n      if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||\n        isArray(o2) || isDate(o2) || isRegExp(o2)) return false;\n      keySet = createMap();\n      for (key in o1) {\n        if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n        if (!equals(o1[key], o2[key])) return false;\n        keySet[key] = true;\n      }\n      for (key in o2) {\n        if (!(key in keySet) &&\n            key.charAt(0) !== '$' &&\n            isDefined(o2[key]) &&\n            !isFunction(o2[key])) return false;\n      }\n      return true;\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (!isDefined(csp.rules)) {\n\n\n    var ngCspElement = (window.document.querySelector('[ng-csp]') ||\n                    window.document.querySelector('[data-ng-csp]'));\n\n    if (ngCspElement) {\n      var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||\n                    ngCspElement.getAttribute('data-ng-csp');\n      csp.rules = {\n        noUnsafeEval: !ngCspAttribute || (ngCspAttribute.indexOf('no-unsafe-eval') !== -1),\n        noInlineStyle: !ngCspAttribute || (ngCspAttribute.indexOf('no-inline-style') !== -1)\n      };\n    } else {\n      csp.rules = {\n        noUnsafeEval: noUnsafeEval(),\n        noInlineStyle: false\n      };\n    }\n  }\n\n  return csp.rules;\n\n  function noUnsafeEval() {\n    try {\n      // eslint-disable-next-line no-new, no-new-func\n      new Function('');\n      return false;\n    } catch (e) {\n      return true;\n    }\n  }\n};\n\n/**\n * @ngdoc directive\n * @module ng\n * @name ngJq\n *\n * @element ANY\n * @param {string=} ngJq the name of the library available under `window`\n * to be used for angular.element\n * @description\n * Use this directive to force the angular.element library.  This should be\n * used to force either jqLite by leaving ng-jq blank or setting the name of\n * the jquery variable under window (eg. jQuery).\n *\n * Since AngularJS looks for this directive when it is loaded (doesn't wait for the\n * DOMContentLoaded event), it must be placed on an element that comes before the script\n * which loads angular. Also, only the first instance of `ng-jq` will be used and all\n * others ignored.\n *\n * @example\n * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.\n ```html\n <!doctype html>\n <html ng-app ng-jq>\n ...\n ...\n </html>\n ```\n * @example\n * This example shows how to use a jQuery based library of a different name.\n * The library name must be available at the top most 'window'.\n ```html\n <!doctype html>\n <html ng-app ng-jq=\"jQueryLib\">\n ...\n ...\n </html>\n ```\n */\nvar jq = function() {\n  if (isDefined(jq.name_)) return jq.name_;\n  var el;\n  var i, ii = ngAttrPrefixes.length, prefix, name;\n  for (i = 0; i < ii; ++i) {\n    prefix = ngAttrPrefixes[i];\n    el = window.document.querySelector('[' + prefix.replace(':', '\\\\:') + 'jq]');\n    if (el) {\n      name = el.getAttribute(prefix + 'jq');\n      break;\n    }\n  }\n\n  return (jq.name_ = name);\n};\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, concat(curryArgs, arguments, 0))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // In IE, native methods are not functions so they cannot be bound (note: they don't need to be).\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  window.document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since AngularJS uses this notation internally.\n *\n * @param {Object|Array|Date|string|number|boolean} obj Input to be serialized into JSON.\n * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.\n *    If set to an integer, the JSON output will contain that many spaces per indentation.\n * @returns {string|undefined} JSON-ified string representing `obj`.\n * @knownIssue\n *\n * The Safari browser throws a `RangeError` instead of returning `null` when it tries to stringify a `Date`\n * object with an invalid date value. The only reliable way to prevent this is to monkeypatch the\n * `Date.prototype.toJSON` method as follows:\n *\n * ```\n * var _DatetoJSON = Date.prototype.toJSON;\n * Date.prototype.toJSON = function() {\n *   try {\n *     return _DatetoJSON.call(this);\n *   } catch(e) {\n *     if (e instanceof RangeError) {\n *       return null;\n *     }\n *     throw e;\n *   }\n * };\n * ```\n *\n * See https://github.com/angular/angular.js/pull/14221 for more information.\n */\nfunction toJson(obj, pretty) {\n  if (isUndefined(obj)) return undefined;\n  if (!isNumber(pretty)) {\n    pretty = pretty ? 2 : null;\n  }\n  return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nvar ALL_COLONS = /:/g;\nfunction timezoneToOffset(timezone, fallback) {\n  // Support: IE 9-11 only, Edge 13-15+\n  // IE/Edge do not \"understand\" colon (`:`) in timezone\n  timezone = timezone.replace(ALL_COLONS, '');\n  var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;\n  return isNumberNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;\n}\n\n\nfunction addDateMinutes(date, minutes) {\n  date = new Date(date.getTime());\n  date.setMinutes(date.getMinutes() + minutes);\n  return date;\n}\n\n\nfunction convertTimezoneToLocal(date, timezone, reverse) {\n  reverse = reverse ? -1 : 1;\n  var dateTimezoneOffset = date.getTimezoneOffset();\n  var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n  return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone().empty();\n  var elemHtml = jqLite('<div></div>').append(element).html();\n  try {\n    return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w-]+)/, function(match, nodeName) {return '<' + lowercase(nodeName);});\n  } catch (e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch (e) {\n    // Ignore any invalid uri component.\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {};\n  forEach((keyValue || '').split('&'), function(keyValue) {\n    var splitPoint, key, val;\n    if (keyValue) {\n      key = keyValue = keyValue.replace(/\\+/g,'%20');\n      splitPoint = keyValue.indexOf('=');\n      if (splitPoint !== -1) {\n        key = keyValue.substring(0, splitPoint);\n        val = keyValue.substring(splitPoint + 1);\n      }\n      key = tryDecodeURIComponent(key);\n      if (isDefined(key)) {\n        val = isDefined(val) ? tryDecodeURIComponent(val) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if (isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query         = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace(/%3B/gi, ';').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n  var attr, i, ii = ngAttrPrefixes.length;\n  for (i = 0; i < ii; ++i) {\n    attr = ngAttrPrefixes[i] + ngAttr;\n    if (isString(attr = element.getAttribute(attr))) {\n      return attr;\n    }\n  }\n  return null;\n}\n\nfunction allowAutoBootstrap(document) {\n  var script = document.currentScript;\n\n  if (!script) {\n    // Support: IE 9-11 only\n    // IE does not have `document.currentScript`\n    return true;\n  }\n\n  // If the `currentScript` property has been clobbered just return false, since this indicates a probable attack\n  if (!(script instanceof window.HTMLScriptElement || script instanceof window.SVGScriptElement)) {\n    return false;\n  }\n\n  var attributes = script.attributes;\n  var srcs = [attributes.getNamedItem('src'), attributes.getNamedItem('href'), attributes.getNamedItem('xlink:href')];\n\n  return srcs.every(function(src) {\n    if (!src) {\n      return true;\n    }\n    if (!src.value) {\n      return false;\n    }\n\n    var link = document.createElement('a');\n    link.href = src.value;\n\n    if (document.location.origin === link.origin) {\n      // Same-origin resources are always allowed, even for banned URL schemes.\n      return true;\n    }\n    // Disabled bootstrapping unless angular.js was loaded from a known scheme used on the web.\n    // This is to prevent angular.js bundled with browser extensions from being used to bypass the\n    // content security policy in web pages and other browser extensions.\n    switch (link.protocol) {\n      case 'http:':\n      case 'https:':\n      case 'ftp:':\n      case 'blob:':\n      case 'file:':\n      case 'data:':\n        return true;\n      default:\n        return false;\n    }\n  });\n}\n\n// Cached as it has to run during loading so that document.currentScript is available.\nvar isAutoBootstrapAllowed = allowAutoBootstrap(window.document);\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n *   created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n *   do not use explicit function annotation (and are thus unsuitable for minification), as described\n *   in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n *   tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * There are a few things to keep in mind when using `ngApp`:\n * - only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n *   found in the document will be used to define the root element to auto-bootstrap as an\n *   application. To run multiple applications in an HTML document you must manually bootstrap them using\n *   {@link angular.bootstrap} instead.\n * - AngularJS applications cannot be nested within each other.\n * - Do not use a directive that uses {@link ng.$compile#transclusion transclusion} on the same element as `ngApp`.\n *   This includes directives such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and\n *   {@link ngRoute.ngView `ngView`}.\n *   Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector},\n *   causing animations to stop working and making the injector inaccessible from outside the app.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * @example\n *\n * ### Simple Usage\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n <example module=\"ngAppDemo\" name=\"ng-app\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n * @example\n *\n * ### With `ngStrictDi`\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n <example ng-app-included=\"true\" name=\"strict-di\">\n   <file name=\"index.html\">\n   <div ng-app=\"ngAppStrictDemo\" ng-strict-di>\n       <div ng-controller=\"GoodController1\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style (see\n              script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"GoodController2\">\n           Name: <input ng-model=\"name\"><br />\n           Hello, {{name}}!\n\n           <p>This renders because the controller does not fail to\n              instantiate, by using explicit annotation style\n              (see script.js for details)\n           </p>\n       </div>\n\n       <div ng-controller=\"BadController\">\n           I can add: {{a}} + {{b}} =  {{ a+b }}\n\n           <p>The controller could not be instantiated, due to relying\n              on automatic function annotations (which are disabled in\n              strict mode). As such, the content of this section is not\n              interpolated, and there should be an error in your web console.\n           </p>\n       </div>\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppStrictDemo', [])\n     // BadController will fail to instantiate, due to relying on automatic function annotation,\n     // rather than an explicit annotation\n     .controller('BadController', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     })\n     // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n     // due to using explicit annotations using the array style and $inject property, respectively.\n     .controller('GoodController1', ['$scope', function($scope) {\n       $scope.a = 1;\n       $scope.b = 2;\n     }])\n     .controller('GoodController2', GoodController2);\n     function GoodController2($scope) {\n       $scope.name = 'World';\n     }\n     GoodController2.$inject = ['$scope'];\n   </file>\n   <file name=\"style.css\">\n   div[ng-controller] {\n       margin-bottom: 1em;\n       -webkit-border-radius: 4px;\n       border-radius: 4px;\n       border: 1px solid;\n       padding: .5em;\n   }\n   div[ng-controller^=Good] {\n       border-color: #d6e9c6;\n       background-color: #dff0d8;\n       color: #3c763d;\n   }\n   div[ng-controller^=Bad] {\n       border-color: #ebccd1;\n       background-color: #f2dede;\n       color: #a94442;\n       margin-bottom: 0;\n   }\n   </file>\n </example>\n */\nfunction angularInit(element, bootstrap) {\n  var appElement,\n      module,\n      config = {};\n\n  // The element `element` has priority over any other element.\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n\n    if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n      appElement = element;\n      module = element.getAttribute(name);\n    }\n  });\n  forEach(ngAttrPrefixes, function(prefix) {\n    var name = prefix + 'app';\n    var candidate;\n\n    if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n      appElement = candidate;\n      module = candidate.getAttribute(name);\n    }\n  });\n  if (appElement) {\n    if (!isAutoBootstrapAllowed) {\n      window.console.error('AngularJS: disabling automatic bootstrap. <script> protocol indicates ' +\n          'an extension, document.location.href does not match.');\n      return;\n    }\n    config.strictDi = getNgAttribute(appElement, 'strict-di') !== null;\n    bootstrap(appElement, module ? [module] : [], config);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up AngularJS application.\n *\n * For more information, see the {@link guide/bootstrap Bootstrap guide}.\n *\n * AngularJS will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of AngularJS try to work on the DOM.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n * </div>\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Do not bootstrap the app on an element with a directive that uses {@link ng.$compile#transclusion transclusion},\n * such as {@link ng.ngIf `ngIf`}, {@link ng.ngInclude `ngInclude`} and {@link ngRoute.ngView `ngView`}.\n * Doing this misplaces the app {@link ng.$rootElement `$rootElement`} and the app's {@link auto.$injector injector},\n * causing animations to stop working and making the injector inaccessible from outside the app.\n * </div>\n *\n * ```html\n * <!doctype html>\n * <html>\n * <body>\n * <div ng-controller=\"WelcomeController\">\n *   {{greeting}}\n * </div>\n *\n * <script src=\"angular.js\"></script>\n * <script>\n *   var app = angular.module('demo', [])\n *   .controller('WelcomeController', function($scope) {\n *       $scope.greeting = 'Welcome!';\n *   });\n *   angular.bootstrap(document, ['demo']);\n * </script>\n * </body>\n * </html>\n * ```\n *\n * @param {DOMElement} element DOM element which is the root of AngularJS application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n *     following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n *   assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n  if (!isObject(config)) config = {};\n  var defaultConfig = {\n    strictDi: false\n  };\n  config = extend(defaultConfig, config);\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === window.document) ? 'document' : startingTag(element);\n      // Encode angle brackets to prevent input from being sanitized to empty string #8683.\n      throw ngMinErr(\n          'btstrpd',\n          'App already bootstrapped with this element \\'{0}\\'',\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n\n    if (config.debugInfoEnabled) {\n      // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n      modules.push(['$compileProvider', function($compileProvider) {\n        $compileProvider.debugInfoEnabled(true);\n      }]);\n    }\n\n    modules.unshift('ng');\n    var injector = createInjector(modules, config.strictDi);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n       function bootstrapApply(scope, element, compile, injector) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n    config.debugInfoEnabled = true;\n    window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n  }\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    return doBootstrap();\n  };\n\n  if (isFunction(angular.resumeDeferredBootstrap)) {\n    angular.resumeDeferredBootstrap();\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n  window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of AngularJS on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of AngularJS application.\n */\nfunction getTestability(rootElement) {\n  var injector = angular.element(rootElement).injector();\n  if (!injector) {\n    throw ngMinErr('test',\n      'no injector found for element argument to getTestability');\n  }\n  return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nvar bindJQueryFired = false;\nfunction bindJQuery() {\n  var originalCleanData;\n\n  if (bindJQueryFired) {\n    return;\n  }\n\n  // bind to jQuery if present;\n  var jqName = jq();\n  jQuery = isUndefined(jqName) ? window.jQuery :   // use jQuery (if present)\n           !jqName             ? undefined     :   // use jqLite\n                                 window[jqName];   // use jQuery specified by `ngJq`\n\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // AngularJS 1.2+ requires jQuery 1.7+ for on()/off() support.\n  // AngularJS 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n  // versions. It will not work for sure with jQuery <1.7, though.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: /** @type {?} */ (JQLitePrototype).controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n  } else {\n    jqLite = JQLite;\n  }\n\n  // All nodes removed from the DOM via various jqLite/jQuery APIs like .remove()\n  // are passed through jqLite/jQuery.cleanData. Monkey-patch this method to fire\n  // the $destroy event on all removed nodes.\n  originalCleanData = jqLite.cleanData;\n  jqLite.cleanData = function(elems) {\n    var events;\n    for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n      events = (jqLite._data(elem) || {}).events;\n      if (events && events.$destroy) {\n        jqLite(elem).triggerHandler('$destroy');\n      }\n    }\n    originalCleanData(elems);\n  };\n\n  angular.element = jqLite;\n\n  // Prevent double-proxying.\n  bindJQueryFired = true;\n}\n\n/**\n * @ngdoc function\n * @name angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement\n * @module ng\n * @kind function\n *\n * @description\n * Restores the pre-1.8 behavior of jqLite that turns XHTML-like strings like\n * `<div /><span />` to `<div></div><span></span>` instead of `<div><span></span></div>`.\n * The new behavior is a security fix. Thus, if you need to call this function, please try to adjust\n * your code for this change and remove your use of this function as soon as possible.\n\n * Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read the\n * [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details\n * about the workarounds.\n */\nfunction UNSAFE_restoreLegacyJqLiteXHTMLReplacement() {\n  JQLite.legacyXHTMLReplacement = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', 'Argument \\'{0}\\' is {1}', (name || '?'), (reason || 'required'));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {Array} the inputted object or a jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n  // TODO(perf): update `nodes` instead of creating a new object?\n  var node = nodes[0];\n  var endNode = nodes[nodes.length - 1];\n  var blockNodes;\n\n  for (var i = 1; node !== endNode && (node = node.nextSibling); i++) {\n    if (blockNodes || nodes[i] !== node) {\n      if (!blockNodes) {\n        blockNodes = jqLite(slice.call(nodes, 0, i));\n      }\n      blockNodes.push(node);\n    }\n  }\n\n  return blockNodes || nodes;\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n  return Object.create(null);\n}\n\nfunction stringify(value) {\n  if (value == null) { // null || undefined\n    return '';\n  }\n  switch (typeof value) {\n    case 'string':\n      break;\n    case 'number':\n      value = '' + value;\n      break;\n    default:\n      if (hasCustomToString(value) && !isArray(value) && !isDate(value)) {\n        value = value.toString();\n      } else {\n        value = toJson(value);\n      }\n  }\n\n  return value;\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_ATTRIBUTE = 2;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring AngularJS {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving AngularJS\n     * modules.\n     * All modules (AngularJS core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * Passing one argument retrieves an existing {@link angular.Module},\n     * whereas passing more than one argument creates a new {@link angular.Module}\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {angular.Module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n\n      var info = {};\n\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', 'Module \\'{0}\\' is not available! You either misspelled ' +\n             'the module name or forgot to load it. If registering a module ensure that you ' +\n             'specify the dependencies as the second argument.', name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var configBlocks = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _configBlocks: configBlocks,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#info\n           * @module ng\n           *\n           * @param {Object=} info Information about the module\n           * @returns {Object|Module} The current info object for this module if called as a getter,\n           *                          or `this` if called as a setter.\n           *\n           * @description\n           * Read and write custom information about this module.\n           * For example you could put the version of the module in here.\n           *\n           * ```js\n           * angular.module('myModule', []).info({ version: '1.0.0' });\n           * ```\n           *\n           * The version could then be read back out by accessing the module elsewhere:\n           *\n           * ```\n           * var version = angular.module('myModule').info().version;\n           * ```\n           *\n           * You can also retrieve this information during runtime via the\n           * {@link $injector#modules `$injector.modules`} property:\n           *\n           * ```js\n           * var version = $injector.modules['myModule'].info().version;\n           * ```\n           */\n          info: function(value) {\n            if (isDefined(value)) {\n              if (!isObject(value)) throw ngMinErr('aobj', 'Argument \\'{0}\\' must be an object', 'value');\n              info = value;\n              return this;\n            }\n            return info;\n          },\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLaterAndSetModuleName('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLaterAndSetModuleName('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLaterAndSetModuleName('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constants are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n           /**\n           * @ngdoc method\n           * @name angular.Module#decorator\n           * @module ng\n           * @param {string} name The name of the service to decorate.\n           * @param {Function} decorFn This function will be invoked when the service needs to be\n           *                           instantiated and should return the decorated service instance.\n           * @description\n           * See {@link auto.$provide#decorator $provide.decorator()}.\n           */\n          decorator: invokeLaterAndSetModuleName('$provide', 'decorator', configBlocks),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link $animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ng.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name - this must be a valid AngularJS expression identifier\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           *\n           * <div class=\"alert alert-warning\">\n           * **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`.\n           * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace\n           * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores\n           * (`myapp_subsection_filterx`).\n           * </div>\n           */\n          filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#component\n           * @module ng\n           * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),\n           *    or an object map of components where the keys are the names and the values are the component definition objects.\n           * @param {Object} options Component definition object (a simplified\n           *    {@link ng.$compile#directive-definition-object directive definition object})\n           *\n           * @description\n           * See {@link ng.$compileProvider#component $compileProvider.component()}.\n           */\n          component: invokeLaterAndSetModuleName('$compileProvider', 'component'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to configure services by injecting their\n           * {@link angular.Module#provider `providers`}, e.g. for adding routes to the\n           * {@link ngRoute.$routeProvider $routeProvider}.\n           *\n           * Note that you can only inject {@link angular.Module#provider `providers`} and\n           * {@link angular.Module#constant `constants`} into this function.\n           *\n           * For more about how to configure services, see\n           * {@link providers#provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod, queue) {\n          if (!queue) queue = invokeQueue;\n          return function() {\n            queue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @returns {angular.Module}\n         */\n        function invokeLaterAndSetModuleName(provider, method, queue) {\n          if (!queue) queue = invokeQueue;\n          return function(recipeName, factoryFunction) {\n            if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;\n            queue.push([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global shallowCopy: true */\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n/* exported toDebugString */\n\nfunction serializeObject(obj, maxDepth) {\n  var seen = [];\n\n  // There is no direct way to stringify object until reaching a specific depth\n  // and a very deep object can cause a performance issue, so we copy the object\n  // based on this specific depth and then stringify it.\n  if (isValidObjectMaxDepth(maxDepth)) {\n    // This file is also included in `angular-loader`, so `copy()` might not always be available in\n    // the closure. Therefore, it is lazily retrieved as `angular.copy()` when needed.\n    obj = angular.copy(obj, null, maxDepth);\n  }\n  return JSON.stringify(obj, function(key, val) {\n    val = toJsonReplacer(key, val);\n    if (isObject(val)) {\n\n      if (seen.indexOf(val) >= 0) return '...';\n\n      seen.push(val);\n    }\n    return val;\n  });\n}\n\nfunction toDebugString(obj, maxDepth) {\n  if (typeof obj === 'function') {\n    return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n  } else if (isUndefined(obj)) {\n    return 'undefined';\n  } else if (typeof obj !== 'string') {\n    return serializeObject(obj, maxDepth);\n  }\n  return obj;\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $CompileProvider,\n\n  htmlAnchorDirective,\n  inputDirective,\n  hiddenInputBrowserCacheDirective,\n  formDirective,\n  scriptDirective,\n  selectDirective,\n  optionDirective,\n  ngBindDirective,\n  ngBindHtmlDirective,\n  ngBindTemplateDirective,\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective,\n  ngCloakDirective,\n  ngControllerDirective,\n  ngFormDirective,\n  ngHideDirective,\n  ngIfDirective,\n  ngIncludeDirective,\n  ngIncludeFillContentDirective,\n  ngInitDirective,\n  ngNonBindableDirective,\n  ngPluralizeDirective,\n  ngRefDirective,\n  ngRepeatDirective,\n  ngShowDirective,\n  ngStyleDirective,\n  ngSwitchDirective,\n  ngSwitchWhenDirective,\n  ngSwitchDefaultDirective,\n  ngOptionsDirective,\n  ngTranscludeDirective,\n  ngModelDirective,\n  ngListDirective,\n  ngChangeDirective,\n  patternDirective,\n  patternDirective,\n  requiredDirective,\n  requiredDirective,\n  minlengthDirective,\n  minlengthDirective,\n  maxlengthDirective,\n  maxlengthDirective,\n  ngValueDirective,\n  ngModelOptionsDirective,\n  ngAttributeAliasDirectives,\n  ngEventDirectives,\n\n  $AnchorScrollProvider,\n  $AnimateProvider,\n  $CoreAnimateCssProvider,\n  $$CoreAnimateJsProvider,\n  $$CoreAnimateQueueProvider,\n  $$AnimateRunnerFactoryProvider,\n  $$AnimateAsyncRunFactoryProvider,\n  $BrowserProvider,\n  $CacheFactoryProvider,\n  $ControllerProvider,\n  $DateProvider,\n  $DocumentProvider,\n  $$IsDocumentHiddenProvider,\n  $ExceptionHandlerProvider,\n  $FilterProvider,\n  $$ForceReflowProvider,\n  $InterpolateProvider,\n  $$IntervalFactoryProvider,\n  $IntervalProvider,\n  $HttpProvider,\n  $HttpParamSerializerProvider,\n  $HttpParamSerializerJQLikeProvider,\n  $HttpBackendProvider,\n  $xhrFactoryProvider,\n  $jsonpCallbacksProvider,\n  $LocationProvider,\n  $LogProvider,\n  $$MapProvider,\n  $ParseProvider,\n  $RootScopeProvider,\n  $QProvider,\n  $$QProvider,\n  $$SanitizeUriProvider,\n  $SceProvider,\n  $SceDelegateProvider,\n  $SnifferProvider,\n  $$TaskTrackerFactoryProvider,\n  $TemplateCacheProvider,\n  $TemplateRequestProvider,\n  $$TestabilityProvider,\n  $TimeoutProvider,\n  $$RAFProvider,\n  $WindowProvider,\n  $$jqLiteProvider,\n  $$CookieReaderProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version.\n *\n * This object has the following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  // These placeholder strings will be replaced by grunt's `build` task.\n  // They need to be double- or single-quoted.\n  full: '1.8.3',\n  major: 1,\n  minor: 8,\n  dot: 3,\n  codeName: 'ultimate-farewell'\n};\n\n\nfunction publishExternalAPI(angular) {\n  extend(angular, {\n    'errorHandlingConfig': errorHandlingConfig,\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'merge': merge,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'callbacks': {$$counter: 0},\n    'getTestability': getTestability,\n    'reloadWithDebugInfo': reloadWithDebugInfo,\n    'UNSAFE_restoreLegacyJqLiteXHTMLReplacement': UNSAFE_restoreLegacyJqLiteXHTMLReplacement,\n    '$$minErr': minErr,\n    '$$csp': csp,\n    '$$encodeUriSegment': encodeUriSegment,\n    '$$encodeUriQuery': encodeUriQuery,\n    '$$lowercase': lowercase,\n    '$$stringify': stringify,\n    '$$uppercase': uppercase\n  });\n\n  angularModule = setupModuleLoader(window);\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRef: ngRefDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            pattern: patternDirective,\n            ngPattern: patternDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            minlength: minlengthDirective,\n            ngMinlength: minlengthDirective,\n            maxlength: maxlengthDirective,\n            ngMaxlength: maxlengthDirective,\n            ngValue: ngValueDirective,\n            ngModelOptions: ngModelOptionsDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective,\n          input: hiddenInputBrowserCacheDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $animateCss: $CoreAnimateCssProvider,\n        $$animateJs: $$CoreAnimateJsProvider,\n        $$animateQueue: $$CoreAnimateQueueProvider,\n        $$AnimateRunner: $$AnimateRunnerFactoryProvider,\n        $$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $$isDocumentHidden: $$IsDocumentHiddenProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $$forceReflow: $$ForceReflowProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $$intervalFactory: $$IntervalFactoryProvider,\n        $http: $HttpProvider,\n        $httpParamSerializer: $HttpParamSerializerProvider,\n        $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,\n        $httpBackend: $HttpBackendProvider,\n        $xhrFactory: $xhrFactoryProvider,\n        $jsonpCallbacks: $jsonpCallbacksProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $$q: $$QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $$taskTrackerFactory: $$TaskTrackerFactoryProvider,\n        $templateCache: $TemplateCacheProvider,\n        $templateRequest: $TemplateRequestProvider,\n        $$testability: $$TestabilityProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$jqLite: $$jqLiteProvider,\n        $$Map: $$MapProvider,\n        $$cookieReader: $$CookieReaderProvider\n      });\n    }\n  ])\n  .info({ angularVersion: '1.8.3' });\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n *     Any commits to this file should be reviewed with security in mind.  *\n *   Changes to this file can potentially create security vulnerabilities. *\n *          An approval from 2 Core members with history of modifying      *\n *                         this file is required.                          *\n *                                                                         *\n *  Does the change somehow allow for arbitrary javascript to be executed? *\n *    Or allows for someone to change the prototype of built-in objects?   *\n *     Or gives undesired access to variables likes document or window?    *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/* global\n  JQLitePrototype: true,\n  BOOLEAN_ATTR: true,\n  ALIASED_ATTR: true\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to AngularJS's built-in subset of jQuery, called \"jQuery lite\" or **jqLite**.\n *\n * jqLite is a tiny, API-compatible subset of jQuery that allows\n * AngularJS to manipulate the DOM in a cross-browser compatible way. jqLite implements only the most\n * commonly needed functionality with the goal of having a very small footprint.\n *\n * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. You can also use the\n * {@link ngJq `ngJq`} directive to specify that jqlite should be used over jQuery, or to use a\n * specific version of jQuery if multiple versions exist on the page.\n *\n * <div class=\"alert alert-info\">**Note:** All element references in AngularJS are always wrapped with jQuery or\n * jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.</div>\n *\n * <div class=\"alert alert-warning\">**Note:** Keep in mind that this function will not find elements\n * by tag name / CSS selector. For lookups by tag name, try instead `angular.element(document).find(...)`\n * or `$document.find()`, or use the standard DOM APIs, e.g. `document.querySelectorAll()`.</div>\n *\n * ## AngularJS's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/) - Does not support a function as first argument\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/) - Contrary to jQuery, this doesn't clone elements\n *   so will not work correctly when invoked on a jqLite object containing more than one DOM node\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) (_deprecated_, use [`on()`](http://api.jquery.com/on/)) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`.\n *   As a setter, does not convert numbers to strings or append 'px', and also does not have automatic property prefixing.\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces, selectors or event object as parameter\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/) (_deprecated_, use `angular.element(callback)` instead of `angular.element(document).ready(callback)`)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/) - Does not support multiple attributes\n * - [`removeClass()`](http://api.jquery.com/removeClass/) - Does not support a function as first argument\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - Does not support a function as first argument\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers\n * - [`unbind()`](http://api.jquery.com/unbind/) (_deprecated_, use [`off()`](http://api.jquery.com/off/)) - Does not support namespaces or event object as parameter\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * jqLite also provides a method restoring pre-1.8 insecure treatment of XHTML-like tags.\n * This legacy behavior turns input like `<div /><span />` to `<div></div><span></span>`\n * instead of `<div><span></span></div>` like version 1.8 & newer do. To restore it, invoke:\n * ```js\n * angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement();\n * ```\n * Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read the\n * [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details\n * about the workarounds.\n *\n * ## jQuery/jqLite Extras\n * AngularJS also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n *   be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @knownIssue You cannot spy on `angular.element` if you are using Jasmine version 1.x. See\n * https://github.com/angular/angular.js/issues/14251 for more information.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1;\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar DASH_LOWERCASE_REGEXP = /-([a-z])/g;\nvar MS_HACK_REGEXP = /^-ms-/;\nvar MOUSE_EVENT_MAP = { mouseleave: 'mouseout', mouseenter: 'mouseover' };\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts kebab-case to camelCase.\n * There is also a special case for the ms prefix starting with a lowercase letter.\n * @param name Name to normalize\n */\nfunction cssKebabToCamel(name) {\n    return kebabToCamel(name.replace(MS_HACK_REGEXP, 'ms-'));\n}\n\nfunction fnCamelCaseReplace(all, letter) {\n  return letter.toUpperCase();\n}\n\n/**\n * Converts kebab-case to camelCase.\n * @param name Name to normalize\n */\nfunction kebabToCamel(name) {\n  return name\n    .replace(DASH_LOWERCASE_REGEXP, fnCamelCaseReplace);\n}\n\nvar SINGLE_TAG_REGEXP = /^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:-]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi;\n\n// Table parts need to be wrapped with `<table>` or they're\n// stripped to their contents when put in a div.\n// XHTML parsers do not magically insert elements in the\n// same way that tag soup parsers do, so we cannot shorten\n// this by omitting <tbody> or other required elements.\nvar wrapMap = {\n  thead: ['table'],\n  col: ['colgroup', 'table'],\n  tr: ['tbody', 'table'],\n  td: ['tr', 'tbody', 'table']\n};\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: IE <10 only\n// IE 9 requires an option wrapper & it needs to have the whole table structure\n// set up in advance; assigning `\"<td></td>\"` to `tr.innerHTML` doesn't work, etc.\nvar wrapMapIE9 = {\n  option: [1, '<select multiple=\"multiple\">', '</select>'],\n  _default: [0, '', '']\n};\n\nfor (var key in wrapMap) {\n  var wrapMapValueClosing = wrapMap[key];\n  var wrapMapValue = wrapMapValueClosing.slice().reverse();\n  wrapMapIE9[key] = [wrapMapValue.length, '<' + wrapMapValue.join('><') + '>', '</' + wrapMapValueClosing.join('></') + '>'];\n}\n\nwrapMapIE9.optgroup = wrapMapIE9.option;\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n  // The window object can accept data but has no nodeType\n  // Otherwise we are only interested in elements (1) and documents (9)\n  var nodeType = node.nodeType;\n  return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteHasData(node) {\n  for (var key in jqCache[node.ng339]) {\n    return true;\n  }\n  return false;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var tmp, tag, wrap, finalHtml,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    // Convert html into DOM nodes\n    tmp = fragment.appendChild(context.createElement('div'));\n    tag = (TAG_NAME_REGEXP.exec(html) || ['', ''])[1].toLowerCase();\n    finalHtml = JQLite.legacyXHTMLReplacement ?\n      html.replace(XHTML_TAG_REGEXP, '<$1></$2>') :\n      html;\n\n    if (msie < 10) {\n      wrap = wrapMapIE9[tag] || wrapMapIE9._default;\n      tmp.innerHTML = wrap[1] + finalHtml + wrap[2];\n\n      // Descend through wrappers to the right content\n      i = wrap[0];\n      while (i--) {\n        tmp = tmp.firstChild;\n      }\n    } else {\n      wrap = wrapMap[tag] || [];\n\n      // Create wrappers & descend into them\n      i = wrap.length;\n      while (--i > -1) {\n        tmp.appendChild(window.document.createElement(wrap[i]));\n        tmp = tmp.firstChild;\n      }\n\n      tmp.innerHTML = finalHtml;\n    }\n\n    nodes = concat(nodes, tmp.childNodes);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = '';\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = '';\n  fragment.innerHTML = ''; // Clear inner HTML\n  forEach(nodes, function(node) {\n    fragment.appendChild(node);\n  });\n\n  return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || window.document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  if ((parsed = jqLiteBuildFragment(html, context))) {\n    return parsed.childNodes;\n  }\n\n  return [];\n}\n\nfunction jqLiteWrapNode(node, wrapper) {\n  var parent = node.parentNode;\n\n  if (parent) {\n    parent.replaceChild(wrapper, node);\n  }\n\n  wrapper.appendChild(node);\n}\n\n\n// IE9-11 has no method \"contains\" in SVG element and in Node.prototype. Bug #10259.\nvar jqLiteContains = window.Node.prototype.contains || /** @this */ function(arg) {\n  // eslint-disable-next-line no-bitwise\n  return !!(this.compareDocumentPosition(arg) & 16);\n};\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n\n  var argIsString;\n\n  if (isString(element)) {\n    element = trim(element);\n    argIsString = true;\n  }\n  if (!(this instanceof JQLite)) {\n    if (argIsString && element.charAt(0) !== '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (argIsString) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n  } else if (isFunction(element)) {\n    jqLiteReady(element);\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n  if (!onlyDescendants && jqLiteAcceptsData(element)) jqLite.cleanData([element]);\n\n  if (element.querySelectorAll) {\n    jqLite.cleanData(element.querySelectorAll('*'));\n  }\n}\n\nfunction isEmptyObject(obj) {\n  var name;\n\n  for (name in obj) {\n    return false;\n  }\n  return true;\n}\n\nfunction removeIfEmptyData(element) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  var events = expandoStore && expandoStore.events;\n  var data = expandoStore && expandoStore.data;\n\n  if ((!data || isEmptyObject(data)) && (!events || isEmptyObject(events))) {\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var expandoStore = jqLiteExpandoStore(element);\n  var events = expandoStore && expandoStore.events;\n  var handle = expandoStore && expandoStore.handle;\n\n  if (!handle) return; //no listeners registered\n\n  if (!type) {\n    for (type in events) {\n      if (type !== '$destroy') {\n        element.removeEventListener(type, handle);\n      }\n      delete events[type];\n    }\n  } else {\n\n    var removeHandler = function(type) {\n      var listenerFns = events[type];\n      if (isDefined(fn)) {\n        arrayRemove(listenerFns || [], fn);\n      }\n      if (!(isDefined(fn) && listenerFns && listenerFns.length > 0)) {\n        element.removeEventListener(type, handle);\n        delete events[type];\n      }\n    };\n\n    forEach(type.split(' '), function(type) {\n      removeHandler(type);\n      if (MOUSE_EVENT_MAP[type]) {\n        removeHandler(MOUSE_EVENT_MAP[type]);\n      }\n    });\n  }\n\n  removeIfEmptyData(element);\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339;\n  var expandoStore = expandoId && jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete expandoStore.data[name];\n    } else {\n      expandoStore.data = {};\n    }\n\n    removeIfEmptyData(element);\n  }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n  var expandoId = element.ng339,\n      expandoStore = expandoId && jqCache[expandoId];\n\n  if (createIfNecessary && !expandoStore) {\n    element.ng339 = expandoId = jqNextId();\n    expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n  }\n\n  return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n  if (jqLiteAcceptsData(element)) {\n    var prop;\n\n    var isSimpleSetter = isDefined(value);\n    var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n    var massGetter = !key;\n    var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n    var data = expandoStore && expandoStore.data;\n\n    if (isSimpleSetter) { // data('key', value)\n      data[kebabToCamel(key)] = value;\n    } else {\n      if (massGetter) {  // data()\n        return data;\n      } else {\n        if (isSimpleGetter) { // data('key')\n          // don't force creation of expandoStore if it doesn't exist yet\n          return data && data[kebabToCamel(key)];\n        } else { // mass-setter: data({key1: val1, key2: val2})\n          for (prop in key) {\n            data[kebabToCamel(prop)] = key[prop];\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((' ' + (element.getAttribute('class') || '') + ' ').replace(/[\\n\\t]/g, ' ').\n      indexOf(' ' + selector + ' ') > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, ' ');\n    var newClasses = existingClasses;\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      newClasses = newClasses.replace(' ' + cssClass + ' ', ' ');\n    });\n\n    if (newClasses !== existingClasses) {\n      element.setAttribute('class', trim(newClasses));\n    }\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, ' ');\n    var newClasses = existingClasses;\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (newClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        newClasses += cssClass + ' ';\n      }\n    });\n\n    if (newClasses !== existingClasses) {\n      element.setAttribute('class', trim(newClasses));\n    }\n  }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n  // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n  if (elements) {\n\n    // if a Node (the most common case)\n    if (elements.nodeType) {\n      root[root.length++] = elements;\n    } else {\n      var length = elements.length;\n\n      // if an Array or NodeList and not a Window\n      if (typeof length === 'number' && elements.window !== elements) {\n        if (length) {\n          for (var i = 0; i < length; i++) {\n            root[root.length++] = elements[i];\n          }\n        }\n      } else {\n        root[root.length++] = elements;\n      }\n    }\n  }\n}\n\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if (element.nodeType === NODE_TYPE_DOCUMENT) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if (isDefined(value = jqLite.data(element, names[i]))) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  jqLiteDealoc(element, true);\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\nfunction jqLiteRemove(element, keepData) {\n  if (!keepData) jqLiteDealoc(element);\n  var parent = element.parentNode;\n  if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n  win = win || window;\n  if (win.document.readyState === 'complete') {\n    // Force the action to be run async for consistent behavior\n    // from the action's point of view\n    // i.e. it will definitely not be in a $apply\n    win.setTimeout(action);\n  } else {\n    // No need to unbind this handler as load is only ever called once\n    jqLite(win).on('load', action);\n  }\n}\n\nfunction jqLiteReady(fn) {\n  function trigger() {\n    window.document.removeEventListener('DOMContentLoaded', trigger);\n    window.removeEventListener('load', trigger);\n    fn();\n  }\n\n  // check if document is already loaded\n  if (window.document.readyState === 'complete') {\n    window.setTimeout(fn);\n  } else {\n    // We can not use jqLite since we are not done loading and jQuery could be loaded later.\n\n    // Works for modern browsers and IE9\n    window.document.addEventListener('DOMContentLoaded', trigger);\n\n    // Fallback to window.onload for others\n    window.addEventListener('load', trigger);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: jqLiteReady,\n  toString: function() {\n    var value = [];\n    forEach(this, function(e) { value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n  'ngMinlength': 'minlength',\n  'ngMaxlength': 'maxlength',\n  'ngMin': 'min',\n  'ngMax': 'max',\n  'ngPattern': 'pattern',\n  'ngStep': 'step'\n};\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(name) {\n  return ALIASED_ATTR[name];\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData,\n  hasData: jqLiteHasData,\n  cleanData: function jqLiteCleanData(nodes) {\n    for (var i = 0, ii = nodes.length; i < ii; i++) {\n      jqLiteRemoveData(nodes[i]);\n      jqLiteOff(nodes[i]);\n    }\n  }\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element, name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = cssKebabToCamel(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      return element.style[name];\n    }\n  },\n\n  attr: function(element, name, value) {\n    var ret;\n    var nodeType = element.nodeType;\n    if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT ||\n      !element.getAttribute) {\n      return;\n    }\n\n    var lowercasedName = lowercase(name);\n    var isBooleanAttr = BOOLEAN_ATTR[lowercasedName];\n\n    if (isDefined(value)) {\n      // setter\n\n      if (value === null || (value === false && isBooleanAttr)) {\n        element.removeAttribute(name);\n      } else {\n        element.setAttribute(name, isBooleanAttr ? lowercasedName : value);\n      }\n    } else {\n      // getter\n\n      ret = element.getAttribute(name);\n\n      if (isBooleanAttr && ret !== null) {\n        ret = lowercasedName;\n      }\n      // Normalize non-existing attributes to undefined (as jQuery).\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      if (isUndefined(value)) {\n        var nodeType = element.nodeType;\n        return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n      }\n      element.textContent = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (element.multiple && nodeName_(element) === 'select') {\n        var result = [];\n        forEach(element.options, function(option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    jqLiteDealoc(element, true);\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name) {\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (isUndefined((fn.length === 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2))) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (isUndefined(value)) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function(event, type) {\n    // jQuery specific api\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented;\n    };\n\n    var eventFns = events[type || event.type];\n    var eventFnsLength = eventFns ? eventFns.length : 0;\n\n    if (!eventFnsLength) return;\n\n    if (isUndefined(event.immediatePropagationStopped)) {\n      var originalStopImmediatePropagation = event.stopImmediatePropagation;\n      event.stopImmediatePropagation = function() {\n        event.immediatePropagationStopped = true;\n\n        if (event.stopPropagation) {\n          event.stopPropagation();\n        }\n\n        if (originalStopImmediatePropagation) {\n          originalStopImmediatePropagation.call(event);\n        }\n      };\n    }\n\n    event.isImmediatePropagationStopped = function() {\n      return event.immediatePropagationStopped === true;\n    };\n\n    // Some events have special handlers that wrap the real handler\n    var handlerWrapper = eventFns.specialHandlerWrapper || defaultHandlerWrapper;\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    if ((eventFnsLength > 1)) {\n      eventFns = shallowCopy(eventFns);\n    }\n\n    for (var i = 0; i < eventFnsLength; i++) {\n      if (!event.isImmediatePropagationStopped()) {\n        handlerWrapper(element, event, eventFns[i]);\n      }\n    }\n  };\n\n  // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n  //       events on `element`\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\nfunction defaultHandlerWrapper(element, event, handler) {\n  handler.call(element, event);\n}\n\nfunction specialMouseHandlerWrapper(target, event, handler) {\n  // Refer to jQuery's implementation of mouseenter & mouseleave\n  // Read about mouseenter and mouseleave:\n  // http://www.quirksmode.org/js/events_mouse.html#link8\n  var related = event.relatedTarget;\n  // For mousenter/leave call the handler if related is outside the target.\n  // NB: No relatedTarget if the mouse left/entered the browser window\n  if (!related || (related !== target && !jqLiteContains.call(target, related))) {\n    handler.call(target, event);\n  }\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  on: function jqLiteOn(element, type, fn, unsupported) {\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    // Do not add event handlers to non-elements because they will not be cleaned up.\n    if (!jqLiteAcceptsData(element)) {\n      return;\n    }\n\n    var expandoStore = jqLiteExpandoStore(element, true);\n    var events = expandoStore.events;\n    var handle = expandoStore.handle;\n\n    if (!handle) {\n      handle = expandoStore.handle = createEventHandler(element, events);\n    }\n\n    // http://jsperf.com/string-indexof-vs-split\n    var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n    var i = types.length;\n\n    var addHandler = function(type, specialHandlerWrapper, noEventListener) {\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        eventFns = events[type] = [];\n        eventFns.specialHandlerWrapper = specialHandlerWrapper;\n        if (type !== '$destroy' && !noEventListener) {\n          element.addEventListener(type, handle);\n        }\n      }\n\n      eventFns.push(fn);\n    };\n\n    while (i--) {\n      type = types[i];\n      if (MOUSE_EVENT_MAP[type]) {\n        addHandler(MOUSE_EVENT_MAP[type], specialMouseHandlerWrapper);\n        addHandler(type, undefined, true);\n      } else {\n        addHandler(type);\n      }\n    }\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node) {\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element) {\n      if (element.nodeType === NODE_TYPE_ELEMENT) {\n        children.push(element);\n      }\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    var nodeType = element.nodeType;\n    if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n    node = new JQLite(node);\n\n    for (var i = 0, ii = node.length; i < ii; i++) {\n      var child = node[i];\n      element.appendChild(child);\n    }\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === NODE_TYPE_ELEMENT) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child) {\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    jqLiteWrapNode(element, jqLite(wrapNode).eq(0).clone()[0]);\n  },\n\n  remove: jqLiteRemove,\n\n  detach: function(element) {\n    jqLiteRemove(element, true);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n\n    if (parent) {\n      newElement = new JQLite(newElement);\n\n      for (var i = 0, ii = newElement.length; i < ii; i++) {\n        var node = newElement[i];\n        parent.insertBefore(node, index.nextSibling);\n        index = node;\n      }\n    }\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className) {\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n  },\n\n  next: function(element) {\n    return element.nextElementSibling;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var expandoStore = jqLiteExpandoStore(element);\n    var events = expandoStore && expandoStore.events;\n    var eventFns = events && events[eventName];\n\n    if (eventFns) {\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n        isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        if (!dummyEvent.isImmediatePropagationStopped()) {\n          fn.apply(element, handlerArgs);\n        }\n      });\n    }\n  }\n}, function(fn, name) {\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n\n    for (var i = 0, ii = this.length; i < ii; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n});\n\n// bind legacy bind/unbind to on/off\nJQLite.prototype.bind = JQLite.prototype.on;\nJQLite.prototype.unbind = JQLite.prototype.off;\n\n\n// Provider for private $$jqLite service\n/** @this */\nfunction $$jqLiteProvider() {\n  this.$get = function $$jqLite() {\n    return extend(JQLite, {\n      hasClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteHasClass(node, classes);\n      },\n      addClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteAddClass(node, classes);\n      },\n      removeClass: function(node, classes) {\n        if (node.attr) node = node[0];\n        return jqLiteRemoveClass(node, classes);\n      }\n    });\n  };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var key = obj && obj.$$hashKey;\n\n  if (key) {\n    if (typeof key === 'function') {\n      key = obj.$$hashKey();\n    }\n    return key;\n  }\n\n  var objType = typeof obj;\n  if (objType === 'function' || (objType === 'object' && obj !== null)) {\n    key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n  } else {\n    key = objType + ':' + obj;\n  }\n\n  return key;\n}\n\n// A minimal ES2015 Map implementation.\n// Should be bug/feature equivalent to the native implementations of supported browsers\n// (for the features required in Angular).\n// See https://kangax.github.io/compat-table/es6/#test-Map\nvar nanKey = Object.create(null);\nfunction NgMapShim() {\n  this._keys = [];\n  this._values = [];\n  this._lastKey = NaN;\n  this._lastIndex = -1;\n}\nNgMapShim.prototype = {\n  _idx: function(key) {\n    if (key !== this._lastKey) {\n      this._lastKey = key;\n      this._lastIndex = this._keys.indexOf(key);\n    }\n    return this._lastIndex;\n  },\n  _transformKey: function(key) {\n    return isNumberNaN(key) ? nanKey : key;\n  },\n  get: function(key) {\n    key = this._transformKey(key);\n    var idx = this._idx(key);\n    if (idx !== -1) {\n      return this._values[idx];\n    }\n  },\n  has: function(key) {\n    key = this._transformKey(key);\n    var idx = this._idx(key);\n    return idx !== -1;\n  },\n  set: function(key, value) {\n    key = this._transformKey(key);\n    var idx = this._idx(key);\n    if (idx === -1) {\n      idx = this._lastIndex = this._keys.length;\n    }\n    this._keys[idx] = key;\n    this._values[idx] = value;\n\n    // Support: IE11\n    // Do not `return this` to simulate the partial IE11 implementation\n  },\n  delete: function(key) {\n    key = this._transformKey(key);\n    var idx = this._idx(key);\n    if (idx === -1) {\n      return false;\n    }\n    this._keys.splice(idx, 1);\n    this._values.splice(idx, 1);\n    this._lastKey = NaN;\n    this._lastIndex = -1;\n    return true;\n  }\n};\n\n// For now, always use `NgMapShim`, even if `window.Map` is available. Some native implementations\n// are still buggy (often in subtle ways) and can cause hard-to-debug failures. When native `Map`\n// implementations get more stable, we can reconsider switching to `window.Map` (when available).\nvar NgMap = NgMapShim;\n\nvar $$MapProvider = [/** @this */function() {\n  this.$get = [function() {\n    return NgMap;\n  }];\n}];\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *     {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n *     disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document) {\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running AngularJS app\n * from outside AngularJS. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @installation\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar ARROW_ARG = /^([^(]+?)=>/;\nvar FN_ARGS = /^[^(]*\\(\\s*([^)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction stringifyFn(fn) {\n  return Function.prototype.toString.call(fn);\n}\n\nfunction extractArgs(fn) {\n  var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),\n      args = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);\n  return args;\n}\n\nfunction anonFn(fn) {\n  // For anonymous functions, showing at the very least the function signature can help in\n  // debugging.\n  var args = extractArgs(fn);\n  if (args) {\n    return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n  }\n  return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n  var $inject,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        if (strictDi) {\n          if (!isString(name) || !name) {\n            name = fn.name || anonFn(fn);\n          }\n          throw $injectorMinErr('strictdi',\n            '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n        }\n        argDecl = extractArgs(fn);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n          arg.replace(FN_ARG, function(all, underscore, name) {\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector) {\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * ## Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ### Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ### `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ### Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc property\n * @name $injector#modules\n * @type {Object}\n * @description\n * A hash containing all the modules that have been loaded into the\n * $injector.\n *\n * You can use this property to find out information about a module via the\n * {@link angular.Module#info `myModule.info(...)`} method.\n *\n * For example:\n *\n * ```\n * var info = $injector.modules['ngAnimate'].info();\n * ```\n *\n * **Do not use this property to attempt to modify the modules after the application\n * has been bootstrapped.**\n */\n\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string=} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are\n *   injected according to the {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * #### Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * #### The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * #### The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n/**\n * @ngdoc method\n * @name $injector#loadNewModules\n *\n * @description\n *\n * **This is a dangerous API, which you use at your own risk!**\n *\n * Add the specified modules to the current injector.\n *\n * This method will add each of the injectables to the injector and execute all of the config and run\n * blocks for each module passed to the method.\n *\n * If a module has already been loaded into the injector then it will not be loaded again.\n *\n * * The application developer is responsible for loading the code containing the modules; and for\n * ensuring that lazy scripts are not downloaded and executed more often that desired.\n * * Previously compiled HTML will not be affected by newly loaded directives, filters and components.\n * * Modules cannot be unloaded.\n *\n * You can use {@link $injector#modules `$injector.modules`} to check whether a module has been loaded\n * into the injector, which may indicate whether the script has been executed already.\n *\n * @example\n * Here is an example of loading a bundle of modules, with a utility method called `getScript`:\n *\n * ```javascript\n * app.factory('loadModule', function($injector) {\n *   return function loadModule(moduleName, bundleUrl) {\n *     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });\n *   };\n * })\n * ```\n *\n * @param {Array<String|Function|Array>=} mods an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a `config` block.\n *     See: {@link angular.module modules}\n */\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An AngularJS **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(name, provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(name, obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(name, obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(name, fn)} - registers a service **factory function**\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(name, Fn)} - registers a **constructor function**\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n * * {@link auto.$provide#decorator decorator(name, decorFn)} - registers a **decorator function** that\n *      will be able to modify or replace the implementation of another service.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * It is possible to inject other providers into the provider function,\n * but the injected provider must have been defined before the one that requires it.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.\n *                      Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is a factory\n * function that returns an instance instantiated by the injector from the service constructor\n * function.\n *\n * Internally it looks a bit like this:\n *\n * ```\n * {\n *   $get: function() {\n *     return $injector.instantiate(constructor);\n *   }\n * }\n * ```\n *\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)\n *     that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function. This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**. That also means it is not possible to inject other services into a value service.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an AngularJS {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service** with the {@link auto.$injector $injector}, such as a string,\n * a number, an array, an object or a function. Like the {@link auto.$provide#value value}, it is not\n * possible to inject other services into a constant.\n *\n * But unlike {@link auto.$provide#value value}, a constant can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an AngularJS {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **decorator function** with the {@link auto.$injector $injector}. A decorator function\n * intercepts the creation of a service, allowing it to override or modify the behavior of the\n * service. The return value of the decorator function may be the original service, or a new service\n * that replaces (or wraps and delegates to) the original service.\n *\n * You can find out more about using decorators in the {@link guide/decorators} guide.\n *\n * @param {string} name The name of the service to decorate.\n * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be\n *    provided and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be replaced, monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n  strictDi = (strictDi === true);\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new NgMap(),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function(serviceName, caller) {\n            if (angular.isString(caller)) {\n              path.push(caller);\n            }\n            throw $injectorMinErr('unpr', 'Unknown provider: {0}', path.join(' <- '));\n          })),\n      instanceCache = {},\n      protoInstanceInjector =\n          createInternalInjector(instanceCache, function(serviceName, caller) {\n            var provider = providerInjector.get(serviceName + providerSuffix, caller);\n            return instanceInjector.invoke(\n                provider.$get, provider, undefined, serviceName);\n          }),\n      instanceInjector = protoInstanceInjector;\n\n  providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) };\n  instanceInjector.modules = providerInjector.modules = createMap();\n  var runBlocks = loadModules(modulesToLoad);\n  instanceInjector = protoInstanceInjector.get('$injector');\n  instanceInjector.strictDi = strictDi;\n  forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); });\n\n  instanceInjector.loadNewModules = function(mods) {\n    forEach(loadModules(mods), function(fn) { if (fn) instanceInjector.invoke(fn); });\n  };\n\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', 'Provider \\'{0}\\' must define $get factory method.', name);\n    }\n    return (providerCache[name + providerSuffix] = provider_);\n  }\n\n  function enforceReturnValue(name, factory) {\n    return /** @this */ function enforcedReturnValue() {\n      var result = instanceInjector.invoke(factory, this);\n      if (isUndefined(result)) {\n        throw $injectorMinErr('undef', 'Provider \\'{0}\\' must return a value from $get factory method.', name);\n      }\n      return result;\n    };\n  }\n\n  function factory(name, factoryFn, enforce) {\n    return provider(name, {\n      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n    });\n  }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val), false); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad) {\n    assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), 'modulesToLoad', 'not an array');\n    var runBlocks = [], moduleFn;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.set(module, true);\n\n      function runInvokeQueue(queue) {\n        var i, ii;\n        for (i = 0, ii = queue.length; i < ii; i++) {\n          var invokeArgs = queue[i],\n              provider = providerInjector.get(invokeArgs[0]);\n\n          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n        }\n      }\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          instanceInjector.modules[module] = moduleFn;\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n          runInvokeQueue(moduleFn._invokeQueue);\n          runInvokeQueue(moduleFn._configBlocks);\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) === -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          // eslint-disable-next-line no-ex-assign\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', 'Failed to instantiate module {0} due to:\\n{1}',\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName, caller) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          cache[serviceName] = factory(serviceName, caller);\n          return cache[serviceName];\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n\n    function injectionArgs(fn, locals, serviceName) {\n      var args = [],\n          $inject = createInjector.$$annotate(fn, strictDi, serviceName);\n\n      for (var i = 0, length = $inject.length; i < length; i++) {\n        var key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(locals && locals.hasOwnProperty(key) ? locals[key] :\n                                                         getService(key, serviceName));\n      }\n      return args;\n    }\n\n    function isClass(func) {\n      // Support: IE 9-11 only\n      // IE 9-11 do not support classes and IE9 leaks with the code below.\n      if (msie || typeof func !== 'function') {\n        return false;\n      }\n      var result = func.$$ngIsClass;\n      if (!isBoolean(result)) {\n        result = func.$$ngIsClass = /^class\\b/.test(stringifyFn(func));\n      }\n      return result;\n    }\n\n    function invoke(fn, self, locals, serviceName) {\n      if (typeof locals === 'string') {\n        serviceName = locals;\n        locals = null;\n      }\n\n      var args = injectionArgs(fn, locals, serviceName);\n      if (isArray(fn)) {\n        fn = fn[fn.length - 1];\n      }\n\n      if (!isClass(fn)) {\n        // http://jsperf.com/angularjs-invoke-apply-vs-switch\n        // #5388\n        return fn.apply(self, args);\n      } else {\n        args.unshift(null);\n        return new (Function.prototype.bind.apply(fn, args))();\n      }\n    }\n\n\n    function instantiate(Type, locals, serviceName) {\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);\n      var args = injectionArgs(Type, locals, serviceName);\n      // Empty object at position 0 is ignored for invocation with `new`, but required.\n      args.unshift(null);\n      return new (Function.prototype.bind.apply(ctor, args))();\n    }\n\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: createInjector.$$annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n * @this\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $anchorScroll\n   * @kind function\n   * @requires $window\n   * @requires $location\n   * @requires $rootScope\n   *\n   * @description\n   * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the\n   * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified\n   * in the\n   * [HTML5 spec](http://www.w3.org/html/wg/drafts/html/master/browsers.html#an-indicated-part-of-the-document).\n   *\n   * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n   * match any anchor whenever it changes. This can be disabled by calling\n   * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n   *\n   * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n   * vertical scroll-offset (either fixed or dynamic).\n   *\n   * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of\n   *                       {@link ng.$location#hash $location.hash()} will be used.\n   *\n   * @property {(number|function|jqLite)} yOffset\n   * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n   * positioned elements at the top of the page, such as navbars, headers etc.\n   *\n   * `yOffset` can be specified in various ways:\n   * - **number**: A fixed number of pixels to be used as offset.<br /><br />\n   * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n   *   a number representing the offset (in pixels).<br /><br />\n   * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n   *   the top of the page to the element's bottom will be used as offset.<br />\n   *   **Note**: The element will be taken into account only as long as its `position` is set to\n   *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n   *   their height and/or positioning according to the viewport's size.\n   *\n   * <br />\n   * <div class=\"alert alert-warning\">\n   * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n   * not some child element.\n   * </div>\n   *\n   * @example\n     <example module=\"anchorScrollExample\" name=\"anchor-scroll\">\n       <file name=\"index.html\">\n         <div id=\"scrollArea\" ng-controller=\"ScrollController\">\n           <a ng-click=\"gotoBottom()\">Go to bottom</a>\n           <a id=\"bottom\"></a> You're at the bottom!\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollExample', [])\n           .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n             function($scope, $location, $anchorScroll) {\n               $scope.gotoBottom = function() {\n                 // set the location.hash to the id of\n                 // the element you wish to scroll to.\n                 $location.hash('bottom');\n\n                 // call $anchorScroll()\n                 $anchorScroll();\n               };\n             }]);\n       </file>\n       <file name=\"style.css\">\n         #scrollArea {\n           height: 280px;\n           overflow: auto;\n         }\n\n         #bottom {\n           display: block;\n           margin-top: 2000px;\n         }\n       </file>\n     </example>\n   *\n   * <hr />\n   * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n   * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n   *\n   * @example\n     <example module=\"anchorScrollOffsetExample\" name=\"anchor-scroll-offset\">\n       <file name=\"index.html\">\n         <div class=\"fixed-header\" ng-controller=\"headerCtrl\">\n           <a href=\"\" ng-click=\"gotoAnchor(x)\" ng-repeat=\"x in [1,2,3,4,5]\">\n             Go to anchor {{x}}\n           </a>\n         </div>\n         <div id=\"anchor{{x}}\" class=\"anchor\" ng-repeat=\"x in [1,2,3,4,5]\">\n           Anchor {{x}} of 5\n         </div>\n       </file>\n       <file name=\"script.js\">\n         angular.module('anchorScrollOffsetExample', [])\n           .run(['$anchorScroll', function($anchorScroll) {\n             $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels\n           }])\n           .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n             function($anchorScroll, $location, $scope) {\n               $scope.gotoAnchor = function(x) {\n                 var newHash = 'anchor' + x;\n                 if ($location.hash() !== newHash) {\n                   // set the $location.hash to `newHash` and\n                   // $anchorScroll will automatically scroll to it\n                   $location.hash('anchor' + x);\n                 } else {\n                   // call $anchorScroll() explicitly,\n                   // since $location.hash hasn't changed\n                   $anchorScroll();\n                 }\n               };\n             }\n           ]);\n       </file>\n       <file name=\"style.css\">\n         body {\n           padding-top: 50px;\n         }\n\n         .anchor {\n           border: 2px dashed DarkOrchid;\n           padding: 10px 10px 200px 10px;\n         }\n\n         .fixed-header {\n           background-color: rgba(0, 0, 0, 0.2);\n           height: 50px;\n           position: fixed;\n           top: 0; left: 0; right: 0;\n         }\n\n         .fixed-header > a {\n           display: inline-block;\n           margin: 5px 15px;\n         }\n       </file>\n     </example>\n   */\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // Helper function to get first anchor from a NodeList\n    // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n    //  and working in all supported browsers.)\n    function getFirstAnchor(list) {\n      var result = null;\n      Array.prototype.some.call(list, function(element) {\n        if (nodeName_(element) === 'a') {\n          result = element;\n          return true;\n        }\n      });\n      return result;\n    }\n\n    function getYOffset() {\n\n      var offset = scroll.yOffset;\n\n      if (isFunction(offset)) {\n        offset = offset();\n      } else if (isElement(offset)) {\n        var elem = offset[0];\n        var style = $window.getComputedStyle(elem);\n        if (style.position !== 'fixed') {\n          offset = 0;\n        } else {\n          offset = elem.getBoundingClientRect().bottom;\n        }\n      } else if (!isNumber(offset)) {\n        offset = 0;\n      }\n\n      return offset;\n    }\n\n    function scrollTo(elem) {\n      if (elem) {\n        elem.scrollIntoView();\n\n        var offset = getYOffset();\n\n        if (offset) {\n          // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n          // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n          // top of the viewport.\n          //\n          // IF the number of pixels from the top of `elem` to the end of the page's content is less\n          // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n          // way down the page.\n          //\n          // This is often the case for elements near the bottom of the page.\n          //\n          // In such cases we do not need to scroll the whole `offset` up, just the difference between\n          // the top of the element and the offset, which is enough to align the top of `elem` at the\n          // desired position.\n          var elemTop = elem.getBoundingClientRect().top;\n          $window.scrollBy(0, elemTop - offset);\n        }\n      } else {\n        $window.scrollTo(0, 0);\n      }\n    }\n\n    function scroll(hash) {\n      // Allow numeric hashes\n      hash = isString(hash) ? hash : isNumber(hash) ? hash.toString() : $location.hash();\n      var elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) scrollTo(null);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n      // no element and hash === 'top', scroll to the top of the page\n      else if (hash === 'top') scrollTo(null);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction(newVal, oldVal) {\n          // skip the initial scroll if $location.hash is empty\n          if (newVal === oldVal && newVal === '') return;\n\n          jqLiteDocumentLoaded(function() {\n            $rootScope.$evalAsync(scroll);\n          });\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\nvar ELEMENT_NODE = 1;\nvar NG_ANIMATE_CLASSNAME = 'ng-animate';\n\nfunction mergeClasses(a,b) {\n  if (!a && !b) return '';\n  if (!a) return b;\n  if (!b) return a;\n  if (isArray(a)) a = a.join(' ');\n  if (isArray(b)) b = b.join(' ');\n  return a + ' ' + b;\n}\n\nfunction extractElementNode(element) {\n  for (var i = 0; i < element.length; i++) {\n    var elm = element[i];\n    if (elm.nodeType === ELEMENT_NODE) {\n      return elm;\n    }\n  }\n}\n\nfunction splitClasses(classes) {\n  if (isString(classes)) {\n    classes = classes.split(' ');\n  }\n\n  // Use createMap() to prevent class assumptions involving property names in\n  // Object.prototype\n  var obj = createMap();\n  forEach(classes, function(klass) {\n    // sometimes the split leaves empty string values\n    // incase extra spaces were applied to the options\n    if (klass.length) {\n      obj[klass] = true;\n    }\n  });\n  return obj;\n}\n\n// if any other type of options value besides an Object value is\n// passed into the $animate.method() animation then this helper code\n// will be run which will ignore it. While this patch is not the\n// greatest solution to this, a lot of existing plugins depend on\n// $animate to either call the callback (< 1.2) or return a promise\n// that can be changed. This helper function ensures that the options\n// are wiped clean incase a callback function is provided.\nfunction prepareAnimateOptions(options) {\n  return isObject(options)\n      ? options\n      : {};\n}\n\nvar $$CoreAnimateJsProvider = /** @this */ function() {\n  this.$get = noop;\n};\n\n// this is prefixed with Core since it conflicts with\n// the animateQueueProvider defined in ngAnimate/animateQueue.js\nvar $$CoreAnimateQueueProvider = /** @this */ function() {\n  var postDigestQueue = new NgMap();\n  var postDigestElements = [];\n\n  this.$get = ['$$AnimateRunner', '$rootScope',\n       function($$AnimateRunner,   $rootScope) {\n    return {\n      enabled: noop,\n      on: noop,\n      off: noop,\n      pin: noop,\n\n      push: function(element, event, options, domOperation) {\n        if (domOperation) {\n          domOperation();\n        }\n\n        options = options || {};\n        if (options.from) {\n          element.css(options.from);\n        }\n        if (options.to) {\n          element.css(options.to);\n        }\n\n        if (options.addClass || options.removeClass) {\n          addRemoveClassesPostDigest(element, options.addClass, options.removeClass);\n        }\n\n        var runner = new $$AnimateRunner();\n\n        // since there are no animations to run the runner needs to be\n        // notified that the animation call is complete.\n        runner.complete();\n        return runner;\n      }\n    };\n\n\n    function updateData(data, classes, value) {\n      var changed = false;\n      if (classes) {\n        classes = isString(classes) ? classes.split(' ') :\n                  isArray(classes) ? classes : [];\n        forEach(classes, function(className) {\n          if (className) {\n            changed = true;\n            data[className] = value;\n          }\n        });\n      }\n      return changed;\n    }\n\n    function handleCSSClassChanges() {\n      forEach(postDigestElements, function(element) {\n        var data = postDigestQueue.get(element);\n        if (data) {\n          var existing = splitClasses(element.attr('class'));\n          var toAdd = '';\n          var toRemove = '';\n          forEach(data, function(status, className) {\n            var hasClass = !!existing[className];\n            if (status !== hasClass) {\n              if (status) {\n                toAdd += (toAdd.length ? ' ' : '') + className;\n              } else {\n                toRemove += (toRemove.length ? ' ' : '') + className;\n              }\n            }\n          });\n\n          forEach(element, function(elm) {\n            if (toAdd) {\n              jqLiteAddClass(elm, toAdd);\n            }\n            if (toRemove) {\n              jqLiteRemoveClass(elm, toRemove);\n            }\n          });\n          postDigestQueue.delete(element);\n        }\n      });\n      postDigestElements.length = 0;\n    }\n\n\n    function addRemoveClassesPostDigest(element, add, remove) {\n      var data = postDigestQueue.get(element) || {};\n\n      var classesAdded = updateData(data, add, true);\n      var classesRemoved = updateData(data, remove, false);\n\n      if (classesAdded || classesRemoved) {\n\n        postDigestQueue.set(element, data);\n        postDigestElements.push(element);\n\n        if (postDigestElements.length === 1) {\n          $rootScope.$$postDigest(handleCSSClassChanges);\n        }\n      }\n    }\n  }];\n};\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM updates and resolves the returned runner promise.\n *\n * In order to enable animations the `ngAnimate` module has to be loaded.\n *\n * To see the functional implementation check out `src/ngAnimate/animate.js`.\n */\nvar $AnimateProvider = ['$provide', /** @this */ function($provide) {\n  var provider = this;\n  var classNameFilter = null;\n  var customFilter = null;\n\n  this.$$registeredAnimations = Object.create(null);\n\n   /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(element, ... , doneFunction, options)`\n   *   The element to animate, the `doneFunction` and the options fed into the animation. Depending\n   *   on the type of animation additional arguments will be injected into the animation function. The\n   *   list below explains the function signatures for the different animation methods:\n   *\n   *   - setClass: function(element, addedClasses, removedClasses, doneFunction, options)\n   *   - addClass: function(element, addedClasses, doneFunction, options)\n   *   - removeClass: function(element, removedClasses, doneFunction, options)\n   *   - enter, leave, move: function(element, doneFunction, options)\n   *   - animate: function(element, fromStyles, toStyles, doneFunction, options)\n   *\n   *   Make sure to trigger the `doneFunction` once the animation is fully complete.\n   *\n   * ```js\n   *   return {\n   *     //enter, leave, move signature\n   *     eventFn : function(element, done, options) {\n   *       //code to run the animation\n   *       //once complete, then run done()\n   *       return function endFunction(wasCancelled) {\n   *         //code to cancel the animation\n   *       }\n   *     }\n   *   }\n   * ```\n   *\n   * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    if (name && name.charAt(0) !== '.') {\n      throw $animateMinErr('notcsel', 'Expecting class selector starting with \\'.\\' got \\'{0}\\'.', name);\n    }\n\n    var key = name + '-animation';\n    provider.$$registeredAnimations[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#customFilter\n   *\n   * @description\n   * Sets and/or returns the custom filter function that is used to \"filter\" animations, i.e.\n   * determine if an animation is allowed or not. When no filter is specified (the default), no\n   * animation will be blocked. Setting the `customFilter` value will only allow animations for\n   * which the filter function's return value is truthy.\n   *\n   * This allows to easily create arbitrarily complex rules for filtering animations, such as\n   * allowing specific events only, or enabling animations on specific subtrees of the DOM, etc.\n   * Filtering animations can also boost performance for low-powered devices, as well as\n   * applications containing a lot of structural operations.\n   *\n   * <div class=\"alert alert-success\">\n   *   **Best Practice:**\n   *   Keep the filtering function as lean as possible, because it will be called for each DOM\n   *   action (e.g. insertion, removal, class change) performed by \"animation-aware\" directives.\n   *   See {@link guide/animations#which-directives-support-animations- here} for a list of built-in\n   *   directives that support animations.\n   *   Performing computationally expensive or time-consuming operations on each call of the\n   *   filtering function can make your animations sluggish.\n   * </div>\n   *\n   * **Note:** If present, `customFilter` will be checked before\n   * {@link $animateProvider#classNameFilter classNameFilter}.\n   *\n   * @param {Function=} filterFn - The filter function which will be used to filter all animations.\n   *   If a falsy value is returned, no animation will be performed. The function will be called\n   *   with the following arguments:\n   *   - **node** `{DOMElement}` - The DOM element to be animated.\n   *   - **event** `{String}` - The name of the animation event (e.g. `enter`, `leave`, `addClass`\n   *     etc).\n   *   - **options** `{Object}` - A collection of options/styles used for the animation.\n   * @return {Function} The current filter function or `null` if there is none set.\n   */\n  this.customFilter = function(filterFn) {\n    if (arguments.length === 1) {\n      customFilter = isFunction(filterFn) ? filterFn : null;\n    }\n\n    return customFilter;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element that is triggered.\n   * When setting the `classNameFilter` value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   *\n   * **Note:** If present, `classNameFilter` will be checked after\n   * {@link $animateProvider#customFilter customFilter}. If `customFilter` is present and returns\n   * false, `classNameFilter` will not be checked.\n   *\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if (arguments.length === 1) {\n      classNameFilter = (expression instanceof RegExp) ? expression : null;\n      if (classNameFilter) {\n        var reservedRegex = new RegExp('[(\\\\s|\\\\/)]' + NG_ANIMATE_CLASSNAME + '[(\\\\s|\\\\/)]');\n        if (reservedRegex.test(classNameFilter.toString())) {\n          classNameFilter = null;\n          throw $animateMinErr('nongcls', '$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the \"{0}\" CSS class.', NG_ANIMATE_CLASSNAME);\n        }\n      }\n    }\n    return classNameFilter;\n  };\n\n  this.$get = ['$$animateQueue', function($$animateQueue) {\n    function domInsert(element, parentElement, afterElement) {\n      // if for some reason the previous element was removed\n      // from the dom sometime before this code runs then let's\n      // just stick to using the parent element as the anchor\n      if (afterElement) {\n        var afterNode = extractElementNode(afterElement);\n        if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {\n          afterElement = null;\n        }\n      }\n      if (afterElement) {\n        afterElement.after(element);\n      } else {\n        parentElement.prepend(element);\n      }\n    }\n\n    /**\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service exposes a series of DOM utility methods that provide support\n     * for animation hooks. The default behavior is the application of DOM operations, however,\n     * when an animation is detected (and animations are enabled), $animate will do the heavy lifting\n     * to ensure that animation runs with the triggered DOM operation.\n     *\n     * By default $animate doesn't trigger any animations. This is because the `ngAnimate` module isn't\n     * included and only when it is active then the animation hooks that `$animate` triggers will be\n     * functional. Once active then all structural `ng-` directives will trigger animations as they perform\n     * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,\n     * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.\n     *\n     * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.\n     *\n     * To learn more about enabling animation support, click here to visit the\n     * {@link ngAnimate ngAnimate module page}.\n     */\n    return {\n      // we don't call it directly since non-existant arguments may\n      // be interpreted as null within the sub enabled function\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#on\n       * @kind function\n       * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)\n       *    has fired on the given element or among any of its children. Once the listener is fired, the provided callback\n       *    is fired with the following params:\n       *\n       * ```js\n       * $animate.on('enter', container,\n       *    function callback(element, phase) {\n       *      // cool we detected an enter animation within the container\n       *    }\n       * );\n       * ```\n       *\n       * <div class=\"alert alert-warning\">\n       * **Note**: Generally, the events that are fired correspond 1:1 to `$animate` method names,\n       * e.g. {@link ng.$animate#addClass addClass()} will fire `addClass`, and {@link ng.ngClass}\n       * will fire `addClass` if classes are added, and `removeClass` if classes are removed.\n       * However, there are two exceptions:\n       *\n       * <ul>\n       *   <li>if both an {@link ng.$animate#addClass addClass()} and a\n       *   {@link ng.$animate#removeClass removeClass()} action are performed during the same\n       *   animation, the event fired will be `setClass`. This is true even for `ngClass`.</li>\n       *   <li>an {@link ng.$animate#animate animate()} call that adds and removes classes will fire\n       *   the `setClass` event, but if it either removes or adds classes,\n       *   it will fire `animate` instead.</li>\n       * </ul>\n       *\n       * </div>\n       *\n       * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)\n       * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself\n       *     as well as among its children\n       * @param {Function} callback the callback function that will be fired when the listener is triggered.\n       *\n       * The arguments present in the callback function are:\n       * * `element` - The captured DOM element that the animation was fired on.\n       * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).\n       * * `data` - an object with these properties:\n       *     * addClass - `{string|null}` - space-separated CSS classes to add to the element\n       *     * removeClass - `{string|null}` - space-separated CSS classes to remove from the element\n       *     * from - `{Object|null}` - CSS properties & values at the beginning of the animation\n       *     * to - `{Object|null}` - CSS properties & values at the end of the animation\n       *\n       * Note that the callback does not trigger a scope digest. Wrap your call into a\n       * {@link $rootScope.Scope#$apply scope.$apply} to propagate changes to the scope.\n       */\n      on: $$animateQueue.on,\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#off\n       * @kind function\n       * @description Deregisters an event listener based on the event which has been associated with the provided element. This method\n       * can be used in three different ways depending on the arguments:\n       *\n       * ```js\n       * // remove all the animation event listeners listening for `enter`\n       * $animate.off('enter');\n       *\n       * // remove listeners for all animation events from the container element\n       * $animate.off(container);\n       *\n       * // remove all the animation event listeners listening for `enter` on the given element and its children\n       * $animate.off('enter', container);\n       *\n       * // remove the event listener function provided by `callback` that is set\n       * // to listen for `enter` on the given `container` as well as its children\n       * $animate.off('enter', container, callback);\n       * ```\n       *\n       * @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move,\n       * addClass, removeClass, etc...), or the container element. If it is the element, all other\n       * arguments are ignored.\n       * @param {DOMElement=} container the container element the event listener was placed on\n       * @param {Function=} callback the callback function that was registered as the listener\n       */\n      off: $$animateQueue.off,\n\n      /**\n       * @ngdoc method\n       * @name $animate#pin\n       * @kind function\n       * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists\n       *    outside of the DOM structure of the AngularJS application. By doing so, any animation triggered via `$animate` can be issued on the\n       *    element despite being outside the realm of the application or within another application. Say for example if the application\n       *    was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated\n       *    as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind\n       *    that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.\n       *\n       *    Note that this feature is only active when the `ngAnimate` module is used.\n       *\n       * @param {DOMElement} element the external element that will be pinned\n       * @param {DOMElement} parentElement the host parent element that will be associated with the external element\n       */\n      pin: $$animateQueue.pin,\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enabled\n       * @kind function\n       * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This\n       * function can be called in four ways:\n       *\n       * ```js\n       * // returns true or false\n       * $animate.enabled();\n       *\n       * // changes the enabled state for all animations\n       * $animate.enabled(false);\n       * $animate.enabled(true);\n       *\n       * // returns true or false if animations are enabled for an element\n       * $animate.enabled(element);\n       *\n       * // changes the enabled state for an element and its children\n       * $animate.enabled(element, true);\n       * $animate.enabled(element, false);\n       * ```\n       *\n       * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state\n       * @param {boolean=} enabled whether or not the animations will be enabled for the element\n       *\n       * @return {boolean} whether or not animations are enabled\n       */\n      enabled: $$animateQueue.enabled,\n\n      /**\n       * @ngdoc method\n       * @name $animate#cancel\n       * @kind function\n       * @description Cancels the provided animation and applies the end state of the animation.\n       * Note that this does not cancel the underlying operation, e.g. the setting of classes or\n       * adding the element to the DOM.\n       *\n       * @param {animationRunner} animationRunner An animation runner returned by an $animate function.\n       *\n       * @example\n        <example module=\"animationExample\" deps=\"angular-animate.js\" animations=\"true\" name=\"animate-cancel\">\n          <file name=\"app.js\">\n            angular.module('animationExample', ['ngAnimate']).component('cancelExample', {\n              templateUrl: 'template.html',\n              controller: function($element, $animate) {\n                this.runner = null;\n\n                this.addClass = function() {\n                  this.runner = $animate.addClass($element.find('div'), 'red');\n                  var ctrl = this;\n                  this.runner.finally(function() {\n                    ctrl.runner = null;\n                  });\n                };\n\n                this.removeClass = function() {\n                  this.runner = $animate.removeClass($element.find('div'), 'red');\n                  var ctrl = this;\n                  this.runner.finally(function() {\n                    ctrl.runner = null;\n                  });\n                };\n\n                this.cancel = function() {\n                  $animate.cancel(this.runner);\n                };\n              }\n            });\n          </file>\n          <file name=\"template.html\">\n            <p>\n              <button id=\"add\" ng-click=\"$ctrl.addClass()\">Add</button>\n              <button ng-click=\"$ctrl.removeClass()\">Remove</button>\n              <br>\n              <button id=\"cancel\" ng-click=\"$ctrl.cancel()\" ng-disabled=\"!$ctrl.runner\">Cancel</button>\n              <br>\n              <div id=\"target\">CSS-Animated Text</div>\n            </p>\n          </file>\n          <file name=\"index.html\">\n            <cancel-example></cancel-example>\n          </file>\n          <file name=\"style.css\">\n            .red-add, .red-remove {\n              transition: all 4s cubic-bezier(0.250, 0.460, 0.450, 0.940);\n            }\n\n            .red,\n            .red-add.red-add-active {\n              color: #FF0000;\n              font-size: 40px;\n            }\n\n            .red-remove.red-remove-active {\n              font-size: 10px;\n              color: black;\n            }\n\n          </file>\n        </example>\n       */\n      cancel: function(runner) {\n        if (runner.cancel) {\n          runner.cancel();\n        }\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element (if provided) or\n       *   as the first child within the `parent` element and then triggers an animation.\n       *   A promise is returned that will be resolved during the next digest once the animation\n       *   has completed.\n       *\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (so long as the after element is not present)\n       * @param {DOMElement=} after the sibling element after which the element will be appended\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      enter: function(element, parent, after, options) {\n        parent = parent && jqLite(parent);\n        after = after && jqLite(after);\n        parent = parent || after.parent();\n        domInsert(element, parent, after);\n        return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Inserts (moves) the element into its new position in the DOM either after\n       *   the `after` element (if provided) or as the first child within the `parent` element\n       *   and then triggers an animation. A promise is returned that will be resolved\n       *   during the next digest once the animation has completed.\n       *\n       * @param {DOMElement} element the element which will be moved into the new DOM position\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (so long as the after element is not present)\n       * @param {DOMElement=} after the sibling element after which the element will be appended\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      move: function(element, parent, after, options) {\n        parent = parent && jqLite(parent);\n        after = after && jqLite(after);\n        parent = parent || after.parent();\n        domInsert(element, parent, after);\n        return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));\n      },\n\n      /**\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Triggers an animation and then removes the element from the DOM.\n       * When the function is called a promise is returned that will be resolved during the next\n       * digest once the animation has completed.\n       *\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      leave: function(element, options) {\n        return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {\n          element.remove();\n        });\n      },\n\n      /**\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       *\n       * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon\n       *   execution, the addClass operation will only be handled after the next digest and it will not trigger an\n       *   animation if element already contains the CSS class or if the class is removed at a later step.\n       *   Note that class-based animations are treated differently compared to structural animations\n       *   (like enter, move and leave) since the CSS classes may be added/removed at different points\n       *   depending if CSS or JavaScript animations are used.\n       *\n       * @param {DOMElement} element the element which the CSS classes will be applied to\n       * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} animationRunner the animation runner\n       */\n      addClass: function(element, className, options) {\n        options = prepareAnimateOptions(options);\n        options.addClass = mergeClasses(options.addclass, className);\n        return $$animateQueue.push(element, 'addClass', options);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       *\n       * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon\n       *   execution, the removeClass operation will only be handled after the next digest and it will not trigger an\n       *   animation if element does not contain the CSS class or if the class is added at a later step.\n       *   Note that class-based animations are treated differently compared to structural animations\n       *   (like enter, move and leave) since the CSS classes may be added/removed at different points\n       *   depending if CSS or JavaScript animations are used.\n       *\n       * @param {DOMElement} element the element which the CSS classes will be applied to\n       * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      removeClass: function(element, className, options) {\n        options = prepareAnimateOptions(options);\n        options.removeClass = mergeClasses(options.removeClass, className);\n        return $$animateQueue.push(element, 'removeClass', options);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       *\n       * @description Performs both the addition and removal of a CSS classes on an element and (during the process)\n       *    triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and\n       *    `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has\n       *    passed. Note that class-based animations are treated differently compared to structural animations\n       *    (like enter, move and leave) since the CSS classes may be added/removed at different points\n       *    depending if CSS or JavaScript animations are used.\n       *\n       * @param {DOMElement} element the element which the CSS classes will be applied to\n       * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)\n       * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      setClass: function(element, add, remove, options) {\n        options = prepareAnimateOptions(options);\n        options.addClass = mergeClasses(options.addClass, add);\n        options.removeClass = mergeClasses(options.removeClass, remove);\n        return $$animateQueue.push(element, 'setClass', options);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $animate#animate\n       * @kind function\n       *\n       * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.\n       * If any detected CSS transition, keyframe or JavaScript matches the provided className value, then the animation will take\n       * on the provided styles. For example, if a transition animation is set for the given className, then the provided `from` and\n       * `to` styles will be applied alongside the given transition. If the CSS style provided in `from` does not have a corresponding\n       * style in `to`, the style in `from` is applied immediately, and no animation is run.\n       * If a JavaScript animation is detected then the provided styles will be given in as function parameters into the `animate`\n       * method (or as part of the `options` parameter):\n       *\n       * ```js\n       * ngModule.animation('.my-inline-animation', function() {\n       *   return {\n       *     animate : function(element, from, to, done, options) {\n       *       //animation\n       *       done();\n       *     }\n       *   }\n       * });\n       * ```\n       *\n       * @param {DOMElement} element the element which the CSS styles will be applied to\n       * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.\n       * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.\n       * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If\n       *    this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.\n       *    (Note that if no animation is detected then this value will not be applied to the element.)\n       * @param {object=} options an optional collection of options/styles that will be applied to the element.\n       *   The object can have the following properties:\n       *\n       *   - **addClass** - `{string}` - space-separated CSS classes to add to element\n       *   - **from** - `{Object}` - CSS properties & values at the beginning of animation. Must have matching `to`\n       *   - **removeClass** - `{string}` - space-separated CSS classes to remove from element\n       *   - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`\n       *\n       * @return {Runner} the animation runner\n       */\n      animate: function(element, from, to, className, options) {\n        options = prepareAnimateOptions(options);\n        options.from = options.from ? extend(options.from, from) : from;\n        options.to   = options.to   ? extend(options.to, to)     : to;\n\n        className = className || 'ng-inline-animate';\n        options.tempClasses = mergeClasses(options.tempClasses, className);\n        return $$animateQueue.push(element, 'animate', options);\n      }\n    };\n  }];\n}];\n\nvar $$AnimateAsyncRunFactoryProvider = /** @this */ function() {\n  this.$get = ['$$rAF', function($$rAF) {\n    var waitQueue = [];\n\n    function waitForTick(fn) {\n      waitQueue.push(fn);\n      if (waitQueue.length > 1) return;\n      $$rAF(function() {\n        for (var i = 0; i < waitQueue.length; i++) {\n          waitQueue[i]();\n        }\n        waitQueue = [];\n      });\n    }\n\n    return function() {\n      var passed = false;\n      waitForTick(function() {\n        passed = true;\n      });\n      return function(callback) {\n        if (passed) {\n          callback();\n        } else {\n          waitForTick(callback);\n        }\n      };\n    };\n  }];\n};\n\nvar $$AnimateRunnerFactoryProvider = /** @this */ function() {\n  this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$$isDocumentHidden', '$timeout',\n       function($q,   $sniffer,   $$animateAsyncRun,   $$isDocumentHidden,   $timeout) {\n\n    var INITIAL_STATE = 0;\n    var DONE_PENDING_STATE = 1;\n    var DONE_COMPLETE_STATE = 2;\n\n    AnimateRunner.chain = function(chain, callback) {\n      var index = 0;\n\n      next();\n      function next() {\n        if (index === chain.length) {\n          callback(true);\n          return;\n        }\n\n        chain[index](function(response) {\n          if (response === false) {\n            callback(false);\n            return;\n          }\n          index++;\n          next();\n        });\n      }\n    };\n\n    AnimateRunner.all = function(runners, callback) {\n      var count = 0;\n      var status = true;\n      forEach(runners, function(runner) {\n        runner.done(onProgress);\n      });\n\n      function onProgress(response) {\n        status = status && response;\n        if (++count === runners.length) {\n          callback(status);\n        }\n      }\n    };\n\n    function AnimateRunner(host) {\n      this.setHost(host);\n\n      var rafTick = $$animateAsyncRun();\n      var timeoutTick = function(fn) {\n        $timeout(fn, 0, false);\n      };\n\n      this._doneCallbacks = [];\n      this._tick = function(fn) {\n        if ($$isDocumentHidden()) {\n          timeoutTick(fn);\n        } else {\n          rafTick(fn);\n        }\n      };\n      this._state = 0;\n    }\n\n    AnimateRunner.prototype = {\n      setHost: function(host) {\n        this.host = host || {};\n      },\n\n      done: function(fn) {\n        if (this._state === DONE_COMPLETE_STATE) {\n          fn();\n        } else {\n          this._doneCallbacks.push(fn);\n        }\n      },\n\n      progress: noop,\n\n      getPromise: function() {\n        if (!this.promise) {\n          var self = this;\n          this.promise = $q(function(resolve, reject) {\n            self.done(function(status) {\n              if (status === false) {\n                reject();\n              } else {\n                resolve();\n              }\n            });\n          });\n        }\n        return this.promise;\n      },\n\n      then: function(resolveHandler, rejectHandler) {\n        return this.getPromise().then(resolveHandler, rejectHandler);\n      },\n\n      'catch': function(handler) {\n        return this.getPromise()['catch'](handler);\n      },\n\n      'finally': function(handler) {\n        return this.getPromise()['finally'](handler);\n      },\n\n      pause: function() {\n        if (this.host.pause) {\n          this.host.pause();\n        }\n      },\n\n      resume: function() {\n        if (this.host.resume) {\n          this.host.resume();\n        }\n      },\n\n      end: function() {\n        if (this.host.end) {\n          this.host.end();\n        }\n        this._resolve(true);\n      },\n\n      cancel: function() {\n        if (this.host.cancel) {\n          this.host.cancel();\n        }\n        this._resolve(false);\n      },\n\n      complete: function(response) {\n        var self = this;\n        if (self._state === INITIAL_STATE) {\n          self._state = DONE_PENDING_STATE;\n          self._tick(function() {\n            self._resolve(response);\n          });\n        }\n      },\n\n      _resolve: function(response) {\n        if (this._state !== DONE_COMPLETE_STATE) {\n          forEach(this._doneCallbacks, function(fn) {\n            fn(response);\n          });\n          this._doneCallbacks.length = 0;\n          this._state = DONE_COMPLETE_STATE;\n        }\n      }\n    };\n\n    return AnimateRunner;\n  }];\n};\n\n/* exported $CoreAnimateCssProvider */\n\n/**\n * @ngdoc service\n * @name $animateCss\n * @kind object\n * @this\n *\n * @description\n * This is the core version of `$animateCss`. By default, only when the `ngAnimate` is included,\n * then the `$animateCss` service will actually perform animations.\n *\n * Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.\n */\nvar $CoreAnimateCssProvider = function() {\n  this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {\n\n    return function(element, initialOptions) {\n      // all of the animation functions should create\n      // a copy of the options data, however, if a\n      // parent service has already created a copy then\n      // we should stick to using that\n      var options = initialOptions || {};\n      if (!options.$$prepared) {\n        options = copy(options);\n      }\n\n      // there is no point in applying the styles since\n      // there is no animation that goes on at all in\n      // this version of $animateCss.\n      if (options.cleanupStyles) {\n        options.from = options.to = null;\n      }\n\n      if (options.from) {\n        element.css(options.from);\n        options.from = null;\n      }\n\n      var closed, runner = new $$AnimateRunner();\n      return {\n        start: run,\n        end: run\n      };\n\n      function run() {\n        $$rAF(function() {\n          applyAnimationContents();\n          if (!closed) {\n            runner.complete();\n          }\n          closed = true;\n        });\n        return runner;\n      }\n\n      function applyAnimationContents() {\n        if (options.addClass) {\n          element.addClass(options.addClass);\n          options.addClass = null;\n        }\n        if (options.removeClass) {\n          element.removeClass(options.removeClass);\n          options.removeClass = null;\n        }\n        if (options.to) {\n          element.css(options.to);\n          options.to = null;\n        }\n      }\n    };\n  }];\n};\n\n/* global getHash: true, stripHash: false */\n\nfunction getHash(url) {\n  var index = url.indexOf('#');\n  return index === -1 ? '' : url.substr(index);\n}\n\nfunction trimEmptyHash(url) {\n  return url.replace(/#$/, '');\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer, $$taskTrackerFactory) {\n  var self = this,\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {},\n      taskTracker = $$taskTrackerFactory($log);\n\n  self.isMock = false;\n\n  //////////////////////////////////////////////////////////////\n  // Task-tracking API\n  //////////////////////////////////////////////////////////////\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = taskTracker.completeTask;\n  self.$$incOutstandingRequestCount = taskTracker.incTaskCount;\n\n  // TODO(vojta): prefix this method with $$ ?\n  self.notifyWhenNoOutstandingRequests = taskTracker.notifyWhenNoPendingTasks;\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var cachedState, lastHistoryState,\n      lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      pendingLocation = null,\n      getCurrentState = !$sniffer.history ? noop : function getCurrentState() {\n        try {\n          return history.state;\n        } catch (e) {\n          // MSIE can reportedly throw when there is no state (UNCONFIRMED).\n        }\n      };\n\n  cacheState();\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of `location.href` (with a\n   * trailing `#` stripped of if the hash is empty).\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, `pushState`/`replaceState` is used, otherwise\n   * `location.href`/`location.replace` is used.\n   * Returns its own instance to allow chaining.\n   *\n   * NOTE: this api is intended for use only by the `$location` service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record?\n   * @param {object=} state State object to use with `pushState`/`replaceState`\n   */\n  self.url = function(url, replace, state) {\n    // In modern browsers `history.state` is `null` by default; treating it separately\n    // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n    // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n    if (isUndefined(state)) {\n      state = null;\n    }\n\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      var sameState = lastHistoryState === state;\n\n      // Normalize the inputted URL\n      url = urlResolve(url).href;\n\n      // Don't change anything if previous and current URLs and states match. This also prevents\n      // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n      // See https://github.com/angular/angular.js/commit/ffb2701\n      if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n        return self;\n      }\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      lastHistoryState = state;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if ($sniffer.history && (!sameBase || !sameState)) {\n        history[replace ? 'replaceState' : 'pushState'](state, '', url);\n        cacheState();\n      } else {\n        if (!sameBase) {\n          pendingLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else if (!sameBase) {\n          location.href = url;\n        } else {\n          location.hash = getHash(url);\n        }\n        if (location.href !== url) {\n          pendingLocation = url;\n        }\n      }\n      if (pendingLocation) {\n        pendingLocation = url;\n      }\n      return self;\n    // getter\n    } else {\n      // - pendingLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened or if there is a bug like in iOS 9 (see\n      //   https://openradar.appspot.com/22186109).\n      return trimEmptyHash(pendingLocation || location.href);\n    }\n  };\n\n  /**\n   * @name $browser#state\n   *\n   * @description\n   * This method is a getter.\n   *\n   * Return history.state or null if history.state is undefined.\n   *\n   * @returns {object} state\n   */\n  self.state = function() {\n    return cachedState;\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function cacheStateAndFireUrlChange() {\n    pendingLocation = null;\n    fireStateOrUrlChange();\n  }\n\n  // This variable should be used *only* inside the cacheState function.\n  var lastCachedState = null;\n  function cacheState() {\n    // This should be the only place in $browser where `history.state` is read.\n    cachedState = getCurrentState();\n    cachedState = isUndefined(cachedState) ? null : cachedState;\n\n    // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n    if (equals(cachedState, lastCachedState)) {\n      cachedState = lastCachedState;\n    }\n\n    lastCachedState = cachedState;\n    lastHistoryState = cachedState;\n  }\n\n  function fireStateOrUrlChange() {\n    var prevLastHistoryState = lastHistoryState;\n    cacheState();\n\n    if (lastBrowserUrl === self.url() && prevLastHistoryState === cachedState) {\n      return;\n    }\n\n    lastBrowserUrl = self.url();\n    lastHistoryState = cachedState;\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url(), cachedState);\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of AngularJS:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in AngularJS apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers don't\n      // fire popstate when user changes the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n      // hashchange event\n      jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * @private\n   * Remove popstate and hashchange handler from window.\n   *\n   * NOTE: this api is intended for use only by $rootScope.\n   */\n  self.$$applicationDestroyed = function() {\n    jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);\n  };\n\n  /**\n   * Checks whether the url has changed outside of AngularJS.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireStateOrUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?:)?\\/\\/[^/]*/, '') : '';\n  };\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] Number of milliseconds to defer the function execution.\n   * @param {string=} [taskType=DEFAULT_TASK_TYPE] The type of task that is deferred.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay, taskType) {\n    var timeoutId;\n\n    delay = delay || 0;\n    taskType = taskType || taskTracker.DEFAULT_TASK_TYPE;\n\n    taskTracker.incTaskCount(taskType);\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      taskTracker.completeTask(fn, taskType);\n    }, delay);\n    pendingDeferIds[timeoutId] = taskType;\n\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds.hasOwnProperty(deferId)) {\n      var taskType = pendingDeferIds[deferId];\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      taskTracker.completeTask(noop, taskType);\n      return true;\n    }\n    return false;\n  };\n\n}\n\n/** @this */\nfunction $BrowserProvider() {\n  this.$get = ['$window', '$log', '$sniffer', '$document', '$$taskTrackerFactory',\n       function($window,   $log,   $sniffer,   $document,   $$taskTrackerFactory) {\n    return new Browser($window, $document, $log, $sniffer, $$taskTrackerFactory);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n * @this\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\" name=\"cache-factory\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if (angular.isUndefined($scope.cache.get(key))) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, angular.isUndefined(value) ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', 'CacheId \\'{0}\\' is already taken!', cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = createMap(),\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = createMap(),\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $templateRequest $templateRequest} and the {@link ng.directive:script script}\n       * directive to cache templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return (caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (isUndefined(value)) return;\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry === freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry === staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          if (!(key in data)) return;\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = createMap();\n          size = 0;\n          lruHash = createMap();\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      });\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry !== freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd === entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry !== prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n * @this\n *\n * @description\n * `$templateCache` is a {@link $cacheFactory.Cache Cache object} created by the\n * {@link ng.$cacheFactory $cacheFactory}.\n *\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, by using {@link $templateRequest},\n * or by consuming the `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (e.g.\n * element with {@link ngApp} attribute), otherwise the template will be ignored.\n *\n * Adding via the `$templateCache` service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your component:\n * ```js\n * myApp.component('myComponent', {\n *    templateUrl: 'templateId.html'\n * });\n * ```\n *\n * or get it via the `$templateCache` service:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n *     Any commits to this file should be reviewed with security in mind.  *\n *   Changes to this file can potentially create security vulnerabilities. *\n *          An approval from 2 Core members with history of modifying      *\n *                         this file is required.                          *\n *                                                                         *\n *  Does the change somehow allow for arbitrary javascript to be executed? *\n *    Or allows for someone to change the prototype of built-in objects?   *\n *     Or gives undesired access to variables like document or window?    *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a {@link $compile#directive-definition-object Directive Definition Object (see below)}\n * that defines the directive properties, or just the `postLink` function (all other properties will have\n * the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       {@link $compile#-priority- priority}: 0,\n *       {@link $compile#-template- template}: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // {@link $compile#-templateurl- templateUrl}: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       {@link $compile#-transclude- transclude}: false,\n *       {@link $compile#-restrict- restrict}: 'A',\n *       {@link $compile#-templatenamespace- templateNamespace}: 'html',\n *       {@link $compile#-scope- scope}: false,\n *       {@link $compile#-controller- controller}: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       {@link $compile#-controlleras- controllerAs}: 'stringIdentifier',\n *       {@link $compile#-bindtocontroller- bindToController}: false,\n *       {@link $compile#-require- require}: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       {@link $compile#-multielement- multiElement}: false,\n *       {@link $compile#-compile- compile}: function compile(tElement, tAttrs, transclude) {\n *         return {\n *            {@link $compile#pre-linking-function pre}: function preLink(scope, iElement, iAttrs, controller) { ... },\n *            {@link $compile#post-linking-function post}: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // {@link $compile#-link- link}: {\n *       //  {@link $compile#pre-linking-function pre}: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  {@link $compile#post-linking-function post}: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // {@link $compile#-link- link}: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n * ### Life-cycle hooks\n * Directive controllers can provide the following methods that are called by AngularJS at points in the life-cycle of the\n * directive:\n * * `$onInit()` - Called on each controller after all the controllers on an element have been constructed and\n *   had their bindings initialized (and before the pre &amp; post linking functions for the directives on\n *   this element). This is a good place to put initialization code for your controller.\n * * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The\n *   `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an\n *   object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a\n *   component such as cloning the bound value to prevent accidental mutation of the outer value. Note that this will\n *   also be called when your bindings are initialized.\n * * `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on\n *   changes. Any actions that you wish to take in response to the changes that you detect must be\n *   invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook\n *   could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not\n *   be detected by AngularJS's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments;\n *   if detecting changes, you must store the previous value(s) for comparison to the current values.\n * * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing\n *   external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in\n *   the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent\n *   components will have their `$onDestroy()` hook called before child components.\n * * `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link\n *   function this hook can be used to set up DOM event handlers and do direct DOM manipulation.\n *   Note that child elements that contain `templateUrl` directives will not have been compiled and linked since\n *   they are waiting for their template to load asynchronously and their own compilation and linking has been\n *   suspended until that occurs.\n *\n * #### Comparison with life-cycle hooks in the new Angular\n * The new Angular also uses life-cycle hooks for its components. While the AngularJS life-cycle hooks are similar there are\n * some differences that you should be aware of, especially when it comes to moving your code from AngularJS to Angular:\n *\n * * AngularJS hooks are prefixed with `$`, such as `$onInit`. Angular hooks are prefixed with `ng`, such as `ngOnInit`.\n * * AngularJS hooks can be defined on the controller prototype or added to the controller inside its constructor.\n *   In Angular you can only define hooks on the prototype of the Component class.\n * * Due to the differences in change-detection, you may get many more calls to `$doCheck` in AngularJS than you would to\n *   `ngDoCheck` in Angular.\n * * Changes to the model inside `$doCheck` will trigger new turns of the digest loop, which will cause the changes to be\n *   propagated throughout the application.\n *   Angular does not allow the `ngDoCheck` hook to trigger a change outside of the component. It will either throw an\n *   error or do nothing depending upon the state of `enableProdMode()`.\n *\n * #### Life-cycle hook examples\n *\n * This example shows how you can check for mutations to a Date object even though the identity of the object\n * has not changed.\n *\n * <example name=\"doCheckDateExample\" module=\"do-check-module\">\n *   <file name=\"app.js\">\n *     angular.module('do-check-module', [])\n *       .component('app', {\n *         template:\n *           'Month: <input ng-model=\"$ctrl.month\" ng-change=\"$ctrl.updateDate()\">' +\n *           'Date: {{ $ctrl.date }}' +\n *           '<test date=\"$ctrl.date\"></test>',\n *         controller: function() {\n *           this.date = new Date();\n *           this.month = this.date.getMonth();\n *           this.updateDate = function() {\n *             this.date.setMonth(this.month);\n *           };\n *         }\n *       })\n *       .component('test', {\n *         bindings: { date: '<' },\n *         template:\n *           '<pre>{{ $ctrl.log | json }}</pre>',\n *         controller: function() {\n *           var previousValue;\n *           this.log = [];\n *           this.$doCheck = function() {\n *             var currentValue = this.date && this.date.valueOf();\n *             if (previousValue !== currentValue) {\n *               this.log.push('doCheck: date mutated: ' + this.date);\n *               previousValue = currentValue;\n *             }\n *           };\n *         }\n *       });\n *   </file>\n *   <file name=\"index.html\">\n *     <app></app>\n *   </file>\n * </example>\n *\n * This example show how you might use `$doCheck` to trigger changes in your component's inputs even if the\n * actual identity of the component doesn't change. (Be aware that cloning and deep equality checks on large\n * arrays or objects can have a negative impact on your application performance.)\n *\n * <example name=\"doCheckArrayExample\" module=\"do-check-module\">\n *   <file name=\"index.html\">\n *     <div ng-init=\"items = []\">\n *       <button ng-click=\"items.push(items.length)\">Add Item</button>\n *       <button ng-click=\"items = []\">Reset Items</button>\n *       <pre>{{ items }}</pre>\n *       <test items=\"items\"></test>\n *     </div>\n *   </file>\n *   <file name=\"app.js\">\n *      angular.module('do-check-module', [])\n *        .component('test', {\n *          bindings: { items: '<' },\n *          template:\n *            '<pre>{{ $ctrl.log | json }}</pre>',\n *          controller: function() {\n *            this.log = [];\n *\n *            this.$doCheck = function() {\n *              if (this.items_ref !== this.items) {\n *                this.log.push('doCheck: items changed');\n *                this.items_ref = this.items;\n *              }\n *              if (!angular.equals(this.items_clone, this.items)) {\n *                this.log.push('doCheck: items mutated');\n *                this.items_clone = angular.copy(this.items);\n *              }\n *            };\n *          }\n *        });\n *   </file>\n * </example>\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true (default is `false`), the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioral (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * The scope property can be `false`, `true`, or an object:\n *\n * * **`false` (default):** No scope will be created for the directive. The directive will use its\n * parent's scope.\n *\n * * **`true`:** A new child scope that prototypically inherits from its parent will be created for\n * the directive's element. If multiple directives on the same element request a new scope,\n * only one new scope is created.\n *\n * * **`{...}` (an object hash):** A new \"isolate\" scope is created for the directive's template.\n * The 'isolate' scope differs from normal scope in that it does not prototypically\n * inherit from its parent scope. This is useful when creating reusable components, which should not\n * accidentally read or modify data in the parent scope. Note that an isolate scope\n * directive without a `template` or `templateUrl` will not apply the isolate scope\n * to its children elements.\n *\n * The 'isolate' scope object hash defines a set of local scope properties derived from attributes on the\n * directive's element. These local properties are useful for aliasing values for templates. The keys in\n * the object hash map to the name of the property on the isolate scope; the values define how the property\n * is bound to the parent scope, via matching attributes on the directive's element:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified then the\n *   attribute name is assumed to be the same as the local name. Given `<my-component\n *   my-attr=\"hello {{name}}\">` and the isolate scope definition `scope: { localName:'@myAttr' }`,\n *   the directive's scope property `localName` will reflect the interpolated value of `hello\n *   {{name}}`. As the `name` attribute changes so will the `localName` property on the directive's\n *   scope. The `name` is read from the parent scope (not the directive's scope).\n *\n * * `=` or `=attr` - set up a bidirectional binding between a local scope property and an expression\n *   passed via the attribute `attr`. The expression is evaluated in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the local\n *   name. Given `<my-component my-attr=\"parentModel\">` and the isolate scope definition `scope: {\n *   localModel: '=myAttr' }`, the property `localModel` on the directive's scope will reflect the\n *   value of `parentModel` on the parent scope. Changes to `parentModel` will be reflected in\n *   `localModel` and vice versa. If the binding expression is non-assignable, or if the attribute\n *   isn't  optional and doesn't exist, an exception\n *   ({@link error/$compile/nonassign `$compile:nonassign`}) will be thrown upon discovering changes\n *   to the local value, since it will be impossible to sync them back to the parent scope.\n *\n *   By default, the {@link ng.$rootScope.Scope#$watch `$watch`}\n *   method is used for tracking changes, and the equality check is based on object identity.\n *   However, if an object literal or an array literal is passed as the binding expression, the\n *   equality check is done by value (using the {@link angular.equals} function). It's also possible\n *   to watch the evaluated value shallowly with {@link ng.$rootScope.Scope#$watchCollection\n *   `$watchCollection`}: use `=*` or `=*attr`\n *\n  * * `<` or `<attr` - set up a one-way (one-directional) binding between a local scope property and an\n *   expression passed via the attribute `attr`. The expression is evaluated in the context of the\n *   parent scope. If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name.\n *\n *   For example, given `<my-component my-attr=\"parentModel\">` and directive definition of\n *   `scope: { localModel:'<myAttr' }`, then the isolated scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel`, but changes in `localModel` will not reflect in `parentModel`. There are however\n *   two caveats:\n *     1. one-way binding does not copy the value from the parent to the isolate scope, it simply\n *     sets the same value. That means if your bound value is an object, changes to its properties\n *     in the isolated scope will be reflected in the parent scope (because both reference the same object).\n *     2. one-way binding watches changes to the **identity** of the parent value. That means the\n *     {@link ng.$rootScope.Scope#$watch `$watch`} on the parent value only fires if the reference\n *     to the value has changed. In most cases, this should not be of concern, but can be important\n *     to know if you one-way bind to an object, and then replace that object in the isolated scope.\n *     If you now change a property of the object in your parent scope, the change will not be\n *     propagated to the isolated scope, because the identity of the object on the parent scope\n *     has not changed. Instead you must assign a new object.\n *\n *   One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings\n *   back to the parent. However, it does not make this completely impossible.\n *\n *   By default, the {@link ng.$rootScope.Scope#$watch `$watch`}\n *   method is used for tracking changes, and the equality check is based on object identity.\n *   It's also possible to watch the evaluated value shallowly with\n *   {@link ng.$rootScope.Scope#$watchCollection `$watchCollection`}: use `<*` or `<*attr`\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. If\n *   no `attr` name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<my-component my-attr=\"count = count + value\">` and the isolate scope definition `scope: {\n *   localFn:'&myAttr' }`, the isolate scope property `localFn` will point to a function wrapper for\n *   the `count = count + value` expression. Often it's desirable to pass data from the isolated scope\n *   via an expression to the parent scope. This can be done by passing a map of local variable names\n *   and values into the expression wrapper fn. For example, if the expression is `increment(amount)`\n *   then we can specify the amount value by calling the `localFn` as `localFn({amount: 22})`.\n *\n * All 4 kinds of bindings (`@`, `=`, `<`, and `&`) can be made optional by adding `?` to the expression.\n * The marker must come after the mode and before the attribute name.\n * See the {@link error/$compile/iscp Invalid Isolate Scope Definition error} for definition examples.\n * This is useful to refine the interface directives provide.\n * One subtle difference between optional and non-optional happens **when the binding attribute is not\n * set**:\n * - the binding is optional: the property will not be defined\n * - the binding is not optional: the property is defined\n *\n * ```js\n *app.directive('testDir', function() {\n    return {\n      scope: {\n        notoptional: '=',\n        optional: '=?',\n      },\n      bindToController: true,\n      controller: function() {\n        this.$onInit = function() {\n          console.log(this.hasOwnProperty('notoptional')) // true\n          console.log(this.hasOwnProperty('optional')) // false\n        }\n      }\n    }\n  })\n *```\n *\n *\n * ##### Combining directives with different scope defintions\n *\n * In general it's possible to apply more than one directive to one element, but there might be limitations\n * depending on the type of scope required by the directives. The following points will help explain these limitations.\n * For simplicity only two directives are taken into account, but it is also applicable for several directives:\n *\n * * **no scope** + **no scope** => Two directives which don't require their own scope will use their parent's scope\n * * **child scope** + **no scope** =>  Both directives will share one single child scope\n * * **child scope** + **child scope** =>  Both directives will share one single child scope\n * * **isolated scope** + **no scope** =>  The isolated directive will use it's own created isolated scope. The other directive will use\n * its parent's scope\n * * **isolated scope** + **child scope** =>  **Won't work!** Only one scope can be related to one element. Therefore these directives cannot\n * be applied to the same element.\n * * **isolated scope** + **isolated scope**  =>  **Won't work!** Only one scope can be related to one element. Therefore these directives\n * cannot be applied to the same element.\n *\n *\n * #### `bindToController`\n * This property is used to bind scope properties directly to the controller. It can be either\n * `true` or an object hash with the same format as the `scope` property.\n *\n * When an isolate scope is used for a directive (see above), `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope.\n *\n * After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller\n * properties. You can access these bindings once they have been initialized by providing a controller method called\n * `$onInit`, which is called after all the controllers on an element have been constructed and had their bindings\n * initialized.\n *\n * It is also possible to set `bindToController` to an object hash with the same format as the `scope` property.\n * This will set up the scope bindings to the controller directly. Note that `scope` can still be used\n * to define which kind of scope is created. By default, no scope is created. Use `scope: {}` to create an isolate\n * scope (useful for component directives).\n *\n * If both `bindToController` and `scope` are defined and have object hashes, `bindToController` overrides `scope`.\n *\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and can be accessed by other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n *   `function([scope], cloneLinkingFn, futureParentElement, slotName)`:\n *    * `scope`: (optional) override the scope.\n *    * `cloneLinkingFn`: (optional) argument to create clones of the original transcluded content.\n *    * `futureParentElement` (optional):\n *        * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n *        * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n *        * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n *          and when the `cloneLinkingFn` is passed,\n *          as those elements need to created and cloned in a special way when they are defined outside their\n *          usual containers (e.g. like `<svg>`).\n *        * See also the `directive.templateNamespace` property.\n *    * `slotName`: (optional) the name of the slot to transclude. If falsy (e.g. `null`, `undefined` or `''`)\n *      then the default transclusion is provided.\n *    The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns\n *    `true` if the specified slot contains content (i.e. one or more DOM nodes).\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` property can be a string, an array or an object:\n * * a **string** containing the name of the directive to pass to the linking function\n * * an **array** containing the names of directives to pass to the linking function. The argument passed to the\n * linking function will be an array of controllers in the same order as the names in the `require` property\n * * an **object** whose property values are the names of the directives to pass to the linking function. The argument\n * passed to the linking function will also be an object with matching keys, whose values will hold the corresponding\n * controllers.\n *\n * If the `require` property is an object and `bindToController` is truthy, then the required controllers are\n * bound to the controller using the keys of the `require` property. This binding occurs after all the controllers\n * have been constructed but before `$onInit` is called.\n * If the name of the required controller is the same as the local name (the key), the name can be\n * omitted. For example, `{parentDir: '^^'}` is equivalent to `{parentDir: '^^parentDir'}`.\n * See the {@link $compileProvider#component} helper for an example of how this can be used.\n * If no such required directive(s) can be found, or if the directive does not have a controller, then an error is\n * raised (unless no link function is specified and the required controllers are not being bound to the directive\n * controller, in which case error checking is skipped). The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Identifier name for a reference to the controller in the directive's scope.\n * This allows the controller to be referenced from the directive template. This is especially\n * useful when a directive is used as component, i.e. with an `isolate` scope. It's also possible\n * to use it in a directive without an `isolate` / `new` scope, but you need to be aware that the\n * `controllerAs` reference might overwrite a property that already exists on the parent scope.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n *   top-level elements such as `<svg>` or `<math>`.\n * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).\n * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved.  In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}.\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace`\n * <div class=\"alert alert-danger\">\n * **Note:** `replace` is deprecated in AngularJS and has been removed in the new Angular (v2+).\n * </div>\n *\n * Specifies what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and\n * stack overflow errors.\n *\n * This can be avoided by manually using `$compile` in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-danger\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - the directive's required controller instance(s) - Instances are shared\n *     among all directives, which allows the directives to use the controllers as a communication\n *     channel. The exact value depends on the directive's `require` property:\n *       * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one\n *       * `string`: the controller instance\n *       * `array`: array of controller instances\n *\n *     If a required controller cannot be found, and it is optional, the instance is `null`,\n *     otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.\n *\n *     Note that you can also require the directive's own controller - it will be made available like\n *     any other controller.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     This is the same as the `$transclude` parameter of directive controllers,\n *     see {@link ng.$compile#-controller- the controller section for details}.\n *     `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM elements from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * There are three kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element, the entire element or multiple parts of the element contents:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that are defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n * * **`{...}` (an object hash):** - map elements of the content onto transclusion \"slots\" in the template.\n *\n * **Multi-slot transclusion** is declared by providing an object for the `transclude` property.\n *\n * This object is a map where the keys are the name of the slot to fill and the value is an element selector\n * used to match the HTML to the slot. The element selector should be in normalized form (e.g. `myElement`)\n * and will match the standard element variants (e.g. `my-element`, `my:element`, `data-my-element`, etc).\n *\n * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}.\n *\n * If the element selector is prefixed with a `?` then that slot is optional.\n *\n * For example, the transclude object `{ slotA: '?myCustomElement' }` maps `<my-custom-element>` elements to\n * the `slotA` slot, which can be accessed via the `$transclude` function or via the {@link ngTransclude} directive.\n *\n * Slots that are not marked as optional (`?`) will trigger a compile time error if there are no matching elements\n * in the transclude content. If you wish to know if an optional slot was filled with content, then you can call\n * `$transclude.isSlotFilled(slotName)` on the transclude function passed to the directive's link function and\n * injectable into the directive's controller.\n *\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n * <div class=\"alert alert-info\">\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n * </div>\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, which the clone will be linked to.\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n * </div>\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n *   element.append(clone);\n *   transcludedContent = clone;\n *   transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n * <div class=\"alert alert-info\">\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n * </div>\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transcluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n * <div ng-app>\n *   <div isolate>\n *     <div transclusion>\n *     </div>\n *   </div>\n * </div>\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n   ```\n   - $rootScope\n     - isolate\n       - transclusion\n   ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n   ```\n   - $rootScope\n     - transclusion\n   - isolate\n   ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * * *Accessing normalized attribute names:* Directives like `ngBind` can be expressed in many ways:\n *   `ng:bind`, `data-ng-bind`, or `x-ng-bind`. The attributes object allows for normalized access\n *   to the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\" name=\"compile\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // Configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects '$compile'.\n        $compileProvider.directive('compile', function($compile) {\n          // The directive factory creates a link function.\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                // Watch the 'compile' expression for changes.\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // When the 'compile' expression changes\n                // assign it into the current DOM.\n                element.html(value);\n\n                // Compile the new DOM and link it to the current scope.\n                // NOTE: we only compile '.childNodes' so that we\n                // don't get into an infinite loop compiling ourselves.\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'AngularJS';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br/>\n      <textarea ng-model=\"html\"></textarea> <br/>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello AngularJS'.\n       expect(output.getText()).toBe('Hello AngularJS');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('AngularJS!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n * <div class=\"alert alert-danger\">\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n *   e.g. will not use the right outer scope. Please pass the transclude function as a\n *   `parentBoundTranscludeFn` to the link function instead.\n * </div>\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br/> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n *  * `options` - An optional object hash with linking options. If `options` is provided, then the following\n *  keys may be used to control linking behavior:\n *\n *      * `parentBoundTranscludeFn` - the transclude function made available to\n *        directives; if given, it will be passed through to the link functions of\n *        directives found in `element` during compilation.\n *      * `transcludeControllers` - an object hash with keys that map controller names\n *        to a hash with the key `instance`, which maps to the controller instance;\n *        if given, it will make the controllers available to directives on the compileNode:\n *        ```\n *        {\n *          parent: {\n *            instance: parentControllerInstance\n *          }\n *        }\n *        ```\n *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n *        the cloned elements; only needed for transcludes that are allowed to contain non HTML\n *        elements (e.g. SVG elements). See also the `directive.controller` property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to `$digest`, which typically is done by\n * AngularJS automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = angular.element('<p>{{total}}</p>');\n *     $compile(element)(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone either via the `cloneAttachFn` or the value returned by the\n *   linking function:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>');\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       // Attach the clone to DOM document at the right place.\n *     });\n *\n *     // Now we have reference to the cloned DOM via `clonedElement`.\n *     // NOTE: The `clonedElement` returned by the linking function is the same as the\n *     //       `clonedElement` passed to `cloneAttachFn`.\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler AngularJS HTML Compiler} section of the Developer Guide.\n *\n * @knownIssue\n *\n * ### Double Compilation\n *\n   Double compilation occurs when an already compiled part of the DOM gets\n   compiled again. This is an undesired effect and can lead to misbehaving directives, performance issues,\n   and memory leaks. Refer to the Compiler Guide {@link guide/compiler#double-compilation-and-how-to-avoid-it\n   section on double compilation} for an in-depth explanation and ways to avoid it.\n\n * @knownIssue\n\n   ### Issues with `replace: true`\n *\n * <div class=\"alert alert-danger\">\n *   **Note**: {@link $compile#-replace- `replace: true`} is deprecated and not recommended to use,\n *   mainly due to the issues listed here. It has been completely removed in the new Angular.\n * </div>\n *\n * #### Attribute values are not merged\n *\n * When a `replace` directive encounters the same attribute on the original and the replace node,\n * it will simply deduplicate the attribute and join the values with a space or with a `;` in case of\n * the `style` attribute.\n * ```html\n * Original Node: <span class=\"original\" style=\"color: red;\"></span>\n * Replace Template: <span class=\"replaced\" style=\"background: blue;\"></span>\n * Result: <span class=\"original replaced\" style=\"color: red; background: blue;\"></span>\n * ```\n *\n * That means attributes that contain AngularJS expressions will not be merged correctly, e.g.\n * {@link ngShow} or {@link ngClass} will cause a {@link $parse} error:\n *\n * ```html\n * Original Node: <span ng-class=\"{'something': something}\" ng-show=\"!condition\"></span>\n * Replace Template: <span ng-class=\"{'else': else}\" ng-show=\"otherCondition\"></span>\n * Result: <span ng-class=\"{'something': something} {'else': else}\" ng-show=\"!condition otherCondition\"></span>\n * ```\n *\n * See issue [#5695](https://github.com/angular/angular.js/issues/5695).\n *\n * #### Directives are not deduplicated before compilation\n *\n * When the original node and the replace template declare the same directive(s), they will be\n * {@link guide/compiler#double-compilation-and-how-to-avoid-it compiled twice} because the compiler\n * does not deduplicate them. In many cases, this is not noticeable, but e.g. {@link ngModel} will\n * attach `$formatters` and `$parsers` twice.\n *\n * See issue [#2573](https://github.com/angular/angular.js/issues/2573).\n *\n * #### `transclude: element` in the replace template root can have unexpected effects\n *\n * When the replace template has a directive at the root node that uses\n * {@link $compile#-transclude- `transclude: element`}, e.g.\n * {@link ngIf} or {@link ngRepeat}, the DOM structure or scope inheritance can be incorrect.\n * See the following issues:\n *\n * - Incorrect scope on replaced element:\n * [#9837](https://github.com/angular/angular.js/issues/9837)\n * - Different DOM between `template` and `templateUrl`:\n * [#10612](https://github.com/angular/angular.js/issues/14326)\n *\n */\n\n/**\n * @ngdoc directive\n * @name ngProp\n * @restrict A\n * @element ANY\n *\n * @usage\n *\n * ```html\n * <ANY ng-prop-propname=\"expression\">\n * </ANY>\n * ```\n *\n * or with uppercase letters in property (e.g. \"propName\"):\n *\n *\n * ```html\n * <ANY ng-prop-prop_name=\"expression\">\n * </ANY>\n * ```\n *\n *\n * @description\n * The `ngProp` directive binds an expression to a DOM element property.\n * `ngProp` allows writing to arbitrary properties by including\n * the property name in the attribute, e.g. `ng-prop-value=\"'my value'\"` binds 'my value' to\n * the `value` property.\n *\n * Usually, it's not necessary to write to properties in AngularJS, as the built-in directives\n * handle the most common use cases (instead of the above example, you would use {@link ngValue}).\n *\n * However, [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements)\n * often use custom properties to hold data, and `ngProp` can be used to provide input to these\n * custom elements.\n *\n * ## Binding to camelCase properties\n *\n * Since HTML attributes are case-insensitive, camelCase properties like `innerHTML` must be escaped.\n * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so\n * `innerHTML`  must be written as `ng-prop-inner_h_t_m_l=\"expression\"` (Note that this is just an\n * example, and for binding HTML {@link ngBindHtml} should be used.\n *\n * ## Security\n *\n * Binding expressions to arbitrary properties poses a security risk, as  properties like `innerHTML`\n * can insert potentially dangerous HTML into the application, e.g. script tags that execute\n * malicious code.\n * For this reason, `ngProp` applies Strict Contextual Escaping with the {@link ng.$sce $sce service}.\n * This means vulnerable properties require their content to be \"trusted\", based on the\n * context of the property. For example, the `innerHTML` is in the `HTML` context, and the\n * `iframe.src` property is in the `RESOURCE_URL` context, which requires that values written to\n * this property are trusted as a `RESOURCE_URL`.\n *\n * This can be set explicitly by calling $sce.trustAs(type, value) on the value that is\n * trusted before passing it to the `ng-prop-*` directive. There are exist shorthand methods for\n * each context type in the form of {@link ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl()} et al.\n *\n * In some cases you can also rely upon automatic sanitization of untrusted values - see below.\n *\n * Based on the context, other options may exist to mark a value as trusted / configure the behavior\n * of {@link ng.$sce}. For example, to restrict the `RESOURCE_URL` context to specific origins, use\n * the {@link $sceDelegateProvider#trustedResourceUrlList trustedResourceUrlList()}\n * and {@link $sceDelegateProvider#bannedResourceUrlList bannedResourceUrlList()}.\n *\n * {@link ng.$sce#what-trusted-context-types-are-supported- Find out more about the different context types}.\n *\n * ### HTML Sanitization\n *\n * By default, `$sce` will throw an error if it detects untrusted HTML content, and will not bind the\n * content.\n * However, if you include the {@link ngSanitize ngSanitize module}, it will try to sanitize the\n * potentially dangerous HTML, e.g. strip non-trusted tags and attributes when binding to\n * `innerHTML`.\n *\n * @example\n * ### Binding to different contexts\n *\n * <example name=\"ngProp\" module=\"exampleNgProp\">\n *   <file name=\"app.js\">\n *     angular.module('exampleNgProp', [])\n *       .component('main', {\n *         templateUrl: 'main.html',\n *         controller: function($sce) {\n *           this.safeContent = '<strong>Safe content</strong>';\n *           this.unsafeContent = '<button onclick=\"alert(\\'Hello XSS!\\')\">Click for XSS</button>';\n *           this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent);\n *         }\n *       });\n *   </file>\n *   <file name=\"main.html\">\n *     <div>\n *       <div class=\"prop-unit\">\n *         Binding to a property without security context:\n *         <div class=\"prop-binding\" ng-prop-inner_text=\"$ctrl.safeContent\"></div>\n *         <span class=\"prop-note\">innerText</span> (safeContent)\n *       </div>\n *\n *       <div class=\"prop-unit\">\n *         \"Safe\" content that requires a security context will throw because the contents could potentially be dangerous ...\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.safeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (safeContent)\n *       </div>\n *\n *       <div class=\"prop-unit\">\n *         ... so that actually dangerous content cannot be executed:\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.unsafeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (unsafeContent)\n *       </div>\n *\n *       <div class=\"prop-unit\">\n *         ... but unsafe Content that has been trusted explicitly works - only do this if you are 100% sure!\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.trustedUnsafeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (trustedUnsafeContent)\n *       </div>\n *     </div>\n *   </file>\n *   <file name=\"index.html\">\n *     <main></main>\n *   </file>\n *   <file name=\"styles.css\">\n *     .prop-unit {\n *       margin-bottom: 10px;\n *     }\n *\n *     .prop-binding {\n *       min-height: 30px;\n *       border: 1px solid blue;\n *     }\n *\n *     .prop-note {\n *       font-family: Monospace;\n *     }\n *   </file>\n * </example>\n *\n *\n * @example\n * ### Binding to innerHTML with ngSanitize\n *\n * <example name=\"ngProp\" module=\"exampleNgProp\" deps=\"angular-sanitize.js\">\n *   <file name=\"app.js\">\n *     angular.module('exampleNgProp', ['ngSanitize'])\n *       .component('main', {\n *         templateUrl: 'main.html',\n *         controller: function($sce) {\n *           this.safeContent = '<strong>Safe content</strong>';\n *           this.unsafeContent = '<button onclick=\"alert(\\'Hello XSS!\\')\">Click for XSS</button>';\n *           this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent);\n *         }\n *       });\n *   </file>\n *   <file name=\"main.html\">\n *     <div>\n *       <div class=\"prop-unit\">\n *         \"Safe\" content will be sanitized ...\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.safeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (safeContent)\n *       </div>\n *\n *       <div class=\"prop-unit\">\n *         ... as will dangerous content:\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.unsafeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (unsafeContent)\n *       </div>\n *\n *       <div class=\"prop-unit\">\n *         ... and content that has been trusted explicitly works the same as without ngSanitize:\n *         <div class=\"prop-binding\" ng-prop-inner_h_t_m_l=\"$ctrl.trustedUnsafeContent\"></div>\n *         <span class=\"prop-note\">innerHTML</span> (trustedUnsafeContent)\n *       </div>\n *     </div>\n *   </file>\n *   <file name=\"index.html\">\n *     <main></main>\n *   </file>\n *   <file name=\"styles.css\">\n *     .prop-unit {\n *       margin-bottom: 10px;\n *     }\n *\n *     .prop-binding {\n *       min-height: 30px;\n *       border: 1px solid blue;\n *     }\n *\n *     .prop-note {\n *       font-family: Monospace;\n *     }\n *   </file>\n * </example>\n *\n */\n\n/** @ngdoc directive\n * @name ngOn\n * @restrict A\n * @element ANY\n *\n * @usage\n *\n * ```html\n * <ANY ng-on-eventname=\"expression\">\n * </ANY>\n * ```\n *\n * or with uppercase letters in property (e.g. \"eventName\"):\n *\n *\n * ```html\n * <ANY ng-on-event_name=\"expression\">\n * </ANY>\n * ```\n *\n * @description\n * The `ngOn` directive adds an event listener to a DOM element via\n * {@link angular.element angular.element().on()}, and evaluates an expression when the event is\n * fired.\n * `ngOn` allows adding listeners for arbitrary events by including\n * the event name in the attribute, e.g. `ng-on-drop=\"onDrop()\"` executes the 'onDrop()' expression\n * when the `drop` event is fired.\n *\n * AngularJS provides specific directives for many events, such as {@link ngClick}, so in most\n * cases it is not necessary to use `ngOn`. However, AngularJS does not support all events\n * (e.g. the `drop` event in the example above), and new events might be introduced in later DOM\n * standards.\n *\n * Another use-case for `ngOn` is listening to\n * [custom events](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events)\n * fired by\n * [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements).\n *\n * ## Binding to camelCase properties\n *\n * Since HTML attributes are case-insensitive, camelCase properties like `myEvent` must be escaped.\n * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so\n * `myEvent` must be written as `ng-on-my_event=\"expression\"`.\n *\n * @example\n * ### Bind to built-in DOM events\n *\n * <example name=\"ngOn\" module=\"exampleNgOn\">\n *   <file name=\"app.js\">\n *     angular.module('exampleNgOn', [])\n *       .component('main', {\n *         templateUrl: 'main.html',\n *         controller: function() {\n *           this.clickCount = 0;\n *           this.mouseoverCount = 0;\n *\n *           this.loadingState = 0;\n *         }\n *       });\n *   </file>\n *   <file name=\"main.html\">\n *     <div>\n *       This is equivalent to `ngClick` and `ngMouseover`:<br>\n *       <button\n *         ng-on-click=\"$ctrl.clickCount = $ctrl.clickCount + 1\"\n *         ng-on-mouseover=\"$ctrl.mouseoverCount = $ctrl.mouseoverCount + 1\">Click or mouseover</button><br>\n *       clickCount: {{$ctrl.clickCount}}<br>\n *       mouseover: {{$ctrl.mouseoverCount}}\n *\n *       <hr>\n *\n *       For the `error` and `load` event on images no built-in AngularJS directives exist:<br>\n *       <img src=\"thisimagedoesnotexist.png\" ng-on-error=\"$ctrl.loadingState = -1\" ng-on-load=\"$ctrl.loadingState = 1\"><br>\n *       <div ng-switch=\"$ctrl.loadingState\">\n *         <span ng-switch-when=\"0\">Image is loading</span>\n *         <span ng-switch-when=\"-1\">Image load error</span>\n *         <span ng-switch-when=\"1\">Image loaded successfully</span>\n *       </div>\n *     </div>\n *   </file>\n *   <file name=\"index.html\">\n *     <main></main>\n *   </file>\n * </example>\n *\n *\n * @example\n * ### Bind to custom DOM events\n *\n * <example name=\"ngOnCustom\" module=\"exampleNgOn\">\n *   <file name=\"app.js\">\n *     angular.module('exampleNgOn', [])\n *       .component('main', {\n *         templateUrl: 'main.html',\n *         controller: function() {\n *           this.eventLog = '';\n *\n *           this.listener = function($event) {\n *             this.eventLog = 'Event with type \"' + $event.type + '\" fired at ' + $event.detail;\n *           };\n *         }\n *       })\n *       .component('childComponent', {\n *         templateUrl: 'child.html',\n *         controller: function($element) {\n *           this.fireEvent = function() {\n *             var event = new CustomEvent('customtype', { detail: new Date()});\n *\n *             $element[0].dispatchEvent(event);\n *           };\n *         }\n *       });\n *   </file>\n *   <file name=\"main.html\">\n *     <child-component ng-on-customtype=\"$ctrl.listener($event)\"></child-component><br>\n *     <span>Event log: {{$ctrl.eventLog}}</span>\n *   </file>\n *   <file name=\"child.html\">\n      <button ng-click=\"$ctrl.fireEvent()\">Fire custom event</button>\n *   </file>\n *   <file name=\"index.html\">\n *     <main></main>\n *   </file>\n * </example>\n */\n\nvar $compileMinErr = minErr('$compile');\n\nfunction UNINITIALIZED_VALUE() {}\nvar _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE();\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\n/** @this */\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive:\\s*([\\w-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\w-]+)(?::([^;]+))?;?)/,\n      ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n      REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n  var bindingCache = createMap();\n\n  function parseIsolateBindings(scope, directiveName, isController) {\n    var LOCAL_REGEXP = /^([@&]|[=<](\\*?))(\\??)\\s*([\\w$]*)$/;\n\n    var bindings = createMap();\n\n    forEach(scope, function(definition, scopeName) {\n      definition = definition.trim();\n\n      if (definition in bindingCache) {\n        bindings[scopeName] = bindingCache[definition];\n        return;\n      }\n      var match = definition.match(LOCAL_REGEXP);\n\n      if (!match) {\n        throw $compileMinErr('iscp',\n            'Invalid {3} for directive \\'{0}\\'.' +\n            ' Definition: {... {1}: \\'{2}\\' ...}',\n            directiveName, scopeName, definition,\n            (isController ? 'controller bindings definition' :\n            'isolate scope definition'));\n      }\n\n      bindings[scopeName] = {\n        mode: match[1][0],\n        collection: match[2] === '*',\n        optional: match[3] === '?',\n        attrName: match[4] || scopeName\n      };\n      if (match[4]) {\n        bindingCache[definition] = bindings[scopeName];\n      }\n    });\n\n    return bindings;\n  }\n\n  function parseDirectiveBindings(directive, directiveName) {\n    var bindings = {\n      isolateScope: null,\n      bindToController: null\n    };\n    if (isObject(directive.scope)) {\n      if (directive.bindToController === true) {\n        bindings.bindToController = parseIsolateBindings(directive.scope,\n                                                         directiveName, true);\n        bindings.isolateScope = {};\n      } else {\n        bindings.isolateScope = parseIsolateBindings(directive.scope,\n                                                     directiveName, false);\n      }\n    }\n    if (isObject(directive.bindToController)) {\n      bindings.bindToController =\n          parseIsolateBindings(directive.bindToController, directiveName, true);\n    }\n    if (bindings.bindToController && !directive.controller) {\n      // There is no controller\n      throw $compileMinErr('noctrl',\n            'Cannot bind to controller without directive \\'{0}\\'s controller.',\n            directiveName);\n    }\n    return bindings;\n  }\n\n  function assertValidDirectiveName(name) {\n    var letter = name.charAt(0);\n    if (!letter || letter !== lowercase(letter)) {\n      throw $compileMinErr('baddir', 'Directive/Component name \\'{0}\\' is invalid. The first character must be a lowercase letter', name);\n    }\n    if (name !== name.trim()) {\n      throw $compileMinErr('baddir',\n            'Directive/Component name \\'{0}\\' is invalid. The name should not contain leading or trailing whitespaces',\n            name);\n    }\n  }\n\n  function getDirectiveRequire(directive) {\n    var require = directive.require || (directive.controller && directive.name);\n\n    if (!isArray(require) && isObject(require)) {\n      forEach(require, function(value, key) {\n        var match = value.match(REQUIRE_PREFIX_REGEXP);\n        var name = value.substring(match[0].length);\n        if (!name) require[key] = match[0] + key;\n      });\n    }\n\n    return require;\n  }\n\n  function getDirectiveRestrict(restrict, name) {\n    if (restrict && !(isString(restrict) && /[EACM]/.test(restrict))) {\n      throw $compileMinErr('badrestrict',\n          'Restrict property \\'{0}\\' of directive \\'{1}\\' is invalid',\n          restrict,\n          name);\n    }\n\n    return restrict || 'EA';\n  }\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. `ngBind` which will match\n   *    as `ng-bind`), or an object map of directives where the keys are the names and the values\n   *    are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See the\n   *    {@link guide/directive directive guide} and the {@link $compile compile API} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n  this.directive = function registerDirective(name, directiveFactory) {\n    assertArg(name, 'name');\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertValidDirectiveName(name);\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = getDirectiveRequire(directive);\n                directive.restrict = getDirectiveRestrict(directive.restrict, name);\n                directive.$$moduleName = directiveFactory.$$moduleName;\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#component\n   * @module ng\n   * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),\n   *    or an object map of components where the keys are the names and the values are the component definition objects.\n   * @param {Object} options Component definition object (a simplified\n   *    {@link ng.$compile#directive-definition-object directive definition object}),\n   *    with the following properties (all optional):\n   *\n   *    - `controller` – `{(string|function()=}` – controller constructor function that should be\n   *      associated with newly created scope or the name of a {@link ng.$compile#-controller-\n   *      registered controller} if passed as a string. An empty `noop` function by default.\n   *    - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.\n   *      If present, the controller will be published to scope under the `controllerAs` name.\n   *      If not present, this will default to be `$ctrl`.\n   *    - `template` – `{string=|function()=}` – html template as a string or a function that\n   *      returns an html template as a string which should be used as the contents of this component.\n   *      Empty string by default.\n   *\n   *      If `template` is a function, then it is {@link auto.$injector#invoke injected} with\n   *      the following locals:\n   *\n   *      - `$element` - Current element\n   *      - `$attrs` - Current attributes object for the element\n   *\n   *    - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html\n   *      template that should be used  as the contents of this component.\n   *\n   *      If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with\n   *      the following locals:\n   *\n   *      - `$element` - Current element\n   *      - `$attrs` - Current attributes object for the element\n   *\n   *    - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.\n   *      Component properties are always bound to the component controller and not to the scope.\n   *      See {@link ng.$compile#-bindtocontroller- `bindToController`}.\n   *    - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.\n   *      Disabled by default.\n   *    - `require` - `{Object<string, string>=}` - requires the controllers of other directives and binds them to\n   *      this component's controller. The object keys specify the property names under which the required\n   *      controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}.\n   *    - `$...` – additional properties to attach to the directive factory function and the controller\n   *      constructor function. (This is used by the component router to annotate)\n   *\n   * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls.\n   * @description\n   * Register a **component definition** with the compiler. This is a shorthand for registering a special\n   * type of directive, which represents a self-contained UI component in your application. Such components\n   * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`).\n   *\n   * Component definitions are very simple and do not require as much configuration as defining general\n   * directives. Component definitions usually consist only of a template and a controller backing it.\n   *\n   * In order to make the definition easier, components enforce best practices like use of `controllerAs`,\n   * `bindToController`. They always have **isolate scope** and are restricted to elements.\n   *\n   * Here are a few examples of how you would usually define components:\n   *\n   * ```js\n   *   var myMod = angular.module(...);\n   *   myMod.component('myComp', {\n   *     template: '<div>My name is {{$ctrl.name}}</div>',\n   *     controller: function() {\n   *       this.name = 'shahar';\n   *     }\n   *   });\n   *\n   *   myMod.component('myComp', {\n   *     template: '<div>My name is {{$ctrl.name}}</div>',\n   *     bindings: {name: '@'}\n   *   });\n   *\n   *   myMod.component('myComp', {\n   *     templateUrl: 'views/my-comp.html',\n   *     controller: 'MyCtrl',\n   *     controllerAs: 'ctrl',\n   *     bindings: {name: '@'}\n   *   });\n   *\n   * ```\n   * For more examples, and an in-depth guide, see the {@link guide/component component guide}.\n   *\n   * <br />\n   * See also {@link ng.$compileProvider#directive $compileProvider.directive()}.\n   */\n  this.component = function registerComponent(name, options) {\n    if (!isString(name)) {\n      forEach(name, reverseParams(bind(this, registerComponent)));\n      return this;\n    }\n\n    var controller = options.controller || function() {};\n\n    function factory($injector) {\n      function makeInjectable(fn) {\n        if (isFunction(fn) || isArray(fn)) {\n          return /** @this */ function(tElement, tAttrs) {\n            return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});\n          };\n        } else {\n          return fn;\n        }\n      }\n\n      var template = (!options.template && !options.templateUrl ? '' : options.template);\n      var ddo = {\n        controller: controller,\n        controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',\n        template: makeInjectable(template),\n        templateUrl: makeInjectable(options.templateUrl),\n        transclude: options.transclude,\n        scope: {},\n        bindToController: options.bindings || {},\n        restrict: 'E',\n        require: options.require\n      };\n\n      // Copy annotations (starting with $) over to the DDO\n      forEach(options, function(val, key) {\n        if (key.charAt(0) === '$') ddo[key] = val;\n      });\n\n      return ddo;\n    }\n\n    // TODO(pete) remove the following `forEach` before we release 1.6.0\n    // The component-router@0.2.0 looks for the annotations on the controller constructor\n    // Nothing in AngularJS looks for annotations on the factory function but we can't remove\n    // it from 1.5.x yet.\n\n    // Copy any annotation properties (starting with $) over to the factory and controller constructor functions\n    // These could be used by libraries such as the new component router\n    forEach(options, function(val, key) {\n      if (key.charAt(0) === '$') {\n        factory[key] = val;\n        // Don't try to copy over annotations to named controller\n        if (isFunction(controller)) controller[key] = val;\n      }\n    });\n\n    factory.$inject = ['$injector'];\n\n    return this.directive(name, factory);\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationTrustedUrlList\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for determining trusted safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationTrustedUrlList`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to trust urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationTrustedUrlList = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationTrustedUrlList(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationTrustedUrlList();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @deprecated\n   * sinceVersion=\"1.8.1\"\n   *\n   * This method is deprecated. Use {@link $compileProvider#aHrefSanitizationTrustedUrlList\n   * aHrefSanitizationTrustedUrlList} instead.\n   */\n  Object.defineProperty(this, 'aHrefSanitizationWhitelist', {\n    get: function() {\n      return this.aHrefSanitizationTrustedUrlList;\n    },\n    set: function(value) {\n      this.aHrefSanitizationTrustedUrlList = value;\n    }\n  });\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationTrustedUrlList\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for determining trusted safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationTrustedUrlList`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to trust urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationTrustedUrlList = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @deprecated\n   * sinceVersion=\"1.8.1\"\n   *\n   * This method is deprecated. Use {@link $compileProvider#imgSrcSanitizationTrustedUrlList\n   * imgSrcSanitizationTrustedUrlList} instead.\n   */\n  Object.defineProperty(this, 'imgSrcSanitizationWhitelist', {\n    get: function() {\n      return this.imgSrcSanitizationTrustedUrlList;\n    },\n    set: function(value) {\n      this.imgSrcSanitizationTrustedUrlList = value;\n    }\n  });\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#debugInfoEnabled\n   *\n   * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n   * current debugInfoEnabled state\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable/disable various debug runtime information in the compiler such as adding\n   * binding information and a reference to the current scope on to DOM elements.\n   * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n   * * `ng-binding` CSS class\n   * * `ng-scope` and `ng-isolated-scope` CSS classes\n   * * `$binding` data property containing an array of the binding expressions\n   * * Data properties used by the {@link angular.element#methods `scope()`/`isolateScope()` methods} to return\n   *   the element's scope.\n   * * Placeholder comments will contain information about what directive and binding caused the placeholder.\n   *   E.g. `<!-- ngIf: shouldShow() -->`.\n   *\n   * You may want to disable this in production for a significant performance boost. See\n   * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n   *\n   * The default value is true.\n   */\n  var debugInfoEnabled = true;\n  this.debugInfoEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      debugInfoEnabled = enabled;\n      return this;\n    }\n    return debugInfoEnabled;\n  };\n\n  /**\n   * @ngdoc method\n   * @name  $compileProvider#strictComponentBindingsEnabled\n   *\n   * @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided,\n   * otherwise return the current strictComponentBindingsEnabled state.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   *\n   * @kind function\n   *\n   * @description\n   * Call this method to enable / disable the strict component bindings check. If enabled, the\n   * compiler will enforce that all scope / controller bindings of a\n   * {@link $compileProvider#directive directive} / {@link $compileProvider#component component}\n   * that are not set as optional with `?`, must be provided when the directive is instantiated.\n   * If not provided, the compiler will throw the\n   * {@link error/$compile/missingattr $compile:missingattr error}.\n   *\n   * The default value is false.\n   */\n  var strictComponentBindingsEnabled = false;\n  this.strictComponentBindingsEnabled = function(enabled) {\n    if (isDefined(enabled)) {\n      strictComponentBindingsEnabled = enabled;\n      return this;\n    }\n    return strictComponentBindingsEnabled;\n  };\n\n  var TTL = 10;\n  /**\n   * @ngdoc method\n   * @name $compileProvider#onChangesTtl\n   * @description\n   *\n   * Sets the number of times `$onChanges` hooks can trigger new changes before giving up and\n   * assuming that the model is unstable.\n   *\n   * The current default is 10 iterations.\n   *\n   * In complex applications it's possible that dependencies between `$onChanges` hooks and bindings will result\n   * in several iterations of calls to these hooks. However if an application needs more than the default 10\n   * iterations to stabilize then you should investigate what is causing the model to continuously change during\n   * the `$onChanges` hook execution.\n   *\n   * Increasing the TTL could have performance implications, so you should not change it without proper justification.\n   *\n   * @param {number} limit The number of `$onChanges` hook iterations.\n   * @returns {number|object} the current limit (or `this` if called as a setter for chaining)\n   */\n  this.onChangesTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n      return this;\n    }\n    return TTL;\n  };\n\n  var commentDirectivesEnabledConfig = true;\n  /**\n   * @ngdoc method\n   * @name $compileProvider#commentDirectivesEnabled\n   * @description\n   *\n   * It indicates to the compiler\n   * whether or not directives on comments should be compiled.\n   * Defaults to `true`.\n   *\n   * Calling this function with false disables the compilation of directives\n   * on comments for the whole application.\n   * This results in a compilation performance gain,\n   * as the compiler doesn't have to check comments when looking for directives.\n   * This should however only be used if you are sure that no comment directives are used in\n   * the application (including any 3rd party directives).\n   *\n   * @param {boolean} enabled `false` if the compiler may ignore directives on comments\n   * @returns {boolean|object} the current value (or `this` if called as a setter for chaining)\n   */\n  this.commentDirectivesEnabled = function(value) {\n    if (arguments.length) {\n      commentDirectivesEnabledConfig = value;\n      return this;\n    }\n    return commentDirectivesEnabledConfig;\n  };\n\n\n  var cssClassDirectivesEnabledConfig = true;\n  /**\n   * @ngdoc method\n   * @name $compileProvider#cssClassDirectivesEnabled\n   * @description\n   *\n   * It indicates to the compiler\n   * whether or not directives on element classes should be compiled.\n   * Defaults to `true`.\n   *\n   * Calling this function with false disables the compilation of directives\n   * on element classes for the whole application.\n   * This results in a compilation performance gain,\n   * as the compiler doesn't have to check element classes when looking for directives.\n   * This should however only be used if you are sure that no class directives are used in\n   * the application (including any 3rd party directives).\n   *\n   * @param {boolean} enabled `false` if the compiler may ignore directives on element classes\n   * @returns {boolean|object} the current value (or `this` if called as a setter for chaining)\n   */\n  this.cssClassDirectivesEnabled = function(value) {\n    if (arguments.length) {\n      cssClassDirectivesEnabledConfig = value;\n      return this;\n    }\n    return cssClassDirectivesEnabledConfig;\n  };\n\n\n  /**\n   * The security context of DOM Properties.\n   * @private\n   */\n  var PROP_CONTEXTS = createMap();\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#addPropertySecurityContext\n   * @description\n   *\n   * Defines the security context for DOM properties bound by ng-prop-*.\n   *\n   * @param {string} elementName The element name or '*' to match any element.\n   * @param {string} propertyName The DOM property name.\n   * @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL`\n   * @returns {object} `this` for chaining\n   */\n  this.addPropertySecurityContext = function(elementName, propertyName, ctx) {\n    var key = (elementName.toLowerCase() + '|' + propertyName.toLowerCase());\n\n    if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) {\n      throw $compileMinErr('ctxoverride', 'Property context \\'{0}.{1}\\' already set to \\'{2}\\', cannot override to \\'{3}\\'.', elementName, propertyName, PROP_CONTEXTS[key], ctx);\n    }\n\n    PROP_CONTEXTS[key] = ctx;\n    return this;\n  };\n\n  /* Default property contexts.\n   *\n   * Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58\n   * Changing:\n   * - SecurityContext.* => SCE_CONTEXTS/$sce.*\n   * - STYLE => CSS\n   * - various URL => MEDIA_URL\n   * - *|formAction, form|action URL => RESOURCE_URL (like the attribute)\n   */\n  (function registerNativePropertyContexts() {\n    function registerContext(ctx, values) {\n      forEach(values, function(v) { PROP_CONTEXTS[v.toLowerCase()] = ctx; });\n    }\n\n    registerContext(SCE_CONTEXTS.HTML, [\n      'iframe|srcdoc',\n      '*|innerHTML',\n      '*|outerHTML'\n    ]);\n    registerContext(SCE_CONTEXTS.CSS, ['*|style']);\n    registerContext(SCE_CONTEXTS.URL, [\n      'area|href',       'area|ping',\n      'a|href',          'a|ping',\n      'blockquote|cite',\n      'body|background',\n      'del|cite',\n      'input|src',\n      'ins|cite',\n      'q|cite'\n    ]);\n    registerContext(SCE_CONTEXTS.MEDIA_URL, [\n      'audio|src',\n      'img|src',    'img|srcset',\n      'source|src', 'source|srcset',\n      'track|src',\n      'video|src',  'video|poster'\n    ]);\n    registerContext(SCE_CONTEXTS.RESOURCE_URL, [\n      '*|formAction',\n      'applet|code',      'applet|codebase',\n      'base|href',\n      'embed|src',\n      'frame|src',\n      'form|action',\n      'head|profile',\n      'html|manifest',\n      'iframe|src',\n      'link|href',\n      'media|src',\n      'object|codebase',  'object|data',\n      'script|src'\n    ]);\n  })();\n\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n            '$controller', '$rootScope', '$sce', '$animate',\n    function($injector,   $interpolate,   $exceptionHandler,   $templateRequest,   $parse,\n             $controller,   $rootScope,   $sce,   $animate) {\n\n    var SIMPLE_ATTR_NAME = /^\\w/;\n    var specialAttrHolder = window.document.createElement('div');\n\n\n    var commentDirectivesEnabled = commentDirectivesEnabledConfig;\n    var cssClassDirectivesEnabled = cssClassDirectivesEnabledConfig;\n\n\n    var onChangesTtl = TTL;\n    // The onChanges hooks should all be run together in a single digest\n    // When changes occur, the call to trigger their hooks will be added to this queue\n    var onChangesQueue;\n\n    // This function is called in a $$postDigest to trigger all the onChanges hooks in a single digest\n    function flushOnChangesQueue() {\n      try {\n        if (!(--onChangesTtl)) {\n          // We have hit the TTL limit so reset everything\n          onChangesQueue = undefined;\n          throw $compileMinErr('infchng', '{0} $onChanges() iterations reached. Aborting!\\n', TTL);\n        }\n        // We must run this hook in an apply since the $$postDigest runs outside apply\n        $rootScope.$apply(function() {\n          for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) {\n            try {\n              onChangesQueue[i]();\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          // Reset the queue to trigger a new schedule next time there is a change\n          onChangesQueue = undefined;\n        });\n      } finally {\n        onChangesTtl++;\n      }\n    }\n\n\n    function sanitizeSrcset(value, invokeType) {\n      if (!value) {\n        return value;\n      }\n      if (!isString(value)) {\n        throw $compileMinErr('srcset', 'Can\\'t pass trusted values to `{0}`: \"{1}\"', invokeType, value.toString());\n      }\n\n      // Such values are a bit too complex to handle automatically inside $sce.\n      // Instead, we sanitize each of the URIs individually, which works, even dynamically.\n\n      // It's not possible to work around this using `$sce.trustAsMediaUrl`.\n      // If you want to programmatically set explicitly trusted unsafe URLs, you should use\n      // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the\n      // `ng-bind-html` directive.\n\n      var result = '';\n\n      // first check if there are spaces because it's not the same pattern\n      var trimmedSrcset = trim(value);\n      //                (   999x   ,|   999w   ,|   ,|,   )\n      var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n      var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n      // split srcset into tuple of uri and descriptor except for the last item\n      var rawUris = trimmedSrcset.split(pattern);\n\n      // for each tuples\n      var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n      for (var i = 0; i < nbrUrisWith2parts; i++) {\n        var innerIdx = i * 2;\n        // sanitize the uri\n        result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));\n        // add the descriptor\n        result += ' ' + trim(rawUris[innerIdx + 1]);\n      }\n\n      // split the last item into uri and descriptor\n      var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n      // sanitize the last uri\n      result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));\n\n      // and add the last descriptor if any\n      if (lastTuple.length === 2) {\n        result += (' ' + trim(lastTuple[1]));\n      }\n      return result;\n    }\n\n\n    function Attributes(element, attributesToCopy) {\n      if (attributesToCopy) {\n        var keys = Object.keys(attributesToCopy);\n        var i, l, key;\n\n        for (i = 0, l = keys.length; i < l; i++) {\n          key = keys[i];\n          this[key] = attributesToCopy[key];\n        }\n      } else {\n        this.$attr = {};\n      }\n\n      this.$$element = element;\n    }\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass: function(classVal) {\n        if (classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass: function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        if (toAdd && toAdd.length) {\n          $animate.addClass(this.$$element, toAdd);\n        }\n\n        var toRemove = tokenDifference(oldClasses, newClasses);\n        if (toRemove && toRemove.length) {\n          $animate.removeClass(this.$$element, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        // is set through this function since it may cause $updateClass to\n        // become unstable.\n\n        var node = this.$$element[0],\n            booleanKey = getBooleanAttrName(node, key),\n            aliasedKey = getAliasedAttrName(key),\n            observer = key,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        } else if (aliasedKey) {\n          this[aliasedKey] = value;\n          observer = aliasedKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        // Sanitize img[srcset] values.\n        if (nodeName === 'img' && key === 'srcset') {\n          this[key] = value = sanitizeSrcset(value, '$set(\\'srcset\\', value)');\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || isUndefined(value)) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            if (SIMPLE_ATTR_NAME.test(attrName)) {\n              // jQuery skips special boolean attrs treatment in XML nodes for\n              // historical reasons and hence AngularJS cannot freely call\n              // `.attr(attrName, false) with such attributes. To avoid issues\n              // in XHTML, call `removeAttr` in such cases instead.\n              // See https://github.com/jquery/jquery/issues/4249\n              if (booleanKey && value === false) {\n                this.$$element.removeAttr(attrName);\n              } else {\n                this.$$element.attr(attrName, value);\n              }\n            } else {\n              setSpecialAttr(this.$$element[0], attrName, value);\n            }\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        if ($$observers) {\n          forEach($$observers[observer], function(fn) {\n            try {\n              fn(value);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          });\n        }\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation\n       *        guide} for more info.\n       * @returns {function()} Returns a deregistration function for this observer.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n\n        return function() {\n          arrayRemove(listeners, fn);\n        };\n      }\n    };\n\n    function setSpecialAttr(element, attrName, value) {\n      // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute`\n      // so we have to jump through some hoops to get such an attribute\n      // https://github.com/angular/angular.js/pull/13318\n      specialAttrHolder.innerHTML = '<span ' + attrName + '>';\n      var attributes = specialAttrHolder.firstChild.attributes;\n      var attribute = attributes[0];\n      // We have to remove the attribute from its container element before we can add it to the destination element\n      attributes.removeNamedItem(attribute.name);\n      attribute.value = value;\n      element.attributes.setNamedItem(attribute);\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch (e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol === '{{' && endSymbol  === '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_PREFIX_BINDING = /^ng(Attr|Prop|On)([A-Z].*)$/;\n    var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;\n\n    compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n      var bindings = $element.data('$binding') || [];\n\n      if (isArray(binding)) {\n        bindings = bindings.concat(binding);\n      } else {\n        bindings.push(binding);\n      }\n\n      $element.data('$binding', bindings);\n    } : noop;\n\n    compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n      safeAddClass($element, 'ng-binding');\n    } : noop;\n\n    compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n      var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n      $element.data(dataName, scope);\n    } : noop;\n\n    compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n      safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n    } : noop;\n\n    compile.$$createComment = function(directiveName, comment) {\n      var content = '';\n      if (debugInfoEnabled) {\n        content = ' ' + (directiveName || '') + ': ';\n        if (comment) content += comment + ' ';\n      }\n      return window.document.createComment(content);\n    };\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      compile.$$addScopeClass($compileNodes);\n      var namespace = null;\n      return function publicLinkFn(scope, cloneConnectFn, options) {\n        if (!$compileNodes) {\n          throw $compileMinErr('multilink', 'This element has already been linked.');\n        }\n        assertArg(scope, 'scope');\n\n        if (previousCompileContext && previousCompileContext.needsNewScope) {\n          // A parent directive did a replace and a directive on this element asked\n          // for transclusion, which caused us to lose a layer of element on which\n          // we could hold the new transclusion scope, so we will create it manually\n          // here.\n          scope = scope.$parent.$new();\n        }\n\n        options = options || {};\n        var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n          transcludeControllers = options.transcludeControllers,\n          futureParentElement = options.futureParentElement;\n\n        // When `parentBoundTranscludeFn` is passed, it is a\n        // `controllersBoundTransclude` function (it was previously passed\n        // as `transclude` to directive.link) so we must unwrap it to get\n        // its `boundTranscludeFn`\n        if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n          parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n        }\n\n        if (!namespace) {\n          namespace = detectNamespaceForChildElements(futureParentElement);\n        }\n        var $linkNode;\n        if (namespace !== 'html') {\n          // When using a directive with replace:true and templateUrl the $compileNodes\n          // (or a child element inside of them)\n          // might change, so we need to recreate the namespace adapted compileNodes\n          // for call to the link function.\n          // Note: This will already clone the nodes...\n          $linkNode = jqLite(\n            wrapTemplate(namespace, jqLite('<div></div>').append($compileNodes).html())\n          );\n        } else if (cloneConnectFn) {\n          // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n          // and sometimes changes the structure of the DOM.\n          $linkNode = JQLitePrototype.clone.call($compileNodes);\n        } else {\n          $linkNode = $compileNodes;\n        }\n\n        if (transcludeControllers) {\n          for (var controllerName in transcludeControllers) {\n            $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n          }\n        }\n\n        compile.$$addScopeInfo($linkNode, scope);\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n\n        if (!cloneConnectFn) {\n          $compileNodes = compositeLinkFn = null;\n        }\n        return $linkNode;\n      };\n    }\n\n    function detectNamespaceForChildElements(parentElement) {\n      // TODO: Make this detect MathML as well...\n      var node = parentElement && parentElement[0];\n      if (!node) {\n        return 'html';\n      } else {\n        return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html';\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          // `nodeList` can be either an element's `.childNodes` (live NodeList)\n          // or a jqLite/jQuery collection or an array\n          notLiveList = isArray(nodeList) || (nodeList instanceof jqLite),\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // Support: IE 11 only\n        // Workaround for #11781 and #14924\n        if (msie === 11) {\n          mergeConsecutiveTextNodes(nodeList, i, notLiveList);\n        }\n\n        // We must always refer to `nodeList[i]` hereafter,\n        // since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          compile.$$addScopeClass(attrs.$$element);\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        if (nodeLinkFn || childLinkFn) {\n          linkFns.push(i, nodeLinkFn, childLinkFn);\n          linkFnFound = true;\n          nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n        }\n\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n        var stableNodeList;\n\n\n        if (nodeLinkFnFound) {\n          // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n          // offsets don't get screwed up\n          var nodeListLength = nodeList.length;\n          stableNodeList = new Array(nodeListLength);\n\n          // create a sparse array by only copying the elements which have a linkFn\n          for (i = 0; i < linkFns.length; i += 3) {\n            idx = linkFns[i];\n            stableNodeList[idx] = nodeList[idx];\n          }\n        } else {\n          stableNodeList = nodeList;\n        }\n\n        for (i = 0, ii = linkFns.length; i < ii;) {\n          node = stableNodeList[linkFns[i++]];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              compile.$$addScopeInfo(jqLite(node), childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if (nodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(\n                  scope, nodeLinkFn.transclude, parentBoundTranscludeFn);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function mergeConsecutiveTextNodes(nodeList, idx, notLiveList) {\n      var node = nodeList[idx];\n      var parent = node.parentNode;\n      var sibling;\n\n      if (node.nodeType !== NODE_TYPE_TEXT) {\n        return;\n      }\n\n      while (true) {\n        sibling = parent ? node.nextSibling : nodeList[idx + 1];\n        if (!sibling || sibling.nodeType !== NODE_TYPE_TEXT) {\n          break;\n        }\n\n        node.nodeValue = node.nodeValue + sibling.nodeValue;\n\n        if (sibling.parentNode) {\n          sibling.parentNode.removeChild(sibling);\n        }\n        if (notLiveList && sibling === nodeList[idx + 1]) {\n          nodeList.splice(idx + 1, 1);\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {\n      function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new(false, containingScope);\n          transcludedScope.$$transcluded = true;\n        }\n\n        return transcludeFn(transcludedScope, cloneFn, {\n          parentBoundTranscludeFn: previousBoundTranscludeFn,\n          transcludeControllers: controllers,\n          futureParentElement: futureParentElement\n        });\n      }\n\n      // We need  to attach the transclusion slots onto the `boundTranscludeFn`\n      // so that they are available inside the `controllersBoundTransclude` function\n      var boundSlots = boundTranscludeFn.$$slots = createMap();\n      for (var slotName in transcludeFn.$$slots) {\n        if (transcludeFn.$$slots[slotName]) {\n          boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);\n        } else {\n          boundSlots[slotName] = null;\n        }\n      }\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          nodeName,\n          className;\n\n      switch (nodeType) {\n        case NODE_TYPE_ELEMENT: /* Element */\n\n          nodeName = nodeName_(node);\n\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            var isNgAttr = false, isNgProp = false, isNgEvent = false;\n            var multiElementMatch;\n\n            attr = nAttrs[j];\n            name = attr.name;\n            value = attr.value;\n\n            nName = directiveNormalize(name.toLowerCase());\n\n            // Support ng-attr-*, ng-prop-* and ng-on-*\n            if ((ngPrefixMatch = nName.match(NG_PREFIX_BINDING))) {\n              isNgAttr = ngPrefixMatch[1] === 'Attr';\n              isNgProp = ngPrefixMatch[1] === 'Prop';\n              isNgEvent = ngPrefixMatch[1] === 'On';\n\n              // Normalize the non-prefixed name\n              name = name.replace(PREFIX_REGEXP, '')\n                .toLowerCase()\n                .substr(4 + ngPrefixMatch[1].length).replace(/_(.)/g, function(match, letter) {\n                  return letter.toUpperCase();\n                });\n\n            // Support *-start / *-end multi element directives\n            } else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) {\n              attrStartName = name;\n              attrEndName = name.substr(0, name.length - 5) + 'end';\n              name = name.substr(0, name.length - 6);\n            }\n\n            if (isNgProp || isNgEvent) {\n              attrs[nName] = value;\n              attrsMap[nName] = attr.name;\n\n              if (isNgProp) {\n                addPropertyDirective(node, directives, nName, name);\n              } else {\n                addEventDirective(directives, nName, name);\n              }\n            } else {\n              // Update nName for cases where a prefix was removed\n              // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-*\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n\n              if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                attrs[nName] = value;\n                if (getBooleanAttrName(node, nName)) {\n                  attrs[nName] = true; // presence means true\n                }\n              }\n\n              addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n              addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                            attrEndName);\n            }\n          }\n\n          if (nodeName === 'input' && node.getAttribute('type') === 'hidden') {\n            // Hidden input elements can have strange behaviour when navigating back to the page\n            // This tells the browser not to try to cache and reinstate previous values\n            node.setAttribute('autocomplete', 'off');\n          }\n\n          // use class as directive\n          if (!cssClassDirectivesEnabled) break;\n          className = node.className;\n          if (isObject(className)) {\n              // Maybe SVGAnimatedString\n              className = className.animVal;\n          }\n          if (isString(className) && className !== '') {\n            while ((match = CLASS_DIRECTIVE_REGEXP.exec(className))) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case NODE_TYPE_TEXT: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case NODE_TYPE_COMMENT: /* Comment */\n          if (!commentDirectivesEnabled) break;\n          collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective);\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    function collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      // function created because of performance, try/catch disables\n      // the optimization of the whole function #14848\n      try {\n        var match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n        if (match) {\n          var nName = directiveNormalize(match[1]);\n          if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n            attrs[nName] = trim(match[2]);\n          }\n        }\n      } catch (e) {\n        // turns out that under some circumstances IE9 throws errors when one attempts to read\n        // comment's node value.\n        // Just ignore it and continue. (Can't seem to reproduce in test case.)\n      }\n    }\n\n    /**\n     * Given a node with a directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      'Unterminated attribute, found \\'{0}\\' but no matching \\'{1}\\' found.',\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType === NODE_TYPE_ELEMENT) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function groupedElementsLink(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * A function generator that is used to support both eager and lazy compilation\n     * linking function.\n     * @param eager\n     * @param $compileNodes\n     * @param transcludeFn\n     * @param maxPriority\n     * @param ignoreDirective\n     * @param previousCompileContext\n     * @returns {Function}\n     */\n    function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {\n      var compiled;\n\n      if (eager) {\n        return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);\n      }\n      return /** @this */ function lazyCompilation() {\n        if (!compiled) {\n          compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);\n\n          // Null out all of these references in order to make them eligible for garbage collection\n          // since this is a potentially long lived closure\n          $compileNodes = transcludeFn = previousCompileContext = null;\n        }\n        return compiled.apply(this, arguments);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective = previousCompileContext.newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          didScanForMultipleTransclusion = false,\n          mightHaveMultipleTransclusionError = false,\n          directiveValue;\n\n      // executes all directives on the current element\n      for (var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        directiveValue = directive.scope;\n\n        if (directiveValue) {\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            if (isObject(directiveValue)) {\n              // This directive is trying to add an isolated scope.\n              // Check that there is no scope of any kind already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n                                directive, $compileNode);\n              newIsolateScopeDirective = directive;\n            } else {\n              // This directive is trying to add a child scope.\n              // Check that there is no isolated scope already\n              assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                                $compileNode);\n            }\n          }\n\n          newScopeDirective = newScopeDirective || directive;\n        }\n\n        directiveName = directive.name;\n\n        // If we encounter a condition that can result in transclusion on the directive,\n        // then scan ahead in the remaining directives for others that may cause a multiple\n        // transclusion error to be thrown during the compilation process.  If a matching directive\n        // is found, then we know that when we encounter a transcluded directive, we need to eagerly\n        // compile the `transclude` function rather than doing it lazily in order to throw\n        // exceptions at the correct time\n        if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))\n            || (directive.transclude && !directive.$$tlb))) {\n                var candidateDirective;\n\n                for (var scanningIndex = i + 1; (candidateDirective = directives[scanningIndex++]);) {\n                    if ((candidateDirective.transclude && !candidateDirective.$$tlb)\n                        || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {\n                        mightHaveMultipleTransclusionError = true;\n                        break;\n                    }\n                }\n\n                didScanForMultipleTransclusion = true;\n        }\n\n        if (!directive.templateUrl && directive.controller) {\n          controllerDirectives = controllerDirectives || createMap();\n          assertNoDuplicate('\\'' + directiveName + '\\' controller',\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        directiveValue = directive.transclude;\n\n        if (directiveValue) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue === 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(compile.$$createComment(directiveName, templateAttrs[directiveName]));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n\n            var slots = createMap();\n\n            if (!isObject(directiveValue)) {\n              $template = jqLite(jqLiteClone(compileNode)).contents();\n            } else {\n\n              // We have transclusion slots,\n              // collect them up, compile them and store their transclusion functions\n              $template = window.document.createDocumentFragment();\n\n              var slotMap = createMap();\n              var filledSlots = createMap();\n\n              // Parse the element selectors\n              forEach(directiveValue, function(elementSelector, slotName) {\n                // If an element selector starts with a ? then it is optional\n                var optional = (elementSelector.charAt(0) === '?');\n                elementSelector = optional ? elementSelector.substring(1) : elementSelector;\n\n                slotMap[elementSelector] = slotName;\n\n                // We explicitly assign `null` since this implies that a slot was defined but not filled.\n                // Later when calling boundTransclusion functions with a slot name we only error if the\n                // slot is `undefined`\n                slots[slotName] = null;\n\n                // filledSlots contains `true` for all slots that are either optional or have been\n                // filled. This is used to check that we have not missed any required slots\n                filledSlots[slotName] = optional;\n              });\n\n              // Add the matching elements into their slot\n              forEach($compileNode.contents(), function(node) {\n                var slotName = slotMap[directiveNormalize(nodeName_(node))];\n                if (slotName) {\n                  filledSlots[slotName] = true;\n                  slots[slotName] = slots[slotName] || window.document.createDocumentFragment();\n                  slots[slotName].appendChild(node);\n                } else {\n                  $template.appendChild(node);\n                }\n              });\n\n              // Check for required slots that were not filled\n              forEach(filledSlots, function(filled, slotName) {\n                if (!filled) {\n                  throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);\n                }\n              });\n\n              for (var slotName in slots) {\n                if (slots[slotName]) {\n                  // Only define a transclusion function if the slot was filled\n                  var slotCompileNodes = jqLite(slots[slotName].childNodes);\n                  slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slotCompileNodes, transcludeFn);\n                }\n              }\n\n              $template = jqLite($template.childNodes);\n            }\n\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,\n                undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});\n            childTranscludeFn.$$slots = slots;\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length !== 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  'Template for directive \\'{0}\\' must have exactly one root element. {1}',\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective || newScopeDirective) {\n              // The original directive caused the current element to be replaced but this element\n              // also needs to have a new scope, so we need to tell the template directives\n              // that they would need to get their scope from further up, if they require transclusion\n              markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          // eslint-disable-next-line no-func-assign\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            var context = directive.$$originalDirective || directive;\n            if (isFunction(linkFn)) {\n              addLinkFns(null, bind(context, linkFn), attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,\n            attrs, scopeBindingInfo;\n\n        if (compileNode === linkNode) {\n          attrs = templateAttrs;\n          $element = templateAttrs.$$element;\n        } else {\n          $element = jqLite(linkNode);\n          attrs = new Attributes($element, templateAttrs);\n        }\n\n        controllerScope = scope;\n        if (newIsolateScopeDirective) {\n          isolateScope = scope.$new(true);\n        } else if (newScopeDirective) {\n          controllerScope = scope.$parent;\n        }\n\n        if (boundTranscludeFn) {\n          // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n          // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n          transcludeFn = controllersBoundTransclude;\n          transcludeFn.$$boundTransclude = boundTranscludeFn;\n          // expose the slots on the `$transclude` function\n          transcludeFn.isSlotFilled = function(slotName) {\n            return !!boundTranscludeFn.$$slots[slotName];\n          };\n        }\n\n        if (controllerDirectives) {\n          elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective);\n        }\n\n        if (newIsolateScopeDirective) {\n          // Initialize isolate scope bindings for new isolate scope directive.\n          compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)));\n          compile.$$addScopeClass($element, true);\n          isolateScope.$$isolateBindings =\n              newIsolateScopeDirective.$$isolateBindings;\n          scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope,\n                                        isolateScope.$$isolateBindings,\n                                        newIsolateScopeDirective);\n          if (scopeBindingInfo.removeWatches) {\n            isolateScope.$on('$destroy', scopeBindingInfo.removeWatches);\n          }\n        }\n\n        // Initialize bindToController bindings\n        for (var name in elementControllers) {\n          var controllerDirective = controllerDirectives[name];\n          var controller = elementControllers[name];\n          var bindings = controllerDirective.$$bindings.bindToController;\n\n          controller.instance = controller();\n          $element.data('$' + controllerDirective.name + 'Controller', controller.instance);\n          controller.bindingInfo =\n            initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);\n          }\n\n        // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy\n        forEach(controllerDirectives, function(controllerDirective, name) {\n          var require = controllerDirective.require;\n          if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {\n            extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));\n          }\n        });\n\n        // Handle the init and destroy lifecycle hooks on all controllers that have them\n        forEach(elementControllers, function(controller) {\n          var controllerInstance = controller.instance;\n          if (isFunction(controllerInstance.$onChanges)) {\n            try {\n              controllerInstance.$onChanges(controller.bindingInfo.initialChanges);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          if (isFunction(controllerInstance.$onInit)) {\n            try {\n              controllerInstance.$onInit();\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          if (isFunction(controllerInstance.$doCheck)) {\n            controllerScope.$watch(function() { controllerInstance.$doCheck(); });\n            controllerInstance.$doCheck();\n          }\n          if (isFunction(controllerInstance.$onDestroy)) {\n            controllerScope.$on('$destroy', function callOnDestroyHook() {\n              controllerInstance.$onDestroy();\n            });\n          }\n        });\n\n        // PRELINKING\n        for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n          linkFn = preLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        if (childLinkFn) {\n          childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n        }\n\n        // POSTLINKING\n        for (i = postLinkFns.length - 1; i >= 0; i--) {\n          linkFn = postLinkFns[i];\n          invokeLinkFn(linkFn,\n              linkFn.isolateScope ? isolateScope : scope,\n              $element,\n              attrs,\n              linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n              transcludeFn\n          );\n        }\n\n        // Trigger $postLink lifecycle hooks\n        forEach(elementControllers, function(controller) {\n          var controllerInstance = controller.instance;\n          if (isFunction(controllerInstance.$postLink)) {\n            controllerInstance.$postLink();\n          }\n        });\n\n        // This is the function that is injected as `$transclude`.\n        // Note: all arguments are optional!\n        function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {\n          var transcludeControllers;\n          // No scope passed in:\n          if (!isScope(scope)) {\n            slotName = futureParentElement;\n            futureParentElement = cloneAttachFn;\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n          if (!futureParentElement) {\n            futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n          }\n          if (slotName) {\n            // slotTranscludeFn can be one of three things:\n            //  * a transclude function - a filled slot\n            //  * `null` - an optional slot that was not filled\n            //  * `undefined` - a slot that was not declared (i.e. invalid)\n            var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];\n            if (slotTranscludeFn) {\n              return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n            } else if (isUndefined(slotTranscludeFn)) {\n              throw $compileMinErr('noslot',\n               'No parent directive that requires a transclusion with slot name \"{0}\". ' +\n               'Element: {1}',\n               slotName, startingTag($element));\n            }\n          } else {\n            return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n          }\n        }\n      }\n    }\n\n    function getControllers(directiveName, require, $element, elementControllers) {\n      var value;\n\n      if (isString(require)) {\n        var match = require.match(REQUIRE_PREFIX_REGEXP);\n        var name = require.substring(match[0].length);\n        var inheritType = match[1] || match[3];\n        var optional = match[2] === '?';\n\n        //If only parents then start at the parent element\n        if (inheritType === '^^') {\n          $element = $element.parent();\n        //Otherwise attempt getting the controller from elementControllers in case\n        //the element is transcluded (and has no data) and to avoid .data if possible\n        } else {\n          value = elementControllers && elementControllers[name];\n          value = value && value.instance;\n        }\n\n        if (!value) {\n          var dataName = '$' + name + 'Controller';\n\n          if (inheritType === '^^' && $element[0] && $element[0].nodeType === NODE_TYPE_DOCUMENT) {\n            // inheritedData() uses the documentElement when it finds the document, so we would\n            // require from the element itself.\n            value = null;\n          } else {\n            value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);\n          }\n        }\n\n        if (!value && !optional) {\n          throw $compileMinErr('ctreq',\n              'Controller \\'{0}\\', required by directive \\'{1}\\', can\\'t be found!',\n              name, directiveName);\n        }\n      } else if (isArray(require)) {\n        value = [];\n        for (var i = 0, ii = require.length; i < ii; i++) {\n          value[i] = getControllers(directiveName, require[i], $element, elementControllers);\n        }\n      } else if (isObject(require)) {\n        value = {};\n        forEach(require, function(controller, property) {\n          value[property] = getControllers(directiveName, controller, $element, elementControllers);\n        });\n      }\n\n      return value || null;\n    }\n\n    function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) {\n      var elementControllers = createMap();\n      for (var controllerKey in controllerDirectives) {\n        var directive = controllerDirectives[controllerKey];\n        var locals = {\n          $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n          $element: $element,\n          $attrs: attrs,\n          $transclude: transcludeFn\n        };\n\n        var controller = directive.controller;\n        if (controller === '@') {\n          controller = attrs[directive.name];\n        }\n\n        var controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n        // For directives with element transclusion the element is a comment.\n        // In this case .data will not attach any data.\n        // Instead, we save the controllers for the element in a local hash and attach to .data\n        // later, once we have the actual element.\n        elementControllers[directive.name] = controllerInstance;\n        $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n      }\n      return elementControllers;\n    }\n\n    // Depending upon the context in which a directive finds itself it might need to have a new isolated\n    // or child scope created. For instance:\n    // * if the directive has been pulled into a template because another directive with a higher priority\n    // asked for element transclusion\n    // * if the directive itself asks for transclusion but it is at the root of a template and the original\n    // element was replaced. See https://github.com/angular/angular.js/issues/12936\n    function markDirectiveScope(directives, isolateScope, newScope) {\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&\n               directive.restrict.indexOf(location) !== -1) {\n            if (startAttrName) {\n              directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n            }\n            if (!directive.$$bindings) {\n              var bindings = directive.$$bindings =\n                  parseDirectiveBindings(directive, directive.name);\n              if (isObject(bindings.isolateScope)) {\n                directive.$$isolateBindings = bindings.isolateScope;\n              }\n            }\n            tDirectives.push(directive);\n            match = directive;\n          }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * looks up the directive and returns true if it is a multi-element directive,\n     * and therefore requires DOM nodes between -start and -end markers to be grouped\n     * together.\n     *\n     * @param {string} name name of the directive to look up.\n     * @returns true if directive was registered as multi-element.\n     */\n    function directiveIsMultiElement(name) {\n      if (hasDirectives.hasOwnProperty(name)) {\n        for (var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i < ii; i++) {\n          directive = directives[i];\n          if (directive.multiElement) {\n            return true;\n          }\n        }\n      }\n      return false;\n    }\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) !== '$') {\n          if (src[key] && src[key] !== value) {\n            if (value.length) {\n              value += (key === 'style' ? ';' : ' ') + src[key];\n            } else {\n              value = src[key];\n            }\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        // Check if we already set this attribute in the loop above.\n        // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n        // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n        // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        if (!dst.hasOwnProperty(key) && key.charAt(0) !== '$') {\n          dst[key] = value;\n\n          if (key !== 'class' && key !== 'style') {\n            dstAttr[key] = srcAttr[key];\n          }\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          derivedSyncDirective = inherit(origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl,\n          templateNamespace = origAsyncDirective.templateNamespace;\n\n      $compileNode.empty();\n\n      $templateRequest(templateUrl)\n        .then(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n            }\n            compileNode = $template[0];\n\n            if ($template.length !== 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n              throw $compileMinErr('tplrt',\n                  'Template for directive \\'{0}\\' must have exactly one root element. {1}',\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              // the original directive that caused the template to be loaded async required\n              // an isolate scope\n              markDirectiveScope(templateDirectives, true);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node === compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while (linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (scope.$$destroyed) continue;\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        }).catch(function(error) {\n          if (isError(error)) {\n            $exceptionHandler(error);\n          }\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (scope.$$destroyed) return;\n        if (linkQueue) {\n          linkQueue.push(scope,\n                         node,\n                         rootElement,\n                         childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n\n      function wrapModuleNameIfDefined(moduleName) {\n        return moduleName ?\n          (' (module: ' + moduleName + ')') :\n          '';\n      }\n\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',\n            previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),\n            directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));\n      }\n    }\n\n\n    function addTextInterpolateDirective(directives, text) {\n      var interpolateFn = $interpolate(text, true);\n      if (interpolateFn) {\n        directives.push({\n          priority: 0,\n          compile: function textInterpolateCompileFn(templateNode) {\n            var templateNodeParent = templateNode.parent(),\n                hasCompileParent = !!templateNodeParent.length;\n\n            // When transcluding a template that has bindings in the root\n            // we don't have a parent and thus need to add the class during linking fn.\n            if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n            return function textInterpolateLinkFn(scope, node) {\n              var parent = node.parent();\n              if (!hasCompileParent) compile.$$addBindingClass(parent);\n              compile.$$addBindingInfo(parent, interpolateFn.expressions);\n              scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                node[0].nodeValue = value;\n              });\n            };\n          }\n        });\n      }\n    }\n\n\n    function wrapTemplate(type, template) {\n      type = lowercase(type || 'html');\n      switch (type) {\n      case 'svg':\n      case 'math':\n        var wrapper = window.document.createElement('div');\n        wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';\n        return wrapper.childNodes[0].childNodes;\n      default:\n        return template;\n      }\n    }\n\n\n    function getTrustedAttrContext(nodeName, attrNormalizedName) {\n      if (attrNormalizedName === 'srcdoc') {\n        return $sce.HTML;\n      }\n      // All nodes with src attributes require a RESOURCE_URL value, except for\n      // img and various html5 media nodes, which require the MEDIA_URL context.\n      if (attrNormalizedName === 'src' || attrNormalizedName === 'ngSrc') {\n        if (['img', 'video', 'audio', 'source', 'track'].indexOf(nodeName) === -1) {\n          return $sce.RESOURCE_URL;\n        }\n        return $sce.MEDIA_URL;\n      } else if (attrNormalizedName === 'xlinkHref') {\n        // Some xlink:href are okay, most aren't\n        if (nodeName === 'image') return $sce.MEDIA_URL;\n        if (nodeName === 'a') return $sce.URL;\n        return $sce.RESOURCE_URL;\n      } else if (\n          // Formaction\n          (nodeName === 'form' && attrNormalizedName === 'action') ||\n          // If relative URLs can go where they are not expected to, then\n          // all sorts of trust issues can arise.\n          (nodeName === 'base' && attrNormalizedName === 'href') ||\n          // links can be stylesheets or imports, which can run script in the current origin\n          (nodeName === 'link' && attrNormalizedName === 'href')\n      ) {\n        return $sce.RESOURCE_URL;\n      } else if (nodeName === 'a' && (attrNormalizedName === 'href' ||\n                                 attrNormalizedName === 'ngHref')) {\n        return $sce.URL;\n      }\n    }\n\n    function getTrustedPropContext(nodeName, propNormalizedName) {\n      var prop = propNormalizedName.toLowerCase();\n      return PROP_CONTEXTS[nodeName + '|' + prop] || PROP_CONTEXTS['*|' + prop];\n    }\n\n    function sanitizeSrcsetPropertyValue(value) {\n      return sanitizeSrcset($sce.valueOf(value), 'ng-prop-srcset');\n    }\n    function addPropertyDirective(node, directives, attrName, propName) {\n      if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) {\n        throw $compileMinErr('nodomevents', 'Property bindings for HTML DOM event properties are disallowed');\n      }\n\n      var nodeName = nodeName_(node);\n      var trustedContext = getTrustedPropContext(nodeName, propName);\n\n      var sanitizer = identity;\n      // Sanitize img[srcset] + source[srcset] values.\n      if (propName === 'srcset' && (nodeName === 'img' || nodeName === 'source')) {\n        sanitizer = sanitizeSrcsetPropertyValue;\n      } else if (trustedContext) {\n        sanitizer = $sce.getTrusted.bind($sce, trustedContext);\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function ngPropCompileFn(_, attr) {\n          var ngPropGetter = $parse(attr[attrName]);\n          var ngPropWatch = $parse(attr[attrName], function sceValueOf(val) {\n            // Unwrap the value to compare the actual inner safe value, not the wrapper object.\n            return $sce.valueOf(val);\n          });\n\n          return {\n            pre: function ngPropPreLinkFn(scope, $element) {\n              function applyPropValue() {\n                var propValue = ngPropGetter(scope);\n                $element[0][propName] = sanitizer(propValue);\n              }\n\n              applyPropValue();\n              scope.$watch(ngPropWatch, applyPropValue);\n            }\n          };\n        }\n      });\n    }\n\n    function addEventDirective(directives, attrName, eventName) {\n      directives.push(\n        createEventDirective($parse, $rootScope, $exceptionHandler, attrName, eventName, /*forceAsync=*/false)\n      );\n    }\n\n    function addAttrInterpolateDirective(node, directives, value, name, isNgAttr) {\n      var nodeName = nodeName_(node);\n      var trustedContext = getTrustedAttrContext(nodeName, name);\n      var mustHaveExpression = !isNgAttr;\n      var allOrNothing = ALL_OR_NOTHING_ATTRS[name] || isNgAttr;\n\n      var interpolateFn = $interpolate(value, mustHaveExpression, trustedContext, allOrNothing);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n      if (name === 'multiple' && nodeName === 'select') {\n        throw $compileMinErr('selmulti',\n            'Binding to the \\'multiple\\' attribute is not supported. Element: {0}',\n            startingTag(node));\n      }\n\n      if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n        throw $compileMinErr('nodomevents', 'Interpolations for HTML DOM event attributes are disallowed');\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = createMap()));\n\n                // If the attribute has changed since last $interpolate()ed\n                var newValue = attr[name];\n                if (newValue !== value) {\n                  // we need to interpolate again since the attribute value has been updated\n                  // (e.g. by another directive's compile function)\n                  // ensure unset/empty values make interpolateFn falsy\n                  interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n                  value = newValue;\n                }\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // initialize attr object so that it's ready in case we need the value for isolate\n                // scope initialization, otherwise the value would not be available from isolate\n                // directive's linking fn during linking phase\n                attr[name] = interpolateFn(scope);\n\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if (name === 'class' && newValue !== oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for (i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] === firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n\n            // If the replaced element is also the jQuery .context then replace it\n            // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n            // http://api.jquery.com/context/\n            if ($rootElement.context === firstElementToRemove) {\n              $rootElement.context = newNode;\n            }\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n\n      // Append all the `elementsToRemove` to a fragment. This will...\n      // - remove them from the DOM\n      // - allow them to still be traversed with .nextSibling\n      // - allow a single fragment.qSA to fetch all elements being removed\n      var fragment = window.document.createDocumentFragment();\n      for (i = 0; i < removeCount; i++) {\n        fragment.appendChild(elementsToRemove[i]);\n      }\n\n      if (jqLite.hasData(firstElementToRemove)) {\n        // Copy over user data (that includes AngularJS's $scope etc.). Don't copy private\n        // data here because there's no public interface in jQuery to do that and copying over\n        // event listeners (which is the main use of private data) wouldn't work anyway.\n        jqLite.data(newNode, jqLite.data(firstElementToRemove));\n\n        // Remove $destroy event listeners from `firstElementToRemove`\n        jqLite(firstElementToRemove).off('$destroy');\n      }\n\n      // Cleanup any data/listeners on the elements and children.\n      // This includes invoking the $destroy event on any elements with listeners.\n      jqLite.cleanData(fragment.querySelectorAll('*'));\n\n      // Update the jqLite collection to only contain the `newNode`\n      for (i = 1; i < removeCount; i++) {\n        delete elementsToRemove[i];\n      }\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n\n\n    function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n      try {\n        linkFn(scope, $element, attrs, controllers, transcludeFn);\n      } catch (e) {\n        $exceptionHandler(e, startingTag($element));\n      }\n    }\n\n    function strictBindingsCheck(attrName, directiveName) {\n      if (strictComponentBindingsEnabled) {\n        throw $compileMinErr('missingattr',\n          'Attribute \\'{0}\\' of \\'{1}\\' is non-optional and must be set!',\n          attrName, directiveName);\n      }\n    }\n\n    // Set up $watches for isolate scope and controller bindings.\n    function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {\n      var removeWatchCollection = [];\n      var initialChanges = {};\n      var changes;\n\n      forEach(bindings, function initializeBinding(definition, scopeName) {\n        var attrName = definition.attrName,\n        optional = definition.optional,\n        mode = definition.mode, // @, =, <, or &\n        lastValue,\n        parentGet, parentSet, compare, removeWatch;\n\n        switch (mode) {\n\n          case '@':\n            if (!optional && !hasOwnProperty.call(attrs, attrName)) {\n              strictBindingsCheck(attrName, directive.name);\n              destination[scopeName] = attrs[attrName] = undefined;\n\n            }\n            removeWatch = attrs.$observe(attrName, function(value) {\n              if (isString(value) || isBoolean(value)) {\n                var oldValue = destination[scopeName];\n                recordChanges(scopeName, value, oldValue);\n                destination[scopeName] = value;\n              }\n            });\n            attrs.$$observers[attrName].$$scope = scope;\n            lastValue = attrs[attrName];\n            if (isString(lastValue)) {\n              // If the attribute has been provided then we trigger an interpolation to ensure\n              // the value is there for use in the link fn\n              destination[scopeName] = $interpolate(lastValue)(scope);\n            } else if (isBoolean(lastValue)) {\n              // If the attributes is one of the BOOLEAN_ATTR then AngularJS will have converted\n              // the value to boolean rather than a string, so we special case this situation\n              destination[scopeName] = lastValue;\n            }\n            initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);\n            removeWatchCollection.push(removeWatch);\n            break;\n\n          case '=':\n            if (!hasOwnProperty.call(attrs, attrName)) {\n              if (optional) break;\n              strictBindingsCheck(attrName, directive.name);\n              attrs[attrName] = undefined;\n            }\n            if (optional && !attrs[attrName]) break;\n\n            parentGet = $parse(attrs[attrName]);\n            if (parentGet.literal) {\n              compare = equals;\n            } else {\n              compare = simpleCompare;\n            }\n            parentSet = parentGet.assign || function() {\n              // reset the change, or we will throw this exception on every $digest\n              lastValue = destination[scopeName] = parentGet(scope);\n              throw $compileMinErr('nonassign',\n                  'Expression \\'{0}\\' in attribute \\'{1}\\' used with directive \\'{2}\\' is non-assignable!',\n                  attrs[attrName], attrName, directive.name);\n            };\n            lastValue = destination[scopeName] = parentGet(scope);\n            var parentValueWatch = function parentValueWatch(parentValue) {\n              if (!compare(parentValue, destination[scopeName])) {\n                // we are out of sync and need to copy\n                if (!compare(parentValue, lastValue)) {\n                  // parent changed and it has precedence\n                  destination[scopeName] = parentValue;\n                } else {\n                  // if the parent can be assigned then do so\n                  parentSet(scope, parentValue = destination[scopeName]);\n                }\n              }\n              lastValue = parentValue;\n              return lastValue;\n            };\n            parentValueWatch.$stateful = true;\n            if (definition.collection) {\n              removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n            } else {\n              removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n            }\n            removeWatchCollection.push(removeWatch);\n            break;\n\n          case '<':\n            if (!hasOwnProperty.call(attrs, attrName)) {\n              if (optional) break;\n              strictBindingsCheck(attrName, directive.name);\n              attrs[attrName] = undefined;\n            }\n            if (optional && !attrs[attrName]) break;\n\n            parentGet = $parse(attrs[attrName]);\n            var isLiteral = parentGet.literal;\n\n            var initialValue = destination[scopeName] = parentGet(scope);\n            initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);\n\n            removeWatch = scope[definition.collection ? '$watchCollection' : '$watch'](parentGet, function parentValueWatchAction(newValue, oldValue) {\n              if (oldValue === newValue) {\n                if (oldValue === initialValue || (isLiteral && equals(oldValue, initialValue))) {\n                  return;\n                }\n                oldValue = initialValue;\n              }\n              recordChanges(scopeName, newValue, oldValue);\n              destination[scopeName] = newValue;\n            });\n\n            removeWatchCollection.push(removeWatch);\n            break;\n\n          case '&':\n            if (!optional && !hasOwnProperty.call(attrs, attrName)) {\n              strictBindingsCheck(attrName, directive.name);\n            }\n            // Don't assign Object.prototype method to scope\n            parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;\n\n            // Don't assign noop to destination if expression is not valid\n            if (parentGet === noop && optional) break;\n\n            destination[scopeName] = function(locals) {\n              return parentGet(scope, locals);\n            };\n            break;\n        }\n      });\n\n      function recordChanges(key, currentValue, previousValue) {\n        if (isFunction(destination.$onChanges) && !simpleCompare(currentValue, previousValue)) {\n          // If we have not already scheduled the top level onChangesQueue handler then do so now\n          if (!onChangesQueue) {\n            scope.$$postDigest(flushOnChangesQueue);\n            onChangesQueue = [];\n          }\n          // If we have not already queued a trigger of onChanges for this controller then do so now\n          if (!changes) {\n            changes = {};\n            onChangesQueue.push(triggerOnChangesHook);\n          }\n          // If the has been a change on this property already then we need to reuse the previous value\n          if (changes[key]) {\n            previousValue = changes[key].previousValue;\n          }\n          // Store this change\n          changes[key] = new SimpleChange(previousValue, currentValue);\n        }\n      }\n\n      function triggerOnChangesHook() {\n        destination.$onChanges(changes);\n        // Now clear the changes so that we schedule onChanges when more changes arrive\n        changes = undefined;\n      }\n\n      return {\n        initialChanges: initialChanges,\n        removeWatches: removeWatchCollection.length && function removeWatches() {\n          for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {\n            removeWatchCollection[i]();\n          }\n        }\n      };\n    }\n  }];\n}\n\nfunction SimpleChange(previous, current) {\n  this.previousValue = previous;\n  this.currentValue = current;\n}\nSimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; };\n\n\nvar PREFIX_REGEXP = /^((?:x|data)[:\\-_])/i;\nvar SPECIAL_CHARS_REGEXP = /[:\\-_]+(.)/g;\n\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return name\n    .replace(PREFIX_REGEXP, '')\n    .replace(SPECIAL_CHARS_REGEXP, function(_, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    });\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in AngularJS:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for (var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for (var j = 0; j < tokens2.length; j++) {\n      if (token === tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\nfunction removeComments(jqNodes) {\n  jqNodes = jqLite(jqNodes);\n  var i = jqNodes.length;\n\n  if (i <= 1) {\n    return jqNodes;\n  }\n\n  while (i--) {\n    var node = jqNodes[i];\n    if (node.nodeType === NODE_TYPE_COMMENT ||\n       (node.nodeType === NODE_TYPE_TEXT && node.nodeValue.trim() === '')) {\n         splice.call(jqNodes, i, 1);\n    }\n  }\n  return jqNodes;\n}\n\nvar $controllerMinErr = minErr('$controller');\n\n\nvar CNTRL_REG = /^(\\S+)(\\s+as\\s+([\\w$]+))?$/;\nfunction identifierForController(controller, ident) {\n  if (ident && isString(ident)) return ident;\n  if (isString(controller)) {\n    var match = CNTRL_REG.exec(controller);\n    if (match) return match[3];\n  }\n}\n\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @this\n *\n * @description\n * The {@link ng.$controller $controller service} is used by AngularJS to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {};\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#has\n   * @param {string} name Controller name to check.\n   */\n  this.has = function(name) {\n    return controllers.hasOwnProperty(name);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *\n     *    The string can use the `controller as property` syntax, where the controller instance is published\n     *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n     *    to work correctly.\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function $controller(expression, locals, later, ident) {\n      // PRIVATE API:\n      //   param `later` --- indicates that the controller's constructor is invoked at a later time.\n      //                     If true, $controller will allocate the object with the correct\n      //                     prototype chain, but will not invoke the controller until a returned\n      //                     callback is invoked.\n      //   param `ident` --- An optional label which overrides the label parsed from the controller\n      //                     expression, if any.\n      var instance, match, constructor, identifier;\n      later = later === true;\n      if (ident && isString(ident)) {\n        identifier = ident;\n      }\n\n      if (isString(expression)) {\n        match = expression.match(CNTRL_REG);\n        if (!match) {\n          throw $controllerMinErr('ctrlfmt',\n            'Badly formed controller string \\'{0}\\'. ' +\n            'Must match `__name__ as __id__` or `__name__`.', expression);\n        }\n        constructor = match[1];\n        identifier = identifier || match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true);\n\n        if (!expression) {\n          throw $controllerMinErr('ctrlreg',\n            'The controller with the name \\'{0}\\' is not registered.', constructor);\n        }\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      if (later) {\n        // Instantiate controller later:\n        // This machinery is used to create an instance of the object before calling the\n        // controller's constructor itself.\n        //\n        // This allows properties to be added to the controller before the constructor is\n        // invoked. Primarily, this is used for isolate scope bindings in $compile.\n        //\n        // This feature is not intended for use by applications, and is thus not documented\n        // publicly.\n        // Object creation: http://jsperf.com/create-constructor/2\n        var controllerPrototype = (isArray(expression) ?\n          expression[expression.length - 1] : expression).prototype;\n        instance = Object.create(controllerPrototype || null);\n\n        if (identifier) {\n          addIdentifier(locals, identifier, instance, constructor || expression.name);\n        }\n\n        return extend(function $controllerInit() {\n          var result = $injector.invoke(expression, instance, locals, constructor);\n          if (result !== instance && (isObject(result) || isFunction(result))) {\n            instance = result;\n            if (identifier) {\n              // If result changed, re-assign controllerAs value to scope.\n              addIdentifier(locals, identifier, instance, constructor || expression.name);\n            }\n          }\n          return instance;\n        }, {\n          instance: instance,\n          identifier: identifier\n        });\n      }\n\n      instance = $injector.instantiate(expression, locals, constructor);\n\n      if (identifier) {\n        addIdentifier(locals, identifier, instance, constructor || expression.name);\n      }\n\n      return instance;\n    };\n\n    function addIdentifier(locals, identifier, instance, name) {\n      if (!(locals && isObject(locals.$scope))) {\n        throw minErr('$controller')('noscp',\n          'Cannot export controller \\'{0}\\' as \\'{1}\\'! No $scope object provided via `locals`.',\n          name, identifier);\n      }\n\n      locals.$scope[identifier] = instance;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n * @this\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\" name=\"document\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider() {\n  this.$get = ['$window', function(window) {\n    return jqLite(window.document);\n  }];\n}\n\n\n/**\n * @private\n * @this\n * Listens for document visibility change and makes the current status accessible.\n */\nfunction $$IsDocumentHiddenProvider() {\n  this.$get = ['$document', '$rootScope', function($document, $rootScope) {\n    var doc = $document[0];\n    var hidden = doc && doc.hidden;\n\n    $document.on('visibilitychange', changeListener);\n\n    $rootScope.$on('$destroy', function() {\n      $document.off('visibilitychange', changeListener);\n    });\n\n    function changeListener() {\n      hidden = doc.hidden;\n    }\n\n    return function() {\n      return hidden;\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n * @this\n *\n * @description\n * Any uncaught exception in AngularJS expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * The example below will overwrite the default `$exceptionHandler` in order to (a) log uncaught\n * errors to the backend for later inspection by the developers and (b) to use `$log.warn()` instead\n * of `$log.error()`.\n *\n * ```js\n *   angular.\n *     module('exceptionOverwrite', []).\n *     factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) {\n *       return function myExceptionHandler(exception, cause) {\n *         logErrorsToBackend(exception, cause);\n *         $log.warn(exception, cause);\n *       };\n *     }]);\n * ```\n *\n * <hr />\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause Optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\nvar $$ForceReflowProvider = /** @this */ function() {\n  this.$get = ['$document', function($document) {\n    return function(domNode) {\n      //the line below will force the browser to perform a repaint so\n      //that all the animated elements within the animation frame will\n      //be properly updated and drawn on screen. This is required to\n      //ensure that the preparation animation is properly flushed so that\n      //the active state picks up from there. DO NOT REMOVE THIS LINE.\n      //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH\n      //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND\n      //WILL TAKE YEARS AWAY FROM YOUR LIFE.\n      if (domNode) {\n        if (!domNode.nodeType && domNode instanceof jqLite) {\n          domNode = domNode[0];\n        }\n      } else {\n        domNode = $document[0].body;\n      }\n      return domNode.offsetWidth + 1;\n    };\n  }];\n};\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n  '[': /]$/,\n  '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)]\\}',?\\n/;\nvar $httpMinErr = minErr('$http');\n\nfunction serializeValue(v) {\n  if (isObject(v)) {\n    return isDate(v) ? v.toISOString() : toJson(v);\n  }\n  return v;\n}\n\n\n/** @this */\nfunction $HttpParamSerializerProvider() {\n  /**\n   * @ngdoc service\n   * @name $httpParamSerializer\n   * @description\n   *\n   * Default {@link $http `$http`} params serializer that converts objects to strings\n   * according to the following rules:\n   *\n   * * `{'foo': 'bar'}` results in `foo=bar`\n   * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)\n   * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)\n   * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object)\n   *\n   * Note that serializer will sort the request parameters alphabetically.\n   */\n\n  this.$get = function() {\n    return function ngParamSerializer(params) {\n      if (!params) return '';\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value) || isFunction(value)) return;\n        if (isArray(value)) {\n          forEach(value, function(v) {\n            parts.push(encodeUriQuery(key)  + '=' + encodeUriQuery(serializeValue(v)));\n          });\n        } else {\n          parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));\n        }\n      });\n\n      return parts.join('&');\n    };\n  };\n}\n\n/** @this */\nfunction $HttpParamSerializerJQLikeProvider() {\n  /**\n   * @ngdoc service\n   * @name $httpParamSerializerJQLike\n   *\n   * @description\n   *\n   * Alternative {@link $http `$http`} params serializer that follows\n   * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.\n   * The serializer will also sort the params alphabetically.\n   *\n   * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:\n   *\n   * ```js\n   * $http({\n   *   url: myUrl,\n   *   method: 'GET',\n   *   params: myParams,\n   *   paramSerializer: '$httpParamSerializerJQLike'\n   * });\n   * ```\n   *\n   * It is also possible to set it as the default `paramSerializer` in the\n   * {@link $httpProvider#defaults `$httpProvider`}.\n   *\n   * Additionally, you can inject the serializer and use it explicitly, for example to serialize\n   * form data for submission:\n   *\n   * ```js\n   * .controller(function($http, $httpParamSerializerJQLike) {\n   *   //...\n   *\n   *   $http({\n   *     url: myUrl,\n   *     method: 'POST',\n   *     data: $httpParamSerializerJQLike(myData),\n   *     headers: {\n   *       'Content-Type': 'application/x-www-form-urlencoded'\n   *     }\n   *   });\n   *\n   * });\n   * ```\n   *\n   */\n  this.$get = function() {\n    return function jQueryLikeParamSerializer(params) {\n      if (!params) return '';\n      var parts = [];\n      serialize(params, '', true);\n      return parts.join('&');\n\n      function serialize(toSerialize, prefix, topLevel) {\n        if (isArray(toSerialize)) {\n          forEach(toSerialize, function(value, index) {\n            serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');\n          });\n        } else if (isObject(toSerialize) && !isDate(toSerialize)) {\n          forEachSorted(toSerialize, function(value, key) {\n            serialize(value, prefix +\n                (topLevel ? '' : '[') +\n                key +\n                (topLevel ? '' : ']'));\n          });\n        } else {\n          if (isFunction(toSerialize)) {\n            toSerialize = toSerialize();\n          }\n          parts.push(encodeUriQuery(prefix) + '=' +\n              (toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize))));\n        }\n      }\n    };\n  };\n}\n\nfunction defaultHttpResponseTransform(data, headers) {\n  if (isString(data)) {\n    // Strip json vulnerability protection prefix and trim whitespace\n    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n    if (tempData) {\n      var contentType = headers('Content-Type');\n      var hasJsonContentType = contentType && (contentType.indexOf(APPLICATION_JSON) === 0);\n\n      if (hasJsonContentType || isJsonLike(tempData)) {\n        try {\n          data = fromJson(tempData);\n        } catch (e) {\n          if (!hasJsonContentType) {\n            return data;\n          }\n          throw $httpMinErr('baddata', 'Data must be a valid JSON object. Received: \"{0}\". ' +\n          'Parse error: \"{1}\"', data, e);\n        }\n      }\n    }\n  }\n\n  return data;\n}\n\nfunction isJsonLike(str) {\n    var jsonStart = str.match(JSON_START);\n    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = createMap(), i;\n\n  function fillInParsed(key, val) {\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  }\n\n  if (isString(headers)) {\n    forEach(headers.split('\\n'), function(line) {\n      i = line.indexOf(':');\n      fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));\n    });\n  } else if (isObject(headers)) {\n    forEach(headers, function(headerVal, headerKey) {\n      fillInParsed(lowercase(headerKey), trim(headerVal));\n    });\n  }\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      var value = headersObj[lowercase(name)];\n      if (value === undefined) {\n        value = null;\n      }\n      return value;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n  if (isFunction(fns)) {\n    return fns(data, headers, status);\n  }\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers, status);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @this\n *\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n */\nfunction $HttpProvider() {\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with\n   * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses\n   * by default. See {@link $http#caching $http Caching} for more information.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   *\n   * - **`defaults.jsonpCallbackParam`** - `{string}` - the name of the query parameter that passes the name of the\n   * callback in a JSONP request. The value of this parameter will be replaced with the expression generated by the\n   * {@link $jsonpCallbacks} service. Defaults to `'callback'`.\n   *\n   * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function\n   *  used to the prepare string representation of request parameters (specified as an object).\n   *  If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.\n   *  Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.\n   *\n   * - **`defaults.transformRequest`** -\n   * `{Array<function(data, headersGetter)>|function(data, headersGetter)}` -\n   * An array of functions (or a single function) which are applied to the request data.\n   * By default, this is an array with one request transformation function:\n   *\n   *   - If the `data` property of the request configuration object contains an object, serialize it\n   *     into JSON format.\n   *\n   * - **`defaults.transformResponse`** -\n   * `{Array<function(data, headersGetter, status)>|function(data, headersGetter, status)}` -\n   * An array of functions (or a single function) which are applied to the response data. By default,\n   * this is an array which applies one response transformation function that does two things:\n   *\n   *  - If XSRF prefix is detected, strip it\n   *    (see {@link ng.$http#security-considerations Security Considerations in the $http docs}).\n   *  - If the `Content-Type` is `application/json` or the response looks like JSON,\n   *    deserialize it using a JSON parser.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   */\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [defaultHttpResponseTransform],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN',\n\n    paramSerializer: '$httpParamSerializer',\n\n    jsonpCallbackParam: 'callback'\n  };\n\n  var useApplyAsync = false;\n  /**\n   * @ngdoc method\n   * @name $httpProvider#useApplyAsync\n   * @description\n   *\n   * Configure $http service to combine processing of multiple http responses received at around\n   * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n   * significant performance improvement for bigger applications that make many HTTP requests\n   * concurrently (common during application bootstrap).\n   *\n   * Defaults to false. If no value is specified, returns the current configured value.\n   *\n   * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n   *    \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n   *    to load and share the same digest cycle.\n   *\n   * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n   *    otherwise, returns the current configured value.\n   */\n  this.useApplyAsync = function(value) {\n    if (isDefined(value)) {\n      useApplyAsync = !!value;\n      return this;\n    }\n    return useApplyAsync;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   */\n  var interceptorFactories = this.interceptors = [];\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#xsrfTrustedOrigins\n   * @description\n   *\n   * Array containing URLs whose origins are trusted to receive the XSRF token. See the\n   * {@link ng.$http#security-considerations Security Considerations} sections for more details on\n   * XSRF.\n   *\n   * **Note:** An \"origin\" consists of the [URI scheme](https://en.wikipedia.org/wiki/URI_scheme),\n   * the [hostname](https://en.wikipedia.org/wiki/Hostname) and the\n   * [port number](https://en.wikipedia.org/wiki/Port_(computer_networking). For `http:` and\n   * `https:`, the port number can be omitted if using th default ports (80 and 443 respectively).\n   * Examples: `http://example.com`, `https://api.example.com:9876`\n   *\n   * <div class=\"alert alert-warning\">\n   *   It is not possible to trust specific URLs/paths. The `path`, `query` and `fragment` parts\n   *   of a URL will be ignored. For example, `https://foo.com/path/bar?query=baz#fragment` will be\n   *   treated as `https://foo.com`, meaning that **all** requests to URLs starting with\n   *   `https://foo.com/` will include the XSRF token.\n   * </div>\n   *\n   * @example\n   *\n   * ```js\n   * // App served from `https://example.com/`.\n   * angular.\n   *   module('xsrfTrustedOriginsExample', []).\n   *   config(['$httpProvider', function($httpProvider) {\n   *     $httpProvider.xsrfTrustedOrigins.push('https://api.example.com');\n   *   }]).\n   *   run(['$http', function($http) {\n   *     // The XSRF token will be sent.\n   *     $http.get('https://api.example.com/preferences').then(...);\n   *\n   *     // The XSRF token will NOT be sent.\n   *     $http.get('https://stats.example.com/activity').then(...);\n   *   }]);\n   * ```\n   */\n  var xsrfTrustedOrigins = this.xsrfTrustedOrigins = [];\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#xsrfWhitelistedOrigins\n   * @description\n   *\n   * @deprecated\n   * sinceVersion=\"1.8.1\"\n   *\n   * This property is deprecated. Use {@link $httpProvider#xsrfTrustedOrigins xsrfTrustedOrigins}\n   * instead.\n   */\n  Object.defineProperty(this, 'xsrfWhitelistedOrigins', {\n    get: function() {\n      return this.xsrfTrustedOrigins;\n    },\n    set: function(origins) {\n      this.xsrfTrustedOrigins = origins;\n    }\n  });\n\n  this.$get = ['$browser', '$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', '$sce',\n      function($browser, $httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector, $sce) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Make sure that default param serializer is exposed as a function\n     */\n    defaults.paramSerializer = isString(defaults.paramSerializer) ?\n      $injector.get(defaults.paramSerializer) : defaults.paramSerializer;\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    /**\n     * A function to check request URLs against a list of allowed origins.\n     */\n    var urlIsAllowedOrigin = urlIsAllowedOriginFactory(xsrfTrustedOrigins);\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core AngularJS service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * ## General usage\n     * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise} that is\n     * resolved (request success) or rejected (request failure) with a\n     * {@link ng.$http#$http-returns response} object.\n     *\n     * ```js\n     *   // Simple GET request example:\n     *   $http({\n     *     method: 'GET',\n     *     url: '/someUrl'\n     *   }).then(function successCallback(response) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }, function errorCallback(response) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     *\n     * ## Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests. An optional config can be passed as the\n     * last argument.\n     *\n     * ```js\n     *   $http.get('/someUrl', config).then(successCallback, errorCallback);\n     *   $http.post('/someUrl', data, config).then(successCallback, errorCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * ## Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * ## Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - <code>Accept: application/json, text/plain, \\*&#65279;/&#65279;\\*</code>\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' }\n     * }\n     *\n     * $http(req).then(function(){...}, function(){...});\n     * ```\n     *\n     * ## Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transformation functions: `transformRequest`\n     * and `transformResponse`. These properties can be a single function that returns\n     * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n     * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n     *\n     * <div class=\"alert alert-warning\">\n     * **Note:** AngularJS does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline.\n     * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference).\n     * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest\n     * function will be reflected on the scope and in any templates where the object is data-bound.\n     * To prevent this, transform functions should have no side-effects.\n     * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return.\n     * </div>\n     *\n     * ### Default Transformations\n     *\n     * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n     * `defaults.transformResponse` properties. If a request does not provide its own transformations\n     * then these will be applied.\n     *\n     * You can augment or replace the default transformations by modifying these properties by adding to or\n     * replacing the array.\n     *\n     * AngularJS provides the following default transformations:\n     *\n     * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`) is\n     * an array with one function that does the following:\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`) is\n     * an array with one function that does the following:\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If the `Content-Type` is `application/json` or the response looks like JSON,\n   *      deserialize it using a JSON parser.\n     *\n     *\n     * ### Overriding the Default Transformations Per Request\n     *\n     * If you wish to override the request/response transformations only for a single request then provide\n     * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n     * into `$http`.\n     *\n     * Note that if you provide these properties on the config object the default transformations will be\n     * overwritten. If you wish to augment the default transformations then you must include them in your\n     * local transformation array.\n     *\n     * The following code demonstrates adding a new response transformation to be run after the default response\n     * transformations have been run.\n     *\n     * ```js\n     * function appendTransform(defaults, transform) {\n     *\n     *   // We can't guarantee that the default transformation is an array\n     *   defaults = angular.isArray(defaults) ? defaults : [defaults];\n     *\n     *   // Append the new transformation to the defaults\n     *   return defaults.concat(transform);\n     * }\n     *\n     * $http({\n     *   url: '...',\n     *   method: 'GET',\n     *   transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n     *     return doTransform(value);\n     *   })\n     * });\n     * ```\n     *\n     *\n     * ## Caching\n     *\n     * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must\n     * set the config.cache value or the default cache value to TRUE or to a cache object (created\n     * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes\n     * precedence over the default cache value.\n     *\n     * In order to:\n     *   * cache all responses - set the default cache value to TRUE or to a cache object\n     *   * cache a specific response - set config.cache value to TRUE or to a cache object\n     *\n     * If caching is enabled, but neither the default cache nor config.cache are set to a cache object,\n     * then the default `$cacheFactory(\"$http\")` object is used.\n     *\n     * The default cache value can be set by updating the\n     * {@link ng.$http#defaults `$http.defaults.cache`} property or the\n     * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property.\n     *\n     * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using\n     * the relevant cache object. The next time the same request is made, the response is returned\n     * from the cache without sending a request to the server.\n     *\n     * Take note that:\n     *\n     *   * Only GET and JSONP requests are cached.\n     *   * The cache key is the request URL including search parameters; headers are not considered.\n     *   * Cached responses are returned asynchronously, in the same way as responses from the server.\n     *   * If multiple identical requests are made using the same cache, which is not yet populated,\n     *     one request will be made to the server and remaining requests will return the same response.\n     *   * A cache-control header on the response does not affect if or how responses are cached.\n     *\n     *\n     * ## Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * ## Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. AngularJS comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ### JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * AngularJS will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * AngularJS will strip the prefix, before processing the JSON.\n     *\n     *\n     * ### Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by\n     * which the attacker can trick an authenticated user into unknowingly executing actions on your\n     * website. AngularJS provides a mechanism to counter XSRF. When performing XHR requests, the\n     * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP\n     * header (by default `X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read\n     * the cookie, your server can be assured that the XHR came from JavaScript running on your\n     * domain.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be\n     * sure that only JavaScript running on your domain could have sent the request. The token must\n     * be unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The header will &mdash; by default &mdash; **not** be set for cross-domain requests. This\n     * prevents unauthorized servers (e.g. malicious or compromised 3rd-party APIs) from gaining\n     * access to your users' XSRF tokens and exposing them to Cross Site Request Forgery. If you\n     * want to, you can trust additional origins to also receive the XSRF token, by adding them\n     * to {@link ng.$httpProvider#xsrfTrustedOrigins xsrfTrustedOrigins}. This might be\n     * useful, for example, if your application, served from `example.com`, needs to access your API\n     * at `api.example.com`.\n     * See {@link ng.$httpProvider#xsrfTrustedOrigins $httpProvider.xsrfTrustedOrigins} for\n     * more details.\n     *\n     * <div class=\"alert alert-danger\">\n     *   **Warning**<br />\n     *   Only trusted origins that you have control over and make sure you understand the\n     *   implications of doing so.\n     * </div>\n     *\n     * The name of the cookie and the header can be specified using the `xsrfCookieName` and\n     * `xsrfHeaderName` properties of either `$httpProvider.defaults` at config-time,\n     * `$http.defaults` at run-time, or the per-request config object.\n     *\n     * In order to prevent collisions in environments where multiple AngularJS apps share the\n     * same domain or subdomain, we recommend that each application uses a unique cookie name.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string|TrustedObject}` – Absolute or relative URL of the resource that is being requested;\n     *      or an object created by a call to `$sce.trustAsResourceUrl(url)`.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized\n     *      with the `paramSerializer` and appended as GET parameters.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent. Functions accept a config object as an argument.\n     *    - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object.\n     *      To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`.\n     *      The handler will be called in the context of a `$apply` block.\n     *    - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload\n     *      object. To bind events to the XMLHttpRequest object, use `eventHandlers`.\n     *      The handler will be called in the context of a `$apply` block.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\n     *    - **transformRequest** –\n     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body, headers and status and returns its transformed (typically deserialized) version.\n     *      See {@link ng.$http#overriding-the-default-transformations-per-request\n     *      Overriding the Default Transformations}\n     *    - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to\n     *      prepare the string representation of request parameters (specified as an object).\n     *      If specified as string, it is interpreted as function registered with the\n     *      {@link $injector $injector}, which means you can create your own serializer\n     *      by registering it as a {@link auto.$provide#service service}.\n     *      The default serializer is the {@link $httpParamSerializer $httpParamSerializer};\n     *      alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}\n     *    - **cache** – `{boolean|Object}` – A boolean value or object created with\n     *      {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response.\n     *      See {@link $http#caching $http Caching} for more information.\n     *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}\n     *      that should abort the request when resolved.\n     *\n     *      A numerical timeout or a promise returned from {@link ng.$timeout $timeout}, will set\n     *      the `xhrStatus` in the {@link $http#$http-returns response} to \"timeout\", and any other\n     *      resolved promise will set it to \"abort\", following standard XMLHttpRequest behavior.\n     *\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).\n     *\n     * @returns {HttpPromise} A {@link ng.$q `Promise}` that will be resolved (request success)\n     *   or rejected (request failure) with a response object.\n     *\n     *   The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with\n     *     the transform functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used\n     *     to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *   - **xhrStatus** – `{string}` – Status of the XMLHttpRequest\n     *     (`complete`, `error`, `timeout` or `abort`).\n     *\n     *\n     *   A response status code between 200 and 299 is considered a success status\n     *   and will result in the success callback being called. Any response status\n     *   code outside of that range is considered an error status and will result\n     *   in the error callback being called.\n     *   Also, status codes less than -1 are normalized to zero. -1 usually means\n     *   the request was aborted, e.g. using a `config.timeout`. More information\n     *   about the status might be available in the `xhrStatus` property.\n     *\n     *   Note that if the response is a redirect, XMLHttpRequest will transparently\n     *   follow it, meaning that the outcome (success or error) will be determined\n     *   by the final response status code.\n     *\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\" name=\"http-service\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\" aria-label=\"Request method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\" aria-label=\"URL\" />\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .config(['$sceDelegateProvider', function($sceDelegateProvider) {\n      // We must add the JSONP endpoint that we are using to the trusted list to show that we trust it\n      $sceDelegateProvider.trustedResourceUrlList([\n        'self',\n        'https://angularjs.org/**'\n      ]);\n    }])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            then(function(response) {\n              $scope.status = response.status;\n              $scope.data = response.data;\n            }, function(response) {\n              $scope.data = response.data || 'Request failed';\n              $scope.status = response.status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n\n      if (!isObject(requestConfig)) {\n        throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);\n      }\n\n      if (!isString($sce.valueOf(requestConfig.url))) {\n        throw minErr('$http')('badreq', 'Http request configuration url must be a string or a $sce trusted object.  Received: {0}', requestConfig.url);\n      }\n\n      var config = extend({\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse,\n        paramSerializer: defaults.paramSerializer,\n        jsonpCallbackParam: defaults.jsonpCallbackParam\n      }, requestConfig);\n\n      config.headers = mergeHeaders(requestConfig);\n      config.method = uppercase(config.method);\n      config.paramSerializer = isString(config.paramSerializer) ?\n          $injector.get(config.paramSerializer) : config.paramSerializer;\n\n      $browser.$$incOutstandingRequestCount('$http');\n\n      var requestInterceptors = [];\n      var responseInterceptors = [];\n      var promise = $q.resolve(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          requestInterceptors.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          responseInterceptors.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      promise = chainInterceptors(promise, requestInterceptors);\n      promise = promise.then(serverRequest);\n      promise = chainInterceptors(promise, responseInterceptors);\n      promise = promise.finally(completeOutstandingRequest);\n\n      return promise;\n\n\n      function chainInterceptors(promise, interceptors) {\n        for (var i = 0, ii = interceptors.length; i < ii;) {\n          var thenFn = interceptors[i++];\n          var rejectFn = interceptors[i++];\n\n          promise = promise.then(thenFn, rejectFn);\n        }\n\n        interceptors.length = 0;\n\n        return promise;\n      }\n\n      function completeOutstandingRequest() {\n        $browser.$$completeOutstandingRequest(noop, '$http');\n      }\n\n      function executeHeaderFns(headers, config) {\n        var headerContent, processedHeaders = {};\n\n        forEach(headers, function(headerFn, header) {\n          if (isFunction(headerFn)) {\n            headerContent = headerFn(config);\n            if (headerContent != null) {\n              processedHeaders[header] = headerContent;\n            }\n          } else {\n            processedHeaders[header] = headerFn;\n          }\n        });\n\n        return processedHeaders;\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unnecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        return executeHeaderFns(reqHeaders, shallowCopy(config));\n      }\n\n      function serverRequest(config) {\n        var headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n              delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData).then(transformResponse, transformResponse);\n      }\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response);\n        resp.data = transformData(response.data, response.headers, response.status,\n                                  config.transformResponse);\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;\n     *                                   or an object created by a call to `$sce.trustAsResourceUrl(url)`.\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;\n     *                                   or an object created by a call to `$sce.trustAsResourceUrl(url)`.\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;\n     *                                   or an object created by a call to `$sce.trustAsResourceUrl(url)`.\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * Note that, since JSONP requests are sensitive because the response is given full access to the browser,\n     * the url must be declared, via {@link $sce} as a trusted resource URL.\n     * You can trust a URL by adding it to the trusted resource URL list via\n     * {@link $sceDelegateProvider#trustedResourceUrlList  `$sceDelegateProvider.trustedResourceUrlList`} or\n     * by explicitly trusting the URL via {@link $sce#trustAsResourceUrl `$sce.trustAsResourceUrl(url)`}.\n     *\n     * You should avoid generating the URL for the JSONP request from user provided data.\n     * Provide additional query parameters via `params` property of the `config` parameter, rather than\n     * modifying the URL itself.\n     *\n     * JSONP requests must specify a callback to be used in the response from the server. This callback\n     * is passed as a query parameter in the request. You must specify the name of this parameter by\n     * setting the `jsonpCallbackParam` property on the request config object.\n     *\n     * ```\n     * $http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'})\n     * ```\n     *\n     * You can also specify a default callback parameter name in `$http.defaults.jsonpCallbackParam`.\n     * Initially this is set to `'callback'`.\n     *\n     * <div class=\"alert alert-danger\">\n     * You can no longer use the `JSON_CALLBACK` string as a placeholder for specifying where the callback\n     * parameter value should go.\n     * </div>\n     *\n     * If you would like to customise where and how the callbacks are stored then try overriding\n     * or decorating the {@link $jsonpCallbacks} service.\n     *\n     * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;\n     *                                   or an object created by a call to `$sce.trustAsResourceUrl(url)`.\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n     * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n     * See {@link ng.$http#$http-returns `$http()` return value}.\n     */\n\n     /**\n      * @ngdoc method\n      * @name $http#patch\n      *\n      * @description\n      * Shortcut method to perform `PATCH` request.\n      *\n      * @param {string} url Relative or absolute URL specifying the destination of the request\n      * @param {*} data Request content\n      * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}.\n      * @returns {HttpPromise}  A Promise that will be resolved or rejected with a response object.\n      * See {@link ng.$http#$http-returns `$http()` return value}.\n      */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n        /**\n         * @ngdoc property\n         * @name $http#defaults\n         *\n         * @description\n         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n         * default headers, withCredentials as well as request and response transformations.\n         *\n         * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n         */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend({}, config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend({}, config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          reqHeaders = config.headers,\n          isJsonp = lowercase(config.method) === 'jsonp',\n          url = config.url;\n\n      if (isJsonp) {\n        // JSONP is a pretty sensitive operation where we're allowing a script to have full access to\n        // our DOM and JS space.  So we require that the URL satisfies SCE.RESOURCE_URL.\n        url = $sce.getTrustedResourceUrl(url);\n      } else if (!isString(url)) {\n        // If it is not a string then the URL must be a $sce trusted object\n        url = $sce.valueOf(url);\n      }\n\n      url = buildUrl(url, config.paramSerializer(config.params));\n\n      if (isJsonp) {\n        // Check the url and add the JSONP callback placeholder\n        url = sanitizeJsonpCallbackParam(url, config.jsonpCallbackParam);\n      }\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n            : isObject(/** @type {?} */ (defaults).cache)\n              ? /** @type {?} */ (defaults).cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3], cachedResp[4]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK', 'complete');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsAllowedOrigin(config.url)\n            ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType,\n            createApplyHandlers(config.eventHandlers),\n            createApplyHandlers(config.uploadEventHandlers));\n      }\n\n      return promise;\n\n      function createApplyHandlers(eventHandlers) {\n        if (eventHandlers) {\n          var applyHandlers = {};\n          forEach(eventHandlers, function(eventHandler, key) {\n            applyHandlers[key] = function(event) {\n              if (useApplyAsync) {\n                $rootScope.$applyAsync(callEventHandler);\n              } else if ($rootScope.$$phase) {\n                callEventHandler();\n              } else {\n                $rootScope.$apply(callEventHandler);\n              }\n\n              function callEventHandler() {\n                eventHandler(event);\n              }\n            };\n          });\n          return applyHandlers;\n        }\n      }\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText, xhrStatus) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText, xhrStatus]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        function resolveHttpPromise() {\n          resolvePromise(response, status, headersString, statusText, xhrStatus);\n        }\n\n        if (useApplyAsync) {\n          $rootScope.$applyAsync(resolveHttpPromise);\n        } else {\n          resolveHttpPromise();\n          if (!$rootScope.$$phase) $rootScope.$apply();\n        }\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText, xhrStatus) {\n        //status: HTTP response status code, 0, -1 (aborted by timeout / promise)\n        status = status >= -1 ? status : 0;\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText: statusText,\n          xhrStatus: xhrStatus\n        });\n      }\n\n      function resolvePromiseWithResult(result) {\n        resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText, result.xhrStatus);\n      }\n\n      function removePendingReq() {\n        var idx = $http.pendingRequests.indexOf(config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, serializedParams) {\n      if (serializedParams.length > 0) {\n        url += ((url.indexOf('?') === -1) ? '?' : '&') + serializedParams;\n      }\n      return url;\n    }\n\n    function sanitizeJsonpCallbackParam(url, cbKey) {\n      var parts = url.split('?');\n      if (parts.length > 2) {\n        // Throw if the url contains more than one `?` query indicator\n        throw $httpMinErr('badjsonp', 'Illegal use more than one \"?\", in url, \"{1}\"', url);\n      }\n      var params = parseKeyValue(parts[1]);\n      forEach(params, function(value, key) {\n        if (value === 'JSON_CALLBACK') {\n          // Throw if the url already contains a reference to JSON_CALLBACK\n          throw $httpMinErr('badjsonp', 'Illegal use of JSON_CALLBACK in url, \"{0}\"', url);\n        }\n        if (key === cbKey) {\n          // Throw if the callback param was already provided\n          throw $httpMinErr('badjsonp', 'Illegal use of callback param, \"{0}\", in url, \"{1}\"', cbKey, url);\n        }\n      });\n\n      // Add in the JSON_CALLBACK callback param value\n      url += ((url.indexOf('?') === -1) ? '?' : '&') + cbKey + '=JSON_CALLBACK';\n\n      return url;\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $xhrFactory\n * @this\n *\n * @description\n * Factory function used to create XMLHttpRequest objects.\n *\n * Replace or decorate this service to create your own custom XMLHttpRequest objects.\n *\n * ```\n * angular.module('myApp', [])\n * .factory('$xhrFactory', function() {\n *   return function createXhr(method, url) {\n *     return new window.XMLHttpRequest({mozSystem: true});\n *   };\n * });\n * ```\n *\n * @param {string} method HTTP method of the request (GET, POST, PUT, ..)\n * @param {string} url URL of the request.\n */\nfunction $xhrFactoryProvider() {\n  this.$get = function() {\n    return function createXhr() {\n      return new window.XMLHttpRequest();\n    };\n  };\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $jsonpCallbacks\n * @requires $document\n * @requires $xhrFactory\n * @this\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$jsonpCallbacks', '$document', '$xhrFactory', function($browser, $jsonpCallbacks, $document, $xhrFactory) {\n    return createHttpBackend($browser, $xhrFactory, $browser.defer, $jsonpCallbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {\n    url = url || $browser.url();\n\n    if (lowercase(method) === 'jsonp') {\n      var callbackPath = callbacks.createCallback(url);\n      var jsonpDone = jsonpReq(url, callbackPath, function(status, text) {\n        // jsonpReq only ever sets status to 200 (OK), 404 (ERROR) or -1 (WAITING)\n        var response = (status === 200) && callbacks.getResponse(callbackPath);\n        completeRequest(callback, status, response, '', text, 'complete');\n        callbacks.removeCallback(callbackPath);\n      });\n    } else {\n\n      var xhr = createXhr(method, url);\n      var abortedByTimeout = false;\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      xhr.onload = function requestLoaded() {\n        var statusText = xhr.statusText || '';\n\n        // responseText is the old-school way of retrieving response (supported by IE9)\n        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n        var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n        var status = xhr.status === 1223 ? 204 : xhr.status;\n\n        // fix status code when it is 0 (0 status is undocumented).\n        // Occurs when accessing file resources or on Android 4.1 stock browser\n        // while retrieving files from application cache.\n        if (status === 0) {\n          status = response ? 200 : urlResolve(url).protocol === 'file' ? 404 : 0;\n        }\n\n        completeRequest(callback,\n            status,\n            response,\n            xhr.getAllResponseHeaders(),\n            statusText,\n            'complete');\n      };\n\n      var requestError = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '', 'error');\n      };\n\n      var requestAborted = function() {\n        completeRequest(callback, -1, null, null, '', abortedByTimeout ? 'timeout' : 'abort');\n      };\n\n      var requestTimeout = function() {\n        // The response is always empty\n        // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n        completeRequest(callback, -1, null, null, '', 'timeout');\n      };\n\n      xhr.onerror = requestError;\n      xhr.ontimeout = requestTimeout;\n      xhr.onabort = requestAborted;\n\n      forEach(eventHandlers, function(value, key) {\n        xhr.addEventListener(key, value);\n      });\n\n      forEach(uploadEventHandlers, function(value, key) {\n        xhr.upload.addEventListener(key, value);\n      });\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(isUndefined(post) ? null : post);\n    }\n\n    // Since we are using xhr.abort() when a request times out, we have to set a flag that\n    // indicates to requestAborted if the request timed out or was aborted.\n    //\n    // http.timeout = numerical timeout   timeout\n    // http.timeout = $timeout            timeout\n    // http.timeout = promise             abort\n    // xhr.abort()                        abort (The xhr object is normally inaccessible, but\n    //                                    can be exposed with the xhrFactory)\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(function() {\n        timeoutRequest('timeout');\n      }, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(function() {\n        timeoutRequest(isDefined(timeout.$$timeoutId) ? 'timeout' : 'abort');\n      });\n    }\n\n    function timeoutRequest(reason) {\n      abortedByTimeout = reason === 'timeout';\n      if (jsonpDone) {\n        jsonpDone();\n      }\n      if (xhr) {\n        xhr.abort();\n      }\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText, xhrStatus) {\n      // cancel timeout and subsequent timeout promise resolution\n      if (isDefined(timeoutId)) {\n        $browserDefer.cancel(timeoutId);\n      }\n      jsonpDone = xhr = null;\n\n      callback(status, response, headersString, statusText, xhrStatus);\n    }\n  };\n\n  function jsonpReq(url, callbackPath, done) {\n    url = url.replace('JSON_CALLBACK', callbackPath);\n    // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = 'text/javascript';\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      script.removeEventListener('load', callback);\n      script.removeEventListener('error', callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = 'unknown';\n\n      if (event) {\n        if (event.type === 'load' && !callbacks.wasCalled(callbackPath)) {\n          event = { type: 'error' };\n        }\n        text = event.type;\n        status = event.type === 'error' ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    script.addEventListener('load', callback);\n    script.addEventListener('error', callback);\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');\n$interpolateMinErr.throwNoconcat = function(text) {\n  throw $interpolateMinErr('noconcat',\n      'Error while interpolating: {0}\\nStrict Contextual Escaping disallows ' +\n      'interpolations that concatenate multiple expressions when a trusted value is ' +\n      'required.  See http://docs.angularjs.org/api/ng.$sce', text);\n};\n\n$interpolateMinErr.interr = function(text, err) {\n  return $interpolateMinErr('interr', 'Can\\'t interpolate: {0}\\n{1}', text, err.toString());\n};\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n * @this\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * <div class=\"alert alert-danger\">\n * This feature is sometimes used to mix different markup languages, e.g. to wrap an AngularJS\n * template within a Python Jinja template (or any other template language). Mixing templating\n * languages is **very dangerous**. The embedding template language will not safely escape AngularJS\n * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)\n * security bugs!\n * </div>\n *\n * @example\n<example name=\"custom-interpolation-markup\" module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value) {\n    if (value) {\n      startSymbol = value;\n      return this;\n    }\n    return startSymbol;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value) {\n    if (value) {\n      endSymbol = value;\n      return this;\n    }\n    return endSymbol;\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length,\n        escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n        escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n    function escape(ch) {\n      return '\\\\\\\\\\\\' + ch;\n    }\n\n    function unescapeText(text) {\n      return text.replace(escapedStartRegexp, startSymbol).\n        replace(escapedEndRegexp, endSymbol);\n    }\n\n    // TODO: this is the same as the constantWatchDelegate in parse.js\n    function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {\n      var unwatch = scope.$watch(function constantInterpolateWatch(scope) {\n        unwatch();\n        return constantInterp(scope);\n      }, listener, objectEquality);\n      return unwatch;\n    }\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'AngularJS'})).toEqual('Hello ANGULARJS!');\n     * ```\n     *\n     * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n     * `true`, the interpolation function will return `undefined` unless all embedded expressions\n     * evaluate to a value other than `undefined`.\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var context = {greeting: 'Hello', name: undefined };\n     *\n     *   // default \"forgiving\" mode\n     *   var exp = $interpolate('{{greeting}} {{name}}!');\n     *   expect(exp(context)).toEqual('Hello !');\n     *\n     *   // \"allOrNothing\" mode\n     *   exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n     *   expect(exp(context)).toBeUndefined();\n     *   context.name = 'AngularJS';\n     *   expect(exp(context)).toEqual('Hello AngularJS!');\n     * ```\n     *\n     * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n     *\n     * #### Escaped Interpolation\n     * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n     * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n     * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n     * or binding.\n     *\n     * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n     * degree, while also enabling code examples to work without relying on the\n     * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n     *\n     * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n     * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all\n     * interpolation start/end markers with their escaped counterparts.**\n     *\n     * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n     * output when the $interpolate service processes the text. So, for HTML elements interpolated\n     * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n     * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n     * this is typically useful only when user-data is used in rendering a template from the server, or\n     * when otherwise untrusted data is used by a directive.\n     *\n     * <example name=\"interpolation\">\n     *  <file name=\"index.html\">\n     *    <div ng-init=\"username='A user'\">\n     *      <p ng-init=\"apptitle='Escaping demo'\">{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n     *        </p>\n     *      <p><strong>{{username}}</strong> attempts to inject code which will deface the\n     *        application, but fails to accomplish their task, because the server has correctly\n     *        escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n     *        characters.</p>\n     *      <p>Instead, the result of the attempted script injection is visible, and can be removed\n     *        from the database by an administrator.</p>\n     *    </div>\n     *  </file>\n     * </example>\n     *\n     * @knownIssue\n     * It is currently not possible for an interpolated expression to contain the interpolation end\n     * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e.\n     * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string.\n     *\n     * @knownIssue\n     * All directives and components must use the standard `{{` `}}` interpolation symbols\n     * in their templates. If you change the application interpolation symbols the {@link $compile}\n     * service will attempt to denormalize the standard symbols to the custom symbols.\n     * The denormalization process is not clever enough to know not to replace instances of the standard\n     * symbols where they would not normally be treated as interpolation symbols. For example in the following\n     * code snippet the closing braces of the literal object will get incorrectly denormalized:\n     *\n     * ```\n     * <div data-context='{\"context\":{\"id\":3,\"type\":\"page\"}}\">\n     * ```\n     *\n     * The workaround is to ensure that such instances are separated by whitespace:\n     * ```\n     * <div data-context='{\"context\":{\"id\":3,\"type\":\"page\"} }\">\n     * ```\n     *\n     * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information.\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n     *    unless all embedded expressions evaluate to a value other than `undefined`.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     * - `context`: evaluation context for all expressions embedded in the interpolated text\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n      var contextAllowsConcatenation = trustedContext === $sce.URL || trustedContext === $sce.MEDIA_URL;\n\n      // Provide a quick exit and simplified result function for text with no interpolation\n      if (!text.length || text.indexOf(startSymbol) === -1) {\n        if (mustHaveExpression) return;\n\n        var unescapedText = unescapeText(text);\n        if (contextAllowsConcatenation) {\n          unescapedText = $sce.getTrusted(trustedContext, unescapedText);\n        }\n        var constantInterp = valueFn(unescapedText);\n        constantInterp.exp = text;\n        constantInterp.expressions = [];\n        constantInterp.$$watchDelegate = constantWatchDelegate;\n\n        return constantInterp;\n      }\n\n      allOrNothing = !!allOrNothing;\n      var startIndex,\n          endIndex,\n          index = 0,\n          expressions = [],\n          parseFns,\n          textLength = text.length,\n          exp,\n          concat = [],\n          expressionPositions = [],\n          singleExpression;\n\n\n      while (index < textLength) {\n        if (((startIndex = text.indexOf(startSymbol, index)) !== -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) !== -1)) {\n          if (index !== startIndex) {\n            concat.push(unescapeText(text.substring(index, startIndex)));\n          }\n          exp = text.substring(startIndex + startSymbolLength, endIndex);\n          expressions.push(exp);\n          index = endIndex + endSymbolLength;\n          expressionPositions.push(concat.length);\n          concat.push(''); // Placeholder that will get replaced with the evaluated expression.\n        } else {\n          // we did not find an interpolation, so we have to add the remainder to the separators array\n          if (index !== textLength) {\n            concat.push(unescapeText(text.substring(index)));\n          }\n          break;\n        }\n      }\n\n      singleExpression = concat.length === 1 && expressionPositions.length === 1;\n      // Intercept expression if we need to stringify concatenated inputs, which may be SCE trusted\n      // objects rather than simple strings\n      // (we don't modify the expression if the input consists of only a single trusted input)\n      var interceptor = contextAllowsConcatenation && singleExpression ? undefined : parseStringifyInterceptor;\n      parseFns = expressions.map(function(exp) { return $parse(exp, interceptor); });\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for some $sce-managed secure contexts (RESOURCE_URLs mostly),\n      // we ensure that the value that's used is assigned or constructed by some JS code somewhere\n      // that is more testable or make it obvious that you bound the value to some user controlled\n      // value.  This helps reduce the load when auditing for XSS issues.\n\n      // Note that URL and MEDIA_URL $sce contexts do not need this, since `$sce` can sanitize the values\n      // passed to it. In that case, `$sce.getTrusted` will be called on either the single expression\n      // or on the overall concatenated string (losing trusted types used in the mix, by design).\n      // Both these methods will sanitize plain strings. Also, HTML could be included, but since it's\n      // only used in srcdoc attributes, this would not be very useful.\n\n      if (!mustHaveExpression || expressions.length) {\n        var compute = function(values) {\n          for (var i = 0, ii = expressions.length; i < ii; i++) {\n            if (allOrNothing && isUndefined(values[i])) return;\n            concat[expressionPositions[i]] = values[i];\n          }\n\n          if (contextAllowsConcatenation) {\n            // If `singleExpression` then `concat[0]` might be a \"trusted\" value or `null`, rather than a string\n            return $sce.getTrusted(trustedContext, singleExpression ? concat[0] : concat.join(''));\n          } else if (trustedContext && concat.length > 1) {\n            // This context does not allow more than one part, e.g. expr + string or exp + exp.\n            $interpolateMinErr.throwNoconcat(text);\n          }\n          // In an unprivileged context or only one part: just concatenate and return.\n          return concat.join('');\n        };\n\n        return extend(function interpolationFn(context) {\n            var i = 0;\n            var ii = expressions.length;\n            var values = new Array(ii);\n\n            try {\n              for (; i < ii; i++) {\n                values[i] = parseFns[i](context);\n              }\n\n              return compute(values);\n            } catch (err) {\n              $exceptionHandler($interpolateMinErr.interr(text, err));\n            }\n\n          }, {\n          // all of these properties are undocumented for now\n          exp: text, //just for compatibility with regular watchers created via $watch\n          expressions: expressions,\n          $$watchDelegate: function(scope, listener) {\n            var lastValue;\n            return scope.$watchGroup(parseFns, /** @this */ function interpolateFnWatcher(values, oldValues) {\n              var currValue = compute(values);\n              listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n              lastValue = currValue;\n            });\n          }\n        });\n      }\n\n      function parseStringifyInterceptor(value) {\n        try {\n          // In concatenable contexts, getTrusted comes at the end, to avoid sanitizing individual\n          // parts of a full URL. We don't care about losing the trustedness here.\n          // In non-concatenable contexts, where there is only one expression, this interceptor is\n          // not applied to the expression.\n          value = (trustedContext && !contextAllowsConcatenation) ?\n                    $sce.getTrusted(trustedContext, value) :\n                    $sce.valueOf(value);\n          return allOrNothing && !isDefined(value) ? value : stringify(value);\n        } catch (err) {\n          $exceptionHandler($interpolateMinErr.interr(text, err));\n        }\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nvar $intervalMinErr = minErr('$interval');\n\n/** @this */\nfunction $IntervalProvider() {\n  this.$get = ['$$intervalFactory', '$window',\n       function($$intervalFactory,   $window) {\n    var intervals = {};\n    var setIntervalFn = function(tick, delay, deferred) {\n      var id = $window.setInterval(tick, delay);\n      intervals[id] = deferred;\n      return id;\n    };\n    var clearIntervalFn = function(id) {\n      $window.clearInterval(id);\n      delete intervals[id];\n    };\n\n    /**\n     * @ngdoc service\n     * @name $interval\n     *\n     * @description\n     * AngularJS's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n     * milliseconds.\n     *\n     * The return value of registering an interval function is a promise. This promise will be\n     * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n     * run indefinitely if `count` is not defined. The value of the notification will be the\n     * number of iterations that have run.\n     * To cancel an interval, call `$interval.cancel(promise)`.\n     *\n     * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n     * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n     * time.\n     *\n     * <div class=\"alert alert-warning\">\n     * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n     * with them.  In particular they are not automatically destroyed when a controller's scope or a\n     * directive's element are destroyed.\n     * You should take this into consideration and make sure to always cancel the interval at the\n     * appropriate moment.  See the example below for more details on how and when to do this.\n     * </div>\n     *\n     * @param {function()} fn A function that should be called repeatedly. If no additional arguments\n     *   are passed (see below), the function is called with the current iteration count.\n     * @param {number} delay Number of milliseconds between each function call.\n     * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n     *   indefinitely.\n     * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n     *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n     * @param {...*=} Pass additional parameters to the executed function.\n     * @returns {promise} A promise which will be notified on each iteration. It will resolve once all iterations of the interval complete.\n     *\n     * @example\n     * <example module=\"intervalExample\" name=\"interval-service\">\n     * <file name=\"index.html\">\n     *   <script>\n     *     angular.module('intervalExample', [])\n     *       .controller('ExampleController', ['$scope', '$interval',\n     *         function($scope, $interval) {\n     *           $scope.format = 'M/d/yy h:mm:ss a';\n     *           $scope.blood_1 = 100;\n     *           $scope.blood_2 = 120;\n     *\n     *           var stop;\n     *           $scope.fight = function() {\n     *             // Don't start a new fight if we are already fighting\n     *             if ( angular.isDefined(stop) ) return;\n     *\n     *             stop = $interval(function() {\n     *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n     *                 $scope.blood_1 = $scope.blood_1 - 3;\n     *                 $scope.blood_2 = $scope.blood_2 - 4;\n     *               } else {\n     *                 $scope.stopFight();\n     *               }\n     *             }, 100);\n     *           };\n     *\n     *           $scope.stopFight = function() {\n     *             if (angular.isDefined(stop)) {\n     *               $interval.cancel(stop);\n     *               stop = undefined;\n     *             }\n     *           };\n     *\n     *           $scope.resetFight = function() {\n     *             $scope.blood_1 = 100;\n     *             $scope.blood_2 = 120;\n     *           };\n     *\n     *           $scope.$on('$destroy', function() {\n     *             // Make sure that the interval is destroyed too\n     *             $scope.stopFight();\n     *           });\n     *         }])\n     *       // Register the 'myCurrentTime' directive factory method.\n     *       // We inject $interval and dateFilter service since the factory method is DI.\n     *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n     *         function($interval, dateFilter) {\n     *           // return the directive link function. (compile function not needed)\n     *           return function(scope, element, attrs) {\n     *             var format,  // date format\n     *                 stopTime; // so that we can cancel the time updates\n     *\n     *             // used to update the UI\n     *             function updateTime() {\n     *               element.text(dateFilter(new Date(), format));\n     *             }\n     *\n     *             // watch the expression, and update the UI on change.\n     *             scope.$watch(attrs.myCurrentTime, function(value) {\n     *               format = value;\n     *               updateTime();\n     *             });\n     *\n     *             stopTime = $interval(updateTime, 1000);\n     *\n     *             // listen on DOM destroy (removal) event, and cancel the next UI update\n     *             // to prevent updating time after the DOM element was removed.\n     *             element.on('$destroy', function() {\n     *               $interval.cancel(stopTime);\n     *             });\n     *           }\n     *         }]);\n     *   </script>\n     *\n     *   <div>\n     *     <div ng-controller=\"ExampleController\">\n     *       <label>Date format: <input ng-model=\"format\"></label> <hr/>\n     *       Current time is: <span my-current-time=\"format\"></span>\n     *       <hr/>\n     *       Blood 1 : <font color='red'>{{blood_1}}</font>\n     *       Blood 2 : <font color='red'>{{blood_2}}</font>\n     *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n     *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n     *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n     *     </div>\n     *   </div>\n     *\n     * </file>\n     * </example>\n     */\n    var interval = $$intervalFactory(setIntervalFn, clearIntervalFn);\n\n    /**\n     * @ngdoc method\n     * @name $interval#cancel\n     *\n     * @description\n     * Cancels a task associated with the `promise`.\n     *\n     * @param {Promise=} promise returned by the `$interval` function.\n     * @returns {boolean} Returns `true` if the task was successfully canceled.\n     */\n    interval.cancel = function(promise) {\n      if (!promise) return false;\n\n      if (!promise.hasOwnProperty('$$intervalId')) {\n        throw $intervalMinErr('badprom',\n            '`$interval.cancel()` called with a promise that was not generated by `$interval()`.');\n      }\n\n      if (!intervals.hasOwnProperty(promise.$$intervalId)) return false;\n\n      var id = promise.$$intervalId;\n      var deferred = intervals[id];\n\n      // Interval cancels should not report an unhandled promise.\n      markQExceptionHandled(deferred.promise);\n      deferred.reject('canceled');\n      clearIntervalFn(id);\n\n      return true;\n    };\n\n    return interval;\n  }];\n}\n\n/** @this */\nfunction $$IntervalFactoryProvider() {\n  this.$get = ['$browser', '$q', '$$q', '$rootScope',\n       function($browser,   $q,   $$q,   $rootScope) {\n    return function intervalFactory(setIntervalFn, clearIntervalFn) {\n      return function intervalFn(fn, delay, count, invokeApply) {\n        var hasParams = arguments.length > 4,\n            args = hasParams ? sliceArgs(arguments, 4) : [],\n            iteration = 0,\n            skipApply = isDefined(invokeApply) && !invokeApply,\n            deferred = (skipApply ? $$q : $q).defer(),\n            promise = deferred.promise;\n\n        count = isDefined(count) ? count : 0;\n\n        function callback() {\n          if (!hasParams) {\n            fn(iteration);\n          } else {\n            fn.apply(null, args);\n          }\n        }\n\n        function tick() {\n          if (skipApply) {\n            $browser.defer(callback);\n          } else {\n            $rootScope.$evalAsync(callback);\n          }\n          deferred.notify(iteration++);\n\n          if (count > 0 && iteration >= count) {\n            deferred.resolve(iteration);\n            clearIntervalFn(promise.$$intervalId);\n          }\n\n          if (!skipApply) $rootScope.$apply();\n        }\n\n        promise.$$intervalId = setIntervalFn(tick, delay, deferred, skipApply);\n\n        return promise;\n      };\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $jsonpCallbacks\n * @requires $window\n * @description\n * This service handles the lifecycle of callbacks to handle JSONP requests.\n * Override this service if you wish to customise where the callbacks are stored and\n * how they vary compared to the requested url.\n */\nvar $jsonpCallbacksProvider = /** @this */ function() {\n  this.$get = function() {\n    var callbacks = angular.callbacks;\n    var callbackMap = {};\n\n    function createCallback(callbackId) {\n      var callback = function(data) {\n        callback.data = data;\n        callback.called = true;\n      };\n      callback.id = callbackId;\n      return callback;\n    }\n\n    return {\n      /**\n       * @ngdoc method\n       * @name $jsonpCallbacks#createCallback\n       * @param {string} url the url of the JSONP request\n       * @returns {string} the callback path to send to the server as part of the JSONP request\n       * @description\n       * {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback\n       * to pass to the server, which will be used to call the callback with its payload in the JSONP response.\n       */\n      createCallback: function(url) {\n        var callbackId = '_' + (callbacks.$$counter++).toString(36);\n        var callbackPath = 'angular.callbacks.' + callbackId;\n        var callback = createCallback(callbackId);\n        callbackMap[callbackPath] = callbacks[callbackId] = callback;\n        return callbackPath;\n      },\n      /**\n       * @ngdoc method\n       * @name $jsonpCallbacks#wasCalled\n       * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n       * @returns {boolean} whether the callback has been called, as a result of the JSONP response\n       * @description\n       * {@link $httpBackend} calls this method to find out whether the JSONP response actually called the\n       * callback that was passed in the request.\n       */\n      wasCalled: function(callbackPath) {\n        return callbackMap[callbackPath].called;\n      },\n      /**\n       * @ngdoc method\n       * @name $jsonpCallbacks#getResponse\n       * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n       * @returns {*} the data received from the response via the registered callback\n       * @description\n       * {@link $httpBackend} calls this method to get hold of the data that was provided to the callback\n       * in the JSONP response.\n       */\n      getResponse: function(callbackPath) {\n        return callbackMap[callbackPath].data;\n      },\n      /**\n       * @ngdoc method\n       * @name $jsonpCallbacks#removeCallback\n       * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n       * @description\n       * {@link $httpBackend} calls this method to remove the callback after the JSONP request has\n       * completed or timed-out.\n       */\n      removeCallback: function(callbackPath) {\n        var callback = callbackMap[callbackPath];\n        delete callbacks[callback.id];\n        delete callbackMap[callbackPath];\n      }\n    };\n  };\n};\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various AngularJS components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\n\n/* global stripHash: true */\n\nvar PATH_MATCH = /^([^?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    // decode forward slashes to prevent them from being double encoded\n    segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/'));\n  }\n\n  return segments.join('/');\n}\n\nfunction decodePath(path, html5Mode) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = decodeURIComponent(segments[i]);\n    if (html5Mode) {\n      // encode forward slashes to prevent them from being mistaken for path separators\n      segments[i] = segments[i].replace(/\\//g, '%2F');\n    }\n  }\n\n  return segments.join('/');\n}\n\nfunction normalizePath(pathValue, searchValue, hashValue) {\n  var search = toKeyValue(searchValue),\n    hash = hashValue ? '#' + encodeUriSegment(hashValue) : '',\n    path = encodePath(pathValue);\n\n  return path + (search ? '?' + search : '') + hash;\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n  var parsedUrl = urlResolve(absoluteUrl);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\nvar DOUBLE_SLASH_REGEX = /^\\s*[\\\\/]{2,}/;\nfunction parseAppUrl(url, locationObj, html5Mode) {\n\n  if (DOUBLE_SLASH_REGEX.test(url)) {\n    throw $locationMinErr('badpath', 'Invalid url \"{0}\".', url);\n  }\n\n  var prefixed = (url.charAt(0) !== '/');\n  if (prefixed) {\n    url = '/' + url;\n  }\n  var match = urlResolve(url);\n  var path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname;\n  locationObj.$$path = decodePath(path, html5Mode);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) !== '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\nfunction startsWith(str, search) {\n  return str.slice(0, search.length) === search;\n}\n\n/**\n *\n * @param {string} base\n * @param {string} url\n * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with\n *                   the expected string.\n */\nfunction stripBaseUrl(base, url) {\n  if (startsWith(url, base)) {\n    return url.substr(base.length);\n  }\n}\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index === -1 ? url : url.substr(0, index);\n}\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents a URL\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} appBaseNoFile application base URL stripped of any filename\n * @param {string} basePrefix URL path prefix\n */\nfunction LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given HTML5 (regular) URL string into properties\n   * @param {string} url HTML5 URL\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = stripBaseUrl(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this, true);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  this.$$normalizeUrl = function(url) {\n    return appBaseNoFile + url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n\n    if (isDefined(appUrl = stripBaseUrl(appBase, url))) {\n      prevAppUrl = appUrl;\n      if (basePrefix && isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) {\n        rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents URL\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} appBaseNoFile application base URL stripped of any filename\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {\n\n  parseAbsoluteUrl(appBase, this);\n\n\n  /**\n   * Parse given hashbang URL into properties\n   * @param {string} url Hashbang URL\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url);\n    var withoutHashUrl;\n\n    if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {\n\n      // The rest of the URL starts with a hash so we have\n      // got either a hashbang path or a plain hash fragment\n      withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl);\n      if (isUndefined(withoutHashUrl)) {\n        // There was no hashbang prefix so we just have a hash fragment\n        withoutHashUrl = withoutBaseUrl;\n      }\n\n    } else {\n      // There was no hashbang path nor hash fragment:\n      // If we are in HTML5 mode we use what is left as the path;\n      // Otherwise we ignore what is left\n      if (this.$$html5) {\n        withoutHashUrl = withoutBaseUrl;\n      } else {\n        withoutHashUrl = '';\n        if (isUndefined(withoutBaseUrl)) {\n          appBase = url;\n          /** @type {?} */ (this).replace();\n        }\n      }\n    }\n\n    parseAppUrl(withoutHashUrl, this, false);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of AngularJS, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName(path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (startsWith(url, base)) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  this.$$normalizeUrl = function(url) {\n    return appBase + (url ? hashPrefix + url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (stripHash(appBase) === stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents URL\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} appBaseNoFile application base URL stripped of any filename\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if (relHref && relHref[0] === '#') {\n      // special case for links to hash fragments:\n      // keep the old url and only replace the hash fragment\n      this.hash(relHref.slice(1));\n      return true;\n    }\n\n    var rewrittenUrl;\n    var appUrl;\n\n    if (appBase === stripHash(url)) {\n      rewrittenUrl = url;\n    } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if (appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$normalizeUrl = function(url) {\n    // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'\n    return appBase + hashPrefix + url;\n  };\n}\n\n\nvar locationPrototype = {\n\n  /**\n   * Ensure absolute URL is initialized.\n   * @private\n   */\n  $$absUrl:'',\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * Compose url and update `url` and `absUrl` property\n   * @private\n   */\n  $$compose: function() {\n    this.$$url = normalizePath(this.$$path, this.$$search, this.$$hash);\n    this.$$absUrl = this.$$normalizeUrl(this.$$url);\n    this.$$urlUpdatedByLocation = true;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full URL representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var absUrl = $location.absUrl();\n   * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @return {string} full URL\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return URL (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var url = $location.url();\n   * // => \"/some/path?foo=bar&baz=xoxo\"\n   * ```\n   *\n   * @param {string=} url New URL without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url)) {\n      return this.$$url;\n    }\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1] || url === '') this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current URL.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var protocol = $location.protocol();\n   * // => \"http\"\n   * ```\n   *\n   * @return {string} protocol of current URL\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current URL.\n   *\n   * Note: compared to the non-AngularJS version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var host = $location.host();\n   * // => \"example.com\"\n   *\n   * // given URL http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo\n   * host = $location.host();\n   * // => \"example.com\"\n   * host = location.host;\n   * // => \"example.com:8080\"\n   * ```\n   *\n   * @return {string} host of current URL.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current URL.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var port = $location.port();\n   * // => 80\n   * ```\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current URL when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var path = $location.path();\n   * // => \"/some/path\"\n   * ```\n   *\n   * @param {(string|number)=} path New path\n   * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) === '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current URL when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the URL.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          search = copy(search, {});\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Returns the hash fragment when called without any parameters.\n   *\n   * Changes the hash fragment when called with a parameter and returns `$location`.\n   *\n   *\n   * ```js\n   * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n   * var hash = $location.hash();\n   * // => \"hashValue\"\n   * ```\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during the current `$digest` will replace the current history\n   * record, instead of adding a new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n  Location.prototype = Object.create(locationPrototype);\n\n  /**\n   * @ngdoc method\n   * @name $location#state\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return the history state object when called without any parameter.\n   *\n   * Change the history state object when called with one parameter and return `$location`.\n   * The state object is later passed to `pushState` or `replaceState`.\n   *\n   * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n   * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n   * older browsers (like IE9 or Android < 4.0), don't use this method.\n   *\n   * @param {object=} state State object for pushState or replaceState\n   * @return {object} state\n   */\n  Location.prototype.state = function(state) {\n    if (!arguments.length) {\n      return this.$$state;\n    }\n\n    if (Location !== LocationHtml5Url || !this.$$html5) {\n      throw $locationMinErr('nostate', 'History API state support is available only ' +\n        'in HTML5 mode and only in browsers supporting HTML5 History API');\n    }\n    // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n    // but we're changing the $$state reference to $browser.state() during the $digest\n    // so the modification window is narrow.\n    this.$$state = isUndefined(state) ? null : state;\n    this.$$urlUpdatedByLocation = true;\n\n    return this;\n  };\n});\n\n\nfunction locationGetter(property) {\n  return /** @this */ function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return /** @this */ function(value) {\n    if (isUndefined(value)) {\n      return this[property];\n    }\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @this\n *\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n  var hashPrefix = '!',\n      html5Mode = {\n        enabled: false,\n        requireBase: true,\n        rewriteLinks: true\n      };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * The default value for the prefix is `'!'`.\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n   *   If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n   *   properties:\n   *   - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n   *     change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n   *     support `pushState`.\n   *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n   *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are\n   *     true, and a base tag is not present, an error will be thrown when `$location` is injected.\n   *     See the {@link guide/$location $location guide for more information}\n   *   - **rewriteLinks** - `{boolean|string}` - (default: `true`) When html5Mode is enabled,\n   *     enables/disables URL rewriting for relative links. If set to a string, URL rewriting will\n   *     only happen on links with an attribute that matches the given string. For example, if set\n   *     to `'internal-link'`, then the URL will only be rewritten for `<a internal-link>` links.\n   *     Note that [attribute name normalization](guide/directive#normalization) does not apply\n   *     here, so `'internalLink'` will **not** match `'internal-link'`.\n   *\n   * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isBoolean(mode)) {\n      html5Mode.enabled = mode;\n      return this;\n    } else if (isObject(mode)) {\n\n      if (isBoolean(mode.enabled)) {\n        html5Mode.enabled = mode.enabled;\n      }\n\n      if (isBoolean(mode.requireBase)) {\n        html5Mode.requireBase = mode.requireBase;\n      }\n\n      if (isBoolean(mode.rewriteLinks) || isString(mode.rewriteLinks)) {\n        html5Mode.rewriteLinks = mode.rewriteLinks;\n      }\n\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change.\n   *\n   * This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n   * the browser supports the HTML5 History API.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   * @param {string=} newState New history state object\n   * @param {string=} oldState History state object that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n      function($rootScope, $browser, $sniffer, $rootElement, $window) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode.enabled) {\n      if (!baseHref && html5Mode.requireBase) {\n        throw $locationMinErr('nobase',\n          '$location in HTML5 mode requires a <base> tag to be present!');\n      }\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    var appBaseNoFile = stripFile(appBase);\n\n    $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    $location.$$state = $browser.state();\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    // Determine if two URLs are equal despite potentially having different encoding/normalizing\n    //  such as $location.absUrl() vs $browser.url()\n    // See https://github.com/angular/angular.js/issues/16592\n    function urlsEqual(a, b) {\n      return a === b || urlResolve(a).href === urlResolve(b).href;\n    }\n\n    function setBrowserUrlWithFallback(url, replace, state) {\n      var oldUrl = $location.url();\n      var oldState = $location.$$state;\n      try {\n        $browser.url(url, replace, state);\n\n        // Make sure $location.state() returns referentially identical (not just deeply equal)\n        // state object; this makes possible quick checking if the state changed in the digest\n        // loop. Checking deep equality would be too expensive.\n        $location.$$state = $browser.state();\n      } catch (e) {\n        // Restore old values if pushState fails\n        $location.url(oldUrl);\n        $location.$$state = oldState;\n\n        throw e;\n      }\n    }\n\n    $rootElement.on('click', function(event) {\n      var rewriteLinks = html5Mode.rewriteLinks;\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (!rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which === 2 || event.button === 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (nodeName_(elm[0]) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      if (isString(rewriteLinks) && isUndefined(elm.attr(rewriteLinks))) return;\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the AngularJS application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() !== $browser.url()) {\n            $rootScope.$apply();\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() !== initialUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    var initializing = true;\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl, newState) {\n\n      if (!startsWith(newUrl, appBaseNoFile)) {\n        // If we are navigating outside of the app then force a reload\n        $window.location.href = newUrl;\n        return;\n      }\n\n      $rootScope.$evalAsync(function() {\n        var oldUrl = $location.absUrl();\n        var oldState = $location.$$state;\n        var defaultPrevented;\n        $location.$$parse(newUrl);\n        $location.$$state = newState;\n\n        defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n            newState, oldState).defaultPrevented;\n\n        // if the location was changed by a `$locationChangeStart` handler then stop\n        // processing this location change\n        if ($location.absUrl() !== newUrl) return;\n\n        if (defaultPrevented) {\n          $location.$$parse(oldUrl);\n          $location.$$state = oldState;\n          setBrowserUrlWithFallback(oldUrl, false, oldState);\n        } else {\n          initializing = false;\n          afterLocationChange(oldUrl, oldState);\n        }\n      });\n      if (!$rootScope.$$phase) $rootScope.$digest();\n    });\n\n    // update browser\n    $rootScope.$watch(function $locationWatch() {\n      if (initializing || $location.$$urlUpdatedByLocation) {\n        $location.$$urlUpdatedByLocation = false;\n\n        var oldUrl = $browser.url();\n        var newUrl = $location.absUrl();\n        var oldState = $browser.state();\n        var currentReplace = $location.$$replace;\n        var urlOrStateChanged = !urlsEqual(oldUrl, newUrl) ||\n          ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n        if (initializing || urlOrStateChanged) {\n          initializing = false;\n\n          $rootScope.$evalAsync(function() {\n            var newUrl = $location.absUrl();\n            var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n                $location.$$state, oldState).defaultPrevented;\n\n            // if the location was changed by a `$locationChangeStart` handler then stop\n            // processing this location change\n            if ($location.absUrl() !== newUrl) return;\n\n            if (defaultPrevented) {\n              $location.$$parse(oldUrl);\n              $location.$$state = oldState;\n            } else {\n              if (urlOrStateChanged) {\n                setBrowserUrlWithFallback(newUrl, currentReplace,\n                                          oldState === $location.$$state ? null : $location.$$state);\n              }\n              afterLocationChange(oldUrl, oldState);\n            }\n          });\n        }\n      }\n\n      $location.$$replace = false;\n\n      // we don't need to return anything because $evalAsync will make the digest loop dirty when\n      // there is a change\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl, oldState) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n        $location.$$state, oldState);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * To reveal the location of the calls to `$log` in the JavaScript console,\n * you can \"blackbox\" the AngularJS source in your browser:\n *\n * [Mozilla description of blackboxing](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Black_box_a_source).\n * [Chrome description of blackboxing](https://developer.chrome.com/devtools/docs/blackboxing).\n *\n * Note: Not all browsers support blackboxing.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\" name=\"log-service\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         <label>Message:\n         <input type=\"text\" ng-model=\"message\" /></label>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n         <button ng-click=\"$log.debug(message)\">debug</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @this\n *\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n      return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window) {\n    // Support: IE 9-11, Edge 12-14+\n    // IE/Edge display errors in such a way that it requires the user to click in 4 places\n    // to see the stack trace. There is no way to feature-detect it so there's a chance\n    // of the user agent sniffing to go wrong but since it's only about logging, this shouldn't\n    // break apps. Other browsers display errors in a sensible way and some of them map stack\n    // traces along source maps if available so it makes sense to let browsers display it\n    // as they want.\n    var formatStackTrace = msie || /\\bEdge\\//.test($window.navigator && $window.navigator.userAgent);\n\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function() {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      })()\n    };\n\n    function formatError(arg) {\n      if (isError(arg)) {\n        if (arg.stack && formatStackTrace) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop;\n\n      return function() {\n        var args = [];\n        forEach(arguments, function(arg) {\n          args.push(formatError(arg));\n        });\n        // Support: IE 9 only\n        // console methods don't inherit from Function.prototype in IE 9 so we can't\n        // call `logFn.apply(console, args)` directly.\n        return Function.prototype.apply.call(logFn, console, args);\n      };\n    }\n  }];\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n *     Any commits to this file should be reviewed with security in mind.  *\n *   Changes to this file can potentially create security vulnerabilities. *\n *          An approval from 2 Core members with history of modifying      *\n *                         this file is required.                          *\n *                                                                         *\n *  Does the change somehow allow for arbitrary javascript to be executed? *\n *    Or allows for someone to change the prototype of built-in objects?   *\n *     Or gives undesired access to variables likes document or window?    *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\nvar $parseMinErr = minErr('$parse');\n\nvar objectValueOf = {}.constructor.prototype.valueOf;\n\n// Sandboxing AngularJS Expressions\n// ------------------------------\n// AngularJS expressions are no longer sandboxed. So it is now even easier to access arbitrary JS code by\n// various means such as obtaining a reference to native JS functions like the Function constructor.\n//\n// As an example, consider the following AngularJS expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// It is important to realize that if you create an expression from a string that contains user provided\n// content then it is possible that your application contains a security vulnerability to an XSS style attack.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction getStringValue(name) {\n  // Property names must be strings. This means that non-string objects cannot be used\n  // as keys in an object. Any non-string object, including a number, is typecasted\n  // into a string via the toString method.\n  // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names\n  //\n  // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it\n  // to a string. It's not always possible. If `name` is an object and its `toString` method is\n  // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown:\n  //\n  // TypeError: Cannot convert object to primitive value\n  //\n  // For performance reasons, we don't catch this error here and allow it to propagate up the call\n  // stack. Note that you'll get the same error in JavaScript if you try to access a property using\n  // such a 'broken' object as a key.\n  return name + '';\n}\n\n\nvar OPERATORS = createMap();\nforEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });\nvar ESCAPE = {'n':'\\n', 'f':'\\f', 'r':'\\r', 't':'\\t', 'v':'\\v', '\\'':'\\'', '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function Lexer(options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function(text) {\n    this.text = text;\n    this.index = 0;\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      if (ch === '\"' || ch === '\\'') {\n        this.readString(ch);\n      } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdentifierStart(this.peekMultichar())) {\n        this.readIdent();\n      } else if (this.is(ch, '(){}[].,;:?')) {\n        this.tokens.push({index: this.index, text: ch});\n        this.index++;\n      } else if (this.isWhitespace(ch)) {\n        this.index++;\n      } else {\n        var ch2 = ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var op1 = OPERATORS[ch];\n        var op2 = OPERATORS[ch2];\n        var op3 = OPERATORS[ch3];\n        if (op1 || op2 || op3) {\n          var token = op3 ? ch3 : (op2 ? ch2 : ch);\n          this.tokens.push({index: this.index, text: token, operator: true});\n          this.index += token.length;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n    }\n    return this.tokens;\n  },\n\n  is: function(ch, chars) {\n    return chars.indexOf(ch) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9') && typeof ch === 'string';\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdentifierStart: function(ch) {\n    return this.options.isIdentifierStart ?\n        this.options.isIdentifierStart(ch, this.codePointAt(ch)) :\n        this.isValidIdentifierStart(ch);\n  },\n\n  isValidIdentifierStart: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isIdentifierContinue: function(ch) {\n    return this.options.isIdentifierContinue ?\n        this.options.isIdentifierContinue(ch, this.codePointAt(ch)) :\n        this.isValidIdentifierContinue(ch);\n  },\n\n  isValidIdentifierContinue: function(ch, cp) {\n    return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch);\n  },\n\n  codePointAt: function(ch) {\n    if (ch.length === 1) return ch.charCodeAt(0);\n    // eslint-disable-next-line no-bitwise\n    return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00;\n  },\n\n  peekMultichar: function() {\n    var ch = this.text.charAt(this.index);\n    var peek = this.peek();\n    if (!peek) {\n      return ch;\n    }\n    var cp1 = ch.charCodeAt(0);\n    var cp2 = peek.charCodeAt(0);\n    if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) {\n      return ch + peek;\n    }\n    return ch;\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch === '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch === 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) === 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) === 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    this.tokens.push({\n      index: start,\n      text: number,\n      constant: true,\n      value: Number(number)\n    });\n  },\n\n  readIdent: function() {\n    var start = this.index;\n    this.index += this.peekMultichar().length;\n    while (this.index < this.text.length) {\n      var ch = this.peekMultichar();\n      if (!this.isIdentifierContinue(ch)) {\n        break;\n      }\n      this.index += ch.length;\n    }\n    this.tokens.push({\n      index: start,\n      text: this.text.slice(start, this.index),\n      identifier: true\n    });\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i)) {\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          }\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          constant: true,\n          value: string\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\nvar AST = function AST(lexer, options) {\n  this.lexer = lexer;\n  this.options = options;\n};\n\nAST.Program = 'Program';\nAST.ExpressionStatement = 'ExpressionStatement';\nAST.AssignmentExpression = 'AssignmentExpression';\nAST.ConditionalExpression = 'ConditionalExpression';\nAST.LogicalExpression = 'LogicalExpression';\nAST.BinaryExpression = 'BinaryExpression';\nAST.UnaryExpression = 'UnaryExpression';\nAST.CallExpression = 'CallExpression';\nAST.MemberExpression = 'MemberExpression';\nAST.Identifier = 'Identifier';\nAST.Literal = 'Literal';\nAST.ArrayExpression = 'ArrayExpression';\nAST.Property = 'Property';\nAST.ObjectExpression = 'ObjectExpression';\nAST.ThisExpression = 'ThisExpression';\nAST.LocalsExpression = 'LocalsExpression';\n\n// Internal use only\nAST.NGValueParameter = 'NGValueParameter';\n\nAST.prototype = {\n  ast: function(text) {\n    this.text = text;\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.program();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    return value;\n  },\n\n  program: function() {\n    var body = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        body.push(this.expressionStatement());\n      if (!this.expect(';')) {\n        return { type: AST.Program, body: body};\n      }\n    }\n  },\n\n  expressionStatement: function() {\n    return { type: AST.ExpressionStatement, expression: this.filterChain() };\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    while (this.expect('|')) {\n      left = this.filter(left);\n    }\n    return left;\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var result = this.ternary();\n    if (this.expect('=')) {\n      if (!isAssignable(result)) {\n        throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');\n      }\n\n      result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};\n    }\n    return result;\n  },\n\n  ternary: function() {\n    var test = this.logicalOR();\n    var alternate;\n    var consequent;\n    if (this.expect('?')) {\n      alternate = this.expression();\n      if (this.consume(':')) {\n        consequent = this.expression();\n        return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};\n      }\n    }\n    return test;\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    while (this.expect('||')) {\n      left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };\n    }\n    return left;\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    while (this.expect('&&')) {\n      left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    while ((token = this.expect('==','!=','===','!=='))) {\n      left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    while ((token = this.expect('<', '>', '<=', '>='))) {\n      left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if ((token = this.expect('+', '-', '!'))) {\n      return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };\n    } else {\n      return this.primary();\n    }\n  },\n\n  primary: function() {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else if (this.selfReferential.hasOwnProperty(this.peek().text)) {\n      primary = copy(this.selfReferential[this.consume().text]);\n    } else if (this.options.literals.hasOwnProperty(this.peek().text)) {\n      primary = { type: AST.Literal, value: this.options.literals[this.consume().text]};\n    } else if (this.peek().identifier) {\n      primary = this.identifier();\n    } else if (this.peek().constant) {\n      primary = this.constant();\n    } else {\n      this.throwError('not a primary expression', this.peek());\n    }\n\n    var next;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };\n        this.consume(')');\n      } else if (next.text === '[') {\n        primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };\n        this.consume(']');\n      } else if (next.text === '.') {\n        primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  filter: function(baseExpression) {\n    var args = [baseExpression];\n    var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};\n\n    while (this.expect(':')) {\n      args.push(this.expression());\n    }\n\n    return result;\n  },\n\n  parseArguments: function() {\n    var args = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        args.push(this.filterChain());\n      } while (this.expect(','));\n    }\n    return args;\n  },\n\n  identifier: function() {\n    var token = this.consume();\n    if (!token.identifier) {\n      this.throwError('is not a valid identifier', token);\n    }\n    return { type: AST.Identifier, name: token.text };\n  },\n\n  constant: function() {\n    // TODO check that it is a constant\n    return { type: AST.Literal, value: this.consume().value };\n  },\n\n  arrayDeclaration: function() {\n    var elements = [];\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        elements.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return { type: AST.ArrayExpression, elements: elements };\n  },\n\n  object: function() {\n    var properties = [], property;\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        property = {type: AST.Property, kind: 'init'};\n        if (this.peek().constant) {\n          property.key = this.constant();\n          property.computed = false;\n          this.consume(':');\n          property.value = this.expression();\n        } else if (this.peek().identifier) {\n          property.key = this.identifier();\n          property.computed = false;\n          if (this.peek(':')) {\n            this.consume(':');\n            property.value = this.expression();\n          } else {\n            property.value = property.key;\n          }\n        } else if (this.peek('[')) {\n          this.consume('[');\n          property.key = this.expression();\n          this.consume(']');\n          property.computed = true;\n          this.consume(':');\n          property.value = this.expression();\n        } else {\n          this.throwError('invalid key', this.peek());\n        }\n        properties.push(property);\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return {type: AST.ObjectExpression, properties: properties };\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  consume: function(e1) {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n\n    var token = this.expect(e1);\n    if (!token) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n    return token;\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0) {\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    }\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    return this.peekAhead(0, e1, e2, e3, e4);\n  },\n\n  peekAhead: function(i, e1, e2, e3, e4) {\n    if (this.tokens.length > i) {\n      var token = this.tokens[i];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4) {\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  selfReferential: {\n    'this': {type: AST.ThisExpression },\n    '$locals': {type: AST.LocalsExpression }\n  }\n};\n\nfunction ifDefined(v, d) {\n  return typeof v !== 'undefined' ? v : d;\n}\n\nfunction plusFn(l, r) {\n  if (typeof l === 'undefined') return r;\n  if (typeof r === 'undefined') return l;\n  return l + r;\n}\n\nfunction isStateless($filter, filterName) {\n  var fn = $filter(filterName);\n  return !fn.$stateful;\n}\n\nvar PURITY_ABSOLUTE = 1;\nvar PURITY_RELATIVE = 2;\n\n// Detect nodes which could depend on non-shallow state of objects\nfunction isPure(node, parentIsPure) {\n  switch (node.type) {\n    // Computed members might invoke a stateful toString()\n    case AST.MemberExpression:\n      if (node.computed) {\n        return false;\n      }\n      break;\n\n    // Unary always convert to primative\n    case AST.UnaryExpression:\n      return PURITY_ABSOLUTE;\n\n    // The binary + operator can invoke a stateful toString().\n    case AST.BinaryExpression:\n      return node.operator !== '+' ? PURITY_ABSOLUTE : false;\n\n    // Functions / filters probably read state from within objects\n    case AST.CallExpression:\n      return false;\n  }\n\n  return (undefined === parentIsPure) ? PURITY_RELATIVE : parentIsPure;\n}\n\nfunction findConstantAndWatchExpressions(ast, $filter, parentIsPure) {\n  var allConstants;\n  var argsToWatch;\n  var isStatelessFilter;\n\n  var astIsPure = ast.isPure = isPure(ast, parentIsPure);\n\n  switch (ast.type) {\n  case AST.Program:\n    allConstants = true;\n    forEach(ast.body, function(expr) {\n      findConstantAndWatchExpressions(expr.expression, $filter, astIsPure);\n      allConstants = allConstants && expr.expression.constant;\n    });\n    ast.constant = allConstants;\n    break;\n  case AST.Literal:\n    ast.constant = true;\n    ast.toWatch = [];\n    break;\n  case AST.UnaryExpression:\n    findConstantAndWatchExpressions(ast.argument, $filter, astIsPure);\n    ast.constant = ast.argument.constant;\n    ast.toWatch = ast.argument.toWatch;\n    break;\n  case AST.BinaryExpression:\n    findConstantAndWatchExpressions(ast.left, $filter, astIsPure);\n    findConstantAndWatchExpressions(ast.right, $filter, astIsPure);\n    ast.constant = ast.left.constant && ast.right.constant;\n    ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);\n    break;\n  case AST.LogicalExpression:\n    findConstantAndWatchExpressions(ast.left, $filter, astIsPure);\n    findConstantAndWatchExpressions(ast.right, $filter, astIsPure);\n    ast.constant = ast.left.constant && ast.right.constant;\n    ast.toWatch = ast.constant ? [] : [ast];\n    break;\n  case AST.ConditionalExpression:\n    findConstantAndWatchExpressions(ast.test, $filter, astIsPure);\n    findConstantAndWatchExpressions(ast.alternate, $filter, astIsPure);\n    findConstantAndWatchExpressions(ast.consequent, $filter, astIsPure);\n    ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;\n    ast.toWatch = ast.constant ? [] : [ast];\n    break;\n  case AST.Identifier:\n    ast.constant = false;\n    ast.toWatch = [ast];\n    break;\n  case AST.MemberExpression:\n    findConstantAndWatchExpressions(ast.object, $filter, astIsPure);\n    if (ast.computed) {\n      findConstantAndWatchExpressions(ast.property, $filter, astIsPure);\n    }\n    ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);\n    ast.toWatch = ast.constant ? [] : [ast];\n    break;\n  case AST.CallExpression:\n    isStatelessFilter = ast.filter ? isStateless($filter, ast.callee.name) : false;\n    allConstants = isStatelessFilter;\n    argsToWatch = [];\n    forEach(ast.arguments, function(expr) {\n      findConstantAndWatchExpressions(expr, $filter, astIsPure);\n      allConstants = allConstants && expr.constant;\n      argsToWatch.push.apply(argsToWatch, expr.toWatch);\n    });\n    ast.constant = allConstants;\n    ast.toWatch = isStatelessFilter ? argsToWatch : [ast];\n    break;\n  case AST.AssignmentExpression:\n    findConstantAndWatchExpressions(ast.left, $filter, astIsPure);\n    findConstantAndWatchExpressions(ast.right, $filter, astIsPure);\n    ast.constant = ast.left.constant && ast.right.constant;\n    ast.toWatch = [ast];\n    break;\n  case AST.ArrayExpression:\n    allConstants = true;\n    argsToWatch = [];\n    forEach(ast.elements, function(expr) {\n      findConstantAndWatchExpressions(expr, $filter, astIsPure);\n      allConstants = allConstants && expr.constant;\n      argsToWatch.push.apply(argsToWatch, expr.toWatch);\n    });\n    ast.constant = allConstants;\n    ast.toWatch = argsToWatch;\n    break;\n  case AST.ObjectExpression:\n    allConstants = true;\n    argsToWatch = [];\n    forEach(ast.properties, function(property) {\n      findConstantAndWatchExpressions(property.value, $filter, astIsPure);\n      allConstants = allConstants && property.value.constant;\n      argsToWatch.push.apply(argsToWatch, property.value.toWatch);\n      if (property.computed) {\n        //`{[key]: value}` implicitly does `key.toString()` which may be non-pure\n        findConstantAndWatchExpressions(property.key, $filter, /*parentIsPure=*/false);\n        allConstants = allConstants && property.key.constant;\n        argsToWatch.push.apply(argsToWatch, property.key.toWatch);\n      }\n    });\n    ast.constant = allConstants;\n    ast.toWatch = argsToWatch;\n    break;\n  case AST.ThisExpression:\n    ast.constant = false;\n    ast.toWatch = [];\n    break;\n  case AST.LocalsExpression:\n    ast.constant = false;\n    ast.toWatch = [];\n    break;\n  }\n}\n\nfunction getInputs(body) {\n  if (body.length !== 1) return;\n  var lastExpression = body[0].expression;\n  var candidate = lastExpression.toWatch;\n  if (candidate.length !== 1) return candidate;\n  return candidate[0] !== lastExpression ? candidate : undefined;\n}\n\nfunction isAssignable(ast) {\n  return ast.type === AST.Identifier || ast.type === AST.MemberExpression;\n}\n\nfunction assignableAST(ast) {\n  if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {\n    return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};\n  }\n}\n\nfunction isLiteral(ast) {\n  return ast.body.length === 0 ||\n      ast.body.length === 1 && (\n      ast.body[0].expression.type === AST.Literal ||\n      ast.body[0].expression.type === AST.ArrayExpression ||\n      ast.body[0].expression.type === AST.ObjectExpression);\n}\n\nfunction isConstant(ast) {\n  return ast.constant;\n}\n\nfunction ASTCompiler($filter) {\n  this.$filter = $filter;\n}\n\nASTCompiler.prototype = {\n  compile: function(ast) {\n    var self = this;\n    this.state = {\n      nextId: 0,\n      filters: {},\n      fn: {vars: [], body: [], own: {}},\n      assign: {vars: [], body: [], own: {}},\n      inputs: []\n    };\n    findConstantAndWatchExpressions(ast, self.$filter);\n    var extra = '';\n    var assignable;\n    this.stage = 'assign';\n    if ((assignable = assignableAST(ast))) {\n      this.state.computing = 'assign';\n      var result = this.nextId();\n      this.recurse(assignable, result);\n      this.return_(result);\n      extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');\n    }\n    var toWatch = getInputs(ast.body);\n    self.stage = 'inputs';\n    forEach(toWatch, function(watch, key) {\n      var fnKey = 'fn' + key;\n      self.state[fnKey] = {vars: [], body: [], own: {}};\n      self.state.computing = fnKey;\n      var intoId = self.nextId();\n      self.recurse(watch, intoId);\n      self.return_(intoId);\n      self.state.inputs.push({name: fnKey, isPure: watch.isPure});\n      watch.watchId = key;\n    });\n    this.state.computing = 'fn';\n    this.stage = 'main';\n    this.recurse(ast);\n    var fnString =\n      // The build and minification steps remove the string \"use strict\" from the code, but this is done using a regex.\n      // This is a workaround for this until we do a better job at only removing the prefix only when we should.\n      '\"' + this.USE + ' ' + this.STRICT + '\";\\n' +\n      this.filterPrefix() +\n      'var fn=' + this.generateFunction('fn', 's,l,a,i') +\n      extra +\n      this.watchFns() +\n      'return fn;';\n\n    // eslint-disable-next-line no-new-func\n    var fn = (new Function('$filter',\n        'getStringValue',\n        'ifDefined',\n        'plus',\n        fnString))(\n          this.$filter,\n          getStringValue,\n          ifDefined,\n          plusFn);\n    this.state = this.stage = undefined;\n    return fn;\n  },\n\n  USE: 'use',\n\n  STRICT: 'strict',\n\n  watchFns: function() {\n    var result = [];\n    var inputs = this.state.inputs;\n    var self = this;\n    forEach(inputs, function(input) {\n      result.push('var ' + input.name + '=' + self.generateFunction(input.name, 's'));\n      if (input.isPure) {\n        result.push(input.name, '.isPure=' + JSON.stringify(input.isPure) + ';');\n      }\n    });\n    if (inputs.length) {\n      result.push('fn.inputs=[' + inputs.map(function(i) { return i.name; }).join(',') + '];');\n    }\n    return result.join('');\n  },\n\n  generateFunction: function(name, params) {\n    return 'function(' + params + '){' +\n        this.varsPrefix(name) +\n        this.body(name) +\n        '};';\n  },\n\n  filterPrefix: function() {\n    var parts = [];\n    var self = this;\n    forEach(this.state.filters, function(id, filter) {\n      parts.push(id + '=$filter(' + self.escape(filter) + ')');\n    });\n    if (parts.length) return 'var ' + parts.join(',') + ';';\n    return '';\n  },\n\n  varsPrefix: function(section) {\n    return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';\n  },\n\n  body: function(section) {\n    return this.state[section].body.join('');\n  },\n\n  recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {\n    var left, right, self = this, args, expression, computed;\n    recursionFn = recursionFn || noop;\n    if (!skipWatchIdCheck && isDefined(ast.watchId)) {\n      intoId = intoId || this.nextId();\n      this.if_('i',\n        this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),\n        this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)\n      );\n      return;\n    }\n    switch (ast.type) {\n    case AST.Program:\n      forEach(ast.body, function(expression, pos) {\n        self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });\n        if (pos !== ast.body.length - 1) {\n          self.current().body.push(right, ';');\n        } else {\n          self.return_(right);\n        }\n      });\n      break;\n    case AST.Literal:\n      expression = this.escape(ast.value);\n      this.assign(intoId, expression);\n      recursionFn(intoId || expression);\n      break;\n    case AST.UnaryExpression:\n      this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });\n      expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';\n      this.assign(intoId, expression);\n      recursionFn(expression);\n      break;\n    case AST.BinaryExpression:\n      this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });\n      this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });\n      if (ast.operator === '+') {\n        expression = this.plus(left, right);\n      } else if (ast.operator === '-') {\n        expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);\n      } else {\n        expression = '(' + left + ')' + ast.operator + '(' + right + ')';\n      }\n      this.assign(intoId, expression);\n      recursionFn(expression);\n      break;\n    case AST.LogicalExpression:\n      intoId = intoId || this.nextId();\n      self.recurse(ast.left, intoId);\n      self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));\n      recursionFn(intoId);\n      break;\n    case AST.ConditionalExpression:\n      intoId = intoId || this.nextId();\n      self.recurse(ast.test, intoId);\n      self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));\n      recursionFn(intoId);\n      break;\n    case AST.Identifier:\n      intoId = intoId || this.nextId();\n      if (nameId) {\n        nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');\n        nameId.computed = false;\n        nameId.name = ast.name;\n      }\n      self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),\n        function() {\n          self.if_(self.stage === 'inputs' || 's', function() {\n            if (create && create !== 1) {\n              self.if_(\n                self.isNull(self.nonComputedMember('s', ast.name)),\n                self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));\n            }\n            self.assign(intoId, self.nonComputedMember('s', ast.name));\n          });\n        }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))\n        );\n      recursionFn(intoId);\n      break;\n    case AST.MemberExpression:\n      left = nameId && (nameId.context = this.nextId()) || this.nextId();\n      intoId = intoId || this.nextId();\n      self.recurse(ast.object, left, undefined, function() {\n        self.if_(self.notNull(left), function() {\n          if (ast.computed) {\n            right = self.nextId();\n            self.recurse(ast.property, right);\n            self.getStringValue(right);\n            if (create && create !== 1) {\n              self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));\n            }\n            expression = self.computedMember(left, right);\n            self.assign(intoId, expression);\n            if (nameId) {\n              nameId.computed = true;\n              nameId.name = right;\n            }\n          } else {\n            if (create && create !== 1) {\n              self.if_(self.isNull(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));\n            }\n            expression = self.nonComputedMember(left, ast.property.name);\n            self.assign(intoId, expression);\n            if (nameId) {\n              nameId.computed = false;\n              nameId.name = ast.property.name;\n            }\n          }\n        }, function() {\n          self.assign(intoId, 'undefined');\n        });\n        recursionFn(intoId);\n      }, !!create);\n      break;\n    case AST.CallExpression:\n      intoId = intoId || this.nextId();\n      if (ast.filter) {\n        right = self.filter(ast.callee.name);\n        args = [];\n        forEach(ast.arguments, function(expr) {\n          var argument = self.nextId();\n          self.recurse(expr, argument);\n          args.push(argument);\n        });\n        expression = right + '(' + args.join(',') + ')';\n        self.assign(intoId, expression);\n        recursionFn(intoId);\n      } else {\n        right = self.nextId();\n        left = {};\n        args = [];\n        self.recurse(ast.callee, right, left, function() {\n          self.if_(self.notNull(right), function() {\n            forEach(ast.arguments, function(expr) {\n              self.recurse(expr, ast.constant ? undefined : self.nextId(), undefined, function(argument) {\n                args.push(argument);\n              });\n            });\n            if (left.name) {\n              expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';\n            } else {\n              expression = right + '(' + args.join(',') + ')';\n            }\n            self.assign(intoId, expression);\n          }, function() {\n            self.assign(intoId, 'undefined');\n          });\n          recursionFn(intoId);\n        });\n      }\n      break;\n    case AST.AssignmentExpression:\n      right = this.nextId();\n      left = {};\n      this.recurse(ast.left, undefined, left, function() {\n        self.if_(self.notNull(left.context), function() {\n          self.recurse(ast.right, right);\n          expression = self.member(left.context, left.name, left.computed) + ast.operator + right;\n          self.assign(intoId, expression);\n          recursionFn(intoId || expression);\n        });\n      }, 1);\n      break;\n    case AST.ArrayExpression:\n      args = [];\n      forEach(ast.elements, function(expr) {\n        self.recurse(expr, ast.constant ? undefined : self.nextId(), undefined, function(argument) {\n          args.push(argument);\n        });\n      });\n      expression = '[' + args.join(',') + ']';\n      this.assign(intoId, expression);\n      recursionFn(intoId || expression);\n      break;\n    case AST.ObjectExpression:\n      args = [];\n      computed = false;\n      forEach(ast.properties, function(property) {\n        if (property.computed) {\n          computed = true;\n        }\n      });\n      if (computed) {\n        intoId = intoId || this.nextId();\n        this.assign(intoId, '{}');\n        forEach(ast.properties, function(property) {\n          if (property.computed) {\n            left = self.nextId();\n            self.recurse(property.key, left);\n          } else {\n            left = property.key.type === AST.Identifier ?\n                       property.key.name :\n                       ('' + property.key.value);\n          }\n          right = self.nextId();\n          self.recurse(property.value, right);\n          self.assign(self.member(intoId, left, property.computed), right);\n        });\n      } else {\n        forEach(ast.properties, function(property) {\n          self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) {\n            args.push(self.escape(\n                property.key.type === AST.Identifier ? property.key.name :\n                  ('' + property.key.value)) +\n                ':' + expr);\n          });\n        });\n        expression = '{' + args.join(',') + '}';\n        this.assign(intoId, expression);\n      }\n      recursionFn(intoId || expression);\n      break;\n    case AST.ThisExpression:\n      this.assign(intoId, 's');\n      recursionFn(intoId || 's');\n      break;\n    case AST.LocalsExpression:\n      this.assign(intoId, 'l');\n      recursionFn(intoId || 'l');\n      break;\n    case AST.NGValueParameter:\n      this.assign(intoId, 'v');\n      recursionFn(intoId || 'v');\n      break;\n    }\n  },\n\n  getHasOwnProperty: function(element, property) {\n    var key = element + '.' + property;\n    var own = this.current().own;\n    if (!own.hasOwnProperty(key)) {\n      own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');\n    }\n    return own[key];\n  },\n\n  assign: function(id, value) {\n    if (!id) return;\n    this.current().body.push(id, '=', value, ';');\n    return id;\n  },\n\n  filter: function(filterName) {\n    if (!this.state.filters.hasOwnProperty(filterName)) {\n      this.state.filters[filterName] = this.nextId(true);\n    }\n    return this.state.filters[filterName];\n  },\n\n  ifDefined: function(id, defaultValue) {\n    return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';\n  },\n\n  plus: function(left, right) {\n    return 'plus(' + left + ',' + right + ')';\n  },\n\n  return_: function(id) {\n    this.current().body.push('return ', id, ';');\n  },\n\n  if_: function(test, alternate, consequent) {\n    if (test === true) {\n      alternate();\n    } else {\n      var body = this.current().body;\n      body.push('if(', test, '){');\n      alternate();\n      body.push('}');\n      if (consequent) {\n        body.push('else{');\n        consequent();\n        body.push('}');\n      }\n    }\n  },\n\n  not: function(expression) {\n    return '!(' + expression + ')';\n  },\n\n  isNull: function(expression) {\n    return expression + '==null';\n  },\n\n  notNull: function(expression) {\n    return expression + '!=null';\n  },\n\n  nonComputedMember: function(left, right) {\n    var SAFE_IDENTIFIER = /^[$_a-zA-Z][$_a-zA-Z0-9]*$/;\n    var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g;\n    if (SAFE_IDENTIFIER.test(right)) {\n      return left + '.' + right;\n    } else {\n      return left  + '[\"' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '\"]';\n    }\n  },\n\n  computedMember: function(left, right) {\n    return left + '[' + right + ']';\n  },\n\n  member: function(left, right, computed) {\n    if (computed) return this.computedMember(left, right);\n    return this.nonComputedMember(left, right);\n  },\n\n  getStringValue: function(item) {\n    this.assign(item, 'getStringValue(' + item + ')');\n  },\n\n  lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {\n    var self = this;\n    return function() {\n      self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);\n    };\n  },\n\n  lazyAssign: function(id, value) {\n    var self = this;\n    return function() {\n      self.assign(id, value);\n    };\n  },\n\n  stringEscapeRegex: /[^ a-zA-Z0-9]/g,\n\n  stringEscapeFn: function(c) {\n    return '\\\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);\n  },\n\n  escape: function(value) {\n    if (isString(value)) return '\\'' + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + '\\'';\n    if (isNumber(value)) return value.toString();\n    if (value === true) return 'true';\n    if (value === false) return 'false';\n    if (value === null) return 'null';\n    if (typeof value === 'undefined') return 'undefined';\n\n    throw $parseMinErr('esc', 'IMPOSSIBLE');\n  },\n\n  nextId: function(skip, init) {\n    var id = 'v' + (this.state.nextId++);\n    if (!skip) {\n      this.current().vars.push(id + (init ? '=' + init : ''));\n    }\n    return id;\n  },\n\n  current: function() {\n    return this.state[this.state.computing];\n  }\n};\n\n\nfunction ASTInterpreter($filter) {\n  this.$filter = $filter;\n}\n\nASTInterpreter.prototype = {\n  compile: function(ast) {\n    var self = this;\n    findConstantAndWatchExpressions(ast, self.$filter);\n    var assignable;\n    var assign;\n    if ((assignable = assignableAST(ast))) {\n      assign = this.recurse(assignable);\n    }\n    var toWatch = getInputs(ast.body);\n    var inputs;\n    if (toWatch) {\n      inputs = [];\n      forEach(toWatch, function(watch, key) {\n        var input = self.recurse(watch);\n        input.isPure = watch.isPure;\n        watch.input = input;\n        inputs.push(input);\n        watch.watchId = key;\n      });\n    }\n    var expressions = [];\n    forEach(ast.body, function(expression) {\n      expressions.push(self.recurse(expression.expression));\n    });\n    var fn = ast.body.length === 0 ? noop :\n             ast.body.length === 1 ? expressions[0] :\n             function(scope, locals) {\n               var lastValue;\n               forEach(expressions, function(exp) {\n                 lastValue = exp(scope, locals);\n               });\n               return lastValue;\n             };\n    if (assign) {\n      fn.assign = function(scope, value, locals) {\n        return assign(scope, locals, value);\n      };\n    }\n    if (inputs) {\n      fn.inputs = inputs;\n    }\n    return fn;\n  },\n\n  recurse: function(ast, context, create) {\n    var left, right, self = this, args;\n    if (ast.input) {\n      return this.inputs(ast.input, ast.watchId);\n    }\n    switch (ast.type) {\n    case AST.Literal:\n      return this.value(ast.value, context);\n    case AST.UnaryExpression:\n      right = this.recurse(ast.argument);\n      return this['unary' + ast.operator](right, context);\n    case AST.BinaryExpression:\n      left = this.recurse(ast.left);\n      right = this.recurse(ast.right);\n      return this['binary' + ast.operator](left, right, context);\n    case AST.LogicalExpression:\n      left = this.recurse(ast.left);\n      right = this.recurse(ast.right);\n      return this['binary' + ast.operator](left, right, context);\n    case AST.ConditionalExpression:\n      return this['ternary?:'](\n        this.recurse(ast.test),\n        this.recurse(ast.alternate),\n        this.recurse(ast.consequent),\n        context\n      );\n    case AST.Identifier:\n      return self.identifier(ast.name, context, create);\n    case AST.MemberExpression:\n      left = this.recurse(ast.object, false, !!create);\n      if (!ast.computed) {\n        right = ast.property.name;\n      }\n      if (ast.computed) right = this.recurse(ast.property);\n      return ast.computed ?\n        this.computedMember(left, right, context, create) :\n        this.nonComputedMember(left, right, context, create);\n    case AST.CallExpression:\n      args = [];\n      forEach(ast.arguments, function(expr) {\n        args.push(self.recurse(expr));\n      });\n      if (ast.filter) right = this.$filter(ast.callee.name);\n      if (!ast.filter) right = this.recurse(ast.callee, true);\n      return ast.filter ?\n        function(scope, locals, assign, inputs) {\n          var values = [];\n          for (var i = 0; i < args.length; ++i) {\n            values.push(args[i](scope, locals, assign, inputs));\n          }\n          var value = right.apply(undefined, values, inputs);\n          return context ? {context: undefined, name: undefined, value: value} : value;\n        } :\n        function(scope, locals, assign, inputs) {\n          var rhs = right(scope, locals, assign, inputs);\n          var value;\n          if (rhs.value != null) {\n            var values = [];\n            for (var i = 0; i < args.length; ++i) {\n              values.push(args[i](scope, locals, assign, inputs));\n            }\n            value = rhs.value.apply(rhs.context, values);\n          }\n          return context ? {value: value} : value;\n        };\n    case AST.AssignmentExpression:\n      left = this.recurse(ast.left, true, 1);\n      right = this.recurse(ast.right);\n      return function(scope, locals, assign, inputs) {\n        var lhs = left(scope, locals, assign, inputs);\n        var rhs = right(scope, locals, assign, inputs);\n        lhs.context[lhs.name] = rhs;\n        return context ? {value: rhs} : rhs;\n      };\n    case AST.ArrayExpression:\n      args = [];\n      forEach(ast.elements, function(expr) {\n        args.push(self.recurse(expr));\n      });\n      return function(scope, locals, assign, inputs) {\n        var value = [];\n        for (var i = 0; i < args.length; ++i) {\n          value.push(args[i](scope, locals, assign, inputs));\n        }\n        return context ? {value: value} : value;\n      };\n    case AST.ObjectExpression:\n      args = [];\n      forEach(ast.properties, function(property) {\n        if (property.computed) {\n          args.push({key: self.recurse(property.key),\n                     computed: true,\n                     value: self.recurse(property.value)\n          });\n        } else {\n          args.push({key: property.key.type === AST.Identifier ?\n                          property.key.name :\n                          ('' + property.key.value),\n                     computed: false,\n                     value: self.recurse(property.value)\n          });\n        }\n      });\n      return function(scope, locals, assign, inputs) {\n        var value = {};\n        for (var i = 0; i < args.length; ++i) {\n          if (args[i].computed) {\n            value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs);\n          } else {\n            value[args[i].key] = args[i].value(scope, locals, assign, inputs);\n          }\n        }\n        return context ? {value: value} : value;\n      };\n    case AST.ThisExpression:\n      return function(scope) {\n        return context ? {value: scope} : scope;\n      };\n    case AST.LocalsExpression:\n      return function(scope, locals) {\n        return context ? {value: locals} : locals;\n      };\n    case AST.NGValueParameter:\n      return function(scope, locals, assign) {\n        return context ? {value: assign} : assign;\n      };\n    }\n  },\n\n  'unary+': function(argument, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = argument(scope, locals, assign, inputs);\n      if (isDefined(arg)) {\n        arg = +arg;\n      } else {\n        arg = 0;\n      }\n      return context ? {value: arg} : arg;\n    };\n  },\n  'unary-': function(argument, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = argument(scope, locals, assign, inputs);\n      if (isDefined(arg)) {\n        arg = -arg;\n      } else {\n        arg = -0;\n      }\n      return context ? {value: arg} : arg;\n    };\n  },\n  'unary!': function(argument, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = !argument(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary+': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var lhs = left(scope, locals, assign, inputs);\n      var rhs = right(scope, locals, assign, inputs);\n      var arg = plusFn(lhs, rhs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary-': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var lhs = left(scope, locals, assign, inputs);\n      var rhs = right(scope, locals, assign, inputs);\n      var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary*': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary/': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary%': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary===': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary!==': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary==': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      // eslint-disable-next-line eqeqeq\n      var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary!=': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      // eslint-disable-next-line eqeqeq\n      var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary<': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary>': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary<=': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary>=': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary&&': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'binary||': function(left, right, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  'ternary?:': function(test, alternate, consequent, context) {\n    return function(scope, locals, assign, inputs) {\n      var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);\n      return context ? {value: arg} : arg;\n    };\n  },\n  value: function(value, context) {\n    return function() { return context ? {context: undefined, name: undefined, value: value} : value; };\n  },\n  identifier: function(name, context, create) {\n    return function(scope, locals, assign, inputs) {\n      var base = locals && (name in locals) ? locals : scope;\n      if (create && create !== 1 && base && base[name] == null) {\n        base[name] = {};\n      }\n      var value = base ? base[name] : undefined;\n      if (context) {\n        return {context: base, name: name, value: value};\n      } else {\n        return value;\n      }\n    };\n  },\n  computedMember: function(left, right, context, create) {\n    return function(scope, locals, assign, inputs) {\n      var lhs = left(scope, locals, assign, inputs);\n      var rhs;\n      var value;\n      if (lhs != null) {\n        rhs = right(scope, locals, assign, inputs);\n        rhs = getStringValue(rhs);\n        if (create && create !== 1) {\n          if (lhs && !(lhs[rhs])) {\n            lhs[rhs] = {};\n          }\n        }\n        value = lhs[rhs];\n      }\n      if (context) {\n        return {context: lhs, name: rhs, value: value};\n      } else {\n        return value;\n      }\n    };\n  },\n  nonComputedMember: function(left, right, context, create) {\n    return function(scope, locals, assign, inputs) {\n      var lhs = left(scope, locals, assign, inputs);\n      if (create && create !== 1) {\n        if (lhs && lhs[right] == null) {\n          lhs[right] = {};\n        }\n      }\n      var value = lhs != null ? lhs[right] : undefined;\n      if (context) {\n        return {context: lhs, name: right, value: value};\n      } else {\n        return value;\n      }\n    };\n  },\n  inputs: function(input, watchId) {\n    return function(scope, value, locals, inputs) {\n      if (inputs) return inputs[watchId];\n      return input(scope, value, locals);\n    };\n  }\n};\n\n/**\n * @constructor\n */\nfunction Parser(lexer, $filter, options) {\n  this.ast = new AST(lexer, options);\n  this.astCompiler = options.csp ? new ASTInterpreter($filter) :\n                                   new ASTCompiler($filter);\n}\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function(text) {\n    var ast = this.getAst(text);\n    var fn = this.astCompiler.compile(ast.ast);\n    fn.literal = isLiteral(ast.ast);\n    fn.constant = isConstant(ast.ast);\n    fn.oneTime = ast.oneTime;\n    return fn;\n  },\n\n  getAst: function(exp) {\n    var oneTime = false;\n    exp = exp.trim();\n\n    if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n      oneTime = true;\n      exp = exp.substring(2);\n    }\n    return {\n      ast: this.ast.ast(exp),\n      oneTime: oneTime\n    };\n  }\n};\n\nfunction getValueOf(value) {\n  return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts AngularJS {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'AngularJS'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('AngularJS');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n * @this\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cache = createMap();\n  var literals = {\n    'true': true,\n    'false': false,\n    'null': null,\n    'undefined': undefined\n  };\n  var identStart, identContinue;\n\n  /**\n   * @ngdoc method\n   * @name $parseProvider#addLiteral\n   * @description\n   *\n   * Configure $parse service to add literal values that will be present as literal at expressions.\n   *\n   * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.\n   * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.\n   *\n   **/\n  this.addLiteral = function(literalName, literalValue) {\n    literals[literalName] = literalValue;\n  };\n\n /**\n  * @ngdoc method\n  * @name $parseProvider#setIdentifierFns\n  *\n  * @description\n  *\n  * Allows defining the set of characters that are allowed in AngularJS expressions. The function\n  * `identifierStart` will get called to know if a given character is a valid character to be the\n  * first character for an identifier. The function `identifierContinue` will get called to know if\n  * a given character is a valid character to be a follow-up identifier character. The functions\n  * `identifierStart` and `identifierContinue` will receive as arguments the single character to be\n  * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in\n  * mind that the `string` parameter can be two characters long depending on the character\n  * representation. It is expected for the function to return `true` or `false`, whether that\n  * character is allowed or not.\n  *\n  * Since this function will be called extensively, keep the implementation of these functions fast,\n  * as the performance of these functions have a direct impact on the expressions parsing speed.\n  *\n  * @param {function=} identifierStart The function that will decide whether the given character is\n  *   a valid identifier start character.\n  * @param {function=} identifierContinue The function that will decide whether the given character is\n  *   a valid identifier continue character.\n  */\n  this.setIdentifierFns = function(identifierStart, identifierContinue) {\n    identStart = identifierStart;\n    identContinue = identifierContinue;\n    return this;\n  };\n\n  this.$get = ['$filter', function($filter) {\n    var noUnsafeEval = csp().noUnsafeEval;\n    var $parseOptions = {\n          csp: noUnsafeEval,\n          literals: copy(literals),\n          isIdentifierStart: isFunction(identStart) && identStart,\n          isIdentifierContinue: isFunction(identContinue) && identContinue\n        };\n    $parse.$$getAst = $$getAst;\n    return $parse;\n\n    function $parse(exp, interceptorFn) {\n      var parsedExpression, cacheKey;\n\n      switch (typeof exp) {\n        case 'string':\n          exp = exp.trim();\n          cacheKey = exp;\n\n          parsedExpression = cache[cacheKey];\n\n          if (!parsedExpression) {\n            var lexer = new Lexer($parseOptions);\n            var parser = new Parser(lexer, $filter, $parseOptions);\n            parsedExpression = parser.parse(exp);\n\n            cache[cacheKey] = addWatchDelegate(parsedExpression);\n          }\n          return addInterceptor(parsedExpression, interceptorFn);\n\n        case 'function':\n          return addInterceptor(exp, interceptorFn);\n\n        default:\n          return addInterceptor(noop, interceptorFn);\n      }\n    }\n\n    function $$getAst(exp) {\n      var lexer = new Lexer($parseOptions);\n      var parser = new Parser(lexer, $filter, $parseOptions);\n      return parser.getAst(exp).ast;\n    }\n\n    function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {\n\n      if (newValue == null || oldValueOfValue == null) { // null/undefined\n        return newValue === oldValueOfValue;\n      }\n\n      if (typeof newValue === 'object') {\n\n        // attempt to convert the value to a primitive type\n        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n        //             be cheaply dirty-checked\n        newValue = getValueOf(newValue);\n\n        if (typeof newValue === 'object' && !compareObjectIdentity) {\n          // objects/arrays are not supported - deep-watching them would be too expensive\n          return false;\n        }\n\n        // fall-through to the primitive equality check\n      }\n\n      //Primitive or NaN\n      // eslint-disable-next-line no-self-compare\n      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n    }\n\n    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {\n      var inputExpressions = parsedExpression.inputs;\n      var lastResult;\n\n      if (inputExpressions.length === 1) {\n        var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        inputExpressions = inputExpressions[0];\n        return scope.$watch(function expressionInputWatch(scope) {\n          var newInputValue = inputExpressions(scope);\n          if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, inputExpressions.isPure)) {\n            lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);\n            oldInputValueOf = newInputValue && getValueOf(newInputValue);\n          }\n          return lastResult;\n        }, listener, objectEquality, prettyPrintExpression);\n      }\n\n      var oldInputValueOfValues = [];\n      var oldInputValues = [];\n      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n        oldInputValues[i] = null;\n      }\n\n      return scope.$watch(function expressionInputsWatch(scope) {\n        var changed = false;\n\n        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n          var newInputValue = inputExpressions[i](scope);\n          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], inputExpressions[i].isPure))) {\n            oldInputValues[i] = newInputValue;\n            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n          }\n        }\n\n        if (changed) {\n          lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);\n        }\n\n        return lastResult;\n      }, listener, objectEquality, prettyPrintExpression);\n    }\n\n    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {\n      var isDone = parsedExpression.literal ? isAllDefined : isDefined;\n      var unwatch, lastValue;\n\n      var exp = parsedExpression.$$intercepted || parsedExpression;\n      var post = parsedExpression.$$interceptor || identity;\n\n      var useInputs = parsedExpression.inputs && !exp.inputs;\n\n      // Propagate the literal/inputs/constant attributes\n      // ... but not oneTime since we are handling it\n      oneTimeWatch.literal = parsedExpression.literal;\n      oneTimeWatch.constant = parsedExpression.constant;\n      oneTimeWatch.inputs = parsedExpression.inputs;\n\n      // Allow other delegates to run on this wrapped expression\n      addWatchDelegate(oneTimeWatch);\n\n      unwatch = scope.$watch(oneTimeWatch, listener, objectEquality, prettyPrintExpression);\n\n      return unwatch;\n\n      function unwatchIfDone() {\n        if (isDone(lastValue)) {\n          unwatch();\n        }\n      }\n\n      function oneTimeWatch(scope, locals, assign, inputs) {\n        lastValue = useInputs && inputs ? inputs[0] : exp(scope, locals, assign, inputs);\n        if (isDone(lastValue)) {\n          scope.$$postDigest(unwatchIfDone);\n        }\n        return post(lastValue);\n      }\n    }\n\n    function isAllDefined(value) {\n      var allDefined = true;\n      forEach(value, function(val) {\n        if (!isDefined(val)) allDefined = false;\n      });\n      return allDefined;\n    }\n\n    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n      var unwatch = scope.$watch(function constantWatch(scope) {\n        unwatch();\n        return parsedExpression(scope);\n      }, listener, objectEquality);\n      return unwatch;\n    }\n\n    function addWatchDelegate(parsedExpression) {\n      if (parsedExpression.constant) {\n        parsedExpression.$$watchDelegate = constantWatchDelegate;\n      } else if (parsedExpression.oneTime) {\n        parsedExpression.$$watchDelegate = oneTimeWatchDelegate;\n      } else if (parsedExpression.inputs) {\n        parsedExpression.$$watchDelegate = inputsWatchDelegate;\n      }\n\n      return parsedExpression;\n    }\n\n    function chainInterceptors(first, second) {\n      function chainedInterceptor(value) {\n        return second(first(value));\n      }\n      chainedInterceptor.$stateful = first.$stateful || second.$stateful;\n      chainedInterceptor.$$pure = first.$$pure && second.$$pure;\n\n      return chainedInterceptor;\n    }\n\n    function addInterceptor(parsedExpression, interceptorFn) {\n      if (!interceptorFn) return parsedExpression;\n\n      // Extract any existing interceptors out of the parsedExpression\n      // to ensure the original parsedExpression is always the $$intercepted\n      if (parsedExpression.$$interceptor) {\n        interceptorFn = chainInterceptors(parsedExpression.$$interceptor, interceptorFn);\n        parsedExpression = parsedExpression.$$intercepted;\n      }\n\n      var useInputs = false;\n\n      var fn = function interceptedExpression(scope, locals, assign, inputs) {\n        var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);\n        return interceptorFn(value);\n      };\n\n      // Maintain references to the interceptor/intercepted\n      fn.$$intercepted = parsedExpression;\n      fn.$$interceptor = interceptorFn;\n\n      // Propagate the literal/oneTime/constant attributes\n      fn.literal = parsedExpression.literal;\n      fn.oneTime = parsedExpression.oneTime;\n      fn.constant = parsedExpression.constant;\n\n      // Treat the interceptor like filters.\n      // If it is not $stateful then only watch its inputs.\n      // If the expression itself has no inputs then use the full expression as an input.\n      if (!interceptorFn.$stateful) {\n        useInputs = !parsedExpression.inputs;\n        fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];\n\n        if (!interceptorFn.$$pure) {\n          fn.inputs = fn.inputs.map(function(e) {\n              // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a\n              // non-pure interceptor function.\n              if (e.isPure === PURITY_RELATIVE) {\n                return function depurifier(s) { return e(s); };\n              }\n              return e;\n            });\n        }\n      }\n\n      return addWatchDelegate(fn);\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is a [Promises/A+](https://promisesaplus.com/)-compliant implementation of promises/deferred\n * objects inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 (ES2015) promises to some degree.\n *\n * ## $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     // perform some asynchronous operation, resolve or reject the promise when appropriate.\n *     return $q(function(resolve, reject) {\n *       setTimeout(function() {\n *         if (okToGreet(name)) {\n *           resolve('Hello, ' + name + '!');\n *         } else {\n *           reject('Greeting ' + name + ' is not allowed.');\n *         }\n *       }, 1000);\n *     });\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * ## The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * ## The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, [errorCallback], [notifyCallback])` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved\n *   with the value which is resolved in that promise using\n *   [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).\n *   It also notifies via the return value of the `notifyCallback` method. The promise cannot be\n *   resolved or rejected from the notifyCallback method. The errorCallback and notifyCallback\n *   arguments are optional.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n * ## Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * ## Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in AngularJS, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n * ## Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n *   rejecting the newly created promise. The first parameter is a function which resolves the\n *   promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\n/**\n * @ngdoc provider\n * @name $qProvider\n * @this\n *\n * @description\n */\nfunction $QProvider() {\n  var errorOnUnhandledRejections = true;\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler, errorOnUnhandledRejections);\n  }];\n\n  /**\n   * @ngdoc method\n   * @name $qProvider#errorOnUnhandledRejections\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides whether to generate an error when a rejected promise is not handled.\n   * This feature is enabled by default.\n   *\n   * @param {boolean=} value Whether to generate an error when a rejected promise is not handled.\n   * @returns {boolean|ng.$qProvider} Current value when called without a new value or self for\n   *    chaining otherwise.\n   */\n  this.errorOnUnhandledRejections = function(value) {\n    if (isDefined(value)) {\n      errorOnUnhandledRejections = value;\n      return this;\n    } else {\n      return errorOnUnhandledRejections;\n    }\n  };\n}\n\n/** @this */\nfunction $$QProvider() {\n  var errorOnUnhandledRejections = true;\n  this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $browser.defer(callback);\n    }, $exceptionHandler, errorOnUnhandledRejections);\n  }];\n\n  this.errorOnUnhandledRejections = function(value) {\n    if (isDefined(value)) {\n      errorOnUnhandledRejections = value;\n      return this;\n    } else {\n      return errorOnUnhandledRejections;\n    }\n  };\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @param {boolean=} errorOnUnhandledRejections Whether an error should be generated on unhandled\n *     promises rejections.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {\n  var $qMinErr = minErr('$q', TypeError);\n  var queueSize = 0;\n  var checkQueue = [];\n\n  /**\n   * @ngdoc method\n   * @name ng.$q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  function defer() {\n    return new Deferred();\n  }\n\n  function Deferred() {\n    var promise = this.promise = new Promise();\n    //Non prototype methods necessary to support unbound execution :/\n    this.resolve = function(val) { resolvePromise(promise, val); };\n    this.reject = function(reason) { rejectPromise(promise, reason); };\n    this.notify = function(progress) { notifyPromise(promise, progress); };\n  }\n\n\n  function Promise() {\n    this.$$state = { status: 0 };\n  }\n\n  extend(Promise.prototype, {\n    then: function(onFulfilled, onRejected, progressBack) {\n      if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {\n        return this;\n      }\n      var result = new Promise();\n\n      this.$$state.pending = this.$$state.pending || [];\n      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n      return result;\n    },\n\n    'catch': function(callback) {\n      return this.then(null, callback);\n    },\n\n    'finally': function(callback, progressBack) {\n      return this.then(function(value) {\n        return handleCallback(value, resolve, callback);\n      }, function(error) {\n        return handleCallback(error, reject, callback);\n      }, progressBack);\n    }\n  });\n\n  function processQueue(state) {\n    var fn, promise, pending;\n\n    pending = state.pending;\n    state.processScheduled = false;\n    state.pending = undefined;\n    try {\n      for (var i = 0, ii = pending.length; i < ii; ++i) {\n        markQStateExceptionHandled(state);\n        promise = pending[i][0];\n        fn = pending[i][state.status];\n        try {\n          if (isFunction(fn)) {\n            resolvePromise(promise, fn(state.value));\n          } else if (state.status === 1) {\n            resolvePromise(promise, state.value);\n          } else {\n            rejectPromise(promise, state.value);\n          }\n        } catch (e) {\n          rejectPromise(promise, e);\n          // This error is explicitly marked for being passed to the $exceptionHandler\n          if (e && e.$$passToExceptionHandler === true) {\n            exceptionHandler(e);\n          }\n        }\n      }\n    } finally {\n      --queueSize;\n      if (errorOnUnhandledRejections && queueSize === 0) {\n        nextTick(processChecks);\n      }\n    }\n  }\n\n  function processChecks() {\n    // eslint-disable-next-line no-unmodified-loop-condition\n    while (!queueSize && checkQueue.length) {\n      var toCheck = checkQueue.shift();\n      if (!isStateExceptionHandled(toCheck)) {\n        markQStateExceptionHandled(toCheck);\n        var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value);\n        if (isError(toCheck.value)) {\n          exceptionHandler(toCheck.value, errorMessage);\n        } else {\n          exceptionHandler(errorMessage);\n        }\n      }\n    }\n  }\n\n  function scheduleProcessQueue(state) {\n    if (errorOnUnhandledRejections && !state.pending && state.status === 2 && !isStateExceptionHandled(state)) {\n      if (queueSize === 0 && checkQueue.length === 0) {\n        nextTick(processChecks);\n      }\n      checkQueue.push(state);\n    }\n    if (state.processScheduled || !state.pending) return;\n    state.processScheduled = true;\n    ++queueSize;\n    nextTick(function() { processQueue(state); });\n  }\n\n  function resolvePromise(promise, val) {\n    if (promise.$$state.status) return;\n    if (val === promise) {\n      $$reject(promise, $qMinErr(\n        'qcycle',\n        'Expected promise to be resolved with value other than itself \\'{0}\\'',\n        val));\n    } else {\n      $$resolve(promise, val);\n    }\n\n  }\n\n  function $$resolve(promise, val) {\n    var then;\n    var done = false;\n    try {\n      if (isObject(val) || isFunction(val)) then = val.then;\n      if (isFunction(then)) {\n        promise.$$state.status = -1;\n        then.call(val, doResolve, doReject, doNotify);\n      } else {\n        promise.$$state.value = val;\n        promise.$$state.status = 1;\n        scheduleProcessQueue(promise.$$state);\n      }\n    } catch (e) {\n      doReject(e);\n    }\n\n    function doResolve(val) {\n      if (done) return;\n      done = true;\n      $$resolve(promise, val);\n    }\n    function doReject(val) {\n      if (done) return;\n      done = true;\n      $$reject(promise, val);\n    }\n    function doNotify(progress) {\n      notifyPromise(promise, progress);\n    }\n  }\n\n  function rejectPromise(promise, reason) {\n    if (promise.$$state.status) return;\n    $$reject(promise, reason);\n  }\n\n  function $$reject(promise, reason) {\n    promise.$$state.value = reason;\n    promise.$$state.status = 2;\n    scheduleProcessQueue(promise.$$state);\n  }\n\n  function notifyPromise(promise, progress) {\n    var callbacks = promise.$$state.pending;\n\n    if ((promise.$$state.status <= 0) && callbacks && callbacks.length) {\n      nextTick(function() {\n        var callback, result;\n        for (var i = 0, ii = callbacks.length; i < ii; i++) {\n          result = callbacks[i][0];\n          callback = callbacks[i][3];\n          try {\n            notifyPromise(result, isFunction(callback) ? callback(progress) : progress);\n          } catch (e) {\n            exceptionHandler(e);\n          }\n        }\n      });\n    }\n  }\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  function reject(reason) {\n    var result = new Promise();\n    rejectPromise(result, reason);\n    return result;\n  }\n\n  function handleCallback(value, resolver, callback) {\n    var callbackOutput = null;\n    try {\n      if (isFunction(callback)) callbackOutput = callback();\n    } catch (e) {\n      return reject(e);\n    }\n    if (isPromiseLike(callbackOutput)) {\n      return callbackOutput.then(function() {\n        return resolver(value);\n      }, reject);\n    } else {\n      return resolver(value);\n    }\n  }\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @param {Function=} successCallback\n   * @param {Function=} errorCallback\n   * @param {Function=} progressCallback\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n\n\n  function when(value, callback, errback, progressBack) {\n    var result = new Promise();\n    resolvePromise(result, value);\n    return result.then(callback, errback, progressBack);\n  }\n\n  /**\n   * @ngdoc method\n   * @name $q#resolve\n   * @kind function\n   *\n   * @description\n   * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.\n   *\n   * @param {*} value Value or a promise\n   * @param {Function=} successCallback\n   * @param {Function=} errorCallback\n   * @param {Function=} progressCallback\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n  var resolve = when;\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n\n  function all(promises) {\n    var result = new Promise(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      when(promise).then(function(value) {\n        results[key] = value;\n        if (!(--counter)) resolvePromise(result, results);\n      }, function(reason) {\n        rejectPromise(result, reason);\n      });\n    });\n\n    if (counter === 0) {\n      resolvePromise(result, results);\n    }\n\n    return result;\n  }\n\n  /**\n   * @ngdoc method\n   * @name $q#race\n   * @kind function\n   *\n   * @description\n   * Returns a promise that resolves or rejects as soon as one of those promises\n   * resolves or rejects, with the value or reason from that promise.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} a promise that resolves or rejects as soon as one of the `promises`\n   * resolves or rejects, with the value or reason from that promise.\n   */\n\n  function race(promises) {\n    var deferred = defer();\n\n    forEach(promises, function(promise) {\n      when(promise).then(deferred.resolve, deferred.reject);\n    });\n\n    return deferred.promise;\n  }\n\n  function $Q(resolver) {\n    if (!isFunction(resolver)) {\n      throw $qMinErr('norslvr', 'Expected resolverFn, got \\'{0}\\'', resolver);\n    }\n\n    var promise = new Promise();\n\n    function resolveFn(value) {\n      resolvePromise(promise, value);\n    }\n\n    function rejectFn(reason) {\n      rejectPromise(promise, reason);\n    }\n\n    resolver(resolveFn, rejectFn);\n\n    return promise;\n  }\n\n  // Let's make the instanceof operator work for promises, so that\n  // `new $q(fn) instanceof $q` would evaluate to true.\n  $Q.prototype = Promise.prototype;\n\n  $Q.defer = defer;\n  $Q.reject = reject;\n  $Q.when = when;\n  $Q.resolve = resolve;\n  $Q.all = all;\n  $Q.race = race;\n\n  return $Q;\n}\n\nfunction isStateExceptionHandled(state) {\n  return !!state.pur;\n}\nfunction markQStateExceptionHandled(state) {\n  state.pur = true;\n}\nfunction markQExceptionHandled(q) {\n  // Built-in `$q` promises will always have a `$$state` property. This check is to allow\n  // overwriting `$q` with a different promise library (e.g. Bluebird + angular-bluebird-promises).\n  // (Currently, this is the only method that might be called with a promise, even if it is not\n  // created by the built-in `$q`.)\n  if (q.$$state) {\n    markQStateExceptionHandled(q.$$state);\n  }\n}\n\n/** @this */\nfunction $$RAFProvider() { //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - This means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in the middle are expensive; so we use linked lists\n *\n * There are fewer watches than observers. This is why you don't want the observer to be implemented\n * in the same way as watch. Watch requires return of the initialization function which is expensive\n * to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @this\n *\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n  var applyAsyncId = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  function createChildScopeClass(parent) {\n    function ChildScope() {\n      this.$$watchers = this.$$nextSibling =\n          this.$$childHead = this.$$childTail = null;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$watchersCount = 0;\n      this.$id = nextUid();\n      this.$$ChildScope = null;\n      this.$$suspended = false;\n    }\n    ChildScope.prototype = parent;\n    return ChildScope;\n  }\n\n  this.$get = ['$exceptionHandler', '$parse', '$browser',\n      function($exceptionHandler, $parse, $browser) {\n\n    function destroyChildScope($event) {\n        $event.currentScope.$$destroyed = true;\n    }\n\n    function cleanUpScope($scope) {\n\n      // Support: IE 9 only\n      if (msie === 9) {\n        // There is a memory leak in IE9 if all child scopes are not disconnected\n        // completely when a scope is destroyed. So this code will recurse up through\n        // all this scopes children\n        //\n        // See issue https://github.com/angular/angular.js/issues/10706\n        if ($scope.$$childHead) {\n          cleanUpScope($scope.$$childHead);\n        }\n        if ($scope.$$nextSibling) {\n          cleanUpScope($scope.$$nextSibling);\n        }\n      }\n\n      // The code below works around IE9 and V8's memory leaks\n      //\n      // See:\n      // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n      // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n      // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n      $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =\n          $scope.$$childTail = $scope.$root = $scope.$$watchers = null;\n    }\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for\n     * an in-depth introduction and usage examples.\n     *\n     *\n     * ## Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     * When interacting with `Scope` in tests, additional helper methods are available on the\n     * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n     * details.\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this.$root = this;\n      this.$$destroyed = false;\n      this.$$suspended = false;\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$watchersCount = 0;\n      this.$$isolateBindings = null;\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n       *                              of the newly created scope. Defaults to `this` scope if not provided.\n       *                              This is used when creating a transclude scope to correctly place it\n       *                              in the scope hierarchy while maintaining the correct prototypical\n       *                              inheritance.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate, parent) {\n        var child;\n\n        parent = parent || this;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$ChildScope) {\n            this.$$ChildScope = createChildScopeClass(this);\n          }\n          child = new this.$$ChildScope();\n        }\n        child.$parent = parent;\n        child.$$prevSibling = parent.$$childTail;\n        if (parent.$$childHead) {\n          parent.$$childTail.$$nextSibling = child;\n          parent.$$childTail = child;\n        } else {\n          parent.$$childHead = parent.$$childTail = child;\n        }\n\n        // When the new scope is not isolated or we inherit from `this`, and\n        // the parent scope is destroyed, the property `$$destroyed` is inherited\n        // prototypically. In all other cases, this property needs to be set\n        // when the parent scope is destroyed.\n        // The listener needs to be added after the parent is set\n        if (isolate || parent !== this) child.$on('$destroy', destroyChildScope);\n\n        return child;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (`watchExpression` should not change\n       *   its value when executed multiple times with the same input because it may be executed multiple\n       *   times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be\n       *   [idempotent](http://en.wikipedia.org/wiki/Idempotence).)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - This should not be used to watch for changes in objects that are (or contain)\n       *   [File](https://developer.mozilla.org/docs/Web/API/File) objects due to limitations with {@link angular.copy `angular.copy`}.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Be prepared for\n       * multiple calls to your `watchExpression` because it will execute multiple times in a\n       * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       *\n       *\n       * @example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a function as a watchExpression\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This function returns the value being watched. It is called for each turn of the $digest loop\n             function() { return food; },\n             // This is the change listener, called when the value returned from the above function changes\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n       *    of `watchExpression` changes.\n       *\n       *    - `newVal` contains the current value of the `watchExpression`\n       *    - `oldVal` contains the previous value of the `watchExpression`\n       *    - `scope` refers to the current scope\n       * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {\n        var get = $parse(watchExp);\n        var fn = isFunction(listener) ? listener : noop;\n\n        if (get.$$watchDelegate) {\n          return get.$$watchDelegate(this, fn, objectEquality, get, watchExp);\n        }\n        var scope = this,\n            array = scope.$$watchers,\n            watcher = {\n              fn: fn,\n              last: initWatchVal,\n              get: get,\n              exp: prettyPrintExpression || watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        if (!array) {\n          array = scope.$$watchers = [];\n          array.$$digestWatchIndex = -1;\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n        array.$$digestWatchIndex++;\n        incrementWatchersCount(this, 1);\n\n        return function deregisterWatch() {\n          var index = arrayRemove(array, watcher);\n          if (index >= 0) {\n            incrementWatchersCount(scope, -1);\n            if (index < array.$$digestWatchIndex) {\n              array.$$digestWatchIndex--;\n            }\n          }\n          lastDirtyWatch = null;\n        };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchGroup\n       * @kind function\n       *\n       * @description\n       * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n       * If any one expression in the collection changes the `listener` is executed.\n       *\n       * - The items in the `watchExpressions` array are observed via the standard `$watch` operation. Their return\n       *   values are examined for changes on every call to `$digest`.\n       * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n       *\n       * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually\n       * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n       *\n       * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n       *    expression in `watchExpressions` changes\n       *    The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n       *    those of `watchExpression`\n       *    The `scope` refers to the current scope.\n       * @returns {function()} Returns a de-registration function for all listeners.\n       */\n      $watchGroup: function(watchExpressions, listener) {\n        var oldValues = new Array(watchExpressions.length);\n        var newValues = new Array(watchExpressions.length);\n        var deregisterFns = [];\n        var self = this;\n        var changeReactionScheduled = false;\n        var firstRun = true;\n\n        if (!watchExpressions.length) {\n          // No expressions means we call the listener ASAP\n          var shouldCall = true;\n          self.$evalAsync(function() {\n            if (shouldCall) listener(newValues, newValues, self);\n          });\n          return function deregisterWatchGroup() {\n            shouldCall = false;\n          };\n        }\n\n        if (watchExpressions.length === 1) {\n          // Special case size of one\n          return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n            newValues[0] = value;\n            oldValues[0] = oldValue;\n            listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n          });\n        }\n\n        forEach(watchExpressions, function(expr, i) {\n          var unwatchFn = self.$watch(expr, function watchGroupSubAction(value) {\n            newValues[i] = value;\n            if (!changeReactionScheduled) {\n              changeReactionScheduled = true;\n              self.$evalAsync(watchGroupAction);\n            }\n          });\n          deregisterFns.push(unwatchFn);\n        });\n\n        function watchGroupAction() {\n          changeReactionScheduled = false;\n\n          try {\n            if (firstRun) {\n              firstRun = false;\n              listener(newValues, newValues, self);\n            } else {\n              listener(newValues, oldValues, self);\n            }\n          } finally {\n            for (var i = 0; i < watchExpressions.length; i++) {\n              oldValues[i] = newValues[i];\n            }\n          }\n        }\n\n        return function deregisterWatchGroup() {\n          while (deregisterFns.length) {\n            deregisterFns.shift()();\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * @example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        // Mark the interceptor as\n        // ... $$pure when literal since the instance will change when any input changes\n        $watchCollectionInterceptor.$$pure = $parse(obj).literal;\n        // ... $stateful when non-literal since we must read the state of the collection\n        $watchCollectionInterceptor.$stateful = !$watchCollectionInterceptor.$$pure;\n\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var changeDetector = $parse(obj, $watchCollectionInterceptor);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionInterceptor(_value) {\n          newValue = _value;\n          var newLength, key, bothNaN, newItem, oldItem;\n\n          // If the new value is undefined, then return undefined as the watch may be a one-time watch\n          if (isUndefined(newValue)) return;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              oldItem = oldValue[i];\n              newItem = newValue[i];\n\n              // eslint-disable-next-line no-self-compare\n              bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n              if (!bothNaN && (oldItem !== newItem)) {\n                changeDetected++;\n                oldValue[i] = newItem;\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (hasOwnProperty.call(newValue, key)) {\n                newLength++;\n                newItem = newValue[key];\n                oldItem = oldValue[key];\n\n                if (key in oldValue) {\n                  // eslint-disable-next-line no-self-compare\n                  bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n                  if (!bothNaN && (oldItem !== newItem)) {\n                    changeDetected++;\n                    oldValue[key] = newItem;\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newItem;\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for (key in oldValue) {\n                if (!hasOwnProperty.call(newValue, key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch(changeDetector, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * @example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last, fn, get,\n            watchers,\n            dirty, ttl = TTL,\n            next, current, target = asyncQueue.length ? $rootScope : this,\n            watchLog = [],\n            logIdx, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        if (this === $rootScope && applyAsyncId !== null) {\n          // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n          // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n          $browser.defer.cancel(applyAsyncId);\n          flushApplyAsync();\n        }\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          // It's safe for asyncQueuePosition to be a local variable here because this loop can't\n          // be reentered recursively. Calling $digest from a function passed to $evalAsync would\n          // lead to a '$digest already in progress' error.\n          for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) {\n            try {\n              asyncTask = asyncQueue[asyncQueuePosition];\n              fn = asyncTask.fn;\n              fn(asyncTask.scope, asyncTask.locals);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n          asyncQueue.length = 0;\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = !current.$$suspended && current.$$watchers)) {\n              // process our watches\n              watchers.$$digestWatchIndex = watchers.length;\n              while (watchers.$$digestWatchIndex--) {\n                try {\n                  watch = watchers[watchers.$$digestWatchIndex];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    get = watch.get;\n                    if ((value = get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (isNumberNaN(value) && isNumberNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      fn = watch.fn;\n                      fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        watchLog[logIdx].push({\n                          msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n                          newVal: value,\n                          oldVal: last\n                        });\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            // (though it differs due to having the extra check for $$suspended and does not\n            // check $$listenerCount)\n            if (!(next = ((!current.$$suspended && current.$$watchersCount && current.$$childHead) ||\n                (current !== target && current.$$nextSibling)))) {\n              while (current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if ((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, watchLog);\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        // postDigestQueuePosition isn't local here because this loop can be reentered recursively.\n        while (postDigestQueuePosition < postDigestQueue.length) {\n          try {\n            postDigestQueue[postDigestQueuePosition++]();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n        postDigestQueue.length = postDigestQueuePosition = 0;\n\n        // Check for changes to browser url that happened during the $digest\n        // (for which no event is fired; e.g. via `history.pushState()`)\n        $browser.$$checkUrlChange();\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$suspend\n       * @kind function\n       *\n       * @description\n       * Suspend watchers of this scope subtree so that they will not be invoked during digest.\n       *\n       * This can be used to optimize your application when you know that running those watchers\n       * is redundant.\n       *\n       * **Warning**\n       *\n       * Suspending scopes from the digest cycle can have unwanted and difficult to debug results.\n       * Only use this approach if you are confident that you know what you are doing and have\n       * ample tests to ensure that bindings get updated as you expect.\n       *\n       * Some of the things to consider are:\n       *\n       * * Any external event on a directive/component will not trigger a digest while the hosting\n       *   scope is suspended - even if the event handler calls `$apply()` or `$rootScope.$digest()`.\n       * * Transcluded content exists on a scope that inherits from outside a directive but exists\n       *   as a child of the directive's containing scope. If the containing scope is suspended the\n       *   transcluded scope will also be suspended, even if the scope from which the transcluded\n       *   scope inherits is not suspended.\n       * * Multiple directives trying to manage the suspended status of a scope can confuse each other:\n       *    * A call to `$suspend()` on an already suspended scope is a no-op.\n       *    * A call to `$resume()` on a non-suspended scope is a no-op.\n       *    * If two directives suspend a scope, then one of them resumes the scope, the scope will no\n       *      longer be suspended. This could result in the other directive believing a scope to be\n       *      suspended when it is not.\n       * * If a parent scope is suspended then all its descendants will be also excluded from future\n       *   digests whether or not they have been suspended themselves. Note that this also applies to\n       *   isolate child scopes.\n       * * Calling `$digest()` directly on a descendant of a suspended scope will still run the watchers\n       *   for that scope and its descendants. When digesting we only check whether the current scope is\n       *   locally suspended, rather than checking whether it has a suspended ancestor.\n       * * Calling `$resume()` on a scope that has a suspended ancestor will not cause the scope to be\n       *   included in future digests until all its ancestors have been resumed.\n       * * Resolved promises, e.g. from explicit `$q` deferreds and `$http` calls, trigger `$apply()`\n       *   against the `$rootScope` and so will still trigger a global digest even if the promise was\n       *   initiated by a component that lives on a suspended scope.\n       */\n      $suspend: function() {\n        this.$$suspended = true;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$isSuspended\n       * @kind function\n       *\n       * @description\n       * Call this method to determine if this scope has been explicitly suspended. It will not\n       * tell you whether an ancestor has been suspended.\n       * To determine if this scope will be excluded from a digest triggered at the $rootScope,\n       * for example, you must check all its ancestors:\n       *\n       * ```\n       * function isExcludedFromDigest(scope) {\n       *   while(scope) {\n       *     if (scope.$isSuspended()) return true;\n       *     scope = scope.$parent;\n       *   }\n       *   return false;\n       * ```\n       *\n       * Be aware that a scope may not be included in digests if it has a suspended ancestor,\n       * even if `$isSuspended()` returns false.\n       *\n       * @returns true if the current scope has been suspended.\n       */\n      $isSuspended: function() {\n        return this.$$suspended;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$resume\n       * @kind function\n       *\n       * @description\n       * Resume watchers of this scope subtree in case it was suspended.\n       *\n       * See {@link $rootScope.Scope#$suspend} for information about the dangers of using this approach.\n       */\n      $resume: function() {\n        this.$$suspended = false;\n      },\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // We can't destroy a scope that has been already destroyed.\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n\n        if (this === $rootScope) {\n          //Remove handlers attached to window when $rootScope is removed\n          $browser.$$applicationDestroyed();\n        }\n\n        incrementWatchersCount(this, -this.$$watchersCount);\n        for (var eventName in this.$$listenerCount) {\n          decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n        }\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent && parent.$$childHead === this) parent.$$childHead = this.$$nextSibling;\n        if (parent && parent.$$childTail === this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n        // Disable listeners, watchers and apply/digest methods\n        this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n        this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n        this.$$listeners = {};\n\n        // Disconnect the next sibling to prevent `cleanUpScope` destroying those too\n        this.$$nextSibling = null;\n        cleanUpScope(this);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating AngularJS\n       * expressions.\n       *\n       * @example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An AngularJS expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An AngularJS expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       */\n      $evalAsync: function(expr, locals) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !asyncQueue.length) {\n          $browser.defer(function() {\n            if (asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          }, null, '$evalAsync');\n        }\n\n        asyncQueue.push({scope: this, fn: $parse(expr), locals: locals});\n      },\n\n      $$postDigest: function(fn) {\n        postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in AngularJS from outside of the AngularJS\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the AngularJS framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * **Life cycle: Pseudo-Code of `$apply()`**\n       *\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An AngularJS expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          try {\n            return this.$eval(expr);\n          } finally {\n            clearPhase();\n          }\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            // eslint-disable-next-line no-unsafe-finally\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$applyAsync\n       * @kind function\n       *\n       * @description\n       * Schedule the invocation of $apply to occur at a later time. The actual time difference\n       * varies across browsers, but is typically around ~10 milliseconds.\n       *\n       * This can be used to queue up multiple expressions which need to be evaluated in the same\n       * digest.\n       *\n       * @param {(string|function())=} exp An AngularJS expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       */\n      $applyAsync: function(expr) {\n        var scope = this;\n        if (expr) {\n          applyAsyncQueue.push($applyAsyncExpression);\n        }\n        expr = $parse(expr);\n        scheduleApplyAsync();\n\n        function $applyAsyncExpression() {\n          scope.$eval(expr);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n       *     event propagates through the scope hierarchy, this property is set to null.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = namedListeners.indexOf(listener);\n          if (indexOfListener !== -1) {\n            // Use delete in the hope of the browser deallocating the memory for the array entry,\n            // while not shifting the array indexes of other listeners.\n            // See issue https://github.com/angular/angular.js/issues/16135\n            delete namedListeners[indexOfListener];\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i = 0, length = namedListeners.length; i < length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) {\n            break;\n          }\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        event.currentScope = null;\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            };\n\n        if (!target.$$listenerCount[name]) return event;\n\n        var listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i = 0, length = listeners.length; i < length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount and\n          // does not check $$suspended)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while (current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        event.currentScope = null;\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n    var asyncQueue = $rootScope.$$asyncQueue = [];\n    var postDigestQueue = $rootScope.$$postDigestQueue = [];\n    var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n    var postDigestQueuePosition = 0;\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function incrementWatchersCount(current, count) {\n      do {\n        current.$$watchersCount += count;\n      } while ((current = current.$parent));\n    }\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n\n    function flushApplyAsync() {\n      while (applyAsyncQueue.length) {\n        try {\n          applyAsyncQueue.shift()();\n        } catch (e) {\n          $exceptionHandler(e);\n        }\n      }\n      applyAsyncId = null;\n    }\n\n    function scheduleApplyAsync() {\n      if (applyAsyncId === null) {\n        applyAsyncId = $browser.defer(function() {\n          $rootScope.$apply(flushApplyAsync);\n        }, null, '$applyAsync');\n      }\n    }\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $rootElement\n *\n * @description\n * The root element of AngularJS application. This is either the element where {@link\n * ng.directive:ngApp ngApp} was declared or the element passed into\n * {@link angular.bootstrap}. The element represents the root element of application. It is also the\n * location where the application's {@link auto.$injector $injector} service gets\n * published, and can be retrieved using `$rootElement.injector()`.\n */\n\n\n// the implementation is in angular.bootstrap\n\n/**\n * @this\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n\n  var aHrefSanitizationTrustedUrlList = /^\\s*(https?|s?ftp|mailto|tel|file):/,\n    imgSrcSanitizationTrustedUrlList = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for determining trusted safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via HTML anchor links.\n   *\n   * Any url due to be assigned to an `a[href]` attribute via interpolation is marked as requiring\n   * the $sce.URL security context. When interpolation occurs a call is made to `$sce.trustAsUrl(url)`\n   * which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize the potentially malicious URL.\n   *\n   * If the URL matches the `aHrefSanitizationTrustedUrlList` regular expression, it is returned unchanged.\n   *\n   * If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written\n   * to the DOM it is inactive and potentially malicious code will not be executed.\n   *\n   * @param {RegExp=} regexp New regexp to trust urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationTrustedUrlList = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationTrustedUrlList = regexp;\n      return this;\n    }\n    return aHrefSanitizationTrustedUrlList;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for determining trusted safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via HTML image src links.\n   *\n   * Any URL due to be assigned to an `img[src]` attribute via interpolation is marked as requiring\n   * the $sce.MEDIA_URL security context. When interpolation occurs a call is made to\n   * `$sce.trustAsMediaUrl(url)` which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize\n   * the potentially malicious URL.\n   *\n   * If the URL matches the `imgSrcSanitizationTrustedUrlList` regular expression, it is returned\n   * unchanged.\n   *\n   * If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written\n   * to the DOM it is inactive and potentially malicious code will not be executed.\n   *\n   * @param {RegExp=} regexp New regexp to trust urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationTrustedUrlList = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationTrustedUrlList = regexp;\n      return this;\n    }\n    return imgSrcSanitizationTrustedUrlList;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isMediaUrl) {\n      // if (!uri) return uri;\n      var regex = isMediaUrl ? imgSrcSanitizationTrustedUrlList : aHrefSanitizationTrustedUrlList;\n      var normalizedVal = urlResolve(uri && uri.trim()).href;\n      if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n        return 'unsafe:' + normalizedVal;\n      }\n      return uri;\n    };\n  };\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n *     Any commits to this file should be reviewed with security in mind.  *\n *   Changes to this file can potentially create security vulnerabilities. *\n *          An approval from 2 Core members with history of modifying      *\n *                         this file is required.                          *\n *                                                                         *\n *  Does the change somehow allow for arbitrary javascript to be executed? *\n *    Or allows for someone to change the prototype of built-in objects?   *\n *     Or gives undesired access to variables likes document or window?    *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\n/* exported $SceProvider, $SceDelegateProvider */\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  // HTML is used when there's HTML rendered (e.g. ng-bind-html, iframe srcdoc binding).\n  HTML: 'html',\n\n  // Style statements or stylesheets. Currently unused in AngularJS.\n  CSS: 'css',\n\n  // An URL used in a context where it refers to the source of media, which are not expected to be run\n  // as scripts, such as an image, audio, video, etc.\n  MEDIA_URL: 'mediaUrl',\n\n  // An URL used in a context where it does not refer to a resource that loads code.\n  // A value that can be trusted as a URL can also trusted as a MEDIA_URL.\n  URL: 'url',\n\n  // RESOURCE_URL is a subtype of URL used where the referred-to resource could be interpreted as\n  // code. (e.g. ng-include, script src binding, templateUrl)\n  // A value that can be trusted as a RESOURCE_URL, can also trusted as a URL and a MEDIA_URL.\n  RESOURCE_URL: 'resourceUrl',\n\n  // Script. Currently unused in AngularJS.\n  JS: 'js'\n};\n\n// Helper functions follow.\n\nvar UNDERSCORE_LOWERCASE_REGEXP = /_([a-z])/g;\n\nfunction snakeToCamel(name) {\n  return name\n    .replace(UNDERSCORE_LOWERCASE_REGEXP, fnCamelCaseReplace);\n}\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace(/\\\\\\*\\\\\\*/g, '.*').\n                  replace(/\\\\\\*/g, '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * For an overview of this service and the functionnality it provides in AngularJS, see the main\n * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how\n * SCE works in their application, which shouldn't be needed in most cases.\n *\n * <div class=\"alert alert-danger\">\n * AngularJS strongly relies on contextual escaping for the security of bindings: disabling or\n * modifying this might cause cross site scripting (XSS) vulnerabilities. For libraries owners,\n * changes to this service will also influence users, so be extra careful and document your changes.\n * </div>\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own trusted and banned resource lists for trusting URLs used for loading AngularJS resources\n * such as templates.  Refer {@link ng.$sceDelegateProvider#trustedResourceUrlList\n * $sceDelegateProvider.trustedResourceUrlList} and {@link\n * ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @this\n *\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate service}, used as a delegate for {@link ng.$sce Strict Contextual Escaping (SCE)}.\n *\n * The `$sceDelegateProvider` allows one to get/set the `trustedResourceUrlList` and\n * `bannedResourceUrlList` used to ensure that the URLs used for sourcing AngularJS templates and\n * other script-running URLs are safe (all places that use the `$sce.RESOURCE_URL` context). See\n * {@link ng.$sceDelegateProvider#trustedResourceUrlList\n * $sceDelegateProvider.trustedResourceUrlList} and\n * {@link ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList},\n *\n * For the general details about this service in AngularJS, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.trustedResourceUrlList([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The banned resource URL list overrides the trusted resource URL list so the open redirect\n *    // here is blocked.\n *    $sceDelegateProvider.bannedResourceUrlList([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n * Note that an empty trusted resource URL list will block every resource URL from being loaded, and will require\n * you to manually mark each one as trusted with `$sce.trustAsResourceUrl`. However, templates\n * requested by {@link ng.$templateRequest $templateRequest} that are present in\n * {@link ng.$templateCache $templateCache} will not go through this check. If you have a mechanism\n * to populate your templates in that cache at config time, then it is a good idea to remove 'self'\n * from the trusted resource URL lsit. This helps to mitigate the security impact of certain types\n * of issues, like for instance attacker-controlled `ng-includes`.\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var trustedResourceUrlList = ['self'],\n      bannedResourceUrlList = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#trustedResourceUrlList\n   * @kind function\n   *\n   * @param {Array=} trustedResourceUrlList When provided, replaces the trustedResourceUrlList with\n   *     the value provided.  This must be an array or null.  A snapshot of this array is used so\n   *     further changes to the array are ignored.\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   * @return {Array} The currently set trusted resource URL array.\n   *\n   * @description\n   * Sets/Gets the list trusted of resource URLs.\n   *\n   * The **default value** when no `trustedResourceUrlList` has been explicitly set is `['self']`\n   * allowing only same origin resource requests.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** the default `trustedResourceUrlList` of 'self' is not recommended if your app shares\n   * its origin with other apps! It is a good idea to limit it to only your application's directory.\n   * </div>\n   */\n  this.trustedResourceUrlList = function(value) {\n    if (arguments.length) {\n      trustedResourceUrlList = adjustMatchers(value);\n    }\n    return trustedResourceUrlList;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @deprecated\n   * sinceVersion=\"1.8.1\"\n   *\n   * This method is deprecated. Use {@link $sceDelegateProvider#trustedResourceUrlList\n   * trustedResourceUrlList} instead.\n   */\n  Object.defineProperty(this, 'resourceUrlWhitelist', {\n    get: function() {\n      return this.trustedResourceUrlList;\n    },\n    set: function(value) {\n      this.trustedResourceUrlList = value;\n    }\n  });\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#bannedResourceUrlList\n   * @kind function\n   *\n   * @param {Array=} bannedResourceUrlList When provided, replaces the `bannedResourceUrlList` with\n   *     the value provided. This must be an array or null. A snapshot of this array is used so\n   *     further changes to the array are ignored.</p><p>\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.</p><p>\n   *     The typical usage for the `bannedResourceUrlList` is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *     </p><p>\n   *     Finally, **the banned resource URL list overrides the trusted resource URL list** and has\n   *     the final say.\n   *\n   * @return {Array} The currently set `bannedResourceUrlList` array.\n   *\n   * @description\n   * Sets/Gets the `bannedResourceUrlList` of trusted resource URLs.\n   *\n   * The **default value** when no trusted resource URL list has been explicitly set is the empty\n   * array (i.e. there is no `bannedResourceUrlList`.)\n   */\n  this.bannedResourceUrlList = function(value) {\n    if (arguments.length) {\n      bannedResourceUrlList = adjustMatchers(value);\n    }\n    return bannedResourceUrlList;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @deprecated\n   * sinceVersion=\"1.8.1\"\n   *\n   * This method is deprecated. Use {@link $sceDelegateProvider#bannedResourceUrlList\n   * bannedResourceUrlList} instead.\n   */\n  Object.defineProperty(this, 'resourceUrlBlacklist', {\n    get: function() {\n      return this.bannedResourceUrlList;\n    },\n    set: function(value) {\n      this.bannedResourceUrlList = value;\n    }\n  });\n\n  this.$get = ['$injector', '$$sanitizeUri', function($injector, $$sanitizeUri) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl) || urlIsSameOriginAsBaseUrl(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the trusted resource URL list allows this url.\n      for (i = 0, n = trustedResourceUrlList.length; i < n; i++) {\n        if (matchUrl(trustedResourceUrlList[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the banned resource URL list has blocked this url.\n        for (i = 0, n = bannedResourceUrlList.length; i < n; i++) {\n          if (matchUrl(bannedResourceUrlList[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.MEDIA_URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(byType[SCE_CONTEXTS.MEDIA_URL]);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns a trusted representation of the parameter for the specified context. This trusted\n     * object will later on be used as-is, without any security check, by bindings or directives\n     * that require this security context.\n     * For instance, marking a string as trusted for the `$sce.HTML` context will entirely bypass\n     * the potential `$sanitize` call in corresponding `$sce.HTML` bindings or directives, such as\n     * `ng-bind-html`. Note that in most cases you won't need to call this function: if you have the\n     * sanitizer loaded, passing the value itself will render all the HTML that does not pose a\n     * security risk.\n     *\n     * See {@link ng.$sceDelegate#getTrusted getTrusted} for the function that will consume those\n     * trusted values, and {@link ng.$sce $sce} for general documentation about strict contextual\n     * escaping.\n     *\n     * @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`,\n     *     `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`.\n     *\n     * @param {*} value The value that should be considered trusted.\n     * @return {*} A trusted representation of value, that can be used in the given context.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, it must be returned as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *     call or anything else.\n     * @return {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Given an object and a security context in which to assign it, returns a value that's safe to\n     * use in this context, which was represented by the parameter. To do so, this function either\n     * unwraps the safe type it has been given (for instance, a {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`} result), or it might try to sanitize the value given, depending on\n     * the context and sanitizer availablility.\n     *\n     * The contexts that can be sanitized are $sce.MEDIA_URL, $sce.URL and $sce.HTML. The first two are available\n     * by default, and the third one relies on the `$sanitize` service (which may be loaded through\n     * the `ngSanitize` module). Furthermore, for $sce.RESOURCE_URL context, a plain string may be\n     * accepted if the resource url policy defined by {@link ng.$sceDelegateProvider#trustedResourceUrlList\n     * `$sceDelegateProvider.trustedResourceUrlList`} and {@link ng.$sceDelegateProvider#bannedResourceUrlList\n     * `$sceDelegateProvider.bannedResourceUrlList`} accepts that resource.\n     *\n     * This function will throw if the safe type isn't appropriate for this context, or if the\n     * value given cannot be accepted in the context (which might be caused by sanitization not\n     * being available, or the value not being recognized as safe).\n     *\n     * <div class=\"alert alert-danger\">\n     * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting\n     * (XSS) vulnerability in your application.\n     * </div>\n     *\n     * @param {string} type The context in which this value is to be used (such as `$sce.HTML`).\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call, or anything else (which will not be considered trusted.)\n     * @return {*} A version of the value that's safe to use in the given context, or throws an\n     *     exception if this is impossible.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      // If maybeTrusted is a trusted class instance or subclass instance, then unwrap and return\n      // as-is.\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n\n      // If maybeTrusted is a trusted class instance but not of the correct trusted type\n      // then unwrap it and allow it to pass through to the rest of the checks\n      if (isFunction(maybeTrusted.$$unwrapTrustedValue)) {\n        maybeTrusted = maybeTrusted.$$unwrapTrustedValue();\n      }\n\n      // If we get here, then we will either sanitize the value or throw an exception.\n      if (type === SCE_CONTEXTS.MEDIA_URL || type === SCE_CONTEXTS.URL) {\n        // we attempt to sanitize non-resource URLs\n        return $$sanitizeUri(maybeTrusted.toString(), type === SCE_CONTEXTS.MEDIA_URL);\n      } else if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        // htmlSanitizer throws its own error when no sanitizer is available.\n        return htmlSanitizer(maybeTrusted);\n      }\n      // Default error when the $sce service has no way to make the input safe.\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @this\n *\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * ## Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS constrains bindings to only render\n * trusted values. Its goal is to assist in writing code in a way that (a) is secure by default, and\n * (b) makes auditing for security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * ### Overview\n *\n * To systematically block XSS security bugs, AngularJS treats all values as untrusted by default in\n * HTML or sensitive URL bindings. When binding untrusted values, AngularJS will automatically\n * run security checks on them (sanitizations, trusted URL resource, depending on context), or throw\n * when it cannot guarantee the security of the result. That behavior depends strongly on contexts:\n * HTML can be sanitized, but template URLs cannot, for instance.\n *\n * To illustrate this, consider the `ng-bind-html` directive. It renders its value directly as HTML:\n * we call that the *context*. When given an untrusted input, AngularJS will attempt to sanitize it\n * before rendering if a sanitizer is available, and throw otherwise. To bypass sanitization and\n * render the input as-is, you will need to mark it as trusted for that context before attempting\n * to bind it.\n *\n * As of version 1.2, AngularJS ships with SCE enabled by default.\n *\n * ### In practice\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\" aria-label=\"User input\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV, which would\n * be an XSS security bug. In a more realistic example, one may be rendering user comments, blog\n * articles, etc. via bindings. (HTML is just one example of a context where rendering user\n * controlled input creates security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, AngularJS makes sure bindings go through that sanitization, or\n * any similar validation process, unless there's a good reason to trust the given value in this\n * context.  That trust is formalized with a function call. This means that as a developer, you\n * can assume all untrusted bindings are safe. Then, to audit your code for binding security issues,\n * you just need to ensure the values you mark as trusted indeed are safe - because they were\n * received from your server, sanitized by your library, etc. You can organize your codebase to\n * help with this - perhaps allowing only the files in a specific directory to do this.\n * Ensuring that the internal API exposed by that code doesn't markup arbitrary values as safe then\n * becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * build the trusted versions of your values.\n *\n * ### How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Think of this function as\n * a way to enforce the required security context in your data sink. Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs\n * the {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. Also,\n * when binding without directives, AngularJS will understand the context of your bindings\n * automatically.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ### Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, AngularJS only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either add them to the {@link ng.$sceDelegateProvider#trustedResourceUrlList\n * trustedResourceUrlList} or {@link ng.$sce#trustAsResourceUrl wrap them} into trusted values.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ### This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works (remember to include the\n * `ngSanitize` module). The `$sceDelegate` will also use the `$sanitize` service if it is available\n * when binding untrusted values to `$sce.HTML` context.\n * AngularJS provides an implementation in `angular-sanitize.js`, and if you\n * wish to use it, you will also need to depend on the {@link ngSanitize `ngSanitize`} module in\n * your application.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#trustedResourceUrlList trusted resource URL list} and {@link\n * ng.$sceDelegateProvider#bannedResourceUrlList banned resource URL list} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ### What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.MEDIA_URL`    | For URLs that are safe to render as media. Is automatically converted from string by sanitizing when needed. |\n * | `$sce.URL`          | For URLs that are safe to follow as links. Is automatically converted from string by sanitizing when needed. Note that `$sce.URL` makes a stronger statement about the URL than `$sce.MEDIA_URL` does and therefore contexts requiring values trusted for `$sce.URL` can be used anywhere that values trusted for `$sce.MEDIA_URL` are required.|\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required. <br><br> The {@link $sceDelegateProvider#trustedResourceUrlList $sceDelegateProvider#trustedResourceUrlList()} and {@link $sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider#bannedResourceUrlList()} can be used to restrict trusted origins for `RESOURCE_URL` |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n *\n * <div class=\"alert alert-warning\">\n * Be aware that, before AngularJS 1.7.0, `a[href]` and `img[src]` used to sanitize their\n * interpolated values directly rather than rely upon {@link ng.$sce#getTrusted `$sce.getTrusted`}.\n *\n * **As of 1.7.0, this is no longer the case.**\n *\n * Now such interpolations are marked as requiring `$sce.URL` (for `a[href]`) or `$sce.MEDIA_URL`\n * (for `img[src]`), so that the sanitization happens (via `$sce.getTrusted...`) when the `$interpolate`\n * service evaluates the expressions.\n * </div>\n *\n * There are no CSS or JS context bindings in AngularJS currently, so their corresponding `$sce.trustAs`\n * functions aren't useful yet. This might evolve.\n *\n * ### Format of items in {@link ng.$sceDelegateProvider#trustedResourceUrlList trustedResourceUrlList}/{@link ng.$sceDelegateProvider#bannedResourceUrlList bannedResourceUrlList} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'.  It's a useful wildcard for use\n *      for matching resource URL lists.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      appropriate for use in a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  E.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ### Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\" name=\"sce-service\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"AppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   angular.module('mySceApp', ['ngSanitize'])\n *     .controller('AppController', ['$http', '$templateCache', '$sce',\n *       function AppController($http, $templateCache, $sce) {\n *         var self = this;\n *         $http.get('test_data.json', {cache: $templateCache}).then(function(response) {\n *           self.userComments = response.data;\n *         });\n *         self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *             '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *             'sanitization.&quot;\">Hover over this text.</span>');\n *       }]);\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getAttribute('innerHTML'))\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getAttribute('innerHTML')).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time. Also do note that this is an app-wide setting, so if\n * you are writing a library, you will cause security bugs applications using it.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects or libraries.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE application-wide.\n   * @return {boolean} True if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function(value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way. In some future, we may not use\n   * inheritance anymore. That is OK because no code outside of sce.js and sceSpecs.js would need to\n   * be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sceDelegate', function(\n                $parse,   $sceDelegate) {\n    // Support: IE 9-11 only\n    // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && msie < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} True if SCE is enabled, false otherwise.  If you want to set the value, you\n     *     have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function() {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts AngularJS {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return $parse(expr, function(value) {\n          return sce.getTrusted(type, value);\n        });\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, returns a\n     * wrapped object that represents your value, and the trust you have in its safety for the given\n     * context. AngularJS can then use that value as-is in bindings of the specified secure context.\n     * This is used in bindings for `ng-bind-html`, `ng-include`, and most `src` attribute\n     * interpolations. See {@link ng.$sce $sce} for strict contextual escaping.\n     *\n     * @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`,\n     *     `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`.\n     *\n     * @param {*} value The value that that should be considered trusted.\n     * @return {*} A wrapped version of value that can be used as a trusted variant of your `value`\n     *     in the context you specified.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to mark as trusted for `$sce.HTML` context.\n     * @return {*} A wrapped version of value that can be used as a trusted variant of your `value`\n     *     in `$sce.HTML` context (like `ng-bind-html`).\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsCss(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.CSS, value)`}\n     *\n     * @param {*} value The value to mark as trusted for `$sce.CSS` context.\n     * @return {*} A wrapped version of value that can be used as a trusted variant\n     *     of your `value` in `$sce.CSS` context. This context is currently unused, so there are\n     *     almost no reasons to use this function so far.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to mark as trusted for `$sce.URL` context.\n     * @return {*} A wrapped version of value that can be used as a trusted variant of your `value`\n     *     in `$sce.URL` context. That context is currently unused, so there are almost no reasons\n     *     to use this function so far.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to mark as trusted for `$sce.RESOURCE_URL` context.\n     * @return {*} A wrapped version of value that can be used as a trusted variant of your `value`\n     *     in `$sce.RESOURCE_URL` context (template URLs in `ng-include`, most `src` attribute\n     *     bindings, ...)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to mark as trusted for `$sce.JS` context.\n     * @return {*} A wrapped version of value that can be used as a trusted variant of your `value`\n     *     in `$sce.JS` context. That context is currently unused, so there are almost no reasons to\n     *     use this function so far.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes any input, and either returns a value that's safe to use in the specified context,\n     * or throws an exception. This function is aware of trusted values created by the `trustAs`\n     * function and its shorthands, and when contexts are appropriate, returns the unwrapped value\n     * as-is. Finally, this function can also throw when there is no way to turn `maybeTrusted` in a\n     * safe value (e.g., no sanitization is available or possible.)\n     *\n     * @param {string} type The context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs\n     *     `$sce.trustAs`} call, or anything else (which will not be considered trusted.)\n     * @return {*} A version of the value that's safe to use in the given context, or throws an\n     *     exception if this is impossible.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @return {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @return {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @return {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @return {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @return {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @return {function(context, locals)} A function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the\n     *      strings are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values\n     *      in `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function(enumValue, name) {\n      var lName = lowercase(name);\n      sce[snakeToCamel('parse_as_' + lName)] = function(expr) {\n        return parse(enumValue, expr);\n      };\n      sce[snakeToCamel('get_trusted_' + lName)] = function(value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[snakeToCamel('trust_as_' + lName)] = function(value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/* exported $SnifferProvider */\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n * @this\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        // Chrome Packaged Apps are not allowed to access `history.pushState`.\n        // If not sandboxed, they can be detected by the presence of `chrome.app.runtime`\n        // (see https://developer.chrome.com/apps/api_index). If sandboxed, they can be detected by\n        // the presence of an extension runtime ID and the absence of other Chrome runtime APIs\n        // (see https://developer.chrome.com/apps/manifest/sandbox).\n        // (NW.js apps have access to Chrome APIs, but do support `history`.)\n        isNw = $window.nw && $window.nw.process,\n        isChromePackagedApp =\n            !isNw &&\n            $window.chrome &&\n            ($window.chrome.app && $window.chrome.app.runtime ||\n                !$window.chrome.app && $window.chrome.runtime && $window.chrome.runtime.id),\n        hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState,\n        android =\n          toInt((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false;\n\n    if (bodyStyle) {\n      // Support: Android <5, Blackberry Browser 10, default Chrome in Android 4.4.x\n      // Mentioned browsers need a -webkit- prefix for transitions & animations.\n      transitions = !!('transition' in bodyStyle || 'webkitTransition' in bodyStyle);\n      animations = !!('animation' in bodyStyle || 'webkitAnimation' in bodyStyle);\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      history: !!(hasHistoryPushState && !(android < 4) && !boxee),\n      hasEvent: function(event) {\n        // Support: IE 9-11 only\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        // IE10+ implements 'input' event but it erroneously fires under various situations,\n        // e.g. when placeholder changes, or a form is focused.\n        if (event === 'input' && msie) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      transitions: transitions,\n      animations: animations,\n      android: android\n    };\n  }];\n}\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $$taskTrackerFactory\n * @description\n * A function to create `TaskTracker` instances.\n *\n * A `TaskTracker` can keep track of pending tasks (grouped by type) and can notify interested\n * parties when all pending tasks (or tasks of a specific type) have been completed.\n *\n * @param {$log} log - A logger instance (such as `$log`). Used to log error during callback\n *     execution.\n *\n * @this\n */\nfunction $$TaskTrackerFactoryProvider() {\n  this.$get = valueFn(function(log) { return new TaskTracker(log); });\n}\n\nfunction TaskTracker(log) {\n  var self = this;\n  var taskCounts = {};\n  var taskCallbacks = [];\n\n  var ALL_TASKS_TYPE = self.ALL_TASKS_TYPE = '$$all$$';\n  var DEFAULT_TASK_TYPE = self.DEFAULT_TASK_TYPE = '$$default$$';\n\n  /**\n   * Execute the specified function and decrement the appropriate `taskCounts` counter.\n   * If the counter reaches 0, all corresponding `taskCallbacks` are executed.\n   *\n   * @param {Function} fn - The function to execute.\n   * @param {string=} [taskType=DEFAULT_TASK_TYPE] - The type of task that is being completed.\n   */\n  self.completeTask = completeTask;\n\n  /**\n   * Increase the task count for the specified task type (or the default task type if non is\n   * specified).\n   *\n   * @param {string=} [taskType=DEFAULT_TASK_TYPE] - The type of task whose count will be increased.\n   */\n  self.incTaskCount = incTaskCount;\n\n  /**\n   * Execute the specified callback when all pending tasks have been completed.\n   *\n   * If there are no pending tasks, the callback is executed immediately. You can optionally limit\n   * the tasks that will be waited for to a specific type, by passing a `taskType`.\n   *\n   * @param {function} callback - The function to call when there are no pending tasks.\n   * @param {string=} [taskType=ALL_TASKS_TYPE] - The type of tasks that will be waited for.\n   */\n  self.notifyWhenNoPendingTasks = notifyWhenNoPendingTasks;\n\n  function completeTask(fn, taskType) {\n    taskType = taskType || DEFAULT_TASK_TYPE;\n\n    try {\n      fn();\n    } finally {\n      decTaskCount(taskType);\n\n      var countForType = taskCounts[taskType];\n      var countForAll = taskCounts[ALL_TASKS_TYPE];\n\n      // If at least one of the queues (`ALL_TASKS_TYPE` or `taskType`) is empty, run callbacks.\n      if (!countForAll || !countForType) {\n        var getNextCallback = !countForAll ? getLastCallback : getLastCallbackForType;\n        var nextCb;\n\n        while ((nextCb = getNextCallback(taskType))) {\n          try {\n            nextCb();\n          } catch (e) {\n            log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  function decTaskCount(taskType) {\n    taskType = taskType || DEFAULT_TASK_TYPE;\n    if (taskCounts[taskType]) {\n      taskCounts[taskType]--;\n      taskCounts[ALL_TASKS_TYPE]--;\n    }\n  }\n\n  function getLastCallback() {\n    var cbInfo = taskCallbacks.pop();\n    return cbInfo && cbInfo.cb;\n  }\n\n  function getLastCallbackForType(taskType) {\n    for (var i = taskCallbacks.length - 1; i >= 0; --i) {\n      var cbInfo = taskCallbacks[i];\n      if (cbInfo.type === taskType) {\n        taskCallbacks.splice(i, 1);\n        return cbInfo.cb;\n      }\n    }\n  }\n\n  function incTaskCount(taskType) {\n    taskType = taskType || DEFAULT_TASK_TYPE;\n    taskCounts[taskType] = (taskCounts[taskType] || 0) + 1;\n    taskCounts[ALL_TASKS_TYPE] = (taskCounts[ALL_TASKS_TYPE] || 0) + 1;\n  }\n\n  function notifyWhenNoPendingTasks(callback, taskType) {\n    taskType = taskType || ALL_TASKS_TYPE;\n    if (!taskCounts[taskType]) {\n      callback();\n    } else {\n      taskCallbacks.push({type: taskType, cb: callback});\n    }\n  }\n}\n\nvar $templateRequestMinErr = minErr('$templateRequest');\n\n/**\n * @ngdoc provider\n * @name $templateRequestProvider\n * @this\n *\n * @description\n * Used to configure the options passed to the {@link $http} service when making a template request.\n *\n * For example, it can be used for specifying the \"Accept\" header that is sent to the server, when\n * requesting a template.\n */\nfunction $TemplateRequestProvider() {\n\n  var httpOptions;\n\n  /**\n   * @ngdoc method\n   * @name $templateRequestProvider#httpOptions\n   * @description\n   * The options to be passed to the {@link $http} service when making the request.\n   * You can use this to override options such as the \"Accept\" header for template requests.\n   *\n   * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the\n   * options if not overridden here.\n   *\n   * @param {string=} value new value for the {@link $http} options.\n   * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter.\n   */\n  this.httpOptions = function(val) {\n    if (val) {\n      httpOptions = val;\n      return this;\n    }\n    return httpOptions;\n  };\n\n  /**\n   * @ngdoc service\n   * @name $templateRequest\n   *\n   * @description\n   * The `$templateRequest` service runs security checks then downloads the provided template using\n   * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request\n   * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the\n   * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the\n   * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted\n   * when `tpl` is of type string and `$templateCache` has the matching entry.\n   *\n   * If you want to pass custom options to the `$http` service, such as setting the Accept header you\n   * can configure this via {@link $templateRequestProvider#httpOptions}.\n   *\n   * `$templateRequest` is used internally by {@link $compile}, {@link ngRoute.$route}, and directives such\n   * as {@link ngInclude} to download and cache templates.\n   *\n   * 3rd party modules should use `$templateRequest` if their services or directives are loading\n   * templates.\n   *\n   * @param {string|TrustedResourceUrl} tpl The HTTP request template URL\n   * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n   *\n   * @return {Promise} a promise for the HTTP response data of the given URL.\n   *\n   * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n   */\n  this.$get = ['$exceptionHandler', '$templateCache', '$http', '$q', '$sce',\n    function($exceptionHandler, $templateCache, $http, $q, $sce) {\n\n      function handleRequestFn(tpl, ignoreRequestError) {\n        handleRequestFn.totalPendingRequests++;\n\n        // We consider the template cache holds only trusted templates, so\n        // there's no need to go through adding the template again to the trusted\n        // resources for keys that already are included in there. This also makes\n        // AngularJS accept any script directive, no matter its name. However, we\n        // still need to unwrap trusted types.\n        if (!isString(tpl) || isUndefined($templateCache.get(tpl))) {\n          tpl = $sce.getTrustedResourceUrl(tpl);\n        }\n\n        var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n        if (isArray(transformResponse)) {\n          transformResponse = transformResponse.filter(function(transformer) {\n            return transformer !== defaultHttpResponseTransform;\n          });\n        } else if (transformResponse === defaultHttpResponseTransform) {\n          transformResponse = null;\n        }\n\n        return $http.get(tpl, extend({\n            cache: $templateCache,\n            transformResponse: transformResponse\n          }, httpOptions))\n          .finally(function() {\n            handleRequestFn.totalPendingRequests--;\n          })\n          .then(function(response) {\n            return $templateCache.put(tpl, response.data);\n          }, handleError);\n\n        function handleError(resp) {\n          if (!ignoreRequestError) {\n            resp = $templateRequestMinErr('tpload',\n                'Failed to load template: {0} (HTTP status: {1} {2})',\n                tpl, resp.status, resp.statusText);\n\n            $exceptionHandler(resp);\n          }\n\n          return $q.reject(resp);\n        }\n      }\n\n      handleRequestFn.totalPendingRequests = 0;\n\n      return handleRequestFn;\n    }\n  ];\n}\n\n/** @this */\nfunction $$TestabilityProvider() {\n  this.$get = ['$rootScope', '$browser', '$location',\n       function($rootScope,   $browser,   $location) {\n\n    /**\n     * @name $testability\n     *\n     * @description\n     * The private $$testability service provides a collection of methods for use when debugging\n     * or by automated test and debugging tools.\n     */\n    var testability = {};\n\n    /**\n     * @name $$testability#findBindings\n     *\n     * @description\n     * Returns an array of elements that are bound (via ng-bind or {{}})\n     * to expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The binding expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression. Filters and whitespace are ignored.\n     */\n    testability.findBindings = function(element, expression, opt_exactMatch) {\n      var bindings = element.getElementsByClassName('ng-binding');\n      var matches = [];\n      forEach(bindings, function(binding) {\n        var dataBinding = angular.element(binding).data('$binding');\n        if (dataBinding) {\n          forEach(dataBinding, function(bindingName) {\n            if (opt_exactMatch) {\n              var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n              if (matcher.test(bindingName)) {\n                matches.push(binding);\n              }\n            } else {\n              if (bindingName.indexOf(expression) !== -1) {\n                matches.push(binding);\n              }\n            }\n          });\n        }\n      });\n      return matches;\n    };\n\n    /**\n     * @name $$testability#findModels\n     *\n     * @description\n     * Returns an array of elements that are two-way found via ng-model to\n     * expressions matching the input.\n     *\n     * @param {Element} element The element root to search from.\n     * @param {string} expression The model expression to match.\n     * @param {boolean} opt_exactMatch If true, only returns exact matches\n     *     for the expression.\n     */\n    testability.findModels = function(element, expression, opt_exactMatch) {\n      var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n      for (var p = 0; p < prefixes.length; ++p) {\n        var attributeEquals = opt_exactMatch ? '=' : '*=';\n        var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n        var elements = element.querySelectorAll(selector);\n        if (elements.length) {\n          return elements;\n        }\n      }\n    };\n\n    /**\n     * @name $$testability#getLocation\n     *\n     * @description\n     * Shortcut for getting the location in a browser agnostic way. Returns\n     *     the path, search, and hash. (e.g. /path?a=b#hash)\n     */\n    testability.getLocation = function() {\n      return $location.url();\n    };\n\n    /**\n     * @name $$testability#setLocation\n     *\n     * @description\n     * Shortcut for navigating to a location without doing a full page reload.\n     *\n     * @param {string} url The location url (path, search and hash,\n     *     e.g. /path?a=b#hash) to go to.\n     */\n    testability.setLocation = function(url) {\n      if (url !== $location.url()) {\n        $location.url(url);\n        $rootScope.$digest();\n      }\n    };\n\n    /**\n     * @name $$testability#whenStable\n     *\n     * @description\n     * Calls the callback when all pending tasks are completed.\n     *\n     * Types of tasks waited for include:\n     * - Pending timeouts (via {@link $timeout}).\n     * - Pending HTTP requests (via {@link $http}).\n     * - In-progress route transitions (via {@link $route}).\n     * - Pending tasks scheduled via {@link $rootScope#$applyAsync}.\n     * - Pending tasks scheduled via {@link $rootScope#$evalAsync}.\n     *   These include tasks scheduled via `$evalAsync()` indirectly (such as {@link $q} promises).\n     *\n     * @param {function} callback\n     */\n    testability.whenStable = function(callback) {\n      $browser.notifyWhenNoOutstandingRequests(callback);\n    };\n\n    return testability;\n  }];\n}\n\nvar $timeoutMinErr = minErr('$timeout');\n\n/** @this */\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $$q,   $exceptionHandler) {\n\n    var deferreds = {};\n\n\n    /**\n     * @ngdoc service\n     * @name $timeout\n     *\n     * @description\n     * AngularJS's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n     * block and delegates any exceptions to\n     * {@link ng.$exceptionHandler $exceptionHandler} service.\n     *\n     * The return value of calling `$timeout` is a promise, which will be resolved when\n     * the delay has passed and the timeout function, if provided, is executed.\n     *\n     * To cancel a timeout request, call `$timeout.cancel(promise)`.\n     *\n     * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n     * synchronously flush the queue of deferred functions.\n     *\n     * If you only want a promise that will be resolved after some specified delay\n     * then you can call `$timeout` without the `fn` function.\n     *\n     * @param {function()=} fn A function, whose execution should be delayed.\n     * @param {number=} [delay=0] Delay in milliseconds.\n     * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n     *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n     * @param {...*=} Pass additional parameters to the executed function.\n     * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise\n     *   will be resolved with the return value of the `fn` function.\n     *\n     */\n    function timeout(fn, delay, invokeApply) {\n      if (!isFunction(fn)) {\n        invokeApply = delay;\n        delay = fn;\n        fn = noop;\n      }\n\n      var args = sliceArgs(arguments, 3),\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          deferred = (skipApply ? $$q : $q).defer(),\n          promise = deferred.promise,\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn.apply(null, args));\n        } catch (e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        } finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay, '$timeout');\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $timeout#cancel\n     *\n     * @description\n     * Cancels a task associated with the `promise`. As a result of this, the promise will be\n     * resolved with a rejection.\n     *\n     * @param {Promise=} promise Promise returned by the `$timeout` function.\n     * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n     *   canceled.\n     */\n    timeout.cancel = function(promise) {\n      if (!promise) return false;\n\n      if (!promise.hasOwnProperty('$$timeoutId')) {\n        throw $timeoutMinErr('badprom',\n            '`$timeout.cancel()` called with a promise that was not generated by `$timeout()`.');\n      }\n\n      if (!deferreds.hasOwnProperty(promise.$$timeoutId)) return false;\n\n      var id = promise.$$timeoutId;\n      var deferred = deferreds[id];\n\n      // Timeout cancels should not report an unhandled promise.\n      markQExceptionHandled(deferred.promise);\n      deferred.reject('canceled');\n      delete deferreds[id];\n\n      return $browser.defer.cancel(id);\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = window.document.createElement('a');\nvar originUrl = urlResolve(window.location.href);\nvar baseUrlParsingNode;\n\nurlParsingNode.href = 'http://[::1]';\n\n// Support: IE 9-11 only, Edge 16-17 only (fixed in 18 Preview)\n// IE/Edge don't wrap IPv6 addresses' hostnames in square brackets\n// when parsed out of an anchor element.\nvar ipv6InBrackets = urlParsingNode.hostname === '[::1]';\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+ etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string|object} url The URL to be parsed. If `url` is not a string, it will be returned\n *     unchanged.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description                                                            |\n *   |---------------|------------------------------------------------------------------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol without the trailing colon                                |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol                                 |\n *   | hostname      | The hostname                                                           |\n *   | port          | The port, without \":\"                                                  |\n *   | pathname      | The pathname, beginning with \"/\"                                       |\n *\n */\nfunction urlResolve(url) {\n  if (!isString(url)) return url;\n\n  var href = url;\n\n  // Support: IE 9-11 only\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute('href', href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  var hostname = urlParsingNode.hostname;\n\n  if (!ipv6InBrackets && hostname.indexOf(':') > -1) {\n    hostname = '[' + hostname + ']';\n  }\n\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application\n * document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  return urlsAreSameOrigin(requestUrl, originUrl);\n}\n\n/**\n * Parse a request URL and determine whether it is same-origin as the current document base URL.\n *\n * Note: The base URL is usually the same as the document location (`location.href`) but can\n * be overriden by using the `<base>` tag.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the URL is same-origin as the document base URL.\n */\nfunction urlIsSameOriginAsBaseUrl(requestUrl) {\n  return urlsAreSameOrigin(requestUrl, getBaseUrl());\n}\n\n/**\n * Create a function that can check a URL's origin against a list of allowed/trusted origins.\n * The current location's origin is implicitly trusted.\n *\n * @param {string[]} trustedOriginUrls - A list of URLs (strings), whose origins are trusted.\n *\n * @returns {Function} - A function that receives a URL (string or parsed URL object) and returns\n *     whether it is of an allowed origin.\n */\nfunction urlIsAllowedOriginFactory(trustedOriginUrls) {\n  var parsedAllowedOriginUrls = [originUrl].concat(trustedOriginUrls.map(urlResolve));\n\n  /**\n   * Check whether the specified URL (string or parsed URL object) has an origin that is allowed\n   * based on a list of trusted-origin URLs. The current location's origin is implicitly\n   * trusted.\n   *\n   * @param {string|Object} requestUrl - The URL to be checked (provided as a string that will be\n   *     resolved or a parsed URL object).\n   *\n   * @returns {boolean} - Whether the specified URL is of an allowed origin.\n   */\n  return function urlIsAllowedOrigin(requestUrl) {\n    var parsedUrl = urlResolve(requestUrl);\n    return parsedAllowedOriginUrls.some(urlsAreSameOrigin.bind(null, parsedUrl));\n  };\n}\n\n/**\n * Determine if two URLs share the same origin.\n *\n * @param {string|Object} url1 - First URL to compare as a string or a normalized URL in the form of\n *     a dictionary object returned by `urlResolve()`.\n * @param {string|object} url2 - Second URL to compare as a string or a normalized URL in the form\n *     of a dictionary object returned by `urlResolve()`.\n *\n * @returns {boolean} - True if both URLs have the same origin, and false otherwise.\n */\nfunction urlsAreSameOrigin(url1, url2) {\n  url1 = urlResolve(url1);\n  url2 = urlResolve(url2);\n\n  return (url1.protocol === url2.protocol &&\n          url1.host === url2.host);\n}\n\n/**\n * Returns the current document base URL.\n * @returns {string}\n */\nfunction getBaseUrl() {\n  if (window.document.baseURI) {\n    return window.document.baseURI;\n  }\n\n  // `document.baseURI` is available everywhere except IE\n  if (!baseUrlParsingNode) {\n    baseUrlParsingNode = window.document.createElement('a');\n    baseUrlParsingNode.href = '.';\n\n    // Work-around for IE bug described in Implementation Notes. The fix in `urlResolve()` is not\n    // suitable here because we need to track changes to the base URL.\n    baseUrlParsingNode = baseUrlParsingNode.cloneNode(false);\n  }\n  return baseUrlParsingNode.href;\n}\n\n/**\n * @ngdoc service\n * @name $window\n * @this\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In AngularJS we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\" name=\"window-service\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" aria-label=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider() {\n  this.$get = valueFn(window);\n}\n\n/**\n * @name $$cookieReader\n * @requires $document\n *\n * @description\n * This is a private service for reading cookies used by $http and ngCookies\n *\n * @return {Object} a key/value map of the current cookies\n */\nfunction $$CookieReader($document) {\n  var rawDocument = $document[0] || {};\n  var lastCookies = {};\n  var lastCookieString = '';\n\n  function safeGetCookie(rawDocument) {\n    try {\n      return rawDocument.cookie || '';\n    } catch (e) {\n      return '';\n    }\n  }\n\n  function safeDecodeURIComponent(str) {\n    try {\n      return decodeURIComponent(str);\n    } catch (e) {\n      return str;\n    }\n  }\n\n  return function() {\n    var cookieArray, cookie, i, index, name;\n    var currentCookieString = safeGetCookie(rawDocument);\n\n    if (currentCookieString !== lastCookieString) {\n      lastCookieString = currentCookieString;\n      cookieArray = lastCookieString.split('; ');\n      lastCookies = {};\n\n      for (i = 0; i < cookieArray.length; i++) {\n        cookie = cookieArray[i];\n        index = cookie.indexOf('=');\n        if (index > 0) { //ignore nameless cookies\n          name = safeDecodeURIComponent(cookie.substring(0, index));\n          // the first value that is seen for a cookie is the most\n          // specific one.  values for the same cookie name that\n          // follow are for less specific paths.\n          if (isUndefined(lastCookies[name])) {\n            lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n          }\n        }\n      }\n    }\n    return lastCookies;\n  };\n}\n\n$$CookieReader.$inject = ['$document'];\n\n/** @this */\nfunction $$CookieReaderProvider() {\n  this.$get = $$CookieReader;\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`.\n * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace\n * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores\n * (`myapp_subsection_filterx`).\n * </div>\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how AngularJS filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the AngularJS Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * They can be used in view templates, controllers or services. AngularJS comes\n * with a collection of [built-in filters](api/ng/filter), but it is easy to\n * define your own as well.\n *\n * The general syntax in templates is as follows:\n *\n * ```html\n * {{ expression [| filter_name[:parameter_value] ... ] }}\n * ```\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\n/** @this */\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   *\n   *    <div class=\"alert alert-warning\">\n   *    **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`.\n   *    Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace\n   *    your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores\n   *    (`myapp_subsection_filterx`).\n   *    </div>\n    * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if (isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * <div class=\"alert alert-info\">\n *   **Note**: If the array contains objects that reference themselves, filtering is not possible.\n * </div>\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is used for matching against the contents of the `array`. All strings or\n *     objects with string properties in `array` that match this string will be returned. This also\n *     applies to nested object properties.\n *     The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name (`$` by default) can be used (e.g. as in `{$: \"text\"}`) to accept a match\n *     against any property of the object or its nested object properties. That's equivalent to the\n *     simple substring match with a `string` as described above. The special property name can be\n *     overwritten, using the `anyPropertyKey` parameter.\n *     The predicate can be negated by prefixing the string with `!`.\n *     For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *     Note that a named property will match properties on the same level only, while the special\n *     `$` property will match properties on the same level or deeper. E.g. an array item like\n *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n *     **will** be matched by `{$: 'John'}`.\n *\n *   - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.\n *     The function is called for each element of the array, with the element, its index, and\n *     the entire array itself as arguments.\n *\n *     The final result is an array of those elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|false} [comparator] Comparator which is used in\n *     determining if values retrieved using `expression` (when it is not a function) should be\n *     considered a match based on the expected value (from the filter expression) and actual\n *     value (from the object in the array).\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if both values should be considered equal.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n *     This is essentially strict comparison of expected and actual.\n *\n *   - `false`: A short hand for a function which will look for a substring match in a case\n *     insensitive way. Primitive values are converted to strings. Objects are not compared against\n *     primitives, unless they have a custom `toString` method (e.g. `Date` objects).\n *\n *\n *   Defaults to `false`.\n *\n * @param {string} [anyPropertyKey] The special property name that matches against any property.\n *     By default `$`.\n *\n * @example\n   <example name=\"filter-filter\">\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       <label>Search: <input ng-model=\"searchText\"></label>\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       <label>Any: <input ng-model=\"search.$\"></label> <br>\n       <label>Name only <input ng-model=\"search.name\"></label><br>\n       <label>Phone only <input ng-model=\"search.phone\"></label><br>\n       <label>Equality <input type=\"checkbox\" ng-model=\"strict\"></label><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\n\nfunction filterFilter() {\n  return function(array, expression, comparator, anyPropertyKey) {\n    if (!isArrayLike(array)) {\n      if (array == null) {\n        return array;\n      } else {\n        throw minErr('filter')('notarray', 'Expected array but received: {0}', array);\n      }\n    }\n\n    anyPropertyKey = anyPropertyKey || '$';\n    var expressionType = getTypeForFilter(expression);\n    var predicateFn;\n    var matchAgainstAnyProp;\n\n    switch (expressionType) {\n      case 'function':\n        predicateFn = expression;\n        break;\n      case 'boolean':\n      case 'null':\n      case 'number':\n      case 'string':\n        matchAgainstAnyProp = true;\n        // falls through\n      case 'object':\n        predicateFn = createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp);\n        break;\n      default:\n        return array;\n    }\n\n    return Array.prototype.filter.call(array, predicateFn);\n  };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp) {\n  var shouldMatchPrimitives = isObject(expression) && (anyPropertyKey in expression);\n  var predicateFn;\n\n  if (comparator === true) {\n    comparator = equals;\n  } else if (!isFunction(comparator)) {\n    comparator = function(actual, expected) {\n      if (isUndefined(actual)) {\n        // No substring matching against `undefined`\n        return false;\n      }\n      if ((actual === null) || (expected === null)) {\n        // No substring matching against `null`; only match against `null`\n        return actual === expected;\n      }\n      if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {\n        // Should not compare primitives against objects, unless they have custom `toString` method\n        return false;\n      }\n\n      actual = lowercase('' + actual);\n      expected = lowercase('' + expected);\n      return actual.indexOf(expected) !== -1;\n    };\n  }\n\n  predicateFn = function(item) {\n    if (shouldMatchPrimitives && !isObject(item)) {\n      return deepCompare(item, expression[anyPropertyKey], comparator, anyPropertyKey, false);\n    }\n    return deepCompare(item, expression, comparator, anyPropertyKey, matchAgainstAnyProp);\n  };\n\n  return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) {\n  var actualType = getTypeForFilter(actual);\n  var expectedType = getTypeForFilter(expected);\n\n  if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n    return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp);\n  } else if (isArray(actual)) {\n    // In case `actual` is an array, consider it a match\n    // if ANY of it's items matches `expected`\n    return actual.some(function(item) {\n      return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp);\n    });\n  }\n\n  switch (actualType) {\n    case 'object':\n      var key;\n      if (matchAgainstAnyProp) {\n        for (key in actual) {\n          // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined\n          // See: https://github.com/angular/angular.js/issues/15644\n          if (key.charAt && (key.charAt(0) !== '$') &&\n              deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) {\n            return true;\n          }\n        }\n        return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false);\n      } else if (expectedType === 'object') {\n        for (key in expected) {\n          var expectedVal = expected[key];\n          if (isFunction(expectedVal) || isUndefined(expectedVal)) {\n            continue;\n          }\n\n          var matchAnyProperty = key === anyPropertyKey;\n          var actualVal = matchAnyProperty ? actual : actual[key];\n          if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) {\n            return false;\n          }\n        }\n        return true;\n      } else {\n        return comparator(actual, expected);\n      }\n    case 'function':\n      return false;\n    default:\n      return comparator(actual, expected);\n  }\n}\n\n// Used for easily differentiating between `null` and actual `object`\nfunction getTypeForFilter(val) {\n  return (val === null) ? 'null' : typeof val;\n}\n\nvar MAX_DIGITS = 22;\nvar DECIMAL_SEP = '.';\nvar ZERO_CHAR = '0';\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\" name=\"currency-filter\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\" aria-label=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span id=\"currency-custom\">{{amount | currency:\"USD$\"}}</span><br>\n         no fractions (0): <span id=\"currency-no-fractions\">{{amount | currency:\"USD$\":0}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n       });\n       it('should update', function() {\n         if (browser.params.browser === 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');\n         expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');\n         expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol, fractionSize) {\n    if (isUndefined(currencySymbol)) {\n      currencySymbol = formats.CURRENCY_SYM;\n    }\n\n    if (isUndefined(fractionSize)) {\n      fractionSize = formats.PATTERNS[1].maxFrac;\n    }\n\n    // If the currency symbol is empty, trim whitespace around the symbol\n    var currencySymbolRe = !currencySymbol ? /\\s*\\u00A4\\s*/g : /\\u00A4/g;\n\n    // if null or undefined pass it through\n    return (amount == null)\n        ? amount\n        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n            replace(currencySymbolRe, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is null or undefined, it will just be returned.\n * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively.\n * If the input is not a number an empty string is returned.\n *\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to `fractionSize` appropriately formatted based on the current\n *                   locale (e.g., in the en_US locale it will have \".\" as the decimal separator and\n *                   include \",\" group separators after each third digit).\n *\n * @example\n   <example module=\"numberFilterExample\" name=\"number-filter\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <label>Enter number: <input ng-model='val'></label><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n\n    // if null or undefined pass it through\n    return (number == null)\n        ? number\n        : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n                       fractionSize);\n  };\n}\n\n/**\n * Parse a number (as a string) into three components that can be used\n * for formatting the number.\n *\n * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)\n *\n * @param  {string} numStr The number to parse\n * @return {object} An object describing this number, containing the following keys:\n *  - d : an array of digits containing leading zeros as necessary\n *  - i : the number of the digits in `d` that are to the left of the decimal point\n *  - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`\n *\n */\nfunction parse(numStr) {\n  var exponent = 0, digits, numberOfIntegerDigits;\n  var i, j, zeros;\n\n  // Decimal point?\n  if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {\n    numStr = numStr.replace(DECIMAL_SEP, '');\n  }\n\n  // Exponential form?\n  if ((i = numStr.search(/e/i)) > 0) {\n    // Work out the exponent.\n    if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;\n    numberOfIntegerDigits += +numStr.slice(i + 1);\n    numStr = numStr.substring(0, i);\n  } else if (numberOfIntegerDigits < 0) {\n    // There was no decimal point or exponent so it is an integer.\n    numberOfIntegerDigits = numStr.length;\n  }\n\n  // Count the number of leading zeros.\n  for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */ }\n\n  if (i === (zeros = numStr.length)) {\n    // The digits are all zero.\n    digits = [0];\n    numberOfIntegerDigits = 1;\n  } else {\n    // Count the number of trailing zeros\n    zeros--;\n    while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;\n\n    // Trailing zeros are insignificant so ignore them\n    numberOfIntegerDigits -= i;\n    digits = [];\n    // Convert string to array of digits without leading/trailing zeros.\n    for (j = 0; i <= zeros; i++, j++) {\n      digits[j] = +numStr.charAt(i);\n    }\n  }\n\n  // If the number overflows the maximum allowed digits then use an exponent.\n  if (numberOfIntegerDigits > MAX_DIGITS) {\n    digits = digits.splice(0, MAX_DIGITS - 1);\n    exponent = numberOfIntegerDigits - 1;\n    numberOfIntegerDigits = 1;\n  }\n\n  return { d: digits, e: exponent, i: numberOfIntegerDigits };\n}\n\n/**\n * Round the parsed number to the specified number of decimal places\n * This function changed the parsedNumber in-place\n */\nfunction roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {\n    var digits = parsedNumber.d;\n    var fractionLen = digits.length - parsedNumber.i;\n\n    // determine fractionSize if it is not specified; `+fractionSize` converts it to a number\n    fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;\n\n    // The index of the digit to where rounding is to occur\n    var roundAt = fractionSize + parsedNumber.i;\n    var digit = digits[roundAt];\n\n    if (roundAt > 0) {\n      // Drop fractional digits beyond `roundAt`\n      digits.splice(Math.max(parsedNumber.i, roundAt));\n\n      // Set non-fractional digits beyond `roundAt` to 0\n      for (var j = roundAt; j < digits.length; j++) {\n        digits[j] = 0;\n      }\n    } else {\n      // We rounded to zero so reset the parsedNumber\n      fractionLen = Math.max(0, fractionLen);\n      parsedNumber.i = 1;\n      digits.length = Math.max(1, roundAt = fractionSize + 1);\n      digits[0] = 0;\n      for (var i = 1; i < roundAt; i++) digits[i] = 0;\n    }\n\n    if (digit >= 5) {\n      if (roundAt - 1 < 0) {\n        for (var k = 0; k > roundAt; k--) {\n          digits.unshift(0);\n          parsedNumber.i++;\n        }\n        digits.unshift(1);\n        parsedNumber.i++;\n      } else {\n        digits[roundAt - 1]++;\n      }\n    }\n\n    // Pad out with zeros to get the required fraction length\n    for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);\n\n\n    // Do any carrying, e.g. a digit was rounded up to 10\n    var carry = digits.reduceRight(function(carry, d, i, digits) {\n      d = d + carry;\n      digits[i] = d % 10;\n      return Math.floor(d / 10);\n    }, 0);\n    if (carry) {\n      digits.unshift(carry);\n      parsedNumber.i++;\n    }\n}\n\n/**\n * Format a number into a string\n * @param  {number} number       The number to format\n * @param  {{\n *           minFrac, // the minimum number of digits required in the fraction part of the number\n *           maxFrac, // the maximum number of digits required in the fraction part of the number\n *           gSize,   // number of digits in each group of separated digits\n *           lgSize,  // number of digits in the last group of digits before the decimal separator\n *           negPre,  // the string to go in front of a negative number (e.g. `-` or `(`))\n *           posPre,  // the string to go in front of a positive number\n *           negSuf,  // the string to go after a negative number (e.g. `)`)\n *           posSuf   // the string to go after a positive number\n *         }} pattern\n * @param  {string} groupSep     The string to separate groups of number (e.g. `,`)\n * @param  {string} decimalSep   The string to act as the decimal separator (e.g. `.`)\n * @param  {[type]} fractionSize The size of the fractional part of the number\n * @return {string}              The number formatted as a string\n */\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n\n  if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';\n\n  var isInfinity = !isFinite(number);\n  var isZero = false;\n  var numStr = Math.abs(number) + '',\n      formattedText = '',\n      parsedNumber;\n\n  if (isInfinity) {\n    formattedText = '\\u221e';\n  } else {\n    parsedNumber = parse(numStr);\n\n    roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);\n\n    var digits = parsedNumber.d;\n    var integerLen = parsedNumber.i;\n    var exponent = parsedNumber.e;\n    var decimals = [];\n    isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);\n\n    // pad zeros for small numbers\n    while (integerLen < 0) {\n      digits.unshift(0);\n      integerLen++;\n    }\n\n    // extract decimals digits\n    if (integerLen > 0) {\n      decimals = digits.splice(integerLen, digits.length);\n    } else {\n      decimals = digits;\n      digits = [0];\n    }\n\n    // format the integer digits with grouping separators\n    var groups = [];\n    if (digits.length >= pattern.lgSize) {\n      groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));\n    }\n    while (digits.length > pattern.gSize) {\n      groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));\n    }\n    if (digits.length) {\n      groups.unshift(digits.join(''));\n    }\n    formattedText = groups.join(groupSep);\n\n    // append the decimal digits\n    if (decimals.length) {\n      formattedText += decimalSep + decimals.join('');\n    }\n\n    if (exponent) {\n      formattedText += 'e+' + exponent;\n    }\n  }\n  if (number < 0 && !isZero) {\n    return pattern.negPre + formattedText + pattern.negSuf;\n  } else {\n    return pattern.posPre + formattedText + pattern.posSuf;\n  }\n}\n\nfunction padNumber(num, digits, trim, negWrap) {\n  var neg = '';\n  if (num < 0 || (negWrap && num <= 0)) {\n    if (negWrap) {\n      num = -num + 1;\n    } else {\n      num = -num;\n      neg = '-';\n    }\n  }\n  num = '' + num;\n  while (num.length < digits) num = ZERO_CHAR + num;\n  if (trim) {\n    num = num.substr(num.length - digits);\n  }\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim, negWrap) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset) {\n      value += offset;\n    }\n    if (value === 0 && offset === -12) value = 12;\n    return padNumber(value, size, trim, negWrap);\n  };\n}\n\nfunction dateStrGetter(name, shortForm, standAlone) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var propPrefix = (standAlone ? 'STANDALONE' : '') + (shortForm ? 'SHORT' : '');\n    var get = uppercase(propPrefix + name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date, formats, offset) {\n  var zone = -1 * offset;\n  var paddedZone = (zone >= 0) ? '+' : '';\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n    // 0 = index of January\n    var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n    // 4 = index of Thursday (+1 to account for 1st = 5)\n    // 11 = index of *next* Thursday (+1 account for 1st = 12)\n    return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n    return new Date(datetime.getFullYear(), datetime.getMonth(),\n      // 4 = index of Thursday\n      datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n   return function(date) {\n      var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n         thisThurs = getThursdayThisWeek(date);\n\n      var diff = +thisThurs - +firstThurs,\n         result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n      return padNumber(result, size);\n   };\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nfunction eraGetter(date, formats) {\n  return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];\n}\n\nfunction longEraGetter(date, formats) {\n  return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4, 0, false, true),\n    yy: dateGetter('FullYear', 2, 0, true, true),\n     y: dateGetter('FullYear', 1, 0, false, true),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n  LLLL: dateStrGetter('Month', false, true),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter,\n    ww: weekGetter(2),\n     w: weekGetter(1),\n     G: eraGetter,\n     GG: eraGetter,\n     GGG: eraGetter,\n     GGGG: longEraGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\\s\\S]*)/,\n    NUMBER_STRING = /^-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'LLLL'`: Stand-alone month in year (January-December)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in AM/PM, padded (01-12)\n *   * `'h'`: Hour in AM/PM, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: AM/PM marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *   * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')\n *   * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 PM)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 PM)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n *   Any other characters in the `format` string will be output as-is.\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the\n *    continental US time zone abbreviations, but for general use, use a time zone offset, for\n *    example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)\n *    If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example name=\"filter-date\">\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010-10-2\\d \\d{2}:\\d{2}:\\d{2} (-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if ((match = string.match(R_ISO8601_STR))) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = toInt(match[9] + match[10]);\n        tzMin = toInt(match[9] + match[11]);\n      }\n      dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));\n      var h = toInt(match[4] || 0) - tzHour;\n      var m = toInt(match[5] || 0) - tzMin;\n      var s = toInt(match[6] || 0);\n      var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format, timezone) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date) || !isFinite(date.getTime())) {\n      return date;\n    }\n\n    while (format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    var dateTimezoneOffset = date.getTimezoneOffset();\n    if (timezone) {\n      dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n      date = convertTimezoneToLocal(date, timezone, true);\n    }\n    forEach(parts, function(value) {\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)\n                 : value === '\\'\\'' ? '\\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\\'');\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example name=\"filter-json\">\n     <file name=\"index.html\">\n       <pre id=\"default-spacing\">{{ {'name':'value'} | json }}</pre>\n       <pre id=\"custom-spacing\">{{ {'name':'value'} | json:4 }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n {2}\"name\": ?\"value\"\\n}/);\n         expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n {4}\"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object, spacing) {\n    if (isUndefined(spacing)) {\n        spacing = 2;\n    }\n    return toJson(object, spacing);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n *\n * See the {@link ng.uppercase uppercase filter documentation} for a functionally identical example.\n *\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @example\n   <example module=\"uppercaseFilterExample\" name=\"filter-uppercase\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('uppercaseFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.title = 'This is a title';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <!-- This title should be formatted normally -->\n         <h1>{{title}}</h1>\n         <!-- This title should be capitalized -->\n         <h1>{{title | uppercase}}</h1>\n       </div>\n     </file>\n   </example>\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements are\n * taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. Other array-like objects are also supported\n * (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input,\n * it is converted to a string.\n *\n * @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited.\n * @param {string|number} limit - The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,\n *     the input will be returned unchanged.\n * @param {(string|number)=} begin - Index at which to begin limitation. As a negative index,\n *     `begin` indicates an offset from the end of `input`. Defaults to `0`.\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had\n *     less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\" name=\"limit-to-filter\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.longNumber = 2345432342;\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n             $scope.longNumberLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <label>\n            Limit {{numbers}} to:\n            <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         </label>\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         <label>\n            Limit {{letters}} to:\n            <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         </label>\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n         <label>\n            Limit {{longNumber}} to:\n            <input type=\"number\" step=\"1\" ng-model=\"longNumberLimit\">\n         </label>\n         <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var longNumberLimitInput = element(by.model('longNumberLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n       var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   longNumberLimitInput.clear();\n       //   longNumberLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       //   expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         longNumberLimitInput.clear();\n         longNumberLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n         expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n       });\n     </file>\n   </example>\n*/\nfunction limitToFilter() {\n  return function(input, limit, begin) {\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = toInt(limit);\n    }\n    if (isNumberNaN(limit)) return input;\n\n    if (isNumber(input)) input = input.toString();\n    if (!isArrayLike(input)) return input;\n\n    begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);\n    begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;\n\n    if (limit >= 0) {\n      return sliceFn(input, begin, begin + limit);\n    } else {\n      if (begin === 0) {\n        return sliceFn(input, limit, input.length);\n      } else {\n        return sliceFn(input, Math.max(0, begin + limit), begin);\n      }\n    }\n  };\n}\n\nfunction sliceFn(input, begin, end) {\n  if (isString(input)) return input.slice(begin, end);\n\n  return slice.call(input, begin, end);\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Returns an array containing the items from the specified `collection`, ordered by a `comparator`\n * function based on the values computed using the `expression` predicate.\n *\n * For example, `[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'` would result in\n * `[{id: 'bar'}, {id: 'foo'}]`.\n *\n * The `collection` can be an Array or array-like object (e.g. NodeList, jQuery object, TypedArray,\n * String, etc).\n *\n * The `expression` can be a single predicate, or a list of predicates each serving as a tie-breaker\n * for the preceding one. The `expression` is evaluated against each item and the output is used\n * for comparing with other items.\n *\n * You can change the sorting order by setting `reverse` to `true`. By default, items are sorted in\n * ascending order.\n *\n * The comparison is done using the `comparator` function. If none is specified, a default, built-in\n * comparator is used (see below for details - in a nutshell, it compares numbers numerically and\n * strings alphabetically).\n *\n * ### Under the hood\n *\n * Ordering the specified `collection` happens in two phases:\n *\n * 1. All items are passed through the predicate (or predicates), and the returned values are saved\n *    along with their type (`string`, `number` etc). For example, an item `{label: 'foo'}`, passed\n *    through a predicate that extracts the value of the `label` property, would be transformed to:\n *    ```\n *    {\n *      value: 'foo',\n *      type: 'string',\n *      index: ...\n *    }\n *    ```\n *    **Note:** `null` values use `'null'` as their type.\n * 2. The comparator function is used to sort the items, based on the derived values, types and\n *    indices.\n *\n * If you use a custom comparator, it will be called with pairs of objects of the form\n * `{value: ..., type: '...', index: ...}` and is expected to return `0` if the objects are equal\n * (as far as the comparator is concerned), `-1` if the 1st one should be ranked higher than the\n * second, or `1` otherwise.\n *\n * In order to ensure that the sorting will be deterministic across platforms, if none of the\n * specified predicates can distinguish between two items, `orderBy` will automatically introduce a\n * dummy predicate that returns the item's index as `value`.\n * (If you are using a custom comparator, make sure it can handle this predicate as well.)\n *\n * If a custom comparator still can't distinguish between two items, then they will be sorted based\n * on their index using the built-in comparator.\n *\n * Finally, in an attempt to simplify things, if a predicate returns an object as the extracted\n * value for an item, `orderBy` will try to convert that object to a primitive value, before passing\n * it to the comparator. The following rules govern the conversion:\n *\n * 1. If the object has a `valueOf()` method that returns a primitive, its return value will be\n *    used instead.<br />\n *    (If the object has a `valueOf()` method that returns another object, then the returned object\n *    will be used in subsequent steps.)\n * 2. If the object has a custom `toString()` method (i.e. not the one inherited from `Object`) that\n *    returns a primitive, its return value will be used instead.<br />\n *    (If the object has a `toString()` method that returns another object, then the returned object\n *    will be used in subsequent steps.)\n * 3. No conversion; the object itself is used.\n *\n * ### The default comparator\n *\n * The default, built-in comparator should be sufficient for most usecases. In short, it compares\n * numbers numerically, strings alphabetically (and case-insensitively), for objects falls back to\n * using their index in the original collection, sorts values of different types by type and puts\n * `undefined` and `null` values at the end of the sorted list.\n *\n * More specifically, it follows these steps to determine the relative order of items:\n *\n * 1. If the compared values are of different types:\n *    - If one of the values is undefined, consider it \"greater than\" the other.\n *    - Else if one of the values is null, consider it \"greater than\" the other.\n *    - Else compare the types themselves alphabetically.\n * 2. If both values are of type `string`, compare them alphabetically in a case- and\n *    locale-insensitive way.\n * 3. If both values are objects, compare their indices instead.\n * 4. Otherwise, return:\n *    -  `0`, if the values are equal (by strict equality comparison, i.e. using `===`).\n *    - `-1`, if the 1st value is \"less than\" the 2nd value (compared using the `<` operator).\n *    -  `1`, otherwise.\n *\n * **Note:** If you notice numbers not being sorted as expected, make sure they are actually being\n *           saved as numbers and not strings.\n * **Note:** For the purpose of sorting, `null` and `undefined` are considered \"greater than\"\n *           any other value (with undefined \"greater than\" null). This effectively means that `null`\n *           and `undefined` values end up at the end of a list sorted in ascending order.\n * **Note:** `null` values use `'null'` as their type to be able to distinguish them from objects.\n *\n * @param {Array|ArrayLike} collection - The collection (array or array-like object) to sort.\n * @param {(Function|string|Array.<Function|string>)=} expression - A predicate (or list of\n *    predicates) to be used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `Function`: A getter function. This function will be called with each item as argument and\n *      the return value will be used for sorting.\n *    - `string`: An AngularJS expression. This expression will be evaluated against each item and the\n *      result will be used for sorting. For example, use `'label'` to sort by a property called\n *      `label` or `'label.substring(0, 3)'` to sort by the first 3 characters of the `label`\n *      property.<br />\n *      (The result of a constant expression is interpreted as a property name to be used for\n *      comparison. For example, use `'\"special name\"'` (note the extra pair of quotes) to sort by a\n *      property called `special name`.)<br />\n *      An expression can be optionally prefixed with `+` or `-` to control the sorting direction,\n *      ascending or descending. For example, `'+label'` or `'-label'`. If no property is provided,\n *      (e.g. `'+'` or `'-'`), the collection element itself is used in comparisons.\n *    - `Array`: An array of function and/or string predicates. If a predicate cannot determine the\n *      relative order of two items, the next predicate is used as a tie-breaker.\n *\n * **Note:** If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse - If `true`, reverse the sorting order.\n * @param {(Function)=} comparator - The comparator function used to determine the relative order of\n *    value pairs. If omitted, the built-in comparator will be used.\n *\n * @returns {Array} - The sorted array.\n *\n *\n * @example\n * ### Ordering a table with `ngRepeat`\n *\n * The example below demonstrates a simple {@link ngRepeat ngRepeat}, where the data is sorted by\n * age in descending order (expression is set to `'-age'`). The `comparator` is not set, which means\n * it defaults to the built-in comparator.\n *\n   <example name=\"orderBy-static\" module=\"orderByExample1\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <table class=\"friends\">\n           <tr>\n             <th>Name</th>\n             <th>Phone Number</th>\n             <th>Age</th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:'-age'\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('orderByExample1', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.friends = [\n             {name: 'John',   phone: '555-1212',  age: 10},\n             {name: 'Mary',   phone: '555-9876',  age: 19},\n             {name: 'Mike',   phone: '555-4321',  age: 21},\n             {name: 'Adam',   phone: '555-5678',  age: 35},\n             {name: 'Julie',  phone: '555-8765',  age: 29}\n           ];\n         }]);\n     </file>\n     <file name=\"style.css\">\n       .friends {\n         border-collapse: collapse;\n       }\n\n       .friends th {\n         border-bottom: 1px solid;\n       }\n       .friends td, .friends th {\n         border-left: 1px solid;\n         padding: 5px 10px;\n       }\n       .friends td:first-child, .friends th:first-child {\n         border-left: none;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       // Element locators\n       var names = element.all(by.repeater('friends').column('friend.name'));\n\n       it('should sort friends by age in reverse order', function() {\n         expect(names.get(0).getText()).toBe('Adam');\n         expect(names.get(1).getText()).toBe('Julie');\n         expect(names.get(2).getText()).toBe('Mike');\n         expect(names.get(3).getText()).toBe('Mary');\n         expect(names.get(4).getText()).toBe('John');\n       });\n     </file>\n   </example>\n * <hr />\n *\n * @example\n * ### Changing parameters dynamically\n *\n * All parameters can be changed dynamically. The next example shows how you can make the columns of\n * a table sortable, by binding the `expression` and `reverse` parameters to scope properties.\n *\n   <example name=\"orderBy-dynamic\" module=\"orderByExample2\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <pre>Sort by = {{propertyName}}; reverse = {{reverse}}</pre>\n         <hr/>\n         <button ng-click=\"propertyName = null; reverse = false\">Set to unsorted</button>\n         <hr/>\n         <table class=\"friends\">\n           <tr>\n             <th>\n               <button ng-click=\"sortBy('name')\">Name</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'name'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n             <th>\n               <button ng-click=\"sortBy('phone')\">Phone Number</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'phone'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n             <th>\n               <button ng-click=\"sortBy('age')\">Age</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'age'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:propertyName:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('orderByExample2', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var friends = [\n             {name: 'John',   phone: '555-1212',  age: 10},\n             {name: 'Mary',   phone: '555-9876',  age: 19},\n             {name: 'Mike',   phone: '555-4321',  age: 21},\n             {name: 'Adam',   phone: '555-5678',  age: 35},\n             {name: 'Julie',  phone: '555-8765',  age: 29}\n           ];\n\n           $scope.propertyName = 'age';\n           $scope.reverse = true;\n           $scope.friends = friends;\n\n           $scope.sortBy = function(propertyName) {\n             $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;\n             $scope.propertyName = propertyName;\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       .friends {\n         border-collapse: collapse;\n       }\n\n       .friends th {\n         border-bottom: 1px solid;\n       }\n       .friends td, .friends th {\n         border-left: 1px solid;\n         padding: 5px 10px;\n       }\n       .friends td:first-child, .friends th:first-child {\n         border-left: none;\n       }\n\n       .sortorder:after {\n         content: '\\25b2';   // BLACK UP-POINTING TRIANGLE\n       }\n       .sortorder.reverse:after {\n         content: '\\25bc';   // BLACK DOWN-POINTING TRIANGLE\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       // Element locators\n       var unsortButton = element(by.partialButtonText('unsorted'));\n       var nameHeader = element(by.partialButtonText('Name'));\n       var phoneHeader = element(by.partialButtonText('Phone'));\n       var ageHeader = element(by.partialButtonText('Age'));\n       var firstName = element(by.repeater('friends').column('friend.name').row(0));\n       var lastName = element(by.repeater('friends').column('friend.name').row(4));\n\n       it('should sort friends by some property, when clicking on the column header', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         phoneHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Mary');\n\n         nameHeader.click();\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('Mike');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Adam');\n       });\n\n       it('should sort friends in reverse order, when clicking on the same column', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Adam');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n       });\n\n       it('should restore the original order, when clicking \"Set to unsorted\"', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         unsortButton.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Julie');\n       });\n     </file>\n   </example>\n * <hr />\n *\n * @example\n * ### Using `orderBy` inside a controller\n *\n * It is also possible to call the `orderBy` filter manually, by injecting `orderByFilter`, and\n * calling it with the desired parameters. (Alternatively, you could inject the `$filter` factory\n * and retrieve the `orderBy` filter with `$filter('orderBy')`.)\n *\n   <example name=\"orderBy-call-manually\" module=\"orderByExample3\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <pre>Sort by = {{propertyName}}; reverse = {{reverse}}</pre>\n         <hr/>\n         <button ng-click=\"sortBy(null)\">Set to unsorted</button>\n         <hr/>\n         <table class=\"friends\">\n           <tr>\n             <th>\n               <button ng-click=\"sortBy('name')\">Name</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'name'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n             <th>\n               <button ng-click=\"sortBy('phone')\">Phone Number</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'phone'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n             <th>\n               <button ng-click=\"sortBy('age')\">Age</button>\n               <span class=\"sortorder\" ng-show=\"propertyName === 'age'\" ng-class=\"{reverse: reverse}\"></span>\n             </th>\n           </tr>\n           <tr ng-repeat=\"friend in friends\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('orderByExample3', [])\n         .controller('ExampleController', ['$scope', 'orderByFilter', function($scope, orderBy) {\n           var friends = [\n             {name: 'John',   phone: '555-1212',  age: 10},\n             {name: 'Mary',   phone: '555-9876',  age: 19},\n             {name: 'Mike',   phone: '555-4321',  age: 21},\n             {name: 'Adam',   phone: '555-5678',  age: 35},\n             {name: 'Julie',  phone: '555-8765',  age: 29}\n           ];\n\n           $scope.propertyName = 'age';\n           $scope.reverse = true;\n           $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse);\n\n           $scope.sortBy = function(propertyName) {\n             $scope.reverse = (propertyName !== null && $scope.propertyName === propertyName)\n                 ? !$scope.reverse : false;\n             $scope.propertyName = propertyName;\n             $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       .friends {\n         border-collapse: collapse;\n       }\n\n       .friends th {\n         border-bottom: 1px solid;\n       }\n       .friends td, .friends th {\n         border-left: 1px solid;\n         padding: 5px 10px;\n       }\n       .friends td:first-child, .friends th:first-child {\n         border-left: none;\n       }\n\n       .sortorder:after {\n         content: '\\25b2';   // BLACK UP-POINTING TRIANGLE\n       }\n       .sortorder.reverse:after {\n         content: '\\25bc';   // BLACK DOWN-POINTING TRIANGLE\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       // Element locators\n       var unsortButton = element(by.partialButtonText('unsorted'));\n       var nameHeader = element(by.partialButtonText('Name'));\n       var phoneHeader = element(by.partialButtonText('Phone'));\n       var ageHeader = element(by.partialButtonText('Age'));\n       var firstName = element(by.repeater('friends').column('friend.name').row(0));\n       var lastName = element(by.repeater('friends').column('friend.name').row(4));\n\n       it('should sort friends by some property, when clicking on the column header', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         phoneHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Mary');\n\n         nameHeader.click();\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('Mike');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Adam');\n       });\n\n       it('should sort friends in reverse order, when clicking on the same column', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Adam');\n\n         ageHeader.click();\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n       });\n\n       it('should restore the original order, when clicking \"Set to unsorted\"', function() {\n         expect(firstName.getText()).toBe('Adam');\n         expect(lastName.getText()).toBe('John');\n\n         unsortButton.click();\n         expect(firstName.getText()).toBe('John');\n         expect(lastName.getText()).toBe('Julie');\n       });\n     </file>\n   </example>\n * <hr />\n *\n * @example\n * ### Using a custom comparator\n *\n * If you have very specific requirements about the way items are sorted, you can pass your own\n * comparator function. For example, you might need to compare some strings in a locale-sensitive\n * way. (When specifying a custom comparator, you also need to pass a value for the `reverse`\n * argument - passing `false` retains the default sorting order, i.e. ascending.)\n *\n   <example name=\"orderBy-custom-comparator\" module=\"orderByExample4\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <div class=\"friends-container custom-comparator\">\n           <h3>Locale-sensitive Comparator</h3>\n           <table class=\"friends\">\n             <tr>\n               <th>Name</th>\n               <th>Favorite Letter</th>\n             </tr>\n             <tr ng-repeat=\"friend in friends | orderBy:'favoriteLetter':false:localeSensitiveComparator\">\n               <td>{{friend.name}}</td>\n               <td>{{friend.favoriteLetter}}</td>\n             </tr>\n           </table>\n         </div>\n         <div class=\"friends-container default-comparator\">\n           <h3>Default Comparator</h3>\n           <table class=\"friends\">\n             <tr>\n               <th>Name</th>\n               <th>Favorite Letter</th>\n             </tr>\n             <tr ng-repeat=\"friend in friends | orderBy:'favoriteLetter'\">\n               <td>{{friend.name}}</td>\n               <td>{{friend.favoriteLetter}}</td>\n             </tr>\n           </table>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('orderByExample4', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.friends = [\n             {name: 'John',   favoriteLetter: 'Ä'},\n             {name: 'Mary',   favoriteLetter: 'Ü'},\n             {name: 'Mike',   favoriteLetter: 'Ö'},\n             {name: 'Adam',   favoriteLetter: 'H'},\n             {name: 'Julie',  favoriteLetter: 'Z'}\n           ];\n\n           $scope.localeSensitiveComparator = function(v1, v2) {\n             // If we don't get strings, just compare by index\n             if (v1.type !== 'string' || v2.type !== 'string') {\n               return (v1.index < v2.index) ? -1 : 1;\n             }\n\n             // Compare strings alphabetically, taking locale into account\n             return v1.value.localeCompare(v2.value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       .friends-container {\n         display: inline-block;\n         margin: 0 30px;\n       }\n\n       .friends {\n         border-collapse: collapse;\n       }\n\n       .friends th {\n         border-bottom: 1px solid;\n       }\n       .friends td, .friends th {\n         border-left: 1px solid;\n         padding: 5px 10px;\n       }\n       .friends td:first-child, .friends th:first-child {\n         border-left: none;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       // Element locators\n       var container = element(by.css('.custom-comparator'));\n       var names = container.all(by.repeater('friends').column('friend.name'));\n\n       it('should sort friends by favorite letter (in correct alphabetical order)', function() {\n         expect(names.get(0).getText()).toBe('John');\n         expect(names.get(1).getText()).toBe('Adam');\n         expect(names.get(2).getText()).toBe('Mike');\n         expect(names.get(3).getText()).toBe('Mary');\n         expect(names.get(4).getText()).toBe('Julie');\n       });\n     </file>\n   </example>\n *\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n  return function(array, sortPredicate, reverseOrder, compareFn) {\n\n    if (array == null) return array;\n    if (!isArrayLike(array)) {\n      throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array);\n    }\n\n    if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n\n    var predicates = processPredicates(sortPredicate);\n\n    var descending = reverseOrder ? -1 : 1;\n\n    // Define the `compare()` function. Use a default comparator if none is specified.\n    var compare = isFunction(compareFn) ? compareFn : defaultCompare;\n\n    // The next three lines are a version of a Swartzian Transform idiom from Perl\n    // (sometimes called the Decorate-Sort-Undecorate idiom)\n    // See https://en.wikipedia.org/wiki/Schwartzian_transform\n    var compareValues = Array.prototype.map.call(array, getComparisonObject);\n    compareValues.sort(doComparison);\n    array = compareValues.map(function(item) { return item.value; });\n\n    return array;\n\n    function getComparisonObject(value, index) {\n      // NOTE: We are adding an extra `tieBreaker` value based on the element's index.\n      // This will be used to keep the sort stable when none of the input predicates can\n      // distinguish between two elements.\n      return {\n        value: value,\n        tieBreaker: {value: index, type: 'number', index: index},\n        predicateValues: predicates.map(function(predicate) {\n          return getPredicateValue(predicate.get(value), index);\n        })\n      };\n    }\n\n    function doComparison(v1, v2) {\n      for (var i = 0, ii = predicates.length; i < ii; i++) {\n        var result = compare(v1.predicateValues[i], v2.predicateValues[i]);\n        if (result) {\n          return result * predicates[i].descending * descending;\n        }\n      }\n\n      return (compare(v1.tieBreaker, v2.tieBreaker) || defaultCompare(v1.tieBreaker, v2.tieBreaker)) * descending;\n    }\n  };\n\n  function processPredicates(sortPredicates) {\n    return sortPredicates.map(function(predicate) {\n      var descending = 1, get = identity;\n\n      if (isFunction(predicate)) {\n        get = predicate;\n      } else if (isString(predicate)) {\n        if ((predicate.charAt(0) === '+' || predicate.charAt(0) === '-')) {\n          descending = predicate.charAt(0) === '-' ? -1 : 1;\n          predicate = predicate.substring(1);\n        }\n        if (predicate !== '') {\n          get = $parse(predicate);\n          if (get.constant) {\n            var key = get();\n            get = function(value) { return value[key]; };\n          }\n        }\n      }\n      return {get: get, descending: descending};\n    });\n  }\n\n  function isPrimitive(value) {\n    switch (typeof value) {\n      case 'number': /* falls through */\n      case 'boolean': /* falls through */\n      case 'string':\n        return true;\n      default:\n        return false;\n    }\n  }\n\n  function objectValue(value) {\n    // If `valueOf` is a valid function use that\n    if (isFunction(value.valueOf)) {\n      value = value.valueOf();\n      if (isPrimitive(value)) return value;\n    }\n    // If `toString` is a valid function and not the one from `Object.prototype` use that\n    if (hasCustomToString(value)) {\n      value = value.toString();\n      if (isPrimitive(value)) return value;\n    }\n\n    return value;\n  }\n\n  function getPredicateValue(value, index) {\n    var type = typeof value;\n    if (value === null) {\n      type = 'null';\n    } else if (type === 'object') {\n      value = objectValue(value);\n    }\n    return {value: value, type: type, index: index};\n  }\n\n  function defaultCompare(v1, v2) {\n    var result = 0;\n    var type1 = v1.type;\n    var type2 = v2.type;\n\n    if (type1 === type2) {\n      var value1 = v1.value;\n      var value2 = v2.value;\n\n      if (type1 === 'string') {\n        // Compare strings case-insensitively\n        value1 = value1.toLowerCase();\n        value2 = value2.toLowerCase();\n      } else if (type1 === 'object') {\n        // For basic objects, use the position of the object\n        // in the collection instead of the value\n        if (isObject(value1)) value1 = v1.index;\n        if (isObject(value2)) value2 = v2.index;\n      }\n\n      if (value1 !== value2) {\n        result = value1 < value2 ? -1 : 1;\n      }\n    } else {\n      result = (type1 === 'undefined') ? 1 :\n        (type2 === 'undefined') ? -1 :\n        (type1 === 'null') ? 1 :\n        (type2 === 'null') ? -1 :\n        (type1 < type2) ? -1 : 1;\n    }\n\n    return result;\n  }\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html a tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * For dynamically creating `href` attributes for a tags, see the {@link ng.ngHref `ngHref`} directive.\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n    if (!attr.href && !attr.xlinkHref) {\n      return function(scope, element) {\n        // If the linked element is not an anchor tag anymore, do nothing\n        if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event) {\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using AngularJS markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * AngularJS has a chance to replace the `{{hash}}` markup with its\n * value. Until AngularJS replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\">link1</a>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example name=\"ng-href\">\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an AngularJS page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        it('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an AngularJS page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using AngularJS markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until AngularJS replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\" alt=\"Description\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\" alt=\"Description\" />\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using AngularJS markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until AngularJS replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\" alt=\"Description\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\" alt=\"Description\" />\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * This directive sets the `disabled` attribute on the element (typically a form control,\n * e.g. `input`, `button`, `select` etc.) if the\n * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.\n *\n * A special directive is necessary because we cannot use interpolation inside the `disabled`\n * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n *\n * @example\n    <example name=\"ng-disabled\">\n      <file name=\"index.html\">\n        <label>Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"></label><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then the `disabled` attribute will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.\n *\n * Note that this directive should not be used together with {@link ngModel `ngModel`},\n * as this can lead to unexpected behavior.\n *\n * A special directive is necessary because we cannot use interpolation inside the `checked`\n * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n *\n * @example\n    <example name=\"ng-checked\">\n      <file name=\"index.html\">\n        <label>Check me to check both: <input type=\"checkbox\" ng-model=\"leader\"></label><br/>\n        <input id=\"checkFollower\" type=\"checkbox\" ng-checked=\"leader\" aria-label=\"Follower input\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkFollower')).getAttribute('checked')).toBeFalsy();\n          element(by.model('leader')).click();\n          expect(element(by.id('checkFollower')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then the `checked` attribute will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy.\n * Note that `readonly` applies only to `input` elements with specific types. [See the input docs on\n * MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information.\n *\n * A special directive is necessary because we cannot use interpolation inside the `readonly`\n * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n *\n * @example\n    <example name=\"ng-readonly\">\n      <file name=\"index.html\">\n        <label>Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"></label><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm AngularJS\" aria-label=\"Readonly field\" />\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.\n *\n * A special directive is necessary because we cannot use interpolation inside the `selected`\n * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n *\n * <div class=\"alert alert-warning\">\n *   **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only\n *   sets the `selected` attribute on the element. If you are using `ngModel` on the select, you\n *   should not use `ngSelected` on the options, as `ngModel` will set the select value and\n *   selected options.\n * </div>\n *\n * @example\n    <example name=\"ng-selected\">\n      <file name=\"index.html\">\n        <label>Check me to select: <input type=\"checkbox\" ng-model=\"selected\"></label><br/>\n        <select aria-label=\"ngSelected demo\">\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.\n *\n * A special directive is necessary because we cannot use interpolation inside the `open`\n * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n *\n * ## A note about browser compatibility\n *\n * Internet Explorer and Edge do not support the `details` element, it is\n * recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead.\n *\n * @example\n     <example name=\"ng-open\">\n       <file name=\"index.html\">\n         <label>Toggle details: <input type=\"checkbox\" ng-model=\"open\"></label><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>List</summary>\n            <ul>\n              <li>Apple</li>\n              <li>Orange</li>\n              <li>Durian</li>\n            </ul>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName === 'multiple') return;\n\n  function defaultLinkFn(scope, element, attr) {\n    scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n      attr.$set(attrName, !!value);\n    });\n  }\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  var linkFn = defaultLinkFn;\n\n  if (propName === 'checked') {\n    linkFn = function(scope, element, attr) {\n      // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input\n      if (attr.ngModel !== attr[normalized]) {\n        defaultLinkFn(scope, element, attr);\n      }\n    };\n  }\n\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      restrict: 'A',\n      priority: 100,\n      link: linkFn\n    };\n  };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n  ngAttributeAliasDirectives[ngAttr] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        //special case ngPattern when a literal regular expression value\n        //is used as the expression (this way we don't have to watch anything).\n        if (ngAttr === 'ngPattern' && attr.ngPattern.charAt(0) === '/') {\n          var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n          if (match) {\n            attr.$set('ngPattern', new RegExp(match[1], match[2]));\n            return;\n          }\n        }\n\n        scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n          attr.$set(ngAttr, value);\n        });\n      }\n    };\n  };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = ['$sce', function($sce) {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        // We need to sanitize the url at least once, in case it is a constant\n        // non-interpolated attribute.\n        attr.$set(normalized, $sce.getTrustedMediaUrl(attr[normalized]));\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // Support: IE 9-11 only\n          // On IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // We use attr[attrName] value since $set might have sanitized the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  }];\n});\n\n/* global -nullFormCtrl, -PENDING_CLASS, -SUBMITTED_CLASS\n */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $getControls: valueFn([]),\n  $$renameControl: nullFormRenameControl,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop,\n  $setSubmitted: noop,\n  $$setSubmitted: noop\n},\nPENDING_CLASS = 'ng-pending',\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n  control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $pending An object hash, containing references to controls or forms with\n *  pending validators, where:\n *\n *  - keys are validations tokens (error names).\n *  - values are arrays of controls or forms that have a pending validator for the given error name.\n *\n * See {@link form.FormController#$error $error} for a list of built-in validation tokens.\n *\n * @property {Object} $error An object hash, containing references to controls or forms with failing\n *  validators, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that have a failing validator for the given error name.\n *\n *  Built-in validation tokens:\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *  - `date`\n *  - `datetimelocal`\n *  - `time`\n *  - `week`\n *  - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController($element, $attrs, $scope, $animate, $interpolate) {\n  this.$$controls = [];\n\n  // init state\n  this.$error = {};\n  this.$$success = {};\n  this.$pending = undefined;\n  this.$name = $interpolate($attrs.name || $attrs.ngForm || '')($scope);\n  this.$dirty = false;\n  this.$pristine = true;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$submitted = false;\n  this.$$parentForm = nullFormCtrl;\n\n  this.$$element = $element;\n  this.$$animate = $animate;\n\n  setupValidity(this);\n}\n\nFormController.prototype = {\n  /**\n   * @ngdoc method\n   * @name form.FormController#$rollbackViewValue\n   *\n   * @description\n   * Rollback all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is typically needed by the reset button of\n   * a form that uses `ng-model-options` to pend updates.\n   */\n  $rollbackViewValue: function() {\n    forEach(this.$$controls, function(control) {\n      control.$rollbackViewValue();\n    });\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$commitViewValue\n   *\n   * @description\n   * Commit all form controls pending updates to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  $commitViewValue: function() {\n    forEach(this.$$controls, function(control) {\n      control.$commitViewValue();\n    });\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   * @param {object} control control object, either a {@link form.FormController} or an\n   * {@link ngModel.NgModelController}\n   *\n   * @description\n   * Register a control with the form. Input elements using ngModelController do this automatically\n   * when they are linked.\n   *\n   * Note that the current state of the control will not be reflected on the new parent form. This\n   * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`\n   * state.\n   *\n   * However, if the method is used programmatically, for example by adding dynamically created controls,\n   * or controls that have been previously removed without destroying their corresponding DOM element,\n   * it's the developers responsibility to make sure the current state propagates to the parent form.\n   *\n   * For example, if an input control is added that is already `$dirty` and has `$error` properties,\n   * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.\n   */\n  $addControl: function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    this.$$controls.push(control);\n\n    if (control.$name) {\n      this[control.$name] = control;\n    }\n\n    control.$$parentForm = this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$getControls\n   * @returns {Array} the controls that are currently part of this form\n   *\n   * @description\n   * This method returns a **shallow copy** of the controls that are currently part of this form.\n   * The controls can be instances of {@link form.FormController `FormController`}\n   * ({@link ngForm \"child-forms\"}) and of {@link ngModel.NgModelController `NgModelController`}.\n   * If you need access to the controls of child-forms, you have to call `$getControls()`\n   * recursively on them.\n   * This can be used for example to iterate over all controls to validate them.\n   *\n   * The controls can be accessed normally, but adding to, or removing controls from the array has\n   * no effect on the form. Instead, use {@link form.FormController#$addControl `$addControl()`} and\n   * {@link form.FormController#$removeControl `$removeControl()`} for this use-case.\n   * Likewise, adding a control to, or removing a control from the form is not reflected\n   * in the shallow copy. That means you should get a fresh copy from `$getControls()` every time\n   * you need access to the controls.\n   */\n  $getControls: function() {\n    return shallowCopy(this.$$controls);\n  },\n\n  // Private API: rename a form control\n  $$renameControl: function(control, newName) {\n    var oldName = control.$name;\n\n    if (this[oldName] === control) {\n      delete this[oldName];\n    }\n    this[newName] = control;\n    control.$name = newName;\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   * @param {object} control control object, either a {@link form.FormController} or an\n   * {@link ngModel.NgModelController}\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   *\n   * Note that only the removed control's validation state (`$errors`etc.) will be removed from the\n   * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be\n   * different from case to case. For example, removing the only `$dirty` control from a form may or\n   * may not mean that the form is still `$dirty`.\n   */\n  $removeControl: function(control) {\n    if (control.$name && this[control.$name] === control) {\n      delete this[control.$name];\n    }\n    forEach(this.$pending, function(value, name) {\n      // eslint-disable-next-line no-invalid-this\n      this.$setValidity(name, null, control);\n    }, this);\n    forEach(this.$error, function(value, name) {\n      // eslint-disable-next-line no-invalid-this\n      this.$setValidity(name, null, control);\n    }, this);\n    forEach(this.$$success, function(value, name) {\n      // eslint-disable-next-line no-invalid-this\n      this.$setValidity(name, null, control);\n    }, this);\n\n    arrayRemove(this.$$controls, control);\n    control.$$parentForm = nullFormCtrl;\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  $setDirty: function() {\n    this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);\n    this.$$animate.addClass(this.$$element, DIRTY_CLASS);\n    this.$dirty = true;\n    this.$pristine = false;\n    this.$$parentForm.$setDirty();\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method sets the form's `$pristine` state to true, the `$dirty` state to false, removes\n   * the `ng-dirty` class and adds the `ng-pristine` class. Additionally, it sets the `$submitted`\n   * state to false.\n   *\n   * This method will also propagate to all the controls contained in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  $setPristine: function() {\n    this.$$animate.setClass(this.$$element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n    this.$dirty = false;\n    this.$pristine = true;\n    this.$submitted = false;\n    forEach(this.$$controls, function(control) {\n      control.$setPristine();\n    });\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setUntouched\n   *\n   * @description\n   * Sets the form to its untouched state.\n   *\n   * This method can be called to remove the 'ng-touched' class and set the form controls to their\n   * untouched state (ng-untouched class).\n   *\n   * Setting a form controls back to their untouched state is often useful when setting the form\n   * back to its pristine state.\n   */\n  $setUntouched: function() {\n    forEach(this.$$controls, function(control) {\n      control.$setUntouched();\n    });\n  },\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setSubmitted\n   *\n   * @description\n   * Sets the form to its `$submitted` state. This will also set `$submitted` on all child and\n   * parent forms of the form.\n   */\n  $setSubmitted: function() {\n    var rootForm = this;\n    while (rootForm.$$parentForm && (rootForm.$$parentForm !== nullFormCtrl)) {\n      rootForm = rootForm.$$parentForm;\n    }\n    rootForm.$$setSubmitted();\n  },\n\n  $$setSubmitted: function() {\n    this.$$animate.addClass(this.$$element, SUBMITTED_CLASS);\n    this.$submitted = true;\n    forEach(this.$$controls, function(control) {\n      if (control.$$setSubmitted) {\n        control.$$setSubmitted();\n      }\n    });\n  }\n};\n\n/**\n * @ngdoc method\n * @name form.FormController#$setValidity\n *\n * @description\n * Change the validity state of the form, and notify the parent form (if any).\n *\n * Application developers will rarely need to call this method directly. It is used internally, by\n * {@link ngModel.NgModelController#$setValidity NgModelController.$setValidity()}, to propagate a\n * control's validity state to the parent `FormController`.\n *\n * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be\n *        assigned to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` (for\n *        unfulfilled `$asyncValidators`), so that it is available for data-binding. The\n *        `validationErrorKey` should be in camelCase and will get converted into dash-case for\n *        class name. Example: `myError` will result in `ng-valid-my-error` and\n *        `ng-invalid-my-error` classes and can be bound to as `{{ someForm.$error.myError }}`.\n * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending\n *        (undefined),  or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n *        Skipped is used by AngularJS when validators do not run because of parse errors and when\n *        `$asyncValidators` do not run because any of the `$validators` failed.\n * @param {NgModelController | FormController} controller - The controller whose validity state is\n *        triggering the change.\n */\naddSetValidityMethod({\n  clazz: FormController,\n  set: function(object, property, controller) {\n    var list = object[property];\n    if (!list) {\n      object[property] = [controller];\n    } else {\n      var index = list.indexOf(controller);\n      if (index === -1) {\n        list.push(controller);\n      }\n    }\n  },\n  unset: function(object, property, controller) {\n    var list = object[property];\n    if (!list) {\n      return;\n    }\n    arrayRemove(list, controller);\n    if (list.length === 0) {\n      delete object[property];\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Helper directive that makes it possible to create control groups inside a\n * {@link ng.directive:form `form`} directive.\n * These \"child forms\" can be used, for example, to determine the validity of a sub-group of\n * controls.\n *\n * <div class=\"alert alert-danger\">\n * **Note**: `ngForm` cannot be used as a replacement for `<form>`, because it lacks its\n * [built-in HTML functionality](https://html.spec.whatwg.org/#the-form-element).\n * Specifically, you cannot submit `ngForm` like a `<form>` tag. That means,\n * you cannot send data to the server with `ngForm`, or integrate it with\n * {@link ng.directive:ngSubmit `ngSubmit`}.\n * </div>\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will\n *                              be published into the related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * ## Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In AngularJS, forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * AngularJS provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to\n * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group\n * of controls needs to be determined.\n *\n * ## CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pending` is set if the form is pending.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *  - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * ## Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side AngularJS applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, AngularJS prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * @animations\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example name=\"ng-form\" deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <code>userType = {{userType}}</code><br>\n         <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>\n         <code>myForm.input.$error = {{myForm.input.$error}}</code><br>\n         <code>myForm.$valid = {{myForm.$valid}}</code><br>\n         <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', '$parse', function($timeout, $parse) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form\n      controller: FormController,\n      compile: function ngFormCompile(formElement, attr) {\n        // Setup initial state of the control\n        formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n        var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);\n\n        return {\n          pre: function ngFormPreLink(scope, formElement, attr, ctrls) {\n            var controller = ctrls[0];\n\n            // if `action` attr is not present on the form, prevent the default action (submission)\n            if (!('action' in attr)) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var handleFormSubmission = function(event) {\n                scope.$apply(function() {\n                  controller.$commitViewValue();\n                  controller.$setSubmitted();\n                });\n\n                event.preventDefault();\n              };\n\n              formElement[0].addEventListener('submit', handleFormSubmission);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  formElement[0].removeEventListener('submit', handleFormSubmission);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = ctrls[1] || controller.$$parentForm;\n            parentFormCtrl.$addControl(controller);\n\n            var setter = nameAttr ? getSetter(controller.$name) : noop;\n\n            if (nameAttr) {\n              setter(scope, controller);\n              attr.$observe(nameAttr, function(newValue) {\n                if (controller.$name === newValue) return;\n                setter(scope, undefined);\n                controller.$$parentForm.$$renameControl(controller, newValue);\n                setter = getSetter(controller.$name);\n                setter(scope, controller);\n              });\n            }\n            formElement.on('$destroy', function() {\n              controller.$$parentForm.$removeControl(controller);\n              setter(scope, undefined);\n              extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n            });\n          }\n        };\n      }\n    };\n\n    return formDirective;\n\n    function getSetter(expression) {\n      if (expression === '') {\n        //create an assignable expression, so forms with an empty name can be renamed later\n        return $parse('this[\"\"]').assign;\n      }\n      return $parse(expression).assign || noop;\n    }\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n\n\n// helper methods\nfunction setupValidity(instance) {\n  instance.$$classCache = {};\n  instance.$$classCache[INVALID_CLASS] = !(instance.$$classCache[VALID_CLASS] = instance.$$element.hasClass(VALID_CLASS));\n}\nfunction addSetValidityMethod(context) {\n  var clazz = context.clazz,\n      set = context.set,\n      unset = context.unset;\n\n  clazz.prototype.$setValidity = function(validationErrorKey, state, controller) {\n    if (isUndefined(state)) {\n      createAndSet(this, '$pending', validationErrorKey, controller);\n    } else {\n      unsetAndCleanup(this, '$pending', validationErrorKey, controller);\n    }\n    if (!isBoolean(state)) {\n      unset(this.$error, validationErrorKey, controller);\n      unset(this.$$success, validationErrorKey, controller);\n    } else {\n      if (state) {\n        unset(this.$error, validationErrorKey, controller);\n        set(this.$$success, validationErrorKey, controller);\n      } else {\n        set(this.$error, validationErrorKey, controller);\n        unset(this.$$success, validationErrorKey, controller);\n      }\n    }\n    if (this.$pending) {\n      cachedToggleClass(this, PENDING_CLASS, true);\n      this.$valid = this.$invalid = undefined;\n      toggleValidationCss(this, '', null);\n    } else {\n      cachedToggleClass(this, PENDING_CLASS, false);\n      this.$valid = isObjectEmpty(this.$error);\n      this.$invalid = !this.$valid;\n      toggleValidationCss(this, '', this.$valid);\n    }\n\n    // re-read the state as the set/unset methods could have\n    // combined state in this.$error[validationError] (used for forms),\n    // where setting/unsetting only increments/decrements the value,\n    // and does not replace it.\n    var combinedState;\n    if (this.$pending && this.$pending[validationErrorKey]) {\n      combinedState = undefined;\n    } else if (this.$error[validationErrorKey]) {\n      combinedState = false;\n    } else if (this.$$success[validationErrorKey]) {\n      combinedState = true;\n    } else {\n      combinedState = null;\n    }\n\n    toggleValidationCss(this, validationErrorKey, combinedState);\n    this.$$parentForm.$setValidity(validationErrorKey, combinedState, this);\n  };\n\n  function createAndSet(ctrl, name, value, controller) {\n    if (!ctrl[name]) {\n      ctrl[name] = {};\n    }\n    set(ctrl[name], value, controller);\n  }\n\n  function unsetAndCleanup(ctrl, name, value, controller) {\n    if (ctrl[name]) {\n      unset(ctrl[name], value, controller);\n    }\n    if (isObjectEmpty(ctrl[name])) {\n      ctrl[name] = undefined;\n    }\n  }\n\n  function cachedToggleClass(ctrl, className, switchValue) {\n    if (switchValue && !ctrl.$$classCache[className]) {\n      ctrl.$$animate.addClass(ctrl.$$element, className);\n      ctrl.$$classCache[className] = true;\n    } else if (!switchValue && ctrl.$$classCache[className]) {\n      ctrl.$$animate.removeClass(ctrl.$$element, className);\n      ctrl.$$classCache[className] = false;\n    }\n  }\n\n  function toggleValidationCss(ctrl, validationErrorKey, isValid) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n\n    cachedToggleClass(ctrl, VALID_CLASS + validationErrorKey, isValid === true);\n    cachedToggleClass(ctrl, INVALID_CLASS + validationErrorKey, isValid === false);\n  }\n}\n\nfunction isObjectEmpty(obj) {\n  if (obj) {\n    for (var prop in obj) {\n      if (obj.hasOwnProperty(prop)) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\n/* global\n  VALID_CLASS: false,\n  INVALID_CLASS: false,\n  PRISTINE_CLASS: false,\n  DIRTY_CLASS: false,\n  ngModelMinErr: false\n*/\n\n// Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /^\\d{4,}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+(?:[+-][0-2]\\d:[0-5]\\d|Z)$/;\n// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)\n// Note: We are being more lenient, because browsers are too.\n//   1. Scheme\n//   2. Slashes\n//   3. Username\n//   4. Password\n//   5. Hostname\n//   6. Port\n//   7. Path\n//   8. Query\n//   9. Fragment\n//                 1111111111111111 222   333333    44444        55555555555555555555555     666     77777777     8888888     999\nvar URL_REGEXP = /^[a-z][a-z\\d.+-]*:\\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\\s:/?#]+|\\[[a-f\\d:]+])(?::\\d+)?(?:\\/[^?#]*)?(?:\\?[^#]*)?(?:#.*)?$/i;\n// eslint-disable-next-line max-len\nvar EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;\nvar NUMBER_REGEXP = /^\\s*(-|\\+)?(\\d+|(\\d*(\\.\\d*)))([eE][+-]?\\d+)?\\s*$/;\nvar DATE_REGEXP = /^(\\d{4,})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4,})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4,})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4,})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown';\nvar PARTIAL_VALIDATION_TYPES = createMap();\nforEach('date,datetime-local,month,time,week'.split(','), function(type) {\n  PARTIAL_VALIDATION_TYPES[type] = true;\n});\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with AngularJS data binding, inherited by most of the `input` elements.\n   *\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n   *    does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object, then this is used directly.\n   *    If the expression evaluates to a string, then it will be converted to a RegExp\n   *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n   *    `new RegExp('^abc$')`.<br />\n   *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n   *    start at the index of the last search's match, thus not taking the whole input value into\n   *    account.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 text: 'guest',\n                 word: /^\\s*\\w*\\s*$/\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <label>Single word:\n             <input type=\"text\" name=\"input\" ng-model=\"example.text\"\n                    ng-pattern=\"example.word\" required ng-trim=\"false\">\n           </label>\n           <div role=\"alert\">\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n               Single word only!</span>\n           </div>\n           <code>text = {{example.text}}</code><br/>\n           <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br/>\n           <code>myForm.input.$error = {{myForm.input.$error}}</code><br/>\n           <code>myForm.$valid = {{myForm.$valid}}</code><br/>\n           <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('example.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n    /**\n     * @ngdoc input\n     * @name input[date]\n     *\n     * @description\n     * Input with date validation and transformation. In browsers that do not yet support\n     * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n     * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n     * modern browsers do not yet support this input type, it is important to provide cues to users on the\n     * expected input format via a placeholder or label.\n     *\n     * The model must always be a Date object, otherwise AngularJS will throw an error.\n     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n     *\n     * The timezone to be used to read/write the `Date` instance in the model can be defined using\n     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n     *\n     * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n     * @param {string=} name Property name of the form under which the control is published.\n     * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n     *   valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute\n     *   (e.g. `min=\"{{minDate | date:'yyyy-MM-dd'}}\"`). Note that `min` will also add native HTML5\n     *   constraint validation.\n     * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n     *   a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute\n     *   (e.g. `max=\"{{maxDate | date:'yyyy-MM-dd'}}\"`). Note that `max` will also add native HTML5\n     *   constraint validation.\n     * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string\n     *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n     * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string\n     *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n     * @param {string=} required Sets `required` validation error key if the value is not entered.\n     * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n     *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n     *    `required` when you want to data-bind to the `required` attribute.\n     * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n     *    interaction with the input element.\n     *\n     * @example\n     <example name=\"date-input-directive\" module=\"dateInputExample\">\n     <file name=\"index.html\">\n       <script>\n          angular.module('dateInputExample', [])\n            .controller('DateController', ['$scope', function($scope) {\n              $scope.example = {\n                value: new Date(2013, 9, 22)\n              };\n            }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n          <label for=\"exampleInput\">Pick a date in 2013:</label>\n          <input type=\"date\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n              placeholder=\"yyyy-MM-dd\" min=\"2013-01-01\" max=\"2013-12-31\" required />\n          <div role=\"alert\">\n            <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n                Required!</span>\n            <span class=\"error\" ng-show=\"myForm.input.$error.date\">\n                Not a valid date!</span>\n           </div>\n           <tt>value = {{example.value | date: \"yyyy-MM-dd\"}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n       </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n        var valid = element(by.binding('myForm.input.$valid'));\n\n        // currently protractor/webdriver does not support\n        // sending keys to all known HTML5 input controls\n        // for various browsers (see https://github.com/angular/protractor/issues/562).\n        function setInput(val) {\n          // set the value of the element and force validation.\n          var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n          \"ipt.value = '\" + val + \"';\" +\n          \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n          browser.executeScript(scr);\n        }\n\n        it('should initialize to model', function() {\n          expect(value.getText()).toContain('2013-10-22');\n          expect(valid.getText()).toContain('myForm.input.$valid = true');\n        });\n\n        it('should be invalid if empty', function() {\n          setInput('');\n          expect(value.getText()).toEqual('value =');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n\n        it('should be invalid if over max', function() {\n          setInput('2015-01-01');\n          expect(value.getText()).toContain('');\n          expect(valid.getText()).toContain('myForm.input.$valid = false');\n        });\n     </file>\n     </example>\n     */\n  'date': createDateInputType('date', DATE_REGEXP,\n         createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n         'yyyy-MM-dd'),\n\n   /**\n    * @ngdoc input\n    * @name input[datetime-local]\n    *\n    * @description\n    * Input with datetime validation and transformation. In browsers that do not yet support\n    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n    *\n    * The model must always be a Date object, otherwise AngularJS will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * The format of the displayed time can be adjusted with the\n    * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat`\n    * and `timeStripZeroSeconds`.\n    *\n    * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n    *   This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation\n    *   inside this attribute (e.g. `min=\"{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}\"`).\n    *   Note that `min` will also add native HTML5 constraint validation.\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n    *   This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation\n    *   inside this attribute (e.g. `max=\"{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}\"`).\n    *   Note that `max` will also add native HTML5 constraint validation.\n    * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string\n    *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n    * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string\n    *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"datetimelocal-input-directive\" module=\"dateExample\">\n    <file name=\"index.html\">\n      <script>\n        angular.module('dateExample', [])\n          .controller('DateController', ['$scope', function($scope) {\n            $scope.example = {\n              value: new Date(2010, 11, 28, 14, 57)\n            };\n          }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        <label for=\"exampleInput\">Pick a date between in 2013:</label>\n        <input type=\"datetime-local\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"yyyy-MM-ddTHH:mm:ss\" min=\"2001-01-01T00:00:00\" max=\"2013-12-31T00:00:00\" required />\n        <div role=\"alert\">\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.datetimelocal\">\n              Not a valid date!</span>\n        </div>\n        <tt>value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2010-12-28T14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01-01T23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n      createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n      'yyyy-MM-ddTHH:mm:ss.sss'),\n\n  /**\n   * @ngdoc input\n   * @name input[time]\n   *\n   * @description\n   * Input with time validation and transformation. In browsers that do not yet support\n   * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n   * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n   *\n   * The model must always be a Date object, otherwise AngularJS will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions}. By default,\n   * this is the timezone of the browser.\n   *\n   * The format of the displayed time can be adjusted with the\n   * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat`\n   * and `timeStripZeroSeconds`.\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   *   This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this\n   *   attribute (e.g. `min=\"{{minTime | date:'HH:mm:ss'}}\"`). Note that `min` will also add\n   *   native HTML5 constraint validation.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   *   This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this\n   *   attribute (e.g. `max=\"{{maxTime | date:'HH:mm:ss'}}\"`). Note that `max` will also add\n   *   native HTML5 constraint validation.\n   * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the\n   *   `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n   * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the\n   *   `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"time-input-directive\" module=\"timeExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('timeExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(1970, 0, 1, 14, 57, 0)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        <label for=\"exampleInput\">Pick a time between 8am and 5pm:</label>\n        <input type=\"time\" id=\"exampleInput\" name=\"input\" ng-model=\"example.value\"\n            placeholder=\"HH:mm:ss\" min=\"08:00:00\" max=\"17:00:00\" required />\n        <div role=\"alert\">\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.time\">\n              Not a valid date!</span>\n        </div>\n        <tt>value = {{example.value | date: \"HH:mm:ss\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('14:57:00');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('23:59:00');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'time': createDateInputType('time', TIME_REGEXP,\n      createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n     'HH:mm:ss.sss'),\n\n   /**\n    * @ngdoc input\n    * @name input[week]\n    *\n    * @description\n    * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n    * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n    * week format (yyyy-W##), for example: `2013-W02`.\n    *\n    * The model must always be a Date object, otherwise AngularJS will throw an error.\n    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n    *\n    * The value of the resulting Date object will be set to Thursday at 00:00:00 of the requested week,\n    * due to ISO-8601 week numbering standards. Information on ISO's system for numbering the weeks of the\n    * year can be found at: https://en.wikipedia.org/wiki/ISO_8601#Week_dates\n    *\n    * The timezone to be used to read/write the `Date` instance in the model can be defined using\n    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n    *\n    * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n    * @param {string=} name Property name of the form under which the control is published.\n    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n    *   This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this\n    *   attribute (e.g. `min=\"{{minWeek | date:'yyyy-Www'}}\"`). Note that `min` will also add\n    *   native HTML5 constraint validation.\n    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n    *   This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this\n    *   attribute (e.g. `max=\"{{maxWeek | date:'yyyy-Www'}}\"`). Note that `max` will also add\n    *   native HTML5 constraint validation.\n    * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string\n    *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n    * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string\n    *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n    * @param {string=} required Sets `required` validation error key if the value is not entered.\n    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n    *    `required` when you want to data-bind to the `required` attribute.\n    * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n    *    interaction with the input element.\n    *\n    * @example\n    <example name=\"week-input-directive\" module=\"weekExample\">\n    <file name=\"index.html\">\n      <script>\n      angular.module('weekExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 0, 3)\n          };\n        }]);\n      </script>\n      <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n        <label>Pick a date between in 2013:\n          <input id=\"exampleInput\" type=\"week\" name=\"input\" ng-model=\"example.value\"\n                 placeholder=\"YYYY-W##\" min=\"2012-W32\"\n                 max=\"2013-W52\" required />\n        </label>\n        <div role=\"alert\">\n          <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n              Required!</span>\n          <span class=\"error\" ng-show=\"myForm.input.$error.week\">\n              Not a valid date!</span>\n        </div>\n        <tt>value = {{example.value | date: \"yyyy-Www\"}}</tt><br/>\n        <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n        <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n        <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n        <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-W01');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-W01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n    </file>\n    </example>\n    */\n  'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n  /**\n   * @ngdoc input\n   * @name input[month]\n   *\n   * @description\n   * Input with month validation and transformation. In browsers that do not yet support\n   * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n   * month format (yyyy-MM), for example: `2009-01`.\n   *\n   * The model must always be a Date object, otherwise AngularJS will throw an error.\n   * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n   * If the model is not set to the first of the month, the next view to model update will set it\n   * to the first of the month.\n   *\n   * The timezone to be used to read/write the `Date` instance in the model can be defined using\n   * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   *   This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this\n   *   attribute (e.g. `min=\"{{minMonth | date:'yyyy-MM'}}\"`). Note that `min` will also add\n   *   native HTML5 constraint validation.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   *   This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this\n   *   attribute (e.g. `max=\"{{maxMonth | date:'yyyy-MM'}}\"`). Note that `max` will also add\n   *   native HTML5 constraint validation.\n   * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string\n   *   the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n   * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string\n   *   the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n   <example name=\"month-input-directive\" module=\"monthExample\">\n   <file name=\"index.html\">\n     <script>\n      angular.module('monthExample', [])\n        .controller('DateController', ['$scope', function($scope) {\n          $scope.example = {\n            value: new Date(2013, 9, 1)\n          };\n        }]);\n     </script>\n     <form name=\"myForm\" ng-controller=\"DateController as dateCtrl\">\n       <label for=\"exampleInput\">Pick a month in 2013:</label>\n       <input id=\"exampleInput\" type=\"month\" name=\"input\" ng-model=\"example.value\"\n          placeholder=\"yyyy-MM\" min=\"2013-01\" max=\"2013-12\" required />\n       <div role=\"alert\">\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n            Required!</span>\n         <span class=\"error\" ng-show=\"myForm.input.$error.month\">\n            Not a valid month!</span>\n       </div>\n       <tt>value = {{example.value | date: \"yyyy-MM\"}}</tt><br/>\n       <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n       <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n       <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n       <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n     </form>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n      var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n      var valid = element(by.binding('myForm.input.$valid'));\n\n      // currently protractor/webdriver does not support\n      // sending keys to all known HTML5 input controls\n      // for various browsers (https://github.com/angular/protractor/issues/562).\n      function setInput(val) {\n        // set the value of the element and force validation.\n        var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n        \"ipt.value = '\" + val + \"';\" +\n        \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n        browser.executeScript(scr);\n      }\n\n      it('should initialize to model', function() {\n        expect(value.getText()).toContain('2013-10');\n        expect(valid.getText()).toContain('myForm.input.$valid = true');\n      });\n\n      it('should be invalid if empty', function() {\n        setInput('');\n        expect(value.getText()).toEqual('value =');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n\n      it('should be invalid if over max', function() {\n        setInput('2015-01');\n        expect(value.getText()).toContain('');\n        expect(valid.getText()).toContain('myForm.input.$valid = false');\n      });\n   </file>\n   </example>\n   */\n  'month': createDateInputType('month', MONTH_REGEXP,\n     createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n     'yyyy-MM'),\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * <div class=\"alert alert-warning\">\n   * The model must always be of type `number` otherwise AngularJS will throw an error.\n   * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}\n   * error docs for more information and an example of how to convert your model if necessary.\n   * </div>\n   *\n   *\n   *\n   * @knownIssue\n   *\n   * ### HTML5 constraint validation and `allowInvalid`\n   *\n   * In browsers that follow the\n   * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),\n   * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.\n   * If a non-number is entered in the input, the browser will report the value as an empty string,\n   * which means the view / model values in `ngModel` and subsequently the scope value\n   * will also be an empty string.\n   *\n   * @knownIssue\n   *\n   * ### Large numbers and `step` validation\n   *\n   * The `step` validation will not work correctly for very large numbers (e.g. 9999999999) due to\n   * Javascript's arithmetic limitations. If you need to handle large numbers, purpose-built\n   * libraries (e.g. https://github.com/MikeMcl/big.js/), can be included into AngularJS by\n   * {@link guide/forms#modifying-built-in-validators overwriting the validators}\n   * for `number` and / or `step`, or by {@link guide/forms#custom-validation applying custom validators}\n   * to an `input[text]` element. The source for `input[number]` type can be used as a starting\n   * point for both implementations.\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   *    Can be interpolated.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   *    Can be interpolated.\n   * @param {string=} ngMin Like `min`, sets the `min` validation error key if the value entered is less than `ngMin`,\n   *    but does not trigger HTML5 native validation. Takes an expression.\n   * @param {string=} ngMax Like `max`, sets the `max` validation error key if the value entered is greater than `ngMax`,\n   *    but does not trigger HTML5 native validation. Takes an expression.\n   * @param {string=} step Sets the `step` validation error key if the value entered does not fit the `step` constraint.\n   *    Can be interpolated.\n   * @param {string=} ngStep Like `step`, sets the `step` validation error key if the value entered does not fit the `ngStep` constraint,\n   *    but does not trigger HTML5 native validation. Takes an expression.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n   *    does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object, then this is used directly.\n   *    If the expression evaluates to a string, then it will be converted to a RegExp\n   *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n   *    `new RegExp('^abc$')`.<br />\n   *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n   *    start at the index of the last search's match, thus not taking the whole input value into\n   *    account.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.example = {\n                 value: 12\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <label>Number:\n             <input type=\"number\" name=\"input\" ng-model=\"example.value\"\n                    min=\"0\" max=\"99\" required>\n          </label>\n           <div role=\"alert\">\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n               Not valid number!</span>\n           </div>\n           <tt>value = {{example.value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('example.value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('example.value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n   * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n   * the built-in validators (see the {@link guide/forms Forms guide})\n   * </div>\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n   *    does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object, then this is used directly.\n   *    If the expression evaluates to a string, then it will be converted to a RegExp\n   *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n   *    `new RegExp('^abc$')`.<br />\n   *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n   *    start at the index of the last search's match, thus not taking the whole input value into\n   *    account.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.url = {\n                 text: 'http://google.com'\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <label>URL:\n             <input type=\"url\" name=\"input\" ng-model=\"url.text\" required>\n           <label>\n           <div role=\"alert\">\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n               Not valid url!</span>\n           </div>\n           <tt>text = {{url.text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('url.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('url.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n   * used in Chromium, which may not fulfill your app's requirements.\n   * If you need stricter (e.g. requiring a top-level domain), or more relaxed validation\n   * (e.g. allowing IPv6 address literals) you can use `ng-pattern` or\n   * modify the built-in validators (see the {@link guide/forms Forms guide}).\n   * </div>\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n   *    any length.\n   * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n   *    that contains the regular expression body that will be converted to a regular expression\n   *    as in the ngPattern directive.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n   *    does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n   *    If the expression evaluates to a RegExp object, then this is used directly.\n   *    If the expression evaluates to a string, then it will be converted to a RegExp\n   *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n   *    `new RegExp('^abc$')`.<br />\n   *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n   *    start at the index of the last search's match, thus not taking the whole input value into\n   *    account.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.email = {\n                 text: 'me@example.com'\n               };\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             <label>Email:\n               <input type=\"email\" name=\"input\" ng-model=\"email.text\" required>\n             </label>\n             <div role=\"alert\">\n               <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n                 Required!</span>\n               <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n                 Not valid email!</span>\n             </div>\n             <tt>text = {{email.text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('email.text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('email.text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * **Note:**<br>\n   * All inputs controlled by {@link ngModel ngModel} (including those of type `radio`) will use the\n   * value of their `name` attribute to determine the property under which their\n   * {@link ngModel.NgModelController NgModelController} will be published on the parent\n   * {@link form.FormController FormController}. Thus, if you use the same `name` for multiple\n   * inputs of a form (e.g. a group of radio inputs), only _one_ `NgModelController` will be\n   * published on the parent `FormController` under that name. The rest of the controllers will\n   * continue to work as expected, but you won't be able to access them as properties on the parent\n   * `FormController`.\n   *\n   * <div class=\"alert alert-info\">\n   *   <p>\n   *     In plain HTML forms, the `name` attribute is used to identify groups of radio inputs, so\n   *     that the browser can manage their state (checked/unchecked) based on the state of other\n   *     inputs in the same group.\n   *   </p>\n   *   <p>\n   *     In AngularJS forms, this is not necessary. The input's state will be updated based on the\n   *     value of the underlying model data.\n   *   </p>\n   * </div>\n   *\n   * <div class=\"alert alert-success\">\n   *   If you omit the `name` attribute on a radio input, `ngModel` will automatically assign it a\n   *   unique name.\n   * </div>\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string} value The value to which the `ngModel` expression should be set when selected.\n   *    Note that `value` only supports `string` values, i.e. the scope model needs to be a string,\n   *    too. Use `ngValue` if you need complex models (`number`, `object`, ...).\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue AngularJS expression to which `ngModel` will be be set when the radio\n   *    is selected. Should be used instead of the `value` attribute if you need\n   *    a non-string `ngModel` (`boolean`, `array`, ...).\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = {\n                 name: 'blue'\n               };\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <label>\n             <input type=\"radio\" ng-model=\"color.name\" value=\"red\">\n             Red\n           </label><br/>\n           <label>\n             <input type=\"radio\" ng-model=\"color.name\" ng-value=\"specialValue\">\n             Green\n           </label><br/>\n           <label>\n             <input type=\"radio\" ng-model=\"color.name\" value=\"blue\">\n             Blue\n           </label><br/>\n           <tt>color = {{color.name | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var inputs = element.all(by.model('color.name'));\n            var color = element(by.binding('color.name'));\n\n            expect(color.getText()).toContain('blue');\n\n            inputs.get(0).click();\n            expect(color.getText()).toContain('red');\n\n            inputs.get(1).click();\n            expect(color.getText()).toContain('green');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n  /**\n   * @ngdoc input\n   * @name input[range]\n   *\n   * @description\n   * Native range input with validation and transformation.\n   *\n   * The model for the range input must always be a `Number`.\n   *\n   * IE9 and other browsers that do not support the `range` type fall back\n   * to a text input without any default values for `min`, `max` and `step`. Model binding,\n   * validation and number parsing are nevertheless supported.\n   *\n   * Browsers that support range (latest Chrome, Safari, Firefox, Edge) treat `input[range]`\n   * in a way that never allows the input to hold an invalid value. That means:\n   * - any non-numerical value is set to `(max + min) / 2`.\n   * - any numerical value that is less than the current min val, or greater than the current max val\n   * is set to the min / max val respectively.\n   * - additionally, the current `step` is respected, so the nearest value that satisfies a step\n   * is used.\n   *\n   * See the [HTML Spec on input[type=range]](https://www.w3.org/TR/html5/forms.html#range-state-(type=range))\n   * for more info.\n   *\n   * This has the following consequences for AngularJS:\n   *\n   * Since the element value should always reflect the current model value, a range input\n   * will set the bound ngModel expression to the value that the browser has set for the\n   * input element. For example, in the following input `<input type=\"range\" ng-model=\"model.value\">`,\n   * if the application sets `model.value = null`, the browser will set the input to `'50'`.\n   * AngularJS will then set the model to `50`, to prevent input and model value being out of sync.\n   *\n   * That means the model for range will immediately be set to `50` after `ngModel` has been\n   * initialized. It also means a range input can never have the required error.\n   *\n   * This does not only affect changes to the model value, but also to the values of the `min`,\n   * `max`, and `step` attributes. When these change in a way that will cause the browser to modify\n   * the input value, AngularJS will also update the model value.\n   *\n   * Automatic value adjustment also means that a range input element can never have the `required`,\n   * `min`, or `max` errors.\n   *\n   * However, `step` is currently only fully implemented by Firefox. Other browsers have problems\n   * when the step value changes dynamically - they do not adjust the element value correctly, but\n   * instead may set the `stepMismatch` error. If that's the case, the AngularJS will set the `step`\n   * error on the input, and set the model to `undefined`.\n   *\n   * Note that `input[range]` is not compatible with`ngMax`, `ngMin`, and `ngStep`, because they do\n   * not set the `min` and `max` attributes, which means that the browser won't automatically adjust\n   * the input value based on their values, and will always assume min = 0, max = 100, and step = 1.\n   *\n   * @param {string}  ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation to ensure that the value entered is greater\n   *                  than `min`. Can be interpolated.\n   * @param {string=} max Sets the `max` validation to ensure that the value entered is less than `max`.\n   *                  Can be interpolated.\n   * @param {string=} step Sets the `step` validation to ensure that the value entered matches the `step`\n   *                  Can be interpolated.\n   * @param {expression=} ngChange AngularJS expression to be executed when the ngModel value changes due\n   *                      to user interaction with the input element.\n   * @param {expression=} ngChecked If the expression is truthy, then the `checked` attribute will be set on the\n   *                      element. **Note** : `ngChecked` should not be used alongside `ngModel`.\n   *                      Checkout {@link ng.directive:ngChecked ngChecked} for usage.\n   *\n   * @example\n      <example name=\"range-input-directive\" module=\"rangeExample\">\n        <file name=\"index.html\">\n          <script>\n            angular.module('rangeExample', [])\n              .controller('ExampleController', ['$scope', function($scope) {\n                $scope.value = 75;\n                $scope.min = 10;\n                $scope.max = 90;\n              }]);\n          </script>\n          <form name=\"myForm\" ng-controller=\"ExampleController\">\n\n            Model as range: <input type=\"range\" name=\"range\" ng-model=\"value\" min=\"{{min}}\"  max=\"{{max}}\">\n            <hr>\n            Model as number: <input type=\"number\" ng-model=\"value\"><br>\n            Min: <input type=\"number\" ng-model=\"min\"><br>\n            Max: <input type=\"number\" ng-model=\"max\"><br>\n            value = <code>{{value}}</code><br/>\n            myForm.range.$valid = <code>{{myForm.range.$valid}}</code><br/>\n            myForm.range.$error = <code>{{myForm.range.$error}}</code>\n          </form>\n        </file>\n      </example>\n\n   * ## Range Input with ngMin & ngMax attributes\n\n   * @example\n      <example name=\"range-input-directive-ng\" module=\"rangeExample\">\n        <file name=\"index.html\">\n          <script>\n            angular.module('rangeExample', [])\n              .controller('ExampleController', ['$scope', function($scope) {\n                $scope.value = 75;\n                $scope.min = 10;\n                $scope.max = 90;\n              }]);\n          </script>\n          <form name=\"myForm\" ng-controller=\"ExampleController\">\n            Model as range: <input type=\"range\" name=\"range\" ng-model=\"value\" ng-min=\"min\" ng-max=\"max\">\n            <hr>\n            Model as number: <input type=\"number\" ng-model=\"value\"><br>\n            Min: <input type=\"number\" ng-model=\"min\"><br>\n            Max: <input type=\"number\" ng-model=\"max\"><br>\n            value = <code>{{value}}</code><br/>\n            myForm.range.$valid = <code>{{myForm.range.$valid}}</code><br/>\n            myForm.range.$error = <code>{{myForm.range.$error}}</code>\n          </form>\n        </file>\n      </example>\n\n   */\n  'range': rangeInputType,\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.checkboxModel = {\n                value1 : true,\n                value2 : 'YES'\n              };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <label>Value1:\n             <input type=\"checkbox\" ng-model=\"checkboxModel.value1\">\n           </label><br/>\n           <label>Value2:\n             <input type=\"checkbox\" ng-model=\"checkboxModel.value2\"\n                    ng-true-value=\"'YES'\" ng-false-value=\"'NO'\">\n            </label><br/>\n           <tt>value1 = {{checkboxModel.value1}}</tt><br/>\n           <tt>value2 = {{checkboxModel.value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('checkboxModel.value1'));\n            var value2 = element(by.binding('checkboxModel.value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('checkboxModel.value1')).click();\n            element(by.model('checkboxModel.value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? value : value.toString();\n  });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var type = lowercase(element[0].type);\n\n  // In composition mode, users are still inputting intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function() {\n      composing = true;\n    });\n\n    // Support: IE9+\n    element.on('compositionupdate', function(ev) {\n      // End composition when ev.data is empty string on 'compositionupdate' event.\n      // When the input de-focusses (e.g. by clicking away), IE triggers 'compositionupdate'\n      // instead of 'compositionend'.\n      if (isUndefined(ev.data) || ev.data === '') {\n        composing = false;\n      }\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var timeout;\n\n  var listener = function(ev) {\n    if (timeout) {\n      $browser.defer.cancel(timeout);\n      timeout = null;\n    }\n    if (composing) return;\n    var value = element.val(),\n        event = ev && ev.type;\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input (due to native validators), browsers discard its\n    // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n    // control's value is the same empty value twice in a row.\n    if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n      ctrl.$setViewValue(value, event);\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var deferListener = function(ev, input, origValue) {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (!input || input.value !== origValue) {\n            listener(ev);\n          }\n        });\n      }\n    };\n\n    element.on('keydown', /** @this */ function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener(event, this, this.value);\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\", \"cut\" and \"drop\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut drop', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  // Some native input types (date-family) have the ability to change validity without\n  // firing any input/change events.\n  // For these event types, when native validators are present and the browser supports the type,\n  // check for validity changes on various DOM events.\n  if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) {\n    element.on(PARTIAL_VALIDATION_EVENTS, /** @this */ function(ev) {\n      if (!timeout) {\n        var validity = this[VALIDITY_STATE_PROPERTY];\n        var origBadInput = validity.badInput;\n        var origTypeMismatch = validity.typeMismatch;\n        timeout = $browser.defer(function() {\n          timeout = null;\n          if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) {\n            listener(ev);\n          }\n        });\n      }\n    });\n  }\n\n  ctrl.$render = function() {\n    // Workaround for Firefox validation #12102.\n    var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;\n    if (element.val() !== value) {\n      element.val(value);\n    }\n  };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n  if (isDate(isoWeek)) {\n    return isoWeek;\n  }\n\n  if (isString(isoWeek)) {\n    WEEK_REGEXP.lastIndex = 0;\n    var parts = WEEK_REGEXP.exec(isoWeek);\n    if (parts) {\n      var year = +parts[1],\n          week = +parts[2],\n          hours = 0,\n          minutes = 0,\n          seconds = 0,\n          milliseconds = 0,\n          firstThurs = getFirstThursdayOfYear(year),\n          addDays = (week - 1) * 7;\n\n      if (existingDate) {\n        hours = existingDate.getHours();\n        minutes = existingDate.getMinutes();\n        seconds = existingDate.getSeconds();\n        milliseconds = existingDate.getMilliseconds();\n      }\n\n      return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n    }\n  }\n\n  return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n  return function(iso, previousDate) {\n    var parts, map;\n\n    if (isDate(iso)) {\n      return iso;\n    }\n\n    if (isString(iso)) {\n      // When a date is JSON'ified to wraps itself inside of an extra\n      // set of double quotes. This makes the date parsing code unable\n      // to match the date string and parse it as a date.\n      if (iso.charAt(0) === '\"' && iso.charAt(iso.length - 1) === '\"') {\n        iso = iso.substring(1, iso.length - 1);\n      }\n      if (ISO_DATE_REGEXP.test(iso)) {\n        return new Date(iso);\n      }\n      regexp.lastIndex = 0;\n      parts = regexp.exec(iso);\n\n      if (parts) {\n        parts.shift();\n        if (previousDate) {\n          map = {\n            yyyy: previousDate.getFullYear(),\n            MM: previousDate.getMonth() + 1,\n            dd: previousDate.getDate(),\n            HH: previousDate.getHours(),\n            mm: previousDate.getMinutes(),\n            ss: previousDate.getSeconds(),\n            sss: previousDate.getMilliseconds() / 1000\n          };\n        } else {\n          map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n        }\n\n        forEach(parts, function(part, index) {\n          if (index < mapping.length) {\n            map[mapping[index]] = +part;\n          }\n        });\n\n        var date = new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n        if (map.yyyy < 100) {\n          // In the constructor, 2-digit years map to 1900-1999.\n          // Use `setFullYear()` to set the correct year.\n          date.setFullYear(map.yyyy);\n        }\n\n        return date;\n      }\n    }\n\n    return NaN;\n  };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n  return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n    badInputChecker(scope, element, attr, ctrl, type);\n    baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n    var isTimeType = type === 'time' || type === 'datetimelocal';\n    var previousDate;\n    var previousTimezone;\n\n    ctrl.$parsers.push(function(value) {\n      if (ctrl.$isEmpty(value)) return null;\n\n      if (regexp.test(value)) {\n        // Note: We cannot read ctrl.$modelValue, as there might be a different\n        // parser/formatter in the processing chain so that the model\n        // contains some different data format!\n        return parseDateAndConvertTimeZoneToLocal(value, previousDate);\n      }\n      ctrl.$$parserName = type;\n      return undefined;\n    });\n\n    ctrl.$formatters.push(function(value) {\n      if (value && !isDate(value)) {\n        throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n      }\n      if (isValidDate(value)) {\n        previousDate = value;\n        var timezone = ctrl.$options.getOption('timezone');\n\n        if (timezone) {\n          previousTimezone = timezone;\n          previousDate = convertTimezoneToLocal(previousDate, timezone, true);\n        }\n\n        return formatter(value, timezone);\n      } else {\n        previousDate = null;\n        previousTimezone = null;\n        return '';\n      }\n    });\n\n    if (isDefined(attr.min) || attr.ngMin) {\n      var minVal = attr.min || $parse(attr.ngMin)(scope);\n      var parsedMinVal = parseObservedDateValue(minVal);\n\n      ctrl.$validators.min = function(value) {\n        return !isValidDate(value) || isUndefined(parsedMinVal) || parseDate(value) >= parsedMinVal;\n      };\n      attr.$observe('min', function(val) {\n        if (val !== minVal) {\n          parsedMinVal = parseObservedDateValue(val);\n          minVal = val;\n          ctrl.$validate();\n        }\n      });\n    }\n\n    if (isDefined(attr.max) || attr.ngMax) {\n      var maxVal = attr.max || $parse(attr.ngMax)(scope);\n      var parsedMaxVal = parseObservedDateValue(maxVal);\n\n      ctrl.$validators.max = function(value) {\n        return !isValidDate(value) || isUndefined(parsedMaxVal) || parseDate(value) <= parsedMaxVal;\n      };\n      attr.$observe('max', function(val) {\n        if (val !== maxVal) {\n          parsedMaxVal = parseObservedDateValue(val);\n          maxVal = val;\n          ctrl.$validate();\n        }\n      });\n    }\n\n    function isValidDate(value) {\n      // Invalid Date: getTime() returns NaN\n      return value && !(value.getTime && value.getTime() !== value.getTime());\n    }\n\n    function parseObservedDateValue(val) {\n      return isDefined(val) && !isDate(val) ? parseDateAndConvertTimeZoneToLocal(val) || undefined : val;\n    }\n\n    function parseDateAndConvertTimeZoneToLocal(value, previousDate) {\n      var timezone = ctrl.$options.getOption('timezone');\n\n      if (previousTimezone && previousTimezone !== timezone) {\n        // If the timezone has changed, adjust the previousDate to the default timezone\n        // so that the new date is converted with the correct timezone offset\n        previousDate = addDateMinutes(previousDate, timezoneToOffset(previousTimezone));\n      }\n\n      var parsedDate = parseDate(value, previousDate);\n\n      if (!isNaN(parsedDate) && timezone) {\n        parsedDate = convertTimezoneToLocal(parsedDate, timezone);\n      }\n      return parsedDate;\n    }\n\n    function formatter(value, timezone) {\n      var targetFormat = format;\n\n      if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) {\n        targetFormat = format\n          .replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat'))\n          .replace(/:$/, '');\n      }\n\n      var formatted =  $filter('date')(value, targetFormat, timezone);\n\n      if (isTimeType && ctrl.$options.getOption('timeStripZeroSeconds')) {\n        formatted = formatted.replace(/(?::00)?(?:\\.000)?$/, '');\n      }\n\n      return formatted;\n    }\n  };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl, parserName) {\n  var node = element[0];\n  var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n  if (nativeValidation) {\n    ctrl.$parsers.push(function(value) {\n      var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n      if (validity.badInput || validity.typeMismatch) {\n        ctrl.$$parserName = parserName;\n        return undefined;\n      }\n\n      return value;\n    });\n  }\n}\n\nfunction numberFormatterParser(ctrl) {\n  ctrl.$parsers.push(function(value) {\n    if (ctrl.$isEmpty(value))      return null;\n    if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n\n    ctrl.$$parserName = 'number';\n    return undefined;\n  });\n\n  ctrl.$formatters.push(function(value) {\n    if (!ctrl.$isEmpty(value)) {\n      if (!isNumber(value)) {\n        throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n      }\n      value = value.toString();\n    }\n    return value;\n  });\n}\n\nfunction parseNumberAttrVal(val) {\n  if (isDefined(val) && !isNumber(val)) {\n    val = parseFloat(val);\n  }\n  return !isNumberNaN(val) ? val : undefined;\n}\n\nfunction isNumberInteger(num) {\n  // See http://stackoverflow.com/questions/14636536/how-to-check-if-a-variable-is-an-integer-in-javascript#14794066\n  // (minus the assumption that `num` is a number)\n\n  // eslint-disable-next-line no-bitwise\n  return (num | 0) === num;\n}\n\nfunction countDecimals(num) {\n  var numString = num.toString();\n  var decimalSymbolIndex = numString.indexOf('.');\n\n  if (decimalSymbolIndex === -1) {\n    if (-1 < num && num < 1) {\n      // It may be in the exponential notation format (`1e-X`)\n      var match = /e-(\\d+)$/.exec(numString);\n\n      if (match) {\n        return Number(match[1]);\n      }\n    }\n\n    return 0;\n  }\n\n  return numString.length - decimalSymbolIndex - 1;\n}\n\nfunction isValidForStep(viewValue, stepBase, step) {\n  // At this point `stepBase` and `step` are expected to be non-NaN values\n  // and `viewValue` is expected to be a valid stringified number.\n  var value = Number(viewValue);\n\n  var isNonIntegerValue = !isNumberInteger(value);\n  var isNonIntegerStepBase = !isNumberInteger(stepBase);\n  var isNonIntegerStep = !isNumberInteger(step);\n\n  // Due to limitations in Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or\n  // `0.5 % 0.1 !== 0`), we need to convert all numbers to integers.\n  if (isNonIntegerValue || isNonIntegerStepBase || isNonIntegerStep) {\n    var valueDecimals = isNonIntegerValue ? countDecimals(value) : 0;\n    var stepBaseDecimals = isNonIntegerStepBase ? countDecimals(stepBase) : 0;\n    var stepDecimals = isNonIntegerStep ? countDecimals(step) : 0;\n\n    var decimalCount = Math.max(valueDecimals, stepBaseDecimals, stepDecimals);\n    var multiplier = Math.pow(10, decimalCount);\n\n    value = value * multiplier;\n    stepBase = stepBase * multiplier;\n    step = step * multiplier;\n\n    if (isNonIntegerValue) value = Math.round(value);\n    if (isNonIntegerStepBase) stepBase = Math.round(stepBase);\n    if (isNonIntegerStep) step = Math.round(step);\n  }\n\n  return (value - stepBase) % step === 0;\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  badInputChecker(scope, element, attr, ctrl, 'number');\n  numberFormatterParser(ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var parsedMinVal;\n\n  if (isDefined(attr.min) || attr.ngMin) {\n    var minVal = attr.min || $parse(attr.ngMin)(scope);\n    parsedMinVal = parseNumberAttrVal(minVal);\n\n    ctrl.$validators.min = function(modelValue, viewValue) {\n      return ctrl.$isEmpty(viewValue) || isUndefined(parsedMinVal) || viewValue >= parsedMinVal;\n    };\n\n    attr.$observe('min', function(val) {\n      if (val !== minVal) {\n        parsedMinVal = parseNumberAttrVal(val);\n        minVal = val;\n        // TODO(matsko): implement validateLater to reduce number of validations\n        ctrl.$validate();\n      }\n    });\n  }\n\n  if (isDefined(attr.max) || attr.ngMax) {\n    var maxVal = attr.max || $parse(attr.ngMax)(scope);\n    var parsedMaxVal = parseNumberAttrVal(maxVal);\n\n    ctrl.$validators.max = function(modelValue, viewValue) {\n      return ctrl.$isEmpty(viewValue) || isUndefined(parsedMaxVal) || viewValue <= parsedMaxVal;\n    };\n\n    attr.$observe('max', function(val) {\n      if (val !== maxVal) {\n        parsedMaxVal = parseNumberAttrVal(val);\n        maxVal = val;\n        // TODO(matsko): implement validateLater to reduce number of validations\n        ctrl.$validate();\n      }\n    });\n  }\n\n  if (isDefined(attr.step) || attr.ngStep) {\n    var stepVal = attr.step || $parse(attr.ngStep)(scope);\n    var parsedStepVal = parseNumberAttrVal(stepVal);\n\n    ctrl.$validators.step = function(modelValue, viewValue) {\n      return ctrl.$isEmpty(viewValue) || isUndefined(parsedStepVal) ||\n        isValidForStep(viewValue, parsedMinVal || 0, parsedStepVal);\n    };\n\n    attr.$observe('step', function(val) {\n      // TODO(matsko): implement validateLater to reduce number of validations\n      if (val !== stepVal) {\n        parsedStepVal = parseNumberAttrVal(val);\n        stepVal = val;\n        ctrl.$validate();\n      }\n\n    });\n\n  }\n}\n\nfunction rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  badInputChecker(scope, element, attr, ctrl, 'range');\n  numberFormatterParser(ctrl);\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var supportsRange = ctrl.$$hasNativeValidators && element[0].type === 'range',\n      minVal = supportsRange ? 0 : undefined,\n      maxVal = supportsRange ? 100 : undefined,\n      stepVal = supportsRange ? 1 : undefined,\n      validity = element[0].validity,\n      hasMinAttr = isDefined(attr.min),\n      hasMaxAttr = isDefined(attr.max),\n      hasStepAttr = isDefined(attr.step);\n\n  var originalRender = ctrl.$render;\n\n  ctrl.$render = supportsRange && isDefined(validity.rangeUnderflow) && isDefined(validity.rangeOverflow) ?\n    //Browsers that implement range will set these values automatically, but reading the adjusted values after\n    //$render would cause the min / max validators to be applied with the wrong value\n    function rangeRender() {\n      originalRender();\n      ctrl.$setViewValue(element.val());\n    } :\n    originalRender;\n\n  if (hasMinAttr) {\n    minVal = parseNumberAttrVal(attr.min);\n\n    ctrl.$validators.min = supportsRange ?\n      // Since all browsers set the input to a valid value, we don't need to check validity\n      function noopMinValidator() { return true; } :\n      // non-support browsers validate the min val\n      function minValidator(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || isUndefined(minVal) || viewValue >= minVal;\n      };\n\n    setInitialValueAndObserver('min', minChange);\n  }\n\n  if (hasMaxAttr) {\n    maxVal = parseNumberAttrVal(attr.max);\n\n    ctrl.$validators.max = supportsRange ?\n      // Since all browsers set the input to a valid value, we don't need to check validity\n      function noopMaxValidator() { return true; } :\n      // non-support browsers validate the max val\n      function maxValidator(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || isUndefined(maxVal) || viewValue <= maxVal;\n      };\n\n    setInitialValueAndObserver('max', maxChange);\n  }\n\n  if (hasStepAttr) {\n    stepVal = parseNumberAttrVal(attr.step);\n\n    ctrl.$validators.step = supportsRange ?\n      function nativeStepValidator() {\n        // Currently, only FF implements the spec on step change correctly (i.e. adjusting the\n        // input element value to a valid value). It's possible that other browsers set the stepMismatch\n        // validity error instead, so we can at least report an error in that case.\n        return !validity.stepMismatch;\n      } :\n      // ngStep doesn't set the setp attr, so the browser doesn't adjust the input value as setting step would\n      function stepValidator(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || isUndefined(stepVal) ||\n               isValidForStep(viewValue, minVal || 0, stepVal);\n      };\n\n    setInitialValueAndObserver('step', stepChange);\n  }\n\n  function setInitialValueAndObserver(htmlAttrName, changeFn) {\n    // interpolated attributes set the attribute value only after a digest, but we need the\n    // attribute value when the input is first rendered, so that the browser can adjust the\n    // input value based on the min/max value\n    element.attr(htmlAttrName, attr[htmlAttrName]);\n    var oldVal = attr[htmlAttrName];\n    attr.$observe(htmlAttrName, function wrappedObserver(val) {\n      if (val !== oldVal) {\n        oldVal = val;\n        changeFn(val);\n      }\n    });\n  }\n\n  function minChange(val) {\n    minVal = parseNumberAttrVal(val);\n    // ignore changes before model is initialized\n    if (isNumberNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    if (supportsRange) {\n      var elVal = element.val();\n      // IE11 doesn't set the el val correctly if the minVal is greater than the element value\n      if (minVal > elVal) {\n        elVal = minVal;\n        element.val(elVal);\n      }\n      ctrl.$setViewValue(elVal);\n    } else {\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    }\n  }\n\n  function maxChange(val) {\n    maxVal = parseNumberAttrVal(val);\n    // ignore changes before model is initialized\n    if (isNumberNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    if (supportsRange) {\n      var elVal = element.val();\n      // IE11 doesn't set the el val correctly if the maxVal is less than the element value\n      if (maxVal < elVal) {\n        element.val(maxVal);\n        // IE11 and Chrome don't set the value to the minVal when max < min\n        elVal = maxVal < minVal ? minVal : maxVal;\n      }\n      ctrl.$setViewValue(elVal);\n    } else {\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    }\n  }\n\n  function stepChange(val) {\n    stepVal = parseNumberAttrVal(val);\n    // ignore changes before model is initialized\n    if (isNumberNaN(ctrl.$modelValue)) {\n      return;\n    }\n\n    // Some browsers don't adjust the input value correctly, but set the stepMismatch error\n    if (!supportsRange) {\n      // TODO(matsko): implement validateLater to reduce number of validations\n      ctrl.$validate();\n    } else if (ctrl.$viewValue !== element.val()) {\n      ctrl.$setViewValue(element.val());\n    }\n  }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$validators.url = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n  };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  // Note: no badInputChecker here by purpose as `url` is only a validation\n  // in browsers, i.e. we can always read out input.value even if it is not valid!\n  baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n  stringBasedInputType(ctrl);\n\n  ctrl.$validators.email = function(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n    return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n  };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  var doTrim = !attr.ngTrim || trim(attr.ngTrim) !== 'false';\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  var listener = function(ev) {\n    var value;\n    if (element[0].checked) {\n      value = attr.value;\n      if (doTrim) {\n        value = trim(value);\n      }\n      ctrl.$setViewValue(value, ev && ev.type);\n    }\n  };\n\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    if (doTrim) {\n      value = trim(value);\n    }\n    element[0].checked = (value === ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n  var parseFn;\n  if (isDefined(expression)) {\n    parseFn = $parse(expression);\n    if (!parseFn.constant) {\n      throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n                                   '`{1}`.', name, expression);\n    }\n    return parseFn(context);\n  }\n  return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n  var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n  var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n  var listener = function(ev) {\n    ctrl.$setViewValue(element[0].checked, ev && ev.type);\n  };\n\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n  // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n  // it to a boolean.\n  ctrl.$isEmpty = function(value) {\n    return value === false;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return equals(value, trueValue);\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with AngularJS data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n *    does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n *    If the expression evaluates to a RegExp object, then this is used directly.\n *    If the expression evaluates to a string, then it will be converted to a RegExp\n *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n *    `new RegExp('^abc$')`.<br />\n *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n *    start at the index of the last search's match, thus not taking the whole input value into\n *    account.\n * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input.\n *\n * @knownIssue\n *\n * When specifying the `placeholder` attribute of `<textarea>`, Internet Explorer will temporarily\n * insert the placeholder value as the textarea's content. If the placeholder value contains\n * interpolation (`{{ ... }}`), an error will be logged in the console when AngularJS tries to update\n * the value of the by-then-removed text node. This doesn't affect the functionality of the\n * textarea, but can be undesirable.\n *\n * You can work around this Internet Explorer issue by using `ng-attr-placeholder` instead of\n * `placeholder` on textareas, whenever you need interpolation in the placeholder value. You can\n * find more details on `ngAttr` in the\n * [Interpolation](guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes) section of the\n * Developer Guide.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n * </div>\n *\n * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n *    length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n *    value does not match a RegExp found by evaluating the AngularJS expression given in the attribute value.\n *    If the expression evaluates to a RegExp object, then this is used directly.\n *    If the expression evaluates to a string, then it will be converted to a RegExp\n *    after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n *    `new RegExp('^abc$')`.<br />\n *    **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n *    start at the index of the last search's match, thus not taking the whole input value into\n *    account.\n * @param {string=} ngChange AngularJS expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           <label>\n              User name:\n              <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           </label>\n           <div role=\"alert\">\n             <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n              Required!</span>\n           </div>\n           <label>\n              Last name:\n              <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n              ng-minlength=\"3\" ng-maxlength=\"10\">\n           </label>\n           <div role=\"alert\">\n             <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n               Too short!</span>\n             <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n               Too long!</span>\n           </div>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.exactBinding('user'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n    function($browser, $sniffer, $filter, $parse) {\n  return {\n    restrict: 'E',\n    require: ['?ngModel'],\n    link: {\n      pre: function(scope, element, attr, ctrls) {\n        if (ctrls[0]) {\n          (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n                                                              $browser, $filter, $parse);\n        }\n      }\n    }\n  };\n}];\n\n\nvar hiddenInputBrowserCacheDirective = function() {\n  var valueProperty = {\n    configurable: true,\n    enumerable: false,\n    get: function() {\n      return this.getAttribute('value') || '';\n    },\n    set: function(val) {\n      this.setAttribute('value', val);\n    }\n  };\n\n  return {\n    restrict: 'E',\n    priority: 200,\n    compile: function(_, attr) {\n      if (lowercase(attr.type) !== 'hidden') {\n        return;\n      }\n\n      return {\n        pre: function(scope, element, attr, ctrls) {\n          var node = element[0];\n\n          // Support: Edge\n          // Moving the DOM around prevents autofillling\n          if (node.parentNode) {\n            node.parentNode.insertBefore(node, node.nextSibling);\n          }\n\n          // Support: FF, IE\n          // Avoiding direct assignment to .value prevents autofillling\n          if (Object.defineProperty) {\n            Object.defineProperty(node, 'value', valueProperty);\n          }\n        }\n      };\n    }\n  };\n};\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n * @restrict A\n * @priority 100\n *\n * @description\n * Binds the given expression to the value of the element.\n *\n * It is mainly used on {@link input[radio] `input[radio]`} and option elements,\n * so that when the element is selected, the {@link ngModel `ngModel`} of that element (or its\n * {@link select `select`} parent element) is set to the bound value. It is especially useful\n * for dynamically generated lists using {@link ngRepeat `ngRepeat`}, as shown below.\n *\n * It can also be used to achieve one-way binding of a given expression to an input element\n * such as an `input[text]` or a `textarea`, when that element does not use ngModel.\n *\n * @element ANY\n * @param {string=} ngValue AngularJS expression, whose value will be bound to the `value` attribute\n * and `value` property of the element.\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  /**\n   *  inputs use the value attribute as their default value if the value property is not set.\n   *  Once the value property has been set (by adding input), it will not react to changes to\n   *  the value attribute anymore. Setting both attribute and property fixes this behavior, and\n   *  makes it possible to use ngValue as a sort of one-way bind.\n   */\n  function updateElementValue(element, attr, value) {\n    // Support: IE9 only\n    // In IE9 values are converted to string (e.g. `input.value = null` results in `input.value === 'null'`).\n    var propValue = isDefined(value) ? value : (msie === 9) ? '' : null;\n    element.prop('value', propValue);\n    attr.$set('value', value);\n  }\n\n  return {\n    restrict: 'A',\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          var value = scope.$eval(attr.ngValue);\n          updateElementValue(elm, attr, value);\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            updateElementValue(elm, attr, value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells AngularJS to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before AngularJS compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\" name=\"ng-bind\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <label>Enter name: <input type=\"text\" ng-model=\"name\"></label><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'AC',\n    compile: function ngBindCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBind);\n        element = element[0];\n        scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n          element.textContent = stringify(value);\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\" name=\"ng-bind-template\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        <label>Salutation: <input type=\"text\" ng-model=\"salutation\"></label><br>\n        <label>Name: <input type=\"text\" ng-model=\"name\"></label><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {\n  return {\n    compile: function ngBindTemplateCompile(templateElement) {\n      $compile.$$addBindingClass(templateElement);\n      return function ngBindTemplateLink(scope, element, attr) {\n        var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n        $compile.$$addBindingInfo(element, interpolateFn.expressions);\n        element = element[0];\n        attr.$observe('ngBindTemplate', function(value) {\n          element.textContent = isUndefined(value) ? '' : value;\n        });\n      };\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,\n * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.\n * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link\n * ngSanitize} in your module's dependencies (not in core AngularJS). In order to use {@link ngSanitize}\n * in your module's dependencies, you need to include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\" name=\"ng-bind-html\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {\n  return {\n    restrict: 'A',\n    compile: function ngBindHtmlCompile(tElement, tAttrs) {\n      var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);\n      var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function sceValueOf(val) {\n        // Unwrap the value to compare the actual inner safe value, not the wrapper object.\n        return $sce.valueOf(val);\n      });\n      $compile.$$addBindingClass(tElement);\n\n      return function ngBindHtmlLink(scope, element, attr) {\n        $compile.$$addBindingInfo(element, attr.ngBindHtml);\n\n        scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {\n          // The watched value is the unwrapped value. To avoid re-escaping, use the direct getter.\n          var value = ngBindHtmlGetter(scope);\n          element.html($sce.getTrustedHtml(value) || '');\n        });\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngChange\n * @restrict A\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n *\n * The `ngChange` expression is only evaluated when a change in the input value causes\n * a new value to be committed to the model.\n *\n * It will not be evaluated:\n * * if the value returned from the `$parsers` transformation pipeline has not changed\n * * if the input has continued to be invalid since the model will stay `null`\n * * if the model is changed programmatically and not by a change to the input value\n *\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element ANY\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  restrict: 'A',\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n/* exported\n  ngClassDirective,\n  ngClassEvenDirective,\n  ngClassOddDirective\n*/\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  var indexWatchExpression;\n\n  return ['$parse', function($parse) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var classCounts = element.data('$classCounts');\n        var oldModulo = true;\n        var oldClassString;\n\n        if (!classCounts) {\n          // Use createMap() to prevent class assumptions involving property\n          // names in Object.prototype\n          classCounts = createMap();\n          element.data('$classCounts', classCounts);\n        }\n\n        if (name !== 'ngClass') {\n          if (!indexWatchExpression) {\n            indexWatchExpression = $parse('$index', function moduloTwo($index) {\n              // eslint-disable-next-line no-bitwise\n              return $index & 1;\n            });\n          }\n\n          scope.$watch(indexWatchExpression, ngClassIndexWatchAction);\n        }\n\n        scope.$watch($parse(attr[name], toClassString), ngClassWatchAction);\n\n        function addClasses(classString) {\n          classString = digestClassCounts(split(classString), 1);\n          attr.$addClass(classString);\n        }\n\n        function removeClasses(classString) {\n          classString = digestClassCounts(split(classString), -1);\n          attr.$removeClass(classString);\n        }\n\n        function updateClasses(oldClassString, newClassString) {\n          var oldClassArray = split(oldClassString);\n          var newClassArray = split(newClassString);\n\n          var toRemoveArray = arrayDifference(oldClassArray, newClassArray);\n          var toAddArray = arrayDifference(newClassArray, oldClassArray);\n\n          var toRemoveString = digestClassCounts(toRemoveArray, -1);\n          var toAddString = digestClassCounts(toAddArray, 1);\n\n          attr.$addClass(toAddString);\n          attr.$removeClass(toRemoveString);\n        }\n\n        function digestClassCounts(classArray, count) {\n          var classesToUpdate = [];\n\n          forEach(classArray, function(className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n\n          return classesToUpdate.join(' ');\n        }\n\n        function ngClassIndexWatchAction(newModulo) {\n          // This watch-action should run before the `ngClassWatchAction()`, thus it\n          // adds/removes `oldClassString`. If the `ngClass` expression has changed as well, the\n          // `ngClassWatchAction()` will update the classes.\n          if (newModulo === selector) {\n            addClasses(oldClassString);\n          } else {\n            removeClasses(oldClassString);\n          }\n\n          oldModulo = newModulo;\n        }\n\n        function ngClassWatchAction(newClassString) {\n          if (oldModulo === selector) {\n            updateClasses(oldClassString, newClassString);\n          }\n\n          oldClassString = newClassString;\n        }\n      }\n    };\n  }];\n\n  // Helpers\n  function arrayDifference(tokens1, tokens2) {\n    if (!tokens1 || !tokens1.length) return [];\n    if (!tokens2 || !tokens2.length) return tokens1;\n\n    var values = [];\n\n    outer:\n    for (var i = 0; i < tokens1.length; i++) {\n      var token = tokens1[i];\n      for (var j = 0; j < tokens2.length; j++) {\n        if (token === tokens2[j]) continue outer;\n      }\n      values.push(token);\n    }\n\n    return values;\n  }\n\n  function split(classString) {\n    return classString && classString.split(' ');\n  }\n\n  function toClassString(classValue) {\n    if (!classValue) return classValue;\n\n    var classString = classValue;\n\n    if (isArray(classValue)) {\n      classString = classValue.map(toClassString).join(' ');\n    } else if (isObject(classValue)) {\n      classString = Object.keys(classValue).\n        filter(function(key) { return classValue[key]; }).\n        join(' ');\n    } else if (!isString(classValue)) {\n      classString = classValue + '';\n    }\n\n    return classString;\n  }\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n * @element ANY\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * 3. If the expression evaluates to an array, each element of the array should either be a string as in\n * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array\n * to give you more control over what CSS classes appear. See the code below for an example of this.\n *\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then are the\n * new classes added.\n *\n * @knownIssue\n * You should not use {@link guide/interpolation interpolation} in the value of the `class`\n * attribute, when using the `ngClass` directive on the same element.\n * See {@link guide/interpolation#known-issues here} for more info.\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#addClass addClass}       | just before the class is applied to the element   |\n * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |\n * | {@link ng.$animate#setClass setClass} | just before classes are added and classes are removed from the element at the same time |\n *\n * ### ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link $animate#addClass $animate.addClass} and\n   {@link $animate#removeClass $animate.removeClass}.\n *\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example\n * ### Basic\n   <example name=\"ng-class\">\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, 'has-error': error}\">Map Syntax Example</p>\n       <label>\n          <input type=\"checkbox\" ng-model=\"deleted\">\n          deleted (apply \"strike\" class)\n       </label><br>\n       <label>\n          <input type=\"checkbox\" ng-model=\"important\">\n          important (apply \"bold\" class)\n       </label><br>\n       <label>\n          <input type=\"checkbox\" ng-model=\"error\">\n          error (apply \"has-error\" class)\n       </label>\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\"\n              placeholder=\"Type: bold strike red\" aria-label=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\"\n              placeholder=\"Type: bold, strike or red\" aria-label=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\"\n              placeholder=\"Type: bold, strike or red\" aria-label=\"Type: bold, strike or red 2\"><br>\n       <input ng-model=\"style3\"\n              placeholder=\"Type: bold, strike or red\" aria-label=\"Type: bold, strike or red 3\"><br>\n       <hr>\n       <p ng-class=\"[style4, {orange: warning}]\">Using Array and Map Syntax</p>\n       <input ng-model=\"style4\" placeholder=\"Type: bold, strike\" aria-label=\"Type: bold, strike\"><br>\n       <label><input type=\"checkbox\" ng-model=\"warning\"> warning (apply \"orange\" class)</label>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n           text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n       .has-error {\n           color: red;\n           background-color: yellow;\n       }\n       .orange {\n           color: orange;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/has-error/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.get(2).getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.get(2).getAttribute('class')).toBe('bold strike red');\n       });\n\n       it('array with map example should have 2 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style4')).sendKeys('bold');\n         element(by.model('warning')).click();\n         expect(ps.last().getAttribute('class')).toBe('bold orange');\n       });\n     </file>\n   </example>\n\n   @example\n   ### Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-class\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#addClass addClass}       | just before the class is applied to the element   |\n * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example name=\"ng-class-odd\">\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n *\n * <hr />\n * @example\n * An example on how to implement animations using `ngClassOdd`:\n *\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-class-odd-animate\">\n     <file name=\"index.html\">\n       <div ng-init=\"items=['Item 3', 'Item 2', 'Item 1', 'Item 0']\">\n         <button ng-click=\"items.unshift('Item ' + items.length)\">Add item</button>\n         <hr />\n         <table>\n           <tr ng-repeat=\"item in items\" ng-class-odd=\"'odd'\">\n             <td>{{ item }}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         background: rgba(255, 255, 0, 0.25);\n       }\n\n       .odd-add, .odd-remove {\n         transition: 1.5s;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should add new entries to the beginning of the list', function() {\n         var button = element(by.buttonText('Add item'));\n         var rows = element.all(by.repeater('item in items'));\n\n         expect(rows.count()).toBe(4);\n         expect(rows.get(0).getText()).toBe('Item 3');\n         expect(rows.get(1).getText()).toBe('Item 2');\n\n         button.click();\n\n         expect(rows.count()).toBe(5);\n         expect(rows.get(0).getText()).toBe('Item 4');\n         expect(rows.get(1).getText()).toBe('Item 3');\n       });\n\n       it('should add odd class to odd entries', function() {\n         var button = element(by.buttonText('Add item'));\n         var rows = element.all(by.repeater('item in items'));\n\n         expect(rows.get(0).getAttribute('class')).toMatch(/odd/);\n         expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/);\n\n         button.click();\n\n         expect(rows.get(0).getAttribute('class')).toMatch(/odd/);\n         expect(rows.get(1).getAttribute('class')).not.toMatch(/odd/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#addClass addClass}       | just before the class is applied to the element   |\n * | {@link ng.$animate#removeClass removeClass} | just before the class is removed from the element |\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example name=\"ng-class-even\">\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n *\n * <hr />\n * @example\n * An example on how to implement animations using `ngClassEven`:\n *\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-class-even-animate\">\n     <file name=\"index.html\">\n       <div ng-init=\"items=['Item 3', 'Item 2', 'Item 1', 'Item 0']\">\n         <button ng-click=\"items.unshift('Item ' + items.length)\">Add item</button>\n         <hr />\n         <table>\n           <tr ng-repeat=\"item in items\" ng-class-even=\"'even'\">\n             <td>{{ item }}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n     <file name=\"style.css\">\n       .even {\n         background: rgba(255, 255, 0, 0.25);\n       }\n\n       .even-add, .even-remove {\n         transition: 1.5s;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should add new entries to the beginning of the list', function() {\n         var button = element(by.buttonText('Add item'));\n         var rows = element.all(by.repeater('item in items'));\n\n         expect(rows.count()).toBe(4);\n         expect(rows.get(0).getText()).toBe('Item 3');\n         expect(rows.get(1).getText()).toBe('Item 2');\n\n         button.click();\n\n         expect(rows.count()).toBe(5);\n         expect(rows.get(0).getText()).toBe('Item 4');\n         expect(rows.get(1).getText()).toBe('Item 3');\n       });\n\n       it('should add even class to even entries', function() {\n         var button = element(by.buttonText('Add item'));\n         var rows = element.all(by.repeater('item in items'));\n\n         expect(rows.get(0).getAttribute('class')).not.toMatch(/even/);\n         expect(rows.get(1).getAttribute('class')).toMatch(/even/);\n\n         button.click();\n\n         expect(rows.get(0).getAttribute('class')).not.toMatch(/even/);\n         expect(rows.get(1).getAttribute('class')).toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the AngularJS html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When AngularJS encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * @element ANY\n *\n * @example\n   <example name=\"ng-cloak\">\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" class=\"ng-cloak\">{{ 'world' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a constructor function registered with the current\n * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}\n * that on the current scope evaluates to a constructor function.\n *\n * The controller instance can be published into a scope property by specifying\n * `ng-controller=\"as propertyName\"`.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the AngularJS markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the AngularJS community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      <label>Name: <input type=\"text\" ng-model=\"settings.name\"/></label>\n *      <button ng-click=\"settings.greet()\">greet</button><br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\" aria-label=\"Contact method\" id=\"select_{{$index}}\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\" aria-labelledby=\"select_{{$index}}\" />\n *          <button ng-click=\"settings.clearContact(contact)\">clear</button>\n *          <button ng-click=\"settings.removeContact(contact)\" aria-label=\"Remove\">X</button>\n *        </li>\n *        <li><button ng-click=\"settings.addContact()\">add</button></li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = 'John Smith';\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'}\n *      ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.buttonText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.buttonText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     <label>Name: <input type=\"text\" ng-model=\"name\"/></label>\n *     <button ng-click=\"greet()\">greet</button><br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\" id=\"select_{{$index}}\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\" aria-labelledby=\"select_{{$index}}\" />\n *         <button ng-click=\"clearContact(contact)\">clear</button>\n *         <button ng-click=\"removeContact(contact)\">X</button>\n *       </li>\n *       <li>[ <button ng-click=\"addContact()\">add</button> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = 'John Smith';\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'}\n *     ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.buttonText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.buttonText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    restrict: 'A',\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @restrict A\n * @element ANY\n * @description\n *\n * AngularJS has some features that can conflict with certain restrictions that are applied when using\n * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules.\n *\n * If you intend to implement CSP with these rules then you must tell AngularJS not to use these\n * features.\n *\n * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.\n *\n *\n * The following default rules in CSP affect AngularJS:\n *\n * * The use of `eval()`, `Function(string)` and similar functions to dynamically create and execute\n * code from strings is forbidden. AngularJS makes use of this in the {@link $parse} service to\n * provide a 30% increase in the speed of evaluating AngularJS expressions. (This CSP rule can be\n * disabled with the CSP keyword `unsafe-eval`, but it is generally not recommended as it would\n * weaken the protections offered by CSP.)\n *\n * * The use of inline resources, such as inline `<script>` and `<style>` elements, are forbidden.\n * This prevents apps from injecting custom styles directly into the document. AngularJS makes use of\n * this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}). To make these\n * directives work when a CSP rule is blocking inline styles, you must link to the `angular-csp.css`\n * in your HTML manually. (This CSP rule can be disabled with the CSP keyword `unsafe-inline`, but\n * it is generally not recommended as it would weaken the protections offered by CSP.)\n *\n * If you do not provide `ngCsp` then AngularJS tries to autodetect if CSP is blocking dynamic code\n * creation from strings (e.g., `unsafe-eval` not specified in CSP header) and automatically\n * deactivates this feature in the {@link $parse} service. This autodetection, however, triggers a\n * CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on an element of the HTML document that appears before the `<script>` tag that loads\n * the `angular.js` file.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * You can specify which of the CSP related AngularJS features should be deactivated by providing\n * a value for the `ng-csp` attribute. The options are as follows:\n *\n * * no-inline-style: this stops AngularJS from injecting CSS styles into the DOM\n *\n * * no-unsafe-eval: this stops AngularJS from optimizing $parse with unsafe eval of strings\n *\n * You can use these values in the following combinations:\n *\n *\n * * No declaration means that AngularJS will assume that you can do inline styles, but it will do\n * a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous\n * versions of AngularJS.\n *\n * * A simple `ng-csp` (or `data-ng-csp`) attribute will tell AngularJS to deactivate both inline\n * styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous\n * versions of AngularJS.\n *\n * * Specifying only `no-unsafe-eval` tells AngularJS that we must not use eval, but that we can\n * inject inline styles. E.g. `<body ng-csp=\"no-unsafe-eval\">`.\n *\n * * Specifying only `no-inline-style` tells AngularJS that we must not inject styles, but that we can\n * run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp=\"no-inline-style\">`\n *\n * * Specifying both `no-unsafe-eval` and `no-inline-style` tells AngularJS that we must not inject\n * styles nor use eval, which is the same as an empty: ng-csp.\n * E.g.`<body ng-csp=\"no-inline-style;no-unsafe-eval\">`\n *\n * @example\n *\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n\n  <!-- Note: the `.csp` suffix in the example name triggers CSP mode in our http server! -->\n  <example name=\"example.csp\" module=\"cspExample\" ng-csp=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"MainController as ctrl\">\n        <div>\n          <button ng-click=\"ctrl.inc()\" id=\"inc\">Increment</button>\n          <span id=\"counter\">\n            {{ctrl.counter}}\n          </span>\n        </div>\n\n        <div>\n          <button ng-click=\"ctrl.evil()\" id=\"evil\">Evil</button>\n          <span id=\"evilError\">\n            {{ctrl.evilError}}\n          </span>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n       angular.module('cspExample', [])\n         .controller('MainController', function MainController() {\n            this.counter = 0;\n            this.inc = function() {\n              this.counter++;\n            };\n            this.evil = function() {\n              try {\n                eval('1+2'); // eslint-disable-line no-eval\n              } catch (e) {\n                this.evilError = e.message;\n              }\n            };\n          });\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var util, webdriver;\n\n      var incBtn = element(by.id('inc'));\n      var counter = element(by.id('counter'));\n      var evilBtn = element(by.id('evil'));\n      var evilError = element(by.id('evilError'));\n\n      function getAndClearSevereErrors() {\n        return browser.manage().logs().get('browser').then(function(browserLog) {\n          return browserLog.filter(function(logEntry) {\n            return logEntry.level.value > webdriver.logging.Level.WARNING.value;\n          });\n        });\n      }\n\n      function clearErrors() {\n        getAndClearSevereErrors();\n      }\n\n      function expectNoErrors() {\n        getAndClearSevereErrors().then(function(filteredLog) {\n          expect(filteredLog.length).toEqual(0);\n          if (filteredLog.length) {\n            console.log('browser console errors: ' + util.inspect(filteredLog));\n          }\n        });\n      }\n\n      function expectError(regex) {\n        getAndClearSevereErrors().then(function(filteredLog) {\n          var found = false;\n          filteredLog.forEach(function(log) {\n            if (log.message.match(regex)) {\n              found = true;\n            }\n          });\n          if (!found) {\n            throw new Error('expected an error that matches ' + regex);\n          }\n        });\n      }\n\n      beforeEach(function() {\n        util = require('util');\n        webdriver = require('selenium-webdriver');\n      });\n\n      // For now, we only test on Chrome,\n      // as Safari does not load the page with Protractor's injected scripts,\n      // and Firefox webdriver always disables content security policy (#6358)\n      if (browser.params.browser !== 'chrome') {\n        return;\n      }\n\n      it('should not report errors when the page is loaded', function() {\n        // clear errors so we are not dependent on previous tests\n        clearErrors();\n        // Need to reload the page as the page is already loaded when\n        // we come here\n        browser.driver.getCurrentUrl().then(function(url) {\n          browser.get(url);\n        });\n        expectNoErrors();\n      });\n\n      it('should evaluate expressions', function() {\n        expect(counter.getText()).toEqual('0');\n        incBtn.click();\n        expect(counter.getText()).toEqual('1');\n        expectNoErrors();\n      });\n\n      it('should throw and report an error when using \"eval\"', function() {\n        evilBtn.click();\n        expect(evilError.getText()).toMatch(/Content Security Policy/);\n        expectError(/Content Security Policy/);\n      });\n    </file>\n  </example>\n  */\n\n// `ngCsp` is not implemented as a proper directive any more, because we need it be processed while\n// we bootstrap the app (before `$parse` is instantiated). For this reason, we just have the `csp()`\n// fn that looks for the `ng-csp` attribute anywhere in the current doc.\n\n/**\n * @ngdoc directive\n * @name ngClick\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-click\">\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      </span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * AngularJS expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', '$exceptionHandler', function($parse, $rootScope, $exceptionHandler) {\n      return createEventDirective($parse, $rootScope, $exceptionHandler, directiveName, eventName, forceAsyncEvents[eventName]);\n    }];\n  }\n);\n\nfunction createEventDirective($parse, $rootScope, $exceptionHandler, directiveName, eventName, forceAsync) {\n  return {\n    restrict: 'A',\n    compile: function($element, attr) {\n      // NOTE:\n      // We expose the powerful `$event` object on the scope that provides access to the Window,\n      // etc. This is OK, because expressions are not sandboxed any more (and the expression\n      // sandbox was never meant to be a security feature anyway).\n      var fn = $parse(attr[directiveName]);\n      return function ngEventHandler(scope, element) {\n        element.on(eventName, function(event) {\n          var callback = function() {\n            fn(scope, {$event: event});\n          };\n\n          if (!$rootScope.$$phase) {\n            scope.$apply(callback);\n          } else if (forceAsync) {\n            scope.$evalAsync(callback);\n          } else {\n            try {\n              callback();\n            } catch (error) {\n              $exceptionHandler(error);\n            }\n          }\n        });\n      };\n    }\n  };\n}\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example name=\"ng-dblclick\">\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mousedown\">\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mouseup\">\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mouseover\">\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mouseenter\">\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mouseleave\">\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-mousemove\">\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example name=\"ng-keydown\">\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n * @restrict A\n * @element ANY\n * @priority 0\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example name=\"ng-keyup\">\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n * @restrict A\n * @element ANY\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example name=\"ng-keypress\">\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n * @restrict A\n * @element form\n * @priority 0\n *\n * @description\n * Enables binding AngularJS expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\" name=\"ng-submit\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n * @restrict A\n * @element window, input, select, textarea, a\n * @priority 0\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n * @restrict A\n * @element window, input, select, textarea, a\n * @priority 0\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n * @restrict A\n * @element window, input, select, textarea, a\n * @priority 0\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-copy\">\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n * @restrict A\n * @element window, input, select, textarea, a\n * @priority 0\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-cut\">\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n * @restrict A\n * @element window, input, select, textarea, a\n * @priority 0\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example name=\"ng-paste\">\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n * @multiElement\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * | Animation                        | Occurs                               |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#enter enter}  | just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container |\n * | {@link ng.$animate#leave leave}  | just before the `ngIf` contents are removed from the DOM |\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-if\">\n    <file name=\"index.html\">\n      <label>Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /></label><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        This is removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', '$compile', function($animate, $compile) {\n  return {\n    multiElement: true,\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (value) {\n            if (!childScope) {\n              $transclude(function(clone, newScope) {\n                childScope = newScope;\n                clone[clone.length++] = $compile.$$createComment('end ngIf', $attr.ngIf);\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if (previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if (childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if (block) {\n              previousElements = getBlockNodes(block.clone);\n              $animate.leave(previousElements).done(function(response) {\n                if (response !== false) previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n * @scope\n * @priority -400\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link $sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either add them to your {@link ng.$sceDelegateProvider#trustedResourceUrlList trusted\n * resource URL list} or {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to\n * AngularJS's {@link ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#enter enter}  | when the expression changes, on the new include |\n * | {@link ng.$animate#leave leave}  | when the expression changes, on the old include |\n *\n * The enter and leave animation occur concurrently.\n *\n * @param {string} ngInclude|src AngularJS expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *                  <div class=\"alert alert-warning\">\n *                  **Note:** When using onload on SVG elements in IE11, the browser will try to call\n *                  a function with the name on the window element, which will usually throw a\n *                  \"function is undefined\" error. To fix this, you can instead use `data-onload` or a\n *                  different form that {@link guide/directive#normalization matches} `onload`.\n *                  </div>\n   *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-include\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <code>{{template.url}}</code>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [{ name: 'template1.html', url: 'template1.html'},\n             { name: 'template2.html', url: 'template2.html'}];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser === 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser === 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentError\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {String} src URL of content to load.\n */\nvar ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',\n                  function($templateRequest,   $anchorScroll,   $animate) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if (previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            $animate.leave(currentElement).done(function(response) {\n              if (response !== false) previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch(srcExp, function ngIncludeWatchAction(src) {\n          var afterAnimation = function(response) {\n            if (response !== false && isDefined(autoScrollExp) &&\n              (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            //set the 2nd param to true to ignore the template request error so that the inner\n            //contents and scope can be cleaned up.\n            $templateRequest(src, true).then(function(response) {\n              if (scope.$$destroyed) return;\n\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include on an element with additional content does not make sense...\n              // Note: We can't remove them in the cloneAttchFn of $transclude as that\n              // function is called before linking the content, which would apply child\n              // directives to non existing elements.\n              var clone = $transclude(newScope, function(clone) {\n                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element).done(afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded', src);\n              scope.$eval(onloadExp);\n            }, function() {\n              if (scope.$$destroyed) return;\n\n              if (thisChangeId === changeCounter) {\n                cleanupLastIncludeContent();\n                scope.$emit('$includeContentError', src);\n              }\n            });\n            scope.$emit('$includeContentRequested', src);\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        if (toString.call($element[0]).match(/SVG/)) {\n          // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not\n          // support innerHTML, so detect this here and try to generate the contents\n          // specially.\n          $element.empty();\n          $compile(jqLiteBuildFragment(ctrl.template, window.document).childNodes)(scope,\n              function namespaceAdaptedClone(clone) {\n            $element.append(clone);\n          }, {futureParentElement: $element});\n          return;\n        }\n\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n * @priority 450\n * @element ANY\n *\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-danger\">\n * This directive can be abused to add unnecessary amounts of logic into your templates.\n * There are only a few appropriate uses of `ngInit`:\n * <ul>\n *   <li>aliasing special properties of {@link ng.directive:ngRepeat `ngRepeat`},\n *     as seen in the demo below.</li>\n *   <li>initializing data during development, or for examples, as seen throughout these docs.</li>\n *   <li>injecting data via server side scripting.</li>\n * </ul>\n *\n * Besides these few cases, you should use {@link guide/component Components} or\n * {@link guide/controller Controllers} rather than `ngInit` to initialize values on a scope.\n * </div>\n *\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with a {@link ng.$filter `filter`}, make\n * sure you have parentheses to ensure correct operator precedence:\n * <pre class=\"prettyprint\">\n * `<div ng-init=\"test1 = ($index | toString)\"></div>`\n * </pre>\n * </div>\n *\n * @example\n   <example module=\"initExample\" name=\"ng-init\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngList\n * @restrict A\n * @priority 100\n *\n * @param {string=} ngList optional delimiter that should be used to split the value.\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The default\n * delimiter is a comma followed by a space - equivalent to `ng-list=\", \"`. You can specify a custom\n * delimiter as the value of the `ngList` attribute - for example, `ng-list=\" | \"`.\n *\n * The behaviour of the directive is affected by the use of the `ngTrim` attribute.\n * * If `ngTrim` is set to `\"false\"` then whitespace around both the separator and each\n *   list item is respected. This implies that the user of the directive is responsible for\n *   dealing with whitespace but also allows you to use whitespace as a delimiter, such as a\n *   tab or newline character.\n * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected\n *   when joining the list items back together) and whitespace around each list item is stripped\n *   before it is added to the model.\n *\n * @example\n * ### Validation\n *\n * <example name=\"ngList-directive\" module=\"listExample\">\n *   <file name=\"app.js\">\n *      angular.module('listExample', [])\n *        .controller('ExampleController', ['$scope', function($scope) {\n *          $scope.names = ['morpheus', 'neo', 'trinity'];\n *        }]);\n *   </file>\n *   <file name=\"index.html\">\n *    <form name=\"myForm\" ng-controller=\"ExampleController\">\n *      <label>List: <input name=\"namesInput\" ng-model=\"names\" ng-list required></label>\n *      <span role=\"alert\">\n *        <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n *        Required!</span>\n *      </span>\n *      <br>\n *      <tt>names = {{names}}</tt><br/>\n *      <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n *      <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n *      <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n *      <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n *     </form>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var listInput = element(by.model('names'));\n *     var names = element(by.exactBinding('names'));\n *     var valid = element(by.binding('myForm.namesInput.$valid'));\n *     var error = element(by.css('span.error'));\n *\n *     it('should initialize to model', function() {\n *       expect(names.getText()).toContain('[\"morpheus\",\"neo\",\"trinity\"]');\n *       expect(valid.getText()).toContain('true');\n *       expect(error.getCssValue('display')).toBe('none');\n *     });\n *\n *     it('should be invalid if empty', function() {\n *       listInput.clear();\n *       listInput.sendKeys('');\n *\n *       expect(names.getText()).toContain('');\n *       expect(valid.getText()).toContain('false');\n *       expect(error.getCssValue('display')).not.toBe('none');\n *     });\n *   </file>\n * </example>\n *\n * @example\n * ### Splitting on newline\n *\n * <example name=\"ngList-directive-newlines\">\n *   <file name=\"index.html\">\n *    <textarea ng-model=\"list\" ng-list=\"&#10;\" ng-trim=\"false\"></textarea>\n *    <pre>{{ list | json }}</pre>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it(\"should split the text by newlines\", function() {\n *       var listInput = element(by.model('list'));\n *       var output = element(by.binding('list | json'));\n *       listInput.sendKeys('abc\\ndef\\nghi');\n *       expect(output.getText()).toContain('[\\n  \"abc\",\\n  \"def\",\\n  \"ghi\"\\n]');\n *     });\n *   </file>\n * </example>\n *\n */\nvar ngListDirective = function() {\n  return {\n    restrict: 'A',\n    priority: 100,\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var ngList = attr.ngList || ', ';\n      var trimValues = attr.ngTrim !== 'false';\n      var separator = trimValues ? trim(ngList) : ngList;\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trimValues ? trim(value) : value);\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(ngList);\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n/* global VALID_CLASS: true,\n  INVALID_CLASS: true,\n  PRISTINE_CLASS: true,\n  DIRTY_CLASS: true,\n  UNTOUCHED_CLASS: true,\n  TOUCHED_CLASS: true,\n  PENDING_CLASS: true,\n  addSetValidityMethod: true,\n  setupValidity: true,\n  defaultModelOptions: false\n*/\n\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty',\n    UNTOUCHED_CLASS = 'ng-untouched',\n    TOUCHED_CLASS = 'ng-touched',\n    EMPTY_CLASS = 'ng-empty',\n    NOT_EMPTY_CLASS = 'ng-not-empty';\n\nvar ngModelMinErr = minErr('ngModel');\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a\n * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue\n * is set.\n *\n * @property {*} $modelValue The value in the model that the control is bound to.\n *\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n *  the control updates the ngModelController with a new {@link ngModel.NgModelController#$viewValue\n    `$viewValue`} from the DOM, usually via user input.\n    See {@link ngModel.NgModelController#$setViewValue `$setViewValue()`} for a detailed lifecycle explanation.\n    Note that the `$parsers` are not called when the bound ngModel expression changes programmatically.\n\n  The functions are called in array order, each passing\n    its return value through to the next. The last return value is forwarded to the\n    {@link ngModel.NgModelController#$validators `$validators`} collection.\n\n  Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue\n    `$viewValue`}.\n\n  Returning `undefined` from a parser means a parse error occurred. In that case,\n    no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`\n    will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}\n    is set to `true`. The parse error is stored in `ngModel.$error.parse`.\n\n  This simple example shows a parser that would convert text input value to lowercase:\n * ```js\n * function parse(value) {\n *   if (value) {\n *     return value.toLowerCase();\n *   }\n * }\n * ngModelController.$parsers.push(parse);\n * ```\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n    the bound ngModel expression changes programmatically. The `$formatters` are not called when the\n    value of the control is changed by user interaction.\n\n  Formatters are used to format / convert the {@link ngModel.NgModelController#$modelValue\n    `$modelValue`} for display in the control.\n\n  The functions are called in reverse array order, each passing the value through to the\n    next. The last return value is used as the actual DOM value.\n\n  This simple example shows a formatter that would convert the model value to uppercase:\n\n * ```js\n * function format(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(format);\n * ```\n *\n * @property {Object.<string, function>} $validators A collection of validators that are applied\n *      whenever the model value changes. The key value within the object refers to the name of the\n *      validator while the function refers to the validation operation. The validation operation is\n *      provided with the model value as an argument and must return a true or false value depending\n *      on the response of that validation.\n *\n * ```js\n * ngModel.$validators.validCharacters = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *   return /[0-9]+/.test(value) &&\n *          /[a-z]+/.test(value) &&\n *          /[A-Z]+/.test(value) &&\n *          /\\W+/.test(value);\n * };\n * ```\n *\n * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to\n *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided\n *      is expected to return a promise when it is run during the model validation process. Once the promise\n *      is delivered then the validation status will be set to true when fulfilled and false when rejected.\n *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model\n *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator\n *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators\n *      will only run once all synchronous validators have passed.\n *\n * Please note that if $http is used then it is important that the server returns a success HTTP response code\n * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.\n *\n * ```js\n * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {\n *   var value = modelValue || viewValue;\n *\n *   // Lookup user by username\n *   return $http.get('/api/users/' + value).\n *      then(function resolved() {\n *        //username exists, this means validation fails\n *        return $q.reject('exists');\n *      }, function rejected() {\n *        //username does not exist, therefore this validation passes\n *        return true;\n *      });\n * };\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever\n *     a change to {@link ngModel.NgModelController#$viewValue `$viewValue`} has caused a change\n *     to {@link ngModel.NgModelController#$modelValue `$modelValue`}.\n *     It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all failing validator ids as keys.\n * @property {Object} $pending An object hash with all pending validator ids as keys.\n *\n * @property {boolean} $untouched True if control has not lost focus yet.\n * @property {boolean} $touched True if control has lost focus.\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n * @property {string} $name The name attribute of the control.\n *\n * @description\n *\n * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.\n * The controller contains services for data-binding, validation, CSS updates, and value formatting\n * and parsing. It purposefully does not contain any logic which deals with DOM rendering or\n * listening to DOM events.\n * Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding to control elements.\n * AngularJS provides this DOM logic for most {@link input `input`} elements.\n * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example\n * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.\n *\n * @example\n * ### Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if (!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if (attrs.stripBr && html === '<br>') {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\" aria-label=\"Dynamic textarea\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser === 'safari' || browser.params.browser === 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nNgModelController.$inject = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$q', '$interpolate'];\nfunction NgModelController($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $q, $interpolate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.\n  this.$validators = {};\n  this.$asyncValidators = {};\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$untouched = true;\n  this.$touched = false;\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$error = {}; // keep invalid keys here\n  this.$$success = {}; // keep valid keys here\n  this.$pending = undefined; // keep pending keys here\n  this.$name = $interpolate($attr.name || '', false)($scope);\n  this.$$parentForm = nullFormCtrl;\n  this.$options = defaultModelOptions;\n  this.$$updateEvents = '';\n  // Attach the correct context to the event handler function for updateOn\n  this.$$updateEventHandler = this.$$updateEventHandler.bind(this);\n\n  this.$$parsedNgModel = $parse($attr.ngModel);\n  this.$$parsedNgModelAssign = this.$$parsedNgModel.assign;\n  this.$$ngModelGet = this.$$parsedNgModel;\n  this.$$ngModelSet = this.$$parsedNgModelAssign;\n  this.$$pendingDebounce = null;\n  this.$$parserValid = undefined;\n  this.$$parserName = 'parse';\n\n  this.$$currentValidationRunId = 0;\n\n  this.$$scope = $scope;\n  this.$$rootScope = $scope.$root;\n  this.$$attr = $attr;\n  this.$$element = $element;\n  this.$$animate = $animate;\n  this.$$timeout = $timeout;\n  this.$$parse = $parse;\n  this.$$q = $q;\n  this.$$exceptionHandler = $exceptionHandler;\n\n  setupValidity(this);\n  setupModelWatcher(this);\n}\n\nNgModelController.prototype = {\n  $$initGetterSetters: function() {\n    if (this.$options.getOption('getterSetter')) {\n      var invokeModelGetter = this.$$parse(this.$$attr.ngModel + '()'),\n          invokeModelSetter = this.$$parse(this.$$attr.ngModel + '($$$p)');\n\n      this.$$ngModelGet = function($scope) {\n        var modelValue = this.$$parsedNgModel($scope);\n        if (isFunction(modelValue)) {\n          modelValue = invokeModelGetter($scope);\n        }\n        return modelValue;\n      };\n      this.$$ngModelSet = function($scope, newValue) {\n        if (isFunction(this.$$parsedNgModel($scope))) {\n          invokeModelSetter($scope, {$$$p: newValue});\n        } else {\n          this.$$parsedNgModelAssign($scope, newValue);\n        }\n      };\n    } else if (!this.$$parsedNgModel.assign) {\n      throw ngModelMinErr('nonassign', 'Expression \\'{0}\\' is non-assignable. Element: {1}',\n          this.$$attr.ngModel, startingTag(this.$$element));\n    }\n  },\n\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   *\n   * The `$render()` method is invoked in the following situations:\n   *\n   * * `$rollbackViewValue()` is called.  If we are rolling back the view value to the last\n   *   committed value then `$render()` is called to update the input control.\n   * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and\n   *   the `$viewValue` are different from last time.\n   *\n   * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of\n   * `$modelValue` and `$viewValue` are actually different from their previous values. If `$modelValue`\n   * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be\n   * invoked if you only change a property on the objects.\n   */\n  $render: noop,\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of an input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   *\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different from the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value The value of the input to check for emptiness.\n   * @returns {boolean} True if `value` is \"empty\".\n   */\n  $isEmpty: function(value) {\n    // eslint-disable-next-line no-self-compare\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  },\n\n  $$updateEmptyClasses: function(value) {\n    if (this.$isEmpty(value)) {\n      this.$$animate.removeClass(this.$$element, NOT_EMPTY_CLASS);\n      this.$$animate.addClass(this.$$element, EMPTY_CLASS);\n    } else {\n      this.$$animate.removeClass(this.$$element, EMPTY_CLASS);\n      this.$$animate.addClass(this.$$element, NOT_EMPTY_CLASS);\n    }\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the `ng-dirty` class and set the control to its pristine\n   * state (`ng-pristine` class). A model is considered to be pristine when the control\n   * has not been changed from when first compiled.\n   */\n  $setPristine: function() {\n    this.$dirty = false;\n    this.$pristine = true;\n    this.$$animate.removeClass(this.$$element, DIRTY_CLASS);\n    this.$$animate.addClass(this.$$element, PRISTINE_CLASS);\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setDirty\n   *\n   * @description\n   * Sets the control to its dirty state.\n   *\n   * This method can be called to remove the `ng-pristine` class and set the control to its dirty\n   * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed\n   * from when first compiled.\n   */\n  $setDirty: function() {\n    this.$dirty = true;\n    this.$pristine = false;\n    this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);\n    this.$$animate.addClass(this.$$element, DIRTY_CLASS);\n    this.$$parentForm.$setDirty();\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setUntouched\n   *\n   * @description\n   * Sets the control to its untouched state.\n   *\n   * This method can be called to remove the `ng-touched` class and set the control to its\n   * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched\n   * by default, however this function can be used to restore that state if the model has\n   * already been touched by the user.\n   */\n  $setUntouched: function() {\n    this.$touched = false;\n    this.$untouched = true;\n    this.$$animate.setClass(this.$$element, UNTOUCHED_CLASS, TOUCHED_CLASS);\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setTouched\n   *\n   * @description\n   * Sets the control to its touched state.\n   *\n   * This method can be called to remove the `ng-untouched` class and set the control to its\n   * touched state (`ng-touched` class). A model is considered to be touched when the user has\n   * first focused the control element and then shifted focus away from the control (blur event).\n   */\n  $setTouched: function() {\n    this.$touched = true;\n    this.$untouched = false;\n    this.$$animate.setClass(this.$$element, TOUCHED_CLASS, UNTOUCHED_CLASS);\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$rollbackViewValue\n   *\n   * @description\n   * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,\n   * which may be caused by a pending debounced event or because the input is waiting for some\n   * future event.\n   *\n   * If you have an input that uses `ng-model-options` to set up debounced updates or updates that\n   * depend on special events such as `blur`, there can be a period when the `$viewValue` is out of\n   * sync with the ngModel's `$modelValue`.\n   *\n   * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update\n   * and reset the input to the last committed view value.\n   *\n   * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue`\n   * programmatically before these debounced/future events have resolved/occurred, because AngularJS's\n   * dirty checking mechanism is not able to tell whether the model has actually changed or not.\n   *\n   * The `$rollbackViewValue()` method should be called before programmatically changing the model of an\n   * input which may have such events pending. This is important in order to make sure that the\n   * input field will be updated with the new model value and any pending operations are cancelled.\n   *\n   * @example\n   * <example name=\"ng-model-cancel-update\" module=\"cancel-update-example\">\n   *   <file name=\"app.js\">\n   *     angular.module('cancel-update-example', [])\n   *\n   *     .controller('CancelUpdateController', ['$scope', function($scope) {\n   *       $scope.model = {value1: '', value2: ''};\n   *\n   *       $scope.setEmpty = function(e, value, rollback) {\n   *         if (e.keyCode === 27) {\n   *           e.preventDefault();\n   *           if (rollback) {\n   *             $scope.myForm[value].$rollbackViewValue();\n   *           }\n   *           $scope.model[value] = '';\n   *         }\n   *       };\n   *     }]);\n   *   </file>\n   *   <file name=\"index.html\">\n   *     <div ng-controller=\"CancelUpdateController\">\n   *       <p>Both of these inputs are only updated if they are blurred. Hitting escape should\n   *       empty them. Follow these steps and observe the difference:</p>\n   *       <ol>\n   *         <li>Type something in the input. You will see that the model is not yet updated</li>\n   *         <li>Press the Escape key.\n   *           <ol>\n   *             <li> In the first example, nothing happens, because the model is already '', and no\n   *             update is detected. If you blur the input, the model will be set to the current view.\n   *             </li>\n   *             <li> In the second example, the pending update is cancelled, and the input is set back\n   *             to the last committed view value (''). Blurring the input does nothing.\n   *             </li>\n   *           </ol>\n   *         </li>\n   *       </ol>\n   *\n   *       <form name=\"myForm\" ng-model-options=\"{ updateOn: 'blur' }\">\n   *         <div>\n   *           <p id=\"inputDescription1\">Without $rollbackViewValue():</p>\n   *           <input name=\"value1\" aria-describedby=\"inputDescription1\" ng-model=\"model.value1\"\n   *                  ng-keydown=\"setEmpty($event, 'value1')\">\n   *           value1: \"{{ model.value1 }}\"\n   *         </div>\n   *\n   *         <div>\n   *           <p id=\"inputDescription2\">With $rollbackViewValue():</p>\n   *           <input name=\"value2\" aria-describedby=\"inputDescription2\" ng-model=\"model.value2\"\n   *                  ng-keydown=\"setEmpty($event, 'value2', true)\">\n   *           value2: \"{{ model.value2 }}\"\n   *         </div>\n   *       </form>\n   *     </div>\n   *   </file>\n       <file name=\"style.css\">\n          div {\n            display: table-cell;\n          }\n          div:nth-child(1) {\n            padding-right: 30px;\n          }\n\n        </file>\n   * </example>\n   */\n  $rollbackViewValue: function() {\n    this.$$timeout.cancel(this.$$pendingDebounce);\n    this.$viewValue = this.$$lastCommittedViewValue;\n    this.$render();\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$validate\n   *\n   * @description\n   * Runs each of the registered validators (first synchronous validators and then\n   * asynchronous validators).\n   * If the validity changes to invalid, the model will be set to `undefined`,\n   * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.\n   * If the validity changes to valid, it will set the model to the last available valid\n   * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.\n   */\n  $validate: function() {\n\n    // ignore $validate before model is initialized\n    if (isNumberNaN(this.$modelValue)) {\n      return;\n    }\n\n    var viewValue = this.$$lastCommittedViewValue;\n    // Note: we use the $$rawModelValue as $modelValue might have been\n    // set to undefined during a view -> model update that found validation\n    // errors. We can't parse the view here, since that could change\n    // the model although neither viewValue nor the model on the scope changed\n    var modelValue = this.$$rawModelValue;\n\n    var prevValid = this.$valid;\n    var prevModelValue = this.$modelValue;\n\n    var allowInvalid = this.$options.getOption('allowInvalid');\n\n    var that = this;\n    this.$$runValidators(modelValue, viewValue, function(allValid) {\n      // If there was no change in validity, don't update the model\n      // This prevents changing an invalid modelValue to undefined\n      if (!allowInvalid && prevValid !== allValid) {\n        // Note: Don't check this.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        that.$modelValue = allValid ? modelValue : undefined;\n\n        if (that.$modelValue !== prevModelValue) {\n          that.$$writeModelToScope();\n        }\n      }\n    });\n  },\n\n  $$runValidators: function(modelValue, viewValue, doneCallback) {\n    this.$$currentValidationRunId++;\n    var localValidationRunId = this.$$currentValidationRunId;\n    var that = this;\n\n    // check parser error\n    if (!processParseErrors()) {\n      validationDone(false);\n      return;\n    }\n    if (!processSyncValidators()) {\n      validationDone(false);\n      return;\n    }\n    processAsyncValidators();\n\n    function processParseErrors() {\n      var errorKey = that.$$parserName;\n\n      if (isUndefined(that.$$parserValid)) {\n        setValidity(errorKey, null);\n      } else {\n        if (!that.$$parserValid) {\n          forEach(that.$validators, function(v, name) {\n            setValidity(name, null);\n          });\n          forEach(that.$asyncValidators, function(v, name) {\n            setValidity(name, null);\n          });\n        }\n\n        // Set the parse error last, to prevent unsetting it, should a $validators key == parserName\n        setValidity(errorKey, that.$$parserValid);\n        return that.$$parserValid;\n      }\n      return true;\n    }\n\n    function processSyncValidators() {\n      var syncValidatorsValid = true;\n      forEach(that.$validators, function(validator, name) {\n        var result = Boolean(validator(modelValue, viewValue));\n        syncValidatorsValid = syncValidatorsValid && result;\n        setValidity(name, result);\n      });\n      if (!syncValidatorsValid) {\n        forEach(that.$asyncValidators, function(v, name) {\n          setValidity(name, null);\n        });\n        return false;\n      }\n      return true;\n    }\n\n    function processAsyncValidators() {\n      var validatorPromises = [];\n      var allValid = true;\n      forEach(that.$asyncValidators, function(validator, name) {\n        var promise = validator(modelValue, viewValue);\n        if (!isPromiseLike(promise)) {\n          throw ngModelMinErr('nopromise',\n            'Expected asynchronous validator to return a promise but got \\'{0}\\' instead.', promise);\n        }\n        setValidity(name, undefined);\n        validatorPromises.push(promise.then(function() {\n          setValidity(name, true);\n        }, function() {\n          allValid = false;\n          setValidity(name, false);\n        }));\n      });\n      if (!validatorPromises.length) {\n        validationDone(true);\n      } else {\n        that.$$q.all(validatorPromises).then(function() {\n          validationDone(allValid);\n        }, noop);\n      }\n    }\n\n    function setValidity(name, isValid) {\n      if (localValidationRunId === that.$$currentValidationRunId) {\n        that.$setValidity(name, isValid);\n      }\n    }\n\n    function validationDone(allValid) {\n      if (localValidationRunId === that.$$currentValidationRunId) {\n\n        doneCallback(allValid);\n      }\n    }\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$commitViewValue\n   *\n   * @description\n   * Commit a pending update to the `$modelValue`.\n   *\n   * Updates may be pending by a debounced event or because the input is waiting for a some future\n   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`\n   * usually handles calling this in response to input events.\n   */\n  $commitViewValue: function() {\n    var viewValue = this.$viewValue;\n\n    this.$$timeout.cancel(this.$$pendingDebounce);\n\n    // If the view value has not changed then we should just exit, except in the case where there is\n    // a native validator on the element. In this case the validation state may have changed even though\n    // the viewValue has stayed empty.\n    if (this.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !this.$$hasNativeValidators)) {\n      return;\n    }\n    this.$$updateEmptyClasses(viewValue);\n    this.$$lastCommittedViewValue = viewValue;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$setDirty();\n    }\n    this.$$parseAndValidate();\n  },\n\n  $$parseAndValidate: function() {\n    var viewValue = this.$$lastCommittedViewValue;\n    var modelValue = viewValue;\n    var that = this;\n\n    this.$$parserValid = isUndefined(modelValue) ? undefined : true;\n\n    // Reset any previous parse error\n    this.$setValidity(this.$$parserName, null);\n    this.$$parserName = 'parse';\n\n    if (this.$$parserValid) {\n      for (var i = 0; i < this.$parsers.length; i++) {\n        modelValue = this.$parsers[i](modelValue);\n        if (isUndefined(modelValue)) {\n          this.$$parserValid = false;\n          break;\n        }\n      }\n    }\n    if (isNumberNaN(this.$modelValue)) {\n      // this.$modelValue has not been touched yet...\n      this.$modelValue = this.$$ngModelGet(this.$$scope);\n    }\n    var prevModelValue = this.$modelValue;\n    var allowInvalid = this.$options.getOption('allowInvalid');\n    this.$$rawModelValue = modelValue;\n\n    if (allowInvalid) {\n      this.$modelValue = modelValue;\n      writeToModelIfNeeded();\n    }\n\n    // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.\n    // This can happen if e.g. $setViewValue is called from inside a parser\n    this.$$runValidators(modelValue, this.$$lastCommittedViewValue, function(allValid) {\n      if (!allowInvalid) {\n        // Note: Don't check this.$valid here, as we could have\n        // external validators (e.g. calculated on the server),\n        // that just call $setValidity and need the model value\n        // to calculate their validity.\n        that.$modelValue = allValid ? modelValue : undefined;\n        writeToModelIfNeeded();\n      }\n    });\n\n    function writeToModelIfNeeded() {\n      if (that.$modelValue !== prevModelValue) {\n        that.$$writeModelToScope();\n      }\n    }\n  },\n\n  $$writeModelToScope: function() {\n    this.$$ngModelSet(this.$$scope, this.$modelValue);\n    forEach(this.$viewChangeListeners, function(listener) {\n      try {\n        listener();\n      } catch (e) {\n        // eslint-disable-next-line no-invalid-this\n        this.$$exceptionHandler(e);\n      }\n    }, this);\n  },\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when a control wants to change the view value; typically,\n   * this is done from within a DOM event handler. For example, the {@link ng.directive:input input}\n   * directive calls it when the value of the input changes and {@link ng.directive:select select}\n   * calls it when an option is selected.\n   *\n   * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers`\n   * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged\n   * value is sent directly for processing through the `$parsers` pipeline. After this, the `$validators` and\n   * `$asyncValidators` are called and the value is applied to `$modelValue`.\n   * Finally, the value is set to the **expression** specified in the `ng-model` attribute and\n   * all the registered change listeners, in the `$viewChangeListeners` list are called.\n   *\n   * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`\n   * and the `default` trigger is not listed, all those actions will remain pending until one of the\n   * `updateOn` events is triggered on the DOM element.\n   * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}\n   * directive is used with a custom debounce for this particular event.\n   * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce`\n   * is specified, once the timer runs out.\n   *\n   * When used with standard inputs, the view value will always be a string (which is in some cases\n   * parsed into another type, such as a `Date` object for `input[date]`.)\n   * However, custom controls might also pass objects to this method. In this case, we should make\n   * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not\n   * perform a deep watch of objects, it only looks for a change of identity. If you only change\n   * the property of the object then ngModel will not realize that the object has changed and\n   * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should\n   * not change properties of the copy once it has been passed to `$setViewValue`.\n   * Otherwise you may cause the model value on the scope to change incorrectly.\n   *\n   * <div class=\"alert alert-info\">\n   * In any case, the value passed to the method should always reflect the current value\n   * of the control. For example, if you are calling `$setViewValue` for an input element,\n   * you should pass the input DOM value. Otherwise, the control and the scope model become\n   * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change\n   * the control's DOM value in any way. If we want to change the control's DOM value\n   * programmatically, we should update the `ngModel` scope expression. Its new value will be\n   * picked up by the model controller, which will run it through the `$formatters`, `$render` it\n   * to update the DOM, and finally call `$validate` on it.\n   * </div>\n   *\n   * @param {*} value value from the view.\n   * @param {string} trigger Event that triggered the update.\n   */\n  $setViewValue: function(value, trigger) {\n    this.$viewValue = value;\n    if (this.$options.getOption('updateOnDefault')) {\n      this.$$debounceViewValueCommit(trigger);\n    }\n  },\n\n  $$debounceViewValueCommit: function(trigger) {\n    var debounceDelay = this.$options.getOption('debounce');\n\n    if (isNumber(debounceDelay[trigger])) {\n      debounceDelay = debounceDelay[trigger];\n    } else if (isNumber(debounceDelay['default']) &&\n      this.$options.getOption('updateOn').indexOf(trigger) === -1\n    ) {\n      debounceDelay = debounceDelay['default'];\n    } else if (isNumber(debounceDelay['*'])) {\n      debounceDelay = debounceDelay['*'];\n    }\n\n    this.$$timeout.cancel(this.$$pendingDebounce);\n    var that = this;\n    if (debounceDelay > 0) { // this fails if debounceDelay is an object\n      this.$$pendingDebounce = this.$$timeout(function() {\n        that.$commitViewValue();\n      }, debounceDelay);\n    } else if (this.$$rootScope.$$phase) {\n      this.$commitViewValue();\n    } else {\n      this.$$scope.$apply(function() {\n        that.$commitViewValue();\n      });\n    }\n  },\n\n  /**\n   * @ngdoc method\n   *\n   * @name ngModel.NgModelController#$overrideModelOptions\n   *\n   * @description\n   *\n   * Override the current model options settings programmatically.\n   *\n   * The previous `ModelOptions` value will not be modified. Instead, a\n   * new `ModelOptions` object will inherit from the previous one overriding\n   * or inheriting settings that are defined in the given parameter.\n   *\n   * See {@link ngModelOptions} for information about what options can be specified\n   * and how model option inheritance works.\n   *\n   * <div class=\"alert alert-warning\">\n   * **Note:** this function only affects the options set on the `ngModelController`,\n   * and not the options on the {@link ngModelOptions} directive from which they might have been\n   * obtained initially.\n   * </div>\n   *\n   * <div class=\"alert alert-danger\">\n   * **Note:** it is not possible to override the `getterSetter` option.\n   * </div>\n   *\n   * @param {Object} options a hash of settings to override the previous options\n   *\n   */\n  $overrideModelOptions: function(options) {\n    this.$options = this.$options.createChild(options);\n    this.$$setUpdateOnEvents();\n  },\n\n  /**\n   * @ngdoc method\n   *\n   * @name  ngModel.NgModelController#$processModelValue\n\n   * @description\n   *\n   * Runs the model -> view pipeline on the current\n   * {@link ngModel.NgModelController#$modelValue $modelValue}.\n   *\n   * The following actions are performed by this method:\n   *\n   * - the `$modelValue` is run through the {@link ngModel.NgModelController#$formatters $formatters}\n   * and the result is set to the {@link ngModel.NgModelController#$viewValue $viewValue}\n   * - the `ng-empty` or `ng-not-empty` class is set on the element\n   * - if the `$viewValue` has changed:\n   *   - {@link ngModel.NgModelController#$render $render} is called on the control\n   *   - the {@link ngModel.NgModelController#$validators $validators} are run and\n   *   the validation status is set.\n   *\n   * This method is called by ngModel internally when the bound scope value changes.\n   * Application developers usually do not have to call this function themselves.\n   *\n   * This function can be used when the `$viewValue` or the rendered DOM value are not correctly\n   * formatted and the `$modelValue` must be run through the `$formatters` again.\n   *\n   * @example\n   * Consider a text input with an autocomplete list (for fruit), where the items are\n   * objects with a name and an id.\n   * A user enters `ap` and then selects `Apricot` from the list.\n   * Based on this, the autocomplete widget will call `$setViewValue({name: 'Apricot', id: 443})`,\n   * but the rendered value will still be `ap`.\n   * The widget can then call `ctrl.$processModelValue()` to run the model -> view\n   * pipeline again, which formats the object to the string `Apricot`,\n   * then updates the `$viewValue`, and finally renders it in the DOM.\n   *\n   * <example module=\"inputExample\" name=\"ng-model-process\">\n     <file name=\"index.html\">\n      <div ng-controller=\"inputController\" style=\"display: flex;\">\n        <div style=\"margin-right: 30px;\">\n          Search Fruit:\n          <basic-autocomplete items=\"items\" on-select=\"selectedFruit = item\"></basic-autocomplete>\n        </div>\n        <div>\n          Model:<br>\n          <pre>{{selectedFruit | json}}</pre>\n        </div>\n      </div>\n     </file>\n     <file name=\"app.js\">\n      angular.module('inputExample', [])\n        .controller('inputController', function($scope) {\n          $scope.items = [\n            {name: 'Apricot', id: 443},\n            {name: 'Clementine', id: 972},\n            {name: 'Durian', id: 169},\n            {name: 'Jackfruit', id: 982},\n            {name: 'Strawberry', id: 863}\n          ];\n        })\n        .component('basicAutocomplete', {\n          bindings: {\n            items: '<',\n            onSelect: '&'\n          },\n          templateUrl: 'autocomplete.html',\n          controller: function($element, $scope) {\n            var that = this;\n            var ngModel;\n\n            that.$postLink = function() {\n              ngModel = $element.find('input').controller('ngModel');\n\n              ngModel.$formatters.push(function(value) {\n                return (value && value.name) || value;\n              });\n\n              ngModel.$parsers.push(function(value) {\n                var match = value;\n                for (var i = 0; i < that.items.length; i++) {\n                  if (that.items[i].name === value) {\n                    match = that.items[i];\n                    break;\n                  }\n                }\n\n                return match;\n              });\n            };\n\n            that.selectItem = function(item) {\n              ngModel.$setViewValue(item);\n              ngModel.$processModelValue();\n              that.onSelect({item: item});\n            };\n          }\n        });\n     </file>\n     <file name=\"autocomplete.html\">\n       <div>\n         <input type=\"search\" ng-model=\"$ctrl.searchTerm\" />\n         <ul>\n           <li ng-repeat=\"item in $ctrl.items | filter:$ctrl.searchTerm\">\n             <button ng-click=\"$ctrl.selectItem(item)\">{{ item.name }}</button>\n           </li>\n         </ul>\n       </div>\n     </file>\n   * </example>\n   *\n   */\n  $processModelValue: function() {\n    var viewValue = this.$$format();\n\n    if (this.$viewValue !== viewValue) {\n      this.$$updateEmptyClasses(viewValue);\n      this.$viewValue = this.$$lastCommittedViewValue = viewValue;\n      this.$render();\n      // It is possible that model and view value have been updated during render\n      this.$$runValidators(this.$modelValue, this.$viewValue, noop);\n    }\n  },\n\n  /**\n   * This method is called internally to run the $formatters on the $modelValue\n   */\n  $$format: function() {\n    var formatters = this.$formatters,\n        idx = formatters.length;\n\n    var viewValue = this.$modelValue;\n    while (idx--) {\n      viewValue = formatters[idx](viewValue);\n    }\n\n    return viewValue;\n  },\n\n  /**\n   * This method is called internally when the bound scope value changes.\n   */\n  $$setModelValue: function(modelValue) {\n    this.$modelValue = this.$$rawModelValue = modelValue;\n    this.$$parserValid = undefined;\n    this.$processModelValue();\n  },\n\n  $$setUpdateOnEvents: function() {\n    if (this.$$updateEvents) {\n      this.$$element.off(this.$$updateEvents, this.$$updateEventHandler);\n    }\n\n    this.$$updateEvents = this.$options.getOption('updateOn');\n    if (this.$$updateEvents) {\n      this.$$element.on(this.$$updateEvents, this.$$updateEventHandler);\n    }\n  },\n\n  $$updateEventHandler: function(ev) {\n    this.$$debounceViewValueCommit(ev && ev.type);\n  }\n};\n\nfunction setupModelWatcher(ctrl) {\n  // model -> value\n  // Note: we cannot use a normal scope.$watch as we want to detect the following:\n  // 1. scope value is 'a'\n  // 2. user enters 'b'\n  // 3. ng-change kicks in and reverts scope value to 'a'\n  //    -> scope value did not change since the last digest as\n  //       ng-change executes in apply phase\n  // 4. view should be changed back to 'a'\n  ctrl.$$scope.$watch(function ngModelWatch(scope) {\n    var modelValue = ctrl.$$ngModelGet(scope);\n\n    // if scope model value and ngModel value are out of sync\n    // This cannot be moved to the action function, because it would not catch the\n    // case where the model is changed in the ngChange function or the model setter\n    if (modelValue !== ctrl.$modelValue &&\n      // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator\n      // eslint-disable-next-line no-self-compare\n      (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)\n    ) {\n      ctrl.$$setModelValue(modelValue);\n    }\n\n    return modelValue;\n  });\n}\n\n/**\n * @ngdoc method\n * @name ngModel.NgModelController#$setValidity\n *\n * @description\n * Change the validity state, and notify the form.\n *\n * This method can be called within $parsers/$formatters or a custom validation implementation.\n * However, in most cases it should be sufficient to use the `ngModel.$validators` and\n * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.\n *\n * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned\n *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`\n *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.\n *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n *        classes and can be bound to as `{{ someForm.someControl.$error.myError }}`.\n * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),\n *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.\n *                          Skipped is used by AngularJS when validators do not run because of parse errors and\n *                          when `$asyncValidators` do not run because any of the `$validators` failed.\n */\naddSetValidityMethod({\n  clazz: NgModelController,\n  set: function(object, property) {\n    object[property] = true;\n  },\n  unset: function(object, property) {\n    delete object[property];\n  }\n});\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n * @restrict A\n * @priority 1\n * @param {expression} ngModel assignable {@link guide/expression Expression} to bind to.\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`,\n *   `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *    - {@link input[date] date}\n *    - {@link input[datetime-local] datetime-local}\n *    - {@link input[time] time}\n *    - {@link input[month] month}\n *    - {@link input[week] week}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * ## Complex Models (objects or collections)\n *\n * By default, `ngModel` watches the model by reference, not value. This is important to know when\n * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the\n * object or collection change, `ngModel` will not be notified and so the input will not be  re-rendered.\n *\n * The model must be assigned an entirely new object or collection before a re-rendering will occur.\n *\n * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression\n * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or\n * if the select is given the `multiple` attribute.\n *\n * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the\n * first level of the object (or only changing the properties of an item in the collection if it's an array) will still\n * not trigger a re-rendering of the model.\n *\n * ## CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid`: the model is valid\n *  - `ng-invalid`: the model is invalid\n *  - `ng-valid-[key]`: for each valid key added by `$setValidity`\n *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`\n *  - `ng-pristine`: the control hasn't been interacted with yet\n *  - `ng-dirty`: the control has been interacted with\n *  - `ng-touched`: the control has been blurred\n *  - `ng-untouched`: the control hasn't been blurred\n *  - `ng-pending`: any `$asyncValidators` are unfulfilled\n *  - `ng-empty`: the view does not contain a value or the value is deemed \"empty\", as defined\n *     by the {@link ngModel.NgModelController#$isEmpty} method\n *  - `ng-not-empty`: the view contains a non-empty value\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * @animations\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * ### Basic Usage\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\" name=\"ng-model\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       <p id=\"inputDescription\">\n        Update input to see transitions when valid/invalid.\n        Integer is a valid value.\n       </p>\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\"\n                aria-describedby=\"inputDescription\" />\n       </form>\n     </file>\n * </example>\n *\n * @example\n * ### Binding to a getter/setter\n *\n * Sometimes it's helpful to bind `ngModel` to a getter/setter function.  A getter/setter is a\n * function that returns a representation of the model when called with zero arguments, and sets\n * the internal state of a model when called with an argument. It's sometimes useful to use this\n * for models that have an internal representation that's different from what the model exposes\n * to the view.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's best to keep getters fast because AngularJS is likely to call them more\n * frequently than other parts of your code.\n * </div>\n *\n * You use this behavior by adding `ng-model-options=\"{ getterSetter: true }\"` to an element that\n * has `ng-model` attached to it. You can also add `ng-model-options=\"{ getterSetter: true }\"` to\n * a `<form>`, which will enable this behavior for all `<input>`s within it. See\n * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.\n *\n * The following example shows how to use `ngModel` with a getter/setter:\n *\n * @example\n * <example name=\"ngModel-getter-setter\" module=\"getterSetterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <form name=\"userForm\">\n           <label>Name:\n             <input type=\"text\" name=\"userName\"\n                    ng-model=\"user.name\"\n                    ng-model-options=\"{ getterSetter: true }\" />\n           </label>\n         </form>\n         <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n       </div>\n     </file>\n     <file name=\"app.js\">\n       angular.module('getterSetterExample', [])\n         .controller('ExampleController', ['$scope', function($scope) {\n           var _name = 'Brian';\n           $scope.user = {\n             name: function(newName) {\n              // Note that newName can be undefined for two reasons:\n              // 1. Because it is called as a getter and thus called with no arguments\n              // 2. Because the property should actually be set to undefined. This happens e.g. if the\n              //    input is invalid\n              return arguments.length ? (_name = newName) : _name;\n             }\n           };\n         }]);\n     </file>\n * </example>\n */\nvar ngModelDirective = ['$rootScope', function($rootScope) {\n  return {\n    restrict: 'A',\n    require: ['ngModel', '^?form', '^?ngModelOptions'],\n    controller: NgModelController,\n    // Prelink needs to run before any input directive\n    // so that we can set the NgModelOptions in NgModelController\n    // before anyone else uses it.\n    priority: 1,\n    compile: function ngModelCompile(element) {\n      // Setup initial state of the control\n      element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);\n\n      return {\n        pre: function ngModelPreLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0],\n              formCtrl = ctrls[1] || modelCtrl.$$parentForm,\n              optionsCtrl = ctrls[2];\n\n          if (optionsCtrl) {\n            modelCtrl.$options = optionsCtrl.$options;\n          }\n\n          modelCtrl.$$initGetterSetters();\n\n          // notify others, especially parent forms\n          formCtrl.$addControl(modelCtrl);\n\n          attr.$observe('name', function(newValue) {\n            if (modelCtrl.$name !== newValue) {\n              modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue);\n            }\n          });\n\n          scope.$on('$destroy', function() {\n            modelCtrl.$$parentForm.$removeControl(modelCtrl);\n          });\n        },\n        post: function ngModelPostLink(scope, element, attr, ctrls) {\n          var modelCtrl = ctrls[0];\n          modelCtrl.$$setUpdateOnEvents();\n\n          function setTouched() {\n            modelCtrl.$setTouched();\n          }\n\n          element.on('blur', function() {\n            if (modelCtrl.$touched) return;\n\n            if ($rootScope.$$phase) {\n              scope.$evalAsync(setTouched);\n            } else {\n              scope.$apply(setTouched);\n            }\n          });\n        }\n      };\n    }\n  };\n}];\n\n/* exported defaultModelOptions */\nvar defaultModelOptions;\nvar DEFAULT_REGEXP = /(\\s+|^)default(\\s+|$)/;\n\n/**\n * @ngdoc type\n * @name ModelOptions\n * @description\n * A container for the options set by the {@link ngModelOptions} directive\n */\nfunction ModelOptions(options) {\n  this.$$options = options;\n}\n\nModelOptions.prototype = {\n\n  /**\n   * @ngdoc method\n   * @name ModelOptions#getOption\n   * @param {string} name the name of the option to retrieve\n   * @returns {*} the value of the option\n   * @description\n   * Returns the value of the given option\n   */\n  getOption: function(name) {\n    return this.$$options[name];\n  },\n\n  /**\n   * @ngdoc method\n   * @name ModelOptions#createChild\n   * @param {Object} options a hash of options for the new child that will override the parent's options\n   * @return {ModelOptions} a new `ModelOptions` object initialized with the given options.\n   */\n  createChild: function(options) {\n    var inheritAll = false;\n\n    // make a shallow copy\n    options = extend({}, options);\n\n    // Inherit options from the parent if specified by the value `\"$inherit\"`\n    forEach(options, /** @this */ function(option, key) {\n      if (option === '$inherit') {\n        if (key === '*') {\n          inheritAll = true;\n        } else {\n          options[key] = this.$$options[key];\n          // `updateOn` is special so we must also inherit the `updateOnDefault` option\n          if (key === 'updateOn') {\n            options.updateOnDefault = this.$$options.updateOnDefault;\n          }\n        }\n      } else {\n        if (key === 'updateOn') {\n          // If the `updateOn` property contains the `default` event then we have to remove\n          // it from the event list and set the `updateOnDefault` flag.\n          options.updateOnDefault = false;\n          options[key] = trim(option.replace(DEFAULT_REGEXP, function() {\n            options.updateOnDefault = true;\n            return ' ';\n          }));\n        }\n      }\n    }, this);\n\n    if (inheritAll) {\n      // We have a property of the form: `\"*\": \"$inherit\"`\n      delete options['*'];\n      defaults(options, this.$$options);\n    }\n\n    // Finally add in any missing defaults\n    defaults(options, defaultModelOptions.$$options);\n\n    return new ModelOptions(options);\n  }\n};\n\n\ndefaultModelOptions = new ModelOptions({\n  updateOn: '',\n  updateOnDefault: true,\n  debounce: 0,\n  getterSetter: false,\n  allowInvalid: false,\n  timezone: null\n});\n\n\n/**\n * @ngdoc directive\n * @name ngModelOptions\n * @restrict A\n * @priority 10\n *\n * @description\n * This directive allows you to modify the behaviour of {@link ngModel} directives within your\n * application. You can specify an `ngModelOptions` directive on any element. All {@link ngModel}\n * directives will use the options of their nearest `ngModelOptions` ancestor.\n *\n * The `ngModelOptions` settings are found by evaluating the value of the attribute directive as\n * an AngularJS expression. This expression should evaluate to an object, whose properties contain\n * the settings. For example: `<div ng-model-options=\"{ debounce: 100 }\"`.\n *\n * ## Inheriting Options\n *\n * You can specify that an `ngModelOptions` setting should be inherited from a parent `ngModelOptions`\n * directive by giving it the value of `\"$inherit\"`.\n * Then it will inherit that setting from the first `ngModelOptions` directive found by traversing up the\n * DOM tree. If there is no ancestor element containing an `ngModelOptions` directive then default settings\n * will be used.\n *\n * For example given the following fragment of HTML\n *\n *\n * ```html\n * <div ng-model-options=\"{ allowInvalid: true, debounce: 200 }\">\n *   <form ng-model-options=\"{ updateOn: 'blur', allowInvalid: '$inherit' }\">\n *     <input ng-model-options=\"{ updateOn: 'default', allowInvalid: '$inherit' }\" />\n *   </form>\n * </div>\n * ```\n *\n * the `input` element will have the following settings\n *\n * ```js\n * { allowInvalid: true, updateOn: 'default', debounce: 0 }\n * ```\n *\n * Notice that the `debounce` setting was not inherited and used the default value instead.\n *\n * You can specify that all undefined settings are automatically inherited from an ancestor by\n * including a property with key of `\"*\"` and value of `\"$inherit\"`.\n *\n * For example given the following fragment of HTML\n *\n *\n * ```html\n * <div ng-model-options=\"{ allowInvalid: true, debounce: 200 }\">\n *   <form ng-model-options=\"{ updateOn: 'blur', \"*\": '$inherit' }\">\n *     <input ng-model-options=\"{ updateOn: 'default', \"*\": '$inherit' }\" />\n *   </form>\n * </div>\n * ```\n *\n * the `input` element will have the following settings\n *\n * ```js\n * { allowInvalid: true, updateOn: 'default', debounce: 200 }\n * ```\n *\n * Notice that the `debounce` setting now inherits the value from the outer `<div>` element.\n *\n * If you are creating a reusable component then you should be careful when using `\"*\": \"$inherit\"`\n * since you may inadvertently inherit a setting in the future that changes the behavior of your component.\n *\n *\n * ## Triggering and debouncing model updates\n *\n * The `updateOn` and `debounce` properties allow you to specify a custom list of events that will\n * trigger a model update and/or a debouncing delay so that the actual update only takes place when\n * a timer expires; this timer will be reset after another change takes place.\n *\n * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might\n * be different from the value in the actual model. This means that if you update the model you\n * should also invoke {@link ngModel.NgModelController#$rollbackViewValue} on the relevant input field in\n * order to make sure it is synchronized with the model and that any debounced action is canceled.\n *\n * The easiest way to reference the control's {@link ngModel.NgModelController#$rollbackViewValue}\n * method is by making sure the input is placed inside a form that has a `name` attribute. This is\n * important because `form` controllers are published to the related scope under the name in their\n * `name` attribute.\n *\n * Any pending changes will take place immediately when an enclosing form is submitted via the\n * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ### Overriding immediate updates\n *\n * The following example shows how to override immediate updates. Changes on the inputs within the\n * form will update the model only when the control loses focus (blur event). If `escape` key is\n * pressed while the input field is focused, the value is reset to the value in the current model.\n *\n * <example name=\"ngModelOptions-directive-blur\" module=\"optionsExample\">\n *   <file name=\"index.html\">\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"userForm\">\n *         <label>\n *           Name:\n *           <input type=\"text\" name=\"userName\"\n *                  ng-model=\"user.name\"\n *                  ng-model-options=\"{ updateOn: 'blur' }\"\n *                  ng-keyup=\"cancel($event)\" />\n *         </label><br />\n *         <label>\n *           Other data:\n *           <input type=\"text\" ng-model=\"user.data\" />\n *         </label><br />\n *       </form>\n *       <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n *     </div>\n *   </file>\n *   <file name=\"app.js\">\n *     angular.module('optionsExample', [])\n *       .controller('ExampleController', ['$scope', function($scope) {\n *         $scope.user = { name: 'say', data: '' };\n *\n *         $scope.cancel = function(e) {\n *           if (e.keyCode === 27) {\n *             $scope.userForm.userName.$rollbackViewValue();\n *           }\n *         };\n *       }]);\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var model = element(by.binding('user.name'));\n *     var input = element(by.model('user.name'));\n *     var other = element(by.model('user.data'));\n *\n *     it('should allow custom events', function() {\n *       input.sendKeys(' hello');\n *       input.click();\n *       expect(model.getText()).toEqual('say');\n *       other.click();\n *       expect(model.getText()).toEqual('say hello');\n *     });\n *\n *     it('should $rollbackViewValue when model changes', function() {\n *       input.sendKeys(' hello');\n *       expect(input.getAttribute('value')).toEqual('say hello');\n *       input.sendKeys(protractor.Key.ESCAPE);\n *       expect(input.getAttribute('value')).toEqual('say');\n *       other.click();\n *       expect(model.getText()).toEqual('say');\n *     });\n *   </file>\n * </example>\n *\n * ### Debouncing updates\n *\n * The next example shows how to debounce model changes. Model will be updated only 1 sec after last change.\n * If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.\n *\n * <example name=\"ngModelOptions-directive-debounce\" module=\"optionsExample\">\n *   <file name=\"index.html\">\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"userForm\">\n *         Name:\n *         <input type=\"text\" name=\"userName\"\n *                ng-model=\"user.name\"\n *                ng-model-options=\"{ debounce: 1000 }\" />\n *         <button ng-click=\"userForm.userName.$rollbackViewValue(); user.name=''\">Clear</button><br />\n *       </form>\n *       <pre>user.name = <span ng-bind=\"user.name\"></span></pre>\n *     </div>\n *   </file>\n *   <file name=\"app.js\">\n *     angular.module('optionsExample', [])\n *       .controller('ExampleController', ['$scope', function($scope) {\n *         $scope.user = { name: 'say' };\n *       }]);\n *   </file>\n * </example>\n *\n * ### Default events, extra triggers, and catch-all debounce values\n *\n * This example shows the relationship between \"default\" update events and\n * additional `updateOn` triggers.\n *\n * `default` events are those that are bound to the control, and when fired, update the `$viewValue`\n * via {@link ngModel.NgModelController#$setViewValue $setViewValue}. Every event that is not listed\n * in `updateOn` is considered a \"default\" event, since different control types have different\n * default events.\n *\n * The control in this example updates by \"default\", \"click\", and \"blur\", with different `debounce`\n * values. You can see that \"click\" doesn't have an individual `debounce` value -\n * therefore it uses the `*` debounce value.\n *\n * There is also a button that calls {@link ngModel.NgModelController#$setViewValue $setViewValue}\n * directly with a \"custom\" event. Since \"custom\" is not defined in the `updateOn` list,\n * it is considered a \"default\" event and will update the\n * control if \"default\" is defined in `updateOn`, and will receive the \"default\" debounce value.\n * Note that this is just to illustrate how custom controls would possibly call `$setViewValue`.\n *\n * You can change the `updateOn` and `debounce` configuration to test different scenarios. This\n * is done with {@link ngModel.NgModelController#$overrideModelOptions $overrideModelOptions}.\n *\n  <example name=\"ngModelOptions-advanced\" module=\"optionsExample\">\n    <file name=\"index.html\">\n       <model-update-demo></model-update-demo>\n    </file>\n    <file name=\"app.js\">\n      angular.module('optionsExample', [])\n        .component('modelUpdateDemo', {\n          templateUrl: 'template.html',\n          controller: function() {\n            this.name = 'Chinua';\n\n            this.options = {\n              updateOn: 'default blur click',\n              debounce: {\n                default: 2000,\n                blur: 0,\n                '*': 1000\n              }\n            };\n\n            this.updateEvents = function() {\n              var eventList = this.options.updateOn.split(' ');\n              eventList.push('*');\n              var events = {};\n\n              for (var i = 0; i < eventList.length; i++) {\n                events[eventList[i]] = this.options.debounce[eventList[i]];\n              }\n\n              this.events = events;\n            };\n\n            this.updateOptions = function() {\n              var options = angular.extend(this.options, {\n                updateOn: Object.keys(this.events).join(' ').replace('*', ''),\n                debounce: this.events\n              });\n\n              this.form.input.$overrideModelOptions(options);\n            };\n\n            // Initialize the event form\n            this.updateEvents();\n          }\n        });\n    </file>\n    <file name=\"template.html\">\n      <form name=\"$ctrl.form\">\n        Input: <input type=\"text\" name=\"input\" ng-model=\"$ctrl.name\" ng-model-options=\"$ctrl.options\" />\n      </form>\n      Model: <tt>{{$ctrl.name}}</tt>\n      <hr>\n      <button ng-click=\"$ctrl.form.input.$setViewValue('some value', 'custom')\">Trigger setViewValue with 'some value' and 'custom' event</button>\n\n      <hr>\n      <form ng-submit=\"$ctrl.updateOptions()\">\n        <b>updateOn</b><br>\n        <input type=\"text\" ng-model=\"$ctrl.options.updateOn\" ng-change=\"$ctrl.updateEvents()\" ng-model-options=\"{debounce: 500}\">\n\n        <table>\n          <tr>\n            <th>Option</th>\n            <th>Debounce value</th>\n          </tr>\n          <tr ng-repeat=\"(key, value) in $ctrl.events\">\n            <td>{{key}}</td>\n            <td><input type=\"number\" ng-model=\"$ctrl.events[key]\" /></td>\n          </tr>\n        </table>\n\n        <br>\n        <input type=\"submit\" value=\"Update options\">\n      </form>\n    </file>\n  </example>\n *\n *\n * ## Model updates and validation\n *\n * The default behaviour in `ngModel` is that the model value is set to `undefined` when the\n * validation determines that the value is invalid. By setting the `allowInvalid` property to true,\n * the model will still be updated even if the value is invalid.\n *\n *\n * ## Connecting to the scope\n *\n * By setting the `getterSetter` property to true you are telling ngModel that the `ngModel` expression\n * on the scope refers to a \"getter/setter\" function rather than the value itself.\n *\n * The following example shows how to bind to getter/setters:\n *\n * <example name=\"ngModelOptions-directive-getter-setter\" module=\"getterSetterExample\">\n *   <file name=\"index.html\">\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"userForm\">\n *         <label>\n *           Name:\n *           <input type=\"text\" name=\"userName\"\n *                  ng-model=\"user.name\"\n *                  ng-model-options=\"{ getterSetter: true }\" />\n *         </label>\n *       </form>\n *       <pre>user.name = <span ng-bind=\"user.name()\"></span></pre>\n *     </div>\n *   </file>\n *   <file name=\"app.js\">\n *     angular.module('getterSetterExample', [])\n *       .controller('ExampleController', ['$scope', function($scope) {\n *         var _name = 'Brian';\n *         $scope.user = {\n *           name: function(newName) {\n *             return angular.isDefined(newName) ? (_name = newName) : _name;\n *           }\n *         };\n *       }]);\n *   </file>\n * </example>\n *\n *\n * ## Programmatically changing options\n *\n * The `ngModelOptions` expression is only evaluated once when the directive is linked; it is not\n * watched for changes. However, it is possible to override the options on a single\n * {@link ngModel.NgModelController} instance with\n * {@link ngModel.NgModelController#$overrideModelOptions `NgModelController#$overrideModelOptions()`}.\n * See also the example for\n * {@link ngModelOptions#default-events-extra-triggers-and-catch-all-debounce-values\n * Default events, extra triggers, and catch-all debounce values}.\n *\n *\n * ## Specifying timezones\n *\n * You can specify the timezone that date/time input directives expect by providing its name in the\n * `timezone` property.\n *\n *\n * ## Formatting the value of `time` and `datetime-local`\n *\n * With the options `timeSecondsFormat` and `timeStripZeroSeconds` it is possible to adjust the value\n * that is displayed in the control. Note that browsers may apply their own formatting\n * in the user interface.\n *\n   <example name=\"ngModelOptions-time-format\" module=\"timeExample\">\n     <file name=\"index.html\">\n       <time-example></time-example>\n     </file>\n     <file name=\"script.js\">\n        angular.module('timeExample', [])\n          .component('timeExample', {\n            templateUrl: 'timeExample.html',\n            controller: function() {\n              this.time = new Date(1970, 0, 1, 14, 57, 0);\n\n              this.options = {\n                timeSecondsFormat: 'ss',\n                timeStripZeroSeconds: true\n              };\n\n              this.optionChange = function() {\n                this.timeForm.timeFormatted.$overrideModelOptions(this.options);\n                this.time = new Date(this.time);\n              };\n            }\n          });\n     </file>\n     <file name=\"timeExample.html\">\n       <form name=\"$ctrl.timeForm\">\n         <strong>Default</strong>:\n         <input type=\"time\" ng-model=\"$ctrl.time\" step=\"any\" /><br>\n         <strong>With options</strong>:\n         <input type=\"time\" name=\"timeFormatted\" ng-model=\"$ctrl.time\" step=\"any\" ng-model-options=\"$ctrl.options\" />\n         <br>\n\n         Options:<br>\n         <code>timeSecondsFormat</code>:\n         <input\n           type=\"text\"\n           ng-model=\"$ctrl.options.timeSecondsFormat\"\n           ng-change=\"$ctrl.optionChange()\">\n         <br>\n         <code>timeStripZeroSeconds</code>:\n         <input\n           type=\"checkbox\"\n           ng-model=\"$ctrl.options.timeStripZeroSeconds\"\n           ng-change=\"$ctrl.optionChange()\">\n        </form>\n      </file>\n *  </example>\n *\n * @param {Object} ngModelOptions options to apply to {@link ngModel} directives on this element and\n *   and its descendents.\n *\n * **General options**:\n *\n *   - `updateOn`: string specifying which event should the input be bound to. You can set several\n *     events using an space delimited list. There is a special event called `default` that\n *     matches the default events belonging to the control. These are the events that are bound to\n *     the control, and when fired, update the `$viewValue` via `$setViewValue`.\n *\n *     `ngModelOptions` considers every event that is not listed in `updateOn` a \"default\" event,\n *     since different control types use different default events.\n *\n *     See also the section {@link ngModelOptions#triggering-and-debouncing-model-updates\n *     Triggering and debouncing model updates}.\n *\n *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A\n *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a\n *     custom value for each event. For example:\n *     ```\n *     ng-model-options=\"{\n *       updateOn: 'default blur',\n *       debounce: { 'default': 500, 'blur': 0 }\n *     }\"\n *     ```\n *     You can use the `*` key to specify a debounce value that applies to all events that are not\n *     specifically listed. In the following example, `mouseup` would have a debounce delay of 1000:\n *     ```\n *     ng-model-options=\"{\n *       updateOn: 'default blur mouseup',\n *       debounce: { 'default': 500, 'blur': 0, '*': 1000 }\n *     }\"\n *     ```\n *   - `allowInvalid`: boolean value which indicates that the model can be set with values that did\n *     not validate correctly instead of the default behavior of setting the model to undefined.\n *   - `getterSetter`: boolean value which determines whether or not to treat functions bound to\n *     `ngModel` as getters/setters.\n *\n *\n *  **Input-type specific options**:\n *\n *   - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for\n *     `<input type=\"date\" />`, `<input type=\"time\" />`, ... . It understands UTC/GMT and the\n *     continental US time zone abbreviations, but for general use, use a time zone offset, for\n *     example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)\n *     If not specified, the timezone of the browser will be used.\n *     Note that changing the timezone will have no effect on the current date, and is only applied after\n *     the next input / model change.\n *\n *   - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and\n *     milliseconds. The option follows the format string of {@link date date filter}.\n *     By default, the options is `undefined` which is equal to `'ss.sss'` (seconds and milliseconds).\n *     The other options are `'ss'` (strips milliseconds), and `''` (empty string), which strips both\n *     seconds and milliseconds.\n *     Note that browsers that support `time` and `datetime-local` require the hour and minutes\n *     part of the time string, and may show the value differently in the user interface.\n *     {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}.\n *\n *   - `timeStripZeroSeconds`: Defines if the `time` and `datetime-local` types should strip the\n *     seconds and milliseconds from the formatted value if they are zero. This option is applied\n *     after `timeSecondsFormat`.\n *     This option can be used to make the formatting consistent over different browsers, as some\n *     browsers with support for `time` will natively hide the milliseconds and\n *     seconds if they are zero, but others won't, and browsers that don't implement these input\n *     types will always show the full string.\n *     {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}.\n *\n */\nvar ngModelOptionsDirective = function() {\n  NgModelOptionsController.$inject = ['$attrs', '$scope'];\n  function NgModelOptionsController($attrs, $scope) {\n    this.$$attrs = $attrs;\n    this.$$scope = $scope;\n  }\n  NgModelOptionsController.prototype = {\n    $onInit: function() {\n      var parentOptions = this.parentCtrl ? this.parentCtrl.$options : defaultModelOptions;\n      var modelOptionsDefinition = this.$$scope.$eval(this.$$attrs.ngModelOptions);\n\n      this.$options = parentOptions.createChild(modelOptionsDefinition);\n    }\n  };\n\n  return {\n    restrict: 'A',\n    // ngModelOptions needs to run before ngModel and input directives\n    priority: 10,\n    require: {parentCtrl: '?^^ngModelOptions'},\n    bindToController: true,\n    controller: NgModelOptionsController\n  };\n};\n\n\n// shallow copy over values from `src` that are not already specified on `dst`\nfunction defaults(dst, src) {\n  forEach(src, function(value, key) {\n    if (!isDefined(dst[key])) {\n      dst[key] = value;\n    }\n  });\n}\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n * @element ANY\n *\n * @description\n * The `ngNonBindable` directive tells AngularJS not to compile or bind the contents of the current\n * DOM element, including directives on the element itself that have a lower priority than\n * `ngNonBindable`. This is useful if the element contains what appears to be AngularJS directives\n * and bindings but which should be ignored by AngularJS. This could be the case if you have a site\n * that displays snippets of code, for instance.\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n  <example name=\"ng-non-bindable\">\n    <file name=\"index.html\">\n      <div>Normal: {{1 + 2}}</div>\n      <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n     it('should check ng-non-bindable', function() {\n       expect(element(by.binding('1 + 2')).getText()).toContain('3');\n       expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n     });\n    </file>\n  </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/* exported ngOptionsDirective */\n\n/* global jqLiteRemove */\n\nvar ngOptionsMinErr = minErr('ngOptions');\n\n/**\n * @ngdoc directive\n * @name ngOptions\n * @restrict A\n *\n * @description\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension expression.\n *\n * In many cases, {@link ng.directive:ngRepeat ngRepeat} can be used on `<option>` elements instead of\n * `ngOptions` to achieve a similar result. However, `ngOptions` provides some benefits:\n * - more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression\n * - reduced memory consumption by not creating a new scope for each repeated instance\n * - increased render speed by creating the options in a documentFragment instead of individually\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * ## Complex Models (objects or collections)\n *\n * By default, `ngModel` watches the model by reference, not value. This is important to know when\n * binding the select to a model that is an object or a collection.\n *\n * One issue occurs if you want to preselect an option. For example, if you set\n * the model to an object that is equal to an object in your collection, `ngOptions` won't be able to set the selection,\n * because the objects are not identical. So by default, you should always reference the item in your collection\n * for preselections, e.g.: `$scope.selected = $scope.collection[3]`.\n *\n * Another solution is to use a `track by` clause, because then `ngOptions` will track the identity\n * of the item not by reference, but by the result of the `track by` expression. For example, if your\n * collection items have an id property, you would `track by item.id`.\n *\n * A different issue with objects or collections is that ngModel won't detect if an object property or\n * a collection item changes. For that reason, `ngOptions` additionally watches the model using\n * `$watchCollection`, when the expression contains a `track by` clause or the the select has the `multiple` attribute.\n * This allows ngOptions to trigger a re-rendering of the options even if the actual object/collection\n * has not changed identity, but only a property on the object or an item in the collection changes.\n *\n * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection\n * if the model is an array). This means that changing a property deeper than the first level inside the\n * object/collection will not trigger a re-rendering.\n *\n * ## `select` **`as`**\n *\n * Using `select` **`as`** will bind the result of the `select` expression to the model, but\n * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)\n * or property name (for object data sources) of the value within the collection. If a **`track by`** expression\n * is used, the result of that expression will be set as the value of the `option` and `select` elements.\n *\n *\n * ### `select` **`as`** and **`track by`**\n *\n * <div class=\"alert alert-warning\">\n * Be careful when using `select` **`as`** and **`track by`** in the same expression.\n * </div>\n *\n * Given this array of items on the $scope:\n *\n * ```js\n * $scope.items = [{\n *   id: 1,\n *   label: 'aLabel',\n *   subItem: { name: 'aSubItem' }\n * }, {\n *   id: 2,\n *   label: 'bLabel',\n *   subItem: { name: 'bSubItem' }\n * }];\n * ```\n *\n * This will work:\n *\n * ```html\n * <select ng-options=\"item as item.label for item in items track by item.id\" ng-model=\"selected\"></select>\n * ```\n * ```js\n * $scope.selected = $scope.items[0];\n * ```\n *\n * but this will not work:\n *\n * ```html\n * <select ng-options=\"item.subItem as item.label for item in items track by item.id\" ng-model=\"selected\"></select>\n * ```\n * ```js\n * $scope.selected = $scope.items[0].subItem;\n * ```\n *\n * In both examples, the **`track by`** expression is applied successfully to each `item` in the\n * `items` array. Because the selected option has been set programmatically in the controller, the\n * **`track by`** expression is also applied to the `ngModel` value. In the first example, the\n * `ngModel` value is `items[0]` and the **`track by`** expression evaluates to `items[0].id` with\n * no issue. In the second example, the `ngModel` value is `items[0].subItem` and the **`track by`**\n * expression evaluates to `items[0].subItem.id` (which is undefined). As a result, the model value\n * is not matched against any `<option>` and the `<select>` appears as having no selected value.\n *\n *\n * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n * @param {comprehension_expression} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`\n *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`\n *        (for including a filter with `track by`)\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`disable when`** `disable`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `disable`: The result of this expression will be used to disable the rendered `<option>`\n *      element. Return `true` to disable.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved\n *      even when the options are recreated (e.g. reloaded from the server).\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngAttrSize sets the size of the select element dynamically. Uses the\n * {@link guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes ngAttr} directive.\n *\n * @example\n    <example module=\"selectExample\" name=\"select\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light', notAnOption: true},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark', notAnOption: true},\n              {name:'yellow', shade:'light', notAnOption: false}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              <label>Name: <input ng-model=\"color.name\"></label>\n              <label><input type=\"checkbox\" ng-model=\"color.notAnOption\"> Disabled?</label>\n              <button ng-click=\"colors.splice($index, 1)\" aria-label=\"Remove\">X</button>\n            </li>\n            <li>\n              <button ng-click=\"colors.push({})\">add</button>\n            </li>\n          </ul>\n          <hr/>\n          <label>Color (null not allowed):\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select>\n          </label><br/>\n          <label>Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span></label><br/>\n\n          <label>Color grouped by shade:\n            <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n            </select>\n          </label><br/>\n\n          <label>Color grouped by shade, with some disabled:\n            <select ng-model=\"myColor\"\n                  ng-options=\"color.name group by color.shade disable when color.notAnOption for color in colors\">\n            </select>\n          </label><br/>\n\n\n\n          Select <button ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</button>.\n          <br/>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor} }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\n/* eslint-disable max-len */\n//                     //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555000000000666666666666600000007777777777777000000000000000888888888800000000000000000009999999999\nvar NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?(?:\\s+disable\\s+when\\s+([\\s\\S]+?))?\\s+for\\s+(?:([$\\w][$\\w]*)|(?:\\(\\s*([$\\w][$\\w]*)\\s*,\\s*([$\\w][$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/;\n                        // 1: value expression (valueFn)\n                        // 2: label expression (displayFn)\n                        // 3: group by expression (groupByFn)\n                        // 4: disable when expression (disableWhenFn)\n                        // 5: array item variable name\n                        // 6: object item key variable name\n                        // 7: object item value variable name\n                        // 8: collection expression\n                        // 9: track by expression\n/* eslint-enable */\n\n\nvar ngOptionsDirective = ['$compile', '$document', '$parse', function($compile, $document, $parse) {\n\n  function parseOptionsExpression(optionsExp, selectElement, scope) {\n\n    var match = optionsExp.match(NG_OPTIONS_REGEXP);\n    if (!(match)) {\n      throw ngOptionsMinErr('iexp',\n        'Expected expression in form of ' +\n        '\\'_select_ (as _label_)? for (_key_,)?_value_ in _collection_\\'' +\n        ' but got \\'{0}\\'. Element: {1}',\n        optionsExp, startingTag(selectElement));\n    }\n\n    // Extract the parts from the ngOptions expression\n\n    // The variable name for the value of the item in the collection\n    var valueName = match[5] || match[7];\n    // The variable name for the key of the item in the collection\n    var keyName = match[6];\n\n    // An expression that generates the viewValue for an option if there is a label expression\n    var selectAs = / as /.test(match[0]) && match[1];\n    // An expression that is used to track the id of each object in the options collection\n    var trackBy = match[9];\n    // An expression that generates the viewValue for an option if there is no label expression\n    var valueFn = $parse(match[2] ? match[1] : valueName);\n    var selectAsFn = selectAs && $parse(selectAs);\n    var viewValueFn = selectAsFn || valueFn;\n    var trackByFn = trackBy && $parse(trackBy);\n\n    // Get the value by which we are going to track the option\n    // if we have a trackFn then use that (passing scope and locals)\n    // otherwise just hash the given viewValue\n    var getTrackByValueFn = trackBy ?\n                              function(value, locals) { return trackByFn(scope, locals); } :\n                              function getHashOfValue(value) { return hashKey(value); };\n    var getTrackByValue = function(value, key) {\n      return getTrackByValueFn(value, getLocals(value, key));\n    };\n\n    var displayFn = $parse(match[2] || match[1]);\n    var groupByFn = $parse(match[3] || '');\n    var disableWhenFn = $parse(match[4] || '');\n    var valuesFn = $parse(match[8]);\n\n    var locals = {};\n    var getLocals = keyName ? function(value, key) {\n      locals[keyName] = key;\n      locals[valueName] = value;\n      return locals;\n    } : function(value) {\n      locals[valueName] = value;\n      return locals;\n    };\n\n\n    function Option(selectValue, viewValue, label, group, disabled) {\n      this.selectValue = selectValue;\n      this.viewValue = viewValue;\n      this.label = label;\n      this.group = group;\n      this.disabled = disabled;\n    }\n\n    function getOptionValuesKeys(optionValues) {\n      var optionValuesKeys;\n\n      if (!keyName && isArrayLike(optionValues)) {\n        optionValuesKeys = optionValues;\n      } else {\n        // if object, extract keys, in enumeration order, unsorted\n        optionValuesKeys = [];\n        for (var itemKey in optionValues) {\n          if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {\n            optionValuesKeys.push(itemKey);\n          }\n        }\n      }\n      return optionValuesKeys;\n    }\n\n    return {\n      trackBy: trackBy,\n      getTrackByValue: getTrackByValue,\n      getWatchables: $parse(valuesFn, function(optionValues) {\n        // Create a collection of things that we would like to watch (watchedArray)\n        // so that they can all be watched using a single $watchCollection\n        // that only runs the handler once if anything changes\n        var watchedArray = [];\n        optionValues = optionValues || [];\n\n        var optionValuesKeys = getOptionValuesKeys(optionValues);\n        var optionValuesLength = optionValuesKeys.length;\n        for (var index = 0; index < optionValuesLength; index++) {\n          var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];\n          var value = optionValues[key];\n\n          var locals = getLocals(value, key);\n          var selectValue = getTrackByValueFn(value, locals);\n          watchedArray.push(selectValue);\n\n          // Only need to watch the displayFn if there is a specific label expression\n          if (match[2] || match[1]) {\n            var label = displayFn(scope, locals);\n            watchedArray.push(label);\n          }\n\n          // Only need to watch the disableWhenFn if there is a specific disable expression\n          if (match[4]) {\n            var disableWhen = disableWhenFn(scope, locals);\n            watchedArray.push(disableWhen);\n          }\n        }\n        return watchedArray;\n      }),\n\n      getOptions: function() {\n\n        var optionItems = [];\n        var selectValueMap = {};\n\n        // The option values were already computed in the `getWatchables` fn,\n        // which must have been called to trigger `getOptions`\n        var optionValues = valuesFn(scope) || [];\n        var optionValuesKeys = getOptionValuesKeys(optionValues);\n        var optionValuesLength = optionValuesKeys.length;\n\n        for (var index = 0; index < optionValuesLength; index++) {\n          var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];\n          var value = optionValues[key];\n          var locals = getLocals(value, key);\n          var viewValue = viewValueFn(scope, locals);\n          var selectValue = getTrackByValueFn(viewValue, locals);\n          var label = displayFn(scope, locals);\n          var group = groupByFn(scope, locals);\n          var disabled = disableWhenFn(scope, locals);\n          var optionItem = new Option(selectValue, viewValue, label, group, disabled);\n\n          optionItems.push(optionItem);\n          selectValueMap[selectValue] = optionItem;\n        }\n\n        return {\n          items: optionItems,\n          selectValueMap: selectValueMap,\n          getOptionFromViewValue: function(value) {\n            return selectValueMap[getTrackByValue(value)];\n          },\n          getViewValueFromOption: function(option) {\n            // If the viewValue could be an object that may be mutated by the application,\n            // we need to make a copy and not return the reference to the value on the option.\n            return trackBy ? copy(option.viewValue) : option.viewValue;\n          }\n        };\n      }\n    };\n  }\n\n\n  // Support: IE 9 only\n  // We can't just jqLite('<option>') since jqLite is not smart enough\n  // to create it in <select> and IE barfs otherwise.\n  var optionTemplate = window.document.createElement('option'),\n      optGroupTemplate = window.document.createElement('optgroup');\n\n    function ngOptionsPostLink(scope, selectElement, attr, ctrls) {\n\n      var selectCtrl = ctrls[0];\n      var ngModelCtrl = ctrls[1];\n      var multiple = attr.multiple;\n\n      // The emptyOption allows the application developer to provide their own custom \"empty\"\n      // option when the viewValue does not match any of the option values.\n      for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          selectCtrl.hasEmptyOption = true;\n          selectCtrl.emptyOption = children.eq(i);\n          break;\n        }\n      }\n\n      // The empty option will be compiled and rendered before we first generate the options\n      selectElement.empty();\n\n      var providedEmptyOption = !!selectCtrl.emptyOption;\n\n      var unknownOption = jqLite(optionTemplate.cloneNode(false));\n      unknownOption.val('?');\n\n      var options;\n      var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);\n      // This stores the newly created options before they are appended to the select.\n      // Since the contents are removed from the fragment when it is appended,\n      // we only need to create it once.\n      var listFragment = $document[0].createDocumentFragment();\n\n      // Overwrite the implementation. ngOptions doesn't use hashes\n      selectCtrl.generateUnknownOptionValue = function(val) {\n        return '?';\n      };\n\n      // Update the controller methods for multiple selectable options\n      if (!multiple) {\n\n        selectCtrl.writeValue = function writeNgOptionsValue(value) {\n          // The options might not be defined yet when ngModel tries to render\n          if (!options) return;\n\n          var selectedOption = selectElement[0].options[selectElement[0].selectedIndex];\n          var option = options.getOptionFromViewValue(value);\n\n          // Make sure to remove the selected attribute from the previously selected option\n          // Otherwise, screen readers might get confused\n          if (selectedOption) selectedOption.removeAttribute('selected');\n\n          if (option) {\n            // Don't update the option when it is already selected.\n            // For example, the browser will select the first option by default. In that case,\n            // most properties are set automatically - except the `selected` attribute, which we\n            // set always\n\n            if (selectElement[0].value !== option.selectValue) {\n              selectCtrl.removeUnknownOption();\n\n              selectElement[0].value = option.selectValue;\n              option.element.selected = true;\n            }\n\n            option.element.setAttribute('selected', 'selected');\n          } else {\n            selectCtrl.selectUnknownOrEmptyOption(value);\n          }\n        };\n\n        selectCtrl.readValue = function readNgOptionsValue() {\n\n          var selectedOption = options.selectValueMap[selectElement.val()];\n\n          if (selectedOption && !selectedOption.disabled) {\n            selectCtrl.unselectEmptyOption();\n            selectCtrl.removeUnknownOption();\n            return options.getViewValueFromOption(selectedOption);\n          }\n          return null;\n        };\n\n        // If we are using `track by` then we must watch the tracked value on the model\n        // since ngModel only watches for object identity change\n        // FIXME: When a user selects an option, this watch will fire needlessly\n        if (ngOptions.trackBy) {\n          scope.$watch(\n            function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },\n            function() { ngModelCtrl.$render(); }\n          );\n        }\n\n      } else {\n\n        selectCtrl.writeValue = function writeNgOptionsMultiple(values) {\n          // The options might not be defined yet when ngModel tries to render\n          if (!options) return;\n\n          // Only set `<option>.selected` if necessary, in order to prevent some browsers from\n          // scrolling to `<option>` elements that are outside the `<select>` element's viewport.\n          var selectedOptions = values && values.map(getAndUpdateSelectedOption) || [];\n\n          options.items.forEach(function(option) {\n            if (option.element.selected && !includes(selectedOptions, option)) {\n              option.element.selected = false;\n            }\n          });\n        };\n\n\n        selectCtrl.readValue = function readNgOptionsMultiple() {\n          var selectedValues = selectElement.val() || [],\n              selections = [];\n\n          forEach(selectedValues, function(value) {\n            var option = options.selectValueMap[value];\n            if (option && !option.disabled) selections.push(options.getViewValueFromOption(option));\n          });\n\n          return selections;\n        };\n\n        // If we are using `track by` then we must watch these tracked values on the model\n        // since ngModel only watches for object identity change\n        if (ngOptions.trackBy) {\n\n          scope.$watchCollection(function() {\n            if (isArray(ngModelCtrl.$viewValue)) {\n              return ngModelCtrl.$viewValue.map(function(value) {\n                return ngOptions.getTrackByValue(value);\n              });\n            }\n          }, function() {\n            ngModelCtrl.$render();\n          });\n\n        }\n      }\n\n      if (providedEmptyOption) {\n\n        // compile the element since there might be bindings in it\n        $compile(selectCtrl.emptyOption)(scope);\n\n        selectElement.prepend(selectCtrl.emptyOption);\n\n        if (selectCtrl.emptyOption[0].nodeType === NODE_TYPE_COMMENT) {\n          // This means the empty option has currently no actual DOM node, probably because\n          // it has been modified by a transclusion directive.\n          selectCtrl.hasEmptyOption = false;\n\n          // Redefine the registerOption function, which will catch\n          // options that are added by ngIf etc. (rendering of the node is async because of\n          // lazy transclusion)\n          selectCtrl.registerOption = function(optionScope, optionEl) {\n            if (optionEl.val() === '') {\n              selectCtrl.hasEmptyOption = true;\n              selectCtrl.emptyOption = optionEl;\n              selectCtrl.emptyOption.removeClass('ng-scope');\n              // This ensures the new empty option is selected if previously no option was selected\n              ngModelCtrl.$render();\n\n              optionEl.on('$destroy', function() {\n                var needsRerender = selectCtrl.$isEmptyOptionSelected();\n\n                selectCtrl.hasEmptyOption = false;\n                selectCtrl.emptyOption = undefined;\n\n                if (needsRerender) ngModelCtrl.$render();\n              });\n            }\n          };\n\n        } else {\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          selectCtrl.emptyOption.removeClass('ng-scope');\n        }\n\n      }\n\n      // We will re-render the option elements if the option values or labels change\n      scope.$watchCollection(ngOptions.getWatchables, updateOptions);\n\n      // ------------------------------------------------------------------ //\n\n      function addOptionElement(option, parent) {\n        var optionElement = optionTemplate.cloneNode(false);\n        parent.appendChild(optionElement);\n        updateOptionElement(option, optionElement);\n      }\n\n      function getAndUpdateSelectedOption(viewValue) {\n        var option = options.getOptionFromViewValue(viewValue);\n        var element = option && option.element;\n\n        if (element && !element.selected) element.selected = true;\n\n        return option;\n      }\n\n      function updateOptionElement(option, element) {\n        option.element = element;\n        element.disabled = option.disabled;\n        // Support: IE 11 only, Edge 12-13 only\n        // NOTE: The label must be set before the value, otherwise IE 11 & Edge create unresponsive\n        // selects in certain circumstances when multiple selects are next to each other and display\n        // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].\n        // See https://github.com/angular/angular.js/issues/11314 for more info.\n        // This is unfortunately untestable with unit / e2e tests\n        if (option.label !== element.label) {\n          element.label = option.label;\n          element.textContent = option.label;\n        }\n        element.value = option.selectValue;\n      }\n\n      function updateOptions() {\n        var previousValue = options && selectCtrl.readValue();\n\n        // We must remove all current options, but cannot simply set innerHTML = null\n        // since the providedEmptyOption might have an ngIf on it that inserts comments which we\n        // must preserve.\n        // Instead, iterate over the current option elements and remove them or their optgroup\n        // parents\n        if (options) {\n\n          for (var i = options.items.length - 1; i >= 0; i--) {\n            var option = options.items[i];\n            if (isDefined(option.group)) {\n              jqLiteRemove(option.element.parentNode);\n            } else {\n              jqLiteRemove(option.element);\n            }\n          }\n        }\n\n        options = ngOptions.getOptions();\n\n        var groupElementMap = {};\n\n        options.items.forEach(function addOption(option) {\n          var groupElement;\n\n          if (isDefined(option.group)) {\n\n            // This option is to live in a group\n            // See if we have already created this group\n            groupElement = groupElementMap[option.group];\n\n            if (!groupElement) {\n\n              groupElement = optGroupTemplate.cloneNode(false);\n              listFragment.appendChild(groupElement);\n\n              // Update the label on the group element\n              // \"null\" is special cased because of Safari\n              groupElement.label = option.group === null ? 'null' : option.group;\n\n              // Store it for use later\n              groupElementMap[option.group] = groupElement;\n            }\n\n            addOptionElement(option, groupElement);\n\n          } else {\n\n            // This option is not in a group\n            addOptionElement(option, listFragment);\n          }\n        });\n\n        selectElement[0].appendChild(listFragment);\n\n        ngModelCtrl.$render();\n\n        // Check to see if the value has changed due to the update to the options\n        if (!ngModelCtrl.$isEmpty(previousValue)) {\n          var nextValue = selectCtrl.readValue();\n          var isNotPrimitive = ngOptions.trackBy || multiple;\n          if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {\n            ngModelCtrl.$setViewValue(nextValue);\n            ngModelCtrl.$render();\n          }\n        }\n      }\n  }\n\n  return {\n    restrict: 'A',\n    terminal: true,\n    require: ['select', 'ngModel'],\n    link: {\n      pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {\n        // Deactivate the SelectController.register method to prevent\n        // option directives from accidentally registering themselves\n        // (and unwanted $destroy handlers etc.)\n        ctrls[0].registerOption = noop;\n      },\n      post: ngOptionsPostLink\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n AngularJS i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * ## Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in AngularJS's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * ## Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * AngularJS expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, AngularJS will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * If no rule is defined for a category, then an empty string is displayed and a warning is generated.\n * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`.\n *\n * ## Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and AngularJS uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\" name=\"ng-pluralize\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <label>Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /></label><br/>\n          <label>Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /></label><br/>\n          <label>Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /></label><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {\n  var BRACE = /{}/g,\n      IS_WHEN = /^when(Minus)?(.+)$/;\n\n  return {\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n          watchRemover = angular.noop,\n          lastCount;\n\n      forEach(attr, function(expression, attributeName) {\n        var tmpMatch = IS_WHEN.exec(attributeName);\n        if (tmpMatch) {\n          var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n          whens[whenKey] = element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\n      });\n\n      scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n        var count = parseFloat(newVal);\n        var countIsNaN = isNumberNaN(count);\n\n        if (!countIsNaN && !(count in whens)) {\n          // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n          // Otherwise, check it against pluralization rules in $locale service.\n          count = $locale.pluralCat(count - offset);\n        }\n\n        // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n        // In JS `NaN !== NaN`, so we have to explicitly check.\n        if ((count !== lastCount) && !(countIsNaN && isNumberNaN(lastCount))) {\n          watchRemover();\n          var whenExpFn = whensExpFns[count];\n          if (isUndefined(whenExpFn)) {\n            if (newVal != null) {\n              $log.debug('ngPluralize: no rule defined for \\'' + count + '\\' in ' + whenExp);\n            }\n            watchRemover = noop;\n            updateElementText();\n          } else {\n            watchRemover = scope.$watch(whenExpFn, updateElementText);\n          }\n          lastCount = count;\n        }\n      });\n\n      function updateElementText(newText) {\n        element.text(newText || '');\n      }\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRef\n * @restrict A\n *\n * @description\n * The `ngRef` attribute tells AngularJS to assign the controller of a component (or a directive)\n * to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM\n * element to the scope.\n *\n * If the element with `ngRef` is destroyed `null` is assigned to the property.\n *\n * Note that if you want to assign from a child into the parent scope, you must initialize the\n * target property on the parent scope, otherwise `ngRef` will assign on the child scope.\n * This commonly happens when assigning elements or components wrapped in {@link ngIf} or\n * {@link ngRepeat}. See the second example below.\n *\n *\n * @element ANY\n * @param {string} ngRef property name - A valid AngularJS expression identifier to which the\n *                       controller or jqlite-wrapped DOM element will be bound.\n * @param {string=} ngRefRead read value - The name of a directive (or component) on this element,\n *                            or the special string `$element`. If a name is provided, `ngRef` will\n *                            assign the matching controller. If `$element` is provided, the element\n *                            itself is assigned (even if a controller is available).\n *\n *\n * @example\n * ### Simple toggle\n * This example shows how the controller of the component toggle\n * is reused in the template through the scope to use its logic.\n * <example name=\"ng-ref-component\" module=\"myApp\">\n *   <file name=\"index.html\">\n *     <my-toggle ng-ref=\"myToggle\"></my-toggle>\n *     <button ng-click=\"myToggle.toggle()\">Toggle</button>\n *     <div ng-show=\"myToggle.isOpen()\">\n *       You are using a component in the same template to show it.\n *     </div>\n *   </file>\n *   <file name=\"index.js\">\n *     angular.module('myApp', [])\n *     .component('myToggle', {\n *       controller: function ToggleController() {\n *         var opened = false;\n *         this.isOpen = function() { return opened; };\n *         this.toggle = function() { opened = !opened; };\n *       }\n *     });\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *      it('should publish the toggle into the scope', function() {\n *        var toggle = element(by.buttonText('Toggle'));\n *        expect(toggle.evaluate('myToggle.isOpen()')).toEqual(false);\n *        toggle.click();\n *        expect(toggle.evaluate('myToggle.isOpen()')).toEqual(true);\n *      });\n *   </file>\n * </example>\n *\n * @example\n * ### ngRef inside scopes\n * This example shows how `ngRef` works with child scopes. The `ngRepeat`-ed `myWrapper` components\n * are assigned to the scope of `myRoot`, because the `toggles` property has been initialized.\n * The repeated `myToggle` components are published to the child scopes created by `ngRepeat`.\n * `ngIf` behaves similarly - the assignment of `myToggle` happens in the `ngIf` child scope,\n * because the target property has not been initialized on the `myRoot` component controller.\n *\n * <example name=\"ng-ref-scopes\" module=\"myApp\">\n *   <file name=\"index.html\">\n *     <my-root></my-root>\n *   </file>\n *   <file name=\"index.js\">\n *     angular.module('myApp', [])\n *     .component('myRoot', {\n *       templateUrl: 'root.html',\n *       controller: function() {\n *         this.wrappers = []; // initialize the array so that the wrappers are assigned into the parent scope\n *       }\n *     })\n *     .component('myToggle', {\n *       template: '<strong>myToggle</strong><button ng-click=\"$ctrl.toggle()\" ng-transclude></button>',\n *       transclude: true,\n *       controller: function ToggleController() {\n *         var opened = false;\n *         this.isOpen = function() { return opened; };\n *         this.toggle = function() { opened = !opened; };\n *       }\n *     })\n *     .component('myWrapper', {\n *       transclude: true,\n *       template: '<strong>myWrapper</strong>' +\n *         '<div>ngRepeatToggle.isOpen(): {{$ctrl.ngRepeatToggle.isOpen() | json}}</div>' +\n *         '<my-toggle ng-ref=\"$ctrl.ngRepeatToggle\"><ng-transclude></ng-transclude></my-toggle>'\n *     });\n *   </file>\n *   <file name=\"root.html\">\n *     <strong>myRoot</strong>\n *     <my-toggle ng-ref=\"$ctrl.outerToggle\">Outer Toggle</my-toggle>\n *     <div>outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}</div>\n *     <div><em>wrappers assigned to root</em><br>\n *     <div ng-repeat=\"wrapper in $ctrl.wrappers\">\n *       wrapper.ngRepeatToggle.isOpen(): {{wrapper.ngRepeatToggle.isOpen() | json}}\n *     </div>\n *\n *     <ul>\n *       <li ng-repeat=\"(index, value) in [1,2,3]\">\n *         <strong>ngRepeat</strong>\n *         <div>outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}</div>\n *         <my-wrapper ng-ref=\"$ctrl.wrappers[index]\">ngRepeat Toggle {{$index + 1}}</my-wrapper>\n *       </li>\n *     </ul>\n *\n *     <div>ngIfToggle.isOpen(): {{ngIfToggle.isOpen()}} // This is always undefined because it's\n *       assigned to the child scope created by ngIf.\n *     </div>\n *     <div ng-if=\"true\">\n          <strong>ngIf</strong>\n *        <my-toggle ng-ref=\"ngIfToggle\">ngIf Toggle</my-toggle>\n *        <div>ngIfToggle.isOpen(): {{ngIfToggle.isOpen() | json}}</div>\n *        <div>outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}</div>\n *     </div>\n *   </file>\n *   <file name=\"styles.css\">\n *     ul {\n *       list-style: none;\n *       padding-left: 0;\n *     }\n *\n *     li[ng-repeat] {\n *       background: lightgreen;\n *       padding: 8px;\n *       margin: 8px;\n *     }\n *\n *     [ng-if] {\n *       background: lightgrey;\n *       padding: 8px;\n *     }\n *\n *     my-root {\n *       background: lightgoldenrodyellow;\n *       padding: 8px;\n *       display: block;\n *     }\n *\n *     my-wrapper {\n *       background: lightsalmon;\n *       padding: 8px;\n *       display: block;\n *     }\n *\n *     my-toggle {\n *       background: lightblue;\n *       padding: 8px;\n *       display: block;\n *     }\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *      var OuterToggle = function() {\n *        this.toggle = function() {\n *          element(by.buttonText('Outer Toggle')).click();\n *        };\n *        this.isOpen = function() {\n *          return element.all(by.binding('outerToggle.isOpen()')).first().getText();\n *        };\n *      };\n *      var NgRepeatToggle = function(i) {\n *        var parent = element.all(by.repeater('(index, value) in [1,2,3]')).get(i - 1);\n *        this.toggle = function() {\n *          element(by.buttonText('ngRepeat Toggle ' + i)).click();\n *        };\n *        this.isOpen = function() {\n *          return parent.element(by.binding('ngRepeatToggle.isOpen() | json')).getText();\n *        };\n *        this.isOuterOpen = function() {\n *          return parent.element(by.binding('outerToggle.isOpen() | json')).getText();\n *        };\n *      };\n *      var NgRepeatToggles = function() {\n *        var toggles = [1,2,3].map(function(i) { return new NgRepeatToggle(i); });\n *        this.forEach = function(fn) {\n *          toggles.forEach(fn);\n *        };\n *        this.isOuterOpen = function(i) {\n *          return toggles[i - 1].isOuterOpen();\n *        };\n *      };\n *      var NgIfToggle = function() {\n *        var parent = element(by.css('[ng-if]'));\n *        this.toggle = function() {\n *          element(by.buttonText('ngIf Toggle')).click();\n *        };\n *        this.isOpen = function() {\n *          return by.binding('ngIfToggle.isOpen() | json').getText();\n *        };\n *        this.isOuterOpen = function() {\n *          return parent.element(by.binding('outerToggle.isOpen() | json')).getText();\n *        };\n *      };\n *\n *      it('should toggle the outer toggle', function() {\n *        var outerToggle = new OuterToggle();\n *        expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false');\n *        outerToggle.toggle();\n *        expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true');\n *      });\n *\n *      it('should toggle all outer toggles', function() {\n *        var outerToggle = new OuterToggle();\n *        var repeatToggles = new NgRepeatToggles();\n *        var ifToggle = new NgIfToggle();\n *        expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false');\n *        expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): false');\n *        expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): false');\n *        expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): false');\n *        expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false');\n *        outerToggle.toggle();\n *        expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true');\n *        expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): true');\n *        expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): true');\n *        expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): true');\n *        expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): true');\n *      });\n *\n *      it('should toggle each repeat iteration separately', function() {\n *        var repeatToggles = new NgRepeatToggles();\n *\n *        repeatToggles.forEach(function(repeatToggle) {\n *          expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): false');\n *          expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false');\n *          repeatToggle.toggle();\n *          expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): true');\n *          expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false');\n *        });\n *      });\n *   </file>\n * </example>\n *\n */\n\nvar ngRefMinErr = minErr('ngRef');\n\nvar ngRefDirective = ['$parse', function($parse) {\n  return {\n    priority: -1, // Needed for compatibility with element transclusion on the same element\n    restrict: 'A',\n    compile: function(tElement, tAttrs) {\n      // Get the expected controller name, converts <data-some-thing> into \"someThing\"\n      var controllerName = directiveNormalize(nodeName_(tElement));\n\n      // Get the expression for value binding\n      var getter = $parse(tAttrs.ngRef);\n      var setter = getter.assign || function() {\n        throw ngRefMinErr('nonassign', 'Expression in ngRef=\"{0}\" is non-assignable!', tAttrs.ngRef);\n      };\n\n      return function(scope, element, attrs) {\n        var refValue;\n\n        if (attrs.hasOwnProperty('ngRefRead')) {\n          if (attrs.ngRefRead === '$element') {\n            refValue = element;\n          } else {\n            refValue = element.data('$' + attrs.ngRefRead + 'Controller');\n\n            if (!refValue) {\n              throw ngRefMinErr(\n                'noctrl',\n                'The controller for ngRefRead=\"{0}\" could not be found on ngRef=\"{1}\"',\n                attrs.ngRefRead,\n                tAttrs.ngRef\n              );\n            }\n          }\n        } else {\n          refValue = element.data('$' + controllerName + 'Controller');\n        }\n\n        refValue = refValue || element;\n\n        setter(scope, refValue);\n\n        // when the element is removed, remove it (nullify it)\n        element.on('$destroy', function() {\n          // only remove it if value has not changed,\n          // because animations (and other procedures) may duplicate elements\n          if (getter(scope) === refValue) {\n            setter(scope, null);\n          }\n        });\n      };\n    }\n  };\n}];\n\n/* exported ngRepeatDirective */\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n * @multiElement\n * @restrict A\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * <div class=\"alert alert-info\">\n *   Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n *   This may be useful when, for instance, nesting ngRepeats.\n * </div>\n *\n *\n * ## Iterating over object properties\n *\n * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n * syntax:\n *\n * ```js\n * <div ng-repeat=\"(key, value) in myObj\"> ... </div>\n * ```\n *\n * However, there are a few limitations compared to array iteration:\n *\n * - The JavaScript specification does not define the order of keys\n *   returned for an object, so AngularJS relies on the order returned by the browser\n *   when running `for key in myObj`. Browsers generally follow the strategy of providing\n *   keys in the order in which they were defined, although there are exceptions when keys are deleted\n *   and reinstated. See the\n *   [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).\n *\n * - `ngRepeat` will silently *ignore* object keys starting with `$`, because\n *   it's a prefix used by AngularJS for public (`$`) and private (`$$`) properties.\n *\n * - The built-in filters {@link ng.orderBy orderBy} and {@link ng.filter filter} do not work with\n *   objects, and will throw an error if used with one.\n *\n * If you are hitting any of these limitations, the recommended workaround is to convert your object into an array\n * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could\n * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n * or implement a `$watch` on the object yourself.\n *\n *\n * ## Tracking and Duplicates\n *\n * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in\n * the collection. When a change happens, `ngRepeat` then makes the corresponding changes to the DOM:\n *\n * * When an item is added, a new instance of the template is added to the DOM.\n * * When an item is removed, its template instance is removed from the DOM.\n * * When items are reordered, their respective templates are reordered in the DOM.\n *\n * To minimize creation of DOM elements, `ngRepeat` uses a function\n * to \"keep track\" of all items in the collection and their corresponding DOM elements.\n * For example, if an item is added to the collection, `ngRepeat` will know that all other items\n * already have DOM elements, and will not re-render them.\n *\n * All different types of tracking functions, their syntax, and their support for duplicate\n * items in collections can be found in the\n * {@link ngRepeat#ngRepeat-arguments ngRepeat expression description}.\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** If you are working with objects that have a unique identifier property, you\n * should track by this identifier instead of the object instance,\n * e.g. `item in items track by item.id`.\n * Should you reload your data later, `ngRepeat` will not have to rebuild the DOM elements for items\n * it has already rendered, even if the JavaScript objects in the collection have been substituted\n * for new ones. For large collections, this significantly improves rendering performance.\n * </div>\n *\n * ### Effects of DOM Element re-use\n *\n * When DOM elements are re-used, ngRepeat updates the scope for the element, which will\n * automatically update any active bindings on the template. However, other\n * functionality will not be updated, because the element is not re-created:\n *\n * - Directives are not re-compiled\n * - {@link guide/expression#one-time-binding one-time expressions} on the repeated template are not\n * updated if they have stabilized.\n *\n * The above affects all kinds of element re-use due to tracking, but may be especially visible\n * when tracking by `$index` due to the way ngRepeat re-uses elements.\n *\n * The following example shows the effects of different actions with tracking:\n\n  <example module=\"ngRepeat\" name=\"ngRepeat-tracking\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"script.js\">\n      angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {\n        var friends = [\n          {name:'John', age:25},\n          {name:'Mary', age:40},\n          {name:'Peter', age:85}\n        ];\n\n        $scope.removeFirst = function() {\n          $scope.friends.shift();\n        };\n\n        $scope.updateAge = function() {\n          $scope.friends.forEach(function(el) {\n            el.age = el.age + 5;\n          });\n        };\n\n        $scope.copy = function() {\n          $scope.friends = angular.copy($scope.friends);\n        };\n\n        $scope.reset = function() {\n          $scope.friends = angular.copy(friends);\n        };\n\n        $scope.reset();\n      });\n    </file>\n    <file name=\"index.html\">\n      <div ng-controller=\"repeatController\">\n        <ol>\n          <li>When you click \"Update Age\", only the first list updates the age, because all others have\n          a one-time binding on the age property. If you then click \"Copy\", the current friend list\n          is copied, and now the second list updates the age, because the identity of the collection items\n          has changed and the list must be re-rendered. The 3rd and 4th list stay the same, because all the\n          items are already known according to their tracking functions.\n          </li>\n          <li>When you click \"Remove First\", the 4th list has the wrong age on both remaining items. This is\n          due to tracking by $index: when the first collection item is removed, ngRepeat reuses the first\n          DOM element for the new first collection item, and so on. Since the age property is one-time\n          bound, the value remains from the collection item which was previously at this index.\n          </li>\n        </ol>\n\n        <button ng-click=\"removeFirst()\">Remove First</button>\n        <button ng-click=\"updateAge()\">Update Age</button>\n        <button ng-click=\"copy()\">Copy</button>\n        <br><button ng-click=\"reset()\">Reset List</button>\n        <br>\n        <code>track by $id(friend)</code> (default):\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends\">\n            {{friend.name}} is {{friend.age}} years old.\n          </li>\n        </ul>\n        <code>track by $id(friend)</code> (default), with age one-time binding:\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends\">\n            {{friend.name}} is {{::friend.age}} years old.\n          </li>\n        </ul>\n        <code>track by friend.name</code>, with age one-time binding:\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends track by friend.name\">\n            {{friend.name}}  is {{::friend.age}} years old.\n          </li>\n        </ul>\n        <code>track by $index</code>, with age one-time binding:\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends track by $index\">\n            {{friend.name}} is {{::friend.age}} years old.\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:30px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:30px;\n      }\n    </file>\n  </example>\n\n *\n * ## Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#enter enter} | when a new item is added to the list or when an item is revealed after a filter |\n * | {@link ng.$animate#leave leave} | when an item is removed from the list or when an item is filtered out |\n * | {@link ng.$animate#move move } | when an adjacent item is filtered out causing a reorder or when the item contents are reordered |\n *\n * See the example below for defining CSS animations with ngRepeat.\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking expression\n *     is specified, ng-repeat associates elements by identity. It is an error to have\n *     more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)\n *\n *     *Default tracking: $id()*: `item in items` is equivalent to `item in items track by $id(item)`.\n *     This implies that the DOM elements will be associated by item identity in the collection.\n *\n *     The built-in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the collection. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the collection by identity. Moving the same object would move\n *     the DOM element in the same way in the DOM.\n *     Note that the default id function does not support duplicate primitive values (`number`, `string`),\n *     but supports duplictae non-primitive values (`object`) that are *equal* in shape.\n *\n *     *Custom Expression*: It is possible to use any AngularJS expression to compute the tracking\n *     id, for example with a function, or using a property on the collection items.\n *     `item in items track by item.id` is a typical pattern when the items have a unique identifier,\n *     e.g. database id. In this case the object identity does not matter. Two objects are considered\n *     equivalent as long as their `id` property is same.\n *     Tracking by unique identifier is the most performant way and should be used whenever possible.\n *\n *     *$index*: This special property tracks the collection items by their index, and\n *     re-uses the DOM elements that match that index, e.g. `item in items track by $index`. This can\n *     be used for a performance improvement if no unique identfier is available and the identity of\n *     the collection items cannot be easily computed. It also allows duplicates.\n *\n *     <div class=\"alert alert-warning\">\n *       <strong>Note:</strong> Re-using DOM elements can have unforeseen effects. Read the\n *       {@link ngRepeat#tracking-and-duplicates section on tracking and duplicates} for\n *       more info.\n *     </div>\n *\n *     <div class=\"alert alert-warning\">\n *       <strong>Note:</strong> the `track by` expression must come last - after any filters, and the alias expression:\n *       `item in items | filter:searchText as results  track by item.id`\n *     </div>\n *\n *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n *     when a filter is active on the repeater, but the filtered result set is empty.\n *\n *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n *     the items have been processed through the filter.\n *\n *     Please note that `as [variable name]` is not an operator but rather a part of ngRepeat\n *     micro-syntax so it can be used only after all filters (and not as operator, inside an expression).\n *\n *     For example: `item in items | filter : x | orderBy : order | limitTo : limit as results track by item.id` .\n *\n * @example\n * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed\n * results by name or by age. New (entering) and removed (leaving) items are animated.\n  <example module=\"ngRepeat\" name=\"ngRepeat\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"repeatController\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" aria-label=\"filter friends\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q as results track by friend.name\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n          <li class=\"animate-repeat\" ng-if=\"results.length === 0\">\n            <strong>No results found...</strong>\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {\n        $scope.friends = [\n          {name:'John', age:25, gender:'boy'},\n          {name:'Jessie', age:30, gender:'girl'},\n          {name:'Johanna', age:28, gender:'girl'},\n          {name:'Joy', age:15, gender:'girl'},\n          {name:'Mary', age:28, gender:'girl'},\n          {name:'Peter', age:95, gender:'boy'},\n          {name:'Sebastian', age:50, gender:'boy'},\n          {name:'Erika', age:27, gender:'girl'},\n          {name:'Patrick', age:40, gender:'boy'},\n          {name:'Samantha', age:60, gender:'girl'}\n        ];\n      });\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:30px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:30px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $animate, $compile) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n\n  var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n    // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n    scope[valueIdentifier] = value;\n    if (keyIdentifier) scope[keyIdentifier] = key;\n    scope.$index = index;\n    scope.$first = (index === 0);\n    scope.$last = (index === (arrayLength - 1));\n    scope.$middle = !(scope.$first || scope.$last);\n    // eslint-disable-next-line no-bitwise\n    scope.$odd = !(scope.$even = (index & 1) === 0);\n  };\n\n  var getBlockStart = function(block) {\n    return block.clone[0];\n  };\n\n  var getBlockEnd = function(block) {\n    return block.clone[block.clone.length - 1];\n  };\n\n  var trackByIdArrayFn = function($scope, key, value) {\n    return hashKey(value);\n  };\n\n  var trackByIdObjFn = function($scope, key) {\n    return key;\n  };\n\n  return {\n    restrict: 'A',\n    multiElement: true,\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    compile: function ngRepeatCompile($element, $attr) {\n      var expression = $attr.ngRepeat;\n      var ngRepeatEndComment = $compile.$$createComment('end ngRepeat', expression);\n\n      var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iexp', 'Expected expression in form of \\'_item_ in _collection_[ track by _id_]\\' but got \\'{0}\\'.',\n            expression);\n      }\n\n      var lhs = match[1];\n      var rhs = match[2];\n      var aliasAs = match[3];\n      var trackByExp = match[4];\n\n      match = lhs.match(/^(?:(\\s*[$\\w]+)|\\(\\s*([$\\w]+)\\s*,\\s*([$\\w]+)\\s*\\))$/);\n\n      if (!match) {\n        throw ngRepeatMinErr('iidexp', '\\'_item_\\' in \\'_item_ in _collection_\\' should be an identifier or \\'(_key_, _value_)\\' expression, but got \\'{0}\\'.',\n            lhs);\n      }\n      var valueIdentifier = match[3] || match[1];\n      var keyIdentifier = match[2];\n\n      if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n          /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n        throw ngRepeatMinErr('badident', 'alias \\'{0}\\' is invalid --- must be a valid JS identifier which is not a reserved name.',\n          aliasAs);\n      }\n\n      var trackByIdExpFn;\n\n      if (trackByExp) {\n        var hashFnLocals = {$id: hashKey};\n        var trackByExpGetter = $parse(trackByExp);\n\n        trackByIdExpFn = function($scope, key, value, index) {\n          // assign key, value, and $index to the locals so that they can be used in hash functions\n          if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n          hashFnLocals[valueIdentifier] = value;\n          hashFnLocals.$index = index;\n          return trackByExpGetter($scope, hashFnLocals);\n        };\n      }\n\n      return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - clone: previous element.\n        //   - index: position\n        //\n        // We are using no-proto object so that we don't need to guard against inherited props via\n        // hasOwnProperty.\n        var lastBlockMap = createMap();\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n          var index, length,\n              previousNode = $element[0],     // node that cloned nodes should be inserted after\n                                              // initialized to the comment node anchor\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = createMap(),\n              collectionLength,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder,\n              elementsToRemove;\n\n          if (aliasAs) {\n            $scope[aliasAs] = collection;\n          }\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, in enumeration order, unsorted\n            collectionKeys = [];\n            for (var itemKey in collection) {\n              if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {\n                collectionKeys.push(itemKey);\n              }\n            }\n          }\n\n          collectionLength = collectionKeys.length;\n          nextBlockOrder = new Array(collectionLength);\n\n          // locate existing items\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            trackById = trackByIdFn($scope, key, value, index);\n            if (lastBlockMap[trackById]) {\n              // found previously seen block\n              block = lastBlockMap[trackById];\n              delete lastBlockMap[trackById];\n              nextBlockMap[trackById] = block;\n              nextBlockOrder[index] = block;\n            } else if (nextBlockMap[trackById]) {\n              // if collision detected. restore lastBlockMap and throw an error\n              forEach(nextBlockOrder, function(block) {\n                if (block && block.scope) lastBlockMap[block.id] = block;\n              });\n              throw ngRepeatMinErr('dupes',\n                  'Duplicates in a repeater are not allowed. Use \\'track by\\' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}',\n                  expression, trackById, value);\n            } else {\n              // new never before seen block\n              nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n              nextBlockMap[trackById] = true;\n            }\n          }\n\n          // Clear the value property from the hashFnLocals object to prevent a reference to the last value\n          // being leaked into the ngRepeatCompile function scope\n          if (hashFnLocals) {\n            hashFnLocals[valueIdentifier] = undefined;\n          }\n\n          // remove leftover items\n          for (var blockKey in lastBlockMap) {\n            block = lastBlockMap[blockKey];\n            elementsToRemove = getBlockNodes(block.clone);\n            $animate.leave(elementsToRemove);\n            if (elementsToRemove[0].parentNode) {\n              // if the element was not removed yet because of pending animation, mark it as deleted\n              // so that we can ignore it later\n              for (index = 0, length = elementsToRemove.length; index < length; index++) {\n                elementsToRemove[index][NG_REMOVED] = true;\n              }\n            }\n            block.scope.$destroy();\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0; index < collectionLength; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n\n              nextNode = previousNode;\n\n              // skip nodes that are already pending removal via leave animation\n              do {\n                nextNode = nextNode.nextSibling;\n              } while (nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) !== nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockNodes(block.clone), null, previousNode);\n              }\n              previousNode = getBlockEnd(block);\n              updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n            } else {\n              // new item which we don't know about\n              $transclude(function ngRepeatTransclude(clone, scope) {\n                block.scope = scope;\n                // http://jsperf.com/clone-vs-createcomment\n                var endNode = ngRepeatEndComment.cloneNode(false);\n                clone[clone.length++] = endNode;\n\n                $animate.enter(clone, null, previousNode);\n                previousNode = endNode;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n                updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n      };\n    }\n  };\n}];\n\nvar NG_HIDE_CLASS = 'ng-hide';\nvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n/**\n * @ngdoc directive\n * @name ngShow\n * @multiElement\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression provided to\n * the `ngShow` attribute.\n *\n * The element is shown or hidden by removing or adding the `.ng-hide` CSS class onto the element.\n * The `.ng-hide` CSS class is predefined in AngularJS and sets the display style to none (using an\n * `!important` flag). For CSP mode please add `angular-csp.css` to your HTML file (see\n * {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added\n * to the class attribute on the element causing it to become hidden. When truthy, the `.ng-hide`\n * CSS class is removed from the element causing the element not to appear hidden.\n *\n * ## Why is `!important` used?\n *\n * You may be wondering why `!important` is used for the `.ng-hide` CSS class. This is because the\n * `.ng-hide` selector can be easily overridden by heavier selectors. For example, something as\n * simple as changing the display style on a HTML list item would make hidden elements appear\n * visible. This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using `!important`, the show and hide behavior will work as expected despite any clash between\n * CSS selector specificity (when `!important` isn't used with any conflicting styles). If a\n * developer chooses to override the styling to change how to hide an element then it is just a\n * matter of using `!important` in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none !important`. If you\n * wish to change the hide behavior with `ngShow`/`ngHide`, you can simply overwrite the styles for\n * the `.ng-hide` CSS class. Note that the selector that needs to be used is actually\n * `.ng-hide:not(.ng-hide-animate)` to cope with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; These are just alternative ways of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override anything in CSS and the animations will work around the\n * display style.\n *\n * @animations\n * | Animation                                           | Occurs                                                                                                        |\n * |-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------|\n * | {@link $animate#addClass addClass} `.ng-hide`       | After the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden. |\n * | {@link $animate#removeClass removeClass} `.ng-hide` | After the `ngShow` expression evaluates to a truthy value and just before contents are set to visible.        |\n *\n * Animations in `ngShow`/`ngHide` work with the show and hide events that are triggered when the\n * directive expression is true and false. This system works like the animation system present with\n * `ngClass` except that you must also include the `!important` flag to override the display\n * property so that the elements are not actually hidden during the animation.\n *\n * ```css\n * /&#42; A working example can be found at the bottom of this page. &#42;/\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: all 0.5s linear;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display property\n * to block during animation states - ngAnimate will automatically handle the style toggling for you.\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy/falsy then the\n *                            element is shown/hidden respectively.\n *\n * @example\n * A simple example, animating the element's opacity:\n *\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-show-simple\">\n    <file name=\"index.html\">\n      Show: <input type=\"checkbox\" ng-model=\"checked\" aria-label=\"Toggle ngShow\"><br />\n      <div class=\"check-element animate-show-hide\" ng-show=\"checked\">\n        I show up when your checkbox is checked.\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .animate-show-hide.ng-hide {\n        opacity: 0;\n      }\n\n      .animate-show-hide.ng-hide-add,\n      .animate-show-hide.ng-hide-remove {\n        transition: all linear 0.5s;\n      }\n\n      .check-element {\n        border: 1px solid black;\n        opacity: 1;\n        padding: 10px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should check ngShow', function() {\n        var checkbox = element(by.model('checked'));\n        var checkElem = element(by.css('.check-element'));\n\n        expect(checkElem.isDisplayed()).toBe(false);\n        checkbox.click();\n        expect(checkElem.isDisplayed()).toBe(true);\n      });\n    </file>\n  </example>\n *\n * <hr />\n * @example\n * A more complex example, featuring different show/hide animations:\n *\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-show-complex\">\n    <file name=\"index.html\">\n      Show: <input type=\"checkbox\" ng-model=\"checked\" aria-label=\"Toggle ngShow\"><br />\n      <div class=\"check-element funky-show-hide\" ng-show=\"checked\">\n        I show up when your checkbox is checked.\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      body {\n        overflow: hidden;\n        perspective: 1000px;\n      }\n\n      .funky-show-hide.ng-hide-add {\n        transform: rotateZ(0);\n        transform-origin: right;\n        transition: all 0.5s ease-in-out;\n      }\n\n      .funky-show-hide.ng-hide-add.ng-hide-add-active {\n        transform: rotateZ(-135deg);\n      }\n\n      .funky-show-hide.ng-hide-remove {\n        transform: rotateY(90deg);\n        transform-origin: left;\n        transition: all 0.5s ease;\n      }\n\n      .funky-show-hide.ng-hide-remove.ng-hide-remove-active {\n        transform: rotateY(0);\n      }\n\n      .check-element {\n        border: 1px solid black;\n        opacity: 1;\n        padding: 10px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should check ngShow', function() {\n        var checkbox = element(by.model('checked'));\n        var checkElem = element(by.css('.check-element'));\n\n        expect(checkElem.isDisplayed()).toBe(false);\n        checkbox.click();\n        expect(checkElem.isDisplayed()).toBe(true);\n      });\n    </file>\n  </example>\n *\n * @knownIssue\n *\n * ### Flickering when using ngShow to toggle between elements\n *\n * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can\n * happen that both the element to show and the element to hide are visible for a very short time.\n *\n * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations\n * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than\n * other browsers.\n *\n * There are several way to mitigate this problem:\n *\n * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}.\n * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}.\n * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements.\n * - Use `ng-class=\"{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}.\n * - Define an animation on the affected elements.\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n        // we're adding a temporary, animation-specific class for ng-hide since this way\n        // we can control when the element is actually displayed on screen without having\n        // to have a global/greedy CSS selector that breaks when other animations are run.\n        // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n        $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n * @multiElement\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression provided to\n * the `ngHide` attribute.\n *\n * The element is shown or hidden by removing or adding the `.ng-hide` CSS class onto the element.\n * The `.ng-hide` CSS class is predefined in AngularJS and sets the display style to none (using an\n * `!important` flag). For CSP mode please add `angular-csp.css` to your HTML file (see\n * {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added\n * to the class attribute on the element causing it to become hidden. When falsy, the `.ng-hide`\n * CSS class is removed from the element causing the element not to appear hidden.\n *\n * ## Why is `!important` used?\n *\n * You may be wondering why `!important` is used for the `.ng-hide` CSS class. This is because the\n * `.ng-hide` selector can be easily overridden by heavier selectors. For example, something as\n * simple as changing the display style on a HTML list item would make hidden elements appear\n * visible. This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using `!important`, the show and hide behavior will work as expected despite any clash between\n * CSS selector specificity (when `!important` isn't used with any conflicting styles). If a\n * developer chooses to override the styling to change how to hide an element then it is just a\n * matter of using `!important` in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display: none !important`. If you\n * wish to change the hide behavior with `ngShow`/`ngHide`, you can simply overwrite the styles for\n * the `.ng-hide` CSS class. Note that the selector that needs to be used is actually\n * `.ng-hide:not(.ng-hide-animate)` to cope with extra animation classes that can be added.\n *\n * ```css\n * .ng-hide:not(.ng-hide-animate) {\n *   /&#42; These are just alternative ways of hiding an element &#42;/\n *   display: block!important;\n *   position: absolute;\n *   top: -9999px;\n *   left: -9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the\n * display style.\n *\n * @animations\n * | Animation                                           | Occurs                                                                                                     |\n * |-----------------------------------------------------|------------------------------------------------------------------------------------------------------------|\n * | {@link $animate#addClass addClass} `.ng-hide`       | After the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden.  |\n * | {@link $animate#removeClass removeClass} `.ng-hide` | After the `ngHide` expression evaluates to a non truthy value and just before contents are set to visible. |\n *\n * Animations in `ngShow`/`ngHide` work with the show and hide events that are triggered when the\n * directive expression is true and false. This system works like the animation system present with\n * `ngClass` except that you must also include the `!important` flag to override the display\n * property so that the elements are not actually hidden during the animation.\n *\n * ```css\n * /&#42; A working example can be found at the bottom of this page. &#42;/\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition: all 0.5s linear;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display property\n * to block during animation states - ngAnimate will automatically handle the style toggling for you.\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy/falsy then the\n *                            element is hidden/shown respectively.\n *\n * @example\n * A simple example, animating the element's opacity:\n *\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-hide-simple\">\n    <file name=\"index.html\">\n      Hide: <input type=\"checkbox\" ng-model=\"checked\" aria-label=\"Toggle ngHide\"><br />\n      <div class=\"check-element animate-show-hide\" ng-hide=\"checked\">\n        I hide when your checkbox is checked.\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .animate-show-hide.ng-hide {\n        opacity: 0;\n      }\n\n      .animate-show-hide.ng-hide-add,\n      .animate-show-hide.ng-hide-remove {\n        transition: all linear 0.5s;\n      }\n\n      .check-element {\n        border: 1px solid black;\n        opacity: 1;\n        padding: 10px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should check ngHide', function() {\n        var checkbox = element(by.model('checked'));\n        var checkElem = element(by.css('.check-element'));\n\n        expect(checkElem.isDisplayed()).toBe(true);\n        checkbox.click();\n        expect(checkElem.isDisplayed()).toBe(false);\n      });\n    </file>\n  </example>\n *\n * <hr />\n * @example\n * A more complex example, featuring different show/hide animations:\n *\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-hide-complex\">\n    <file name=\"index.html\">\n      Hide: <input type=\"checkbox\" ng-model=\"checked\" aria-label=\"Toggle ngHide\"><br />\n      <div class=\"check-element funky-show-hide\" ng-hide=\"checked\">\n        I hide when your checkbox is checked.\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      body {\n        overflow: hidden;\n        perspective: 1000px;\n      }\n\n      .funky-show-hide.ng-hide-add {\n        transform: rotateZ(0);\n        transform-origin: right;\n        transition: all 0.5s ease-in-out;\n      }\n\n      .funky-show-hide.ng-hide-add.ng-hide-add-active {\n        transform: rotateZ(-135deg);\n      }\n\n      .funky-show-hide.ng-hide-remove {\n        transform: rotateY(90deg);\n        transform-origin: left;\n        transition: all 0.5s ease;\n      }\n\n      .funky-show-hide.ng-hide-remove.ng-hide-remove-active {\n        transform: rotateY(0);\n      }\n\n      .check-element {\n        border: 1px solid black;\n        opacity: 1;\n        padding: 10px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should check ngHide', function() {\n        var checkbox = element(by.model('checked'));\n        var checkElem = element(by.css('.check-element'));\n\n        expect(checkElem.isDisplayed()).toBe(true);\n        checkbox.click();\n        expect(checkElem.isDisplayed()).toBe(false);\n      });\n    </file>\n  </example>\n *\n * @knownIssue\n *\n * ### Flickering when using ngHide to toggle between elements\n *\n * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can\n * happen that both the element to show and the element to hide are visible for a very short time.\n *\n * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations\n * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than\n * other browsers.\n *\n * There are several way to mitigate this problem:\n *\n * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}.\n * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}.\n * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements.\n * - Use `ng-class=\"{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}.\n * - Define an animation on the affected elements.\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'A',\n    multiElement: true,\n    link: function(scope, element, attr) {\n      scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n        // The comment inside of the ngShowDirective explains why we add and\n        // remove a temporary class for the show/hide animation\n        $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n          tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n        });\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @knownIssue\n * You should not use {@link guide/interpolation interpolation} in the value of the `style`\n * attribute, when using the `ngStyle` directive on the same element.\n * See {@link guide/interpolation#known-issues here} for more info.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example name=\"ng-style\">\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toMatch(/rgba\\(0, 0, 0, 1\\)|rgb\\(0, 0, 0\\)/);\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toMatch(/rgba\\(255, 0, 0, 1\\)|rgb\\(255, 0, 0\\)/);\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toMatch(/rgba\\(0, 0, 0, 1\\)|rgb\\(0, 0, 0\\)/);\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, ''); });\n    }\n    if (newStyles) element.css(newStyles);\n  });\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#enter enter}  | after the ngSwitch contents change and the matched child element is placed inside the container |\n * | {@link ng.$animate#leave leave}  | after the ngSwitch contents change and just before the former contents are removed from the DOM |\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 1200\n * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed. It is possible to associate multiple values to\n *   the same `ngSwitchWhen` by defining the optional attribute\n *   `ngSwitchWhenSeparator`. The separator will be used to split the value of\n *   the `ngSwitchWhen` attribute into multiple tokens, and the element will show\n *   if any of the `ngSwitch` evaluates to any of these tokens.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\" name=\"ng-switch\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <code>selection={{selection}}</code>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings|options\" ng-switch-when-separator=\"|\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'options', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should change to settings via \"options\"', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(3).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', '$compile', function($animate, $compile) {\n  return {\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function NgSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousLeaveAnimations = [],\n          selectedScopes = [];\n\n      var spliceFactory = function(array, index) {\n          return function(response) {\n            if (response !== false) array.splice(index, 1);\n          };\n      };\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n\n        // Start with the last, in case the array is modified during the loop\n        while (previousLeaveAnimations.length) {\n          $animate.cancel(previousLeaveAnimations.pop());\n        }\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = getBlockNodes(selectedElements[i].clone);\n          selectedScopes[i].$destroy();\n          var runner = previousLeaveAnimations[i] = $animate.leave(selected);\n          runner.done(spliceFactory(previousLeaveAnimations, i));\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            selectedTransclude.transclude(function(caseElement, selectedScope) {\n              selectedScopes.push(selectedScope);\n              var anchor = selectedTransclude.element;\n              caseElement[caseElement.length++] = $compile.$$createComment('end ngSwitchWhen');\n              var block = { clone: caseElement };\n\n              selectedElements.push(block);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attrs, ctrl, $transclude) {\n\n    var cases = attrs.ngSwitchWhen.split(attrs.ngSwitchWhenSeparator).sort().filter(\n      // Filter duplicate cases\n      function(element, index, array) { return array[index - 1] !== element; }\n    );\n\n    forEach(cases, function(whenCase) {\n      ctrl.cases['!' + whenCase] = (ctrl.cases['!' + whenCase] || []);\n      ctrl.cases['!' + whenCase].push({ transclude: $transclude, element: element });\n    });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 1200,\n  require: '^ngSwitch',\n  multiElement: true,\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict EAC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name\n * as the value of the `ng-transclude` or `ng-transclude-slot` attribute.\n *\n * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing\n * content of this element will be removed before the transcluded content is inserted.\n * If the transcluded content is empty (or only whitespace), the existing content is left intact. This lets you provide fallback\n * content in the case that no transcluded content is provided.\n *\n * @element ANY\n *\n * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty\n *                                               or its value is the same as the name of the attribute then the default slot is used.\n *\n * @example\n * ### Basic transclusion\n * This example demonstrates basic transclusion of content into a component directive.\n * <example name=\"simpleTranscludeExample\" module=\"transcludeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('transcludeExample', [])\n *        .directive('pane', function(){\n *           return {\n *             restrict: 'E',\n *             transclude: true,\n *             scope: { title:'@' },\n *             template: '<div style=\"border: 1px solid black;\">' +\n *                         '<div style=\"background-color: gray\">{{title}}</div>' +\n *                         '<ng-transclude></ng-transclude>' +\n *                       '</div>'\n *           };\n *       })\n *       .controller('ExampleController', ['$scope', function($scope) {\n *         $scope.title = 'Lorem Ipsum';\n *         $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n *       }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input ng-model=\"title\" aria-label=\"title\"> <br/>\n *       <textarea ng-model=\"text\" aria-label=\"text\"></textarea> <br/>\n *       <pane title=\"{{title}}\"><span>{{text}}</span></pane>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *      it('should have transcluded', function() {\n *        var titleElement = element(by.model('title'));\n *        titleElement.clear();\n *        titleElement.sendKeys('TITLE');\n *        var textElement = element(by.model('text'));\n *        textElement.clear();\n *        textElement.sendKeys('TEXT');\n *        expect(element(by.binding('title')).getText()).toEqual('TITLE');\n *        expect(element(by.binding('text')).getText()).toEqual('TEXT');\n *      });\n *   </file>\n * </example>\n *\n * @example\n * ### Transclude fallback content\n * This example shows how to use `NgTransclude` with fallback content, that\n * is displayed if no transcluded content is provided.\n *\n * <example module=\"transcludeFallbackContentExample\" name=\"ng-transclude\">\n * <file name=\"index.html\">\n * <script>\n * angular.module('transcludeFallbackContentExample', [])\n * .directive('myButton', function(){\n *             return {\n *               restrict: 'E',\n *               transclude: true,\n *               scope: true,\n *               template: '<button style=\"cursor: pointer;\">' +\n *                           '<ng-transclude>' +\n *                             '<b style=\"color: red;\">Button1</b>' +\n *                           '</ng-transclude>' +\n *                         '</button>'\n *             };\n *         });\n * </script>\n * <!-- fallback button content -->\n * <my-button id=\"fallback\"></my-button>\n * <!-- modified button content -->\n * <my-button id=\"modified\">\n *   <i style=\"color: green;\">Button2</i>\n * </my-button>\n * </file>\n * <file name=\"protractor.js\" type=\"protractor\">\n * it('should have different transclude element content', function() {\n *          expect(element(by.id('fallback')).getText()).toBe('Button1');\n *          expect(element(by.id('modified')).getText()).toBe('Button2');\n *        });\n * </file>\n * </example>\n *\n * @example\n * ### Multi-slot transclusion\n * This example demonstrates using multi-slot transclusion in a component directive.\n * <example name=\"multiSlotTranscludeExample\" module=\"multiSlotTranscludeExample\">\n *   <file name=\"index.html\">\n *    <style>\n *      .title, .footer {\n *        background-color: gray\n *      }\n *    </style>\n *    <div ng-controller=\"ExampleController\">\n *      <input ng-model=\"title\" aria-label=\"title\"> <br/>\n *      <textarea ng-model=\"text\" aria-label=\"text\"></textarea> <br/>\n *      <pane>\n *        <pane-title><a ng-href=\"{{link}}\">{{title}}</a></pane-title>\n *        <pane-body><p>{{text}}</p></pane-body>\n *      </pane>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('multiSlotTranscludeExample', [])\n *     .directive('pane', function() {\n *        return {\n *          restrict: 'E',\n *          transclude: {\n *            'title': '?paneTitle',\n *            'body': 'paneBody',\n *            'footer': '?paneFooter'\n *          },\n *          template: '<div style=\"border: 1px solid black;\">' +\n *                      '<div class=\"title\" ng-transclude=\"title\">Fallback Title</div>' +\n *                      '<div ng-transclude=\"body\"></div>' +\n *                      '<div class=\"footer\" ng-transclude=\"footer\">Fallback Footer</div>' +\n *                    '</div>'\n *        };\n *    })\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.title = 'Lorem Ipsum';\n *      $scope.link = 'https://google.com';\n *      $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n *    }]);\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *      it('should have transcluded the title and the body', function() {\n *        var titleElement = element(by.model('title'));\n *        titleElement.clear();\n *        titleElement.sendKeys('TITLE');\n *        var textElement = element(by.model('text'));\n *        textElement.clear();\n *        textElement.sendKeys('TEXT');\n *        expect(element(by.css('.title')).getText()).toEqual('TITLE');\n *        expect(element(by.binding('text')).getText()).toEqual('TEXT');\n *        expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer');\n *      });\n *   </file>\n * </example>\n */\nvar ngTranscludeMinErr = minErr('ngTransclude');\nvar ngTranscludeDirective = ['$compile', function($compile) {\n  return {\n    restrict: 'EAC',\n    compile: function ngTranscludeCompile(tElement) {\n\n      // Remove and cache any original content to act as a fallback\n      var fallbackLinkFn = $compile(tElement.contents());\n      tElement.empty();\n\n      return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) {\n\n        if (!$transclude) {\n          throw ngTranscludeMinErr('orphan',\n          'Illegal use of ngTransclude directive in the template! ' +\n          'No parent directive that requires a transclusion found. ' +\n          'Element: {0}',\n          startingTag($element));\n        }\n\n\n        // If the attribute is of the form: `ng-transclude=\"ng-transclude\"` then treat it like the default\n        if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {\n          $attrs.ngTransclude = '';\n        }\n        var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;\n\n        // If the slot is required and no transclusion content is provided then this call will throw an error\n        $transclude(ngTranscludeCloneAttachFn, null, slotName);\n\n        // If the slot is optional and no transclusion content is provided then use the fallback content\n        if (slotName && !$transclude.isSlotFilled(slotName)) {\n          useFallbackContent();\n        }\n\n        function ngTranscludeCloneAttachFn(clone, transcludedScope) {\n          if (clone.length && notWhitespace(clone)) {\n            $element.append(clone);\n          } else {\n            useFallbackContent();\n            // There is nothing linked against the transcluded scope since no content was available,\n            // so it should be safe to clean up the generated scope.\n            transcludedScope.$destroy();\n          }\n        }\n\n        function useFallbackContent() {\n          // Since this is the fallback content rather than the transcluded content,\n          // we link against the scope of this directive rather than the transcluded scope\n          fallbackLinkFn($scope, function(clone) {\n            $element.append(clone);\n          });\n        }\n\n        function notWhitespace(nodes) {\n          for (var i = 0, ii = nodes.length; i < ii; i++) {\n            var node = nodes[i];\n            if (node.nodeType !== NODE_TYPE_TEXT || node.nodeValue.trim()) {\n              return true;\n            }\n          }\n        }\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example  name=\"script-tag\">\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type === 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\n/* exported selectDirective, optionDirective */\n\nvar noopNgModelController = { $setViewValue: noop, $render: noop };\n\nfunction setOptionSelectedStatus(optionEl, value) {\n  optionEl.prop('selected', value);\n  /**\n   * When unselecting an option, setting the property to null / false should be enough\n   * However, screenreaders might react to the selected attribute instead, see\n   * https://github.com/angular/angular.js/issues/14419\n   * Note: \"selected\" is a boolean attr and will be removed when the \"value\" arg in attr() is false\n   * or null\n   */\n  optionEl.attr('selected', value);\n}\n\n/**\n * @ngdoc type\n * @name  select.SelectController\n *\n * @description\n * The controller for the {@link ng.select select} directive. The controller exposes\n * a few utility methods that can be used to augment the behavior of a regular or an\n * {@link ng.ngOptions ngOptions} select element.\n *\n * @example\n * ### Set a custom error when the unknown option is selected\n *\n * This example sets a custom error \"unknownValue\" on the ngModelController\n * when the select element's unknown option is selected, i.e. when the model is set to a value\n * that is not matched by any option.\n *\n * <example name=\"select-unknown-value-error\" module=\"staticSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"testSelect\"> Single select: </label><br>\n *     <select name=\"testSelect\" ng-model=\"selected\" unknown-value-error>\n *       <option value=\"option-1\">Option 1</option>\n *       <option value=\"option-2\">Option 2</option>\n *     </select><br>\n *     <span class=\"error\" ng-if=\"myForm.testSelect.$error.unknownValue\">\n *       Error: The current model doesn't match any option</span><br>\n *\n *     <button ng-click=\"forceUnknownOption()\">Force unknown option</button><br>\n *   </form>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('staticSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.selected = null;\n *\n *      $scope.forceUnknownOption = function() {\n *        $scope.selected = 'nonsense';\n *      };\n *   }])\n *   .directive('unknownValueError', function() {\n *     return {\n *       require: ['ngModel', 'select'],\n *       link: function(scope, element, attrs, ctrls) {\n *         var ngModelCtrl = ctrls[0];\n *         var selectCtrl = ctrls[1];\n *\n *         ngModelCtrl.$validators.unknownValue = function(modelValue, viewValue) {\n *           if (selectCtrl.$isUnknownOptionSelected()) {\n *             return false;\n *           }\n *\n *           return true;\n *         };\n *       }\n *\n *     };\n *   });\n * </file>\n *</example>\n *\n *\n * @example\n * ### Set the \"required\" error when the unknown option is selected.\n *\n * By default, the \"required\" error on the ngModelController is only set on a required select\n * when the empty option is selected. This example adds a custom directive that also sets the\n * error when the unknown option is selected.\n *\n * <example name=\"select-unknown-value-required\" module=\"staticSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"testSelect\"> Select: </label><br>\n *     <select name=\"testSelect\" ng-model=\"selected\" required unknown-value-required>\n *       <option value=\"option-1\">Option 1</option>\n *       <option value=\"option-2\">Option 2</option>\n *     </select><br>\n *     <span class=\"error\" ng-if=\"myForm.testSelect.$error.required\">Error: Please select a value</span><br>\n *\n *     <button ng-click=\"forceUnknownOption()\">Force unknown option</button><br>\n *   </form>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('staticSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.selected = null;\n *\n *      $scope.forceUnknownOption = function() {\n *        $scope.selected = 'nonsense';\n *      };\n *   }])\n *   .directive('unknownValueRequired', function() {\n *     return {\n *       priority: 1, // This directive must run after the required directive has added its validator\n *       require: ['ngModel', 'select'],\n *       link: function(scope, element, attrs, ctrls) {\n *         var ngModelCtrl = ctrls[0];\n *         var selectCtrl = ctrls[1];\n *\n *         var originalRequiredValidator = ngModelCtrl.$validators.required;\n *\n *         ngModelCtrl.$validators.required = function() {\n *           if (attrs.required && selectCtrl.$isUnknownOptionSelected()) {\n *             return false;\n *           }\n *\n *           return originalRequiredValidator.apply(this, arguments);\n *         };\n *       }\n *     };\n *   });\n * </file>\n * <file name=\"protractor.js\" type=\"protractor\">\n *  it('should show the error message when the unknown option is selected', function() {\n\n      var error = element(by.className('error'));\n\n      expect(error.getText()).toBe('Error: Please select a value');\n\n      element(by.cssContainingText('option', 'Option 1')).click();\n\n      expect(error.isPresent()).toBe(false);\n\n      element(by.tagName('button')).click();\n\n      expect(error.getText()).toBe('Error: Please select a value');\n    });\n * </file>\n *</example>\n *\n *\n */\nvar SelectController =\n        ['$element', '$scope', /** @this */ function($element, $scope) {\n\n  var self = this,\n      optionsMap = new NgMap();\n\n  self.selectValueMap = {}; // Keys are the hashed values, values the original values\n\n  // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors\n  self.ngModelCtrl = noopNgModelController;\n  self.multiple = false;\n\n  // The \"unknown\" option is one that is prepended to the list if the viewValue\n  // does not match any of the options. When it is rendered the value of the unknown\n  // option is '? XXX ?' where XXX is the hashKey of the value that is not known.\n  //\n  // Support: IE 9 only\n  // We can't just jqLite('<option>') since jqLite is not smart enough\n  // to create it in <select> and IE barfs otherwise.\n  self.unknownOption = jqLite(window.document.createElement('option'));\n\n  // The empty option is an option with the value '' that the application developer can\n  // provide inside the select. It is always selectable and indicates that a \"null\" selection has\n  // been made by the user.\n  // If the select has an empty option, and the model of the select is set to \"undefined\" or \"null\",\n  // the empty option is selected.\n  // If the model is set to a different unmatched value, the unknown option is rendered and\n  // selected, i.e both are present, because a \"null\" selection and an unknown value are different.\n  self.hasEmptyOption = false;\n  self.emptyOption = undefined;\n\n  self.renderUnknownOption = function(val) {\n    var unknownVal = self.generateUnknownOptionValue(val);\n    self.unknownOption.val(unknownVal);\n    $element.prepend(self.unknownOption);\n    setOptionSelectedStatus(self.unknownOption, true);\n    $element.val(unknownVal);\n  };\n\n  self.updateUnknownOption = function(val) {\n    var unknownVal = self.generateUnknownOptionValue(val);\n    self.unknownOption.val(unknownVal);\n    setOptionSelectedStatus(self.unknownOption, true);\n    $element.val(unknownVal);\n  };\n\n  self.generateUnknownOptionValue = function(val) {\n    return '? ' + hashKey(val) + ' ?';\n  };\n\n  self.removeUnknownOption = function() {\n    if (self.unknownOption.parent()) self.unknownOption.remove();\n  };\n\n  self.selectEmptyOption = function() {\n    if (self.emptyOption) {\n      $element.val('');\n      setOptionSelectedStatus(self.emptyOption, true);\n    }\n  };\n\n  self.unselectEmptyOption = function() {\n    if (self.hasEmptyOption) {\n      setOptionSelectedStatus(self.emptyOption, false);\n    }\n  };\n\n  $scope.$on('$destroy', function() {\n    // disable unknown option so that we don't do work when the whole select is being destroyed\n    self.renderUnknownOption = noop;\n  });\n\n  // Read the value of the select control, the implementation of this changes depending\n  // upon whether the select can have multiple values and whether ngOptions is at work.\n  self.readValue = function readSingleValue() {\n    var val = $element.val();\n    // ngValue added option values are stored in the selectValueMap, normal interpolations are not\n    var realVal = val in self.selectValueMap ? self.selectValueMap[val] : val;\n\n    if (self.hasOption(realVal)) {\n      return realVal;\n    }\n\n    return null;\n  };\n\n\n  // Write the value to the select control, the implementation of this changes depending\n  // upon whether the select can have multiple values and whether ngOptions is at work.\n  self.writeValue = function writeSingleValue(value) {\n    // Make sure to remove the selected attribute from the previously selected option\n    // Otherwise, screen readers might get confused\n    var currentlySelectedOption = $element[0].options[$element[0].selectedIndex];\n    if (currentlySelectedOption) setOptionSelectedStatus(jqLite(currentlySelectedOption), false);\n\n    if (self.hasOption(value)) {\n      self.removeUnknownOption();\n\n      var hashedVal = hashKey(value);\n      $element.val(hashedVal in self.selectValueMap ? hashedVal : value);\n\n      // Set selected attribute and property on selected option for screen readers\n      var selectedOption = $element[0].options[$element[0].selectedIndex];\n      setOptionSelectedStatus(jqLite(selectedOption), true);\n    } else {\n      self.selectUnknownOrEmptyOption(value);\n    }\n  };\n\n\n  // Tell the select control that an option, with the given value, has been added\n  self.addOption = function(value, element) {\n    // Skip comment nodes, as they only pollute the `optionsMap`\n    if (element[0].nodeType === NODE_TYPE_COMMENT) return;\n\n    assertNotHasOwnProperty(value, '\"option value\"');\n    if (value === '') {\n      self.hasEmptyOption = true;\n      self.emptyOption = element;\n    }\n    var count = optionsMap.get(value) || 0;\n    optionsMap.set(value, count + 1);\n    // Only render at the end of a digest. This improves render performance when many options\n    // are added during a digest and ensures all relevant options are correctly marked as selected\n    scheduleRender();\n  };\n\n  // Tell the select control that an option, with the given value, has been removed\n  self.removeOption = function(value) {\n    var count = optionsMap.get(value);\n    if (count) {\n      if (count === 1) {\n        optionsMap.delete(value);\n        if (value === '') {\n          self.hasEmptyOption = false;\n          self.emptyOption = undefined;\n        }\n      } else {\n        optionsMap.set(value, count - 1);\n      }\n    }\n  };\n\n  // Check whether the select control has an option matching the given value\n  self.hasOption = function(value) {\n    return !!optionsMap.get(value);\n  };\n\n  /**\n   * @ngdoc method\n   * @name select.SelectController#$hasEmptyOption\n   *\n   * @description\n   *\n   * Returns `true` if the select element currently has an empty option\n   * element, i.e. an option that signifies that the select is empty / the selection is null.\n   *\n   */\n  self.$hasEmptyOption = function() {\n    return self.hasEmptyOption;\n  };\n\n  /**\n   * @ngdoc method\n   * @name select.SelectController#$isUnknownOptionSelected\n   *\n   * @description\n   *\n   * Returns `true` if the select element's unknown option is selected. The unknown option is added\n   * and automatically selected whenever the select model doesn't match any option.\n   *\n   */\n  self.$isUnknownOptionSelected = function() {\n    // Presence of the unknown option means it is selected\n    return $element[0].options[0] === self.unknownOption[0];\n  };\n\n  /**\n   * @ngdoc method\n   * @name select.SelectController#$isEmptyOptionSelected\n   *\n   * @description\n   *\n   * Returns `true` if the select element has an empty option and this empty option is currently\n   * selected. Returns `false` if the select element has no empty option or it is not selected.\n   *\n   */\n  self.$isEmptyOptionSelected = function() {\n    return self.hasEmptyOption && $element[0].options[$element[0].selectedIndex] === self.emptyOption[0];\n  };\n\n  self.selectUnknownOrEmptyOption = function(value) {\n    if (value == null && self.emptyOption) {\n      self.removeUnknownOption();\n      self.selectEmptyOption();\n    } else if (self.unknownOption.parent().length) {\n      self.updateUnknownOption(value);\n    } else {\n      self.renderUnknownOption(value);\n    }\n  };\n\n  var renderScheduled = false;\n  function scheduleRender() {\n    if (renderScheduled) return;\n    renderScheduled = true;\n    $scope.$$postDigest(function() {\n      renderScheduled = false;\n      self.ngModelCtrl.$render();\n    });\n  }\n\n  var updateScheduled = false;\n  function scheduleViewValueUpdate(renderAfter) {\n    if (updateScheduled) return;\n\n    updateScheduled = true;\n\n    $scope.$$postDigest(function() {\n      if ($scope.$$destroyed) return;\n\n      updateScheduled = false;\n      self.ngModelCtrl.$setViewValue(self.readValue());\n      if (renderAfter) self.ngModelCtrl.$render();\n    });\n  }\n\n\n  self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {\n\n    if (optionAttrs.$attr.ngValue) {\n      // The value attribute is set by ngValue\n      var oldVal, hashedVal;\n      optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {\n\n        var removal;\n        var previouslySelected = optionElement.prop('selected');\n\n        if (isDefined(hashedVal)) {\n          self.removeOption(oldVal);\n          delete self.selectValueMap[hashedVal];\n          removal = true;\n        }\n\n        hashedVal = hashKey(newVal);\n        oldVal = newVal;\n        self.selectValueMap[hashedVal] = newVal;\n        self.addOption(newVal, optionElement);\n        // Set the attribute directly instead of using optionAttrs.$set - this stops the observer\n        // from firing a second time. Other $observers on value will also get the result of the\n        // ngValue expression, not the hashed value\n        optionElement.attr('value', hashedVal);\n\n        if (removal && previouslySelected) {\n          scheduleViewValueUpdate();\n        }\n\n      });\n    } else if (interpolateValueFn) {\n      // The value attribute is interpolated\n      optionAttrs.$observe('value', function valueAttributeObserveAction(newVal) {\n        // This method is overwritten in ngOptions and has side-effects!\n        self.readValue();\n\n        var removal;\n        var previouslySelected = optionElement.prop('selected');\n\n        if (isDefined(oldVal)) {\n          self.removeOption(oldVal);\n          removal = true;\n        }\n        oldVal = newVal;\n        self.addOption(newVal, optionElement);\n\n        if (removal && previouslySelected) {\n          scheduleViewValueUpdate();\n        }\n      });\n    } else if (interpolateTextFn) {\n      // The text content is interpolated\n      optionScope.$watch(interpolateTextFn, function interpolateWatchAction(newVal, oldVal) {\n        optionAttrs.$set('value', newVal);\n        var previouslySelected = optionElement.prop('selected');\n        if (oldVal !== newVal) {\n          self.removeOption(oldVal);\n        }\n        self.addOption(newVal, optionElement);\n\n        if (oldVal && previouslySelected) {\n          scheduleViewValueUpdate();\n        }\n      });\n    } else {\n      // The value attribute is static\n      self.addOption(optionAttrs.value, optionElement);\n    }\n\n\n    optionAttrs.$observe('disabled', function(newVal) {\n\n      // Since model updates will also select disabled options (like ngOptions),\n      // we only have to handle options becoming disabled, not enabled\n\n      if (newVal === 'true' || newVal && optionElement.prop('selected')) {\n        if (self.multiple) {\n          scheduleViewValueUpdate(true);\n        } else {\n          self.ngModelCtrl.$setViewValue(null);\n          self.ngModelCtrl.$render();\n        }\n      }\n    });\n\n    optionElement.on('$destroy', function() {\n      var currentValue = self.readValue();\n      var removeValue = optionAttrs.value;\n\n      self.removeOption(removeValue);\n      scheduleRender();\n\n      if (self.multiple && currentValue && currentValue.indexOf(removeValue) !== -1 ||\n          currentValue === removeValue\n      ) {\n        // When multiple (selected) options are destroyed at the same time, we don't want\n        // to run a model update for each of them. Instead, run a single update in the $$postDigest\n        scheduleViewValueUpdate(true);\n      }\n    });\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `select` element with AngularJS data-binding.\n *\n * The `select` directive is used together with {@link ngModel `ngModel`} to provide data-binding\n * between the scope and the `<select>` control (including setting default values).\n * It also handles dynamic `<option>` elements, which can be added using the {@link ngRepeat `ngRepeat}` or\n * {@link ngOptions `ngOptions`} directives.\n *\n * When an item in the `<select>` menu is selected, the value of the selected option will be bound\n * to the model identified by the `ngModel` directive. With static or repeated options, this is\n * the content of the `value` attribute or the textContent of the `<option>`, if the value attribute is missing.\n * Value and textContent can be interpolated.\n *\n * The {@link select.SelectController select controller} exposes utility functions that can be used\n * to manipulate the select's behavior.\n *\n * ## Matching model and option values\n *\n * In general, the match between the model and an option is evaluated by strictly comparing the model\n * value against the value of the available options.\n *\n * If you are setting the option value with the option's `value` attribute, or textContent, the\n * value will always be a `string` which means that the model value must also be a string.\n * Otherwise the `select` directive cannot match them correctly.\n *\n * To bind the model to a non-string value, you can use one of the following strategies:\n * - the {@link ng.ngOptions `ngOptions`} directive\n *   ({@link ng.select#using-select-with-ngoptions-and-setting-a-default-value})\n * - the {@link ng.ngValue `ngValue`} directive, which allows arbitrary expressions to be\n *   option values ({@link ng.select#using-ngvalue-to-bind-the-model-to-an-array-of-objects Example})\n * - model $parsers / $formatters to convert the string value\n *   ({@link ng.select#binding-select-to-a-non-string-value-via-ngmodel-parsing-formatting Example})\n *\n * If the viewValue of `ngModel` does not match any of the options, then the control\n * will automatically add an \"unknown\" option, which it then removes when the mismatch is resolved.\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * ## Choosing between `ngRepeat` and `ngOptions`\n *\n * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions\n * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits:\n * - more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the\n * comprehension expression\n * - reduced memory consumption by not creating a new scope for each repeated instance\n * - increased render speed by creating the options in a documentFragment instead of individually\n *\n * Specifically, select with repeated options slows down significantly starting at 2000 options in\n * Chrome and Internet Explorer / Edge.\n *\n *\n * @param {string} ngModel Assignable AngularJS expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} multiple Allows multiple options to be selected. The selected values will be\n *     bound to the model as an array.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds required attribute and required validation constraint to\n * the element when the ngRequired expression evaluates to true. Use ngRequired instead of required\n * when you want to data-bind to the required attribute.\n * @param {string=} ngChange AngularJS expression to be executed when selected option(s) changes due to user\n *    interaction with the select element.\n * @param {string=} ngOptions sets the options that the select is populated with and defines what is\n * set on the model on selection. See {@link ngOptions `ngOptions`}.\n * @param {string=} ngAttrSize sets the size of the select element dynamically. Uses the\n * {@link guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes ngAttr} directive.\n *\n *\n * @example\n * ### Simple `select` elements with static options\n *\n * <example name=\"static-select\" module=\"staticSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"singleSelect\"> Single select: </label><br>\n *     <select name=\"singleSelect\" ng-model=\"data.singleSelect\">\n *       <option value=\"option-1\">Option 1</option>\n *       <option value=\"option-2\">Option 2</option>\n *     </select><br>\n *\n *     <label for=\"singleSelect\"> Single select with \"not selected\" option and dynamic option values: </label><br>\n *     <select name=\"singleSelect\" id=\"singleSelect\" ng-model=\"data.singleSelect\">\n *       <option value=\"\">---Please select---</option> <!-- not selected / blank option -->\n *       <option value=\"{{data.option1}}\">Option 1</option> <!-- interpolation -->\n *       <option value=\"option-2\">Option 2</option>\n *     </select><br>\n *     <button ng-click=\"forceUnknownOption()\">Force unknown option</button><br>\n *     <tt>singleSelect = {{data.singleSelect}}</tt>\n *\n *     <hr>\n *     <label for=\"multipleSelect\"> Multiple select: </label><br>\n *     <select name=\"multipleSelect\" id=\"multipleSelect\" ng-model=\"data.multipleSelect\" multiple>\n *       <option value=\"option-1\">Option 1</option>\n *       <option value=\"option-2\">Option 2</option>\n *       <option value=\"option-3\">Option 3</option>\n *     </select><br>\n *     <tt>multipleSelect = {{data.multipleSelect}}</tt><br/>\n *   </form>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('staticSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.data = {\n *       singleSelect: null,\n *       multipleSelect: [],\n *       option1: 'option-1'\n *      };\n *\n *      $scope.forceUnknownOption = function() {\n *        $scope.data.singleSelect = 'nonsense';\n *      };\n *   }]);\n * </file>\n *</example>\n *\n * @example\n * ### Using `ngRepeat` to generate `select` options\n * <example name=\"select-ngrepeat\" module=\"ngrepeatSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"repeatSelect\"> Repeat select: </label>\n *     <select name=\"repeatSelect\" id=\"repeatSelect\" ng-model=\"data.model\">\n *       <option ng-repeat=\"option in data.availableOptions\" value=\"{{option.id}}\">{{option.name}}</option>\n *     </select>\n *   </form>\n *   <hr>\n *   <tt>model = {{data.model}}</tt><br/>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('ngrepeatSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.data = {\n *       model: null,\n *       availableOptions: [\n *         {id: '1', name: 'Option A'},\n *         {id: '2', name: 'Option B'},\n *         {id: '3', name: 'Option C'}\n *       ]\n *      };\n *   }]);\n * </file>\n *</example>\n *\n * @example\n * ### Using `ngValue` to bind the model to an array of objects\n * <example name=\"select-ngvalue\" module=\"ngvalueSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"ngvalueselect\"> ngvalue select: </label>\n *     <select size=\"6\" name=\"ngvalueselect\" ng-model=\"data.model\" multiple>\n *       <option ng-repeat=\"option in data.availableOptions\" ng-value=\"option.value\">{{option.name}}</option>\n *     </select>\n *   </form>\n *   <hr>\n *   <pre>model = {{data.model | json}}</pre><br/>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('ngvalueSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.data = {\n *       model: null,\n *       availableOptions: [\n           {value: 'myString', name: 'string'},\n           {value: 1, name: 'integer'},\n           {value: true, name: 'boolean'},\n           {value: null, name: 'null'},\n           {value: {prop: 'value'}, name: 'object'},\n           {value: ['a'], name: 'array'}\n *       ]\n *      };\n *   }]);\n * </file>\n *</example>\n *\n * @example\n * ### Using `select` with `ngOptions` and setting a default value\n * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples.\n *\n * <example name=\"select-with-default-values\" module=\"defaultValueSelect\">\n * <file name=\"index.html\">\n * <div ng-controller=\"ExampleController\">\n *   <form name=\"myForm\">\n *     <label for=\"mySelect\">Make a choice:</label>\n *     <select name=\"mySelect\" id=\"mySelect\"\n *       ng-options=\"option.name for option in data.availableOptions track by option.id\"\n *       ng-model=\"data.selectedOption\"></select>\n *   </form>\n *   <hr>\n *   <tt>option = {{data.selectedOption}}</tt><br/>\n * </div>\n * </file>\n * <file name=\"app.js\">\n *  angular.module('defaultValueSelect', [])\n *    .controller('ExampleController', ['$scope', function($scope) {\n *      $scope.data = {\n *       availableOptions: [\n *         {id: '1', name: 'Option A'},\n *         {id: '2', name: 'Option B'},\n *         {id: '3', name: 'Option C'}\n *       ],\n *       selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui\n *       };\n *   }]);\n * </file>\n *</example>\n *\n * @example\n * ### Binding `select` to a non-string value via `ngModel` parsing / formatting\n *\n * <example name=\"select-with-non-string-options\" module=\"nonStringSelect\">\n *   <file name=\"index.html\">\n *     <select ng-model=\"model.id\" convert-to-number>\n *       <option value=\"0\">Zero</option>\n *       <option value=\"1\">One</option>\n *       <option value=\"2\">Two</option>\n *     </select>\n *     {{ model }}\n *   </file>\n *   <file name=\"app.js\">\n *     angular.module('nonStringSelect', [])\n *       .run(function($rootScope) {\n *         $rootScope.model = { id: 2 };\n *       })\n *       .directive('convertToNumber', function() {\n *         return {\n *           require: 'ngModel',\n *           link: function(scope, element, attrs, ngModel) {\n *             ngModel.$parsers.push(function(val) {\n *               return parseInt(val, 10);\n *             });\n *             ngModel.$formatters.push(function(val) {\n *               return '' + val;\n *             });\n *           }\n *         };\n *       });\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should initialize to model', function() {\n *       expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');\n *     });\n *   </file>\n * </example>\n *\n */\nvar selectDirective = function() {\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: SelectController,\n    priority: 1,\n    link: {\n      pre: selectPreLink,\n      post: selectPostLink\n    }\n  };\n\n  function selectPreLink(scope, element, attr, ctrls) {\n\n      var selectCtrl = ctrls[0];\n      var ngModelCtrl = ctrls[1];\n\n      // if ngModel is not defined, we don't need to do anything but set the registerOption\n      // function to noop, so options don't get added internally\n      if (!ngModelCtrl) {\n        selectCtrl.registerOption = noop;\n        return;\n      }\n\n\n      selectCtrl.ngModelCtrl = ngModelCtrl;\n\n      // When the selected item(s) changes we delegate getting the value of the select control\n      // to the `readValue` method, which can be changed if the select can have multiple\n      // selected values or if the options are being generated by `ngOptions`\n      element.on('change', function() {\n        selectCtrl.removeUnknownOption();\n        scope.$apply(function() {\n          ngModelCtrl.$setViewValue(selectCtrl.readValue());\n        });\n      });\n\n      // If the select allows multiple values then we need to modify how we read and write\n      // values from and to the control; also what it means for the value to be empty and\n      // we have to add an extra watch since ngModel doesn't work well with arrays - it\n      // doesn't trigger rendering if only an item in the array changes.\n      if (attr.multiple) {\n        selectCtrl.multiple = true;\n\n        // Read value now needs to check each option to see if it is selected\n        selectCtrl.readValue = function readMultipleValue() {\n          var array = [];\n          forEach(element.find('option'), function(option) {\n            if (option.selected && !option.disabled) {\n              var val = option.value;\n              array.push(val in selectCtrl.selectValueMap ? selectCtrl.selectValueMap[val] : val);\n            }\n          });\n          return array;\n        };\n\n        // Write value now needs to set the selected property of each matching option\n        selectCtrl.writeValue = function writeMultipleValue(value) {\n          forEach(element.find('option'), function(option) {\n            var shouldBeSelected = !!value && (includes(value, option.value) ||\n                                               includes(value, selectCtrl.selectValueMap[option.value]));\n            var currentlySelected = option.selected;\n\n            // Support: IE 9-11 only, Edge 12-15+\n            // In IE and Edge adding options to the selection via shift+click/UP/DOWN\n            // will de-select already selected options if \"selected\" on those options was set\n            // more than once (i.e. when the options were already selected)\n            // So we only modify the selected property if necessary.\n            // Note: this behavior cannot be replicated via unit tests because it only shows in the\n            // actual user interface.\n            if (shouldBeSelected !== currentlySelected) {\n              setOptionSelectedStatus(jqLite(option), shouldBeSelected);\n            }\n\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        var lastView, lastViewRef = NaN;\n        scope.$watch(function selectMultipleWatch() {\n          if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {\n            lastView = shallowCopy(ngModelCtrl.$viewValue);\n            ngModelCtrl.$render();\n          }\n          lastViewRef = ngModelCtrl.$viewValue;\n        });\n\n        // If we are a multiple select then value is now a collection\n        // so the meaning of $isEmpty changes\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n\n      }\n    }\n\n    function selectPostLink(scope, element, attrs, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      var ngModelCtrl = ctrls[1];\n      if (!ngModelCtrl) return;\n\n      var selectCtrl = ctrls[0];\n\n      // We delegate rendering to the `writeValue` method, which can be changed\n      // if the select can have multiple selected values or if the options are being\n      // generated by `ngOptions`.\n      // This must be done in the postLink fn to prevent $render to be called before\n      // all nodes have been linked correctly.\n      ngModelCtrl.$render = function() {\n        selectCtrl.writeValue(ngModelCtrl.$viewValue);\n      };\n    }\n};\n\n\n// The option directive is purely designed to communicate the existence (or lack of)\n// of dynamically created (and destroyed) option elements to their containing select\n// directive via its controller.\nvar optionDirective = ['$interpolate', function($interpolate) {\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      var interpolateValueFn, interpolateTextFn;\n\n      if (isDefined(attr.ngValue)) {\n        // Will be handled by registerOption\n      } else if (isDefined(attr.value)) {\n        // If the value attribute is defined, check if it contains an interpolation\n        interpolateValueFn = $interpolate(attr.value, true);\n      } else {\n        // If the value attribute is not defined then we fall back to the\n        // text content of the option element, which may be interpolated\n        interpolateTextFn = $interpolate(element.text(), true);\n        if (!interpolateTextFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function(scope, element, attr) {\n        // This is an optimization over using ^^ since we don't want to have to search\n        // all the way to the root of the DOM for every single option element\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl) {\n          selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn);\n        }\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRequired\n * @restrict A\n *\n * @param {expression} ngRequired AngularJS expression. If it evaluates to `true`, it sets the\n *                                `required` attribute to the element and adds the `required`\n *                                {@link ngModel.NgModelController#$validators `validator`}.\n *\n * @description\n *\n * ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.\n * It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be\n * applied to custom controls.\n *\n * The directive sets the `required` attribute on the element if the AngularJS expression inside\n * `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we\n * cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}\n * for more info.\n *\n * The validator will set the `required` error key to true if the `required` attribute is set and\n * calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the\n * {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the\n * `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing\n * custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.\n *\n * @example\n * <example name=\"ngRequiredDirective\" module=\"ngRequiredExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('ngRequiredExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.required = true;\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"form\">\n *         <label for=\"required\">Toggle required: </label>\n *         <input type=\"checkbox\" ng-model=\"required\" id=\"required\" />\n *         <br>\n *         <label for=\"input\">This input must be filled if `required` is true: </label>\n *         <input type=\"text\" ng-model=\"model\" id=\"input\" name=\"input\" ng-required=\"required\" /><br>\n *         <hr>\n *         required error set? = <code>{{form.input.$error.required}}</code><br>\n *         model = <code>{{model}}</code>\n *       </form>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n       var required = element(by.binding('form.input.$error.required'));\n       var model = element(by.binding('model'));\n       var input = element(by.id('input'));\n\n       it('should set the required error', function() {\n         expect(required.getText()).toContain('true');\n\n         input.sendKeys('123');\n         expect(required.getText()).not.toContain('true');\n         expect(model.getText()).toContain('123');\n       });\n *   </file>\n * </example>\n */\nvar requiredDirective = ['$parse', function($parse) {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      // For boolean attributes like required, presence means true\n      var value = attr.hasOwnProperty('required') || $parse(attr.ngRequired)(scope);\n\n      if (!attr.ngRequired) {\n        // force truthy in case we are on non input element\n        // (input elements do this automatically for boolean attributes like required)\n        attr.required = true;\n      }\n\n      ctrl.$validators.required = function(modelValue, viewValue) {\n        return !value || !ctrl.$isEmpty(viewValue);\n      };\n\n      attr.$observe('required', function(newVal) {\n\n        if (value !== newVal) {\n          value = newVal;\n          ctrl.$validate();\n        }\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngPattern\n * @restrict A\n *\n * @param {expression|RegExp} ngPattern AngularJS expression that must evaluate to a `RegExp` or a `String`\n *                                      parsable into a `RegExp`, or a `RegExp` literal. See above for\n *                                      more details.\n *\n * @description\n *\n * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.\n * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.\n *\n * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}\n * does not match a RegExp which is obtained from the `ngPattern` attribute value:\n * - the value is an AngularJS expression:\n *   - If the expression evaluates to a RegExp object, then this is used directly.\n *   - If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it\n *     in `^` and `$` characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n * - If the value is a RegExp literal, e.g. `ngPattern=\"/^\\d+$/\"`, it is used directly.\n *\n * <div class=\"alert alert-info\">\n * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n * start at the index of the last search's match, thus not taking the whole input value into\n * account.\n * </div>\n *\n * <div class=\"alert alert-info\">\n * **Note:** This directive is also added when the plain `pattern` attribute is used, with two\n * differences:\n * <ol>\n *   <li>\n *     `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is\n *     not available.\n *   </li>\n *   <li>\n *     The `ngPattern` attribute must be an expression, while the `pattern` value must be\n *     interpolated.\n *   </li>\n * </ol>\n * </div>\n *\n * @example\n * <example name=\"ngPatternDirective\" module=\"ngPatternExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('ngPatternExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.regex = '\\\\d+';\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"form\">\n *         <label for=\"regex\">Set a pattern (regex string): </label>\n *         <input type=\"text\" ng-model=\"regex\" id=\"regex\" />\n *         <br>\n *         <label for=\"input\">This input is restricted by the current pattern: </label>\n *         <input type=\"text\" ng-model=\"model\" id=\"input\" name=\"input\" ng-pattern=\"regex\" /><br>\n *         <hr>\n *         input valid? = <code>{{form.input.$valid}}</code><br>\n *         model = <code>{{model}}</code>\n *       </form>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n       var model = element(by.binding('model'));\n       var input = element(by.id('input'));\n\n       it('should validate the input with the default pattern', function() {\n         input.sendKeys('aaa');\n         expect(model.getText()).not.toContain('aaa');\n\n         input.clear().then(function() {\n           input.sendKeys('123');\n           expect(model.getText()).toContain('123');\n         });\n       });\n *   </file>\n * </example>\n */\nvar patternDirective = ['$parse', function($parse) {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    compile: function(tElm, tAttr) {\n      var patternExp;\n      var parseFn;\n\n      if (tAttr.ngPattern) {\n        patternExp = tAttr.ngPattern;\n\n        // ngPattern might be a scope expression, or an inlined regex, which is not parsable.\n        // We get value of the attribute here, so we can compare the old and the new value\n        // in the observer to avoid unnecessary validations\n        if (tAttr.ngPattern.charAt(0) === '/' && REGEX_STRING_REGEXP.test(tAttr.ngPattern)) {\n          parseFn = function() { return tAttr.ngPattern; };\n        } else {\n          parseFn = $parse(tAttr.ngPattern);\n        }\n      }\n\n      return function(scope, elm, attr, ctrl) {\n        if (!ctrl) return;\n\n        var attrVal = attr.pattern;\n\n        if (attr.ngPattern) {\n          attrVal = parseFn(scope);\n        } else {\n          patternExp = attr.pattern;\n        }\n\n        var regexp = parsePatternAttr(attrVal, patternExp, elm);\n\n        attr.$observe('pattern', function(newVal) {\n          var oldRegexp = regexp;\n\n          regexp = parsePatternAttr(newVal, patternExp, elm);\n\n          if ((oldRegexp && oldRegexp.toString()) !== (regexp && regexp.toString())) {\n            ctrl.$validate();\n          }\n        });\n\n        ctrl.$validators.pattern = function(modelValue, viewValue) {\n          // HTML5 pattern constraint validates the input value, so we validate the viewValue\n          return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);\n        };\n      };\n    }\n\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngMaxlength\n * @restrict A\n *\n * @param {expression} ngMaxlength AngularJS expression that must evaluate to a `Number` or `String`\n *                                 parsable into a `Number`. Used as value for the `maxlength`\n *                                 {@link ngModel.NgModelController#$validators validator}.\n *\n * @description\n *\n * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.\n * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.\n *\n * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}\n * is longer than the integer obtained by evaluating the AngularJS expression given in the\n * `ngMaxlength` attribute value.\n *\n * <div class=\"alert alert-info\">\n * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two\n * differences:\n * <ol>\n *   <li>\n *     `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint\n *     validation is not available.\n *   </li>\n *   <li>\n *     The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be\n *     interpolated.\n *   </li>\n * </ol>\n * </div>\n *\n * @example\n * <example name=\"ngMaxlengthDirective\" module=\"ngMaxlengthExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('ngMaxlengthExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.maxlength = 5;\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"form\">\n *         <label for=\"maxlength\">Set a maxlength: </label>\n *         <input type=\"number\" ng-model=\"maxlength\" id=\"maxlength\" />\n *         <br>\n *         <label for=\"input\">This input is restricted by the current maxlength: </label>\n *         <input type=\"text\" ng-model=\"model\" id=\"input\" name=\"input\" ng-maxlength=\"maxlength\" /><br>\n *         <hr>\n *         input valid? = <code>{{form.input.$valid}}</code><br>\n *         model = <code>{{model}}</code>\n *       </form>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n       var model = element(by.binding('model'));\n       var input = element(by.id('input'));\n\n       it('should validate the input with the default maxlength', function() {\n         input.sendKeys('abcdef');\n         expect(model.getText()).not.toContain('abcdef');\n\n         input.clear().then(function() {\n           input.sendKeys('abcde');\n           expect(model.getText()).toContain('abcde');\n         });\n       });\n *   </file>\n * </example>\n */\nvar maxlengthDirective = ['$parse', function($parse) {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var maxlength = attr.maxlength || $parse(attr.ngMaxlength)(scope);\n      var maxlengthParsed = parseLength(maxlength);\n\n      attr.$observe('maxlength', function(value) {\n        if (maxlength !== value) {\n          maxlengthParsed = parseLength(value);\n          maxlength = value;\n          ctrl.$validate();\n        }\n      });\n      ctrl.$validators.maxlength = function(modelValue, viewValue) {\n        return (maxlengthParsed < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlengthParsed);\n      };\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngMinlength\n * @restrict A\n *\n * @param {expression} ngMinlength AngularJS expression that must evaluate to a `Number` or `String`\n *                                 parsable into a `Number`. Used as value for the `minlength`\n *                                 {@link ngModel.NgModelController#$validators validator}.\n *\n * @description\n *\n * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.\n * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.\n *\n * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}\n * is shorter than the integer obtained by evaluating the AngularJS expression given in the\n * `ngMinlength` attribute value.\n *\n * <div class=\"alert alert-info\">\n * **Note:** This directive is also added when the plain `minlength` attribute is used, with two\n * differences:\n * <ol>\n *   <li>\n *     `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint\n *     validation is not available.\n *   </li>\n *   <li>\n *     The `ngMinlength` value must be an expression, while the `minlength` value must be\n *     interpolated.\n *   </li>\n * </ol>\n * </div>\n *\n * @example\n * <example name=\"ngMinlengthDirective\" module=\"ngMinlengthExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('ngMinlengthExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.minlength = 3;\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <form name=\"form\">\n *         <label for=\"minlength\">Set a minlength: </label>\n *         <input type=\"number\" ng-model=\"minlength\" id=\"minlength\" />\n *         <br>\n *         <label for=\"input\">This input is restricted by the current minlength: </label>\n *         <input type=\"text\" ng-model=\"model\" id=\"input\" name=\"input\" ng-minlength=\"minlength\" /><br>\n *         <hr>\n *         input valid? = <code>{{form.input.$valid}}</code><br>\n *         model = <code>{{model}}</code>\n *       </form>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n       var model = element(by.binding('model'));\n       var input = element(by.id('input'));\n\n       it('should validate the input with the default minlength', function() {\n         input.sendKeys('ab');\n         expect(model.getText()).not.toContain('ab');\n\n         input.sendKeys('abc');\n         expect(model.getText()).toContain('abc');\n       });\n *   </file>\n * </example>\n */\nvar minlengthDirective = ['$parse', function($parse) {\n  return {\n    restrict: 'A',\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n\n      var minlength = attr.minlength || $parse(attr.ngMinlength)(scope);\n      var minlengthParsed = parseLength(minlength) || -1;\n\n      attr.$observe('minlength', function(value) {\n        if (minlength !== value) {\n          minlengthParsed = parseLength(value) || -1;\n          minlength = value;\n          ctrl.$validate();\n        }\n\n      });\n      ctrl.$validators.minlength = function(modelValue, viewValue) {\n        return ctrl.$isEmpty(viewValue) || viewValue.length >= minlengthParsed;\n      };\n    }\n  };\n}];\n\n\nfunction parsePatternAttr(regex, patternExp, elm) {\n  if (!regex) return undefined;\n\n  if (isString(regex)) {\n    regex = new RegExp('^' + regex + '$');\n  }\n\n  if (!regex.test) {\n    throw minErr('ngPattern')('noregexp',\n      'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,\n      regex, startingTag(elm));\n  }\n\n  return regex;\n}\n\nfunction parseLength(val) {\n  var intVal = toInt(val);\n  return isNumberNaN(intVal) ? -1 : intVal;\n}\n\nif (window.angular.bootstrap) {\n  // AngularJS is already loaded, so we can return here...\n  if (window.console) {\n    console.log('WARNING: Tried to load AngularJS more than once.');\n  }\n  return;\n}\n\n// try to bind to jquery now so that one can write jqLite(fn)\n// but we will rebind on bootstrap again.\nbindJQuery();\n\npublishExternalAPI(angular);\n\nangular.module(\"ngLocale\", [], [\"$provide\", function($provide) {\nvar PLURAL_CATEGORY = {ZERO: \"zero\", ONE: \"one\", TWO: \"two\", FEW: \"few\", MANY: \"many\", OTHER: \"other\"};\nfunction getDecimals(n) {\n  n = n + '';\n  var i = n.indexOf('.');\n  return (i == -1) ? 0 : n.length - i - 1;\n}\n\nfunction getVF(n, opt_precision) {\n  var v = opt_precision;\n\n  if (undefined === v) {\n    v = Math.min(getDecimals(n), 3);\n  }\n\n  var base = Math.pow(10, v);\n  var f = ((n * base) | 0) % base;\n  return {v: v, f: f};\n}\n\n$provide.value(\"$locale\", {\n  \"DATETIME_FORMATS\": {\n    \"AMPMS\": [\n      \"AM\",\n      \"PM\"\n    ],\n    \"DAY\": [\n      \"Sunday\",\n      \"Monday\",\n      \"Tuesday\",\n      \"Wednesday\",\n      \"Thursday\",\n      \"Friday\",\n      \"Saturday\"\n    ],\n    \"ERANAMES\": [\n      \"Before Christ\",\n      \"Anno Domini\"\n    ],\n    \"ERAS\": [\n      \"BC\",\n      \"AD\"\n    ],\n    \"FIRSTDAYOFWEEK\": 6,\n    \"MONTH\": [\n      \"January\",\n      \"February\",\n      \"March\",\n      \"April\",\n      \"May\",\n      \"June\",\n      \"July\",\n      \"August\",\n      \"September\",\n      \"October\",\n      \"November\",\n      \"December\"\n    ],\n    \"SHORTDAY\": [\n      \"Sun\",\n      \"Mon\",\n      \"Tue\",\n      \"Wed\",\n      \"Thu\",\n      \"Fri\",\n      \"Sat\"\n    ],\n    \"SHORTMONTH\": [\n      \"Jan\",\n      \"Feb\",\n      \"Mar\",\n      \"Apr\",\n      \"May\",\n      \"Jun\",\n      \"Jul\",\n      \"Aug\",\n      \"Sep\",\n      \"Oct\",\n      \"Nov\",\n      \"Dec\"\n    ],\n    \"STANDALONEMONTH\": [\n      \"January\",\n      \"February\",\n      \"March\",\n      \"April\",\n      \"May\",\n      \"June\",\n      \"July\",\n      \"August\",\n      \"September\",\n      \"October\",\n      \"November\",\n      \"December\"\n    ],\n    \"WEEKENDRANGE\": [\n      5,\n      6\n    ],\n    \"fullDate\": \"EEEE, MMMM d, y\",\n    \"longDate\": \"MMMM d, y\",\n    \"medium\": \"MMM d, y h:mm:ss a\",\n    \"mediumDate\": \"MMM d, y\",\n    \"mediumTime\": \"h:mm:ss a\",\n    \"short\": \"M/d/yy h:mm a\",\n    \"shortDate\": \"M/d/yy\",\n    \"shortTime\": \"h:mm a\"\n  },\n  \"NUMBER_FORMATS\": {\n    \"CURRENCY_SYM\": \"$\",\n    \"DECIMAL_SEP\": \".\",\n    \"GROUP_SEP\": \",\",\n    \"PATTERNS\": [\n      {\n        \"gSize\": 3,\n        \"lgSize\": 3,\n        \"maxFrac\": 3,\n        \"minFrac\": 0,\n        \"minInt\": 1,\n        \"negPre\": \"-\",\n        \"negSuf\": \"\",\n        \"posPre\": \"\",\n        \"posSuf\": \"\"\n      },\n      {\n        \"gSize\": 3,\n        \"lgSize\": 3,\n        \"maxFrac\": 2,\n        \"minFrac\": 2,\n        \"minInt\": 1,\n        \"negPre\": \"-\\u00a4\",\n        \"negSuf\": \"\",\n        \"posPre\": \"\\u00a4\",\n        \"posSuf\": \"\"\n      }\n    ]\n  },\n  \"id\": \"en-us\",\n  \"localeID\": \"en_US\",\n  \"pluralCat\": function(n, opt_precision) {  var i = n | 0;  var vf = getVF(n, opt_precision);  if (i == 1 && vf.v == 0) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;}\n});\n}]);\n\n  jqLite(function() {\n    angularInit(window.document, bootstrap);\n  });\n\n})(window);\n\n!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend(window.angular.element('<style>').text('@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}'));","require('./angular');\nmodule.exports = angular;\n","import angular from \"angular\";\r\n\r\nimport { ApiCrudObject, ApiListItem, CrudApiBase, IUserObjectIndex, ODataQueryOptions, ODataResult, VersionInfo, WorkflowEvent } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ODataQueryController } from \"./ODataQueryController\";\r\n\r\n/**\r\n * Base class for version 03 CRUD controllers where OData list functionality has been\r\n * separated from the item editing CRUD functionality.\r\n * This version also shifts away from the old Service-infrastructure.\r\n */\r\nexport abstract class ApiCrudObjectController<TItem extends ApiCrudObject, TListItem extends ApiListItem> implements angular.IController {\r\n\r\n  /**\r\n   * Defines the binding mode of the component.\r\n   *\r\n   * - \"model\" takes the model directly from the model parameter.\r\n   * - \"parentCtrl\" takes the model from the given parent controller. Main actions (like Save, reload) are delegated to that controller.\r\n   * - \"id\" fetches the item from the server using the current-id attribute (currentId property).\r\n   * - \"url\" like \"id\", but the id is fetched from route parameters.\r\n   * - \"new\" Creates a new item as current.\r\n   * - \"null\": Current item is null\r\n   *\r\n   * The mode is set in the model property setter.\r\n   */\r\n  public bindingMode: \"id\" | \"url\" | \"model\" | \"parentCtrl\" | \"new\" | \"null\";\r\n\r\n  /** Action for the controller */\r\n  public action: \"default\" | \"copy-as-new\" | string;\r\n\r\n  /**\r\n   * For list-controls, this is the URL for item select event\r\n   * as well as the URL where a new item is edited. Basically showing the Details view.\r\n   * Id is added directly to the string and this is an angular route.\r\n   * I.e. use \"/calc/details/\" (not \"#/calc/details/\" or \"/calc/details\")\r\n   * For more control, use onListSelect or onCreateNew events.\r\n   * @example <salaxy-payroll-list details-url=\"/myCustomRoute/\"></salaxy-payroll-list>\r\n   */\r\n  public detailsUrl: string;\r\n\r\n  /**\r\n   * URL for the list view. At the moment, if specified, the browser is redirected here after delete.\r\n   * @example\r\n   * <!-- Main worker list is in the front page in this case -->\r\n   * <salaxy-employment-details list-url=\"/home\"></salaxy-employment-details>\r\n   */\r\n  public listUrl: string;\r\n\r\n  /** If the Crud controller is used from within a ODataQueryController, this is the containing controller. */\r\n  public odataController: ODataQueryController;\r\n\r\n  /** If the controller is bound to parent controller, the controller is set here. */\r\n  public parentController: ApiCrudObjectController<TItem, TListItem>;\r\n\r\n  /**\r\n   * Contains the inner value currentId if stored by this controller and not the parent.\r\n   */\r\n  protected _currentId: string;\r\n\r\n  /**\r\n   * The status of the data loading for the current controller.\r\n   */\r\n  private _status: \"noInit\" | \"initialLoading\" | \"loaded\" | \"reloading\" | \"loadError\" = \"noInit\";\r\n  private _current: TItem;\r\n\r\n  private _original: TItem;\r\n\r\n  private _model: any;\r\n\r\n  /** If true, current item is read only */\r\n  private _isReadOnlyForced: boolean;\r\n  private _versions: VersionInfo[];\r\n\r\n  private _versionsId: string;\r\n  private _version: { version: VersionInfo, item?: TItem };\r\n  private _versionId: string;\r\n\r\n  /** The status of the initialization process $onInit  */\r\n  protected initStatus = {\r\n    isInitDone: false,\r\n    isReloadRequested: false,\r\n  };\r\n\r\n  /**\r\n   * Creates a new CrudControllerBase.\r\n   * @param api Api module typically defined in @salaxy/core used for communicating to server.\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   * @param $location Angular.js Location service that is used for navigation. Especially the list views.\r\n   * @param $routeParams - Angular.js routing component\r\n   */\r\n  constructor(\r\n    protected api: CrudApiBase<TItem, TListItem>,\r\n    protected uiHelpers: UiHelpers,\r\n    protected $location: angular.ILocationService,\r\n    protected $routeParams: any,\r\n  ) {\r\n    if (!api) {\r\n      throw new Error(\"api is undefined in ApiCrudObjectController\");\r\n    }\r\n    if (!uiHelpers) {\r\n      throw new Error(\"uiHelpers is undefined in ApiCrudObjectController\");\r\n    }\r\n    if (!$location) {\r\n      throw new Error(\"$location is undefined in ApiCrudObjectController\");\r\n    }\r\n    if (!$routeParams) {\r\n      throw new Error(\"$routeParams is undefined in ApiCrudObjectController\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Implement IController by providing onInit method.\r\n   * We currently do nothing here, but if you override this function,\r\n   * you should call this method in base class for future compatibility.\r\n   */\r\n  public $onInit() {\r\n    this.bindingMode = this.bindingMode || \"null\";\r\n    if (this.initStatus.isReloadRequested) {\r\n      this.initStatus.isReloadRequested = false;\r\n      this.reload();\r\n    }\r\n    this.initStatus.isInitDone = true;\r\n  }\r\n\r\n  /** URL for the OData list service */\r\n  public get odataServiceUrl(): string {\r\n    return this.parentController ? this.parentController.odataServiceUrl : this.api.getODataUrl();\r\n  }\r\n\r\n  /**\r\n   * Set the Current selected item (the model).\r\n   * The model may be:\r\n   *\r\n   * - TItem: A bound item (default), which can also be null.\r\n   * - ApiCrudObjectController<TItem>: Parent controller of the same type. Model is fetched from its current and all methods are delegated.\r\n   * - \"new\": A new item is created.\r\n   * - \"url\": Fetches the item from the server using the id query string (crudItemId in routeParams).\r\n   * - string: Any other string is interpreted as id which is used to fetch the item from the server.\r\n   */\r\n  public set model(value: \"new\" | \"url\" | string | TItem | ApiCrudObjectController<TItem, TListItem>) {\r\n    this._model = value;\r\n    if (!value) {\r\n      this._currentId = null;\r\n      this.bindingMode = \"null\";\r\n      this.parentController = null;\r\n    } else if (value === \"new\") {\r\n      this._currentId = null;\r\n      this.bindingMode = \"new\";\r\n      this.parentController = null;\r\n    } else if (value === \"url\") {\r\n      this._currentId = this.getRouteData().id;\r\n      this.bindingMode = (this.currentId ? \"url\" : \"null\");\r\n      this.parentController = null;\r\n      this.action = this.action || this.getRouteData().action;\r\n    } else if (angular.isString(value)) {\r\n      this._currentId = value;\r\n      this.bindingMode = (this.currentId ? \"id\" : \"null\");\r\n      this.parentController = null;\r\n    } else {\r\n      if (value && (value as ApiCrudObjectController<TItem, TListItem>).$onInit) {\r\n        // If parent controller, we do not call reload() - it shold be called by the parent itself.\r\n        this.bindingMode = \"parentCtrl\";\r\n        this.parentController = value as ApiCrudObjectController<TItem, TListItem>;\r\n        this.action = this.parentController.action;\r\n        return;\r\n      } else {\r\n        this._currentId = null; // Getter gets it from the object itself.\r\n        this.bindingMode = \"model\";\r\n        this.parentController = null;\r\n      }\r\n    }\r\n    this.action = this.action || \"default\";\r\n    if (this.initStatus.isInitDone) {\r\n      this.reload();\r\n    } else {\r\n      this.initStatus.isReloadRequested = true;\r\n    }\r\n  }\r\n  /** Gets the Current selected item (the model).  */\r\n  public get model() {\r\n    return this._model;\r\n  }\r\n\r\n  /** Gets the Current selected item. */\r\n  public get current(): TItem {\r\n    return this.parentController ? this.parentController.current : this._current;\r\n  }\r\n\r\n  /** The current Id for the controller. */\r\n  public get currentId(): string {\r\n    if (this.parentController) {\r\n      return this.parentController.currentId;\r\n    }\r\n    return this._currentId || (this.current ? this.current.id : null);\r\n  }\r\n\r\n  /** Gets the Original item before changes. */\r\n  public get original(): TItem {\r\n    return this.parentController ? this.parentController.original : this._original;\r\n  }\r\n\r\n  /** Gets the isReadOnlyForced status. */\r\n  public get isReadOnlyForced(): boolean {\r\n    return this.parentController ? this.parentController.isReadOnlyForced : this._isReadOnlyForced;\r\n  }\r\n\r\n  /** Sets the isReadOnlyForced status. */\r\n  public set isReadOnlyForced(value: boolean) {\r\n    /* do not set values by non-bound variables */\r\n    if (value === undefined) {\r\n      return;\r\n    }\r\n    if (this.parentController) {\r\n      this.parentController.isReadOnlyForced = value;\r\n    } else {\r\n      this._isReadOnlyForced = value;\r\n    }\r\n  }\r\n  /**\r\n   * Gets the defaults for service-specific URLs, options etc.\r\n   * This method must be implemented when implementing ApiCrudObjectController.\r\n   */\r\n  public abstract getDefaults(): {\r\n    /**\r\n     * URL for the list view. This is list-url attribute with controller-specific default value (e.g. \"/articles\").\r\n     * At the moment, if specified, the browser is redirected here after delete.\r\n     */\r\n    listUrl: string,\r\n\r\n    /**\r\n     * For lists, this is the URL for item select event as well as the URL where a new item is edited.\r\n     * Basically showing the Details view. For more control, use onListSelect or onCreateNew events.\r\n     * This is details-url attribute with controller-specific default value.\r\n     * Id is added directly to the string and this is an angular route.\r\n     * I.e. use \"/calc/details/\" (not \"#/calc/details/\" or \"/calc/details\")\r\n     */\r\n    detailsUrl: string,\r\n\r\n    /** Template for displaying the items as list.  */\r\n    oDataTemplateUrl: string,\r\n\r\n    /** The OData options for default query. */\r\n    oDataOptions: ODataQueryOptions,\r\n  };\r\n\r\n  /** If true, this is a new unsaved object */\r\n  public isNew(): boolean {\r\n    if (this.parentController) {\r\n      return this.parentController.isNew();\r\n    }\r\n    return !this.currentId || this.currentId === \"new\" || this.action === \"copy-as-new\";\r\n  }\r\n\r\n  /** If true, the component is in the middle of loading data. */\r\n  public get isLoading() {\r\n    switch (this.status) {\r\n      case \"initialLoading\":\r\n      case \"reloading\":\r\n        return true;\r\n      case \"loaded\":\r\n      case \"loadError\":\r\n      case \"noInit\":\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * If true, the form controls should be disabled.\r\n   */\r\n  public get isDisabled() {\r\n    switch (this.status) {\r\n      case \"initialLoading\":\r\n      case \"reloading\":\r\n      case \"loadError\":\r\n      case \"noInit\":\r\n        return true;\r\n      case \"loaded\":\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * If true, the form controls should be read-only (no input control at all).\r\n   */\r\n  public get isReadOnly(): boolean {\r\n    return this.status === \"noInit\" || this.status === \"initialLoading\" || !this.current || this.current.isReadOnly || this.isReadOnlyForced || false;\r\n  }\r\n\r\n  /** Returns true, if the current object has changes. */\r\n  public get hasChanges(): boolean {\r\n    return this.parentController ? this.parentController.hasChanges : !angular.equals(this._original, this._current);\r\n  }\r\n\r\n  /**\r\n   * Gets the status of the data if it is being loaded from a remote server.\r\n   */\r\n  public get status(): \"noInit\" | \"initialLoading\" | \"loaded\" | \"reloading\" | \"loadError\" {\r\n    return this.parentController ? this.parentController.status : this._status;\r\n  }\r\n\r\n  /** Makes an OData query  */\r\n  public getOData(options: ODataQueryOptions, result: ODataResult<TListItem> = null): Promise<ODataResult<TListItem>> {\r\n    return this.api.getOData(options).then( (data) => {\r\n      if (result) {\r\n        Object.assign(result, data);\r\n      }\r\n      return result ?? data;\r\n    });\r\n  }\r\n\r\n  /** Returns base url of the underlying api. */\r\n  public getBaseUrl(): string {\r\n    return this.api.getBaseUrl();\r\n  }\r\n\r\n  /** Gets the data transmitted in the route / url */\r\n  public getRouteData(): {\r\n    /** id parameter in the route */\r\n    id: string,\r\n    /** Action parameter in the route. */\r\n    action: \"default\" | \"copy-as-new\" | string,\r\n  } {\r\n    const result = {\r\n      id: null,\r\n      action: null,\r\n    };\r\n    if (this.$routeParams && this.$routeParams.crudItemId) {\r\n      let crudItemIdArr = this.$routeParams.crudItemId.split(\"/\");\r\n      crudItemIdArr = crudItemIdArr.map(x => x ? x.replace(/[?&#](.*)/g, \"\") : x); // remove trailing parameters. eg. access_token\r\n      result.id = crudItemIdArr[0] || null;\r\n      if (crudItemIdArr[1]) {\r\n        result.action = crudItemIdArr[1];\r\n      }\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /** Save changes to the current item */\r\n  public save(options: any = undefined): Promise<TItem> {\r\n    if (this.parentController) {\r\n      return this.parentController.save(options);\r\n    }\r\n    const wasNew = this.isNew();\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n    this._status = \"reloading\";\r\n    return this.api.save(this.current, options)\r\n      .then((data) => {\r\n        loader.dismiss();\r\n        this._current = data;\r\n        this._original = angular.copy(data);\r\n        this._status = \"loaded\";\r\n        if (this.bindingMode === \"url\" && wasNew) {\r\n          this.$location.url(this.getDefaults().detailsUrl + data.id);\r\n          this.action = \"default\";\r\n        }\r\n        return data;\r\n      })\r\n      .catch((error) => {\r\n        loader.dismiss();\r\n        this._status = \"loadError\";\r\n        return null;\r\n      });\r\n  }\r\n\r\n  /** Reset the changes in the current element */\r\n  public reset(): TItem {\r\n    if (this.parentController) {\r\n      return this.parentController.reset();\r\n    }\r\n    return angular.copy(this._original, this._current);\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view for the item.\r\n   * Typically, this takes the user to a new page with the ID.\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showDetails(item: TItem | IUserObjectIndex): angular.ILocationService {\r\n    if (this.parentController) {\r\n      return this.parentController.showDetails(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item));\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view with a new item that is a copy of the given item.\r\n   * Typically, this takes the user to a new page with the ID with action \"copy-as-new\".\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showCopyAsNew(item: TItem | IUserObjectIndex): angular.ILocationService {\r\n    if (this.parentController) {\r\n      return this.parentController.showCopyAsNew(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item) + \"/copy-as-new\");\r\n  }\r\n\r\n  /**\r\n   * Shows the \"Are you sure?\" dialog and if user clicks OK, deletes the item.\r\n   * Cancels the started payment for the payroll too.\r\n   * @param item Item to be deleted.\r\n   * If not specified, the current item.\r\n   * @param confirmMessage Optional custom message for the confirm dialog.\r\n   * If not specified, a generic message is shown.\r\n   * If set to boolean false, the confirm message is not shown at all.\r\n   * @returns Promise that resolves to true if the item is deleted.\r\n   * False, if user cancels and fails if the deletion fails.\r\n   */\r\n  public delete = (item?: TItem, confirmMessage?: string): Promise<boolean> => {\r\n    if (this.parentController) {\r\n      return this.parentController.delete(item, confirmMessage);\r\n    }\r\n    item = item || this.current;\r\n    return this.uiHelpers.showConfirm(confirmMessage || \"SALAXY.NG1.ApiCrudObjectComponent.deleteDialog\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          return this.deleteNoConfirm(item).then(() => {\r\n            if (this.current === item) {\r\n              this._currentId = null;\r\n              this._current = null;\r\n              this._original = null;\r\n              this._status = \"noInit\";\r\n            }\r\n            if (this.odataController) {\r\n              this.odataController.reload();\r\n            } else {\r\n              this.$location.url(this.getDefaults().listUrl);\r\n            }\r\n            return true;\r\n          });\r\n        } else {\r\n          return Promise.resolve(false);\r\n        }\r\n      });\r\n  };\r\n\r\n  /**\r\n   * Gets the id for the object regardless of whther the object is Container or list item.\r\n   * Error is thrown if the item does not exist.\r\n   * The method is an extension point for future item types that may have other ID's in the future.\r\n   * @param item The item for which to fetch the ID.\r\n   */\r\n  public getId(item: TItem | IUserObjectIndex) {\r\n    if (!item) {\r\n      throw new Error(\"getId called for null item.\");\r\n    }\r\n    if ((item as IUserObjectIndex).containerGuid) {\r\n      return (item as IUserObjectIndex).containerGuid;\r\n    }\r\n    return item.id;\r\n  }\r\n\r\n  /**\r\n   * Deletes an item without showing the confirm dialog.\r\n   * The method shows the \"Please wait...\" loader, but does not refresh the\r\n   * list or move the browser to listUrl. The caller should take care\r\n   * of the UX actions after delete if necessary.\r\n   * @param item Item to be deleted.\r\n   * @returns Promise that resolves to true (never false). Fails if the deletion fails.\r\n   */\r\n  public deleteNoConfirm(item: TItem | IUserObjectIndex): Promise<boolean> {\r\n    if (this.parentController) {\r\n      return this.parentController.deleteNoConfirm(item);\r\n    }\r\n    if (!item) {\r\n      throw new Error(\"item not specified in deleteNoConfirm.\");\r\n    }\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return this.api.delete(this.getId(item)).then(() => {\r\n      loading.dismiss();\r\n      return true;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Creates a copy of a given item.\r\n   * This is a synchronous method that should basically convert a saved item to a new item.\r\n   * @param copySource Item (container item) to copy as new.\r\n   */\r\n  public copyItem(copySource: TItem): TItem {\r\n    // TODO: Consider moving to logic or probably API.\r\n    const copy = JSON.parse(JSON.stringify(copySource)) as TItem;\r\n    (copy as any).id = null;\r\n    (copy as any).owner = null;\r\n    (copy as any).isReadOnly = false;\r\n    return copy;\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process depending on the bindingMode:\r\n   */\r\n  public reload(): Promise<TItem> {\r\n    // TODO: The promise reloads here may require $scope.apply() so that .then() works on the promise.\r\n    // We should go through whether $scope.apply() should be added here instead of caller needing to worry about it.\r\n    if (this.parentController) {\r\n      this._currentId = this.parentController.currentId;\r\n      return this.parentController.reload().then((item) => {\r\n        this._currentId = this.parentController.currentId;\r\n        return item;\r\n      });\r\n    }\r\n    switch (this.bindingMode) {\r\n      case \"id\":\r\n      case \"url\":\r\n        if (this.bindingMode === \"url\") {\r\n          this._currentId = this.getRouteData().id;\r\n          if (!this.currentId) {\r\n            this.setCurrentRef(null);\r\n            this._status = \"loaded\";\r\n            return Promise.resolve<TItem>(this.current);\r\n          }\r\n        }\r\n        if (this.currentId === \"new\") {\r\n          this.setCurrentRef(this.api.getBlank());\r\n          this._currentId = null;\r\n          this._status = \"loaded\";\r\n          return Promise.resolve<TItem>(this.current);\r\n        }\r\n        // Reloads from server (status is set by the loading).\r\n        return this.setStatus(this.api.getSingle(this.currentId))\r\n          .then((item) => {\r\n            if (!item) {\r\n              this._status = \"loadError\";\r\n              throw new Error(`Item ${this.currentId} not found.`);\r\n            }\r\n            if (this.action === \"copy-as-new\") {\r\n              item = this.copyItem(item);\r\n            }\r\n            this.setCurrentRef(item);\r\n            return item;\r\n          });\r\n      case \"model\":\r\n        // Gets the model again from source.\r\n        this.setCurrentRef(this._model as TItem);\r\n        this._currentId = this.current ? this.current.id : null;\r\n        this._status = this.current ? \"loaded\" : \"noInit\";\r\n        return Promise.resolve<TItem>(this.current);\r\n      case \"parentCtrl\":\r\n        throw new Error(\"Binding mode parentCtrl without parentController.\");\r\n      case \"new\":\r\n        // Recreates a new item\r\n        this.setCurrentRef(this.api.getBlank());\r\n        this._currentId = null;\r\n        this._status = \"loaded\";\r\n        return Promise.resolve<TItem>(this.current);\r\n      case \"null\":\r\n      default:\r\n        // Sets the current as null.\r\n        this.setCurrentRef(null);\r\n        this._currentId = null;\r\n        this._status = \"loaded\";\r\n        return Promise.resolve<TItem>(this.current);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets the current item as the given object (reference to a new object).\r\n   * This also resets the original item. This method is typically used when the object is first loaded,\r\n   * when object that is being edited is changed or when object is reloaded from server after saving.\r\n   * @param item The new current item.\r\n   */\r\n  public setCurrentRef(item: TItem) {\r\n    if (this.parentController) {\r\n      return this.parentController.setCurrentRef(item);\r\n    }\r\n    this._current = item;\r\n    this._original = angular.copy(item);\r\n  }\r\n\r\n  /**\r\n   * Sets the current item value:\r\n   * The object reference remains the same, but all its properties are copied using angular.copy().\r\n   * Original object remains as-is by default. This method is typically used at the end of modifyinjg user interfaces.\r\n   * @param item The new current item.\r\n   * @param resetOriginal If true, also resets the orginal value.\r\n   */\r\n  public setCurrentValue(item: TItem, resetOriginal = false) {\r\n    if (this.parentController) {\r\n      return this.parentController.setCurrentValue(item, resetOriginal);\r\n    }\r\n    if (this._current) {\r\n      angular.copy(item, this._current);\r\n    } else {\r\n      // This should not really happen, but just in case the methods are used in a wrong way.\r\n      this._current = item;\r\n    }\r\n    if (resetOriginal) {\r\n      this._original = angular.copy(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets the current item. This also resets the original item.\r\n   * @param item The new current item.\r\n   * @param keepOriginalAsIs If true, will not update the original.\r\n   */\r\n  public setCurrent(item: TItem, keepOriginalAsIs = false): void {\r\n    if (this.parentController) {\r\n      return this.parentController.setCurrent(item, keepOriginalAsIs);\r\n    }\r\n    if (this._current) {\r\n      angular.copy(item, this._current);\r\n    } else {\r\n      this._current = item;\r\n    }\r\n    if (!keepOriginalAsIs) {\r\n      this._original = angular.copy(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Calls a promise updating the status on the controller.\r\n   * @param loadAction The promise that executes the loading from server.\r\n   * If action is null, the status is directly set as \"loaded\".\r\n   */\r\n  public setStatus(loadAction: Promise<TItem>): Promise<TItem> {\r\n    if (this.parentController) {\r\n      return this.parentController.setStatus(loadAction);\r\n    }\r\n    // eslint-disable-next-line @typescript-eslint/no-misused-promises\r\n    if (!loadAction) {\r\n      this._status = \"loaded\";\r\n      return null;\r\n    }\r\n    switch (this._status) {\r\n      case \"noInit\":\r\n        this._status = \"initialLoading\";\r\n        break;\r\n      case \"initialLoading\":\r\n        this._status = \"initialLoading\";\r\n        break;\r\n      case \"loadError\":\r\n        this._status = (this.current ? \"reloading\" : \"initialLoading\");\r\n        break;\r\n      case \"loaded\":\r\n        this._status = \"reloading\";\r\n        break;\r\n      case \"reloading\":\r\n        this._status = \"reloading\";\r\n        break;\r\n      default:\r\n        throw Error(\"Unexpected status: \" + this._status);\r\n    }\r\n    return loadAction.then((data) => {\r\n      this._status = \"loaded\";\r\n      return data;\r\n    })\r\n      .catch((error) => {\r\n        this._status = \"loadError\";\r\n        return null;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Adds/updates the workflow event for the current using API.\r\n   * @param wfEvent - Workflow event to add/update.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public saveWorkflowEvent(wfEvent: WorkflowEvent): Promise<TItem> {\r\n    return this.api.saveWorkflowEvent(this.current, wfEvent).then(() => {\r\n      return this.reload();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes the given event or all events with given type using API.\r\n   * @param wfIdOrType Id or type of the workflow event.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public deleteWorkflowEvent(wfIdOrType: string): Promise<TItem> {\r\n    return this.api.deleteWorkflowEvent(this.current, wfIdOrType).then(() => {\r\n      return this.reload();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a single workflow event for the item.\r\n   * @param wfId Id of the workflow event.\r\n   * @returns - Single workflow event\r\n   */\r\n  public getWorkflowEvent(wfId: string): Promise<WorkflowEvent> {\r\n    return this.api.getWorkflowEvent(this.current, wfId);\r\n  }\r\n\r\n  /** Returns the current api */\r\n  public getApi(): CrudApiBase<TItem, TListItem> {\r\n    return this.api;\r\n  }\r\n\r\n  /**\r\n   * Returns the versions for the current item.\r\n   */\r\n  public get versions(): VersionInfo[] {\r\n    if (!this._versions || this._versionsId !== this.currentId) {\r\n      this._versions = this._versions ?? [];\r\n      this._versions.splice(0,  this._versions.length);\r\n      this._versionsId = this.currentId;\r\n      if (this.currentId) {\r\n        this.api.getVersions(this.currentId).then((data) => {\r\n          this._versions.push(...data);\r\n        });\r\n      }\r\n    }\r\n    return this._versions;\r\n  }\r\n\r\n  /**\r\n   * Gets a version of the current item.\r\n   * @param version VersionInfo of the item.\r\n   */\r\n  public getVersion(version: VersionInfo): { version: VersionInfo, item?: TItem } {\r\n    if (!this._version || this._versionId !== `${this.currentId}-${version?.versionId}`) {\r\n      this._version = (this._version ?? { version: {}, item: null} as any);\r\n      angular.copy(version, this._version.version);\r\n      this._version.item = null;\r\n      this._versionId = `${this.currentId}-${version?.versionId}`;\r\n      if (this.currentId) {\r\n        this.api.getVersion(this.currentId, version?.versionId).then((data) => {\r\n          this._version.item = data;\r\n        });\r\n      }\r\n    }\r\n    return this._version;\r\n  }\r\n}\r\n","/**\r\n * Bindings for the components that use ApiCrudObjectController.\r\n */\r\nexport class ApiCrudObjectControllerBindings {\r\n\r\n  [boundProperty: string]: string;\r\n\r\n  /**\r\n   * URL to which the component navigates when an item is clicked.\r\n   * The \"id\" or \"rowIndex\" property of the selected item is added to the URL.\r\n   * URL is ignored if onListSelect is set. In this case, you may navigate yourself in that method.\r\n   * Id is added directly to the string and this is an angular route.\r\n   * I.e. use \"/calc/details/\" (not \"#/calc/details/\" or \"#/calc/details\")\r\n   * @example <salaxy-payroll-list details-url=\"/myCustomRoute/\"></salaxy-payroll-list>\r\n   */\r\n  public detailsUrl = \"@\";\r\n\r\n  /**\r\n   * URL for the list view. At the moment, if specified, the browser is redirected here after delete.\r\n   * @example\r\n   * <!-- Main worker list is in the front page in this case -->\r\n   * <salaxy-employment-details list-url=\"/home\"></salaxy-employment-details>\r\n   */\r\n  public listUrl = \"@\";\r\n\r\n  /**\r\n   * Set the Current selected item (the model).\r\n   * The model may be:\r\n   *\r\n   * - TItem: A bound item (default), which can also be null.\r\n   * - \"new\": A new item is created.\r\n   * - \"url\": Fetches the item from the server using the id query string (crudItemId in routeParams).\r\n   * - string: Any other string is interpreted as id which is used to fetch the item from the server.\r\n   */\r\n  public model = \"<\";\r\n\r\n   /** If true, current item is read only */\r\n  public isReadOnlyForced = \"<\";\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Base class for list controllers that edit a list of items within a parent object (parent property).\r\n * Abstract class implementation defines the location of list with items of type TListItem.\r\n * Typically, the list items do not have ID's, they and all operations are synchronous.\r\n * Save operation is currently done to the parent, it may be later connected also to this controller.\r\n */\r\nexport abstract class ListControllerBase<TParent, TListItem> implements angular.IController {\r\n\r\n  /**\r\n   * Original parent value for reset. This value is set when the controller is created.\r\n   */\r\n  public original: TParent;\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user interface indicates that\r\n   * the changes made by the list controller should be committed.\r\n   * Typically this would result to saving of the object.\r\n   * @example <salaxy-calc-rows on-commit=\"$ctrl.save()\"></salaxy-calc-rows>\r\n   */\r\n  public onCommit: (eventData: {\r\n    /** The parent object that contains the list (typically the one that is saved). */\r\n    parent: TParent,\r\n    /** The list that was modified by the control */\r\n    list: TListItem[],\r\n  }) => void;\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user interface indicates that\r\n   * the changes made by the list controller should be reset (canceled).\r\n   * Typically this would result to just closing the control, but some changes to the parent object may be necessary.\r\n   * @example <salaxy-calc-rows on-reset=\"$ctrl.resetParentThings()\"></salaxy-calc-rows>\r\n   */\r\n  public onReset: (eventData: {\r\n    /** The parent object that contains the list  (typically the one that is reset). */\r\n    parent: TParent,\r\n  }) => void;\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user switches from read-only mode to edit.\r\n   * Not all components support read-only vs. edit modes.\r\n   * Typically there is no action needed, but e.g. external menu items may be modified.\r\n   * @example <salaxy-calc-rows on-reset=\"$ctrl.showEditMenu()\"></salaxy-calc-rows>\r\n   */\r\n  public onStartEdit: (eventData: {\r\n    /** The parent object that contains the list  (typically the one that is reset). */\r\n    parent: TParent,\r\n  }) => void;\r\n\r\n  /**\r\n   * The edit mode of the component:\r\n   *\r\n   * - edit: Editable, if the calculation is editable.\r\n   * - read-edit: first read-only, but there is an edit button if the calculation is editable.\r\n   * - read-only: Always read-only.\r\n   *\r\n   * Note that not all components support the mode attribute. Also, the default depends on the component logic.\r\n   */\r\n  public mode: \"edit\" | \"read-edit\" | \"read-only\";\r\n\r\n  /** Parent object to which the component is bound.  */\r\n  private _parent: TParent;\r\n\r\n  protected _isInEdit: boolean;\r\n\r\n  /**\r\n   * Creates a new ListControllerBase.\r\n   * @param uiHelpers - Salaxy ui helpers service for dialogs etc.\r\n   */\r\n  constructor(\r\n      protected uiHelpers: UiHelpers,\r\n  ) {\r\n      if (!uiHelpers) {\r\n        throw new Error(\"uiHelpers is undefined in ListControllerBase\");\r\n      }\r\n  }\r\n\r\n  /**\r\n   * Implement IController by providing onInit method.\r\n   * We currently do nothing here, but if you override this function,\r\n   * you should call this method in base class for future compatibility.\r\n   */\r\n  public $onInit() {\r\n    // init here.\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the parent object that contains the list that is being edited.\r\n   * Typically this parent object is an ApiCrudObject.\r\n   */\r\n  public get parent(): TParent {\r\n    return this._parent;\r\n  }\r\n  public set parent(value: TParent) {\r\n    this.original =  angular.copy(this.parent);\r\n    this._parent = value;\r\n  }\r\n\r\n  /**\r\n   * When overriding the abstract class, you should provide the list within the parent that is edited / viewed.\r\n   * If the parent object is not provided or list is not otherwise available, you should provide null.\r\n   */\r\n  public abstract get list(): TListItem[];\r\n\r\n  /** The template URL for the edit dialog. Set to null if you do not want an edit dialog */\r\n  public abstract getEditDialogTemplateUrl(): string;\r\n\r\n  /**\r\n   * Possiblity to define additional logic that is passed to the edit dialog as $ctrl.logic.\r\n   * This may contain additional metadata as well as functions.\r\n   */\r\n  public getEditDialogLogic(): any {\r\n    return {};\r\n  }\r\n\r\n  /** When overriding the abstract class, provide her the factory method that creates a new list item. */\r\n  public abstract getBlank(): TListItem;\r\n\r\n  /** View should call this method if there is a UI component that fires commit (typically save) to the parent. */\r\n  public commit() {\r\n    this.isInEdit = false;\r\n    if (this.onCommit) {\r\n      // Note: When used as component (\"&\"-binding), there is always a value here even if no function is bound. This if is just for controller use without component.\r\n      this.onCommit({\r\n        parent: this.parent,\r\n        list: this.list,\r\n      });\r\n    }\r\n  }\r\n\r\n  /** View should call this method if there is a UI component that fires reset / cancel to the parent. */\r\n  public reset() {\r\n    this.isInEdit = false;\r\n    if (this.onReset) {\r\n      // Note: When used as component (\"&\"-binding), there is always a value here even if no function is bound. This if is just for controller use without component.\r\n      this.onReset({\r\n        parent: this.parent,\r\n        // TODO: Add possibility to signal that reset has been done (from parent back to child).\r\n      });\r\n    }\r\n    if (this.original) {\r\n      angular.copy(this.original, this.parent);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns true if the parent can be edited by this component.\r\n   * Takes into account parent being null, isReadOnly and the \"read-only\" mode of the component.\r\n   */\r\n  public get isEditable(): boolean {\r\n    if (!this.parent || (this.parent as any).isReadOnly || this.mode === \"read-only\") {\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the flag telling whether the component is in edit or read-only mode.\r\n   * This is restricted by the mode and isReadOnly of the parent calculation.\r\n   */\r\n  public get isInEdit(): boolean {\r\n    if (!this.isEditable) {\r\n      return false;\r\n    }\r\n    if (this.mode === \"edit\") {\r\n      return true;\r\n    }\r\n    return !!this._isInEdit;\r\n  }\r\n  public set isInEdit(value: boolean) {\r\n    this._isInEdit = value;\r\n  }\r\n\r\n  /**\r\n   * View should call this method if the component is changed from read-only mode to edit mode.\r\n   * Not all components support read-only vs. edit modes.\r\n   */\r\n  public startEdit() {\r\n    if (this.isEditable) {\r\n      this.isInEdit = true;\r\n      this.onStartEdit({\r\n        parent: this.parent,\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Deletes an item from list (no confirm etc.)\r\n   * The method shows the \"Please wait...\" loader, but does not call onDelete\r\n   * or move the browser to listUrl. The caller should take care\r\n   * of the UX actions after delete if necessary.\r\n   * @param item Item to delete.\r\n   * @returns Promise that resolves to true (never false). Fails if the deletion fails.\r\n   */\r\n  public delete(item: TListItem): TListItem[] {\r\n    return this.list.splice(this.list.indexOf(item), 1);\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog.\r\n   * @param item Item to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: TListItem | \"new\", isNew = false) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    if (item === \"new\") {\r\n      isNew = true;\r\n      item = this.getBlank();\r\n    }\r\n    this.uiHelpers.openEditDialog(this.getEditDialogTemplateUrl(), item, this.getEditDialogLogic()).then((result) => {\r\n      if (result.action === \"ok\" || result.action === \"ok-no-save\" ) {\r\n        if (isNew) {\r\n          this.list.push(result.item);\r\n        }\r\n        if (( isNew || result.hasChanges) && result.action !== \"ok-no-save\") {\r\n          this.commit();\r\n        }\r\n      } else if (result.action === \"delete\" || result.action === \"delete-no-save\") {\r\n        if (!isNew) {\r\n          this.delete(item as TListItem);\r\n          if (result.action !== \"delete-no-save\" ) {\r\n            this.commit();\r\n          }\r\n        }\r\n      } else {\r\n        // No changes, cancel\r\n      }\r\n      });\r\n  }\r\n}\r\n","/**\r\n * Bindings for the component which uses ListControllerBase.\r\n */\r\nexport class ListControllerBaseBindings {\r\n\r\n  /**\r\n   * Parent object that contains the list that is being edited.\r\n   * Typically this parent object is an ApiCrudObject.\r\n   */\r\n  public parent = \"<\";\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user interface indicates that\r\n   * the changes made by the list controller should be committed.\r\n   * Typically this would result to saving of the object.\r\n   * @example <salaxy-calc-rows on-commit=\"$ctrl.save()\"></salaxy-calc-rows>\r\n   */\r\n  public onCommit = \"&\";\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user interface indicates that\r\n   * the changes made by the list controller should be reset (canceled).\r\n   * Typically this would result to just closing the control, but some changes to the parent object may be necessary.\r\n   * @example <salaxy-calc-rows on-reset=\"$ctrl.resetParentThings()\"></salaxy-calc-rows>\r\n   */\r\n  public onReset = \"&\";\r\n\r\n  /**\r\n   * Event that is fired by the list controller if the user switches from read-only mode to edit (within the component).\r\n   * Typically there is no action needed, but e.g. external menu items may be modified.\r\n   * Not all components support read-only vs. edit modes.\r\n   * @example <salaxy-calc-rows on-reset=\"$ctrl.showEditMenu()\"></salaxy-calc-rows>\r\n   */\r\n  public onStartEdit = \"&\";\r\n\r\n  /**\r\n   * Sets the component edit mode (true/false).\r\n   * This is typically subject to isReadOnly (i.e. if isReadOnly is true on parent, true value is ignored).\r\n   * Edit mode depends on the component UI logic and not all components support editable or non-editable modes.\r\n   */\r\n  public isInEdit = \"<\";\r\n\r\n  /**\r\n   * The edit mode of the component:\r\n   *\r\n   * - edit: Editable, if the calculation is editable.\r\n   * - read-edit: first read-only, but there is an edit button if the calculation is editable.\r\n   * - read-only: Always read-only.\r\n   *\r\n   * Note that not all components support the mode attribute.\r\n   * Also, the default depends on the component logic and component may offer additional modes (e.g. calendar).\r\n   */\r\n  public mode = \"@\";\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AjaxNg1 } from \"../../ajax\";\r\nimport { ODataQueryController } from \"./ODataQueryController\";\r\n\r\n/**\r\n * Controller that provides helper methods in components inside ODataQueryController.\r\n */\r\nexport class ODataHelperController  implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\"];\r\n\r\n  /** Signals that the component should render a table column header with orderby (OData sort) */\r\n  public orderby: string;\r\n\r\n  /**\r\n   * Manually defined URL for the nextPageLink.\r\n   * Browser is directed to this URL instead of loading more data from nextPageLink.\r\n   */\r\n  public nextPageUrl: string;\r\n\r\n  /** The parent ODataQueryController that contains the list and all the methods. */\r\n  public $odata: ODataQueryController;\r\n\r\n  constructor(private ajax: AjaxNg1) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n      // Init\r\n  };\r\n\r\n  /**\r\n   * Gets the \"No items\" message if there is no items to show.\r\n   * Null, if there are rows to show.\r\n   * The message changesdepending on the situation: No items, Not initiated, Authentication required.\r\n   */\r\n  public getNoItemsMessage() {\r\n    if (this.$odata.items && this.$odata.items.length > 0) {\r\n      return null;\r\n    }\r\n    if (!this.$odata.options.anon && this.ajax.getTokenStatus() !== \"ok\") {\r\n      return \"SALAXY.NG1.ODataFooterComponent.getNoItemsMessage.anon\";\r\n    }\r\n    if (this.$odata.status === \"noInit\") {\r\n      // NOTE: This message is for developers => Does not need to be translated.\r\n      return \"OData Service not initialized: Set url property or call setUrl().\";\r\n    }\r\n    if (this.$odata.status === \"loadError\") {\r\n      return \"SALAXY.NG1.ODataFooterComponent.getNoItemsMessage.loadError\";\r\n    }\r\n    if (this.$odata.status === \"reloading\") {\r\n      return null; // Show previous results, just dimmed (opacity 0.7)\r\n    }\r\n    if (this.$odata.status === \"initialLoading\") {\r\n      return \"SALAXY.UI_Terms.loading\";\r\n    }\r\n    if (this.$odata.status === \"loaded\") {\r\n      return \"SALAXY.NG1.ODataFooterComponent.getNoItemsMessage.noItems\";\r\n    }\r\n    return \"SALAXY.NG1.ODataFooterComponent.getNoItemsMessage.noItems\";\r\n  }\r\n\r\n  /** Gets the CSS classes for No items message  */\r\n  public getNoItemsCssClass() {\r\n    if (this.$odata.items && this.$odata.items.length > 0) {\r\n      return \"\";\r\n    }\r\n    if (this.$odata.status === \"noInit\" || this.$odata.status === \"loadError\") {\r\n      // Also invalid token is either noInit or loadError at the moment.\r\n      return \"alert alert-danger\";\r\n    }\r\n    return \"alert alert-default\";\r\n  }\r\n\r\n  /** Gets the paging view to show */\r\n  public getPagingView(): \"clientLimit\" | \"nextPageLink\" | \"url\" | \"allVisible\" {\r\n    if (this.$odata.nextPageLink) {\r\n      return this.nextPageUrl ? \"url\" : \"nextPageLink\";\r\n    }\r\n    if (this.$odata.options.$top) {\r\n      if (this.$odata.count) {\r\n        if (this.$odata.count > this.$odata.items.length) {\r\n          return this.nextPageUrl ? \"url\" : \"clientLimit\";\r\n        } else {\r\n          return \"allVisible\";\r\n        }\r\n      } else {\r\n        if (!this.$odata.items || this.$odata.items.length < ((this.$odata.options.$skip || 0) + this.$odata.options.$top)) {\r\n          return \"allVisible\";\r\n        } else {\r\n          return this.nextPageUrl ? \"url\" : \"clientLimit\";\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiListItem, ApiCrudObject, CrudApiBase, OData, ODataQueryOptions, ODataResult, progressNotification, Ajax } from \"@salaxy/core\";\r\n\r\nimport { AjaxNg1 } from \"../../ajax\";\r\nimport { CacheService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * User interface logic for making and displaying an OData query and displaying its results as list.\r\n */\r\nexport class ODataQueryController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"CacheService\", \"AjaxNg1\", \"$timeout\", \"$scope\", \"$controller\", \"UiHelpers\"];\r\n\r\n  /**\r\n   * CRUD controller that implements Delete and potentially other methods about the object.\r\n   * If you wish to use this in the view use \"as $controllerName\" syntax\r\n   * @example\r\n   * <salaxy-odata-table crud-controller=\"PayrollCrudController as $crud\" crud-bindings=\"{ myProp: 'foobar' }\">\r\n   */\r\n  public crudController: string;\r\n\r\n  /**\r\n   * Optional bindings for the CRUD controller. All properties are set to crudController before calling init.\r\n   * @example\r\n   * <salaxy-odata-table crud-controller=\"PayrollCrudController as $crud\" crud-bindings=\"{ myProp: 'foobar' }\">\r\n   */\r\n  public crudBindings: { [key: string]: any; };\r\n\r\n  /** OData endpoint URL */\r\n  public url: string;\r\n\r\n  /** The status of the data loading */\r\n  public _status: \"noInit\" | \"initialLoading\" | \"loaded\" | \"reloading\" | \"loadError\" = \"noInit\";\r\n\r\n  /**\r\n   * If true, the items collection has data.\r\n   * This means that items is not null. It may be an empty array though if there is nothing coming from data source.\r\n   */\r\n  public hasData: boolean;\r\n\r\n  /** Query options for the next query */\r\n  public options: ODataQueryOptions;\r\n\r\n  /** Items once loaded from the server. This is an empty array when the loading starts. */\r\n  public items: any[];\r\n\r\n  /** Total count of the items (server-side/storage) if updated in the previous query. */\r\n  public count: number | null = null;\r\n\r\n  /** Link for the next page if available in the previous query */\r\n  public nextPageLink: string = null;\r\n\r\n  /** Data passed from the parent to the component / view */\r\n  public data: any;\r\n\r\n  /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n  public readOnly: any;\r\n\r\n  /** Selected search items */\r\n  public selectedItems: any[];\r\n\r\n  /** If set, uses caching to store cache result between controller loads. */\r\n  public cacheKey: string;\r\n\r\n  /** Time in milliseconds when the data was loaded.  */\r\n  public loadedAt: number;\r\n\r\n  /** Optional OData reader. Defaults to AjaxNg1.getJSON -method */\r\n  public reader: {\r\n     /** Gets a JSON-message from server using the API */\r\n     getJSON: (method: string ) => Promise<any>,\r\n  } = null;\r\n\r\n  /**\r\n   * Function that is called when user selects an item in the list.\r\n   * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n   * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n   * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n   */\r\n  public onListSelect: (params: {\r\n    /** In multi-select mode, the value may be true (selected) or false (unselected). */\r\n    value: true | false,\r\n    /** Item that was last selected / deselected. */\r\n    item: any,\r\n    /** All items that are currently selected. */\r\n    allItems: any[],\r\n  }) => void;\r\n\r\n  /** Function that is called when the data has been loaded and set as values of the items. */\r\n  public onDataLoaded: (params: {\r\n    /** If true, the load was append to previous values. */\r\n    append: boolean,\r\n    /** The resulted data */\r\n    result: ODataResult<any>,\r\n  }) => void;\r\n\r\n  /**\r\n   * When list is used as selection (dialog) specifies whether the selection is single or multiple.\r\n   * NOTE: Currently only affects select all buttons. Later implementations may use to implement single/multiple selections.\r\n   */\r\n  public selectMode: \"multiselect\" | \"select\";\r\n\r\n  /** Used in the searchChanged function if the searchType is \"other\" (potentially some other special searches in the future). */\r\n  public rawSearchStringOther: string;\r\n\r\n  /** Used in the searchChanged function if the searchType is \"owner\" (potentially some other special searches in the future). */\r\n  public rawSearchStringOwner: string;\r\n\r\n  /** HACK: Extract interface */\r\n  private $crudController: ApiCrudObjectController<ApiCrudObject, ApiListItem>;\r\n\r\n  private filterTimeout: any;\r\n\r\n  /**\r\n   * Creates a new controller instance\r\n   * @ignore\r\n   */\r\n  constructor(\r\n\r\n    protected cacheService: CacheService,\r\n    private ajax: AjaxNg1,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $scope: angular.IScope,\r\n    private $controller: angular.IControllerService,\r\n    private uiHelpers: UiHelpers,\r\n  ) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n\r\n    if (!this.reader) {\r\n      this.reader = this.ajax;\r\n    }\r\n\r\n    if (!this.options) {\r\n      this.options = {\r\n        $count: false,\r\n      };\r\n    }\r\n    if (this.crudController) {\r\n      this.$crudController = this.$controller(this.crudController, { $scope: this.$scope });\r\n      this.$crudController.odataController = this;\r\n      if (this.crudBindings) {\r\n        Object.keys(this.crudBindings).forEach((key) => {\r\n          this.$crudController[key] = this.crudBindings[key];\r\n        });\r\n      }\r\n      this.$crudController.$onInit();\r\n    }\r\n    this.selectedItems = this.selectedItems || [];\r\n    this.items = this.items || [];\r\n\r\n    this.reload();\r\n  };\r\n\r\n  /**\r\n   * Cleaning the timeout.\r\n   */\r\n  public $onDestroy = () => {\r\n    if (angular.isDefined(this.filterTimeout)) {\r\n      this.$timeout.cancel(this.filterTimeout);\r\n    }\r\n  };\r\n\r\n  /**\r\n   * Gets the status of the data if it is being loaded from a remote server.\r\n   */\r\n  public get status(): \"noInit\" | \"initialLoading\" | \"loaded\" | \"reloading\" | \"loadError\" {\r\n    return this._status;\r\n  }\r\n\r\n  /**\r\n   * Set the URL and start reload.\r\n   * @param url OData enndpoint\r\n   * @param queryOptions Optional initial query options.\r\n   */\r\n  public setUrl(url: string, queryOptions?: ODataQueryOptions) {\r\n    this.url = url;\r\n    this.options = queryOptions || this.options;\r\n    this.reload();\r\n  }\r\n\r\n  /**\r\n   * Sets query options. Does not trigger reload.\r\n   * @param queryOptions Query options.\r\n   */\r\n  public setQueryOptions(queryOptions?: ODataQueryOptions) {\r\n    this.options = queryOptions || this.options;\r\n  }\r\n\r\n  /**\r\n   * Method to set the sort by for a column\r\n   * @param column Column to sort by\r\n   * @param direction Optional direction is either \"asc\" for ascending or \"desc\" for descending.\r\n   * If direction is not set, will reverse the sort order or ascending being the default.\r\n   */\r\n  public orderBy(column: string, direction?: \"asc\" | \"desc\") {\r\n    if (!direction) {\r\n      const currentOrder = this.getColumnOrder(column);\r\n      direction = currentOrder === \"asc\" ? \"desc\" : \"asc\";\r\n    }\r\n    this.options.$orderby = column + \" \" + direction;\r\n    this.options.$skip = 0; // Consider not resetting this, when implementing client-side paging.\r\n    this.reload();\r\n    return;\r\n  }\r\n\r\n  /**\r\n   * Sets a column filter and reloads the data set.\r\n   * @param column Name of the column.\r\n   * Set the column name as null, if you want to clear all filters.\r\n   * @param value Value of the filter. Null clears the filter (not filter-by-null).\r\n   * TODO: This could potententially be a comma separated value if requirement comes up.\r\n   * @param operation Possibility to negate the equality.\r\n   * @param andFilters If set, adds these additional filters (with and) to the new primary filter.\r\n   * @param valueType Type for the value. Default is string, other option is date\r\n   */\r\n  public setFilter(column: string | null, value: string, operation: \"eq\" | \"ne\" = \"eq\", andFilters?: string, valueType =\"string\"): void {\r\n    if (column && value) {\r\n      this.options.$filter = `${column} ${operation || \"eq\"} ` + (valueType == \"date\" ? `${value}` : `'${value}'`);\r\n      if (andFilters) {\r\n        this.options.$filter += \" and (\" + andFilters + \")\";\r\n      }\r\n    } else {\r\n      this.options.$filter = andFilters || null;\r\n    }\r\n    this.options.$skip = 0;\r\n    this.reload();\r\n  }\r\n\r\n  /**\r\n   * Gets the text indicating the time that has passed since the data was loaded.\r\n   */\r\n  public getLoadedTime(unit: \"min\" | \"10sec\" | \"sec\" = \"min\"): number {\r\n    if (!this.loadedAt) {\r\n      return null;\r\n    }\r\n    const ms = new Date().getTime() - this.loadedAt;\r\n    switch (unit) {\r\n      case \"min\":{\r\n        const minutes = Math.floor(ms / 60000);\r\n        if (minutes < 1) {\r\n          return null;\r\n        }\r\n        return minutes;\r\n      }\r\n      case \"10sec\":\r\n        return Math.floor(ms / 10000) * 10;\r\n      case \"sec\":\r\n        return Math.floor(ms / 1000);\r\n    }\r\n  }\r\n\r\n  /** Clears the cache and reloads from the server. */\r\n  public refresh() {\r\n    this.cacheService.clear(this.cacheKey);\r\n    this.reload();\r\n  }\r\n\r\n  /** Clears the entire cache - all keys and reloads. */\r\n  public refreshClearAll() {\r\n    this.cacheService.clearAllKeys();\r\n    this.reload();\r\n  }\r\n\r\n  /**\r\n   * Sets an item as selected.\r\n   * @param item Item to set as selected\r\n   * @param value Selected true / false or \"toggle\" to toggle to other value.\r\n   */\r\n  public setSelected(item: any, value: true | false | \"toggle\" = true) {\r\n    // TODO: This now only supports items with id. Add other identifiers if necessary.\r\n    const ix = this.selectedItems.findIndex((x) => x.id === item.id);\r\n    const exists = ix >= 0;\r\n    if (exists) {\r\n      this.selectedItems.splice(ix, 1);\r\n    }\r\n    switch (value) {\r\n      case true:\r\n        this.selectedItems.push(item);\r\n        break;\r\n      case false:\r\n        // Already done\r\n        break;\r\n      case \"toggle\":\r\n        if (!exists) {\r\n          this.selectedItems.push(item);\r\n        }\r\n        break;\r\n    }\r\n    this.onListSelect({\r\n      value: value === \"toggle\" ? !exists : value,\r\n      item,\r\n      allItems: this.selectedItems,\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns true if the item is selected.\r\n   * @param item Item to check for selected value.\r\n   */\r\n  public isSelected(item: any) {\r\n    return this.selectedItems.findIndex((x) => x.id === item.id) >= 0;\r\n  }\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n    if (this.selectedItems) {\r\n      this.selectedItems.splice(0, this.selectedItems.length);\r\n    }\r\n  }\r\n\r\n  /** Select all */\r\n  public selectAll() {\r\n    if (this.selectedItems && this.items) {\r\n      this.selectedItems.splice(0, this.selectedItems.length);\r\n      this.selectedItems.push(...this.items);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets a column ordering for the specified column.\r\n   * @param columnName Name of the column\r\n   * @returns Column order \"asc\" or \"desc\" if column is being sorted. Otherwise null.\r\n   */\r\n  public getColumnOrder(columnName: string): \"asc\" | \"desc\" | null {\r\n    if (!columnName) {\r\n      return null;\r\n    }\r\n    if (!(this.options.$orderby || \"\").trim()) {\r\n      return null;\r\n    }\r\n    const columns = this.options.$orderby.split(\",\");\r\n    for (const colSpec of columns) {\r\n      const colArr = colSpec.trim().split(/\\s+/);\r\n      if (colArr[0].trim().toLowerCase() === columnName.trim().toLowerCase()) {\r\n        return colArr.length > 1 && colArr[1].trim().toLowerCase() === \"desc\" ? \"desc\" : \"asc\";\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Loads items on next page\r\n   * @param append If true, appends the data of the next page link to the current set of items\r\n   */\r\n  public loadNextPage(append: boolean) {\r\n    if (this.nextPageLink) {\r\n      const queryString = this.nextPageLink.indexOf(\"?\");\r\n      if (queryString >= 0) {\r\n        const searchParams = new URLSearchParams(this.nextPageLink.substr(queryString));\r\n        if (searchParams.get(\"$skip\")) {\r\n          this.options.$skip = Number(searchParams.get(\"$skip\"));\r\n        }\r\n      }\r\n      this.loadData(this.options, append);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Called by the view when the search text changes\r\n   * @param searchType If \"owner\" or \"other\", the search is performed as owner:search or other:search and the search string is taken from rawSearchString.\r\n   * By default, the search string should be bound to options.$search or options.fullSearch.\r\n   */\r\n  public searchChanged(searchType: \"default\" | \"owner\" | \"other\" | \"both\" = \"default\") {\r\n    if (searchType == \"other\") {\r\n      this.options.fullSearch = `${searchType}:${this.rawSearchStringOther || \"\"}`;\r\n    }\r\n    if (searchType == \"owner\") {\r\n      this.options.fullSearch = `${searchType}:${this.rawSearchStringOwner || \"\"}`;\r\n    }\r\n    if (searchType == \"both\") {\r\n      this.options.fullSearch = `owner:${this.rawSearchStringOwner || \"\"} AND other:${this.rawSearchStringOther || \"\"}`;\r\n    }\r\n    this.options.$skip = 0;\r\n    this.reloadWithDelay(500);\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process.\r\n   * @param delay Loading occurs asyncronously after the specified delay\r\n   */\r\n  public reloadWithDelay(delay: number): void {\r\n    if (!this.getUrl()) {\r\n      return;\r\n    }\r\n    if (angular.isDefined(this.filterTimeout)) {\r\n      this.$timeout.cancel(this.filterTimeout);\r\n    }\r\n    this.filterTimeout = this.$timeout(() => {\r\n      this.loadData(this.options, false);\r\n    }, delay);\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process.\r\n   * @returns A promise of OData result as returned by setValues() method.\r\n   */\r\n  public reload(): Promise<ODataResult<any>> {\r\n    if (!this.getUrl()) {\r\n      return;\r\n    }\r\n    if (angular.isDefined(this.filterTimeout)) {\r\n      this.$timeout.cancel(this.filterTimeout);\r\n    }\r\n    return this.loadData(this.options, false);\r\n  }\r\n\r\n  /** Gets the URL for the server request using the current url and queryOptions */\r\n  public getUrl() {\r\n    const baseUrl = this.url || (this.$crudController ? this.$crudController.odataServiceUrl : null);\r\n    if (!baseUrl) {\r\n      return null;\r\n    }\r\n\r\n    return OData.getUrl(baseUrl, this.options);\r\n  }\r\n\r\n  /** If true, the component is in the middle of loading data. */\r\n  public get isLoading() {\r\n    switch (this.status) {\r\n      case \"initialLoading\":\r\n      case \"reloading\":\r\n        return true;\r\n      case \"loaded\":\r\n      case \"loadError\":\r\n      case \"noInit\":\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the CSS classes for OData table container.\r\n   * Main function is to get the `salaxy-loading class`.\r\n   * Also renders `salaxy-component salaxy-odata-table` for convenience\r\n   */\r\n  public getCssClass() {\r\n    return \"salaxy-component salaxy-odata-table\"\r\n      + \" salaxy-odata-table-status-\" + this.status\r\n      + (this.isLoading ? \" salaxy-odata-table-loading\" : \"\");\r\n  }\r\n\r\n  /**\r\n   * Sets the values to items from an OData result.\r\n   * @param data Data as returned from the Ajax component. This is expected being either ODataResult or array of items.\r\n   * @param append If true, appends the result to existing values. Used particularly with nextPageLink if this is used fo \"Load more\", not \"Next page\".\r\n   * @returns The data harmonized as OData result.\r\n   */\r\n  public setValues(data: any, append = false): ODataResult<any> {\r\n    const result = OData.getODataResult<any>(data);\r\n\r\n    this.items = this.items || [];\r\n    if (!append && this.items.length > 0) {\r\n       // remove values\r\n       this.items.splice(0, this.items.length);\r\n    }\r\n    this.items.push(...result.items);\r\n    this.count = result.count;\r\n    this.nextPageLink = result.nextPageLink;\r\n    this.hasData = true;\r\n    this.loadedAt = data.$loaded || new Date().getTime(); // Cache service injects loaded time in $loaded.\r\n    if (this.onDataLoaded) {\r\n      this.onDataLoaded({ append, result });\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Calls a promise updating the status on the controller.\r\n   * @param loadAction The promise that executes the loading from server.\r\n   */\r\n  public setStatus(loadAction: Promise<ODataResult<any>>): Promise<ODataResult<any>> {\r\n    switch (this._status) {\r\n      case \"noInit\":\r\n        this._status = \"initialLoading\";\r\n        break;\r\n      case \"initialLoading\":\r\n        // TODO: We should somehow cancel the first call and run only the last one.\r\n        this._status = \"initialLoading\";\r\n        break;\r\n      case \"loadError\":\r\n        this._status = (this.items ? \"reloading\" : \"initialLoading\");\r\n        break;\r\n      case \"loaded\":\r\n        this._status = \"reloading\";\r\n        break;\r\n      case \"reloading\":\r\n        // TODO: We should somehow cancel the first call and run only the last one.\r\n        this._status = \"reloading\";\r\n        break;\r\n      default:\r\n        throw Error(\"Unexpected status: \" + this._status);\r\n    }\r\n    return loadAction.then((data) => {\r\n      this._status = \"loaded\";\r\n      return data;\r\n    })\r\n      .catch((error) => {\r\n        this._status = \"loadError\";\r\n        return null;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Returns the current crud api.\r\n   */\r\n  public getApi(): CrudApiBase<any, any> {\r\n    if ( this.$crudController ) {\r\n      return this.$crudController.getApi();\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Export items. Does not update cache or current items.\r\n   * @param maxCount - maximum number of items to return.\r\n   * maxCount can have the following values:\r\n   * - ```0``` Return all items from the data source.\r\n   * - ```-1``` Return only the currently listed items using the current $filter and $search.\r\n   * - ```n``` Where n is any positive number, returns the given number of items. Should be more than 50 (default page size).\r\n   * @param notify -  function for notifying progress.\r\n   */\r\n  public exportItems(maxCount: number, notify: progressNotification<void> = null): Promise<ApiListItem[]> {\r\n    if (maxCount == -1) {\r\n      return Promise.resolve(this.items || []);\r\n    }\r\n    // TODO: See if all this IF's is really necessary\r\n    if (this.url) {\r\n      return OData.exportItems(this.url, {}, this.reader as Ajax, notify);\r\n    }\r\n    else if (this.$crudController)\r\n    {\r\n      return OData.exportItems(this.$crudController.getApi().getODataUrl(), {}, this.reader as Ajax, notify);\r\n    }\r\n    else\r\n    {\r\n      return Promise.resolve([]);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Makes a http call to server using the curre\r\n   * @param options - Options based on which the OData query is created.\r\n   * @param append - If true, appends the result to the data.\r\n   * @returns A promise of OData result as returned by setValues() method.\r\n   */\r\n  protected loadData(options: ODataQueryOptions, append = false): Promise<ODataResult<any>> {\r\n    // HACK: Go though this logic: When to use the strongly typed API and how to enable hard-coded url.\r\n    const url = this.getUrl();\r\n    if (!append && this.cacheService.hasData(this.cacheKey, url)) {\r\n      // TODO: Consider should we support append in cache as well?\r\n      return this.setStatus(Promise.resolve(this.setValues(this.cacheService.getData(this.cacheKey, url), append)));\r\n    }\r\n    if (this.url) {\r\n      // URL has been overriden\r\n      return this.setStatus(this.reader.getJSON(url).then((data) => {\r\n        this.cacheService.setData(this.cacheKey, url, data, 5 * 60);\r\n        return this.setValues(data, append);\r\n      }));\r\n    }\r\n\r\n    if (this.$crudController) {\r\n      return this.setStatus(this.$crudController.getOData(options).then((data) => {\r\n        this.cacheService.setData(this.cacheKey, url, data, 5 * 60);\r\n        return this.setValues(data, append);\r\n      }));\r\n    }\r\n\r\n    throw Error(\"No url given for OData queries\");\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Certificate, Certificates } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Plain CRUD controller for Certificates.\r\n */\r\nexport class CertificateCrudController extends ApiCrudObjectController<Certificate, never> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Certificates\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n  ];\r\n\r\n  constructor(\r\n    private fullApi: Certificates,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/certificates\",\r\n      detailsUrl: this.detailsUrl || \"/certificates/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Certificates.html\",\r\n      oDataOptions: { },\r\n    };\r\n  }\r\n}\r\n","\r\n/**\r\n * Known dialog actions: Buttons that result in closing the dialog.\r\n * A dialog action can be a string for special purposes, but if the dialog action is something clerly reuasable, you may add it here.\r\n */\r\nexport enum EditDialogKnownActions {\r\n  /** Primary action of the dialog: Often Save (Insert / Update) */\r\n  Ok = \"ok\",\r\n\r\n  /** Primary action of the dialog: Often Save (Insert / Update). Does not perform any save operation against api. */\r\n  OkNoCommit = \"ok-no-save\",\r\n\r\n  /**\r\n   * Cancel / reset dialog action.\r\n   * Also the close button at the top-right corner, esc keyboard action and clicking outside dialog when available.\r\n   */\r\n  Cancel = \"cancel\",\r\n\r\n  /**\r\n   * Delete item action in editor windows.\r\n   */\r\n  Delete = \"delete\",\r\n\r\n  /**\r\n   * Delete item action in editor windows. Does not perform any delete operation against api.\r\n   */\r\n  DeleteNoCommit = \"delete-no-save\",\r\n}\r\n","/**\r\n * Parameters that are passed to an Edit dialog using uiHelpers.openEditDialog()\r\n * and potentially in the future by other logic.\r\n */\r\nexport class EditDialogParameters<TItem> {\r\n\r\n  /** The edited item - published as $ctrl.current within the view. */\r\n  public current: TItem;\r\n\r\n  /**\r\n   * Additional logic that can be used to pass small functions and non-item parameters / data to view.\r\n   * Large amounts of logic should be passed as custom controllers.\r\n   * Published as $ctrl.logic within the view.\r\n   */\r\n  public logic: any;\r\n}\r\n","import { EditDialogKnownActions } from \"./EditDialogKnownActions\";\r\n\r\n/** Result from a modal dialog */\r\nexport class EditDialogResult<TItem> {\r\n\r\n  /**\r\n   * Result of the modal is typically either OK or Cancel.\r\n   * Edit dialogs often also have \"delete\", but you may add custom actions.\r\n   */\r\n  public action: EditDialogKnownActions | string;\r\n\r\n  /**\r\n   * Result is the object that Dialog sends back in $close() method.\r\n   * If this is string, it is interpreted as action.\r\n   */\r\n  public result: EditDialogKnownActions | string | {\r\n     /** Action of the result. */\r\n     action?: EditDialogKnownActions | string,\r\n     } | any;\r\n\r\n  /**\r\n   * Data that is being edited in the dialog.\r\n   */\r\n  public item: TItem;\r\n\r\n  /**\r\n   * The logic part should typically contain functions for the modal view, but in exceptional\r\n   * scenarios you may pass some data back here as well.\r\n   */\r\n  public logic: any;\r\n\r\n  /** If true, the item has been edited by the user and should typically be saved. */\r\n  public hasChanges: boolean;\r\n}\r\n","import { AjaxNg1 } from \"../../ajax\";\r\n\r\n/**\r\n * Handles error, warning and debug alerts and other such error handling situations.\r\n * Default functionality is to find #salaxy-alert-container and insert a bootstrap alert box into that container.\r\n */\r\nexport class AlertService {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$rootScope\", \"$timeout\", \"$sce\"];\r\n\r\n    /** Default duration for alerts to be visible */\r\n    public duration = 10;\r\n\r\n    /** Service level counter of alerts. Used for identifier. */\r\n    private alertCounter = 0;\r\n\r\n    private alerts: {\r\n      /** Id for the alert. */\r\n      id: number,\r\n      /** Message of the alert. */\r\n      message: string,\r\n      /** Type of the alert. */\r\n      alertType: string,\r\n    }[] = [];\r\n\r\n    private eventPrefix = \"alert\";\r\n\r\n    /** Dependency injection etc. */\r\n    constructor(private $rootScope: angular.IRootScopeService, private $timeout: angular.ITimeoutService, private $sce: angular.ISCEService) {\r\n        this.init();\r\n    }\r\n\r\n    /**\r\n     * Adds an error message\r\n     * @param message Message to add\r\n     */\r\n    public addError(message: string): void { this.addAlert(message, \"danger\"); }\r\n\r\n    /**\r\n     * Adds a warning message\r\n     * @param message Message to add\r\n     */\r\n    public addWarning(message: string): void { this.addAlert(message, \"warning\"); }\r\n\r\n    /**\r\n     * Adds a success message\r\n     * @param message Message to add\r\n     */\r\n    public addSuccess(message: string): void { this.addAlert(message, \"success\"); }\r\n\r\n    /**\r\n     * Adds an info message\r\n     * @param message Message to add\r\n     */\r\n    public addInfo(message: string): void { this.addAlert(message, \"info\"); }\r\n\r\n    /**\r\n     * Last message - consider this a temporary implementation of the custom alert handling\r\n     * @returns Last message\r\n     */\r\n    public getLastMessage(): string {\r\n        return this.alerts[this.alerts.length - 1].message || null;\r\n    }\r\n\r\n    /**\r\n     * Last alertType is bootstrap type: info (default), success, warning or danger.\r\n     * Consider this a temporary implementation of the custom alert handling\r\n     * @returns Last alert type\r\n     */\r\n    public getLastAlertType(): string {\r\n        return this.alerts[this.alerts.length - 1].alertType || null;\r\n    }\r\n\r\n    /**\r\n     * INTERNAL ONLY: This functionality is under consideration.\r\n     * We may not support it in the future and we may remove it without it being a breaking change.\r\n     *\r\n     * Controllers can subscribe to changes in service data using this method.\r\n     * Read more about the pattern in: http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/\r\n     * @ignore\r\n     * @param scope - Controller scope for the subscribing controller (or directive etc.)\r\n     * @param callback - The event listener function. See $on documentation for details\r\n     */\r\n    public onChange(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n        const handler = this.$rootScope.$on(this.eventPrefix + \"-service-event\", callback);\r\n        scope.$on(\"$destroy\", handler);\r\n    }\r\n\r\n    /**\r\n     * Attaches the alert service to AjaxNg1.\r\n     * The init is currently called automatically in constructor, but here you can make an explicit call.\r\n     */\r\n    public init() {\r\n      AjaxNg1.alertService = this;\r\n    }\r\n\r\n    /**\r\n     * Adds an alert message\r\n     * @param message - A message text for the Alert. Preferably a short text so that it fits to the pull-righ box.\r\n     * @param alertType - Bootstrap color code for the alert info (default), success, warning or danger\r\n     */\r\n    private addAlert(message: string, alertType: \"info\" | \"success\" | \"warning\" | \"danger\"): void {\r\n\r\n        const alert = {\r\n            message,\r\n            alertType: alertType || \"info\",\r\n            id: this.alertCounter++,\r\n        };\r\n\r\n        this.alerts.push(alert);\r\n        this.notify();\r\n        this.renderAlerts();\r\n\r\n        this.$timeout(() => {\r\n            this.alerts.splice(0, 1);\r\n            this.notify();\r\n            this.renderAlerts();\r\n        }, 1000 * this.duration);\r\n    }\r\n\r\n    private renderAlerts() {\r\n        const container = document.getElementById(\"salaxy-alert-container\");\r\n        if (!container) {\r\n            return;\r\n        }\r\n\r\n        const hiddenAlerts = [];\r\n        const currentList = container.children;\r\n        for (let i = 0; i < currentList.length; i++) {\r\n            if (currentList[i].classList.contains(\"hide\")) {\r\n                hiddenAlerts.push(currentList[i].id);\r\n            }\r\n        }\r\n\r\n        let html = \"\";\r\n        const length = this.alerts.length;\r\n        for (let i = length; i-- !== 0;) {\r\n            const alert = this.alerts[i];\r\n            const alertElementId = \"salaxy-alert-id-\" + alert.id;\r\n            if (hiddenAlerts.find((x) => x === alertElementId)) {\r\n                continue;\r\n            }\r\n\r\n            html += `<div id=\"${alertElementId}\" class=\"alert alert-${alert.alertType} alert-dismissible\" role=\"alert\">\r\n            ${this.$sce.getTrustedHtml(alert.message)}\r\n            <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\" onclick=\"document.getElementById('${alertElementId}').classList.toggle('hide');\">\r\n              <span aria-hidden=\"true\">&times;</span>\r\n            </button>\r\n          </div>`;\r\n        }\r\n        container.innerHTML = html;\r\n    }\r\n\r\n    private notify(): void {\r\n        this.$rootScope.$emit(this.eventPrefix + \"-service-event\");\r\n    }\r\n}\r\n","/* eslint-disable */\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n/* Allowed flush values; see deflate() and inflate() below for details */\nvar Z_NO_FLUSH =          0;\nvar Z_PARTIAL_FLUSH =     1;\nvar Z_SYNC_FLUSH =        2;\nvar Z_FULL_FLUSH =        3;\nvar Z_FINISH =            4;\nvar Z_BLOCK =             5;\nvar Z_TREES =             6;\n\n/* Return codes for the compression/decompression functions. Negative values\n* are errors, positive values are used for special but normal events.\n*/\nvar Z_OK =                0;\nvar Z_STREAM_END =        1;\nvar Z_NEED_DICT =         2;\nvar Z_ERRNO =            -1;\nvar Z_STREAM_ERROR =     -2;\nvar Z_DATA_ERROR =       -3;\n//export var Z_MEM_ERROR =      -4;\nvar Z_BUF_ERROR =        -5;\n//export var Z_VERSION_ERROR =  -6;\n\n/* compression levels */\nvar Z_NO_COMPRESSION =          0;\nvar Z_BEST_SPEED =              1;\nvar Z_BEST_COMPRESSION =        9;\nvar Z_DEFAULT_COMPRESSION =    -1;\n\n\nvar Z_FILTERED =                1;\nvar Z_HUFFMAN_ONLY =            2;\nvar Z_RLE =                     3;\nvar Z_FIXED =                   4;\nvar Z_DEFAULT_STRATEGY =        0;\n\n/* Possible values of the data_type field (though see inflate()) */\nvar Z_BINARY =                  0;\nvar Z_TEXT =                    1;\n//export var Z_ASCII =                 1; // = Z_TEXT (deprecated)\nvar Z_UNKNOWN =                 2;\n\n/* The deflate compression method */\nvar Z_DEFLATED =                8;\n//export var Z_NULL =                  null // Use -1 or null inline; depending on var type\n\n/* eslint-disable */\n\nfunction _has(obj, key) {\n  return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nfunction assign(obj /*from1, from2, from3, ...*/) {\n  var sources = Array.prototype.slice.call(arguments, 1);\n  while (sources.length) {\n    var source = sources.shift();\n    if (!source) { continue; }\n\n    if (typeof source !== 'object') {\n      throw new TypeError(source + 'must be non-object');\n    }\n\n    for (var p in source) {\n      if (_has(source, p)) {\n        obj[p] = source[p];\n      }\n    }\n  }\n\n  return obj;\n}\n\n\n// reduce buffer size, avoiding mem copy\nfunction shrinkBuf(buf, size) {\n  if (buf.length === size) { return buf; }\n  if (buf.subarray) { return buf.subarray(0, size); }\n  buf.length = size;\n  return buf;\n}\n\nvar fnTyped = {\n  arraySet: function (dest, src, src_offs, len, dest_offs) {\n    if (src.subarray && dest.subarray) {\n      dest.set(src.subarray(src_offs, src_offs + len), dest_offs);\n      return;\n    }\n    // Fallback to ordinary array\n    for (var i = 0; i < len; i++) {\n      dest[dest_offs + i] = src[src_offs + i];\n    }\n  },\n  // Join array of chunks to single array.\n  flattenChunks: function (chunks) {\n    var i, l, len, pos, chunk, result;\n\n    // calculate data length\n    len = 0;\n    for (i = 0, l = chunks.length; i < l; i++) {\n      len += chunks[i].length;\n    }\n\n    // join chunks\n    result = new Uint8Array(len);\n    pos = 0;\n    for (i = 0, l = chunks.length; i < l; i++) {\n      chunk = chunks[i];\n      result.set(chunk, pos);\n      pos += chunk.length;\n    }\n\n    return result;\n  },\n  Buf8: function(size) {\n    return new Uint8Array(size);\n  },\n  Buf16: function(size) {\n    return new Uint16Array(size);\n  },\n  Buf32: function(size) {\n    return new Int32Array(size);\n  }\n};\n\nvar fnUntyped = {\n  arraySet: function (dest, src, src_offs, len, dest_offs) {\n    for (var i = 0; i < len; i++) {\n      dest[dest_offs + i] = src[src_offs + i];\n    }\n  },\n  // Join array of chunks to single array.\n  flattenChunks: function (chunks) {\n    return [].concat.apply([], chunks);\n  },\n  Buf8: function(size) {\n    return new Array(size);\n  },\n  Buf16: function(size) {\n    return new Array(size);\n  },\n  Buf32: function(size) {\n    return new Array(size);\n  }\n};\n\nvar typedOK = function () {\n  var supported =\n    (typeof Uint8Array !== 'undefined') &&\n    (typeof Uint16Array !== 'undefined') &&\n    (typeof Int32Array !== 'undefined');\n\n  typedOK = function () { return supported; };\n  return supported;\n};\n\nvar arraySet = function (dest, src, src_offs, len, dest_offs) {\n  arraySet = typedOK() ?\n    fnTyped.arraySet : fnUntyped.arraySet;\n\n  return arraySet(dest, src, src_offs, len, dest_offs);\n};\n\nvar flattenChunks = function (chunks) {\n  flattenChunks = typedOK() ?\n    fnTyped.flattenChunks : fnUntyped.flattenChunks;\n\n  return flattenChunks(chunks);\n};\n\nvar Buf8 = function (size) {\n  Buf8 = typedOK() ? fnTyped.Buf8 : fnUntyped.Buf8;\n  return Buf8(size);\n};\n\nvar Buf16 = function (size) {\n  Buf16 = typedOK() ? fnTyped.Buf16 : fnUntyped.Buf16;\n  return Buf16(size);\n};\n\nvar Buf32 = function (size) {\n  Buf32 = typedOK() ? fnTyped.Buf32 : fnUntyped.Buf32;\n  return Buf32(size);\n};\n\n/* eslint-disable */\n\n\n// Quick check if we can use fast array to bin string conversion\n//\n// - apply(Array) can fail on Android 2.2\n// - apply(Uint8Array) can fail on iOS 5.1 Safari\nvar strApplyOK = function() {\n    var result = true;\n    try {\n        String.fromCharCode.apply(null, [ 0 ]);\n    } catch (_) {\n        result = false;\n    }\n\n    strApplyOK = function () { return result; };\n    return result;\n};\n\nvar strApplyUintOK = function() {\n    var result = true;\n    try {\n        String.fromCharCode.apply(null, new Uint8Array(1));\n    } catch (_) {\n        result = false;\n    }\n\n    strApplyUintOK = function () { return result; };\n    return result;\n};\n\nvar utf8len = function(c) {\n    // Table with utf8 lengths (calculated by first byte of sequence)\n    // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n    // because max possible codepoint is 0x10ffff\n    var table = Buf8(256);\n    for (var q = 0; q < 256; q++) {\n      table[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);\n    }\n    table[254] = table[254] = 1; // Invalid sequence start\n\n    utf8len = function (arg) { return table[arg]; };\n    return table[c];\n};\n\n// convert string to array (typed, when possible)\nfunction string2buf(str) {\n  var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;\n\n  // count binary size\n  for (m_pos = 0; m_pos < str_len; m_pos++) {\n    c = str.charCodeAt(m_pos);\n    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n      c2 = str.charCodeAt(m_pos + 1);\n      if ((c2 & 0xfc00) === 0xdc00) {\n        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n        m_pos++;\n      }\n    }\n    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;\n  }\n\n  // allocate buffer\n  buf = new Uint8Array(buf_len);\n\n  // convert\n  for (i = 0, m_pos = 0; i < buf_len; m_pos++) {\n    c = str.charCodeAt(m_pos);\n    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n      c2 = str.charCodeAt(m_pos + 1);\n      if ((c2 & 0xfc00) === 0xdc00) {\n        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n        m_pos++;\n      }\n    }\n    if (c < 0x80) {\n      /* one byte */\n      buf[i++] = c;\n    } else if (c < 0x800) {\n      /* two bytes */\n      buf[i++] = 0xC0 | (c >>> 6);\n      buf[i++] = 0x80 | (c & 0x3f);\n    } else if (c < 0x10000) {\n      /* three bytes */\n      buf[i++] = 0xE0 | (c >>> 12);\n      buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n      buf[i++] = 0x80 | (c & 0x3f);\n    } else {\n      /* four bytes */\n      buf[i++] = 0xf0 | (c >>> 18);\n      buf[i++] = 0x80 | (c >>> 12 & 0x3f);\n      buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n      buf[i++] = 0x80 | (c & 0x3f);\n    }\n  }\n\n  return buf;\n}\n\n// Helper (used in 2 places)\nfunction _buf2binstring(buf, len) {\n  // On Chrome, the arguments in a function call that are allowed is `65534`.\n  // If the length of the buffer is smaller than that, we can use this optimization,\n  // otherwise we will take a slower path.\n  if (len < 65534) {\n    if ((buf.subarray && strApplyUintOK()) || (!buf.subarray && strApplyOK())) {\n      return String.fromCharCode.apply(null, shrinkBuf(buf, len));\n    }\n  }\n\n  var result = '';\n  for (var i = 0; i < len; i++) {\n    result += String.fromCharCode(buf[i]);\n  }\n  return result;\n}\n\n\n// Convert byte array to binary string\nfunction buf2binstring(buf) {\n  return _buf2binstring(buf, buf.length);\n}\n\n\n// Convert binary string (typed, when possible)\nfunction binstring2buf(str) {\n  var buf = new Uint8Array(str.length);\n  for (var i = 0, len = buf.length; i < len; i++) {\n    buf[i] = str.charCodeAt(i);\n  }\n  return buf;\n}\n\n\n// convert array to string\nfunction buf2string(buf, max) {\n  var i, out, c, c_len;\n  var len = max || buf.length;\n\n  // Reserve max possible length (2 words per char)\n  // NB: by unknown reasons, Array is significantly faster for\n  //     String.fromCharCode.apply than Uint16Array.\n  var utf16buf = new Array(len * 2);\n\n  for (out = 0, i = 0; i < len;) {\n    c = buf[i++];\n    // quick process ascii\n    if (c < 0x80) { utf16buf[out++] = c; continue; }\n\n    c_len = utf8len(c);\n    // skip 5 & 6 byte codes\n    if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }\n\n    // apply mask on first byte\n    c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;\n    // join the rest\n    while (c_len > 1 && i < len) {\n      c = (c << 6) | (buf[i++] & 0x3f);\n      c_len--;\n    }\n\n    // terminated by end of string?\n    if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }\n\n    if (c < 0x10000) {\n      utf16buf[out++] = c;\n    } else {\n      c -= 0x10000;\n      utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);\n      utf16buf[out++] = 0xdc00 | (c & 0x3ff);\n    }\n  }\n\n  return _buf2binstring(utf16buf, out);\n}\n\n\n// Calculate max possible position in utf8 buffer,\n// that will not break sequence. If that's not possible\n// - (very small limits) return max size as is.\n//\n// buf[] - utf8 bytes array\n// max   - length limit (mandatory);\nfunction utf8border(buf, max) {\n  var pos;\n\n  max = max || buf.length;\n  if (max > buf.length) { max = buf.length; }\n\n  // go back from last position, until start of sequence found\n  pos = max - 1;\n  while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }\n\n  // Very small and broken sequence,\n  // return max, because we should return something anyway.\n  if (pos < 0) { return max; }\n\n  // If we came to start of buffer - that means buffer is too small,\n  // return max too.\n  if (pos === 0) { return max; }\n\n  return (pos + utf8len(buf[pos]) > max) ? pos : max;\n}\n\n/* eslint-disable */\n\n// Note: adler32 takes 12% for level 0 and 2% for level 6.\n// It isn't worth it to make additional optimizations as in original.\n// Small size is preferable.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction adler32(adler, buf, len, pos) {\n  var s1 = (adler & 0xffff) |0,\n      s2 = ((adler >>> 16) & 0xffff) |0,\n      n = 0;\n\n  while (len !== 0) {\n    // Set limit ~ twice less than 5552, to keep\n    // s2 in 31-bits, because we force signed ints.\n    // in other case %= will fail.\n    n = len > 2000 ? 2000 : len;\n    len -= n;\n\n    do {\n      s1 = (s1 + buf[pos++]) |0;\n      s2 = (s2 + s1) |0;\n    } while (--n);\n\n    s1 %= 65521;\n    s2 %= 65521;\n  }\n\n  return (s1 | (s2 << 16)) |0;\n}\n\n/* eslint-disable */\n\n// Note: we can't get significant speed boost here.\n// So write code to minimize size - no pregenerated tables\n// and array tools dependencies.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// Use ordinary array, since untyped makes no boost here\nfunction makeTable() {\n  var c, table = [];\n\n  for (var n = 0; n < 256; n++) {\n    c = n;\n    for (var k = 0; k < 8; k++) {\n      c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n    }\n    table[n] = c;\n  }\n\n  return table;\n}\n\nvar crcTable = function() {\n    var table = makeTable();\n    crcTable = function () { return table; };\n    return table;\n};\n\nfunction crc32(crc, buf, len, pos) {\n  var t = crcTable(),\n      end = pos + len;\n\n  crc ^= -1;\n\n  for (var i = pos; i < end; i++) {\n    crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];\n  }\n\n  return (crc ^ (-1)); // >>> 0;\n}\n\n/* eslint-disable */\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// See state defs from inflate.js\nvar BAD = 30;       /* got a data error -- remain here until reset */\nvar TYPE = 12;      /* i: waiting for type bits, including last-flag bit */\n\n/*\n   Decode literal, length, and distance codes and write out the resulting\n   literal and match bytes until either not enough input or output is\n   available, an end-of-block is encountered, or a data error is encountered.\n   When large enough input and output buffers are supplied to inflate(), for\n   example, a 16K input buffer and a 64K output buffer, more than 95% of the\n   inflate execution time is spent in this routine.\n\n   Entry assumptions:\n\n        state.mode === LEN\n        strm.avail_in >= 6\n        strm.avail_out >= 258\n        start >= strm.avail_out\n        state.bits < 8\n\n   On return, state.mode is one of:\n\n        LEN -- ran out of enough output space or enough available input\n        TYPE -- reached end of block code, inflate() to interpret next block\n        BAD -- error in block data\n\n   Notes:\n\n    - The maximum input bits used by a length/distance pair is 15 bits for the\n      length code, 5 bits for the length extra, 15 bits for the distance code,\n      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.\n      Therefore if strm.avail_in >= 6, then there is enough input to avoid\n      checking for available input while decoding.\n\n    - The maximum bytes that a single length/distance pair can output is 258\n      bytes, which is the maximum length that can be coded.  inflate_fast()\n      requires strm.avail_out >= 258 for each loop to avoid checking for\n      output space.\n */\nfunction inflate_fast(strm, start) {\n  var state;\n  var _in;                    /* local strm.input */\n  var last;                   /* have enough input while in < last */\n  var _out;                   /* local strm.output */\n  var beg;                    /* inflate()'s initial strm.output */\n  var end;                    /* while out < end, enough space available */\n//#ifdef INFLATE_STRICT\n  var dmax;                   /* maximum distance from zlib header */\n//#endif\n  var wsize;                  /* window size or zero if not using window */\n  var whave;                  /* valid bytes in the window */\n  var wnext;                  /* window write index */\n  // Use `s_window` instead `window`, avoid conflict with instrumentation tools\n  var s_window;               /* allocated sliding window, if wsize != 0 */\n  var hold;                   /* local strm.hold */\n  var bits;                   /* local strm.bits */\n  var lcode;                  /* local strm.lencode */\n  var dcode;                  /* local strm.distcode */\n  var lmask;                  /* mask for first level of length codes */\n  var dmask;                  /* mask for first level of distance codes */\n  var here;                   /* retrieved table entry */\n  var op;                     /* code bits, operation, extra bits, or */\n                              /*  window position, window bytes to copy */\n  var len;                    /* match length, unused bytes */\n  var dist;                   /* match distance */\n  var from;                   /* where to copy match from */\n  var from_source;\n\n\n  var input, output; // JS specific, because we have no pointers\n\n  /* copy state to local variables */\n  state = strm.state;\n  //here = state.here;\n  _in = strm.next_in;\n  input = strm.input;\n  last = _in + (strm.avail_in - 5);\n  _out = strm.next_out;\n  output = strm.output;\n  beg = _out - (start - strm.avail_out);\n  end = _out + (strm.avail_out - 257);\n//#ifdef INFLATE_STRICT\n  dmax = state.dmax;\n//#endif\n  wsize = state.wsize;\n  whave = state.whave;\n  wnext = state.wnext;\n  s_window = state.window;\n  hold = state.hold;\n  bits = state.bits;\n  lcode = state.lencode;\n  dcode = state.distcode;\n  lmask = (1 << state.lenbits) - 1;\n  dmask = (1 << state.distbits) - 1;\n\n\n  /* decode literals and length/distances until end-of-block or not enough\n     input data or output space */\n\n  top:\n  do {\n    if (bits < 15) {\n      hold += input[_in++] << bits;\n      bits += 8;\n      hold += input[_in++] << bits;\n      bits += 8;\n    }\n\n    here = lcode[hold & lmask];\n\n    dolen:\n    for (;;) { // Goto emulation\n      op = here >>> 24/*here.bits*/;\n      hold >>>= op;\n      bits -= op;\n      op = (here >>> 16) & 0xff/*here.op*/;\n      if (op === 0) {                          /* literal */\n        //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n        //        \"inflate:         literal '%c'\\n\" :\n        //        \"inflate:         literal 0x%02x\\n\", here.val));\n        output[_out++] = here & 0xffff/*here.val*/;\n      }\n      else if (op & 16) {                     /* length base */\n        len = here & 0xffff/*here.val*/;\n        op &= 15;                           /* number of extra bits */\n        if (op) {\n          if (bits < op) {\n            hold += input[_in++] << bits;\n            bits += 8;\n          }\n          len += hold & ((1 << op) - 1);\n          hold >>>= op;\n          bits -= op;\n        }\n        //Tracevv((stderr, \"inflate:         length %u\\n\", len));\n        if (bits < 15) {\n          hold += input[_in++] << bits;\n          bits += 8;\n          hold += input[_in++] << bits;\n          bits += 8;\n        }\n        here = dcode[hold & dmask];\n\n        dodist:\n        for (;;) { // goto emulation\n          op = here >>> 24/*here.bits*/;\n          hold >>>= op;\n          bits -= op;\n          op = (here >>> 16) & 0xff/*here.op*/;\n\n          if (op & 16) {                      /* distance base */\n            dist = here & 0xffff/*here.val*/;\n            op &= 15;                       /* number of extra bits */\n            if (bits < op) {\n              hold += input[_in++] << bits;\n              bits += 8;\n              if (bits < op) {\n                hold += input[_in++] << bits;\n                bits += 8;\n              }\n            }\n            dist += hold & ((1 << op) - 1);\n//#ifdef INFLATE_STRICT\n            if (dist > dmax) {\n              strm.msg = 'invalid distance too far back';\n              state.mode = BAD;\n              break top;\n            }\n//#endif\n            hold >>>= op;\n            bits -= op;\n            //Tracevv((stderr, \"inflate:         distance %u\\n\", dist));\n            op = _out - beg;                /* max distance in output */\n            if (dist > op) {                /* see if copy from window */\n              op = dist - op;               /* distance back in window */\n              if (op > whave) {\n                if (state.sane) {\n                  strm.msg = 'invalid distance too far back';\n                  state.mode = BAD;\n                  break top;\n                }\n\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n//                if (len <= op - whave) {\n//                  do {\n//                    output[_out++] = 0;\n//                  } while (--len);\n//                  continue top;\n//                }\n//                len -= op - whave;\n//                do {\n//                  output[_out++] = 0;\n//                } while (--op > whave);\n//                if (op === 0) {\n//                  from = _out - dist;\n//                  do {\n//                    output[_out++] = output[from++];\n//                  } while (--len);\n//                  continue top;\n//                }\n//#endif\n              }\n              from = 0; // window index\n              from_source = s_window;\n              if (wnext === 0) {           /* very common case */\n                from += wsize - op;\n                if (op < len) {         /* some from window */\n                  len -= op;\n                  do {\n                    output[_out++] = s_window[from++];\n                  } while (--op);\n                  from = _out - dist;  /* rest from output */\n                  from_source = output;\n                }\n              }\n              else if (wnext < op) {      /* wrap around window */\n                from += wsize + wnext - op;\n                op -= wnext;\n                if (op < len) {         /* some from end of window */\n                  len -= op;\n                  do {\n                    output[_out++] = s_window[from++];\n                  } while (--op);\n                  from = 0;\n                  if (wnext < len) {  /* some from start of window */\n                    op = wnext;\n                    len -= op;\n                    do {\n                      output[_out++] = s_window[from++];\n                    } while (--op);\n                    from = _out - dist;      /* rest from output */\n                    from_source = output;\n                  }\n                }\n              }\n              else {                      /* contiguous in window */\n                from += wnext - op;\n                if (op < len) {         /* some from window */\n                  len -= op;\n                  do {\n                    output[_out++] = s_window[from++];\n                  } while (--op);\n                  from = _out - dist;  /* rest from output */\n                  from_source = output;\n                }\n              }\n              while (len > 2) {\n                output[_out++] = from_source[from++];\n                output[_out++] = from_source[from++];\n                output[_out++] = from_source[from++];\n                len -= 3;\n              }\n              if (len) {\n                output[_out++] = from_source[from++];\n                if (len > 1) {\n                  output[_out++] = from_source[from++];\n                }\n              }\n            }\n            else {\n              from = _out - dist;          /* copy direct from output */\n              do {                        /* minimum length is three */\n                output[_out++] = output[from++];\n                output[_out++] = output[from++];\n                output[_out++] = output[from++];\n                len -= 3;\n              } while (len > 2);\n              if (len) {\n                output[_out++] = output[from++];\n                if (len > 1) {\n                  output[_out++] = output[from++];\n                }\n              }\n            }\n          }\n          else if ((op & 64) === 0) {          /* 2nd level distance code */\n            here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n            continue dodist;\n          }\n          else {\n            strm.msg = 'invalid distance code';\n            state.mode = BAD;\n            break top;\n          }\n\n          break; // need to emulate goto via \"continue\"\n        }\n      }\n      else if ((op & 64) === 0) {              /* 2nd level length code */\n        here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n        continue dolen;\n      }\n      else if (op & 32) {                     /* end-of-block */\n        //Tracevv((stderr, \"inflate:         end of block\\n\"));\n        state.mode = TYPE;\n        break top;\n      }\n      else {\n        strm.msg = 'invalid literal/length code';\n        state.mode = BAD;\n        break top;\n      }\n\n      break; // need to emulate goto via \"continue\"\n    }\n  } while (_in < last && _out < end);\n\n  /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n  len = bits >> 3;\n  _in -= len;\n  bits -= len << 3;\n  hold &= (1 << bits) - 1;\n\n  /* update state and return */\n  strm.next_in = _in;\n  strm.next_out = _out;\n  strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));\n  strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));\n  state.hold = hold;\n  state.bits = bits;\n  return;\n}\n\n/* eslint-disable */\n\nvar MAXBITS = 15;\nvar ENOUGH_LENS = 852;\nvar ENOUGH_DISTS = 592;\n//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nvar CODES = 0;\nvar LENS = 1;\nvar DISTS = 2;\n\nvar lbase = [ /* Length codes 257..285 base */\n  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0\n];\n\nvar lext = [ /* Length codes 257..285 extra */\n  16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n  19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78\n];\n\nvar dbase = [ /* Distance codes 0..29 base */\n  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n  8193, 12289, 16385, 24577, 0, 0\n];\n\nvar dext = [ /* Distance codes 0..29 extra */\n  16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n  23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n  28, 28, 29, 29, 64, 64\n];\n\nfunction inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) {\n  var bits = opts.bits;\n      //here = opts.here; /* table entry for duplication */\n\n  var len = 0;               /* a code's length in bits */\n  var sym = 0;               /* index of code symbols */\n  var min = 0, max = 0;          /* minimum and maximum code lengths */\n  var root = 0;              /* number of index bits for root table */\n  var curr = 0;              /* number of index bits for current table */\n  var drop = 0;              /* code bits to drop for sub-table */\n  var left = 0;                   /* number of prefix codes available */\n  var used = 0;              /* code entries in table used */\n  var huff = 0;              /* Huffman code */\n  var incr;              /* for incrementing code, index */\n  var fill;              /* index for replicating entries */\n  var low;               /* low bits for current root entry */\n  var mask;              /* mask for low root bits */\n  var next;             /* next available space in table */\n  var base = null;     /* base value table to use */\n  var base_index = 0;\n//  var shoextra;    /* extra bits table to use */\n  var end;                    /* use base and extra for symbol > end */\n  var count = Buf16(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */\n  var offs = Buf16(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */\n  var extra = null;\n  var extra_index = 0;\n\n  var here_bits, here_op, here_val;\n\n  /*\n   Process a set of code lengths to create a canonical Huffman code.  The\n   code lengths are lens[0..codes-1].  Each length corresponds to the\n   symbols 0..codes-1.  The Huffman code is generated by first sorting the\n   symbols by length from short to long, and retaining the symbol order\n   for codes with equal lengths.  Then the code starts with all zero bits\n   for the first code of the shortest length, and the codes are integer\n   increments for the same length, and zeros are appended as the length\n   increases.  For the deflate format, these bits are stored backwards\n   from their more natural integer increment ordering, and so when the\n   decoding tables are built in the large loop below, the integer codes\n   are incremented backwards.\n\n   This routine assumes, but does not check, that all of the entries in\n   lens[] are in the range 0..MAXBITS.  The caller must assure this.\n   1..MAXBITS is interpreted as that code length.  zero means that that\n   symbol does not occur in this code.\n\n   The codes are sorted by computing a count of codes for each length,\n   creating from that a table of starting indices for each length in the\n   sorted table, and then entering the symbols in order in the sorted\n   table.  The sorted table is work[], with that space being provided by\n   the caller.\n\n   The length counts are used for other purposes as well, i.e. finding\n   the minimum and maximum length codes, determining if there are any\n   codes at all, checking for a valid set of lengths, and looking ahead\n   at length counts to determine sub-table sizes when building the\n   decoding tables.\n   */\n\n  /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n  for (len = 0; len <= MAXBITS; len++) {\n    count[len] = 0;\n  }\n  for (sym = 0; sym < codes; sym++) {\n    count[lens[lens_index + sym]]++;\n  }\n\n  /* bound code lengths, force root to be within code lengths */\n  root = bits;\n  for (max = MAXBITS; max >= 1; max--) {\n    if (count[max] !== 0) { break; }\n  }\n  if (root > max) {\n    root = max;\n  }\n  if (max === 0) {                     /* no symbols to code at all */\n    //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */\n    //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;\n    //table.val[opts.table_index++] = 0;   //here.val = (var short)0;\n    table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n\n    //table.op[opts.table_index] = 64;\n    //table.bits[opts.table_index] = 1;\n    //table.val[opts.table_index++] = 0;\n    table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n    opts.bits = 1;\n    return 0;     /* no symbols, but wait for decoding to report error */\n  }\n  for (min = 1; min < max; min++) {\n    if (count[min] !== 0) { break; }\n  }\n  if (root < min) {\n    root = min;\n  }\n\n  /* check for an over-subscribed or incomplete set of lengths */\n  left = 1;\n  for (len = 1; len <= MAXBITS; len++) {\n    left <<= 1;\n    left -= count[len];\n    if (left < 0) {\n      return -1;\n    }        /* over-subscribed */\n  }\n  if (left > 0 && (type === CODES || max !== 1)) {\n    return -1;                      /* incomplete set */\n  }\n\n  /* generate offsets into symbol table for each length for sorting */\n  offs[1] = 0;\n  for (len = 1; len < MAXBITS; len++) {\n    offs[len + 1] = offs[len] + count[len];\n  }\n\n  /* sort symbols by length, by symbol order within each length */\n  for (sym = 0; sym < codes; sym++) {\n    if (lens[lens_index + sym] !== 0) {\n      work[offs[lens[lens_index + sym]]++] = sym;\n    }\n  }\n\n  /*\n   Create and fill in decoding tables.  In this loop, the table being\n   filled is at next and has curr index bits.  The code being used is huff\n   with length len.  That code is converted to an index by dropping drop\n   bits off of the bottom.  For codes where len is less than drop + curr,\n   those top drop + curr - len bits are incremented through all values to\n   fill the table with replicated entries.\n\n   root is the number of index bits for the root table.  When len exceeds\n   root, sub-tables are created pointed to by the root entry with an index\n   of the low root bits of huff.  This is saved in low to check for when a\n   new sub-table should be started.  drop is zero when the root table is\n   being filled, and drop is root when sub-tables are being filled.\n\n   When a new sub-table is needed, it is necessary to look ahead in the\n   code lengths to determine what size sub-table is needed.  The length\n   counts are used for this, and so count[] is decremented as codes are\n   entered in the tables.\n\n   used keeps track of how many table entries have been allocated from the\n   provided *table space.  It is checked for LENS and DIST tables against\n   the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n   the initial root table size constants.  See the comments in inftrees.h\n   for more information.\n\n   sym increments through all symbols, and the loop terminates when\n   all codes of length max, i.e. all codes, have been processed.  This\n   routine permits incomplete codes, so another loop after this one fills\n   in the rest of the decoding tables with invalid code markers.\n   */\n\n  /* set up for code type */\n  // poor man optimization - use if-else instead of switch,\n  // to avoid deopts in old v8\n  if (type === CODES) {\n    base = extra = work;    /* dummy value--not used */\n    end = 19;\n\n  } else if (type === LENS) {\n    base = lbase;\n    base_index -= 257;\n    extra = lext;\n    extra_index -= 257;\n    end = 256;\n\n  } else {                    /* DISTS */\n    base = dbase;\n    extra = dext;\n    end = -1;\n  }\n\n  /* initialize opts for loop */\n  huff = 0;                   /* starting code */\n  sym = 0;                    /* starting code symbol */\n  len = min;                  /* starting code length */\n  next = table_index;              /* current table to fill in */\n  curr = root;                /* current table index bits */\n  drop = 0;                   /* current bits to drop from code for index */\n  low = -1;                   /* trigger new sub-table when len > root */\n  used = 1 << root;          /* use root table entries */\n  mask = used - 1;            /* mask for comparing low */\n\n  /* check available table space */\n  if ((type === LENS && used > ENOUGH_LENS) ||\n    (type === DISTS && used > ENOUGH_DISTS)) {\n    return 1;\n  }\n\n  /* process all codes and make table entries */\n  for (;;) {\n    /* create table entry */\n    here_bits = len - drop;\n    if (work[sym] < end) {\n      here_op = 0;\n      here_val = work[sym];\n    }\n    else if (work[sym] > end) {\n      here_op = extra[extra_index + work[sym]];\n      here_val = base[base_index + work[sym]];\n    }\n    else {\n      here_op = 32 + 64;         /* end of block */\n      here_val = 0;\n    }\n\n    /* replicate for those indices with low len bits equal to huff */\n    incr = 1 << (len - drop);\n    fill = 1 << curr;\n    min = fill;                 /* save offset to next table */\n    do {\n      fill -= incr;\n      table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;\n    } while (fill !== 0);\n\n    /* backwards increment the len-bit code huff */\n    incr = 1 << (len - 1);\n    while (huff & incr) {\n      incr >>= 1;\n    }\n    if (incr !== 0) {\n      huff &= incr - 1;\n      huff += incr;\n    } else {\n      huff = 0;\n    }\n\n    /* go to next symbol, update count, len */\n    sym++;\n    if (--count[len] === 0) {\n      if (len === max) { break; }\n      len = lens[lens_index + work[sym]];\n    }\n\n    /* create new sub-table if needed */\n    if (len > root && (huff & mask) !== low) {\n      /* if first time, transition to sub-tables */\n      if (drop === 0) {\n        drop = root;\n      }\n\n      /* increment past last table */\n      next += min;            /* here min is 1 << curr */\n\n      /* determine length of next table */\n      curr = len - drop;\n      left = 1 << curr;\n      while (curr + drop < max) {\n        left -= count[curr + drop];\n        if (left <= 0) { break; }\n        curr++;\n        left <<= 1;\n      }\n\n      /* check for enough space */\n      used += 1 << curr;\n      if ((type === LENS && used > ENOUGH_LENS) ||\n        (type === DISTS && used > ENOUGH_DISTS)) {\n        return 1;\n      }\n\n      /* point entry in root table to sub-table */\n      low = huff & mask;\n      /*table.op[low] = curr;\n      table.bits[low] = root;\n      table.val[low] = next - opts.table_index;*/\n      table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;\n    }\n  }\n\n  /* fill in remaining table entry if code is incomplete (guaranteed to have\n   at most one remaining entry, since if the code is incomplete, the\n   maximum code length that was allowed to get this far is one bit) */\n  if (huff !== 0) {\n    //table.op[next + huff] = 64;            /* invalid code marker */\n    //table.bits[next + huff] = len - drop;\n    //table.val[next + huff] = 0;\n    table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;\n  }\n\n  /* set return parameters */\n  //opts.table_index += used;\n  opts.bits = root;\n  return 0;\n}\n\n/* eslint-disable */\n\nvar CODES$1 = 0;\nvar LENS$1 = 1;\nvar DISTS$1 = 2;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\n\n/* Allowed flush values; see deflate() and inflate() below for details */\n//var Z_NO_FLUSH      = 0;\n//var Z_PARTIAL_FLUSH = 1;\n//var Z_SYNC_FLUSH    = 2;\n//var Z_FULL_FLUSH    = 3;\nvar Z_FINISH$1        = 4;\nvar Z_BLOCK$1         = 5;\nvar Z_TREES$1         = 6;\n\n\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\nvar Z_OK$1            = 0;\nvar Z_STREAM_END$1    = 1;\nvar Z_NEED_DICT$1     = 2;\n//var Z_ERRNO         = -1;\nvar Z_STREAM_ERROR$1  = -2;\nvar Z_DATA_ERROR$1    = -3;\nvar Z_MEM_ERROR     = -4;\nvar Z_BUF_ERROR$1     = -5;\n//var Z_VERSION_ERROR = -6;\n\n/* The deflate compression method */\nvar Z_DEFLATED$1  = 8;\n\n\n/* STATES ====================================================================*/\n/* ===========================================================================*/\n\n\nvar    HEAD = 1;       /* i: waiting for magic header */\nvar    FLAGS = 2;      /* i: waiting for method and flags (gzip) */\nvar    TIME = 3;       /* i: waiting for modification time (gzip) */\nvar    OS = 4;         /* i: waiting for extra flags and operating system (gzip) */\nvar    EXLEN = 5;      /* i: waiting for extra length (gzip) */\nvar    EXTRA = 6;      /* i: waiting for extra bytes (gzip) */\nvar    NAME = 7;       /* i: waiting for end of file name (gzip) */\nvar    COMMENT = 8;    /* i: waiting for end of comment (gzip) */\nvar    HCRC = 9;       /* i: waiting for header crc (gzip) */\nvar    DICTID = 10;    /* i: waiting for dictionary check value */\nvar    DICT = 11;      /* waiting for inflateSetDictionary() call */\nvar        TYPE$1 = 12;      /* i: waiting for type bits, including last-flag bit */\nvar        TYPEDO = 13;    /* i: same, but skip check to exit inflate on new block */\nvar        STORED = 14;    /* i: waiting for stored size (length and complement) */\nvar        COPY_ = 15;     /* i/o: same as COPY below, but only first time in */\nvar        COPY = 16;      /* i/o: waiting for input or output to copy stored block */\nvar        TABLE = 17;     /* i: waiting for dynamic block table lengths */\nvar        LENLENS = 18;   /* i: waiting for code length code lengths */\nvar        CODELENS = 19;  /* i: waiting for length/lit and distance code lengths */\nvar            LEN_ = 20;      /* i: same as LEN below, but only first time in */\nvar            LEN = 21;       /* i: waiting for length/lit/eob code */\nvar            LENEXT = 22;    /* i: waiting for length extra bits */\nvar            DIST = 23;      /* i: waiting for distance code */\nvar            DISTEXT = 24;   /* i: waiting for distance extra bits */\nvar            MATCH = 25;     /* o: waiting for output space to copy string */\nvar            LIT = 26;       /* o: waiting for output space to write literal */\nvar    CHECK = 27;     /* i: waiting for 32-bit check value */\nvar    LENGTH = 28;    /* i: waiting for 32-bit length (gzip) */\nvar    DONE = 29;      /* finished check, done -- remain here until reset */\nvar    BAD$1 = 30;       /* got a data error -- remain here until reset */\nvar    MEM = 31;       /* got an inflate() memory error -- remain here until reset */\nvar    SYNC = 32;      /* looking for synchronization bytes to restart inflate() */\n\n/* ===========================================================================*/\n\n\n\nvar ENOUGH_LENS$1 = 852;\nvar ENOUGH_DISTS$1 = 592;\n\n\nfunction zswap32(q) {\n  return  (((q >>> 24) & 0xff) +\n          ((q >>> 8) & 0xff00) +\n          ((q & 0xff00) << 8) +\n          ((q & 0xff) << 24));\n}\n\n\nfunction InflateState() {\n  this.mode = 0;             /* current inflate mode */\n  this.last = false;          /* true if processing last block */\n  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */\n  this.havedict = false;      /* true if dictionary provided */\n  this.flags = 0;             /* gzip header method and flags (0 if zlib) */\n  this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */\n  this.check = 0;             /* protected copy of check value */\n  this.total = 0;             /* protected copy of output count */\n  // TODO: may be {}\n  this.head = null;           /* where to save gzip header information */\n\n  /* sliding window */\n  this.wbits = 0;             /* log base 2 of requested window size */\n  this.wsize = 0;             /* window size or zero if not using window */\n  this.whave = 0;             /* valid bytes in the window */\n  this.wnext = 0;             /* window write index */\n  this.window = null;         /* allocated sliding window, if needed */\n\n  /* bit accumulator */\n  this.hold = 0;              /* input bit accumulator */\n  this.bits = 0;              /* number of bits in \"in\" */\n\n  /* for string and stored block copying */\n  this.length = 0;            /* literal or length of data to copy */\n  this.offset = 0;            /* distance back to copy string from */\n\n  /* for table and code decoding */\n  this.extra = 0;             /* extra bits needed */\n\n  /* fixed and dynamic code tables */\n  this.lencode = null;          /* starting table for length/literal codes */\n  this.distcode = null;         /* starting table for distance codes */\n  this.lenbits = 0;           /* index bits for lencode */\n  this.distbits = 0;          /* index bits for distcode */\n\n  /* dynamic table building */\n  this.ncode = 0;             /* number of code length code lengths */\n  this.nlen = 0;              /* number of length code lengths */\n  this.ndist = 0;             /* number of distance code lengths */\n  this.have = 0;              /* number of code lengths in lens[] */\n  this.next = null;              /* next available space in codes[] */\n\n  this.lens = Buf16(320); /* temporary storage for code lengths */\n  this.work = Buf16(288); /* work area for code table building */\n\n  /*\n   because we don't have pointers in js, we use lencode and distcode directly\n   as buffers so we don't need codes\n  */\n  //this.codes = Buf32(ENOUGH);       /* space for code tables */\n  this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */\n  this.distdyn = null;             /* dynamic table for distance codes (JS specific) */\n  this.sane = 0;                   /* if false, allow invalid distance too far */\n  this.back = 0;                   /* bits back of last unprocessed length/lit */\n  this.was = 0;                    /* initial length of match */\n}\n\nfunction inflateResetKeep(strm) {\n  var state;\n\n  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }\n  state = strm.state;\n  strm.total_in = strm.total_out = state.total = 0;\n  strm.msg = ''; /*Z_NULL*/\n  if (state.wrap) {       /* to support ill-conceived Java test suite */\n    strm.adler = state.wrap & 1;\n  }\n  state.mode = HEAD;\n  state.last = 0;\n  state.havedict = 0;\n  state.dmax = 32768;\n  state.head = null/*Z_NULL*/;\n  state.hold = 0;\n  state.bits = 0;\n  //state.lencode = state.distcode = state.next = state.codes;\n  state.lencode = state.lendyn = Buf32(ENOUGH_LENS$1);\n  state.distcode = state.distdyn = Buf32(ENOUGH_DISTS$1);\n\n  state.sane = 1;\n  state.back = -1;\n  //Tracev((stderr, \"inflate: reset\\n\"));\n  return Z_OK$1;\n}\n\nfunction inflateReset(strm) {\n  var state;\n\n  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }\n  state = strm.state;\n  state.wsize = 0;\n  state.whave = 0;\n  state.wnext = 0;\n  return inflateResetKeep(strm);\n\n}\n\nfunction inflateReset2(strm, windowBits) {\n  var wrap;\n  var state;\n\n  /* get the state */\n  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }\n  state = strm.state;\n\n  /* extract wrap request from windowBits parameter */\n  if (windowBits < 0) {\n    wrap = 0;\n    windowBits = -windowBits;\n  }\n  else {\n    wrap = (windowBits >> 4) + 1;\n    if (windowBits < 48) {\n      windowBits &= 15;\n    }\n  }\n\n  /* set number of window bits, free window if different */\n  if (windowBits && (windowBits < 8 || windowBits > 15)) {\n    return Z_STREAM_ERROR$1;\n  }\n  if (state.window !== null && state.wbits !== windowBits) {\n    state.window = null;\n  }\n\n  /* update state and reset the rest of it */\n  state.wrap = wrap;\n  state.wbits = windowBits;\n  return inflateReset(strm);\n}\n\nfunction inflateInit2(strm, windowBits) {\n  var ret;\n  var state;\n\n  if (!strm) { return Z_STREAM_ERROR$1; }\n  //strm.msg = Z_NULL;                 /* in case we return an error */\n\n  state = new InflateState();\n\n  //if (state === Z_NULL) return Z_MEM_ERROR;\n  //Tracev((stderr, \"inflate: allocated\\n\"));\n  strm.state = state;\n  state.window = null/*Z_NULL*/;\n  ret = inflateReset2(strm, windowBits);\n  if (ret !== Z_OK$1) {\n    strm.state = null/*Z_NULL*/;\n  }\n  return ret;\n}\n\n\n/*\n Return state with length and distance decoding tables and index sizes set to\n fixed code decoding.  Normally this returns fixed tables from inffixed.h.\n If BUILDFIXED is defined, then instead this routine builds the tables the\n first time it's called, and returns those tables the first time and\n thereafter.  This reduces the size of the code by about 2K bytes, in\n exchange for a little execution time.  However, BUILDFIXED should not be\n used for threaded applications, since the rewriting of the tables and virgin\n may not be thread-safe.\n */\nvar virgin = true;\n\nvar lenfix, distfix; // We have no pointers in JS, so keep tables separate\n\nfunction fixedtables(state) {\n  /* build fixed huffman tables if first call (may not be thread safe) */\n  if (virgin) {\n    var sym;\n\n    lenfix = Buf32(512);\n    distfix = Buf32(32);\n\n    /* literal/length table */\n    sym = 0;\n    while (sym < 144) { state.lens[sym++] = 8; }\n    while (sym < 256) { state.lens[sym++] = 9; }\n    while (sym < 280) { state.lens[sym++] = 7; }\n    while (sym < 288) { state.lens[sym++] = 8; }\n\n    inflate_table(LENS$1,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });\n\n    /* distance table */\n    sym = 0;\n    while (sym < 32) { state.lens[sym++] = 5; }\n\n    inflate_table(DISTS$1, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });\n\n    /* do this just once */\n    virgin = false;\n  }\n\n  state.lencode = lenfix;\n  state.lenbits = 9;\n  state.distcode = distfix;\n  state.distbits = 5;\n}\n\n\n/*\n Update the window with the last wsize (normally 32K) bytes written before\n returning.  If window does not exist yet, create it.  This is only called\n when a window is already in use, or when output has been written during this\n inflate call, but the end of the deflate stream has not been reached yet.\n It is also called to create a window for dictionary data when a dictionary\n is loaded.\n\n Providing output buffers larger than 32K to inflate() should provide a speed\n advantage, since only the last 32K of output is copied to the sliding window\n upon return from inflate(), and since all distances after the first 32K of\n output will fall in the output data, making match copies simpler and faster.\n The advantage may be dependent on the size of the processor's data caches.\n */\nfunction updatewindow(strm, src, end, copy) {\n  var dist;\n  var state = strm.state;\n\n  /* if it hasn't been done already, allocate space for the window */\n  if (state.window === null) {\n    state.wsize = 1 << state.wbits;\n    state.wnext = 0;\n    state.whave = 0;\n\n    state.window = Buf8(state.wsize);\n  }\n\n  /* copy state->wsize or less output bytes into the circular window */\n  if (copy >= state.wsize) {\n    arraySet(state.window, src, end - state.wsize, state.wsize, 0);\n    state.wnext = 0;\n    state.whave = state.wsize;\n  }\n  else {\n    dist = state.wsize - state.wnext;\n    if (dist > copy) {\n      dist = copy;\n    }\n    //zmemcpy(state->window + state->wnext, end - copy, dist);\n    arraySet(state.window, src, end - copy, dist, state.wnext);\n    copy -= dist;\n    if (copy) {\n      //zmemcpy(state->window, end - copy, copy);\n      arraySet(state.window, src, end - copy, copy, 0);\n      state.wnext = copy;\n      state.whave = state.wsize;\n    }\n    else {\n      state.wnext += dist;\n      if (state.wnext === state.wsize) { state.wnext = 0; }\n      if (state.whave < state.wsize) { state.whave += dist; }\n    }\n  }\n  return 0;\n}\n\nfunction inflate(strm, flush) {\n  var state;\n  var input, output;          // input/output buffers\n  var next;                   /* next input INDEX */\n  var put;                    /* next output INDEX */\n  var have, left;             /* available input and output */\n  var hold;                   /* bit buffer */\n  var bits;                   /* bits in bit buffer */\n  var _in, _out;              /* save starting available input and output */\n  var copy;                   /* number of stored or match bytes to copy */\n  var from;                   /* where to copy match bytes from */\n  var from_source;\n  var here = 0;               /* current decoding table entry */\n  var here_bits, here_op, here_val; // paked \"here\" denormalized (JS specific)\n  //var last;                   /* parent table entry */\n  var last_bits, last_op, last_val; // paked \"last\" denormalized (JS specific)\n  var len;                    /* length to copy for repeats, bits to drop */\n  var ret;                    /* return code */\n  var hbuf = Buf8(4);    /* buffer for gzip header crc calculation */\n  var opts;\n\n  var n; // temporary var for NEED_BITS\n\n  var order = /* permutation of code lengths */\n    [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];\n\n\n  if (!strm || !strm.state || !strm.output ||\n      (!strm.input && strm.avail_in !== 0)) {\n    return Z_STREAM_ERROR$1;\n  }\n\n  state = strm.state;\n  if (state.mode === TYPE$1) { state.mode = TYPEDO; }    /* skip check */\n\n\n  //--- LOAD() ---\n  put = strm.next_out;\n  output = strm.output;\n  left = strm.avail_out;\n  next = strm.next_in;\n  input = strm.input;\n  have = strm.avail_in;\n  hold = state.hold;\n  bits = state.bits;\n  //---\n\n  _in = have;\n  _out = left;\n  ret = Z_OK$1;\n\n  inf_leave: // goto emulation\n  for (;;) {\n    switch (state.mode) {\n      case HEAD:\n        if (state.wrap === 0) {\n          state.mode = TYPEDO;\n          break;\n        }\n        //=== NEEDBITS(16);\n        while (bits < 16) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */\n          state.check = 0/*crc32(0L, Z_NULL, 0)*/;\n          //=== CRC2(state.check, hold);\n          hbuf[0] = hold & 0xff;\n          hbuf[1] = (hold >>> 8) & 0xff;\n          state.check = crc32(state.check, hbuf, 2, 0);\n          //===//\n\n          //=== INITBITS();\n          hold = 0;\n          bits = 0;\n          //===//\n          state.mode = FLAGS;\n          break;\n        }\n        state.flags = 0;           /* expect zlib header */\n        if (state.head) {\n          state.head.done = false;\n        }\n        if (!(state.wrap & 1) ||   /* check if zlib header allowed */\n          (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {\n          strm.msg = 'incorrect header check';\n          state.mode = BAD$1;\n          break;\n        }\n        if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED$1) {\n          strm.msg = 'unknown compression method';\n          state.mode = BAD$1;\n          break;\n        }\n        //--- DROPBITS(4) ---//\n        hold >>>= 4;\n        bits -= 4;\n        //---//\n        len = (hold & 0x0f)/*BITS(4)*/ + 8;\n        if (state.wbits === 0) {\n          state.wbits = len;\n        }\n        else if (len > state.wbits) {\n          strm.msg = 'invalid window size';\n          state.mode = BAD$1;\n          break;\n        }\n        state.dmax = 1 << len;\n        //Tracev((stderr, \"inflate:   zlib header ok\\n\"));\n        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n        state.mode = hold & 0x200 ? DICTID : TYPE$1;\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        break;\n      case FLAGS:\n        //=== NEEDBITS(16); */\n        while (bits < 16) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        state.flags = hold;\n        if ((state.flags & 0xff) !== Z_DEFLATED$1) {\n          strm.msg = 'unknown compression method';\n          state.mode = BAD$1;\n          break;\n        }\n        if (state.flags & 0xe000) {\n          strm.msg = 'unknown header flags set';\n          state.mode = BAD$1;\n          break;\n        }\n        if (state.head) {\n          state.head.text = ((hold >> 8) & 1);\n        }\n        if (state.flags & 0x0200) {\n          //=== CRC2(state.check, hold);\n          hbuf[0] = hold & 0xff;\n          hbuf[1] = (hold >>> 8) & 0xff;\n          state.check = crc32(state.check, hbuf, 2, 0);\n          //===//\n        }\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        state.mode = TIME;\n        /* falls through */\n      case TIME:\n        //=== NEEDBITS(32); */\n        while (bits < 32) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        if (state.head) {\n          state.head.time = hold;\n        }\n        if (state.flags & 0x0200) {\n          //=== CRC4(state.check, hold)\n          hbuf[0] = hold & 0xff;\n          hbuf[1] = (hold >>> 8) & 0xff;\n          hbuf[2] = (hold >>> 16) & 0xff;\n          hbuf[3] = (hold >>> 24) & 0xff;\n          state.check = crc32(state.check, hbuf, 4, 0);\n          //===\n        }\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        state.mode = OS;\n        /* falls through */\n      case OS:\n        //=== NEEDBITS(16); */\n        while (bits < 16) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        if (state.head) {\n          state.head.xflags = (hold & 0xff);\n          state.head.os = (hold >> 8);\n        }\n        if (state.flags & 0x0200) {\n          //=== CRC2(state.check, hold);\n          hbuf[0] = hold & 0xff;\n          hbuf[1] = (hold >>> 8) & 0xff;\n          state.check = crc32(state.check, hbuf, 2, 0);\n          //===//\n        }\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        state.mode = EXLEN;\n        /* falls through */\n      case EXLEN:\n        if (state.flags & 0x0400) {\n          //=== NEEDBITS(16); */\n          while (bits < 16) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          state.length = hold;\n          if (state.head) {\n            state.head.extra_len = hold;\n          }\n          if (state.flags & 0x0200) {\n            //=== CRC2(state.check, hold);\n            hbuf[0] = hold & 0xff;\n            hbuf[1] = (hold >>> 8) & 0xff;\n            state.check = crc32(state.check, hbuf, 2, 0);\n            //===//\n          }\n          //=== INITBITS();\n          hold = 0;\n          bits = 0;\n          //===//\n        }\n        else if (state.head) {\n          state.head.extra = null/*Z_NULL*/;\n        }\n        state.mode = EXTRA;\n        /* falls through */\n      case EXTRA:\n        if (state.flags & 0x0400) {\n          copy = state.length;\n          if (copy > have) { copy = have; }\n          if (copy) {\n            if (state.head) {\n              len = state.head.extra_len - state.length;\n              if (!state.head.extra) {\n                // Use untyped array for more convenient processing later\n                state.head.extra = new Array(state.head.extra_len);\n              }\n              arraySet(\n                state.head.extra,\n                input,\n                next,\n                // extra field is limited to 65536 bytes\n                // - no need for additional size check\n                copy,\n                /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/\n                len\n              );\n              //zmemcpy(state.head.extra + len, next,\n              //        len + copy > state.head.extra_max ?\n              //        state.head.extra_max - len : copy);\n            }\n            if (state.flags & 0x0200) {\n              state.check = crc32(state.check, input, copy, next);\n            }\n            have -= copy;\n            next += copy;\n            state.length -= copy;\n          }\n          if (state.length) { break inf_leave; }\n        }\n        state.length = 0;\n        state.mode = NAME;\n        /* falls through */\n      case NAME:\n        if (state.flags & 0x0800) {\n          if (have === 0) { break inf_leave; }\n          copy = 0;\n          do {\n            // TODO: 2 or 1 bytes?\n            len = input[next + copy++];\n            /* use constant limit because in js we should not preallocate memory */\n            if (state.head && len &&\n                (state.length < 65536 /*state.head.name_max*/)) {\n              state.head.name += String.fromCharCode(len);\n            }\n          } while (len && copy < have);\n\n          if (state.flags & 0x0200) {\n            state.check = crc32(state.check, input, copy, next);\n          }\n          have -= copy;\n          next += copy;\n          if (len) { break inf_leave; }\n        }\n        else if (state.head) {\n          state.head.name = null;\n        }\n        state.length = 0;\n        state.mode = COMMENT;\n        /* falls through */\n      case COMMENT:\n        if (state.flags & 0x1000) {\n          if (have === 0) { break inf_leave; }\n          copy = 0;\n          do {\n            len = input[next + copy++];\n            /* use constant limit because in js we should not preallocate memory */\n            if (state.head && len &&\n                (state.length < 65536 /*state.head.comm_max*/)) {\n              state.head.comment += String.fromCharCode(len);\n            }\n          } while (len && copy < have);\n          if (state.flags & 0x0200) {\n            state.check = crc32(state.check, input, copy, next);\n          }\n          have -= copy;\n          next += copy;\n          if (len) { break inf_leave; }\n        }\n        else if (state.head) {\n          state.head.comment = null;\n        }\n        state.mode = HCRC;\n        /* falls through */\n      case HCRC:\n        if (state.flags & 0x0200) {\n          //=== NEEDBITS(16); */\n          while (bits < 16) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          if (hold !== (state.check & 0xffff)) {\n            strm.msg = 'header crc mismatch';\n            state.mode = BAD$1;\n            break;\n          }\n          //=== INITBITS();\n          hold = 0;\n          bits = 0;\n          //===//\n        }\n        if (state.head) {\n          state.head.hcrc = ((state.flags >> 9) & 1);\n          state.head.done = true;\n        }\n        strm.adler = state.check = 0;\n        state.mode = TYPE$1;\n        break;\n      case DICTID:\n        //=== NEEDBITS(32); */\n        while (bits < 32) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        strm.adler = state.check = zswap32(hold);\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        state.mode = DICT;\n        /* falls through */\n      case DICT:\n        if (state.havedict === 0) {\n          //--- RESTORE() ---\n          strm.next_out = put;\n          strm.avail_out = left;\n          strm.next_in = next;\n          strm.avail_in = have;\n          state.hold = hold;\n          state.bits = bits;\n          //---\n          return Z_NEED_DICT$1;\n        }\n        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n        state.mode = TYPE$1;\n        /* falls through */\n      case TYPE$1:\n        if (flush === Z_BLOCK$1 || flush === Z_TREES$1) { break inf_leave; }\n        /* falls through */\n      case TYPEDO:\n        if (state.last) {\n          //--- BYTEBITS() ---//\n          hold >>>= bits & 7;\n          bits -= bits & 7;\n          //---//\n          state.mode = CHECK;\n          break;\n        }\n        //=== NEEDBITS(3); */\n        while (bits < 3) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        state.last = (hold & 0x01)/*BITS(1)*/;\n        //--- DROPBITS(1) ---//\n        hold >>>= 1;\n        bits -= 1;\n        //---//\n\n        switch ((hold & 0x03)/*BITS(2)*/) {\n          case 0:                             /* stored block */\n            //Tracev((stderr, \"inflate:     stored block%s\\n\",\n            //        state.last ? \" (last)\" : \"\"));\n            state.mode = STORED;\n            break;\n          case 1:                             /* fixed block */\n            fixedtables(state);\n            //Tracev((stderr, \"inflate:     fixed codes block%s\\n\",\n            //        state.last ? \" (last)\" : \"\"));\n            state.mode = LEN_;             /* decode codes */\n            if (flush === Z_TREES$1) {\n              //--- DROPBITS(2) ---//\n              hold >>>= 2;\n              bits -= 2;\n              //---//\n              break inf_leave;\n            }\n            break;\n          case 2:                             /* dynamic block */\n            //Tracev((stderr, \"inflate:     dynamic codes block%s\\n\",\n            //        state.last ? \" (last)\" : \"\"));\n            state.mode = TABLE;\n            break;\n          case 3:\n            strm.msg = 'invalid block type';\n            state.mode = BAD$1;\n        }\n        //--- DROPBITS(2) ---//\n        hold >>>= 2;\n        bits -= 2;\n        //---//\n        break;\n      case STORED:\n        //--- BYTEBITS() ---// /* go to byte boundary */\n        hold >>>= bits & 7;\n        bits -= bits & 7;\n        //---//\n        //=== NEEDBITS(32); */\n        while (bits < 32) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {\n          strm.msg = 'invalid stored block lengths';\n          state.mode = BAD$1;\n          break;\n        }\n        state.length = hold & 0xffff;\n        //Tracev((stderr, \"inflate:       stored length %u\\n\",\n        //        state.length));\n        //=== INITBITS();\n        hold = 0;\n        bits = 0;\n        //===//\n        state.mode = COPY_;\n        if (flush === Z_TREES$1) { break inf_leave; }\n        /* falls through */\n      case COPY_:\n        state.mode = COPY;\n        /* falls through */\n      case COPY:\n        copy = state.length;\n        if (copy) {\n          if (copy > have) { copy = have; }\n          if (copy > left) { copy = left; }\n          if (copy === 0) { break inf_leave; }\n          //--- zmemcpy(put, next, copy); ---\n          arraySet(output, input, next, copy, put);\n          //---//\n          have -= copy;\n          next += copy;\n          left -= copy;\n          put += copy;\n          state.length -= copy;\n          break;\n        }\n        //Tracev((stderr, \"inflate:       stored end\\n\"));\n        state.mode = TYPE$1;\n        break;\n      case TABLE:\n        //=== NEEDBITS(14); */\n        while (bits < 14) {\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n        }\n        //===//\n        state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;\n        //--- DROPBITS(5) ---//\n        hold >>>= 5;\n        bits -= 5;\n        //---//\n        state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;\n        //--- DROPBITS(5) ---//\n        hold >>>= 5;\n        bits -= 5;\n        //---//\n        state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;\n        //--- DROPBITS(4) ---//\n        hold >>>= 4;\n        bits -= 4;\n        //---//\n//#ifndef PKZIP_BUG_WORKAROUND\n        if (state.nlen > 286 || state.ndist > 30) {\n          strm.msg = 'too many length or distance symbols';\n          state.mode = BAD$1;\n          break;\n        }\n//#endif\n        //Tracev((stderr, \"inflate:       table sizes ok\\n\"));\n        state.have = 0;\n        state.mode = LENLENS;\n        /* falls through */\n      case LENLENS:\n        while (state.have < state.ncode) {\n          //=== NEEDBITS(3);\n          while (bits < 3) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);\n          //--- DROPBITS(3) ---//\n          hold >>>= 3;\n          bits -= 3;\n          //---//\n        }\n        while (state.have < 19) {\n          state.lens[order[state.have++]] = 0;\n        }\n        // We have separate tables & no pointers. 2 commented lines below not needed.\n        //state.next = state.codes;\n        //state.lencode = state.next;\n        // Switch to use dynamic table\n        state.lencode = state.lendyn;\n        state.lenbits = 7;\n\n        opts = { bits: state.lenbits };\n        ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts);\n        state.lenbits = opts.bits;\n\n        if (ret) {\n          strm.msg = 'invalid code lengths set';\n          state.mode = BAD$1;\n          break;\n        }\n        //Tracev((stderr, \"inflate:       code lengths ok\\n\"));\n        state.have = 0;\n        state.mode = CODELENS;\n        /* falls through */\n      case CODELENS:\n        while (state.have < state.nlen + state.ndist) {\n          for (;;) {\n            here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/\n            here_bits = here >>> 24;\n            here_op = (here >>> 16) & 0xff;\n            here_val = here & 0xffff;\n\n            if ((here_bits) <= bits) { break; }\n            //--- PULLBYTE() ---//\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n            //---//\n          }\n          if (here_val < 16) {\n            //--- DROPBITS(here.bits) ---//\n            hold >>>= here_bits;\n            bits -= here_bits;\n            //---//\n            state.lens[state.have++] = here_val;\n          }\n          else {\n            if (here_val === 16) {\n              //=== NEEDBITS(here.bits + 2);\n              n = here_bits + 2;\n              while (bits < n) {\n                if (have === 0) { break inf_leave; }\n                have--;\n                hold += input[next++] << bits;\n                bits += 8;\n              }\n              //===//\n              //--- DROPBITS(here.bits) ---//\n              hold >>>= here_bits;\n              bits -= here_bits;\n              //---//\n              if (state.have === 0) {\n                strm.msg = 'invalid bit length repeat';\n                state.mode = BAD$1;\n                break;\n              }\n              len = state.lens[state.have - 1];\n              copy = 3 + (hold & 0x03);//BITS(2);\n              //--- DROPBITS(2) ---//\n              hold >>>= 2;\n              bits -= 2;\n              //---//\n            }\n            else if (here_val === 17) {\n              //=== NEEDBITS(here.bits + 3);\n              n = here_bits + 3;\n              while (bits < n) {\n                if (have === 0) { break inf_leave; }\n                have--;\n                hold += input[next++] << bits;\n                bits += 8;\n              }\n              //===//\n              //--- DROPBITS(here.bits) ---//\n              hold >>>= here_bits;\n              bits -= here_bits;\n              //---//\n              len = 0;\n              copy = 3 + (hold & 0x07);//BITS(3);\n              //--- DROPBITS(3) ---//\n              hold >>>= 3;\n              bits -= 3;\n              //---//\n            }\n            else {\n              //=== NEEDBITS(here.bits + 7);\n              n = here_bits + 7;\n              while (bits < n) {\n                if (have === 0) { break inf_leave; }\n                have--;\n                hold += input[next++] << bits;\n                bits += 8;\n              }\n              //===//\n              //--- DROPBITS(here.bits) ---//\n              hold >>>= here_bits;\n              bits -= here_bits;\n              //---//\n              len = 0;\n              copy = 11 + (hold & 0x7f);//BITS(7);\n              //--- DROPBITS(7) ---//\n              hold >>>= 7;\n              bits -= 7;\n              //---//\n            }\n            if (state.have + copy > state.nlen + state.ndist) {\n              strm.msg = 'invalid bit length repeat';\n              state.mode = BAD$1;\n              break;\n            }\n            while (copy--) {\n              state.lens[state.have++] = len;\n            }\n          }\n        }\n\n        /* handle error breaks in while */\n        if (state.mode === BAD$1) { break; }\n\n        /* check for end-of-block code (better have one) */\n        if (state.lens[256] === 0) {\n          strm.msg = 'invalid code -- missing end-of-block';\n          state.mode = BAD$1;\n          break;\n        }\n\n        /* build code tables -- note: do not change the lenbits or distbits\n           values here (9 and 6) without reading the comments in inftrees.h\n           concerning the ENOUGH constants, which depend on those values */\n        state.lenbits = 9;\n\n        opts = { bits: state.lenbits };\n        ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);\n        // We have separate tables & no pointers. 2 commented lines below not needed.\n        // state.next_index = opts.table_index;\n        state.lenbits = opts.bits;\n        // state.lencode = state.next;\n\n        if (ret) {\n          strm.msg = 'invalid literal/lengths set';\n          state.mode = BAD$1;\n          break;\n        }\n\n        state.distbits = 6;\n        //state.distcode.copy(state.codes);\n        // Switch to use dynamic table\n        state.distcode = state.distdyn;\n        opts = { bits: state.distbits };\n        ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);\n        // We have separate tables & no pointers. 2 commented lines below not needed.\n        // state.next_index = opts.table_index;\n        state.distbits = opts.bits;\n        // state.distcode = state.next;\n\n        if (ret) {\n          strm.msg = 'invalid distances set';\n          state.mode = BAD$1;\n          break;\n        }\n        //Tracev((stderr, 'inflate:       codes ok\\n'));\n        state.mode = LEN_;\n        if (flush === Z_TREES$1) { break inf_leave; }\n        /* falls through */\n      case LEN_:\n        state.mode = LEN;\n        /* falls through */\n      case LEN:\n        if (have >= 6 && left >= 258) {\n          //--- RESTORE() ---\n          strm.next_out = put;\n          strm.avail_out = left;\n          strm.next_in = next;\n          strm.avail_in = have;\n          state.hold = hold;\n          state.bits = bits;\n          //---\n          inflate_fast(strm, _out);\n          //--- LOAD() ---\n          put = strm.next_out;\n          output = strm.output;\n          left = strm.avail_out;\n          next = strm.next_in;\n          input = strm.input;\n          have = strm.avail_in;\n          hold = state.hold;\n          bits = state.bits;\n          //---\n\n          if (state.mode === TYPE$1) {\n            state.back = -1;\n          }\n          break;\n        }\n        state.back = 0;\n        for (;;) {\n          here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/\n          here_bits = here >>> 24;\n          here_op = (here >>> 16) & 0xff;\n          here_val = here & 0xffff;\n\n          if (here_bits <= bits) { break; }\n          //--- PULLBYTE() ---//\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n          //---//\n        }\n        if (here_op && (here_op & 0xf0) === 0) {\n          last_bits = here_bits;\n          last_op = here_op;\n          last_val = here_val;\n          for (;;) {\n            here = state.lencode[last_val +\n                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n            here_bits = here >>> 24;\n            here_op = (here >>> 16) & 0xff;\n            here_val = here & 0xffff;\n\n            if ((last_bits + here_bits) <= bits) { break; }\n            //--- PULLBYTE() ---//\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n            //---//\n          }\n          //--- DROPBITS(last.bits) ---//\n          hold >>>= last_bits;\n          bits -= last_bits;\n          //---//\n          state.back += last_bits;\n        }\n        //--- DROPBITS(here.bits) ---//\n        hold >>>= here_bits;\n        bits -= here_bits;\n        //---//\n        state.back += here_bits;\n        state.length = here_val;\n        if (here_op === 0) {\n          //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n          //        \"inflate:         literal '%c'\\n\" :\n          //        \"inflate:         literal 0x%02x\\n\", here.val));\n          state.mode = LIT;\n          break;\n        }\n        if (here_op & 32) {\n          //Tracevv((stderr, \"inflate:         end of block\\n\"));\n          state.back = -1;\n          state.mode = TYPE$1;\n          break;\n        }\n        if (here_op & 64) {\n          strm.msg = 'invalid literal/length code';\n          state.mode = BAD$1;\n          break;\n        }\n        state.extra = here_op & 15;\n        state.mode = LENEXT;\n        /* falls through */\n      case LENEXT:\n        if (state.extra) {\n          //=== NEEDBITS(state.extra);\n          n = state.extra;\n          while (bits < n) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n          //--- DROPBITS(state.extra) ---//\n          hold >>>= state.extra;\n          bits -= state.extra;\n          //---//\n          state.back += state.extra;\n        }\n        //Tracevv((stderr, \"inflate:         length %u\\n\", state.length));\n        state.was = state.length;\n        state.mode = DIST;\n        /* falls through */\n      case DIST:\n        for (;;) {\n          here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/\n          here_bits = here >>> 24;\n          here_op = (here >>> 16) & 0xff;\n          here_val = here & 0xffff;\n\n          if ((here_bits) <= bits) { break; }\n          //--- PULLBYTE() ---//\n          if (have === 0) { break inf_leave; }\n          have--;\n          hold += input[next++] << bits;\n          bits += 8;\n          //---//\n        }\n        if ((here_op & 0xf0) === 0) {\n          last_bits = here_bits;\n          last_op = here_op;\n          last_val = here_val;\n          for (;;) {\n            here = state.distcode[last_val +\n                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n            here_bits = here >>> 24;\n            here_op = (here >>> 16) & 0xff;\n            here_val = here & 0xffff;\n\n            if ((last_bits + here_bits) <= bits) { break; }\n            //--- PULLBYTE() ---//\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n            //---//\n          }\n          //--- DROPBITS(last.bits) ---//\n          hold >>>= last_bits;\n          bits -= last_bits;\n          //---//\n          state.back += last_bits;\n        }\n        //--- DROPBITS(here.bits) ---//\n        hold >>>= here_bits;\n        bits -= here_bits;\n        //---//\n        state.back += here_bits;\n        if (here_op & 64) {\n          strm.msg = 'invalid distance code';\n          state.mode = BAD$1;\n          break;\n        }\n        state.offset = here_val;\n        state.extra = (here_op) & 15;\n        state.mode = DISTEXT;\n        /* falls through */\n      case DISTEXT:\n        if (state.extra) {\n          //=== NEEDBITS(state.extra);\n          n = state.extra;\n          while (bits < n) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n          //--- DROPBITS(state.extra) ---//\n          hold >>>= state.extra;\n          bits -= state.extra;\n          //---//\n          state.back += state.extra;\n        }\n//#ifdef INFLATE_STRICT\n        if (state.offset > state.dmax) {\n          strm.msg = 'invalid distance too far back';\n          state.mode = BAD$1;\n          break;\n        }\n//#endif\n        //Tracevv((stderr, \"inflate:         distance %u\\n\", state.offset));\n        state.mode = MATCH;\n        /* falls through */\n      case MATCH:\n        if (left === 0) { break inf_leave; }\n        copy = _out - left;\n        if (state.offset > copy) {         /* copy from window */\n          copy = state.offset - copy;\n          if (copy > state.whave) {\n            if (state.sane) {\n              strm.msg = 'invalid distance too far back';\n              state.mode = BAD$1;\n              break;\n            }\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n//          Trace((stderr, \"inflate.c too far\\n\"));\n//          copy -= state.whave;\n//          if (copy > state.length) { copy = state.length; }\n//          if (copy > left) { copy = left; }\n//          left -= copy;\n//          state.length -= copy;\n//          do {\n//            output[put++] = 0;\n//          } while (--copy);\n//          if (state.length === 0) { state.mode = LEN; }\n//          break;\n//#endif\n          }\n          if (copy > state.wnext) {\n            copy -= state.wnext;\n            from = state.wsize - copy;\n          }\n          else {\n            from = state.wnext - copy;\n          }\n          if (copy > state.length) { copy = state.length; }\n          from_source = state.window;\n        }\n        else {                              /* copy from output */\n          from_source = output;\n          from = put - state.offset;\n          copy = state.length;\n        }\n        if (copy > left) { copy = left; }\n        left -= copy;\n        state.length -= copy;\n        do {\n          output[put++] = from_source[from++];\n        } while (--copy);\n        if (state.length === 0) { state.mode = LEN; }\n        break;\n      case LIT:\n        if (left === 0) { break inf_leave; }\n        output[put++] = state.length;\n        left--;\n        state.mode = LEN;\n        break;\n      case CHECK:\n        if (state.wrap) {\n          //=== NEEDBITS(32);\n          while (bits < 32) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            // Use '|' instead of '+' to make sure that result is signed\n            hold |= input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          _out -= left;\n          strm.total_out += _out;\n          state.total += _out;\n          if (_out) {\n            strm.adler = state.check =\n                /*UPDATE(state.check, put - _out, _out);*/\n                (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));\n\n          }\n          _out = left;\n          // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too\n          if ((state.flags ? hold : zswap32(hold)) !== state.check) {\n            strm.msg = 'incorrect data check';\n            state.mode = BAD$1;\n            break;\n          }\n          //=== INITBITS();\n          hold = 0;\n          bits = 0;\n          //===//\n          //Tracev((stderr, \"inflate:   check matches trailer\\n\"));\n        }\n        state.mode = LENGTH;\n        /* falls through */\n      case LENGTH:\n        if (state.wrap && state.flags) {\n          //=== NEEDBITS(32);\n          while (bits < 32) {\n            if (have === 0) { break inf_leave; }\n            have--;\n            hold += input[next++] << bits;\n            bits += 8;\n          }\n          //===//\n          if (hold !== (state.total & 0xffffffff)) {\n            strm.msg = 'incorrect length check';\n            state.mode = BAD$1;\n            break;\n          }\n          //=== INITBITS();\n          hold = 0;\n          bits = 0;\n          //===//\n          //Tracev((stderr, \"inflate:   length matches trailer\\n\"));\n        }\n        state.mode = DONE;\n        /* falls through */\n      case DONE:\n        ret = Z_STREAM_END$1;\n        break inf_leave;\n      case BAD$1:\n        ret = Z_DATA_ERROR$1;\n        break inf_leave;\n      case MEM:\n        return Z_MEM_ERROR;\n      case SYNC:\n        /* falls through */\n      default:\n        return Z_STREAM_ERROR$1;\n    }\n  }\n\n  // inf_leave <- here is real place for \"goto inf_leave\", emulated via \"break inf_leave\"\n\n  /*\n     Return from inflate(), updating the total counts and the check value.\n     If there was no progress during the inflate() call, return a buffer\n     error.  Call updatewindow() to create and/or update the window state.\n     Note: a memory error from inflate() is non-recoverable.\n   */\n\n  //--- RESTORE() ---\n  strm.next_out = put;\n  strm.avail_out = left;\n  strm.next_in = next;\n  strm.avail_in = have;\n  state.hold = hold;\n  state.bits = bits;\n  //---\n\n  if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 &&\n                      (state.mode < CHECK || flush !== Z_FINISH$1))) {\n    if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;\n  }\n  _in -= strm.avail_in;\n  _out -= strm.avail_out;\n  strm.total_in += _in;\n  strm.total_out += _out;\n  state.total += _out;\n  if (state.wrap && _out) {\n    strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/\n      (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));\n  }\n  strm.data_type = state.bits + (state.last ? 64 : 0) +\n                    (state.mode === TYPE$1 ? 128 : 0) +\n                    (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);\n  if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {\n    ret = Z_BUF_ERROR$1;\n  }\n  return ret;\n}\n\nfunction inflateEnd(strm) {\n\n  if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {\n    return Z_STREAM_ERROR$1;\n  }\n\n  var state = strm.state;\n  if (state.window) {\n    state.window = null;\n  }\n  strm.state = null;\n  return Z_OK$1;\n}\n\nfunction inflateGetHeader(strm, head) {\n  var state;\n\n  /* check state */\n  if (!strm || !strm.state) { return Z_STREAM_ERROR$1; }\n  state = strm.state;\n  if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }\n\n  /* save header structure */\n  state.head = head;\n  head.done = false;\n  return Z_OK$1;\n}\n\nfunction inflateSetDictionary(strm, dictionary) {\n  var dictLength = dictionary.length;\n\n  var state;\n  var dictid;\n  var ret;\n\n  /* check state */\n  if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR$1; }\n  state = strm.state;\n\n  if (state.wrap !== 0 && state.mode !== DICT) {\n    return Z_STREAM_ERROR$1;\n  }\n\n  /* check for correct dictionary identifier */\n  if (state.mode === DICT) {\n    dictid = 1; /* adler32(0, null, 0)*/\n    /* dictid = adler32(dictid, dictionary, dictLength); */\n    dictid = adler32(dictid, dictionary, dictLength, 0);\n    if (dictid !== state.check) {\n      return Z_DATA_ERROR$1;\n    }\n  }\n  /* copy dictionary to window using updatewindow(), which will amend the\n   existing dictionary if appropriate */\n  ret = updatewindow(strm, dictionary, dictLength, dictLength);\n  if (ret) {\n    state.mode = MEM;\n    return Z_MEM_ERROR;\n  }\n  state.havedict = 1;\n  // Tracev((stderr, \"inflate:   dictionary set\\n\"));\n  return Z_OK$1;\n}\n\n/* Not implemented\nexports.inflateCopy = inflateCopy;\nexports.inflateGetDictionary = inflateGetDictionary;\nexports.inflateMark = inflateMark;\nexports.inflatePrime = inflatePrime;\nexports.inflateSync = inflateSync;\nexports.inflateSyncPoint = inflateSyncPoint;\nexports.inflateUndermine = inflateUndermine;\n*/\n\n/* eslint-disable */\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar msg = {\n  2:      'need dictionary',     /* Z_NEED_DICT       2  */\n  1:      'stream end',          /* Z_STREAM_END      1  */\n  0:      '',                    /* Z_OK              0  */\n  '-1':   'file error',          /* Z_ERRNO         (-1) */\n  '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */\n  '-3':   'data error',          /* Z_DATA_ERROR    (-3) */\n  '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */\n  '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */\n  '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */\n};\n\n/* eslint-disable */\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction ZStream() {\n  /* next input byte */\n  this.input = null; // JS specific, because we have no pointers\n  this.next_in = 0;\n  /* number of bytes available at input */\n  this.avail_in = 0;\n  /* total number of input bytes read so far */\n  this.total_in = 0;\n  /* next output byte should be put there */\n  this.output = null; // JS specific, because we have no pointers\n  this.next_out = 0;\n  /* remaining free space at output */\n  this.avail_out = 0;\n  /* total number of bytes output so far */\n  this.total_out = 0;\n  /* last error message, NULL if no error */\n  this.msg = ''/*Z_NULL*/;\n  /* not visible by applications */\n  this.state = null;\n  /* best guess about the data type: binary or text */\n  this.data_type = 2/*Z_UNKNOWN*/;\n  /* adler32 value of the uncompressed data */\n  this.adler = 0;\n}\n\n/* eslint-disable */\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n//   claim that you wrote the original software. If you use this software\n//   in a product, an acknowledgment in the product documentation would be\n//   appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//   misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction GZheader() {\n  /* true if compressed data believed to be text */\n  this.text       = 0;\n  /* modification time */\n  this.time       = 0;\n  /* extra flags (not used when writing a gzip file) */\n  this.xflags     = 0;\n  /* operating system */\n  this.os         = 0;\n  /* pointer to extra field or Z_NULL if none */\n  this.extra      = null;\n  /* extra field length (valid if extra != Z_NULL) */\n  this.extra_len  = 0; // Actually, we don't need it in JS,\n                       // but leave for few code modifications\n\n  //\n  // Setup limits is not necessary because in js we should not preallocate memory\n  // for inflate use constant limit in 65536 bytes\n  //\n\n  /* space at extra (only when reading header) */\n  // this.extra_max  = 0;\n  /* pointer to zero-terminated file name or Z_NULL */\n  this.name       = '';\n  /* space at name (only when reading header) */\n  // this.name_max   = 0;\n  /* pointer to zero-terminated comment or Z_NULL */\n  this.comment    = '';\n  /* space at comment (only when reading header) */\n  // this.comm_max   = 0;\n  /* true if there was or will be a header crc */\n  this.hcrc       = 0;\n  /* true when done reading gzip header (not used when writing a gzip file) */\n  this.done       = false;\n}\n\n/* eslint-disable */\n\nvar toString = Object.prototype.toString;\n\n/**\n * class Inflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[inflate]]\n * and [[inflateRaw]].\n **/\n\n/* internal\n * inflate.chunks -> Array\n *\n * Chunks of output data, if [[Inflate#onData]] not overridden.\n **/\n\n/**\n * Inflate.result -> Uint8Array|Array|String\n *\n * Uncompressed result, generated by default [[Inflate#onData]]\n * and [[Inflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you\n * push a chunk with explicit flush (call [[Inflate#push]] with\n * `Z_SYNC_FLUSH` param).\n **/\n\n/**\n * Inflate.err -> Number\n *\n * Error code after inflate finished. 0 (Z_OK) on success.\n * Should be checked if broken data possible.\n **/\n\n/**\n * Inflate.msg -> String\n *\n * Error message, if [[Inflate.err]] != 0\n **/\n\n\n/**\n * new Inflate(options)\n * - options (Object): zlib inflate options.\n *\n * Creates new inflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `windowBits`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw inflate\n * - `to` (String) - if equal to 'string', then result will be converted\n *   from utf8 to utf16 (javascript) string. When string output requested,\n *   chunk length can differ from `chunkSize`, depending on content.\n *\n * By default, when no options set, autodetect deflate/gzip data format via\n * wrapper header.\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])\n *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * var inflate = new pako.Inflate({ level: 3});\n *\n * inflate.push(chunk1, false);\n * inflate.push(chunk2, true);  // true -> last chunk\n *\n * if (inflate.err) { throw new Error(inflate.err); }\n *\n * console.log(inflate.result);\n * ```\n **/\nvar Inflate = function Inflate(options) {\n  if (!(this instanceof Inflate)) { return new Inflate(options); }\n\n  this.options = assign({\n    chunkSize: 16384,\n    windowBits: 0,\n    to: ''\n  }, options || {});\n\n  var opt = this.options;\n\n  // Force window size for `raw` data, if not set directly,\n  // because we have no header for autodetect.\n  if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {\n    opt.windowBits = -opt.windowBits;\n    if (opt.windowBits === 0) { opt.windowBits = -15; }\n  }\n\n  // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate\n  if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&\n      !(options && options.windowBits)) {\n    opt.windowBits += 32;\n  }\n\n  // Gzip header has no info about windows size, we can do autodetect only\n  // for deflate. So, if window size not set, force it to max when gzip possible\n  if ((opt.windowBits > 15) && (opt.windowBits < 48)) {\n    // bit 3 (16) -> gzipped data\n    // bit 4 (32) -> autodetect gzip/deflate\n    if ((opt.windowBits & 15) === 0) {\n      opt.windowBits |= 15;\n    }\n  }\n\n  this.err  = 0;    // error code, if happens (0 = Z_OK)\n  this.msg  = '';   // error message\n  this.ended= false;// used to avoid multiple onEnd() calls\n  this.chunks = [];   // chunks of compressed data\n\n  this.strm = new ZStream();\n  this.strm.avail_out = 0;\n\n  var status= inflateInit2(\n    this.strm,\n    opt.windowBits\n  );\n\n  if (status !== Z_OK) {\n    throw new Error(msg[status]);\n  }\n\n  this.header = new GZheader();\n\n  inflateGetHeader(this.strm, this.header);\n\n  // Setup dictionary\n  if (opt.dictionary) {\n    // Convert data if needed\n    if (typeof opt.dictionary === 'string') {\n      opt.dictionary = string2buf(opt.dictionary);\n    } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {\n      opt.dictionary = new Uint8Array(opt.dictionary);\n    }\n    if (opt.raw) { //In raw mode we need to set the dictionary early\n      status = inflateSetDictionary(this.strm, opt.dictionary);\n      if (status !== Z_OK) {\n        throw new Error(msg[status]);\n      }\n    }\n  }\n};\n\n/**\n * Inflate#push(data[, mode]) -> Boolean\n * - data (Uint8Array|Array|ArrayBuffer|String): input data\n * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.\n *\n * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with\n * new output chunks. Returns `true` on success. The last data block must have\n * mode Z_FINISH (or `true`). That will flush internal pending buffers and call\n * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you\n * can use mode Z_SYNC_FLUSH, keeping the decompression context.\n *\n * On fail call [[Inflate#onEnd]] with error code and return false.\n *\n * We strongly recommend to use `Uint8Array` on input for best speed (output\n * format is detected automatically). Also, don't skip last param and always\n * use the same type in your code (boolean or number). That will improve JS speed.\n *\n * For regular `Array`-s make sure all elements are [0..255].\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true);// push last chunk\n * ```\n **/\nInflate.prototype.push = function push (data, mode) {\n  var strm = this.strm;\n  var chunkSize = this.options.chunkSize;\n  var dictionary = this.options.dictionary;\n  var status, _mode;\n  var next_out_utf8, tail, utf8str;\n  var dict;\n\n  // Flag to properly process Z_BUF_ERROR on testing inflate call\n  // when we check that all output data was flushed.\n  var allowBufError = false;\n\n  if (this.ended) { return false; }\n  _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);\n\n  // Convert data if needed\n  if (typeof data === 'string') {\n    // Only binary strings can be decompressed on practice\n    strm.input = binstring2buf(data);\n  } else if (toString.call(data) === '[object ArrayBuffer]') {\n    strm.input = new Uint8Array(data);\n  } else {\n    strm.input = data;\n  }\n\n  strm.next_in = 0;\n  strm.avail_in = strm.input.length;\n\n  do {\n    if (strm.avail_out === 0) {\n      strm.output = Buf8(chunkSize);\n      strm.next_out = 0;\n      strm.avail_out = chunkSize;\n    }\n\n    status = inflate(strm, Z_NO_FLUSH);  /* no bad return value */\n\n    if (status === Z_NEED_DICT && dictionary) {\n      // Convert data if needed\n      if (typeof dictionary === 'string') {\n        dict = string2buf(dictionary);\n      } else if (toString.call(dictionary) === '[object ArrayBuffer]') {\n        dict = new Uint8Array(dictionary);\n      } else {\n        dict = dictionary;\n      }\n\n      status = inflateSetDictionary(this.strm, dict);\n\n    }\n\n    if (status === Z_BUF_ERROR && allowBufError === true) {\n      status = Z_OK;\n      allowBufError = false;\n    }\n\n    if (status !== Z_STREAM_END && status !== Z_OK) {\n      this.onEnd(status);\n      this.ended = true;\n      return false;\n    }\n\n    if (strm.next_out) {\n      if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) {\n\n        if (this.options.to === 'string') {\n\n          next_out_utf8 = utf8border(strm.output, strm.next_out);\n\n          tail = strm.next_out - next_out_utf8;\n          utf8str = buf2string(strm.output, next_out_utf8);\n\n          // move tail\n          strm.next_out = tail;\n          strm.avail_out = chunkSize - tail;\n          if (tail) { arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }\n\n          this.onData(utf8str);\n\n        } else {\n          this.onData(shrinkBuf(strm.output, strm.next_out));\n        }\n      }\n    }\n\n    // When no more input data, we should check that internal inflate buffers\n    // are flushed. The only way to do it when avail_out = 0 - run one more\n    // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR.\n    // Here we set flag to process this error properly.\n    //\n    // NOTE. Deflate does not return error in this case and does not needs such\n    // logic.\n    if (strm.avail_in === 0 && strm.avail_out === 0) {\n      allowBufError = true;\n    }\n\n  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);\n\n  if (status === Z_STREAM_END) {\n    _mode = Z_FINISH;\n  }\n\n  // Finalize on the last chunk.\n  if (_mode === Z_FINISH) {\n    status = inflateEnd(this.strm);\n    this.onEnd(status);\n    this.ended = true;\n    return status === Z_OK;\n  }\n\n  // callback interim results if Z_SYNC_FLUSH.\n  if (_mode === Z_SYNC_FLUSH) {\n    this.onEnd(Z_OK);\n    strm.avail_out = 0;\n    return true;\n  }\n\n  return true;\n};\n\n\n/**\n * Inflate#onData(chunk) -> Void\n * - chunk (Uint8Array|Array|String): output data. Type of array depends\n * on js engine support. When string output requested, each chunk\n * will be string.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nInflate.prototype.onData = function onData (chunk) {\n  this.chunks.push(chunk);\n};\n\n\n/**\n * Inflate#onEnd(status) -> Void\n * - status (Number): inflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called either after you tell inflate that the input stream is\n * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)\n * or if an error happened. By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nInflate.prototype.onEnd = function onEnd (status) {\n  // On success - join\n  if (status === Z_OK) {\n    if (this.options.to === 'string') {\n      // Glue & convert here, until we teach pako to send\n      // utf8 aligned strings to onData\n      this.result = this.chunks.join('');\n    } else {\n      this.result = flattenChunks(this.chunks);\n    }\n  }\n  this.chunks = [];\n  this.err = status;\n  this.msg = this.strm.msg;\n};\n\n/**\n * inflate(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Decompress `data` with inflate/ungzip and `options`. Autodetect\n * format via wrapper header by default. That's why we don't provide\n * separate `ungzip` method.\n *\n * Supported options are:\n *\n * - windowBits\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n *   negative windowBits implicitly.\n * - `to` (String) - if equal to 'string', then result will be converted\n *   from utf8 to utf16 (javascript) string. When string output requested,\n *   chunk length can differ from `chunkSize`, depending on content.\n *\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n *   , input = pako.deflate([1,2,3,4,5,6,7,8,9])\n *   , output;\n *\n * try {\n *   output = pako.inflate(input);\n * } catch (err)\n *   console.log(err);\n * }\n * ```\n **/\nfunction inflate$1(input, options) {\n  var inflator = new Inflate(options);\n\n  inflator.push(input, true);\n\n  // That will never happens, if you don't cheat with options :)\n  if (inflator.err) { throw inflator.msg || msg[inflator.err]; }\n\n  return inflator.result;\n}\n\n\n/**\n * inflateRaw(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * The same as [[inflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction inflateRaw(input, options) {\n  options = options || {};\n  options.raw = true;\n  return inflate$1(input, options);\n}\n\n/**\n * ungzip(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Just shortcut to [[inflate]], because it autodetects format\n * by header.content. Done for convenience.\n **/\nvar ungzip = inflate$1;\n\n/* eslint-disable */\n\nfunction zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }\n\n// From zutil.h\n\nvar STORED_BLOCK = 0;\nvar STATIC_TREES = 1;\nvar DYN_TREES    = 2;\n/* The three kinds of block type */\n\nvar MIN_MATCH    = 3;\nvar MAX_MATCH    = 258;\n/* The minimum and maximum match lengths */\n\n// From deflate.h\n/* ===========================================================================\n * Internal compression state.\n */\n\nvar LENGTH_CODES  = 29;\n/* number of length codes, not counting the special END_BLOCK code */\n\nvar LITERALS      = 256;\n/* number of literal bytes 0..255 */\n\nvar L_CODES       = LITERALS + 1 + LENGTH_CODES;\n/* number of Literal or Length codes, including the END_BLOCK code */\n\nvar D_CODES       = 30;\n/* number of distance codes */\n\nvar BL_CODES      = 19;\n/* number of codes used to transfer the bit lengths */\n\nvar HEAP_SIZE     = 2 * L_CODES + 1;\n/* maximum heap size */\n\nvar MAX_BITS      = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nvar Buf_size      = 16;\n/* size of bit buffer in bi_buf */\n\n\n/* ===========================================================================\n * Constants\n */\n\nvar MAX_BL_BITS = 7;\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\nvar END_BLOCK   = 256;\n/* end of block literal code */\n\nvar REP_3_6     = 16;\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\nvar REPZ_3_10   = 17;\n/* repeat a zero length 3-10 times  (3 bits of repeat count) */\n\nvar REPZ_11_138 = 18;\n/* repeat a zero length 11-138 times  (7 bits of repeat count) */\n\n/* eslint-disable comma-spacing,array-bracket-spacing */\nvar extra_lbits =   /* extra bits for each length code */\n  [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];\n\nvar extra_dbits =   /* extra bits for each distance code */\n  [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];\n\nvar extra_blbits =  /* extra bits for each bit length code */\n  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];\n\nvar bl_order =\n  [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];\n/* eslint-enable comma-spacing,array-bracket-spacing */\n\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n\n// We pre-fill arrays with 0 to avoid uninitialized gaps\n\nvar DIST_CODE_LEN = 512; /* see definition of array dist_code below */\n\n// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1\nvar static_ltree;\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nvar static_dtree;\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nvar _dist_code;\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nvar _length_code;\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nvar base_length;\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nvar base_dist;\n/* First normalized distance for each code (0 = distance of 1) */\n\n\nfunction StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {\n\n  this.static_tree  = static_tree;  /* static tree or NULL */\n  this.extra_bits   = extra_bits;   /* extra bits for each code or NULL */\n  this.extra_base   = extra_base;   /* base index for extra_bits */\n  this.elems        = elems;        /* max number of elements in the tree */\n  this.max_length   = max_length;   /* max bit length for the codes */\n\n  // show if `static_tree` has data or dummy - needed for monomorphic objects\n  this.has_stree    = static_tree && static_tree.length;\n}\n\n\nvar static_l_desc;\nvar static_d_desc;\nvar static_bl_desc;\n\n\nfunction TreeDesc(dyn_tree, stat_desc) {\n  this.dyn_tree = dyn_tree;     /* the dynamic tree */\n  this.max_code = 0;            /* largest code with non zero frequency */\n  this.stat_desc = stat_desc;   /* the corresponding static tree */\n}\n\n\n\nfunction d_code(dist) {\n  return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];\n}\n\n\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\nfunction put_short(s, w) {\n//    put_byte(s, (uch)((w) & 0xff));\n//    put_byte(s, (uch)((ush)(w) >> 8));\n  s.pending_buf[s.pending++] = (w) & 0xff;\n  s.pending_buf[s.pending++] = (w >>> 8) & 0xff;\n}\n\n\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\nfunction send_bits(s, value, length) {\n  if (s.bi_valid > (Buf_size - length)) {\n    s.bi_buf |= (value << s.bi_valid) & 0xffff;\n    put_short(s, s.bi_buf);\n    s.bi_buf = value >> (Buf_size - s.bi_valid);\n    s.bi_valid += length - Buf_size;\n  } else {\n    s.bi_buf |= (value << s.bi_valid) & 0xffff;\n    s.bi_valid += length;\n  }\n}\n\n\nfunction send_code(s, c, tree) {\n  send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);\n}\n\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nfunction bi_reverse(code, len) {\n  var res = 0;\n  do {\n    res |= code & 1;\n    code >>>= 1;\n    res <<= 1;\n  } while (--len > 0);\n  return res >>> 1;\n}\n\n\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\nfunction bi_flush(s) {\n  if (s.bi_valid === 16) {\n    put_short(s, s.bi_buf);\n    s.bi_buf = 0;\n    s.bi_valid = 0;\n\n  } else if (s.bi_valid >= 8) {\n    s.pending_buf[s.pending++] = s.bi_buf & 0xff;\n    s.bi_buf >>= 8;\n    s.bi_valid -= 8;\n  }\n}\n\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n *    above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n *     array bl_count contains the frequencies for each bit length.\n *     The length opt_len is updated; static_len is also updated if stree is\n *     not null.\n */\nfunction gen_bitlen(s, desc)\n//    deflate_state *s;\n//    tree_desc *desc;    /* the tree descriptor */\n{\n  var tree            = desc.dyn_tree;\n  var max_code        = desc.max_code;\n  var stree           = desc.stat_desc.static_tree;\n  var has_stree       = desc.stat_desc.has_stree;\n  var extra           = desc.stat_desc.extra_bits;\n  var base            = desc.stat_desc.extra_base;\n  var max_length      = desc.stat_desc.max_length;\n  var h;              /* heap index */\n  var n, m;           /* iterate over the tree elements */\n  var bits;           /* bit length */\n  var xbits;          /* extra bits */\n  var f;              /* frequency */\n  var overflow = 0;   /* number of elements with bit length too large */\n\n  for (bits = 0; bits <= MAX_BITS; bits++) {\n    s.bl_count[bits] = 0;\n  }\n\n  /* In a first pass, compute the optimal bit lengths (which may\n   * overflow in the case of the bit length tree).\n   */\n  tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */\n\n  for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {\n    n = s.heap[h];\n    bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;\n    if (bits > max_length) {\n      bits = max_length;\n      overflow++;\n    }\n    tree[n * 2 + 1]/*.Len*/ = bits;\n    /* We overwrite tree[n].Dad which is no longer needed */\n\n    if (n > max_code) { continue; } /* not a leaf node */\n\n    s.bl_count[bits]++;\n    xbits = 0;\n    if (n >= base) {\n      xbits = extra[n - base];\n    }\n    f = tree[n * 2]/*.Freq*/;\n    s.opt_len += f * (bits + xbits);\n    if (has_stree) {\n      s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);\n    }\n  }\n  if (overflow === 0) { return; }\n\n  // Trace((stderr,\"\\nbit length overflow\\n\"));\n  /* This happens for example on obj2 and pic of the Calgary corpus */\n\n  /* Find the first bit length which could increase: */\n  do {\n    bits = max_length - 1;\n    while (s.bl_count[bits] === 0) { bits--; }\n    s.bl_count[bits]--;      /* move one leaf down the tree */\n    s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */\n    s.bl_count[max_length]--;\n    /* The brother of the overflow item also moves one step up,\n     * but this does not affect bl_count[max_length]\n     */\n    overflow -= 2;\n  } while (overflow > 0);\n\n  /* Now recompute all bit lengths, scanning in increasing frequency.\n   * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n   * lengths instead of fixing only the wrong ones. This idea is taken\n   * from 'ar' written by Haruhiko Okumura.)\n   */\n  for (bits = max_length; bits !== 0; bits--) {\n    n = s.bl_count[bits];\n    while (n !== 0) {\n      m = s.heap[--h];\n      if (m > max_code) { continue; }\n      if (tree[m * 2 + 1]/*.Len*/ !== bits) {\n        // Trace((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n        s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;\n        tree[m * 2 + 1]/*.Len*/ = bits;\n      }\n      n--;\n    }\n  }\n}\n\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n *     zero code length.\n */\nfunction gen_codes(tree, max_code, bl_count)\n//    ct_data *tree;             /* the tree to decorate */\n//    int max_code;              /* largest code with non zero frequency */\n//    ushf *bl_count;            /* number of codes at each bit length */\n{\n  var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */\n  var code = 0;              /* running code value */\n  var bits;                  /* bit index */\n  var n;                     /* code index */\n\n  /* The distribution counts are first used to generate the code values\n   * without bit reversal.\n   */\n  for (bits = 1; bits <= MAX_BITS; bits++) {\n    next_code[bits] = code = (code + bl_count[bits - 1]) << 1;\n  }\n  /* Check that the bit counts in bl_count are consistent. The last code\n   * must be all ones.\n   */\n  //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,\n  //        \"inconsistent bit counts\");\n  //Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n  for (n = 0;  n <= max_code; n++) {\n    var len = tree[n * 2 + 1]/*.Len*/;\n    if (len === 0) { continue; }\n    /* Now reverse the bits */\n    tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);\n\n    //Tracecv(tree != static_ltree, (stderr,\"\\nn %3d %c l %2d c %4x (%x) \",\n    //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));\n  }\n}\n\n\n/* ===========================================================================\n * Initialize the various 'constant' tables.\n */\nfunction tr_static_init() {\n  var n;        /* iterates over tree elements */\n  var bits;     /* bit counter */\n  var length;   /* length value */\n  var code;     /* code value */\n  var dist;     /* distance index */\n  var bl_count = new Array(MAX_BITS + 1);\n  /* number of codes at each bit length for an optimal tree */\n\n  static_ltree  = new Array((L_CODES + 2) * 2);\n  zero(static_ltree);\n\n  static_dtree  = new Array(D_CODES * 2);\n  zero(static_dtree);\n\n  _dist_code    = new Array(DIST_CODE_LEN);\n  zero(_dist_code);\n\n  _length_code  = new Array(MAX_MATCH - MIN_MATCH + 1);\n  zero(_length_code);\n\n  base_length   = new Array(LENGTH_CODES);\n  zero(base_length);\n\n  base_dist     = new Array(D_CODES);\n  zero(base_dist);\n\n  // do check in _tr_init()\n  //if (static_init_done) return;\n\n  /* For some embedded targets, global variables are not initialized: */\n/*#ifdef NO_INIT_GLOBAL_POINTERS\n  static_l_desc.static_tree = static_ltree;\n  static_l_desc.extra_bits = extra_lbits;\n  static_d_desc.static_tree = static_dtree;\n  static_d_desc.extra_bits = extra_dbits;\n  static_bl_desc.extra_bits = extra_blbits;\n#endif*/\n\n  /* Initialize the mapping length (0..255) -> length code (0..28) */\n  length = 0;\n  for (code = 0; code < LENGTH_CODES - 1; code++) {\n    base_length[code] = length;\n    for (n = 0; n < (1 << extra_lbits[code]); n++) {\n      _length_code[length++] = code;\n    }\n  }\n  //Assert (length == 256, \"tr_static_init: length != 256\");\n  /* Note that the length 255 (match length 258) can be represented\n   * in two different ways: code 284 + 5 bits or code 285, so we\n   * overwrite length_code[255] to use the best encoding:\n   */\n  _length_code[length - 1] = code;\n\n  /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n  dist = 0;\n  for (code = 0; code < 16; code++) {\n    base_dist[code] = dist;\n    for (n = 0; n < (1 << extra_dbits[code]); n++) {\n      _dist_code[dist++] = code;\n    }\n  }\n  //Assert (dist == 256, \"tr_static_init: dist != 256\");\n  dist >>= 7; /* from now on, all distances are divided by 128 */\n  for (; code < D_CODES; code++) {\n    base_dist[code] = dist << 7;\n    for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {\n      _dist_code[256 + dist++] = code;\n    }\n  }\n  //Assert (dist == 256, \"tr_static_init: 256+dist != 512\");\n\n  /* Construct the codes of the static literal tree */\n  for (bits = 0; bits <= MAX_BITS; bits++) {\n    bl_count[bits] = 0;\n  }\n\n  n = 0;\n  while (n <= 143) {\n    static_ltree[n * 2 + 1]/*.Len*/ = 8;\n    n++;\n    bl_count[8]++;\n  }\n  while (n <= 255) {\n    static_ltree[n * 2 + 1]/*.Len*/ = 9;\n    n++;\n    bl_count[9]++;\n  }\n  while (n <= 279) {\n    static_ltree[n * 2 + 1]/*.Len*/ = 7;\n    n++;\n    bl_count[7]++;\n  }\n  while (n <= 287) {\n    static_ltree[n * 2 + 1]/*.Len*/ = 8;\n    n++;\n    bl_count[8]++;\n  }\n  /* Codes 286 and 287 do not exist, but we must include them in the\n   * tree construction to get a canonical Huffman tree (longest code\n   * all ones)\n   */\n  gen_codes(static_ltree, L_CODES + 1, bl_count);\n\n  /* The static distance tree is trivial: */\n  for (n = 0; n < D_CODES; n++) {\n    static_dtree[n * 2 + 1]/*.Len*/ = 5;\n    static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);\n  }\n\n  // Now data ready and we can init static trees\n  static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);\n  static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS);\n  static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0,         BL_CODES, MAX_BL_BITS);\n\n  //static_init_done = true;\n}\n\n\n/* ===========================================================================\n * Initialize a new block.\n */\nfunction init_block(s) {\n  var n; /* iterates over tree elements */\n\n  /* Initialize the trees. */\n  for (n = 0; n < L_CODES;  n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }\n  for (n = 0; n < D_CODES;  n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }\n  for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }\n\n  s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;\n  s.opt_len = s.static_len = 0;\n  s.last_lit = s.matches = 0;\n}\n\n\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\nfunction bi_windup(s)\n{\n  if (s.bi_valid > 8) {\n    put_short(s, s.bi_buf);\n  } else if (s.bi_valid > 0) {\n    //put_byte(s, (Byte)s->bi_buf);\n    s.pending_buf[s.pending++] = s.bi_buf;\n  }\n  s.bi_buf = 0;\n  s.bi_valid = 0;\n}\n\n/* ===========================================================================\n * Copy a stored block, storing first the length and its\n * one's complement if requested.\n */\nfunction copy_block(s, buf, len, header)\n//DeflateState *s;\n//charf    *buf;    /* the input data */\n//unsigned len;     /* its length */\n//int      header;  /* true if block header must be written */\n{\n  bi_windup(s);        /* align on byte boundary */\n\n  if (header) {\n    put_short(s, len);\n    put_short(s, ~len);\n  }\n//  while (len--) {\n//    put_byte(s, *buf++);\n//  }\n  arraySet(s.pending_buf, s.window, buf, len, s.pending);\n  s.pending += len;\n}\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\nfunction smaller(tree, n, m, depth) {\n  var _n2 = n * 2;\n  var _m2 = m * 2;\n  return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||\n         (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));\n}\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nfunction pqdownheap(s, tree, k)\n//    deflate_state *s;\n//    ct_data *tree;  /* the tree to restore */\n//    int k;               /* node to move down */\n{\n  var v = s.heap[k];\n  var j = k << 1;  /* left son of k */\n  while (j <= s.heap_len) {\n    /* Set j to the smallest of the two sons: */\n    if (j < s.heap_len &&\n      smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {\n      j++;\n    }\n    /* Exit if v is smaller than both sons */\n    if (smaller(tree, v, s.heap[j], s.depth)) { break; }\n\n    /* Exchange v with the smallest son */\n    s.heap[k] = s.heap[j];\n    k = j;\n\n    /* And continue down the tree, setting j to the left son of k */\n    j <<= 1;\n  }\n  s.heap[k] = v;\n}\n\n\n// inlined manually\n// var SMALLEST = 1;\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nfunction compress_block(s, ltree, dtree)\n//    deflate_state *s;\n//    const ct_data *ltree; /* literal tree */\n//    const ct_data *dtree; /* distance tree */\n{\n  var dist;           /* distance of matched string */\n  var lc;             /* match length or unmatched char (if dist == 0) */\n  var lx = 0;         /* running index in l_buf */\n  var code;           /* the code to send */\n  var extra;          /* number of extra bits to send */\n\n  if (s.last_lit !== 0) {\n    do {\n      dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);\n      lc = s.pending_buf[s.l_buf + lx];\n      lx++;\n\n      if (dist === 0) {\n        send_code(s, lc, ltree); /* send a literal byte */\n        //Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n      } else {\n        /* Here, lc is the match length - MIN_MATCH */\n        code = _length_code[lc];\n        send_code(s, code + LITERALS + 1, ltree); /* send the length code */\n        extra = extra_lbits[code];\n        if (extra !== 0) {\n          lc -= base_length[code];\n          send_bits(s, lc, extra);       /* send the extra length bits */\n        }\n        dist--; /* dist is now the match distance - 1 */\n        code = d_code(dist);\n        //Assert (code < D_CODES, \"bad d_code\");\n\n        send_code(s, code, dtree);       /* send the distance code */\n        extra = extra_dbits[code];\n        if (extra !== 0) {\n          dist -= base_dist[code];\n          send_bits(s, dist, extra);   /* send the extra distance bits */\n        }\n      } /* literal or match pair ? */\n\n      /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */\n      //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,\n      //       \"pendingBuf overflow\");\n\n    } while (lx < s.last_lit);\n  }\n\n  send_code(s, END_BLOCK, ltree);\n}\n\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n *     and corresponding code. The length opt_len is updated; static_len is\n *     also updated if stree is not null. The field max_code is set.\n */\nfunction build_tree(s, desc)\n//    deflate_state *s;\n//    tree_desc *desc; /* the tree descriptor */\n{\n  var tree     = desc.dyn_tree;\n  var stree    = desc.stat_desc.static_tree;\n  var has_stree = desc.stat_desc.has_stree;\n  var elems    = desc.stat_desc.elems;\n  var n, m;          /* iterate over heap elements */\n  var max_code = -1; /* largest code with non zero frequency */\n  var node;          /* new node being created */\n\n  /* Construct the initial heap, with least frequent element in\n   * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n   * heap[0] is not used.\n   */\n  s.heap_len = 0;\n  s.heap_max = HEAP_SIZE;\n\n  for (n = 0; n < elems; n++) {\n    if (tree[n * 2]/*.Freq*/ !== 0) {\n      s.heap[++s.heap_len] = max_code = n;\n      s.depth[n] = 0;\n\n    } else {\n      tree[n * 2 + 1]/*.Len*/ = 0;\n    }\n  }\n\n  /* The pkzip format requires that at least one distance code exists,\n   * and that at least one bit should be sent even if there is only one\n   * possible code. So to avoid special checks later on we force at least\n   * two codes of non zero frequency.\n   */\n  while (s.heap_len < 2) {\n    node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);\n    tree[node * 2]/*.Freq*/ = 1;\n    s.depth[node] = 0;\n    s.opt_len--;\n\n    if (has_stree) {\n      s.static_len -= stree[node * 2 + 1]/*.Len*/;\n    }\n    /* node is 0 or 1 so it does not have extra bits */\n  }\n  desc.max_code = max_code;\n\n  /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n   * establish sub-heaps of increasing lengths:\n   */\n  for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }\n\n  /* Construct the Huffman tree by repeatedly combining the least two\n   * frequent nodes.\n   */\n  node = elems;              /* next internal node of the tree */\n  do {\n    //pqremove(s, tree, n);  /* n = node of least frequency */\n    /*** pqremove ***/\n    n = s.heap[1/*SMALLEST*/];\n    s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];\n    pqdownheap(s, tree, 1/*SMALLEST*/);\n    /***/\n\n    m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */\n\n    s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */\n    s.heap[--s.heap_max] = m;\n\n    /* Create a new node father of n and m */\n    tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;\n    s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;\n    tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;\n\n    /* and insert the new node in the heap */\n    s.heap[1/*SMALLEST*/] = node++;\n    pqdownheap(s, tree, 1/*SMALLEST*/);\n\n  } while (s.heap_len >= 2);\n\n  s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];\n\n  /* At this point, the fields freq and dad are set. We can now\n   * generate the bit lengths.\n   */\n  gen_bitlen(s, desc);\n\n  /* The field len is now set, we can generate the bit codes */\n  gen_codes(tree, max_code, s.bl_count);\n}\n\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\nfunction scan_tree(s, tree, max_code)\n//    deflate_state *s;\n//    ct_data *tree;   /* the tree to be scanned */\n//    int max_code;    /* and its largest code of non zero frequency */\n{\n  var n;                     /* iterates over all tree elements */\n  var prevlen = -1;          /* last emitted length */\n  var curlen;                /* length of current code */\n\n  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n  var count = 0;             /* repeat count of the current code */\n  var max_count = 7;         /* max repeat count */\n  var min_count = 4;         /* min repeat count */\n\n  if (nextlen === 0) {\n    max_count = 138;\n    min_count = 3;\n  }\n  tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */\n\n  for (n = 0; n <= max_code; n++) {\n    curlen = nextlen;\n    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n    if (++count < max_count && curlen === nextlen) {\n      continue;\n\n    } else if (count < min_count) {\n      s.bl_tree[curlen * 2]/*.Freq*/ += count;\n\n    } else if (curlen !== 0) {\n\n      if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }\n      s.bl_tree[REP_3_6 * 2]/*.Freq*/++;\n\n    } else if (count <= 10) {\n      s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;\n\n    } else {\n      s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;\n    }\n\n    count = 0;\n    prevlen = curlen;\n\n    if (nextlen === 0) {\n      max_count = 138;\n      min_count = 3;\n\n    } else if (curlen === nextlen) {\n      max_count = 6;\n      min_count = 3;\n\n    } else {\n      max_count = 7;\n      min_count = 4;\n    }\n  }\n}\n\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nfunction send_tree(s, tree, max_code)\n//    deflate_state *s;\n//    ct_data *tree; /* the tree to be scanned */\n//    int max_code;       /* and its largest code of non zero frequency */\n{\n  var n;                     /* iterates over all tree elements */\n  var prevlen = -1;          /* last emitted length */\n  var curlen;                /* length of current code */\n\n  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n  var count = 0;             /* repeat count of the current code */\n  var max_count = 7;         /* max repeat count */\n  var min_count = 4;         /* min repeat count */\n\n  /* tree[max_code+1].Len = -1; */  /* guard already set */\n  if (nextlen === 0) {\n    max_count = 138;\n    min_count = 3;\n  }\n\n  for (n = 0; n <= max_code; n++) {\n    curlen = nextlen;\n    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n    if (++count < max_count && curlen === nextlen) {\n      continue;\n\n    } else if (count < min_count) {\n      do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);\n\n    } else if (curlen !== 0) {\n      if (curlen !== prevlen) {\n        send_code(s, curlen, s.bl_tree);\n        count--;\n      }\n      //Assert(count >= 3 && count <= 6, \" 3_6?\");\n      send_code(s, REP_3_6, s.bl_tree);\n      send_bits(s, count - 3, 2);\n\n    } else if (count <= 10) {\n      send_code(s, REPZ_3_10, s.bl_tree);\n      send_bits(s, count - 3, 3);\n\n    } else {\n      send_code(s, REPZ_11_138, s.bl_tree);\n      send_bits(s, count - 11, 7);\n    }\n\n    count = 0;\n    prevlen = curlen;\n    if (nextlen === 0) {\n      max_count = 138;\n      min_count = 3;\n\n    } else if (curlen === nextlen) {\n      max_count = 6;\n      min_count = 3;\n\n    } else {\n      max_count = 7;\n      min_count = 4;\n    }\n  }\n}\n\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nfunction build_bl_tree(s) {\n  var max_blindex;  /* index of last bit length code of non zero freq */\n\n  /* Determine the bit length frequencies for literal and distance trees */\n  scan_tree(s, s.dyn_ltree, s.l_desc.max_code);\n  scan_tree(s, s.dyn_dtree, s.d_desc.max_code);\n\n  /* Build the bit length tree: */\n  build_tree(s, s.bl_desc);\n  /* opt_len now includes the length of the tree representations, except\n   * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n   */\n\n  /* Determine the number of bit length codes to send. The pkzip format\n   * requires that at least 4 bit length codes be sent. (appnote.txt says\n   * 3 but the actual value used is 4.)\n   */\n  for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {\n    if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {\n      break;\n    }\n  }\n  /* Update opt_len to include the bit length tree and counts */\n  s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;\n  //Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n  //        s->opt_len, s->static_len));\n\n  return max_blindex;\n}\n\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nfunction send_all_trees(s, lcodes, dcodes, blcodes)\n//    deflate_state *s;\n//    int lcodes, dcodes, blcodes; /* number of codes for each tree */\n{\n  var rank;                    /* index in bl_order */\n\n  //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n  //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n  //        \"too many codes\");\n  //Tracev((stderr, \"\\nbl counts: \"));\n  send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */\n  send_bits(s, dcodes - 1,   5);\n  send_bits(s, blcodes - 4,  4); /* not -3 as stated in appnote.txt */\n  for (rank = 0; rank < blcodes; rank++) {\n    //Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n    send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);\n  }\n  //Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n  send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */\n  //Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n  send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */\n  //Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n}\n\n\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n *    a) There are no non-portable control characters belonging to the\n *       \"black list\" (0..6, 14..25, 28..31).\n *    b) There is at least one printable character belonging to the\n *       \"white list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n *   \"gray list\" that is ignored in this detection algorithm:\n *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\nfunction detect_data_type(s) {\n  /* black_mask is the bit mask of black-listed bytes\n   * set bits 0..6, 14..25, and 28..31\n   * 0xf3ffc07f = binary 11110011111111111100000001111111\n   */\n  var black_mask = 0xf3ffc07f;\n  var n;\n\n  /* Check for non-textual (\"black-listed\") bytes. */\n  for (n = 0; n <= 31; n++, black_mask >>>= 1) {\n    if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {\n      return Z_BINARY;\n    }\n  }\n\n  /* Check for textual (\"white-listed\") bytes. */\n  if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||\n      s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {\n    return Z_TEXT;\n  }\n  for (n = 32; n < LITERALS; n++) {\n    if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {\n      return Z_TEXT;\n    }\n  }\n\n  /* There are no \"black-listed\" or \"white-listed\" bytes:\n   * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n   */\n  return Z_BINARY;\n}\n\n\nvar static_init_done = false;\n\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\nfunction _tr_init(s) {\n\n  if (!static_init_done) {\n    tr_static_init();\n    static_init_done = true;\n  }\n\n  s.l_desc  = new TreeDesc(s.dyn_ltree, static_l_desc);\n  s.d_desc  = new TreeDesc(s.dyn_dtree, static_d_desc);\n  s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);\n\n  s.bi_buf = 0;\n  s.bi_valid = 0;\n\n  /* Initialize the first block of the first file: */\n  init_block(s);\n}\n\n\n/* ===========================================================================\n * Send a stored block\n */\nfunction _tr_stored_block(s, buf, stored_len, last) {\n  //DeflateState *s;\n  //charf *buf;       /* input block */\n  //ulg stored_len;   /* length of input block */\n  //int last;         /* one if this is the last block for a file */\n  send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3);    /* send block type */\n  copy_block(s, buf, stored_len, true); /* with header */\n}\n\n\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\nfunction _tr_align(s) {\n  send_bits(s, STATIC_TREES << 1, 3);\n  send_code(s, END_BLOCK, static_ltree);\n  bi_flush(s);\n}\n\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and output the encoded block to the zip file.\n */\nfunction _tr_flush_block(s, buf, stored_len, last) {\n  //DeflateState *s;\n  //charf *buf;       /* input block, or NULL if too old */\n  //ulg stored_len;   /* length of input block */\n  //int last;         /* one if this is the last block for a file */\n  var opt_lenb, static_lenb;  /* opt_len and static_len in bytes */\n  var max_blindex = 0;        /* index of last bit length code of non zero freq */\n\n  /* Build the Huffman trees unless a stored block is forced */\n  if (s.level > 0) {\n\n    /* Check if the file is binary or text */\n    if (s.strm.data_type === Z_UNKNOWN) {\n      s.strm.data_type = detect_data_type(s);\n    }\n\n    /* Construct the literal and distance trees */\n    build_tree(s, s.l_desc);\n    // Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n    //        s->static_len));\n\n    build_tree(s, s.d_desc);\n    // Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n    //        s->static_len));\n    /* At this point, opt_len and static_len are the total bit lengths of\n     * the compressed block data, excluding the tree representations.\n     */\n\n    /* Build the bit length tree for the above two trees, and get the index\n     * in bl_order of the last bit length code to send.\n     */\n    max_blindex = build_bl_tree(s);\n\n    /* Determine the best encoding. Compute the block lengths in bytes. */\n    opt_lenb = (s.opt_len + 3 + 7) >>> 3;\n    static_lenb = (s.static_len + 3 + 7) >>> 3;\n\n    // Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n    //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n    //        s->last_lit));\n\n    if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }\n\n  } else {\n    // Assert(buf != (char*)0, \"lost buf\");\n    opt_lenb = static_lenb = stored_len + 5; /* force a stored block */\n  }\n\n  if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {\n    /* 4: two words for the lengths */\n\n    /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n     * Otherwise we can't have processed more than WSIZE input bytes since\n     * the last block flush, because compression would have been\n     * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n     * transform a block into a stored block.\n     */\n    _tr_stored_block(s, buf, stored_len, last);\n\n  } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {\n\n    send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);\n    compress_block(s, static_ltree, static_dtree);\n\n  } else {\n    send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);\n    send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);\n    compress_block(s, s.dyn_ltree, s.dyn_dtree);\n  }\n  // Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n  /* The above check is made mod 2^32, for files larger than 512 MB\n   * and uLong implemented on 32 bits.\n   */\n  init_block(s);\n\n  if (last) {\n    bi_windup(s);\n  }\n  // Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len>>3,\n  //       s->compressed_len-7*last));\n}\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nfunction _tr_tally(s, dist, lc) {\n  //    deflate_state *s;\n  //    unsigned dist;  /* distance of matched string */\n  //    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */\n  //var out_length, in_length, dcode;\n\n  s.pending_buf[s.d_buf + s.last_lit * 2]     = (dist >>> 8) & 0xff;\n  s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;\n\n  s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;\n  s.last_lit++;\n\n  if (dist === 0) {\n    /* lc is the unmatched char */\n    s.dyn_ltree[lc * 2]/*.Freq*/++;\n  } else {\n    s.matches++;\n    /* Here, lc is the match length - MIN_MATCH */\n    dist--;             /* dist = match distance - 1 */\n    //Assert((ush)dist < (ush)MAX_DIST(s) &&\n    //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n    //       (ush)d_code(dist) < (ush)D_CODES,  \"_tr_tally: bad match\");\n\n    s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++;\n    s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;\n  }\n\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n\n//#ifdef TRUNCATE_BLOCK\n//  /* Try to guess if it is profitable to stop the current block here */\n//  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {\n//    /* Compute an upper bound for the compressed length */\n//    out_length = s.last_lit*8;\n//    in_length = s.strstart - s.block_start;\n//\n//    for (dcode = 0; dcode < D_CODES; dcode++) {\n//      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);\n//    }\n//    out_length >>>= 3;\n//    //Tracev((stderr,\"\\nlast_lit %u, in %ld, out ~%ld(%ld%%) \",\n//    //       s->last_lit, in_length, out_length,\n//    //       100L - out_length*100L/in_length));\n//    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {\n//      return true;\n//    }\n//  }\n//#endif\n\n  return (s.last_lit === s.lit_bufsize - 1);\n  /* We avoid equality with lit_bufsize because of wraparound at 64K\n   * on 16 bit machines and because stored blocks are restricted to\n   * 64K-1 bytes.\n   */\n}\n\n/* eslint-disable */\n\nvar MAX_MEM_LEVEL = 9;\n\n\nvar LENGTH_CODES$1  = 29;\n/* number of length codes, not counting the special END_BLOCK code */\nvar LITERALS$1      = 256;\n/* number of literal bytes 0..255 */\nvar L_CODES$1       = LITERALS$1 + 1 + LENGTH_CODES$1;\n/* number of Literal or Length codes, including the END_BLOCK code */\nvar D_CODES$1       = 30;\n/* number of distance codes */\nvar BL_CODES$1      = 19;\n/* number of codes used to transfer the bit lengths */\nvar HEAP_SIZE$1     = 2 * L_CODES$1 + 1;\n/* maximum heap size */\nvar MAX_BITS$1  = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nvar MIN_MATCH$1 = 3;\nvar MAX_MATCH$1 = 258;\nvar MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1);\n\nvar PRESET_DICT = 0x20;\n\nvar INIT_STATE = 42;\nvar EXTRA_STATE = 69;\nvar NAME_STATE = 73;\nvar COMMENT_STATE = 91;\nvar HCRC_STATE = 103;\nvar BUSY_STATE = 113;\nvar FINISH_STATE = 666;\n\nvar BS_NEED_MORE      = 1; /* block not completed, need more input or more output */\nvar BS_BLOCK_DONE     = 2; /* block flush performed */\nvar BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */\nvar BS_FINISH_DONE    = 4; /* finish done, accept no more input or output */\n\nvar OS_CODE = 0x03; // Unix :) . Don't detect, use this default.\n\nfunction err(strm, errorCode) {\n  strm.msg = msg[errorCode];\n  return errorCode;\n}\n\nfunction rank(f) {\n  return ((f) << 1) - ((f) > 4 ? 9 : 0);\n}\n\nfunction zero$1(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }\n\n\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output goes\n * through this function so some applications may wish to modify it\n * to avoid allocating a large strm->output buffer and copying into it.\n * (See also read_buf()).\n */\nfunction flush_pending(strm) {\n  var s = strm.state;\n\n  //_tr_flush_bits(s);\n  var len = s.pending;\n  if (len > strm.avail_out) {\n    len = strm.avail_out;\n  }\n  if (len === 0) { return; }\n\n  arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);\n  strm.next_out += len;\n  s.pending_out += len;\n  strm.total_out += len;\n  strm.avail_out -= len;\n  s.pending -= len;\n  if (s.pending === 0) {\n    s.pending_out = 0;\n  }\n}\n\n\nfunction flush_block_only(s, last) {\n  _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);\n  s.block_start = s.strstart;\n  flush_pending(s.strm);\n}\n\n\nfunction put_byte(s, b) {\n  s.pending_buf[s.pending++] = b;\n}\n\n\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\nfunction putShortMSB(s, b) {\n//  put_byte(s, (Byte)(b >> 8));\n//  put_byte(s, (Byte)(b & 0xff));\n  s.pending_buf[s.pending++] = (b >>> 8) & 0xff;\n  s.pending_buf[s.pending++] = b & 0xff;\n}\n\n\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read.  All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->input buffer and copying from it.\n * (See also flush_pending()).\n */\nfunction read_buf(strm, buf, start, size) {\n  var len = strm.avail_in;\n\n  if (len > size) { len = size; }\n  if (len === 0) { return 0; }\n\n  strm.avail_in -= len;\n\n  // zmemcpy(buf, strm->next_in, len);\n  arraySet(buf, strm.input, strm.next_in, len, start);\n  if (strm.state.wrap === 1) {\n    strm.adler = adler32(strm.adler, buf, len, start);\n  }\n\n  else if (strm.state.wrap === 2) {\n    strm.adler = crc32(strm.adler, buf, len, start);\n  }\n\n  strm.next_in += len;\n  strm.total_in += len;\n\n  return len;\n}\n\n\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\nfunction longest_match(s, cur_match) {\n  var chain_length = s.max_chain_length;      /* max hash chain length */\n  var scan = s.strstart; /* current string */\n  var match;                       /* matched string */\n  var len;                           /* length of current match */\n  var best_len = s.prev_length;              /* best match length so far */\n  var nice_match = s.nice_match;             /* stop if match long enough */\n  var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?\n      s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;\n\n  var _win = s.window; // shortcut\n\n  var wmask = s.w_mask;\n  var prev  = s.prev;\n\n  /* Stop when cur_match becomes <= limit. To simplify the code,\n   * we prevent matches with the string of window index 0.\n   */\n\n  var strend = s.strstart + MAX_MATCH$1;\n  var scan_end1  = _win[scan + best_len - 1];\n  var scan_end   = _win[scan + best_len];\n\n  /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n   * It is easy to get rid of this optimization if necessary.\n   */\n  // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n  /* Do not waste too much time if we already have a good match: */\n  if (s.prev_length >= s.good_match) {\n    chain_length >>= 2;\n  }\n  /* Do not look for matches beyond the end of the input. This is necessary\n   * to make deflate deterministic.\n   */\n  if (nice_match > s.lookahead) { nice_match = s.lookahead; }\n\n  // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n  do {\n    // Assert(cur_match < s->strstart, \"no future\");\n    match = cur_match;\n\n    /* Skip to next match if the match length cannot increase\n     * or if the match length is less than 2.  Note that the checks below\n     * for insufficient lookahead only occur occasionally for performance\n     * reasons.  Therefore uninitialized memory will be accessed, and\n     * conditional jumps will be made that depend on those values.\n     * However the length of the match is limited to the lookahead, so\n     * the output of deflate is not affected by the uninitialized values.\n     */\n\n    if (_win[match + best_len]     !== scan_end  ||\n        _win[match + best_len - 1] !== scan_end1 ||\n        _win[match]                !== _win[scan] ||\n        _win[++match]              !== _win[scan + 1]) {\n      continue;\n    }\n\n    /* The check at best_len-1 can be removed because it will be made\n     * again later. (This heuristic is not always a win.)\n     * It is not necessary to compare scan[2] and match[2] since they\n     * are always equal when the other bytes match, given that\n     * the hash keys are equal and that HASH_BITS >= 8.\n     */\n    scan += 2;\n    match++;\n    // Assert(*scan == *match, \"match[2]?\");\n\n    /* We check for insufficient lookahead only every 8th comparison;\n     * the 256th check will be made at strstart+258.\n     */\n    do {\n      /*jshint noempty:false*/\n    } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n             scan < strend);\n\n    // Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n    len = MAX_MATCH$1 - (strend - scan);\n    scan = strend - MAX_MATCH$1;\n\n    if (len > best_len) {\n      s.match_start = cur_match;\n      best_len = len;\n      if (len >= nice_match) {\n        break;\n      }\n      scan_end1  = _win[scan + best_len - 1];\n      scan_end   = _win[scan + best_len];\n    }\n  } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);\n\n  if (best_len <= s.lookahead) {\n    return best_len;\n  }\n  return s.lookahead;\n}\n\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n *    At least one byte has been read, or avail_in == 0; reads are\n *    performed for at least two bytes (required for the zip translate_eol\n *    option -- not supported here).\n */\nfunction fill_window(s) {\n  var _w_size = s.w_size;\n  var p, n, m, more, str;\n\n  //Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n  do {\n    more = s.window_size - s.lookahead - s.strstart;\n\n    // JS ints have 32 bit, block below not needed\n    /* Deal with !@#$% 64K limit: */\n    //if (sizeof(int) <= 2) {\n    //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n    //        more = wsize;\n    //\n    //  } else if (more == (unsigned)(-1)) {\n    //        /* Very unlikely, but possible on 16 bit machine if\n    //         * strstart == 0 && lookahead == 1 (input done a byte at time)\n    //         */\n    //        more--;\n    //    }\n    //}\n\n\n    /* If the window is almost full and there is insufficient lookahead,\n     * move the upper half to the lower one to make room in the upper half.\n     */\n    if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {\n\n      arraySet(s.window, s.window, _w_size, _w_size, 0);\n      s.match_start -= _w_size;\n      s.strstart -= _w_size;\n      /* we now have strstart >= MAX_DIST */\n      s.block_start -= _w_size;\n\n      /* Slide the hash table (could be avoided with 32 bit values\n       at the expense of memory usage). We slide even when level == 0\n       to keep the hash table consistent if we switch back to level > 0\n       later. (Using level 0 permanently is not an optimal usage of\n       zlib, so we don't care about this pathological case.)\n       */\n\n      n = s.hash_size;\n      p = n;\n      do {\n        m = s.head[--p];\n        s.head[p] = (m >= _w_size ? m - _w_size : 0);\n      } while (--n);\n\n      n = _w_size;\n      p = n;\n      do {\n        m = s.prev[--p];\n        s.prev[p] = (m >= _w_size ? m - _w_size : 0);\n        /* If n is not on any hash chain, prev[n] is garbage but\n         * its value will never be used.\n         */\n      } while (--n);\n\n      more += _w_size;\n    }\n    if (s.strm.avail_in === 0) {\n      break;\n    }\n\n    /* If there was no sliding:\n     *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n     *    more == window_size - lookahead - strstart\n     * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n     * => more >= window_size - 2*WSIZE + 2\n     * In the BIG_MEM or MMAP case (not yet supported),\n     *   window_size == input_size + MIN_LOOKAHEAD  &&\n     *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n     * Otherwise, window_size == 2*WSIZE so more >= 2.\n     * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n     */\n    //Assert(more >= 2, \"more < 2\");\n    n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);\n    s.lookahead += n;\n\n    /* Initialize the hash value now that we have some input: */\n    if (s.lookahead + s.insert >= MIN_MATCH$1) {\n      str = s.strstart - s.insert;\n      s.ins_h = s.window[str];\n\n      /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */\n      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;\n//#if MIN_MATCH != 3\n//        Call update_hash() MIN_MATCH-3 more times\n//#endif\n      while (s.insert) {\n        /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask;\n\n        s.prev[str & s.w_mask] = s.head[s.ins_h];\n        s.head[s.ins_h] = str;\n        str++;\n        s.insert--;\n        if (s.lookahead + s.insert < MIN_MATCH$1) {\n          break;\n        }\n      }\n    }\n    /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n     * but this is not important since only literal bytes will be emitted.\n     */\n\n  } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);\n\n  /* If the WIN_INIT bytes after the end of the current data have never been\n   * written, then zero those bytes in order to avoid memory check reports of\n   * the use of uninitialized (or uninitialised as Julian writes) bytes by\n   * the longest match routines.  Update the high water mark for the next\n   * time through here.  WIN_INIT is set to MAX_MATCH since the longest match\n   * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n   */\n//  if (s.high_water < s.window_size) {\n//    var curr = s.strstart + s.lookahead;\n//    var init = 0;\n//\n//    if (s.high_water < curr) {\n//      /* Previous high water mark below current data -- zero WIN_INIT\n//       * bytes or up to end of window, whichever is less.\n//       */\n//      init = s.window_size - curr;\n//      if (init > WIN_INIT)\n//        init = WIN_INIT;\n//      zmemzero(s->window + curr, (unsigned)init);\n//      s->high_water = curr + init;\n//    }\n//    else if (s->high_water < (ulg)curr + WIN_INIT) {\n//      /* High water mark at or above current data, but below current data\n//       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n//       * to end of window, whichever is less.\n//       */\n//      init = (ulg)curr + WIN_INIT - s->high_water;\n//      if (init > s->window_size - s->high_water)\n//        init = s->window_size - s->high_water;\n//      zmemzero(s->window + s->high_water, (unsigned)init);\n//      s->high_water += init;\n//    }\n//  }\n//\n//  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n//    \"not enough room for search\");\n}\n\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n * This function does not insert new strings in the dictionary since\n * uncompressible data is probably not useful. This function is used\n * only for the level=0 compression option.\n * NOTE: this function should be optimized to avoid extra copying from\n * window to pending_buf.\n */\nfunction deflate_stored(s, flush) {\n  /* Stored blocks are limited to 0xffff bytes, pending_buf is limited\n   * to pending_buf_size, and each stored block has a 5 byte header:\n   */\n  var max_block_size = 0xffff;\n\n  if (max_block_size > s.pending_buf_size - 5) {\n    max_block_size = s.pending_buf_size - 5;\n  }\n\n  /* Copy as much as possible from input to output: */\n  for (;;) {\n    /* Fill the window as much as possible: */\n    if (s.lookahead <= 1) {\n\n      //Assert(s->strstart < s->w_size+MAX_DIST(s) ||\n      //  s->block_start >= (long)s->w_size, \"slide too late\");\n//      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||\n//        s.block_start >= s.w_size)) {\n//        throw  new Error(\"slide too late\");\n//      }\n\n      fill_window(s);\n      if (s.lookahead === 0 && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE;\n      }\n\n      if (s.lookahead === 0) {\n        break;\n      }\n      /* flush the current block */\n    }\n    //Assert(s->block_start >= 0L, \"block gone\");\n//    if (s.block_start < 0) throw new Error(\"block gone\");\n\n    s.strstart += s.lookahead;\n    s.lookahead = 0;\n\n    /* Emit a stored block if pending_buf will be full: */\n    var max_start = s.block_start + max_block_size;\n\n    if (s.strstart === 0 || s.strstart >= max_start) {\n      /* strstart == 0 is possible when wraparound on 16-bit machine */\n      s.lookahead = s.strstart - max_start;\n      s.strstart = max_start;\n      /*** FLUSH_BLOCK(s, 0); ***/\n      flush_block_only(s, false);\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n      /***/\n\n\n    }\n    /* Flush if we may have to slide, otherwise block_start may become\n     * negative and the data will be gone:\n     */\n    if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {\n      /*** FLUSH_BLOCK(s, 0); ***/\n      flush_block_only(s, false);\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n      /***/\n    }\n  }\n\n  s.insert = 0;\n\n  if (flush === Z_FINISH) {\n    /*** FLUSH_BLOCK(s, 1); ***/\n    flush_block_only(s, true);\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED;\n    }\n    /***/\n    return BS_FINISH_DONE;\n  }\n\n  if (s.strstart > s.block_start) {\n    /*** FLUSH_BLOCK(s, 0); ***/\n    flush_block_only(s, false);\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE;\n    }\n    /***/\n  }\n\n  return BS_NEED_MORE;\n}\n\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nfunction deflate_fast(s, flush) {\n  var hash_head;        /* head of the hash chain */\n  var bflush;           /* set if current block must be flushed */\n\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the next match, plus MIN_MATCH bytes to insert the\n     * string following the next match.\n     */\n    if (s.lookahead < MIN_LOOKAHEAD) {\n      fill_window(s);\n      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE;\n      }\n      if (s.lookahead === 0) {\n        break; /* flush the current block */\n      }\n    }\n\n    /* Insert the string window[strstart .. strstart+2] in the\n     * dictionary, and set hash_head to the head of the hash chain:\n     */\n    hash_head = 0/*NIL*/;\n    if (s.lookahead >= MIN_MATCH$1) {\n      /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;\n      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n      s.head[s.ins_h] = s.strstart;\n      /***/\n    }\n\n    /* Find the longest match, discarding those <= prev_length.\n     * At this point we have always match_length < MIN_MATCH\n     */\n    if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {\n      /* To simplify the code, we prevent matches with the string\n       * of window index 0 (in particular we have to avoid a match\n       * of the string with itself at the start of the input file).\n       */\n      s.match_length = longest_match(s, hash_head);\n      /* longest_match() sets match_start */\n    }\n    if (s.match_length >= MIN_MATCH$1) {\n      // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only\n\n      /*** _tr_tally_dist(s, s.strstart - s.match_start,\n                     s.match_length - MIN_MATCH, bflush); ***/\n      bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1);\n\n      s.lookahead -= s.match_length;\n\n      /* Insert new strings in the hash table only if the match length\n       * is not too large. This saves time but degrades compression.\n       */\n      if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) {\n        s.match_length--; /* string at strstart already in table */\n        do {\n          s.strstart++;\n          /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;\n          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n          s.head[s.ins_h] = s.strstart;\n          /***/\n          /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n           * always MIN_MATCH bytes ahead.\n           */\n        } while (--s.match_length !== 0);\n        s.strstart++;\n      } else\n      {\n        s.strstart += s.match_length;\n        s.match_length = 0;\n        s.ins_h = s.window[s.strstart];\n        /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */\n        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;\n\n//#if MIN_MATCH != 3\n//                Call UPDATE_HASH() MIN_MATCH-3 more times\n//#endif\n        /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n         * matter since it will be recomputed at next deflate call.\n         */\n      }\n    } else {\n      /* No match, output a literal byte */\n      //Tracevv((stderr,\"%c\", s.window[s.strstart]));\n      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n      bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n      s.lookahead--;\n      s.strstart++;\n    }\n    if (bflush) {\n      /*** FLUSH_BLOCK(s, 0); ***/\n      flush_block_only(s, false);\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n      /***/\n    }\n  }\n  s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1);\n  if (flush === Z_FINISH) {\n    /*** FLUSH_BLOCK(s, 1); ***/\n    flush_block_only(s, true);\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED;\n    }\n    /***/\n    return BS_FINISH_DONE;\n  }\n  if (s.last_lit) {\n    /*** FLUSH_BLOCK(s, 0); ***/\n    flush_block_only(s, false);\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE;\n    }\n    /***/\n  }\n  return BS_BLOCK_DONE;\n}\n\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nfunction deflate_slow(s, flush) {\n  var hash_head;          /* head of hash chain */\n  var bflush;              /* set if current block must be flushed */\n\n  var max_insert;\n\n  /* Process the input block. */\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the next match, plus MIN_MATCH bytes to insert the\n     * string following the next match.\n     */\n    if (s.lookahead < MIN_LOOKAHEAD) {\n      fill_window(s);\n      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE;\n      }\n      if (s.lookahead === 0) { break; } /* flush the current block */\n    }\n\n    /* Insert the string window[strstart .. strstart+2] in the\n     * dictionary, and set hash_head to the head of the hash chain:\n     */\n    hash_head = 0/*NIL*/;\n    if (s.lookahead >= MIN_MATCH$1) {\n      /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;\n      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n      s.head[s.ins_h] = s.strstart;\n      /***/\n    }\n\n    /* Find the longest match, discarding those <= prev_length.\n     */\n    s.prev_length = s.match_length;\n    s.prev_match = s.match_start;\n    s.match_length = MIN_MATCH$1 - 1;\n\n    if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&\n        s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {\n      /* To simplify the code, we prevent matches with the string\n       * of window index 0 (in particular we have to avoid a match\n       * of the string with itself at the start of the input file).\n       */\n      s.match_length = longest_match(s, hash_head);\n      /* longest_match() sets match_start */\n\n      if (s.match_length <= 5 &&\n         (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {\n\n        /* If prev_match is also MIN_MATCH, match_start is garbage\n         * but we will ignore the current match anyway.\n         */\n        s.match_length = MIN_MATCH$1 - 1;\n      }\n    }\n    /* If there was a match at the previous step and the current\n     * match is not better, output the previous match:\n     */\n    if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) {\n      max_insert = s.strstart + s.lookahead - MIN_MATCH$1;\n      /* Do not insert strings in hash table beyond this. */\n\n      //check_match(s, s.strstart-1, s.prev_match, s.prev_length);\n\n      /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,\n                     s.prev_length - MIN_MATCH, bflush);***/\n      bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1);\n      /* Insert in hash table all strings up to the end of the match.\n       * strstart-1 and strstart are already inserted. If there is not\n       * enough lookahead, the last two strings are not inserted in\n       * the hash table.\n       */\n      s.lookahead -= s.prev_length - 1;\n      s.prev_length -= 2;\n      do {\n        if (++s.strstart <= max_insert) {\n          /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask;\n          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n          s.head[s.ins_h] = s.strstart;\n          /***/\n        }\n      } while (--s.prev_length !== 0);\n      s.match_available = 0;\n      s.match_length = MIN_MATCH$1 - 1;\n      s.strstart++;\n\n      if (bflush) {\n        /*** FLUSH_BLOCK(s, 0); ***/\n        flush_block_only(s, false);\n        if (s.strm.avail_out === 0) {\n          return BS_NEED_MORE;\n        }\n        /***/\n      }\n\n    } else if (s.match_available) {\n      /* If there was no match at the previous position, output a\n       * single literal. If there was a match but the current match\n       * is longer, truncate the previous match to a single literal.\n       */\n      //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n      /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n      bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n      if (bflush) {\n        /*** FLUSH_BLOCK_ONLY(s, 0) ***/\n        flush_block_only(s, false);\n        /***/\n      }\n      s.strstart++;\n      s.lookahead--;\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n    } else {\n      /* There is no previous match to compare with, wait for\n       * the next step to decide.\n       */\n      s.match_available = 1;\n      s.strstart++;\n      s.lookahead--;\n    }\n  }\n  //Assert (flush != Z_NO_FLUSH, \"no flush?\");\n  if (s.match_available) {\n    //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n    /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n    bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n    s.match_available = 0;\n  }\n  s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1;\n  if (flush === Z_FINISH) {\n    /*** FLUSH_BLOCK(s, 1); ***/\n    flush_block_only(s, true);\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED;\n    }\n    /***/\n    return BS_FINISH_DONE;\n  }\n  if (s.last_lit) {\n    /*** FLUSH_BLOCK(s, 0); ***/\n    flush_block_only(s, false);\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE;\n    }\n    /***/\n  }\n\n  return BS_BLOCK_DONE;\n}\n\n\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one.  Do not maintain a hash table.  (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\nfunction deflate_rle(s, flush) {\n  var bflush;            /* set if current block must be flushed */\n  var prev;              /* byte at distance one to match */\n  var scan, strend;      /* scan goes up to strend for length of run */\n\n  var _win = s.window;\n\n  for (;;) {\n    /* Make sure that we always have enough lookahead, except\n     * at the end of the input file. We need MAX_MATCH bytes\n     * for the longest run, plus one for the unrolled loop.\n     */\n    if (s.lookahead <= MAX_MATCH$1) {\n      fill_window(s);\n      if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) {\n        return BS_NEED_MORE;\n      }\n      if (s.lookahead === 0) { break; } /* flush the current block */\n    }\n\n    /* See how many times the previous byte repeats */\n    s.match_length = 0;\n    if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) {\n      scan = s.strstart - 1;\n      prev = _win[scan];\n      if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {\n        strend = s.strstart + MAX_MATCH$1;\n        do {\n          /*jshint noempty:false*/\n        } while (prev === _win[++scan] && prev === _win[++scan] &&\n                 prev === _win[++scan] && prev === _win[++scan] &&\n                 prev === _win[++scan] && prev === _win[++scan] &&\n                 prev === _win[++scan] && prev === _win[++scan] &&\n                 scan < strend);\n        s.match_length = MAX_MATCH$1 - (strend - scan);\n        if (s.match_length > s.lookahead) {\n          s.match_length = s.lookahead;\n        }\n      }\n      //Assert(scan <= s->window+(uInt)(s->window_size-1), \"wild scan\");\n    }\n\n    /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n    if (s.match_length >= MIN_MATCH$1) {\n      //check_match(s, s.strstart, s.strstart - 1, s.match_length);\n\n      /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/\n      bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1);\n\n      s.lookahead -= s.match_length;\n      s.strstart += s.match_length;\n      s.match_length = 0;\n    } else {\n      /* No match, output a literal byte */\n      //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n      bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n      s.lookahead--;\n      s.strstart++;\n    }\n    if (bflush) {\n      /*** FLUSH_BLOCK(s, 0); ***/\n      flush_block_only(s, false);\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n      /***/\n    }\n  }\n  s.insert = 0;\n  if (flush === Z_FINISH) {\n    /*** FLUSH_BLOCK(s, 1); ***/\n    flush_block_only(s, true);\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED;\n    }\n    /***/\n    return BS_FINISH_DONE;\n  }\n  if (s.last_lit) {\n    /*** FLUSH_BLOCK(s, 0); ***/\n    flush_block_only(s, false);\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE;\n    }\n    /***/\n  }\n  return BS_BLOCK_DONE;\n}\n\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\nfunction deflate_huff(s, flush) {\n  var bflush;             /* set if current block must be flushed */\n\n  for (;;) {\n    /* Make sure that we have a literal to write. */\n    if (s.lookahead === 0) {\n      fill_window(s);\n      if (s.lookahead === 0) {\n        if (flush === Z_NO_FLUSH) {\n          return BS_NEED_MORE;\n        }\n        break;      /* flush the current block */\n      }\n    }\n\n    /* Output a literal byte */\n    s.match_length = 0;\n    //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n    /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n    bflush = _tr_tally(s, 0, s.window[s.strstart]);\n    s.lookahead--;\n    s.strstart++;\n    if (bflush) {\n      /*** FLUSH_BLOCK(s, 0); ***/\n      flush_block_only(s, false);\n      if (s.strm.avail_out === 0) {\n        return BS_NEED_MORE;\n      }\n      /***/\n    }\n  }\n  s.insert = 0;\n  if (flush === Z_FINISH) {\n    /*** FLUSH_BLOCK(s, 1); ***/\n    flush_block_only(s, true);\n    if (s.strm.avail_out === 0) {\n      return BS_FINISH_STARTED;\n    }\n    /***/\n    return BS_FINISH_DONE;\n  }\n  if (s.last_lit) {\n    /*** FLUSH_BLOCK(s, 0); ***/\n    flush_block_only(s, false);\n    if (s.strm.avail_out === 0) {\n      return BS_NEED_MORE;\n    }\n    /***/\n  }\n  return BS_BLOCK_DONE;\n}\n\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\nfunction Config(good_length, max_lazy, nice_length, max_chain, func) {\n  this.good_length = good_length;\n  this.max_lazy = max_lazy;\n  this.nice_length = nice_length;\n  this.max_chain = max_chain;\n  this.func = func;\n}\n\nvar configurationTable = function() {\n  var table = [\n    /*      good lazy nice chain */\n    new Config(0, 0, 0, 0, deflate_stored),          /* 0 store only */\n    new Config(4, 4, 8, 4, deflate_fast),            /* 1 max speed, no lazy matches */\n    new Config(4, 5, 16, 8, deflate_fast),           /* 2 */\n    new Config(4, 6, 32, 32, deflate_fast),          /* 3 */\n  \n    new Config(4, 4, 16, 16, deflate_slow),          /* 4 lazy matches */\n    new Config(8, 16, 32, 32, deflate_slow),         /* 5 */\n    new Config(8, 16, 128, 128, deflate_slow),       /* 6 */\n    new Config(8, 32, 128, 256, deflate_slow),       /* 7 */\n    new Config(32, 128, 258, 1024, deflate_slow),    /* 8 */\n    new Config(32, 258, 258, 4096, deflate_slow)     /* 9 max compression */\n  ];\n\n  configurationTable = function () { return table; };\n  return table;\n};\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\nfunction lm_init(s) {\n  s.window_size = 2 * s.w_size;\n\n  /*** CLEAR_HASH(s); ***/\n  zero$1(s.head); // Fill with NIL (= 0);\n\n  var table = configurationTable();\n  /* Set the default configuration parameters:\n   */\n  s.max_lazy_match = table[s.level].max_lazy;\n  s.good_match = table[s.level].good_length;\n  s.nice_match = table[s.level].nice_length;\n  s.max_chain_length = table[s.level].max_chain;\n\n  s.strstart = 0;\n  s.block_start = 0;\n  s.lookahead = 0;\n  s.insert = 0;\n  s.match_length = s.prev_length = MIN_MATCH$1 - 1;\n  s.match_available = 0;\n  s.ins_h = 0;\n}\n\n\nfunction DeflateState() {\n  this.strm = null;            /* pointer back to this zlib stream */\n  this.status = 0;            /* as the name implies */\n  this.pending_buf = null;      /* output still pending */\n  this.pending_buf_size = 0;  /* size of pending_buf */\n  this.pending_out = 0;       /* next pending byte to output to the stream */\n  this.pending = 0;           /* nb of bytes in the pending buffer */\n  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */\n  this.gzhead = null;         /* gzip header information to write */\n  this.gzindex = 0;           /* where in extra, name, or comment */\n  this.method = Z_DEFLATED; /* can only be DEFLATED */\n  this.last_flush = -1;   /* value of flush param for previous deflate call */\n\n  this.w_size = 0;  /* LZ77 window size (32K by default) */\n  this.w_bits = 0;  /* log2(w_size)  (8..16) */\n  this.w_mask = 0;  /* w_size - 1 */\n\n  this.window = null;\n  /* Sliding window. Input bytes are read into the second half of the window,\n   * and move to the first half later to keep a dictionary of at least wSize\n   * bytes. With this organization, matches are limited to a distance of\n   * wSize-MAX_MATCH bytes, but this ensures that IO is always\n   * performed with a length multiple of the block size.\n   */\n\n  this.window_size = 0;\n  /* Actual size of window: 2*wSize, except when the user input buffer\n   * is directly used as sliding window.\n   */\n\n  this.prev = null;\n  /* Link to older string with same hash index. To limit the size of this\n   * array to 64K, this link is maintained only for the last 32K strings.\n   * An index in this array is thus a window index modulo 32K.\n   */\n\n  this.head = null;   /* Heads of the hash chains or NIL. */\n\n  this.ins_h = 0;       /* hash index of string to be inserted */\n  this.hash_size = 0;   /* number of elements in hash table */\n  this.hash_bits = 0;   /* log2(hash_size) */\n  this.hash_mask = 0;   /* hash_size-1 */\n\n  this.hash_shift = 0;\n  /* Number of bits by which ins_h must be shifted at each input\n   * step. It must be such that after MIN_MATCH steps, the oldest\n   * byte no longer takes part in the hash key, that is:\n   *   hash_shift * MIN_MATCH >= hash_bits\n   */\n\n  this.block_start = 0;\n  /* Window position at the beginning of the current output block. Gets\n   * negative when the window is moved backwards.\n   */\n\n  this.match_length = 0;      /* length of best match */\n  this.prev_match = 0;        /* previous match */\n  this.match_available = 0;   /* set if previous match exists */\n  this.strstart = 0;          /* start of string to insert */\n  this.match_start = 0;       /* start of matching string */\n  this.lookahead = 0;         /* number of valid bytes ahead in window */\n\n  this.prev_length = 0;\n  /* Length of the best match at previous step. Matches not greater than this\n   * are discarded. This is used in the lazy match evaluation.\n   */\n\n  this.max_chain_length = 0;\n  /* To speed up deflation, hash chains are never searched beyond this\n   * length.  A higher limit improves compression ratio but degrades the\n   * speed.\n   */\n\n  this.max_lazy_match = 0;\n  /* Attempt to find a better match only when the current match is strictly\n   * smaller than this value. This mechanism is used only for compression\n   * levels >= 4.\n   */\n  // That's alias to max_lazy_match, don't use directly\n  //this.max_insert_length = 0;\n  /* Insert new strings in the hash table only if the match length is not\n   * greater than this length. This saves time but degrades compression.\n   * max_insert_length is used only for compression levels <= 3.\n   */\n\n  this.level = 0;     /* compression level (1..9) */\n  this.strategy = 0;  /* favor or force Huffman coding*/\n\n  this.good_match = 0;\n  /* Use a faster search when the previous match is longer than this */\n\n  this.nice_match = 0; /* Stop searching when current match exceeds this */\n\n              /* used by trees.c: */\n\n  /* Didn't use ct_data typedef below to suppress compiler warning */\n\n  // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */\n  // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n  // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */\n\n  // Use flat array of DOUBLE size, with interleaved fata,\n  // because JS does not support effective\n  this.dyn_ltree  = Buf16(HEAP_SIZE$1 * 2);\n  this.dyn_dtree  = Buf16((2 * D_CODES$1 + 1) * 2);\n  this.bl_tree    = Buf16((2 * BL_CODES$1 + 1) * 2);\n  zero$1(this.dyn_ltree);\n  zero$1(this.dyn_dtree);\n  zero$1(this.bl_tree);\n\n  this.l_desc   = null;         /* desc. for literal tree */\n  this.d_desc   = null;         /* desc. for distance tree */\n  this.bl_desc  = null;         /* desc. for bit length tree */\n\n  //ush bl_count[MAX_BITS+1];\n  this.bl_count = Buf16(MAX_BITS$1 + 1);\n  /* number of codes at each bit length for an optimal tree */\n\n  //int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */\n  this.heap = Buf16(2 * L_CODES$1 + 1);  /* heap used to build the Huffman trees */\n  zero$1(this.heap);\n\n  this.heap_len = 0;               /* number of elements in the heap */\n  this.heap_max = 0;               /* element of largest frequency */\n  /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n   * The same heap array is used to build all trees.\n   */\n\n  this.depth = Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1];\n  zero$1(this.depth);\n  /* Depth of each subtree used as tie breaker for trees of equal frequency\n   */\n\n  this.l_buf = 0;          /* buffer index for literals or lengths */\n\n  this.lit_bufsize = 0;\n  /* Size of match buffer for literals/lengths.  There are 4 reasons for\n   * limiting lit_bufsize to 64K:\n   *   - frequencies can be kept in 16 bit counters\n   *   - if compression is not successful for the first block, all input\n   *     data is still in the window so we can still emit a stored block even\n   *     when input comes from standard input.  (This can also be done for\n   *     all blocks if lit_bufsize is not greater than 32K.)\n   *   - if compression is not successful for a file smaller than 64K, we can\n   *     even emit a stored file instead of a stored block (saving 5 bytes).\n   *     This is applicable only for zip (not gzip or zlib).\n   *   - creating new Huffman trees less frequently may not provide fast\n   *     adaptation to changes in the input data statistics. (Take for\n   *     example a binary file with poorly compressible code followed by\n   *     a highly compressible string table.) Smaller buffer sizes give\n   *     fast adaptation but have of course the overhead of transmitting\n   *     trees more frequently.\n   *   - I can't count above 4\n   */\n\n  this.last_lit = 0;      /* running index in l_buf */\n\n  this.d_buf = 0;\n  /* Buffer index for distances. To simplify the code, d_buf and l_buf have\n   * the same number of elements. To use different lengths, an extra flag\n   * array would be necessary.\n   */\n\n  this.opt_len = 0;       /* bit length of current block with optimal trees */\n  this.static_len = 0;    /* bit length of current block with static trees */\n  this.matches = 0;       /* number of string matches in current block */\n  this.insert = 0;        /* bytes at end of window left to insert */\n\n\n  this.bi_buf = 0;\n  /* Output buffer. bits are inserted starting at the bottom (least\n   * significant bits).\n   */\n  this.bi_valid = 0;\n  /* Number of valid bits in bi_buf.  All bits above the last valid bit\n   * are always zero.\n   */\n\n  // Used for window memory init. We safely ignore it for JS. That makes\n  // sense only for pointers and memory check tools.\n  //this.high_water = 0;\n  /* High water mark offset in window for initialized bytes -- bytes above\n   * this are set to zero in order to avoid memory check warnings when\n   * longest match routines access bytes past the input.  This is then\n   * updated to the new high water mark.\n   */\n}\n\n\nfunction deflateResetKeep(strm) {\n  var s;\n\n  if (!strm || !strm.state) {\n    return err(strm, Z_STREAM_ERROR);\n  }\n\n  strm.total_in = strm.total_out = 0;\n  strm.data_type = Z_UNKNOWN;\n\n  s = strm.state;\n  s.pending = 0;\n  s.pending_out = 0;\n\n  if (s.wrap < 0) {\n    s.wrap = -s.wrap;\n    /* was made negative by deflate(..., Z_FINISH); */\n  }\n  s.status = (s.wrap ? INIT_STATE : BUSY_STATE);\n  strm.adler = (s.wrap === 2) ?\n    0  // crc32(0, Z_NULL, 0)\n  :\n    1; // adler32(0, Z_NULL, 0)\n  s.last_flush = Z_NO_FLUSH;\n  _tr_init(s);\n  return Z_OK;\n}\n\n\nfunction deflateReset(strm) {\n  var ret = deflateResetKeep(strm);\n  if (ret === Z_OK) {\n    lm_init(strm.state);\n  }\n  return ret;\n}\n\n\nfunction deflateSetHeader(strm, head) {\n  if (!strm || !strm.state) { return Z_STREAM_ERROR; }\n  if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }\n  strm.state.gzhead = head;\n  return Z_OK;\n}\n\n\nfunction deflateInit2(strm, level, method, windowBits, memLevel, strategy) {\n  if (!strm) { // === Z_NULL\n    return Z_STREAM_ERROR;\n  }\n  var wrap = 1;\n\n  if (level === Z_DEFAULT_COMPRESSION) {\n    level = 6;\n  }\n\n  if (windowBits < 0) { /* suppress zlib wrapper */\n    wrap = 0;\n    windowBits = -windowBits;\n  }\n\n  else if (windowBits > 15) {\n    wrap = 2;           /* write gzip wrapper instead */\n    windowBits -= 16;\n  }\n\n\n  if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||\n    windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||\n    strategy < 0 || strategy > Z_FIXED) {\n    return err(strm, Z_STREAM_ERROR);\n  }\n\n\n  if (windowBits === 8) {\n    windowBits = 9;\n  }\n  /* until 256-byte window bug fixed */\n\n  var s = new DeflateState();\n\n  strm.state = s;\n  s.strm = strm;\n\n  s.wrap = wrap;\n  s.gzhead = null;\n  s.w_bits = windowBits;\n  s.w_size = 1 << s.w_bits;\n  s.w_mask = s.w_size - 1;\n\n  s.hash_bits = memLevel + 7;\n  s.hash_size = 1 << s.hash_bits;\n  s.hash_mask = s.hash_size - 1;\n  s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1);\n\n  s.window = Buf8(s.w_size * 2);\n  s.head = Buf16(s.hash_size);\n  s.prev = Buf16(s.w_size);\n\n  // Don't need mem init magic for JS.\n  //s.high_water = 0;  /* nothing written to s->window yet */\n\n  s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */\n\n  s.pending_buf_size = s.lit_bufsize * 4;\n\n  //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);\n  //s->pending_buf = (uchf *) overlay;\n  s.pending_buf = Buf8(s.pending_buf_size);\n\n  // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)\n  //s->d_buf = overlay + s->lit_bufsize/sizeof(ush);\n  s.d_buf = 1 * s.lit_bufsize;\n\n  //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;\n  s.l_buf = (1 + 2) * s.lit_bufsize;\n\n  s.level = level;\n  s.strategy = strategy;\n  s.method = method;\n\n  return deflateReset(strm);\n}\n\n\nfunction deflate(strm, flush) {\n  var old_flush, s;\n  var beg, val; // for gzip header write only\n\n  if (!strm || !strm.state ||\n    flush > Z_BLOCK || flush < 0) {\n    return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;\n  }\n\n  s = strm.state;\n\n  if (!strm.output ||\n      (!strm.input && strm.avail_in !== 0) ||\n      (s.status === FINISH_STATE && flush !== Z_FINISH)) {\n    return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);\n  }\n\n  s.strm = strm; /* just in case */\n  old_flush = s.last_flush;\n  s.last_flush = flush;\n\n  /* Write the header */\n  if (s.status === INIT_STATE) {\n\n    if (s.wrap === 2) { // GZIP header\n      strm.adler = 0;  //crc32(0L, Z_NULL, 0);\n      put_byte(s, 31);\n      put_byte(s, 139);\n      put_byte(s, 8);\n      if (!s.gzhead) { // s->gzhead == Z_NULL\n        put_byte(s, 0);\n        put_byte(s, 0);\n        put_byte(s, 0);\n        put_byte(s, 0);\n        put_byte(s, 0);\n        put_byte(s, s.level === 9 ? 2 :\n                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n                     4 : 0));\n        put_byte(s, OS_CODE);\n        s.status = BUSY_STATE;\n      }\n      else {\n        put_byte(s, (s.gzhead.text ? 1 : 0) +\n                    (s.gzhead.hcrc ? 2 : 0) +\n                    (!s.gzhead.extra ? 0 : 4) +\n                    (!s.gzhead.name ? 0 : 8) +\n                    (!s.gzhead.comment ? 0 : 16)\n        );\n        put_byte(s, s.gzhead.time & 0xff);\n        put_byte(s, (s.gzhead.time >> 8) & 0xff);\n        put_byte(s, (s.gzhead.time >> 16) & 0xff);\n        put_byte(s, (s.gzhead.time >> 24) & 0xff);\n        put_byte(s, s.level === 9 ? 2 :\n                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n                     4 : 0));\n        put_byte(s, s.gzhead.os & 0xff);\n        if (s.gzhead.extra && s.gzhead.extra.length) {\n          put_byte(s, s.gzhead.extra.length & 0xff);\n          put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);\n        }\n        if (s.gzhead.hcrc) {\n          strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);\n        }\n        s.gzindex = 0;\n        s.status = EXTRA_STATE;\n      }\n    }\n    else // DEFLATE header\n    {\n      var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;\n      var level_flags = -1;\n\n      if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {\n        level_flags = 0;\n      } else if (s.level < 6) {\n        level_flags = 1;\n      } else if (s.level === 6) {\n        level_flags = 2;\n      } else {\n        level_flags = 3;\n      }\n      header |= (level_flags << 6);\n      if (s.strstart !== 0) { header |= PRESET_DICT; }\n      header += 31 - (header % 31);\n\n      s.status = BUSY_STATE;\n      putShortMSB(s, header);\n\n      /* Save the adler32 of the preset dictionary: */\n      if (s.strstart !== 0) {\n        putShortMSB(s, strm.adler >>> 16);\n        putShortMSB(s, strm.adler & 0xffff);\n      }\n      strm.adler = 1; // adler32(0L, Z_NULL, 0);\n    }\n  }\n\n//#ifdef GZIP\n  if (s.status === EXTRA_STATE) {\n    if (s.gzhead.extra/* != Z_NULL*/) {\n      beg = s.pending;  /* start of bytes to update crc */\n\n      while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n          }\n          flush_pending(strm);\n          beg = s.pending;\n          if (s.pending === s.pending_buf_size) {\n            break;\n          }\n        }\n        put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);\n        s.gzindex++;\n      }\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n      }\n      if (s.gzindex === s.gzhead.extra.length) {\n        s.gzindex = 0;\n        s.status = NAME_STATE;\n      }\n    }\n    else {\n      s.status = NAME_STATE;\n    }\n  }\n  if (s.status === NAME_STATE) {\n    if (s.gzhead.name/* != Z_NULL*/) {\n      beg = s.pending;  /* start of bytes to update crc */\n      //int val;\n\n      do {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n          }\n          flush_pending(strm);\n          beg = s.pending;\n          if (s.pending === s.pending_buf_size) {\n            val = 1;\n            break;\n          }\n        }\n        // JS specific: little magic to add zero terminator to end of string\n        if (s.gzindex < s.gzhead.name.length) {\n          val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;\n        } else {\n          val = 0;\n        }\n        put_byte(s, val);\n      } while (val !== 0);\n\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n      }\n      if (val === 0) {\n        s.gzindex = 0;\n        s.status = COMMENT_STATE;\n      }\n    }\n    else {\n      s.status = COMMENT_STATE;\n    }\n  }\n  if (s.status === COMMENT_STATE) {\n    if (s.gzhead.comment/* != Z_NULL*/) {\n      beg = s.pending;  /* start of bytes to update crc */\n      //int val;\n\n      do {\n        if (s.pending === s.pending_buf_size) {\n          if (s.gzhead.hcrc && s.pending > beg) {\n            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n          }\n          flush_pending(strm);\n          beg = s.pending;\n          if (s.pending === s.pending_buf_size) {\n            val = 1;\n            break;\n          }\n        }\n        // JS specific: little magic to add zero terminator to end of string\n        if (s.gzindex < s.gzhead.comment.length) {\n          val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;\n        } else {\n          val = 0;\n        }\n        put_byte(s, val);\n      } while (val !== 0);\n\n      if (s.gzhead.hcrc && s.pending > beg) {\n        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);\n      }\n      if (val === 0) {\n        s.status = HCRC_STATE;\n      }\n    }\n    else {\n      s.status = HCRC_STATE;\n    }\n  }\n  if (s.status === HCRC_STATE) {\n    if (s.gzhead.hcrc) {\n      if (s.pending + 2 > s.pending_buf_size) {\n        flush_pending(strm);\n      }\n      if (s.pending + 2 <= s.pending_buf_size) {\n        put_byte(s, strm.adler & 0xff);\n        put_byte(s, (strm.adler >> 8) & 0xff);\n        strm.adler = 0; //crc32(0L, Z_NULL, 0);\n        s.status = BUSY_STATE;\n      }\n    }\n    else {\n      s.status = BUSY_STATE;\n    }\n  }\n//#endif\n\n  /* Flush as much pending output as possible */\n  if (s.pending !== 0) {\n    flush_pending(strm);\n    if (strm.avail_out === 0) {\n      /* Since avail_out is 0, deflate will be called again with\n       * more output space, but possibly with both pending and\n       * avail_in equal to zero. There won't be anything to do,\n       * but this is not an error situation so make sure we\n       * return OK instead of BUF_ERROR at next call of deflate:\n       */\n      s.last_flush = -1;\n      return Z_OK;\n    }\n\n    /* Make sure there is something to do and avoid duplicate consecutive\n     * flushes. For repeated and useless calls with Z_FINISH, we keep\n     * returning Z_STREAM_END instead of Z_BUF_ERROR.\n     */\n  } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&\n    flush !== Z_FINISH) {\n    return err(strm, Z_BUF_ERROR);\n  }\n\n  /* User must not provide more input after the first FINISH: */\n  if (s.status === FINISH_STATE && strm.avail_in !== 0) {\n    return err(strm, Z_BUF_ERROR);\n  }\n\n  /* Start a new block or continue the current one.\n   */\n  if (strm.avail_in !== 0 || s.lookahead !== 0 ||\n    (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {\n    var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :\n      (s.strategy === Z_RLE ? deflate_rle(s, flush) :\n        configurationTable()[s.level].func(s, flush));\n\n    if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {\n      s.status = FINISH_STATE;\n    }\n    if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {\n      if (strm.avail_out === 0) {\n        s.last_flush = -1;\n        /* avoid BUF_ERROR next call, see above */\n      }\n      return Z_OK;\n      /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n       * of deflate should use the same flush parameter to make sure\n       * that the flush is complete. So we don't have to output an\n       * empty block here, this will be done at next call. This also\n       * ensures that for a very small output buffer, we emit at most\n       * one empty block.\n       */\n    }\n    if (bstate === BS_BLOCK_DONE) {\n      if (flush === Z_PARTIAL_FLUSH) {\n        _tr_align(s);\n      }\n      else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */\n\n        _tr_stored_block(s, 0, 0, false);\n        /* For a full flush, this empty block will be recognized\n         * as a special marker by inflate_sync().\n         */\n        if (flush === Z_FULL_FLUSH) {\n          /*** CLEAR_HASH(s); ***/             /* forget history */\n          zero$1(s.head); // Fill with NIL (= 0);\n\n          if (s.lookahead === 0) {\n            s.strstart = 0;\n            s.block_start = 0;\n            s.insert = 0;\n          }\n        }\n      }\n      flush_pending(strm);\n      if (strm.avail_out === 0) {\n        s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */\n        return Z_OK;\n      }\n    }\n  }\n  //Assert(strm->avail_out > 0, \"bug2\");\n  //if (strm.avail_out <= 0) { throw new Error(\"bug2\");}\n\n  if (flush !== Z_FINISH) { return Z_OK; }\n  if (s.wrap <= 0) { return Z_STREAM_END; }\n\n  /* Write the trailer */\n  if (s.wrap === 2) {\n    put_byte(s, strm.adler & 0xff);\n    put_byte(s, (strm.adler >> 8) & 0xff);\n    put_byte(s, (strm.adler >> 16) & 0xff);\n    put_byte(s, (strm.adler >> 24) & 0xff);\n    put_byte(s, strm.total_in & 0xff);\n    put_byte(s, (strm.total_in >> 8) & 0xff);\n    put_byte(s, (strm.total_in >> 16) & 0xff);\n    put_byte(s, (strm.total_in >> 24) & 0xff);\n  }\n  else\n  {\n    putShortMSB(s, strm.adler >>> 16);\n    putShortMSB(s, strm.adler & 0xffff);\n  }\n\n  flush_pending(strm);\n  /* If avail_out is zero, the application will call deflate again\n   * to flush the rest.\n   */\n  if (s.wrap > 0) { s.wrap = -s.wrap; }\n  /* write the trailer only once! */\n  return s.pending !== 0 ? Z_OK : Z_STREAM_END;\n}\n\nfunction deflateEnd(strm) {\n  var status;\n\n  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {\n    return Z_STREAM_ERROR;\n  }\n\n  status = strm.state.status;\n  if (status !== INIT_STATE &&\n    status !== EXTRA_STATE &&\n    status !== NAME_STATE &&\n    status !== COMMENT_STATE &&\n    status !== HCRC_STATE &&\n    status !== BUSY_STATE &&\n    status !== FINISH_STATE\n  ) {\n    return err(strm, Z_STREAM_ERROR);\n  }\n\n  strm.state = null;\n\n  return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;\n}\n\n\n/* =========================================================================\n * Initializes the compression dictionary from the given byte\n * sequence without producing any compressed output.\n */\nfunction deflateSetDictionary(strm, dictionary) {\n  var dictLength = dictionary.length;\n\n  var s;\n  var str, n;\n  var wrap;\n  var avail;\n  var next;\n  var input;\n  var tmpDict;\n\n  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {\n    return Z_STREAM_ERROR;\n  }\n\n  s = strm.state;\n  wrap = s.wrap;\n\n  if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {\n    return Z_STREAM_ERROR;\n  }\n\n  /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n  if (wrap === 1) {\n    /* adler32(strm->adler, dictionary, dictLength); */\n    strm.adler = adler32(strm.adler, dictionary, dictLength, 0);\n  }\n\n  s.wrap = 0;   /* avoid computing Adler-32 in read_buf */\n\n  /* if dictionary would fill window, just replace the history */\n  if (dictLength >= s.w_size) {\n    if (wrap === 0) {            /* already empty otherwise */\n      /*** CLEAR_HASH(s); ***/\n      zero$1(s.head); // Fill with NIL (= 0);\n      s.strstart = 0;\n      s.block_start = 0;\n      s.insert = 0;\n    }\n    /* use the tail */\n    // dictionary = dictionary.slice(dictLength - s.w_size);\n    tmpDict = Buf8(s.w_size);\n    arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0);\n    dictionary = tmpDict;\n    dictLength = s.w_size;\n  }\n  /* insert dictionary into window and hash */\n  avail = strm.avail_in;\n  next = strm.next_in;\n  input = strm.input;\n  strm.avail_in = dictLength;\n  strm.next_in = 0;\n  strm.input = dictionary;\n  fill_window(s);\n  while (s.lookahead >= MIN_MATCH$1) {\n    str = s.strstart;\n    n = s.lookahead - (MIN_MATCH$1 - 1);\n    do {\n      /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask;\n\n      s.prev[str & s.w_mask] = s.head[s.ins_h];\n\n      s.head[s.ins_h] = str;\n      str++;\n    } while (--n);\n    s.strstart = str;\n    s.lookahead = MIN_MATCH$1 - 1;\n    fill_window(s);\n  }\n  s.strstart += s.lookahead;\n  s.block_start = s.strstart;\n  s.insert = s.lookahead;\n  s.lookahead = 0;\n  s.match_length = s.prev_length = MIN_MATCH$1 - 1;\n  s.match_available = 0;\n  strm.next_in = next;\n  strm.input = input;\n  strm.avail_in = avail;\n  s.wrap = wrap;\n  return Z_OK;\n}\n\n/* Not implemented\nexports.deflateBound = deflateBound;\nexports.deflateCopy = deflateCopy;\nexports.deflateParams = deflateParams;\nexports.deflatePending = deflatePending;\nexports.deflatePrime = deflatePrime;\nexports.deflateTune = deflateTune;\n*/\n\n/* eslint-disable */\n\nvar toString$1 = Object.prototype.toString;\n\n/**\n * class Deflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[deflate]],\n * [[deflateRaw]] and [[gzip]].\n **/\n\n/* internal\n * Deflate.chunks -> Array\n *\n * Chunks of output data, if [[Deflate#onData]] not overridden.\n **/\n\n/**\n * Deflate.result -> Uint8Array|Array\n *\n * Compressed result, generated by default [[Deflate#onData]]\n * and [[Deflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Deflate#push]] with `Z_FINISH` / `true` param)  or if you\n * push a chunk with explicit flush (call [[Deflate#push]] with\n * `Z_SYNC_FLUSH` param).\n **/\n\n/**\n * Deflate.err -> Number\n *\n * Error code after deflate finished. 0 (Z_OK) on success.\n * You will not need it in real life, because deflate errors\n * are possible only on wrong options or bad `onData` / `onEnd`\n * custom handlers.\n **/\n\n/**\n * Deflate.msg -> String\n *\n * Error message, if [[Deflate.err]] != 0\n **/\n\n/**\n * new Deflate(options)\n * - options (Object): zlib deflate options.\n *\n * Creates new deflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `level`\n * - `windowBits`\n * - `memLevel`\n * - `strategy`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw deflate\n * - `gzip` (Boolean) - create gzip wrapper\n * - `to` (String) - if equal to 'string', then result will be \"binary string\"\n *    (each char code [0..255])\n * - `header` (Object) - custom header for gzip\n *   - `text` (Boolean) - true if compressed data believed to be text\n *   - `time` (Number) - modification time, unix timestamp\n *   - `os` (Number) - operation system code\n *   - `extra` (Array) - array of bytes with extra data (max 65536)\n *   - `name` (String) - file name (binary string)\n *   - `comment` (String) - comment (binary string)\n *   - `hcrc` (Boolean) - true if header crc should be added\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])\n *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * var deflate = new pako.Deflate({ level: 3});\n *\n * deflate.push(chunk1, false);\n * deflate.push(chunk2, true);  // true -> last chunk\n *\n * if (deflate.err) { throw new Error(deflate.err); }\n *\n * console.log(deflate.result);\n * ```\n **/\nvar Deflate = function Deflate(options) {\n  this.options = assign({\n    level: Z_DEFAULT_COMPRESSION,\n    method: Z_DEFLATED,\n    chunkSize: 16384,\n    windowBits: 15,\n    memLevel: 8,\n    strategy: Z_DEFAULT_STRATEGY,\n    to: ''\n  }, options || {});\n\n  var opt = this.options;\n\n  if (opt.raw && (opt.windowBits > 0)) {\n    opt.windowBits = -opt.windowBits;\n  }\n\n  else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {\n    opt.windowBits += 16;\n  }\n\n  this.err  = 0;    // error code, if happens (0 = Z_OK)\n  this.msg  = '';   // error message\n  this.ended= false;// used to avoid multiple onEnd() calls\n  this.chunks = [];   // chunks of compressed data\n\n  this.strm = new ZStream();\n  this.strm.avail_out = 0;\n\n  var status = deflateInit2(\n    this.strm,\n    opt.level,\n    opt.method,\n    opt.windowBits,\n    opt.memLevel,\n    opt.strategy\n  );\n\n  if (status !== Z_OK) {\n    throw new Error(msg[status]);\n  }\n\n  if (opt.header) {\n    deflateSetHeader(this.strm, opt.header);\n  }\n\n  if (opt.dictionary) {\n    var dict;\n    // Convert data if needed\n    if (typeof opt.dictionary === 'string') {\n      // If we need to compress text, change encoding to utf8.\n      dict = string2buf(opt.dictionary);\n    } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {\n      dict = new Uint8Array(opt.dictionary);\n    } else {\n      dict = opt.dictionary;\n    }\n\n    status = deflateSetDictionary(this.strm, dict);\n\n    if (status !== Z_OK) {\n      throw new Error(msg[status]);\n    }\n\n    this._dict_set = true;\n  }\n};\n\n/**\n * Deflate#push(data[, mode]) -> Boolean\n * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be\n * converted to utf8 byte sequence.\n * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.\n *\n * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with\n * new compressed chunks. Returns `true` on success. The last data block must have\n * mode Z_FINISH (or `true`). That will flush internal pending buffers and call\n * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you\n * can use mode Z_SYNC_FLUSH, keeping the compression context.\n *\n * On fail call [[Deflate#onEnd]] with error code and return false.\n *\n * We strongly recommend to use `Uint8Array` on input for best speed (output\n * array format is detected automatically). Also, don't skip last param and always\n * use the same type in your code (boolean or number). That will improve JS speed.\n *\n * For regular `Array`-s make sure all elements are [0..255].\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true);// push last chunk\n * ```\n **/\nDeflate.prototype.push = function push (data, mode) {\n  var strm = this.strm;\n  var chunkSize = this.options.chunkSize;\n  var status, _mode;\n\n  if (this.ended) { return false; }\n\n  _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);\n\n  // Convert data if needed\n  if (typeof data === 'string') {\n    // If we need to compress text, change encoding to utf8.\n    strm.input = string2buf(data);\n  } else if (toString$1.call(data) === '[object ArrayBuffer]') {\n    strm.input = new Uint8Array(data);\n  } else {\n    strm.input = data;\n  }\n\n  strm.next_in = 0;\n  strm.avail_in = strm.input.length;\n\n  do {\n    if (strm.avail_out === 0) {\n      strm.output = Buf8(chunkSize);\n      strm.next_out = 0;\n      strm.avail_out = chunkSize;\n    }\n    status = deflate(strm, _mode);  /* no bad return value */\n\n    if (status !== Z_STREAM_END && status !== Z_OK) {\n      this.onEnd(status);\n      this.ended = true;\n      return false;\n    }\n    if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) {\n      if (this.options.to === 'string') {\n        this.onData(buf2binstring(shrinkBuf(strm.output, strm.next_out)));\n      } else {\n        this.onData(shrinkBuf(strm.output, strm.next_out));\n      }\n    }\n  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);\n\n  // Finalize on the last chunk.\n  if (_mode === Z_FINISH) {\n    status = deflateEnd(this.strm);\n    this.onEnd(status);\n    this.ended = true;\n    return status === Z_OK;\n  }\n\n  // callback interim results if Z_SYNC_FLUSH.\n  if (_mode === Z_SYNC_FLUSH) {\n    this.onEnd(Z_OK);\n    strm.avail_out = 0;\n    return true;\n  }\n\n  return true;\n};\n\n\n/**\n * Deflate#onData(chunk) -> Void\n * - chunk (Uint8Array|Array|String): output data. Type of array depends\n * on js engine support. When string output requested, each chunk\n * will be string.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nDeflate.prototype.onData = function onData (chunk) {\n  this.chunks.push(chunk);\n};\n\n\n/**\n * Deflate#onEnd(status) -> Void\n * - status (Number): deflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called once after you tell deflate that the input stream is\n * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)\n * or if an error happened. By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nDeflate.prototype.onEnd = function onEnd (status) {\n  // On success - join\n  if (status === Z_OK) {\n    if (this.options.to === 'string') {\n      this.result = this.chunks.join('');\n    } else {\n      this.result = flattenChunks(this.chunks);\n    }\n  }\n  this.chunks = [];\n  this.err = status;\n  this.msg = this.strm.msg;\n};\n\n\n/**\n * deflate(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * Compress `data` with deflate algorithm and `options`.\n *\n * Supported options are:\n *\n * - level\n * - windowBits\n * - memLevel\n * - strategy\n * - dictionary\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n *   negative windowBits implicitly.\n * - `to` (String) - if equal to 'string', then result will be \"binary string\"\n *    (each char code [0..255])\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n *   , data = Uint8Array([1,2,3,4,5,6,7,8,9]);\n *\n * console.log(pako.deflate(data));\n * ```\n **/\nfunction deflate$1(input, options) {\n  var deflator = new Deflate(options);\n\n  deflator.push(input, true);\n\n  // That will never happens, if you don't cheat with options :)\n  if (deflator.err) { throw deflator.msg || msg[deflator.err]; }\n\n  return deflator.result;\n}\n\n\n/**\n * deflateRaw(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction deflateRaw(input, options) {\n  options = options || {};\n  options.raw = true;\n  return deflate$1(input, options);\n}\n\n\n/**\n * gzip(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but create gzip wrapper instead of\n * deflate one.\n **/\nfunction gzip(input, options) {\n  options = options || {};\n  options.gzip = true;\n  return deflate$1(input, options);\n}\n\nexport { Deflate, Inflate, Z_BEST_COMPRESSION, Z_BEST_SPEED, Z_BINARY, Z_BLOCK, Z_BUF_ERROR, Z_DATA_ERROR, Z_DEFAULT_COMPRESSION, Z_DEFAULT_STRATEGY, Z_DEFLATED, Z_ERRNO, Z_FILTERED, Z_FINISH, Z_FIXED, Z_FULL_FLUSH, Z_HUFFMAN_ONLY, Z_NEED_DICT, Z_NO_COMPRESSION, Z_NO_FLUSH, Z_OK, Z_PARTIAL_FLUSH, Z_RLE, Z_STREAM_END, Z_STREAM_ERROR, Z_SYNC_FLUSH, Z_TEXT, Z_TREES, Z_UNKNOWN, deflate$1 as deflate, deflateRaw, gzip, inflate$1 as inflate, inflateRaw, ungzip };\n","import { Deflate, Inflate } from '@progress/pako-esm';\n\n/**\n * Let the user use/change some implementations.\n */\nvar external = {\n    Promise: Promise\n};\n\nvar support = {\n    base64: true,\n    array: true,\n    string: true,\n    nodebuffer: false,\n    nodestream: false,\n\n    get arraybuffer() {\n        return typeof ArrayBuffer !== \"undefined\" && typeof Uint8Array !== \"undefined\";\n    },\n\n    // Returns true if JSZip can read/generate Uint8Array, false otherwise.\n    get uint8array() {\n        return typeof Uint8Array !== \"undefined\";\n    },\n\n    get blob() {\n        return blob();\n    }\n};\n\nvar blob = function() {\n    var supported;\n\n    if (typeof ArrayBuffer === \"undefined\") {\n        supported = false;\n    } else {\n        var buffer = new ArrayBuffer(0);\n        try {\n            supported = new Blob([ buffer ], {\n                type: \"application/zip\"\n            }).size === 0;\n        } catch (e) {\n            supported = false;\n        }\n    }\n\n    blob = function () { return supported; };\n    return supported;\n};\n\n/* eslint-disable */\n\n// private property\nvar _keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n// public method for encoding\nvar encode = function(input) {\n    var output = [];\n    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n    var i = 0, len = input.length, remainingBytes = len;\n\n    var isArray = typeof input !== \"string\";\n    while (i < input.length) {\n        remainingBytes = len - i;\n\n        if (!isArray) {\n            chr1 = input.charCodeAt(i++);\n            chr2 = i < len ? input.charCodeAt(i++) : 0;\n            chr3 = i < len ? input.charCodeAt(i++) : 0;\n        } else {\n            chr1 = input[i++];\n            chr2 = i < len ? input[i++] : 0;\n            chr3 = i < len ? input[i++] : 0;\n        }\n\n        enc1 = chr1 >> 2;\n        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n        enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64;\n        enc4 = remainingBytes > 2 ? (chr3 & 63) : 64;\n\n        output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4));\n\n    }\n\n    return output.join(\"\");\n};\n\n// public method for decoding\nvar decode = function(input) {\n    var chr1, chr2, chr3;\n    var enc1, enc2, enc3, enc4;\n    var i = 0, resultIndex = 0;\n\n    var dataUrlPrefix = \"data:\";\n\n    if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) {\n        // This is a common error: people give a data url\n        // (data:image/png;base64,iVBOR...) with a {base64: true} and\n        // wonders why things don't work.\n        // We can detect that the string input looks like a data url but we\n        // *can't* be sure it is one: removing everything up to the comma would\n        // be too dangerous.\n        throw new Error(\"Invalid base64 input, it looks like a data url.\");\n    }\n\n    input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n    var totalLength = input.length * 3 / 4;\n    if(input.charAt(input.length - 1) === _keyStr.charAt(64)) {\n        totalLength--;\n    }\n    if(input.charAt(input.length - 2) === _keyStr.charAt(64)) {\n        totalLength--;\n    }\n    if (totalLength % 1 !== 0) {\n        // totalLength is not an integer, the length does not match a valid\n        // base64 content. That can happen if:\n        // - the input is not a base64 content\n        // - the input is *almost* a base64 content, with a extra chars at the\n        //   beginning or at the end\n        // - the input uses a base64 letiant (base64url for example)\n        throw new Error(\"Invalid base64 input, bad content length.\");\n    }\n    var output;\n    if (support.uint8array) {\n        output = new Uint8Array(totalLength|0);\n    } else {\n        output = new Array(totalLength|0);\n    }\n\n    while (i < input.length) {\n\n        enc1 = _keyStr.indexOf(input.charAt(i++));\n        enc2 = _keyStr.indexOf(input.charAt(i++));\n        enc3 = _keyStr.indexOf(input.charAt(i++));\n        enc4 = _keyStr.indexOf(input.charAt(i++));\n\n        chr1 = (enc1 << 2) | (enc2 >> 4);\n        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n        chr3 = ((enc3 & 3) << 6) | enc4;\n\n        output[resultIndex++] = chr1;\n\n        if (enc3 !== 64) {\n            output[resultIndex++] = chr2;\n        }\n        if (enc4 !== 64) {\n            output[resultIndex++] = chr3;\n        }\n\n    }\n\n    return output;\n};\n\n/* eslint-disable */\n\n/**\n * Convert a string that pass as a \"binary string\": it should represent a byte\n * array but may have > 255 char codes. Be sure to take only the first byte\n * and returns the byte array.\n * @param {String} str the string to transform.\n * @return {Array|Uint8Array} the string in a binary format.\n */\nfunction string2binary(str) {\n    var result = null;\n    if (support.uint8array) {\n      result = new Uint8Array(str.length);\n    } else {\n      result = new Array(str.length);\n    }\n    return stringToArrayLike(str, result);\n}\n\n/**\n * Create a new blob with the given content and the given type.\n * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use\n * an Uint8Array because the stock browser of android 4 won't accept it (it\n * will be silently converted to a string, \"[object Uint8Array]\").\n *\n * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge:\n * when a large amount of Array is used to create the Blob, the amount of\n * memory consumed is nearly 100 times the original data amount.\n *\n * @param {String} type the mime type of the blob.\n * @return {Blob} the created blob.\n */\nvar newBlob = function(part, type) {\n    checkSupport(\"blob\");\n\n    // Blob constructor\n    return new Blob([part], {\n        type: type\n    });\n};\n\n/**\n * The identity function.\n * @param {Object} input the input.\n * @return {Object} the same input.\n */\nfunction identity(input) {\n    return input;\n}\n\n/**\n * Fill in an array with a string.\n * @param {String} str the string to use.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).\n * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.\n */\nfunction stringToArrayLike(str, array) {\n    for (var i = 0; i < str.length; ++i) {\n        array[i] = str.charCodeAt(i) & 0xFF;\n    }\n    return array;\n}\n\n/**\n * Transform an array of int into a string, chunk by chunk.\n * See the performances notes on arrayLikeToString.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.\n * @param {String} type the type of the array.\n * @param {Integer} chunk the chunk size.\n * @return {String} the resulting string.\n * @throws Error if the chunk is too big for the stack.\n */\nfunction stringifyByChunk(array, type, chunk) {\n    var result = [], k = 0, len = array.length;\n    // shortcut\n    if (len <= chunk) {\n        return String.fromCharCode.apply(null, array);\n    }\n    while (k < len) {\n        if (type === \"array\") {\n            result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));\n        }\n        else {\n            result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));\n        }\n        k += chunk;\n    }\n    return result.join(\"\");\n}\n\n/**\n * Call String.fromCharCode on every item in the array.\n * This is the naive implementation, which generate A LOT of intermediate string.\n * This should be used when everything else fail.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.\n * @return {String} the result.\n */\nfunction stringifyByChar(array) {\n    var resultStr = \"\";\n    for(var i = 0; i < array.length; i++) {\n        resultStr += String.fromCharCode(array[i]);\n    }\n    return resultStr;\n}\n\n/**\n * true if the browser accepts to use String.fromCharCode on Uint8Array\n */\nvar fromCharCodeSupportsTypedArrays = function () {\n    var supported;\n    try {\n        supported = support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1;\n    } catch (e) {\n        supported = false;\n    }\n\n    fromCharCodeSupportsTypedArrays = function () { return supported; };\n    return supported;\n};\n\n/**\n * Transform an array-like object to a string.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.\n * @return {String} the result.\n */\nfunction arrayLikeToString(array) {\n    // Performances notes :\n    // --------------------\n    // String.fromCharCode.apply(null, array) is the fastest, see\n    // see http://jsperf.com/converting-a-uint8array-to-a-string/2\n    // but the stack is limited (and we can get huge arrays !).\n    //\n    // result += String.fromCharCode(array[i]); generate too many strings !\n    //\n    // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2\n    // TODO : we now have workers that split the work. Do we still need that ?\n    var chunk = 65536,\n        type = getTypeOf(array),\n        canUseApply = true;\n    if (type === \"uint8array\") {\n        canUseApply = fromCharCodeSupportsTypedArrays();\n    }\n\n    if (canUseApply) {\n        while (chunk > 1) {\n            try {\n                return stringifyByChunk(array, type, chunk);\n            } catch (e) {\n                chunk = Math.floor(chunk / 2);\n            }\n        }\n    }\n\n    // no apply or chunk error : slow and painful algorithm\n    // default browser on android 4.*\n    return stringifyByChar(array);\n}\n\nvar applyFromCharCode = arrayLikeToString;\n\n\n/**\n * Copy the data from an array-like to an other array-like.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.\n * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.\n * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.\n */\nfunction arrayLikeToArrayLike(arrayFrom, arrayTo) {\n    for (var i = 0; i < arrayFrom.length; i++) {\n        arrayTo[i] = arrayFrom[i];\n    }\n    return arrayTo;\n}\n\n// a matrix containing functions to transform everything into everything.\nvar transform = {\n    // string to ?\n    \"string\": {\n        \"string\": identity,\n        \"array\": function(input) {\n            return stringToArrayLike(input, new Array(input.length));\n        },\n        \"arraybuffer\": function(input) {\n            return transform[\"string\"][\"uint8array\"](input).buffer;\n        },\n        \"uint8array\": function(input) {\n            return stringToArrayLike(input, new Uint8Array(input.length));\n        }\n    },\n\n    // array to ?\n    \"array\": {\n        \"string\": arrayLikeToString,\n        \"array\": identity,\n        \"arraybuffer\": function(input) {\n            return (new Uint8Array(input)).buffer;\n        },\n        \"uint8array\": function(input) {\n            return new Uint8Array(input);\n        }\n    },\n\n    // arraybuffer to ?\n    \"arraybuffer\": {\n        \"string\": function(input) {\n            return arrayLikeToString(new Uint8Array(input));\n        },\n        \"array\": function(input) {\n            return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));\n        },\n        \"arraybuffer\": identity,\n        \"uint8array\": function(input) {\n            return new Uint8Array(input);\n        }\n    },\n\n    // uint8array to ?\n    \"uint8array\": {\n        \"string\": arrayLikeToString,\n        \"array\": function(input) {\n            return arrayLikeToArrayLike(input, new Array(input.length));\n        },\n        \"arraybuffer\": function(input) {\n            return input.buffer;\n        },\n        \"uint8array\": identity\n    }\n};\n\n/**\n * Transform an input into any type.\n * The supported output type are : string, array, uint8array, arraybuffer.\n * If no output type is specified, the unmodified input will be returned.\n * @param {String} outputType the output type.\n * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.\n * @throws {Error} an Error if the browser doesn't support the requested output type.\n */\nvar transformTo = function(outputType, input) {\n    if (!input) {\n        // undefined, null, etc\n        // an empty string won't harm.\n        input = \"\";\n    }\n    if (!outputType) {\n        return input;\n    }\n    checkSupport(outputType);\n    var inputType = getTypeOf(input);\n    var result = transform[inputType][outputType](input);\n    return result;\n};\n\n/**\n * Return the type of the input.\n * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.\n * @param {Object} input the input to identify.\n * @return {String} the (lowercase) type of the input.\n */\nvar getTypeOf = function(input) {\n    if (typeof input === \"string\") {\n        return \"string\";\n    }\n    if (Object.prototype.toString.call(input) === \"[object Array]\") {\n        return \"array\";\n    }\n    if (support.uint8array && input instanceof Uint8Array) {\n        return \"uint8array\";\n    }\n    if (support.arraybuffer && input instanceof ArrayBuffer) {\n        return \"arraybuffer\";\n    }\n};\n\n/**\n * Throw an exception if the type is not supported.\n * @param {String} type the type to check.\n * @throws {Error} an Error if the browser doesn't support the requested type.\n */\nvar checkSupport = function(type) {\n    var supported = support[type.toLowerCase()];\n    if (!supported) {\n        throw new Error(type + \" is not supported by this platform\");\n    }\n};\n\nvar MAX_VALUE_16BITS = 65535;\nvar MAX_VALUE_32BITS = -1; // well, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" is parsed as -1\n\n/**\n * Prettify a string read as binary.\n * @param {string} str the string to prettify.\n * @return {string} a pretty string.\n */\nvar pretty = function(str) {\n    var res = '',\n        code, i;\n    for (i = 0; i < (str || \"\").length; i++) {\n        code = str.charCodeAt(i);\n        res += '\\\\x' + (code < 16 ? \"0\" : \"\") + code.toString(16).toUpperCase();\n    }\n    return res;\n};\n\n/**\n * Defer the call of a function.\n * @param {Function} callback the function to call asynchronously.\n * @param {Array} args the arguments to give to the callback.\n */\nvar delay = function(callback, args, self) {\n    setTimeout(function() {\n        callback.apply(self || null, args || []);\n    }, 0);\n};\n\n/**\n * Merge the objects passed as parameters into a new one.\n * @private\n * @param {...Object} var_args All objects to merge.\n * @return {Object} a new object with the data of the others.\n */\nvar extend = function() {\n    var arguments$1 = arguments;\n\n    var result = {}, i, attr;\n    for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers\n        for (attr in arguments[i]) {\n            if (Object.hasOwnProperty.call(arguments$1[i], attr) && typeof result[attr] === \"undefined\") {\n                result[attr] = arguments$1[i][attr];\n            }\n        }\n    }\n    return result;\n};\n\n/**\n * Transform arbitrary content into a Promise.\n * @param {String} name a name for the content being processed.\n * @param {Object} inputData the content to process.\n * @param {Boolean} isBinary true if the content is not an unicode string\n * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character.\n * @param {Boolean} isBase64 true if the string content is encoded with base64.\n * @return {Promise} a promise in a format usable by JSZip.\n */\nvar prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) {\n\n    // if inputData is already a promise, this flatten it.\n    var promise = external.Promise.resolve(inputData).then(function(data) {\n\n\n        var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1);\n\n        if (isBlob && typeof FileReader !== \"undefined\") {\n            return new external.Promise(function (resolve, reject) {\n                var reader = new FileReader();\n\n                reader.onload = function(e) {\n                    resolve(e.target.result);\n                };\n                reader.onerror = function(e) {\n                    reject(e.target.error);\n                };\n                reader.readAsArrayBuffer(data);\n            });\n        } else {\n            return data;\n        }\n    });\n\n    return promise.then(function(data) {\n        var dataType = getTypeOf(data);\n\n        if (!dataType) {\n            return external.Promise.reject(\n                new Error(\"Can't read the data of '\" + name + \"'. Is it \" +\n                          \"in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?\")\n            );\n        }\n        // special case : it's way easier to work with Uint8Array than with ArrayBuffer\n        if (dataType === \"arraybuffer\") {\n            data = transformTo(\"uint8array\", data);\n        } else if (dataType === \"string\") {\n            if (isBase64) {\n                data = decode(data);\n            }\n            else if (isBinary) {\n                // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask\n                if (isOptimizedBinaryString !== true) {\n                    // this is a string, not in a base64 format.\n                    // Be sure that this is a correct \"binary string\"\n                    data = string2binary(data);\n                }\n            }\n        }\n        return data;\n    });\n};\n\n/* eslint-disable */\n\n/**\n * A worker that does nothing but passing chunks to the next one. This is like\n * a nodejs stream but with some differences. On the good side :\n * - it works on IE 6-9 without any issue / polyfill\n * - it weights less than the full dependencies bundled with browserify\n * - it forwards errors (no need to declare an error handler EVERYWHERE)\n *\n * A chunk is an object with 2 attributes : `meta` and `data`. The former is an\n * object containing anything (`percent` for example), see each worker for more\n * details. The latter is the real data (String, Uint8Array, etc).\n *\n * @constructor\n * @param {String} name the name of the stream (mainly used for debugging purposes)\n */\nvar GenericWorker = function GenericWorker(name) {\n    // the name of the worker\n    this.name = name || \"default\";\n    // an object containing metadata about the workers chain\n    this.streamInfo = {};\n    // an error which happened when the worker was paused\n    this.generatedError = null;\n    // an object containing metadata to be merged by this worker into the general metadata\n    this.extraStreamInfo = {};\n    // true if the stream is paused (and should not do anything), false otherwise\n    this.isPaused = true;\n    // true if the stream is finished (and should not do anything), false otherwise\n    this.isFinished = false;\n    // true if the stream is locked to prevent further structure updates (pipe), false otherwise\n    this.isLocked = false;\n    // the event listeners\n    this._listeners = {\n        'data':[],\n        'end':[],\n        'error':[]\n    };\n    // the previous worker, if any\n    this.previous = null;\n};\n\n/**\n * Push a chunk to the next workers.\n * @param {Object} chunk the chunk to push\n */\nGenericWorker.prototype.push = function push (chunk) {\n    this.emit(\"data\", chunk);\n};\n\n/**\n * End the stream.\n * @return {Boolean} true if this call ended the worker, false otherwise.\n */\nGenericWorker.prototype.end = function end () {\n    if (this.isFinished) {\n        return false;\n    }\n\n    this.flush();\n    try {\n        this.emit(\"end\");\n        this.cleanUp();\n        this.isFinished = true;\n    } catch (e) {\n        this.emit(\"error\", e);\n    }\n    return true;\n};\n\n/**\n * End the stream with an error.\n * @param {Error} e the error which caused the premature end.\n * @return {Boolean} true if this call ended the worker with an error, false otherwise.\n */\nGenericWorker.prototype.error = function error (e) {\n    if (this.isFinished) {\n        return false;\n    }\n\n    if(this.isPaused) {\n        this.generatedError = e;\n    } else {\n        this.isFinished = true;\n\n        this.emit(\"error\", e);\n\n        // in the workers chain exploded in the middle of the chain,\n        // the error event will go downward but we also need to notify\n        // workers upward that there has been an error.\n        if(this.previous) {\n            this.previous.error(e);\n        }\n\n        this.cleanUp();\n    }\n    return true;\n};\n\n/**\n * Add a callback on an event.\n * @param {String} name the name of the event (data, end, error)\n * @param {Function} listener the function to call when the event is triggered\n * @return {GenericWorker} the current object for chainability\n */\nGenericWorker.prototype.on = function on (name, listener) {\n    this._listeners[name].push(listener);\n    return this;\n};\n\n/**\n * Clean any references when a worker is ending.\n */\nGenericWorker.prototype.cleanUp = function cleanUp () {\n    this.streamInfo = this.generatedError = this.extraStreamInfo = null;\n    this._listeners = [];\n};\n\n/**\n * Trigger an event. This will call registered callback with the provided arg.\n * @param {String} name the name of the event (data, end, error)\n * @param {Object} arg the argument to call the callback with.\n */\nGenericWorker.prototype.emit = function emit (name, arg) {\n    if (this._listeners[name]) {\n        for(var i = 0; i < this._listeners[name].length; i++) {\n            this._listeners[name][i].call(this, arg);\n        }\n    }\n};\n\n/**\n * Chain a worker with an other.\n * @param {Worker} next the worker receiving events from the current one.\n * @return {worker} the next worker for chainability\n */\nGenericWorker.prototype.pipe = function pipe (next) {\n    return next.registerPrevious(this);\n};\n\n/**\n * Same as `pipe` in the other direction.\n * Using an API with `pipe(next)` is very easy.\n * Implementing the API with the point of view of the next one registering\n * a source is easier, see the ZipFileWorker.\n * @param {Worker} previous the previous worker, sending events to this one\n * @return {Worker} the current worker for chainability\n */\nGenericWorker.prototype.registerPrevious = function registerPrevious (previous) {\n    if (this.isLocked) {\n        throw new Error(\"The stream '\" + this + \"' has already been used.\");\n    }\n\n    // sharing the streamInfo...\n    this.streamInfo = previous.streamInfo;\n    // ... and adding our own bits\n    this.mergeStreamInfo();\n    this.previous =  previous;\n    var self = this;\n    previous.on('data', function (chunk) {\n        self.processChunk(chunk);\n    });\n    previous.on('end', function () {\n        self.end();\n    });\n    previous.on('error', function (e) {\n        self.error(e);\n    });\n    return this;\n};\n\n/**\n * Pause the stream so it doesn't send events anymore.\n * @return {Boolean} true if this call paused the worker, false otherwise.\n */\nGenericWorker.prototype.pause = function pause () {\n    if(this.isPaused || this.isFinished) {\n        return false;\n    }\n    this.isPaused = true;\n\n    if(this.previous) {\n        this.previous.pause();\n    }\n    return true;\n};\n\n/**\n * Resume a paused stream.\n * @return {Boolean} true if this call resumed the worker, false otherwise.\n */\nGenericWorker.prototype.resume = function resume () {\n    if(!this.isPaused || this.isFinished) {\n        return false;\n    }\n    this.isPaused = false;\n\n    // if true, the worker tried to resume but failed\n    var withError = false;\n    if(this.generatedError) {\n        this.error(this.generatedError);\n        withError = true;\n    }\n    if(this.previous) {\n        this.previous.resume();\n    }\n\n    return !withError;\n};\n\n/**\n * Flush any remaining bytes as the stream is ending.\n */\nGenericWorker.prototype.flush = function flush () {};\n\n/**\n * Process a chunk. This is usually the method overridden.\n * @param {Object} chunk the chunk to process.\n */\nGenericWorker.prototype.processChunk = function processChunk (chunk) {\n    this.push(chunk);\n};\n\n/**\n * Add a key/value to be added in the workers chain streamInfo once activated.\n * @param {String} key the key to use\n * @param {Object} value the associated value\n * @return {Worker} the current worker for chainability\n */\nGenericWorker.prototype.withStreamInfo = function withStreamInfo (key, value) {\n    this.extraStreamInfo[key] = value;\n    this.mergeStreamInfo();\n    return this;\n};\n\n/**\n * Merge this worker's streamInfo into the chain's streamInfo.\n */\nGenericWorker.prototype.mergeStreamInfo = function mergeStreamInfo () {\n    for(var key in this.extraStreamInfo) {\n        if (!this.extraStreamInfo.hasOwnProperty(key)) {\n            continue;\n        }\n        this.streamInfo[key] = this.extraStreamInfo[key];\n    }\n};\n\n/**\n * Lock the stream to prevent further updates on the workers chain.\n * After calling this method, all calls to pipe will fail.\n */\nGenericWorker.prototype.lock = function lock () {\n    if (this.isLocked) {\n        throw new Error(\"The stream '\" + this + \"' has already been used.\");\n    }\n    this.isLocked = true;\n    if (this.previous) {\n        this.previous.lock();\n    }\n};\n\n/**\n *\n * Pretty print the workers chain.\n */\nGenericWorker.prototype.toString = function toString () {\n    var me = \"Worker \" + this.name;\n    if (this.previous) {\n        return this.previous + \" -> \" + me;\n    } else {\n        return me;\n    }\n};\n\n/* eslint-disable */\n\n/**\n * The following functions come from pako, from pako/lib/utils/strings\n * released under the MIT license, see pako https://github.com/nodeca/pako/\n */\n\n// Returns the utf8 lengths (calculated by first byte of sequence)\n// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n// because max possible codepoint is 0x10ffff\nvar utf8len = function(c) {\n    var _utf8len = new Array(256);\n    for (var i = 0; i < 256; i++) {\n        _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);\n    }\n    _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start\n\n    // Memoize table after first call\n    utf8len = function(c) {\n        return _utf8len[c];\n    };\n\n    return _utf8len[c];\n};\n\n// convert string to array (typed, when possible)\nvar string2buf = function (str) {\n    var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;\n\n    // count binary size\n    for (m_pos = 0; m_pos < str_len; m_pos++) {\n        c = str.charCodeAt(m_pos);\n        if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {\n            c2 = str.charCodeAt(m_pos+1);\n            if ((c2 & 0xfc00) === 0xdc00) {\n                c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n                m_pos++;\n            }\n        }\n        buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;\n    }\n\n    // allocate buffer\n    if (support.uint8array) {\n        buf = new Uint8Array(buf_len);\n    } else {\n        buf = new Array(buf_len);\n    }\n\n    // convert\n    for (i=0, m_pos = 0; i < buf_len; m_pos++) {\n        c = str.charCodeAt(m_pos);\n        if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {\n            c2 = str.charCodeAt(m_pos+1);\n            if ((c2 & 0xfc00) === 0xdc00) {\n                c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n                m_pos++;\n            }\n        }\n        if (c < 0x80) {\n            /* one byte */\n            buf[i++] = c;\n        } else if (c < 0x800) {\n            /* two bytes */\n            buf[i++] = 0xC0 | (c >>> 6);\n            buf[i++] = 0x80 | (c & 0x3f);\n        } else if (c < 0x10000) {\n            /* three bytes */\n            buf[i++] = 0xE0 | (c >>> 12);\n            buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n            buf[i++] = 0x80 | (c & 0x3f);\n        } else {\n            /* four bytes */\n            buf[i++] = 0xf0 | (c >>> 18);\n            buf[i++] = 0x80 | (c >>> 12 & 0x3f);\n            buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n            buf[i++] = 0x80 | (c & 0x3f);\n        }\n    }\n\n    return buf;\n};\n\n// Calculate max possible position in utf8 buffer,\n// that will not break sequence. If that's not possible\n// - (very small limits) return max size as is.\n//\n// buf[] - utf8 bytes array\n// max   - length limit (mandatory);\nvar utf8border = function(buf, max) {\n    var pos;\n\n    max = max || buf.length;\n    if (max > buf.length) { max = buf.length; }\n\n    // go back from last position, until start of sequence found\n    pos = max-1;\n    while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }\n\n    // Fuckup - very small and broken sequence,\n    // return max, because we should return something anyway.\n    if (pos < 0) { return max; }\n\n    // If we came to start of buffer - that means vuffer is too small,\n    // return max too.\n    if (pos === 0) { return max; }\n\n    return (pos + utf8len(buf[pos]) > max) ? pos : max;\n};\n\n// convert array to string\nvar buf2string = function (buf) {\n    var i, out, c, c_len;\n    var len = buf.length;\n\n    // Reserve max possible length (2 words per char)\n    // NB: by unknown reasons, Array is significantly faster for\n    //     String.fromCharCode.apply than Uint16Array.\n    var utf16buf = new Array(len*2);\n\n    for (out=0, i=0; i<len;) {\n        c = buf[i++];\n        // quick process ascii\n        if (c < 0x80) { utf16buf[out++] = c; continue; }\n\n        c_len = utf8len(c);\n        // skip 5 & 6 byte codes\n        if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }\n\n        // apply mask on first byte\n        c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;\n        // join the rest\n        while (c_len > 1 && i < len) {\n            c = (c << 6) | (buf[i++] & 0x3f);\n            c_len--;\n        }\n\n        // terminated by end of string?\n        if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }\n\n        if (c < 0x10000) {\n            utf16buf[out++] = c;\n        } else {\n            c -= 0x10000;\n            utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);\n            utf16buf[out++] = 0xdc00 | (c & 0x3ff);\n        }\n    }\n\n    // shrinkBuf(utf16buf, out)\n    if (utf16buf.length !== out) {\n        if(utf16buf.subarray) {\n            utf16buf = utf16buf.subarray(0, out);\n        } else {\n            utf16buf.length = out;\n        }\n    }\n\n    // return String.fromCharCode.apply(null, utf16buf);\n    return applyFromCharCode(utf16buf);\n};\n\n\n// That's all for the pako functions.\n\n\n/**\n * Transform a javascript string into an array (typed if possible) of bytes,\n * UTF-8 encoded.\n * @param {String} str the string to encode\n * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string.\n */\nvar utf8encode = function utf8encode(str) {\n    return string2buf(str);\n};\n\n/**\n * Transform a bytes array (or a representation) representing an UTF-8 encoded\n * string into a javascript string.\n * @param {Array|Uint8Array|Buffer} buf the data de decode\n * @return {String} the decoded string.\n */\nvar utf8decode = function utf8decode(buf) {\n    buf = transformTo(support.uint8array ? \"uint8array\" : \"array\", buf);\n\n    return buf2string(buf);\n};\n\n/**\n * A worker to decode utf8 encoded binary chunks into string chunks.\n * @constructor\n */\nvar Utf8DecodeWorker = /*@__PURE__*/(function (GenericWorker) {\n    function Utf8DecodeWorker() {\n        GenericWorker.call(this, \"utf-8 decode\");\n\n        // the last bytes if a chunk didn't end with a complete codepoint.\n        this.leftOver = null;\n    }\n\n    if ( GenericWorker ) Utf8DecodeWorker.__proto__ = GenericWorker;\n    Utf8DecodeWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    Utf8DecodeWorker.prototype.constructor = Utf8DecodeWorker;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    Utf8DecodeWorker.prototype.processChunk = function processChunk (chunk) {\n        var data = transformTo(support.uint8array ? \"uint8array\" : \"array\", chunk.data);\n\n        // 1st step, re-use what's left of the previous chunk\n        if (this.leftOver && this.leftOver.length) {\n            if(support.uint8array) {\n                var previousData = data;\n                data = new Uint8Array(previousData.length + this.leftOver.length);\n                data.set(this.leftOver, 0);\n                data.set(previousData, this.leftOver.length);\n            } else {\n                data = this.leftOver.concat(data);\n            }\n            this.leftOver = null;\n        }\n\n        var nextBoundary = utf8border(data);\n        var usableData = data;\n        if (nextBoundary !== data.length) {\n            if (support.uint8array) {\n                usableData = data.subarray(0, nextBoundary);\n                this.leftOver = data.subarray(nextBoundary, data.length);\n            } else {\n                usableData = data.slice(0, nextBoundary);\n                this.leftOver = data.slice(nextBoundary, data.length);\n            }\n        }\n\n        this.push({\n            data : utf8decode(usableData),\n            meta : chunk.meta\n        });\n    };\n\n    /**\n     * @see GenericWorker.flush\n     */\n    Utf8DecodeWorker.prototype.flush = function flush () {\n        if (this.leftOver && this.leftOver.length) {\n            this.push({\n                data : utf8decode(this.leftOver),\n                meta : {}\n            });\n            this.leftOver = null;\n        }\n    };\n\n    return Utf8DecodeWorker;\n}(GenericWorker));\n\n/**\n * A worker to endcode string chunks into utf8 encoded binary chunks.\n * @constructor\n */\nvar Utf8EncodeWorker = /*@__PURE__*/(function (GenericWorker) {\n    function Utf8EncodeWorker() {\n        GenericWorker.call(this, \"utf-8 encode\");\n    }\n\n    if ( GenericWorker ) Utf8EncodeWorker.__proto__ = GenericWorker;\n    Utf8EncodeWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    Utf8EncodeWorker.prototype.constructor = Utf8EncodeWorker;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    Utf8EncodeWorker.prototype.processChunk = function processChunk (chunk) {\n        this.push({\n            data: utf8encode(chunk.data),\n            meta: chunk.meta\n        });\n    };\n\n    return Utf8EncodeWorker;\n}(GenericWorker));\n\n/**\n * A worker which convert chunks to a specified type.\n * @constructor\n * @param {String} destType the destination type.\n */\nvar ConvertWorker = /*@__PURE__*/(function (GenericWorker) {\n    function ConvertWorker(destType) {\n        GenericWorker.call(this, \"ConvertWorker to \" + destType);\n        this.destType = destType;\n    }\n\n    if ( GenericWorker ) ConvertWorker.__proto__ = GenericWorker;\n    ConvertWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    ConvertWorker.prototype.constructor = ConvertWorker;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    ConvertWorker.prototype.processChunk = function processChunk (chunk) {\n        this.push({\n            data: transformTo(this.destType, chunk.data),\n            meta: chunk.meta\n        });\n    };\n\n    return ConvertWorker;\n}(GenericWorker));\n\n/* eslint-disable */\n\n/**\n * Apply the final transformation of the data. If the user wants a Blob for\n * example, it's easier to work with an U8intArray and finally do the\n * ArrayBuffer/Blob conversion.\n * @param {String} type the name of the final type\n * @param {String|Uint8Array|Buffer} content the content to transform\n * @param {String} mimeType the mime type of the content, if applicable.\n * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format.\n */\nfunction transformZipOutput(type, content, mimeType) {\n    switch(type) {\n        case \"blob\" :\n            return newBlob(transformTo(\"arraybuffer\", content), mimeType);\n        case \"base64\" :\n            return encode(content);\n        default :\n            return transformTo(type, content);\n    }\n}\n\n/**\n * Concatenate an array of data of the given type.\n * @param {String} type the type of the data in the given array.\n * @param {Array} dataArray the array containing the data chunks to concatenate\n * @return {String|Uint8Array|Buffer} the concatenated data\n * @throws Error if the asked type is unsupported\n */\nfunction concat (type, dataArray) {\n    var i, index = 0, res = null, totalLength = 0;\n    for(i = 0; i < dataArray.length; i++) {\n        totalLength += dataArray[i].length;\n    }\n    switch(type) {\n        case \"string\":\n            return dataArray.join(\"\");\n          case \"array\":\n            return Array.prototype.concat.apply([], dataArray);\n        case \"uint8array\":\n            res = new Uint8Array(totalLength);\n            for(i = 0; i < dataArray.length; i++) {\n                res.set(dataArray[i], index);\n                index += dataArray[i].length;\n            }\n            return res;\n        default:\n            throw new Error(\"concat : unsupported type '\"  + type + \"'\");\n    }\n}\n\n/**\n * Listen a StreamHelper, accumulate its content and concatenate it into a\n * complete block.\n * @param {StreamHelper} helper the helper to use.\n * @param {Function} updateCallback a callback called on each update. Called\n * with one arg :\n * - the metadata linked to the update received.\n * @return Promise the promise for the accumulation.\n */\nfunction accumulate(helper, updateCallback) {\n    return new external.Promise(function (resolve, reject){\n        var dataArray = [];\n        var chunkType = helper._internalType,\n            resultType = helper._outputType,\n            mimeType = helper._mimeType;\n        helper\n        .on('data', function (data, meta) {\n            dataArray.push(data);\n            if(updateCallback) {\n                updateCallback(meta);\n            }\n        })\n        .on('error', function(err) {\n            dataArray = [];\n            reject(err);\n        })\n        .on('end', function (){\n            try {\n                var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType);\n                resolve(result);\n            } catch (e) {\n                reject(e);\n            }\n            dataArray = [];\n        })\n        .resume();\n    });\n}\n\n/**\n * An helper to easily use workers outside of JSZip.\n * @constructor\n * @param {Worker} worker the worker to wrap\n * @param {String} outputType the type of data expected by the use\n * @param {String} mimeType the mime type of the content, if applicable.\n */\nvar StreamHelper = function StreamHelper (worker, outputType, mimeType) {\n    var internalType = outputType;\n    switch(outputType) {\n        case \"blob\":\n        case \"arraybuffer\":\n            internalType = \"uint8array\";\n        break;\n        case \"base64\":\n            internalType = \"string\";\n        break;\n    }\n\n    try {\n        // the type used internally\n        this._internalType = internalType;\n        // the type used to output results\n        this._outputType = outputType;\n        // the mime type\n        this._mimeType = mimeType;\n        checkSupport(internalType);\n        this._worker = worker.pipe(new ConvertWorker(internalType));\n        // the last workers can be rewired without issues but we need to\n        // prevent any updates on previous workers.\n        worker.lock();\n    } catch(e) {\n        this._worker = new GenericWorker(\"error\");\n        this._worker.error(e);\n    }\n};\n\n/**\n * Listen a StreamHelper, accumulate its content and concatenate it into a\n * complete block.\n * @param {Function} updateCb the update callback.\n * @return Promise the promise for the accumulation.\n */\nStreamHelper.prototype.accumulate = function accumulate$1 (updateCb) {\n    return accumulate(this, updateCb);\n};\n\n/**\n * Add a listener on an event triggered on a stream.\n * @param {String} evt the name of the event\n * @param {Function} fn the listener\n * @return {StreamHelper} the current helper.\n */\nStreamHelper.prototype.on = function on (evt, fn) {\n    var self = this;\n\n    if(evt === \"data\") {\n        this._worker.on(evt, function (chunk) {\n            fn.call(self, chunk.data, chunk.meta);\n        });\n    } else {\n        this._worker.on(evt, function () {\n            delay(fn, arguments, self);\n        });\n    }\n    return this;\n};\n\n/**\n * Resume the flow of chunks.\n * @return {StreamHelper} the current helper.\n */\nStreamHelper.prototype.resume = function resume () {\n    delay(this._worker.resume, [], this._worker);\n    return this;\n};\n\n/**\n * Pause the flow of chunks.\n * @return {StreamHelper} the current helper.\n */\nStreamHelper.prototype.pause = function pause () {\n    this._worker.pause();\n    return this;\n};\n\nvar base64 = false;\nvar binary = false;\nvar dir = false;\nvar createFolders = true;\nvar date = null;\nvar compression = null;\nvar compressionOptions = null;\nvar comment = null;\nvar unixPermissions = null;\nvar dosPermissions = null;\n\nvar defaults = /*#__PURE__*/Object.freeze({\n    __proto__: null,\n    base64: base64,\n    binary: binary,\n    dir: dir,\n    createFolders: createFolders,\n    date: date,\n    compression: compression,\n    compressionOptions: compressionOptions,\n    comment: comment,\n    unixPermissions: unixPermissions,\n    dosPermissions: dosPermissions\n});\n\n/* eslint-disable */\n\n// the size of the generated chunks\n// TODO expose this as a public variable\nvar DEFAULT_BLOCK_SIZE = 16 * 1024;\n\n/**\n * A worker that reads a content and emits chunks.\n * @constructor\n * @param {Promise} dataP the promise of the data to split\n */\nvar DataWorker = /*@__PURE__*/(function (GenericWorker) {\n    function DataWorker(dataP) {\n        GenericWorker.call(this, \"DataWorker\");\n        var self = this;\n        this.dataIsReady = false;\n        this.index = 0;\n        this.max = 0;\n        this.data = null;\n        this.type = \"\";\n\n        this._tickScheduled = false;\n\n        dataP.then(function (data) {\n            self.dataIsReady = true;\n            self.data = data;\n            self.max = data && data.length || 0;\n            self.type = getTypeOf(data);\n            if(!self.isPaused) {\n                self._tickAndRepeat();\n            }\n        }, function (e) {\n            self.error(e);\n        });\n    }\n\n    if ( GenericWorker ) DataWorker.__proto__ = GenericWorker;\n    DataWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    DataWorker.prototype.constructor = DataWorker;\n\n    /**\n     * @see GenericWorker.cleanUp\n     */\n    DataWorker.prototype.cleanUp = function cleanUp () {\n        GenericWorker.prototype.cleanUp.call(this);\n        this.data = null;\n    };\n\n    /**\n     * @see GenericWorker.resume\n     */\n    DataWorker.prototype.resume = function resume () {\n        if(!GenericWorker.prototype.resume.call(this)) {\n            return false;\n        }\n\n        if (!this._tickScheduled && this.dataIsReady) {\n            this._tickScheduled = true;\n            delay(this._tickAndRepeat, [], this);\n        }\n        return true;\n    };\n\n    /**\n     * Trigger a tick a schedule an other call to this function.\n     */\n    DataWorker.prototype._tickAndRepeat = function _tickAndRepeat () {\n        this._tickScheduled = false;\n        if(this.isPaused || this.isFinished) {\n            return;\n        }\n        this._tick();\n        if(!this.isFinished) {\n            delay(this._tickAndRepeat, [], this);\n            this._tickScheduled = true;\n        }\n    };\n    /**\n     * Read and push a chunk.\n     */\n    DataWorker.prototype._tick = function _tick () {\n\n        if(this.isPaused || this.isFinished) {\n            return false;\n        }\n\n        var size = DEFAULT_BLOCK_SIZE;\n        var data = null, nextIndex = Math.min(this.max, this.index + size);\n        if (this.index >= this.max) {\n            // EOF\n            return this.end();\n        } else {\n            switch(this.type) {\n                case \"string\":\n                    data = this.data.substring(this.index, nextIndex);\n                break;\n                case \"uint8array\":\n                    data = this.data.subarray(this.index, nextIndex);\n                break;\n                case \"array\":\n                    data = this.data.slice(this.index, nextIndex);\n                break;\n            }\n            this.index = nextIndex;\n            return this.push({\n                data : data,\n                meta : {\n                    percent : this.max ? this.index / this.max * 100 : 0\n                }\n            });\n        }\n    };\n\n    return DataWorker;\n}(GenericWorker));\n\n/**\n * A worker which calculate the total length of the data flowing through.\n * @constructor\n * @param {String} propName the name used to expose the length\n */\nvar DataLengthProbe = /*@__PURE__*/(function (GenericWorker) {\n    function DataLengthProbe(propName) {\n        GenericWorker.call(this, \"DataLengthProbe for \" + propName);\n        this.propName = propName;\n        this.withStreamInfo(propName, 0);\n    }\n\n    if ( GenericWorker ) DataLengthProbe.__proto__ = GenericWorker;\n    DataLengthProbe.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    DataLengthProbe.prototype.constructor = DataLengthProbe;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    DataLengthProbe.prototype.processChunk = function processChunk (chunk) {\n        if (chunk) {\n            var length = this.streamInfo[this.propName] || 0;\n            this.streamInfo[this.propName] = length + chunk.data.length;\n        }\n        GenericWorker.prototype.processChunk.call(this, chunk);\n    };\n\n    return DataLengthProbe;\n}(GenericWorker));\n\n/* eslint-disable */\n\n/**\n * The following functions come from pako, from pako/lib/zlib/crc32.js\n * released under the MIT license, see pako https://github.com/nodeca/pako/\n */\n\nvar makeTable = function() {\n    // Use ordinary array, since untyped makes no boost here\n    var table = [];\n\n    for (var n =0; n < 256; n++){\n        var c = n;\n        for(var k =0; k < 8; k++){\n            c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n        }\n        table[n] = c;\n    }\n\n    // Memoize table on first call.\n    makeTable = function() {\n        return table;\n    };\n\n    return table;\n};\n\nfunction crc32(crc, buf, len, pos) {\n    var t = makeTable();\n    var end = pos + len;\n\n    crc = crc ^ (-1);\n\n    for (var i = pos; i < end; i++ ) {\n        crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];\n    }\n\n    return (crc ^ (-1)); // >>> 0;\n}\n\n// That's all for the pako functions.\n\n/**\n * Compute the crc32 of a string.\n * This is almost the same as the function crc32, but for strings. Using the\n * same function for the two use cases leads to horrible performances.\n * @param {Number} crc the starting value of the crc.\n * @param {String} str the string to use.\n * @param {Number} len the length of the string.\n * @param {Number} pos the starting position for the crc32 computation.\n * @return {Number} the computed crc32.\n */\nfunction crc32str(crc, str, len, pos) {\n    var t = makeTable();\n    var end = pos + len;\n\n    crc = crc ^ (-1);\n\n    for (var i = pos; i < end; i++ ) {\n        crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF];\n    }\n\n    return (crc ^ (-1)); // >>> 0;\n}\n\nfunction crc32wrapper(input, crc) {\n    if (typeof input === \"undefined\" || !input.length) {\n        return 0;\n    }\n\n    var isArray = getTypeOf(input) !== \"string\";\n\n    if (isArray) {\n        return crc32(crc | 0, input, input.length, 0);\n    } else {\n        return crc32str(crc | 0, input, input.length, 0);\n    }\n}\n\n/**\n * A worker which calculate the crc32 of the data flowing through.\n * @constructor\n */\nvar Crc32Probe = /*@__PURE__*/(function (GenericWorker) {\n    function Crc32Probe() {\n        GenericWorker.call(this, \"Crc32Probe\");\n        this.withStreamInfo(\"crc32\", 0);\n    }\n\n    if ( GenericWorker ) Crc32Probe.__proto__ = GenericWorker;\n    Crc32Probe.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    Crc32Probe.prototype.constructor = Crc32Probe;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    Crc32Probe.prototype.processChunk = function processChunk (chunk) {\n        this.streamInfo.crc32 = crc32wrapper(chunk.data, this.streamInfo.crc32 || 0);\n        this.push(chunk);\n    };\n\n    return Crc32Probe;\n}(GenericWorker));\n\n/* eslint-disable */\n\n/**\n * Represent a compressed object, with everything needed to decompress it.\n * @constructor\n * @param {number} compressedSize the size of the data compressed.\n * @param {number} uncompressedSize the size of the data after decompression.\n * @param {number} crc32 the crc32 of the decompressed file.\n * @param {object} compression the type of compression, see lib/compressions.js.\n * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data.\n */\nvar CompressedObject = function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) {\n    this.compressedSize = compressedSize;\n    this.uncompressedSize = uncompressedSize;\n    this.crc32 = crc32;\n    this.compression = compression;\n    this.compressedContent = data;\n};\n\n/**\n * Create a worker to get the uncompressed content.\n * @return {GenericWorker} the worker.\n */\nCompressedObject.prototype.getContentWorker = function getContentWorker () {\n    var worker = new DataWorker(external.Promise.resolve(this.compressedContent))\n    .pipe(this.compression.uncompressWorker())\n    .pipe(new DataLengthProbe(\"data_length\"));\n\n    var that = this;\n    worker.on(\"end\", function () {\n        if(this.streamInfo['data_length'] !== that.uncompressedSize) {\n            throw new Error(\"Bug : uncompressed data size mismatch\");\n        }\n    });\n    return worker;\n};\n\n/**\n * Create a worker to get the compressed content.\n * @return {GenericWorker} the worker.\n */\nCompressedObject.prototype.getCompressedWorker = function getCompressedWorker () {\n    return new DataWorker(external.Promise.resolve(this.compressedContent))\n    .withStreamInfo(\"compressedSize\", this.compressedSize)\n    .withStreamInfo(\"uncompressedSize\", this.uncompressedSize)\n    .withStreamInfo(\"crc32\", this.crc32)\n    .withStreamInfo(\"compression\", this.compression)\n    ;\n};\n\n/**\n * Chain the given worker with other workers to compress the content with the\n * given compression.\n * @param {GenericWorker} uncompressedWorker the worker to pipe.\n * @param {Object} compression the compression object.\n * @param {Object} compressionOptions the options to use when compressing.\n * @return {GenericWorker} the new worker compressing the content.\n */\nCompressedObject.createWorkerFrom = function createWorkerFrom (uncompressedWorker, compression, compressionOptions) {\n    return uncompressedWorker\n    .pipe(new Crc32Probe())\n    .pipe(new DataLengthProbe(\"uncompressedSize\"))\n    .pipe(compression.compressWorker(compressionOptions))\n    .pipe(new DataLengthProbe(\"compressedSize\"))\n    .withStreamInfo(\"compression\", compression);\n};\n\n/* eslint-disable */\n\n/**\n * A simple object representing a file in the zip file.\n * @constructor\n * @param {string} name the name of the file\n * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data\n * @param {Object} options the options of the file\n */\nvar ZipObject = function ZipObject(name, data, options) {\n    this.name = name;\n    this.dir = options.dir;\n    this.date = options.date;\n    this.comment = options.comment;\n    this.unixPermissions = options.unixPermissions;\n    this.dosPermissions = options.dosPermissions;\n\n    this._data = data;\n    this._dataBinary = options.binary;\n    // keep only the compression\n    this.options = {\n        compression : options.compression,\n        compressionOptions : options.compressionOptions\n    };\n};\n\n/**\n * Create an internal stream for the content of this object.\n * @param {String} type the type of each chunk.\n * @return StreamHelper the stream.\n */\nZipObject.prototype.internalStream = function internalStream (type) {\n    var result = null, outputType = \"string\";\n    try {\n        if (!type) {\n            throw new Error(\"No output type specified.\");\n        }\n        outputType = type.toLowerCase();\n        var askUnicodeString = outputType === \"string\" || outputType === \"text\";\n        if (outputType === \"binarystring\" || outputType === \"text\") {\n            outputType = \"string\";\n        }\n        result = this._decompressWorker();\n\n        var isUnicodeString = !this._dataBinary;\n\n        if (isUnicodeString && !askUnicodeString) {\n            result = result.pipe(new Utf8EncodeWorker());\n        }\n        if (!isUnicodeString && askUnicodeString) {\n            result = result.pipe(new Utf8DecodeWorker());\n        }\n    } catch (e) {\n        result = new GenericWorker(\"error\");\n        result.error(e);\n    }\n\n    return new StreamHelper(result, outputType, \"\");\n};\n\n/**\n * Prepare the content in the asked type.\n * @param {String} type the type of the result.\n * @param {Function} onUpdate a function to call on each internal update.\n * @return Promise the promise of the result.\n */\nZipObject.prototype.async = function async (type, onUpdate) {\n    return this.internalStream(type).accumulate(onUpdate);\n};\n\n/**\n * Return a worker for the compressed content.\n * @private\n * @param {Object} compression the compression object to use.\n * @param {Object} compressionOptions the options to use when compressing.\n * @return Worker the worker.\n */\nZipObject.prototype._compressWorker = function _compressWorker (compression, compressionOptions) {\n    if (\n        this._data instanceof CompressedObject &&\n        this._data.compression.magic === compression.magic\n    ) {\n        return this._data.getCompressedWorker();\n    } else {\n        var result = this._decompressWorker();\n        if(!this._dataBinary) {\n            result = result.pipe(new Utf8EncodeWorker());\n        }\n        return CompressedObject.createWorkerFrom(result, compression, compressionOptions);\n    }\n};\n\n/**\n * Return a worker for the decompressed content.\n * @private\n * @return Worker the worker.\n */\nZipObject.prototype._decompressWorker = function _decompressWorker () {\n    if (this._data instanceof CompressedObject) {\n        return this._data.getContentWorker();\n    } else if (this._data instanceof GenericWorker) {\n        return this._data;\n    } else {\n        return new DataWorker(this._data);\n    }\n};\n\nvar arrayType = function() {\n    var useTypedArray = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined');\n    var resolved = useTypedArray ? \"uint8array\" : \"array\";\n\n    arrayType = function() {\n        return resolved;\n    };\n};\n\n/**\n * Create a worker that uses pako to inflate/deflate.\n * @constructor\n * @param {String} action the name of the pako function to call : either \"Deflate\" or \"Inflate\".\n * @param {Object} options the options to use when (de)compressing.\n */\nvar FlateWorker = /*@__PURE__*/(function (GenericWorker) {\n    function FlateWorker(action, options) {\n        GenericWorker.call(this, \"FlateWorker/\" + action);\n\n        this._pako = null;\n        this._pakoAction = action;\n        this._pakoOptions = options;\n        // the `meta` object from the last chunk received\n        // this allow this worker to pass around metadata\n        this.meta = {};\n    }\n\n    if ( GenericWorker ) FlateWorker.__proto__ = GenericWorker;\n    FlateWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    FlateWorker.prototype.constructor = FlateWorker;\n\n    /**\n     * @see GenericWorker.processChunk\n     */\n    FlateWorker.prototype.processChunk = function processChunk (chunk) {\n        this.meta = chunk.meta;\n        if (this._pako === null) {\n            this._createPako();\n        }\n        this._pako.push(transformTo(arrayType(), chunk.data), false);\n    };\n\n    /**\n     * @see GenericWorker.flush\n     */\n    FlateWorker.prototype.flush = function flush () {\n        GenericWorker.prototype.flush.call(this);\n        if (this._pako === null) {\n            this._createPako();\n        }\n        this._pako.push([], true);\n    };\n    /**\n     * @see GenericWorker.cleanUp\n     */\n    FlateWorker.prototype.cleanUp = function cleanUp () {\n        GenericWorker.prototype.cleanUp.call(this);\n        this._pako = null;\n    };\n\n    /**\n     * Create the _pako object.\n     * TODO: lazy-loading this object isn't the best solution but it's the\n     * quickest. The best solution is to lazy-load the worker list. See also the\n     * issue #446.\n     */\n    FlateWorker.prototype._createPako = function _createPako () {\n        var this$1$1 = this;\n\n        var params = {\n            raw: true,\n            level: this._pakoOptions.level || -1 // default compression\n        };\n        this._pako = this._pakoAction === 'Deflate' ? new Deflate(params) : new Inflate(params);\n        this._pako.onData = function (data) {\n            this$1$1.push({\n                data: data,\n                meta: this$1$1.meta\n            });\n        };\n    };\n\n    return FlateWorker;\n}(GenericWorker));\n\nvar DEFLATE = {\n    magic: \"\\x08\\x00\",\n    compressWorker: function(compressionOptions) {\n        return new FlateWorker(\"Deflate\", compressionOptions);\n    },\n\n    uncompressWorker: function() {\n        return new FlateWorker(\"Inflate\", {});\n    }\n};\n\nvar STORE = {\n    magic: \"\\x00\\x00\",\n    compressWorker: function() {\n        return new GenericWorker(\"STORE compression\");\n    },\n    uncompressWorker: function() {\n        return new GenericWorker(\"STORE decompression\");\n    }\n};\n\nvar compressions = {\n    STORE: STORE,\n    DEFLATE: DEFLATE\n};\n\nvar LOCAL_FILE_HEADER = \"PK\\x03\\x04\";\nvar CENTRAL_FILE_HEADER = \"PK\\x01\\x02\";\nvar CENTRAL_DIRECTORY_END = \"PK\\x05\\x06\";\nvar ZIP64_CENTRAL_DIRECTORY_LOCATOR = \"PK\\x06\\x07\";\nvar ZIP64_CENTRAL_DIRECTORY_END = \"PK\\x06\\x06\";\nvar DATA_DESCRIPTOR = \"PK\\x07\\x08\";\n\n/* eslint-disable */\n\n/**\n * Transform an integer into a string in hexadecimal.\n * @private\n * @param {number} dec the number to convert.\n * @param {number} bytes the number of bytes to generate.\n * @returns {string} the result.\n */\nvar decToHex = function(dec, bytes) {\n    var hex = \"\", i;\n    for (i = 0; i < bytes; i++) {\n        hex += String.fromCharCode(dec & 0xff);\n        dec = dec >>> 8;\n    }\n    return hex;\n};\n\n/**\n * Generate the UNIX part of the external file attributes.\n * @param {Object} unixPermissions the unix permissions or null.\n * @param {Boolean} isDir true if the entry is a directory, false otherwise.\n * @return {Number} a 32 bit integer.\n *\n * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute :\n *\n * TTTTsstrwxrwxrwx0000000000ADVSHR\n * ^^^^____________________________ file type, see zipinfo.c (UNX_*)\n *     ^^^_________________________ setuid, setgid, sticky\n *        ^^^^^^^^^________________ permissions\n *                 ^^^^^^^^^^______ not used ?\n *                           ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only\n */\nvar generateUnixExternalFileAttr = function (unixPermissions, isDir) {\n\n    var result = unixPermissions;\n    if (!unixPermissions) {\n        // I can't use octal values in strict mode, hence the hexa.\n        //  040775 => 0x41fd\n        // 0100664 => 0x81b4\n        result = isDir ? 0x41fd : 0x81b4;\n    }\n    return (result & 0xFFFF) << 16;\n};\n\n/**\n * Generate the DOS part of the external file attributes.\n * @param {Object} dosPermissions the dos permissions or null.\n * @param {Boolean} isDir true if the entry is a directory, false otherwise.\n * @return {Number} a 32 bit integer.\n *\n * Bit 0     Read-Only\n * Bit 1     Hidden\n * Bit 2     System\n * Bit 3     Volume Label\n * Bit 4     Directory\n * Bit 5     Archive\n */\nvar generateDosExternalFileAttr = function (dosPermissions, isDir) {\n\n    // the dir flag is already set for compatibility\n    return (dosPermissions || 0)  & 0x3F;\n};\n\n/**\n * Generate the various parts used in the construction of the final zip file.\n * @param {Object} streamInfo the hash with information about the compressed file.\n * @param {Boolean} streamedContent is the content streamed ?\n * @param {Boolean} streamingEnded is the stream finished ?\n * @param {number} offset the current offset from the start of the zip file.\n * @param {String} platform let's pretend we are this platform (change platform dependents fields)\n * @param {Function} encodeFileName the function to encode the file name / comment.\n * @return {Object} the zip parts.\n */\nvar generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) {\n    var file = streamInfo['file'],\n    compression = streamInfo['compression'],\n    useCustomEncoding = encodeFileName !== utf8encode,\n    encodedFileName = transformTo(\"string\", encodeFileName(file.name)),\n    utfEncodedFileName = transformTo(\"string\", utf8encode(file.name)),\n    comment = file.comment,\n    encodedComment = transformTo(\"string\", encodeFileName(comment)),\n    utfEncodedComment = transformTo(\"string\", utf8encode(comment)),\n    useUTF8ForFileName = utfEncodedFileName.length !== file.name.length,\n    useUTF8ForComment = utfEncodedComment.length !== comment.length,\n    dosTime,\n    dosDate,\n    extraFields = \"\",\n    unicodePathExtraField = \"\",\n    unicodeCommentExtraField = \"\",\n    dir = file.dir,\n    date = file.date;\n\n\n    var dataInfo = {\n        crc32 : 0,\n        compressedSize : 0,\n        uncompressedSize : 0\n    };\n\n    // if the content is streamed, the sizes/crc32 are only available AFTER\n    // the end of the stream.\n    if (!streamedContent || streamingEnded) {\n        dataInfo.crc32 = streamInfo['crc32'];\n        dataInfo.compressedSize = streamInfo['compressedSize'];\n        dataInfo.uncompressedSize = streamInfo['uncompressedSize'];\n    }\n\n    var bitflag = 0;\n    if (streamedContent) {\n        // Bit 3: the sizes/crc32 are set to zero in the local header.\n        // The correct values are put in the data descriptor immediately\n        // following the compressed data.\n        bitflag |= 0x0008;\n    }\n    if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) {\n        // Bit 11: Language encoding flag (EFS).\n        bitflag |= 0x0800;\n    }\n\n\n    var extFileAttr = 0;\n    var versionMadeBy = 0;\n    if (dir) {\n        // dos or unix, we set the dos dir flag\n        extFileAttr |= 0x00010;\n    }\n    if(platform === \"UNIX\") {\n        versionMadeBy = 0x031E; // UNIX, version 3.0\n        extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir);\n    } else { // DOS or other, fallback to DOS\n        versionMadeBy = 0x0014; // DOS, version 2.0\n        extFileAttr |= generateDosExternalFileAttr(file.dosPermissions);\n    }\n\n    // date\n    // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html\n    // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html\n    // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html\n\n    dosTime = date.getUTCHours();\n    dosTime = dosTime << 6;\n    dosTime = dosTime | date.getUTCMinutes();\n    dosTime = dosTime << 5;\n    dosTime = dosTime | date.getUTCSeconds() / 2;\n\n    dosDate = date.getUTCFullYear() - 1980;\n    dosDate = dosDate << 4;\n    dosDate = dosDate | (date.getUTCMonth() + 1);\n    dosDate = dosDate << 5;\n    dosDate = dosDate | date.getUTCDate();\n\n    if (useUTF8ForFileName) {\n        // set the unicode path extra field. unzip needs at least one extra\n        // field to correctly handle unicode path, so using the path is as good\n        // as any other information. This could improve the situation with\n        // other archive managers too.\n        // This field is usually used without the utf8 flag, with a non\n        // unicode path in the header (winrar, winzip). This helps (a bit)\n        // with the messy Windows' default compressed folders feature but\n        // breaks on p7zip which doesn't seek the unicode path extra field.\n        // So for now, UTF-8 everywhere !\n        unicodePathExtraField =\n            // Version\n            decToHex(1, 1) +\n            // NameCRC32\n            decToHex(crc32wrapper(encodedFileName), 4) +\n            // UnicodeName\n            utfEncodedFileName;\n\n        extraFields +=\n            // Info-ZIP Unicode Path Extra Field\n            \"\\x75\\x70\" +\n            // size\n            decToHex(unicodePathExtraField.length, 2) +\n            // content\n            unicodePathExtraField;\n    }\n\n    if(useUTF8ForComment) {\n\n        unicodeCommentExtraField =\n            // Version\n            decToHex(1, 1) +\n            // CommentCRC32\n            decToHex(crc32wrapper(encodedComment), 4) +\n            // UnicodeName\n            utfEncodedComment;\n\n        extraFields +=\n            // Info-ZIP Unicode Path Extra Field\n            \"\\x75\\x63\" +\n            // size\n            decToHex(unicodeCommentExtraField.length, 2) +\n            // content\n            unicodeCommentExtraField;\n    }\n\n    var header = \"\";\n\n    // version needed to extract\n    header += \"\\x0A\\x00\";\n    // general purpose bit flag\n    header += decToHex(bitflag, 2);\n    // compression method\n    header += compression.magic;\n    // last mod file time\n    header += decToHex(dosTime, 2);\n    // last mod file date\n    header += decToHex(dosDate, 2);\n    // crc-32\n    header += decToHex(dataInfo.crc32, 4);\n    // compressed size\n    header += decToHex(dataInfo.compressedSize, 4);\n    // uncompressed size\n    header += decToHex(dataInfo.uncompressedSize, 4);\n    // file name length\n    header += decToHex(encodedFileName.length, 2);\n    // extra field length\n    header += decToHex(extraFields.length, 2);\n\n\n    var fileRecord = LOCAL_FILE_HEADER + header + encodedFileName + extraFields;\n\n    var dirRecord = CENTRAL_FILE_HEADER +\n        // version made by (00: DOS)\n        decToHex(versionMadeBy, 2) +\n        // file header (common to file and central directory)\n        header +\n        // file comment length\n        decToHex(encodedComment.length, 2) +\n        // disk number start\n        \"\\x00\\x00\" +\n        // internal file attributes TODO\n        \"\\x00\\x00\" +\n        // external file attributes\n        decToHex(extFileAttr, 4) +\n        // relative offset of local header\n        decToHex(offset, 4) +\n        // file name\n        encodedFileName +\n        // extra field\n        extraFields +\n        // file comment\n        encodedComment;\n\n    return {\n        fileRecord: fileRecord,\n        dirRecord: dirRecord\n    };\n};\n\n/**\n * Generate the EOCD record.\n * @param {Number} entriesCount the number of entries in the zip file.\n * @param {Number} centralDirLength the length (in bytes) of the central dir.\n * @param {Number} localDirLength the length (in bytes) of the local dir.\n * @param {String} comment the zip file comment as a binary string.\n * @param {Function} encodeFileName the function to encode the comment.\n * @return {String} the EOCD record.\n */\nvar generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) {\n    var dirEnd = \"\";\n    var encodedComment = transformTo(\"string\", encodeFileName(comment));\n\n    // end of central dir signature\n    dirEnd = CENTRAL_DIRECTORY_END +\n        // number of this disk\n        \"\\x00\\x00\" +\n        // number of the disk with the start of the central directory\n        \"\\x00\\x00\" +\n        // total number of entries in the central directory on this disk\n        decToHex(entriesCount, 2) +\n        // total number of entries in the central directory\n        decToHex(entriesCount, 2) +\n        // size of the central directory   4 bytes\n        decToHex(centralDirLength, 4) +\n        // offset of start of central directory with respect to the starting disk number\n        decToHex(localDirLength, 4) +\n        // .ZIP file comment length\n        decToHex(encodedComment.length, 2) +\n        // .ZIP file comment\n        encodedComment;\n\n    return dirEnd;\n};\n\n/**\n * Generate data descriptors for a file entry.\n * @param {Object} streamInfo the hash generated by a worker, containing information\n * on the file entry.\n * @return {String} the data descriptors.\n */\nvar generateDataDescriptors = function (streamInfo) {\n    var descriptor = \"\";\n    descriptor = DATA_DESCRIPTOR +\n        // crc-32                          4 bytes\n        decToHex(streamInfo['crc32'], 4) +\n        // compressed size                 4 bytes\n        decToHex(streamInfo['compressedSize'], 4) +\n        // uncompressed size               4 bytes\n        decToHex(streamInfo['uncompressedSize'], 4);\n\n    return descriptor;\n};\n\n\n/**\n * A worker to concatenate other workers to create a zip file.\n * @param {Boolean} streamFiles `true` to stream the content of the files,\n * `false` to accumulate it.\n * @param {String} comment the comment to use.\n * @param {String} platform the platform to use, \"UNIX\" or \"DOS\".\n * @param {Function} encodeFileName the function to encode file names and comments.\n */\nvar ZipFileWorker = /*@__PURE__*/(function (GenericWorker) {\n    function ZipFileWorker(streamFiles, comment, platform, encodeFileName) {\n        GenericWorker.call(this, \"ZipFileWorker\");\n        // The number of bytes written so far. This doesn't count accumulated chunks.\n        this.bytesWritten = 0;\n        // The comment of the zip file\n        this.zipComment = comment;\n        // The platform \"generating\" the zip file.\n        this.zipPlatform = platform;\n        // the function to encode file names and comments.\n        this.encodeFileName = encodeFileName;\n        // Should we stream the content of the files ?\n        this.streamFiles = streamFiles;\n        // If `streamFiles` is false, we will need to accumulate the content of the\n        // files to calculate sizes / crc32 (and write them *before* the content).\n        // This boolean indicates if we are accumulating chunks (it will change a lot\n        // during the lifetime of this worker).\n        this.accumulate = false;\n        // The buffer receiving chunks when accumulating content.\n        this.contentBuffer = [];\n        // The list of generated directory records.\n        this.dirRecords = [];\n        // The offset (in bytes) from the beginning of the zip file for the current source.\n        this.currentSourceOffset = 0;\n        // The total number of entries in this zip file.\n        this.entriesCount = 0;\n        // the name of the file currently being added, null when handling the end of the zip file.\n        // Used for the emitted metadata.\n        this.currentFile = null;\n\n        this._sources = [];\n    }\n\n    if ( GenericWorker ) ZipFileWorker.__proto__ = GenericWorker;\n    ZipFileWorker.prototype = Object.create( GenericWorker && GenericWorker.prototype );\n    ZipFileWorker.prototype.constructor = ZipFileWorker;\n\n    /**\n     * @see GenericWorker.push\n     */\n    ZipFileWorker.prototype.push = function push (chunk) {\n\n        var currentFilePercent = chunk.meta.percent || 0;\n        var entriesCount = this.entriesCount;\n        var remainingFiles = this._sources.length;\n\n        if(this.accumulate) {\n            this.contentBuffer.push(chunk);\n        } else {\n            this.bytesWritten += chunk.data.length;\n\n            GenericWorker.prototype.push.call(this, {\n                data : chunk.data,\n                meta : {\n                    currentFile : this.currentFile,\n                    percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100\n                }\n            });\n        }\n    };\n\n    /**\n     * The worker started a new source (an other worker).\n     * @param {Object} streamInfo the streamInfo object from the new source.\n     */\n    ZipFileWorker.prototype.openedSource = function openedSource (streamInfo) {\n        this.currentSourceOffset = this.bytesWritten;\n        this.currentFile = streamInfo['file'].name;\n\n        var streamedContent = this.streamFiles && !streamInfo['file'].dir;\n\n        // don't stream folders (because they don't have any content)\n        if(streamedContent) {\n            var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);\n            this.push({\n                data : record.fileRecord,\n                meta : {percent:0}\n            });\n        } else {\n            // we need to wait for the whole file before pushing anything\n            this.accumulate = true;\n        }\n    };\n\n    /**\n     * The worker finished a source (an other worker).\n     * @param {Object} streamInfo the streamInfo object from the finished source.\n     */\n    ZipFileWorker.prototype.closedSource = function closedSource (streamInfo) {\n        this.accumulate = false;\n        var streamedContent = this.streamFiles && !streamInfo['file'].dir;\n        var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);\n\n        this.dirRecords.push(record.dirRecord);\n        if(streamedContent) {\n            // after the streamed file, we put data descriptors\n            this.push({\n                data : generateDataDescriptors(streamInfo),\n                meta : {percent:100}\n            });\n        } else {\n            // the content wasn't streamed, we need to push everything now\n            // first the file record, then the content\n            this.push({\n                data : record.fileRecord,\n                meta : {percent:0}\n            });\n            while(this.contentBuffer.length) {\n                this.push(this.contentBuffer.shift());\n            }\n        }\n        this.currentFile = null;\n    };\n\n    /**\n     * @see GenericWorker.flush\n     */\n    ZipFileWorker.prototype.flush = function flush () {\n\n        var localDirLength = this.bytesWritten;\n        for(var i = 0; i < this.dirRecords.length; i++) {\n            this.push({\n                data : this.dirRecords[i],\n                meta : {percent:100}\n            });\n        }\n        var centralDirLength = this.bytesWritten - localDirLength;\n\n        var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName);\n\n        this.push({\n            data : dirEnd,\n            meta : {percent:100}\n        });\n    };\n\n    /**\n     * Prepare the next source to be read.\n     */\n    ZipFileWorker.prototype.prepareNextSource = function prepareNextSource () {\n        this.previous = this._sources.shift();\n        this.openedSource(this.previous.streamInfo);\n        if (this.isPaused) {\n            this.previous.pause();\n        } else {\n            this.previous.resume();\n        }\n    };\n\n    /**\n     * @see GenericWorker.registerPrevious\n     */\n    ZipFileWorker.prototype.registerPrevious = function registerPrevious (previous) {\n        this._sources.push(previous);\n        var self = this;\n\n        previous.on('data', function (chunk) {\n            self.processChunk(chunk);\n        });\n        previous.on('end', function () {\n            self.closedSource(self.previous.streamInfo);\n            if(self._sources.length) {\n                self.prepareNextSource();\n            } else {\n                self.end();\n            }\n        });\n        previous.on('error', function (e) {\n            self.error(e);\n        });\n        return this;\n    };\n\n    /**\n     * @see GenericWorker.resume\n     */\n    ZipFileWorker.prototype.resume = function resume () {\n        if(!GenericWorker.prototype.resume.call(this)) {\n            return false;\n        }\n\n        if (!this.previous && this._sources.length) {\n            this.prepareNextSource();\n            return true;\n        }\n        if (!this.previous && !this._sources.length && !this.generatedError) {\n            this.end();\n            return true;\n        }\n    };\n\n    /**\n     * @see GenericWorker.error\n     */\n    ZipFileWorker.prototype.error = function error (e) {\n        var sources = this._sources;\n        if(!GenericWorker.prototype.error.call(this, e)) {\n            return false;\n        }\n        for(var i = 0; i < sources.length; i++) {\n            try {\n                sources[i].error(e);\n            } catch(e$1) {\n                // the `error` exploded, nothing to do\n            }\n        }\n        return true;\n    };\n\n    /**\n     * @see GenericWorker.lock\n     */\n    ZipFileWorker.prototype.lock = function lock () {\n        GenericWorker.prototype.lock.call(this);\n        var sources = this._sources;\n        for(var i = 0; i < sources.length; i++) {\n            sources[i].lock();\n        }\n    };\n\n    return ZipFileWorker;\n}(GenericWorker));\n\n/* eslint-disable */\n\n/**\n * Find the compression to use.\n * @param {String} fileCompression the compression defined at the file level, if any.\n * @param {String} zipCompression the compression defined at the load() level.\n * @return {Object} the compression object to use.\n */\nvar getCompression = function (fileCompression, zipCompression) {\n\n    var compressionName = fileCompression || zipCompression;\n    var compression = compressions[compressionName];\n    if (!compression) {\n        throw new Error(compressionName + \" is not a valid compression method !\");\n    }\n    return compression;\n};\n\n/**\n * Create a worker to generate a zip file.\n * @param {JSZip} zip the JSZip instance at the right root level.\n * @param {Object} options to generate the zip file.\n * @param {String} comment the comment to use.\n */\nvar generateWorker = function (zip, options, comment) {\n\n    var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName);\n    var entriesCount = 0;\n    try {\n\n        zip.forEach(function (relativePath, file) {\n            entriesCount++;\n            var compression = getCompression(file.options.compression, options.compression);\n            var compressionOptions = file.options.compressionOptions || options.compressionOptions || {};\n            var dir = file.dir, date = file.date;\n\n            file._compressWorker(compression, compressionOptions)\n            .withStreamInfo(\"file\", {\n                name : relativePath,\n                dir : dir,\n                date : date,\n                comment : file.comment || \"\",\n                unixPermissions : file.unixPermissions,\n                dosPermissions : file.dosPermissions\n            })\n            .pipe(zipFileWorker);\n        });\n        zipFileWorker.entriesCount = entriesCount;\n    } catch (e) {\n        zipFileWorker.error(e);\n    }\n\n    return zipFileWorker;\n};\n\n/* eslint-disable */\n\nvar DataReader = function DataReader(data) {\n    this.data = data; // type : see implementation\n    this.length = data.length;\n    this.index = 0;\n    this.zero = 0;\n};\n\n/**\n * Check that the offset will not go too far.\n * @param {string} offset the additional offset to check.\n * @throws {Error} an Error if the offset is out of bounds.\n */\nDataReader.prototype.checkOffset = function checkOffset (offset) {\n    this.checkIndex(this.index + offset);\n};\n\n/**\n * Check that the specified index will not be too far.\n * @param {string} newIndex the index to check.\n * @throws {Error} an Error if the index is out of bounds.\n */\nDataReader.prototype.checkIndex = function checkIndex (newIndex) {\n    if (this.length < this.zero + newIndex || newIndex < 0) {\n        throw new Error(\"End of data reached (data length = \" + this.length + \", asked index = \" + (newIndex) + \"). Corrupted zip ?\");\n    }\n};\n\n/**\n * Change the index.\n * @param {number} newIndex The new index.\n * @throws {Error} if the new index is out of the data.\n */\nDataReader.prototype.setIndex = function setIndex (newIndex) {\n    this.checkIndex(newIndex);\n    this.index = newIndex;\n};\n\n/**\n * Skip the next n bytes.\n * @param {number} n the number of bytes to skip.\n * @throws {Error} if the new index is out of the data.\n */\nDataReader.prototype.skip = function skip (n) {\n    this.setIndex(this.index + n);\n};\n\n/**\n * Get the byte at the specified index.\n * @param {number} i the index to use.\n * @return {number} a byte.\n */\nDataReader.prototype.byteAt = function byteAt (i) {\n    // see implementations\n};\n\n/**\n * Get the next number with a given byte size.\n * @param {number} size the number of bytes to read.\n * @return {number} the corresponding number.\n */\nDataReader.prototype.readInt = function readInt (size) {\n    var result = 0,\n        i;\n    this.checkOffset(size);\n    for (i = this.index + size - 1; i >= this.index; i--) {\n        result = (result << 8) + this.byteAt(i);\n    }\n    this.index += size;\n    return result;\n};\n\n/**\n * Get the next string with a given byte size.\n * @param {number} size the number of bytes to read.\n * @return {string} the corresponding string.\n */\nDataReader.prototype.readString = function readString (size) {\n    return transformTo(\"string\", this.readData(size));\n};\n\n/**\n * Get raw data without conversion, <size> bytes.\n * @param {number} size the number of bytes to read.\n * @return {Object} the raw data, implementation specific.\n */\nDataReader.prototype.readData = function readData (size) {\n    // see implementations\n};\n\n/**\n * Find the last occurrence of a zip signature (4 bytes).\n * @param {string} sig the signature to find.\n * @return {number} the index of the last occurrence, -1 if not found.\n */\nDataReader.prototype.lastIndexOfSignature = function lastIndexOfSignature (sig) {\n    // see implementations\n};\n\n/**\n * Read the signature (4 bytes) at the current position and compare it with sig.\n * @param {string} sig the expected signature\n * @return {boolean} true if the signature matches, false otherwise.\n */\nDataReader.prototype.readAndCheckSignature = function readAndCheckSignature (sig) {\n    // see implementations\n};\n\n/**\n * Get the next date.\n * @return {Date} the date.\n */\nDataReader.prototype.readDate = function readDate () {\n    var dostime = this.readInt(4);\n    return new Date(Date.UTC(\n    ((dostime >> 25) & 0x7f) + 1980, // year\n    ((dostime >> 21) & 0x0f) - 1, // month\n    (dostime >> 16) & 0x1f, // day\n    (dostime >> 11) & 0x1f, // hour\n    (dostime >> 5) & 0x3f, // minute\n    (dostime & 0x1f) << 1)); // second\n};\n\n/* eslint-disable */\n\nvar ArrayReader = /*@__PURE__*/(function (DataReader) {\n    function ArrayReader(data) {\n        DataReader.call(this, data);\n        for(var i = 0; i < this.data.length; i++) {\n            data[i] = data[i] & 0xFF;\n        }\n    }\n\n    if ( DataReader ) ArrayReader.__proto__ = DataReader;\n    ArrayReader.prototype = Object.create( DataReader && DataReader.prototype );\n    ArrayReader.prototype.constructor = ArrayReader;\n\n    /**\n     * @see DataReader.byteAt\n     */\n    ArrayReader.prototype.byteAt = function byteAt (i) {\n        return this.data[this.zero + i];\n    };\n\n    /**\n     * @see DataReader.lastIndexOfSignature\n     */\n    ArrayReader.prototype.lastIndexOfSignature = function lastIndexOfSignature (sig) {\n        var sig0 = sig.charCodeAt(0),\n            sig1 = sig.charCodeAt(1),\n            sig2 = sig.charCodeAt(2),\n            sig3 = sig.charCodeAt(3);\n        for (var i = this.length - 4; i >= 0; --i) {\n            if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) {\n                return i - this.zero;\n            }\n        }\n\n        return -1;\n    };\n\n    /**\n     * @see DataReader.readAndCheckSignature\n     */\n    ArrayReader.prototype.readAndCheckSignature = function readAndCheckSignature (sig) {\n        var sig0 = sig.charCodeAt(0),\n            sig1 = sig.charCodeAt(1),\n            sig2 = sig.charCodeAt(2),\n            sig3 = sig.charCodeAt(3),\n            data = this.readData(4);\n        return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3];\n    };\n\n    /**\n     * @see DataReader.readData\n     */\n    ArrayReader.prototype.readData = function readData (size) {\n        this.checkOffset(size);\n        if(size === 0) {\n            return [];\n        }\n        var result = this.data.slice(this.zero + this.index, this.zero + this.index + size);\n        this.index += size;\n        return result;\n    };\n\n    return ArrayReader;\n}(DataReader));\n\nvar StringReader = /*@__PURE__*/(function (DataReader) {\n    function StringReader(data) {\n        DataReader.call(this, data);\n    }\n\n    if ( DataReader ) StringReader.__proto__ = DataReader;\n    StringReader.prototype = Object.create( DataReader && DataReader.prototype );\n    StringReader.prototype.constructor = StringReader;\n\n    /**\n     * @see DataReader.byteAt\n     */\n    StringReader.prototype.byteAt = function byteAt (i) {\n        return this.data.charCodeAt(this.zero + i);\n    };\n\n    /**\n     * @see DataReader.lastIndexOfSignature\n     */\n    StringReader.prototype.lastIndexOfSignature = function lastIndexOfSignature (sig) {\n        return this.data.lastIndexOf(sig) - this.zero;\n    };\n\n    /**\n     * @see DataReader.readAndCheckSignature\n     */\n    StringReader.prototype.readAndCheckSignature = function readAndCheckSignature (sig) {\n        var data = this.readData(4);\n        return sig === data;\n    };\n\n    /**\n     * @see DataReader.readData\n     */\n    StringReader.prototype.readData = function readData (size) {\n        this.checkOffset(size);\n        // this will work because the constructor applied the \"& 0xff\" mask.\n        var result = this.data.slice(this.zero + this.index, this.zero + this.index + size);\n        this.index += size;\n        return result;\n    };\n\n    return StringReader;\n}(DataReader));\n\n/* eslint-disable */\n\nvar Uint8ArrayReader = /*@__PURE__*/(function (ArrayReader) {\n    function Uint8ArrayReader(data) {\n        ArrayReader.call(this, data);\n    }\n\n    if ( ArrayReader ) Uint8ArrayReader.__proto__ = ArrayReader;\n    Uint8ArrayReader.prototype = Object.create( ArrayReader && ArrayReader.prototype );\n    Uint8ArrayReader.prototype.constructor = Uint8ArrayReader;\n\n    /**\n     * @see DataReader.readData\n     */\n    Uint8ArrayReader.prototype.readData = function readData (size) {\n        this.checkOffset(size);\n        if(size === 0) {\n            // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of [].\n            return new Uint8Array(0);\n        }\n        var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size);\n        this.index += size;\n        return result;\n    };\n\n    return Uint8ArrayReader;\n}(ArrayReader));\n\n/**\n * Create a reader adapted to the data.\n * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read.\n * @return {DataReader} the data reader.\n */\nfunction readerFor(data) {\n    var type = getTypeOf(data);\n    checkSupport(type);\n    if (type === \"string\" && !support.uint8array) {\n        return new StringReader(data);\n    }\n    if (support.uint8array) {\n        return new Uint8ArrayReader(transformTo(\"uint8array\", data));\n    }\n    return new ArrayReader(transformTo(\"array\", data));\n}\n\n/* eslint-disable */\n\nvar MADE_BY_DOS = 0x00;\nvar MADE_BY_UNIX = 0x03;\n\n/**\n * Find a compression registered in JSZip.\n * @param {string} compressionMethod the method magic to find.\n * @return {Object|null} the JSZip compression object, null if none found.\n */\nvar findCompression = function(compressionMethod) {\n    for (var method in compressions) {\n        if (!compressions.hasOwnProperty(method)) {\n            continue;\n        }\n        if (compressions[method].magic === compressionMethod) {\n            return compressions[method];\n        }\n    }\n    return null;\n};\n\n// class ZipEntry {{{\n/**\n * An entry in the zip file.\n * @constructor\n * @param {Object} options Options of the current file.\n * @param {Object} loadOptions Options for loading the stream.\n */\nvar ZipEntry = function ZipEntry(options, loadOptions) {\n    this.options = options;\n    this.loadOptions = loadOptions;\n};\n\n/**\n * say if the file is encrypted.\n * @return {boolean} true if the file is encrypted, false otherwise.\n */\nZipEntry.prototype.isEncrypted = function isEncrypted () {\n    // bit 1 is set\n    return (this.bitFlag & 0x0001) === 0x0001;\n};\n\n/**\n * say if the file has utf-8 filename/comment.\n * @return {boolean} true if the filename/comment is in utf-8, false otherwise.\n */\nZipEntry.prototype.useUTF8 = function useUTF8 () {\n    // bit 11 is set\n    return (this.bitFlag & 0x0800) === 0x0800;\n};\n\n/**\n * Read the local part of a zip file and add the info in this object.\n * @param {DataReader} reader the reader to use.\n */\nZipEntry.prototype.readLocalPart = function readLocalPart (reader) {\n    var compression, localExtraFieldsLength;\n\n    // we already know everything from the central dir !\n    // If the central dir data are false, we are doomed.\n    // On the bright side, the local part is scary  : zip64, data descriptors, both, etc.\n    // The less data we get here, the more reliable this should be.\n    // Let's skip the whole header and dash to the data !\n    reader.skip(22);\n    // in some zip created on windows, the filename stored in the central dir contains \\ instead of /.\n    // Strangely, the filename here is OK.\n    // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes\n    // or APPNOTE#4.4.17.1, \"All slashes MUST be forward slashes '/'\") but there are a lot of bad zip generators...\n    // Search \"unzip mismatching \"local\" filename continuing with \"central\" filename version\" on\n    // the internet.\n    //\n    // I think I see the logic here : the central directory is used to display\n    // content and the local directory is used to extract the files. Mixing / and \\\n    // may be used to display \\ to windows users and use / when extracting the files.\n    // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394\n    this.fileNameLength = reader.readInt(2);\n    localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir\n    // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding.\n    this.fileName = reader.readData(this.fileNameLength);\n    reader.skip(localExtraFieldsLength);\n\n    if (this.compressedSize === -1 || this.uncompressedSize === -1) {\n        throw new Error(\"Bug or corrupted zip : didn't get enough information from the central directory \" + \"(compressedSize === -1 || uncompressedSize === -1)\");\n    }\n\n    compression = findCompression(this.compressionMethod);\n    if (compression === null) { // no compression found\n        throw new Error(\"Corrupted zip : compression \" + pretty(this.compressionMethod) + \" unknown (inner file : \" + transformTo(\"string\", this.fileName) + \")\");\n    }\n    this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize));\n};\n\n/**\n * Read the central part of a zip file and add the info in this object.\n * @param {DataReader} reader the reader to use.\n */\nZipEntry.prototype.readCentralPart = function readCentralPart (reader) {\n    this.versionMadeBy = reader.readInt(2);\n    reader.skip(2);\n    // this.versionNeeded = reader.readInt(2);\n    this.bitFlag = reader.readInt(2);\n    this.compressionMethod = reader.readString(2);\n    this.date = reader.readDate();\n    this.crc32 = reader.readInt(4);\n    this.compressedSize = reader.readInt(4);\n    this.uncompressedSize = reader.readInt(4);\n    var fileNameLength = reader.readInt(2);\n    this.extraFieldsLength = reader.readInt(2);\n    this.fileCommentLength = reader.readInt(2);\n    this.diskNumberStart = reader.readInt(2);\n    this.internalFileAttributes = reader.readInt(2);\n    this.externalFileAttributes = reader.readInt(4);\n    this.localHeaderOffset = reader.readInt(4);\n\n    if (this.isEncrypted()) {\n        throw new Error(\"Encrypted zip are not supported\");\n    }\n\n    // will be read in the local part, see the comments there\n    reader.skip(fileNameLength);\n    this.readExtraFields(reader);\n    this.parseZIP64ExtraField(reader);\n    this.fileComment = reader.readData(this.fileCommentLength);\n};\n\n/**\n * Parse the external file attributes and get the unix/dos permissions.\n */\nZipEntry.prototype.processAttributes = function processAttributes () {\n    this.unixPermissions = null;\n    this.dosPermissions = null;\n    var madeBy = this.versionMadeBy >> 8;\n\n    // Check if we have the DOS directory flag set.\n    // We look for it in the DOS and UNIX permissions\n    // but some unknown platform could set it as a compatibility flag.\n    this.dir = this.externalFileAttributes & 0x0010 ? true : false;\n\n    if(madeBy === MADE_BY_DOS) {\n        // first 6 bits (0 to 5)\n        this.dosPermissions = this.externalFileAttributes & 0x3F;\n    }\n\n    if(madeBy === MADE_BY_UNIX) {\n        this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;\n        // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);\n    }\n\n    // fail safe : if the name ends with a / it probably means a folder\n    if (!this.dir && this.fileNameStr.slice(-1) === '/') {\n        this.dir = true;\n    }\n};\n\n/**\n * Parse the ZIP64 extra field and merge the info in the current ZipEntry.\n * @param {DataReader} reader the reader to use.\n */\nZipEntry.prototype.parseZIP64ExtraField = function parseZIP64ExtraField (reader) {\n\n    if (!this.extraFields[0x0001]) {\n        return;\n    }\n\n    // should be something, preparing the extra reader\n    var extraReader = readerFor(this.extraFields[0x0001].value);\n\n    // I really hope that these 64bits integer can fit in 32 bits integer, because js\n    // won't let us have more.\n    if (this.uncompressedSize === MAX_VALUE_32BITS) {\n        this.uncompressedSize = extraReader.readInt(8);\n    }\n    if (this.compressedSize === MAX_VALUE_32BITS) {\n        this.compressedSize = extraReader.readInt(8);\n    }\n    if (this.localHeaderOffset === MAX_VALUE_32BITS) {\n        this.localHeaderOffset = extraReader.readInt(8);\n    }\n    if (this.diskNumberStart === MAX_VALUE_32BITS) {\n        this.diskNumberStart = extraReader.readInt(4);\n    }\n};\n\n/**\n * Read the central part of a zip file and add the info in this object.\n * @param {DataReader} reader the reader to use.\n */\nZipEntry.prototype.readExtraFields = function readExtraFields (reader) {\n    var end = reader.index + this.extraFieldsLength,\n        extraFieldId,\n        extraFieldLength,\n        extraFieldValue;\n\n    if (!this.extraFields) {\n        this.extraFields = {};\n    }\n\n    while (reader.index < end) {\n        extraFieldId = reader.readInt(2);\n        extraFieldLength = reader.readInt(2);\n        extraFieldValue = reader.readData(extraFieldLength);\n\n        this.extraFields[extraFieldId] = {\n            id: extraFieldId,\n            length: extraFieldLength,\n            value: extraFieldValue\n        };\n    }\n};\n\n/**\n * Apply an UTF8 transformation if needed.\n */\nZipEntry.prototype.handleUTF8 = function handleUTF8 () {\n    var decodeParamType = support.uint8array ? \"uint8array\" : \"array\";\n    if (this.useUTF8()) {\n        this.fileNameStr = utf8decode(this.fileName);\n        this.fileCommentStr = utf8decode(this.fileComment);\n    } else {\n        var upath = this.findExtraFieldUnicodePath();\n        if (upath !== null) {\n            this.fileNameStr = upath;\n        } else {\n            // ASCII text or unsupported code page\n            var fileNameByteArray =  transformTo(decodeParamType, this.fileName);\n            this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray);\n        }\n\n        var ucomment = this.findExtraFieldUnicodeComment();\n        if (ucomment !== null) {\n            this.fileCommentStr = ucomment;\n        } else {\n            // ASCII text or unsupported code page\n            var commentByteArray =  transformTo(decodeParamType, this.fileComment);\n            this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray);\n        }\n    }\n};\n\n/**\n * Find the unicode path declared in the extra field, if any.\n * @return {String} the unicode path, null otherwise.\n */\nZipEntry.prototype.findExtraFieldUnicodePath = function findExtraFieldUnicodePath () {\n    var upathField = this.extraFields[0x7075];\n    if (upathField) {\n        var extraReader = readerFor(upathField.value);\n\n        // wrong version\n        if (extraReader.readInt(1) !== 1) {\n            return null;\n        }\n\n        // the crc of the filename changed, this field is out of date.\n        if (crc32wrapper(this.fileName) !== extraReader.readInt(4)) {\n            return null;\n        }\n\n        return utf8decode(extraReader.readData(upathField.length - 5));\n    }\n    return null;\n};\n\n/**\n * Find the unicode comment declared in the extra field, if any.\n * @return {String} the unicode comment, null otherwise.\n */\nZipEntry.prototype.findExtraFieldUnicodeComment = function findExtraFieldUnicodeComment () {\n    var ucommentField = this.extraFields[0x6375];\n    if (ucommentField) {\n        var extraReader = readerFor(ucommentField.value);\n\n        // wrong version\n        if (extraReader.readInt(1) !== 1) {\n            return null;\n        }\n\n        // the crc of the comment changed, this field is out of date.\n        if (crc32wrapper(this.fileComment) !== extraReader.readInt(4)) {\n            return null;\n        }\n\n        return utf8decode(extraReader.readData(ucommentField.length - 5));\n    }\n    return null;\n};\n\n/* eslint-disable */\n\n//  class ZipEntries {{{\n/**\n * All the entries in the zip file.\n * @constructor\n * @param {Object} loadOptions Options for loading the stream.\n */\nvar ZipEntries = function ZipEntries(loadOptions) {\n    this.files = [];\n    this.loadOptions = loadOptions;\n};\n\n/**\n * Check that the reader is on the specified signature.\n * @param {string} expectedSignature the expected signature.\n * @throws {Error} if it is an other signature.\n */\nZipEntries.prototype.checkSignature = function checkSignature (expectedSignature) {\n    if (!this.reader.readAndCheckSignature(expectedSignature)) {\n        this.reader.index -= 4;\n        var signature = this.reader.readString(4);\n        throw new Error(\"Corrupted zip or bug: unexpected signature \" + \"(\" + pretty(signature) + \", expected \" + pretty(expectedSignature) + \")\");\n    }\n};\n\n/**\n * Check if the given signature is at the given index.\n * @param {number} askedIndex the index to check.\n * @param {string} expectedSignature the signature to expect.\n * @return {boolean} true if the signature is here, false otherwise.\n */\nZipEntries.prototype.isSignature = function isSignature (askedIndex, expectedSignature) {\n    var currentIndex = this.reader.index;\n    this.reader.setIndex(askedIndex);\n    var signature = this.reader.readString(4);\n    var result = signature === expectedSignature;\n    this.reader.setIndex(currentIndex);\n    return result;\n};\n\n/**\n * Read the end of the central directory.\n */\nZipEntries.prototype.readBlockEndOfCentral = function readBlockEndOfCentral () {\n    this.diskNumber = this.reader.readInt(2);\n    this.diskWithCentralDirStart = this.reader.readInt(2);\n    this.centralDirRecordsOnThisDisk = this.reader.readInt(2);\n    this.centralDirRecords = this.reader.readInt(2);\n    this.centralDirSize = this.reader.readInt(4);\n    this.centralDirOffset = this.reader.readInt(4);\n\n    this.zipCommentLength = this.reader.readInt(2);\n    // warning : the encoding depends of the system locale\n    // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded.\n    // On a windows machine, this field is encoded with the localized windows code page.\n    var zipComment = this.reader.readData(this.zipCommentLength);\n    var decodeParamType = support.uint8array ? \"uint8array\" : \"array\";\n    // To get consistent behavior with the generation part, we will assume that\n    // this is utf8 encoded unless specified otherwise.\n    var decodeContent = transformTo(decodeParamType, zipComment);\n    this.zipComment = this.loadOptions.decodeFileName(decodeContent);\n};\n\n/**\n * Read the end of the Zip 64 central directory.\n * Not merged with the method readEndOfCentral :\n * The end of central can coexist with its Zip64 brother,\n * I don't want to read the wrong number of bytes !\n */\nZipEntries.prototype.readBlockZip64EndOfCentral = function readBlockZip64EndOfCentral () {\n    this.zip64EndOfCentralSize = this.reader.readInt(8);\n    this.reader.skip(4);\n    // this.versionMadeBy = this.reader.readString(2);\n    // this.versionNeeded = this.reader.readInt(2);\n    this.diskNumber = this.reader.readInt(4);\n    this.diskWithCentralDirStart = this.reader.readInt(4);\n    this.centralDirRecordsOnThisDisk = this.reader.readInt(8);\n    this.centralDirRecords = this.reader.readInt(8);\n    this.centralDirSize = this.reader.readInt(8);\n    this.centralDirOffset = this.reader.readInt(8);\n\n    this.zip64ExtensibleData = {};\n    var extraDataSize = this.zip64EndOfCentralSize - 44,\n        index = 0,\n        extraFieldId,\n        extraFieldLength,\n        extraFieldValue;\n    while (index < extraDataSize) {\n        extraFieldId = this.reader.readInt(2);\n        extraFieldLength = this.reader.readInt(4);\n        extraFieldValue = this.reader.readData(extraFieldLength);\n        this.zip64ExtensibleData[extraFieldId] = {\n            id: extraFieldId,\n            length: extraFieldLength,\n            value: extraFieldValue\n        };\n    }\n};\n\n/**\n * Read the end of the Zip 64 central directory locator.\n */\nZipEntries.prototype.readBlockZip64EndOfCentralLocator = function readBlockZip64EndOfCentralLocator () {\n    this.diskWithZip64CentralDirStart = this.reader.readInt(4);\n    this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);\n    this.disksCount = this.reader.readInt(4);\n    if (this.disksCount > 1) {\n        throw new Error(\"Multi-volumes zip are not supported\");\n    }\n};\n\n/**\n * Read the local files, based on the offset read in the central part.\n */\nZipEntries.prototype.readLocalFiles = function readLocalFiles () {\n    var i, file;\n    for (i = 0; i < this.files.length; i++) {\n        file = this.files[i];\n        this.reader.setIndex(file.localHeaderOffset);\n        this.checkSignature(LOCAL_FILE_HEADER);\n        file.readLocalPart(this.reader);\n        file.handleUTF8();\n        file.processAttributes();\n    }\n};\n\n/**\n * Read the central directory.\n */\nZipEntries.prototype.readCentralDir = function readCentralDir () {\n    var file;\n\n    this.reader.setIndex(this.centralDirOffset);\n    while (this.reader.readAndCheckSignature(CENTRAL_FILE_HEADER)) {\n        file = new ZipEntry({\n            zip64: this.zip64\n        }, this.loadOptions);\n        file.readCentralPart(this.reader);\n        this.files.push(file);\n    }\n\n    if (this.centralDirRecords !== this.files.length) {\n        if (this.centralDirRecords !== 0 && this.files.length === 0) {\n            // We expected some records but couldn't find ANY.\n            // This is really suspicious, as if something went wrong.\n            throw new Error(\"Corrupted zip or bug: expected \" + this.centralDirRecords + \" records in central dir, got \" + this.files.length);\n        }\n    }\n};\n\n/**\n * Read the end of central directory.\n */\nZipEntries.prototype.readEndOfCentral = function readEndOfCentral () {\n    var offset = this.reader.lastIndexOfSignature(CENTRAL_DIRECTORY_END);\n    if (offset < 0) {\n        // Check if the content is a truncated zip or complete garbage.\n        // A \"LOCAL_FILE_HEADER\" is not required at the beginning (auto\n        // extractible zip for example) but it can give a good hint.\n        // If an ajax request was used without responseType, we will also\n        // get unreadable data.\n        var isGarbage = !this.isSignature(0, LOCAL_FILE_HEADER);\n\n        if (isGarbage) {\n            throw new Error(\"Can't find end of central directory : is this a zip file ? \" +\n                            \"If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html\");\n        } else {\n            throw new Error(\"Corrupted zip: can't find end of central directory\");\n        }\n\n    }\n    this.reader.setIndex(offset);\n    var endOfCentralDirOffset = offset;\n    this.checkSignature(CENTRAL_DIRECTORY_END);\n    this.readBlockEndOfCentral();\n\n\n    /* extract from the zip spec :\n        4)  If one of the fields in the end of central directory\n            record is too small to hold required data, the field\n            should be set to -1 (0xFFFF or 0xFFFFFFFF) and the\n            ZIP64 format record should be created.\n        5)  The end of central directory record and the\n            Zip64 end of central directory locator record must\n            reside on the same disk when splitting or spanning\n            an archive.\n     */\n    if (this.diskNumber === MAX_VALUE_16BITS || this.diskWithCentralDirStart === MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === MAX_VALUE_16BITS || this.centralDirRecords === MAX_VALUE_16BITS || this.centralDirSize === MAX_VALUE_32BITS || this.centralDirOffset === MAX_VALUE_32BITS) {\n        this.zip64 = true;\n\n        /*\n        Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from\n        the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents\n        all numbers as 64-bit double precision IEEE 754 floating point numbers.\n        So, we have 53bits for integers and bitwise operations treat everything as 32bits.\n        see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators\n        and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5\n        */\n\n        // should look for a zip64 EOCD locator\n        offset = this.reader.lastIndexOfSignature(ZIP64_CENTRAL_DIRECTORY_LOCATOR);\n        if (offset < 0) {\n            throw new Error(\"Corrupted zip: can't find the ZIP64 end of central directory locator\");\n        }\n        this.reader.setIndex(offset);\n        this.checkSignature(ZIP64_CENTRAL_DIRECTORY_LOCATOR);\n        this.readBlockZip64EndOfCentralLocator();\n\n        // now the zip64 EOCD record\n        if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, ZIP64_CENTRAL_DIRECTORY_END)) {\n            // console.warn(\"ZIP64 end of central directory not where expected.\");\n            this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(ZIP64_CENTRAL_DIRECTORY_END);\n            if (this.relativeOffsetEndOfZip64CentralDir < 0) {\n                throw new Error(\"Corrupted zip: can't find the ZIP64 end of central directory\");\n            }\n        }\n        this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);\n        this.checkSignature(ZIP64_CENTRAL_DIRECTORY_END);\n        this.readBlockZip64EndOfCentral();\n    }\n\n    var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize;\n    if (this.zip64) {\n        expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator\n        expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize;\n    }\n\n    var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset;\n\n    if (extraBytes > 0) {\n        // console.warn(extraBytes, \"extra bytes at beginning or within zipfile\");\n        if (this.isSignature(endOfCentralDirOffset, CENTRAL_FILE_HEADER)) ; else {\n            // the offset is wrong, update the \"zero\" of the reader\n            // this happens if data has been prepended (crx files for example)\n            this.reader.zero = extraBytes;\n        }\n    } else if (extraBytes < 0) {\n        throw new Error(\"Corrupted zip: missing \" + Math.abs(extraBytes) + \" bytes.\");\n    }\n};\n\nZipEntries.prototype.prepareReader = function prepareReader (data) {\n    this.reader = readerFor(data);\n};\n\n/**\n * Read a zip file and create ZipEntries.\n * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.\n */\nZipEntries.prototype.load = function load (data) {\n    this.prepareReader(data);\n    this.readEndOfCentral();\n    this.readCentralDir();\n    this.readLocalFiles();\n};\n\n/* eslint-disable */\n\n/**\n * Check the CRC32 of an entry.\n * @param {ZipEntry} zipEntry the zip entry to check.\n * @return {Promise} the result.\n */\nfunction checkEntryCRC32(zipEntry) {\n    return new external.Promise(function (resolve, reject) {\n        var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe());\n        worker.on(\"error\", function (e) {\n            reject(e);\n        })\n        .on(\"end\", function () {\n            if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) {\n                reject(new Error(\"Corrupted zip : CRC32 mismatch\"));\n            } else {\n                resolve();\n            }\n        })\n        .resume();\n    });\n}\n\nfunction load(data, options) {\n    var zip = this;\n    options = extend(options || {}, {\n        base64: false,\n        checkCRC32: false,\n        optimizedBinaryString: false,\n        createFolders: false,\n        decodeFileName: utf8decode\n    });\n\n    return prepareContent(\"the loaded zip file\", data, true, options.optimizedBinaryString, options.base64)\n    .then(function(data) {\n        var zipEntries = new ZipEntries(options);\n        zipEntries.load(data);\n        return zipEntries;\n    }).then(function checkCRC32(zipEntries) {\n        var promises = [external.Promise.resolve(zipEntries)];\n        var files = zipEntries.files;\n        if (options.checkCRC32) {\n            for (var i = 0; i < files.length; i++) {\n                promises.push(checkEntryCRC32(files[i]));\n            }\n        }\n        return external.Promise.all(promises);\n    }).then(function addFiles(results) {\n        var zipEntries = results.shift();\n        var files = zipEntries.files;\n        for (var i = 0; i < files.length; i++) {\n            var input = files[i];\n            zip.file(input.fileNameStr, input.decompressed, {\n                binary: true,\n                optimizedBinaryString: true,\n                date: input.date,\n                dir: input.dir,\n                comment : input.fileCommentStr.length ? input.fileCommentStr : null,\n                unixPermissions : input.unixPermissions,\n                dosPermissions : input.dosPermissions,\n                createFolders: options.createFolders\n            });\n        }\n        if (zipEntries.zipComment.length) {\n            zip.comment = zipEntries.zipComment;\n        }\n\n        return zip;\n    });\n}\n\n/* eslint-disable */\n\n/**\n * Add a file in the current folder.\n * @private\n * @param {string} name the name of the file\n * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file\n * @param {Object} originalOptions the options of the file\n * @return {Object} the new file.\n */\nvar fileAdd = function(name, data, originalOptions) {\n    // be sure sub folders exist\n    var dataType = getTypeOf(data),\n        parent;\n\n\n    /*\n     * Correct options.\n     */\n\n    var o = extend(originalOptions || {}, defaults);\n    o.date = o.date || new Date();\n    if (o.compression !== null) {\n        o.compression = o.compression.toUpperCase();\n    }\n\n    if (typeof o.unixPermissions === \"string\") {\n        o.unixPermissions = parseInt(o.unixPermissions, 8);\n    }\n\n    // UNX_IFDIR  0040000 see zipinfo.c\n    if (o.unixPermissions && (o.unixPermissions & 0x4000)) {\n        o.dir = true;\n    }\n    // Bit 4    Directory\n    if (o.dosPermissions && (o.dosPermissions & 0x0010)) {\n        o.dir = true;\n    }\n\n    if (o.dir) {\n        name = forceTrailingSlash(name);\n    }\n    if (o.createFolders && (parent = parentFolder(name))) {\n        folderAdd.call(this, parent, true);\n    }\n\n    var isUnicodeString = dataType === \"string\" && o.binary === false && o.base64 === false;\n    if (!originalOptions || typeof originalOptions.binary === \"undefined\") {\n        o.binary = !isUnicodeString;\n    }\n\n\n    var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0;\n\n    if (isCompressedEmpty || o.dir || !data || data.length === 0) {\n        o.base64 = false;\n        o.binary = true;\n        data = \"\";\n        o.compression = \"STORE\";\n        dataType = \"string\";\n    }\n\n    /*\n     * Convert content to fit.\n     */\n\n    var zipObjectContent = null;\n    if (data instanceof CompressedObject || data instanceof GenericWorker) {\n        zipObjectContent = data;\n    } else {\n        zipObjectContent = prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64);\n    }\n\n    var object = new ZipObject(name, zipObjectContent, o);\n    this.files[name] = object;\n    /*\n    TODO: we can't throw an exception because we have async promises\n    (we can have a promise of a Date() for example) but returning a\n    promise is useless because file(name, data) returns the JSZip\n    object for chaining. Should we break that to allow the user\n    to catch the error ?\n\n    return external.Promise.resolve(zipObjectContent)\n    .then(function () {\n        return object;\n    });\n    */\n};\n\n/**\n * Find the parent folder of the path.\n * @private\n * @param {string} path the path to use\n * @return {string} the parent folder, or \"\"\n */\nvar parentFolder = function (path) {\n    if (path.slice(-1) === '/') {\n        path = path.substring(0, path.length - 1);\n    }\n    var lastSlash = path.lastIndexOf('/');\n    return (lastSlash > 0) ? path.substring(0, lastSlash) : \"\";\n};\n\n/**\n * Returns the path with a slash at the end.\n * @private\n * @param {String} path the path to check.\n * @return {String} the path with a trailing slash.\n */\nvar forceTrailingSlash = function(path) {\n    // Check the name ends with a /\n    if (path.slice(-1) !== \"/\") {\n        path += \"/\"; // IE doesn't like substr(-1)\n    }\n    return path;\n};\n\n/**\n * Add a (sub) folder in the current folder.\n * @private\n * @param {string} name the folder's name\n * @param {boolean=} [createFolders] If true, automatically create sub\n *  folders. Defaults to false.\n * @return {Object} the new folder.\n */\nvar folderAdd = function(name, createFolders$1) {\n    createFolders$1 = (typeof createFolders$1 !== 'undefined') ? createFolders$1 : createFolders;\n\n    name = forceTrailingSlash(name);\n\n    // Does this folder already exist?\n    if (!this.files[name]) {\n        fileAdd.call(this, name, null, {\n            dir: true,\n            createFolders: createFolders$1\n        });\n    }\n    return this.files[name];\n};\n\n/**\n* Cross-window, cross-Node-context regular expression detection\n* @param  {Object}  object Anything\n* @return {Boolean}        true if the object is a regular expression,\n* false otherwise\n*/\nfunction isRegExp(object) {\n    return Object.prototype.toString.call(object) === \"[object RegExp]\";\n}\n\n/**\n * Representation a of zip file in js\n * @constructor\n */\nvar JSZip = function JSZip() {\n    if (arguments.length) {\n        throw new Error(\"The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.\");\n    }\n\n    // object containing the files :\n    // {\n    //   \"folder/\" : {...},\n    //   \"folder/data.txt\" : {...}\n    // }\n    // NOTE: we use a null prototype because we do not\n    // want filenames like \"toString\" coming from a zip file\n    // to overwrite methods and attributes in a normal Object.\n    this.files = Object.create(null);\n\n    this.comment = null;\n\n    // Where we are in the hierarchy\n    this.root = \"\";\n    this.clone = function() {\n        var newObj = new JSZip();\n        for (var i in this) {\n            if (typeof this[i] !== \"function\") {\n                newObj[i] = this[i];\n            }\n        }\n        return newObj;\n    };\n};\n\nvar staticAccessors = { support: { configurable: true },defaults: { configurable: true },version: { configurable: true },external: { configurable: true } };\n\n/**\n * @see loadAsync\n */\nJSZip.prototype.load = function load () {\n    throw new Error(\"This method has been removed in JSZip 3.0, please check the upgrade guide.\");\n};\n\n/**\n * Call a callback function for each entry at this folder level.\n * @param {Function} cb the callback function:\n * function (relativePath, file) {...}\n * It takes 2 arguments : the relative path and the file.\n */\nJSZip.prototype.forEach = function forEach (cb) {\n    var filename, relativePath, file;\n    for (filename in this.files) {\n        file = this.files[filename];\n        relativePath = filename.slice(this.root.length, filename.length);\n        if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root\n            cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn...\n        }\n    }\n};\n\n/**\n * Filter nested files/folders with the specified function.\n * @param {Function} search the predicate to use :\n * function (relativePath, file) {...}\n * It takes 2 arguments : the relative path and the file.\n * @return {Array} An array of matching elements.\n */\nJSZip.prototype.filter = function filter (search) {\n    var result = [];\n    this.forEach(function (relativePath, entry) {\n        if (search(relativePath, entry)) { // the file matches the function\n            result.push(entry);\n        }\n\n    });\n    return result;\n};\n\n/**\n * Add a file to the zip file, or search a file.\n * @param   {string|RegExp} name The name of the file to add (if data is defined),\n * the name of the file to find (if no data) or a regex to match files.\n * @param   {String|ArrayBuffer|Uint8Array|Buffer} data  The file data, either raw or base64 encoded\n * @param   {Object} o File options\n * @return  {JSZip|Object|Array} this JSZip object (when adding a file),\n * a file (when searching by string) or an array of files (when searching by regex).\n */\nJSZip.prototype.file = function file (name, data, o) {\n    if (arguments.length === 1) {\n        if (isRegExp(name)) {\n            var regexp = name;\n            return this.filter(function(relativePath, file) {\n                return !file.dir && regexp.test(relativePath);\n            });\n        }\n        else { // text\n            var obj = this.files[this.root + name];\n            if (obj && !obj.dir) {\n                return obj;\n            } else {\n                return null;\n            }\n        }\n    }\n    else { // more than one argument : we have data !\n        name = this.root + name;\n        fileAdd.call(this, name, data, o);\n    }\n    return this;\n};\n\n/**\n * Add a directory to the zip file, or search.\n * @param   {String|RegExp} arg The name of the directory to add, or a regex to search folders.\n * @return  {JSZip} an object with the new directory as the root, or an array containing matching folders.\n */\nJSZip.prototype.folder = function folder (arg) {\n    if (!arg) {\n        return this;\n    }\n\n    if (isRegExp(arg)) {\n        return this.filter(function(relativePath, file) {\n            return file.dir && arg.test(relativePath);\n        });\n    }\n\n    // else, name is a new folder\n    var name = this.root + arg;\n    var newFolder = folderAdd.call(this, name);\n\n    // Allow chaining by returning a new object with this folder as the root\n    var ret = this.clone();\n    ret.root = newFolder.name;\n    return ret;\n};\n\n/**\n * Delete a file, or a directory and all sub-files, from the zip\n * @param {string} name the name of the file to delete\n * @return {JSZip} this JSZip object\n */\nJSZip.prototype.remove = function remove (name) {\n    name = this.root + name;\n    var file = this.files[name];\n    if (!file) {\n        // Look for any folders\n        if (name.slice(-1) !== \"/\") {\n            name += \"/\";\n        }\n        file = this.files[name];\n    }\n\n    if (file && !file.dir) {\n        // file\n        delete this.files[name];\n    } else {\n        // maybe a folder, delete recursively\n        var kids = this.filter(function(relativePath, file) {\n            return file.name.slice(0, name.length) === name;\n        });\n        for (var i = 0; i < kids.length; i++) {\n            delete this.files[kids[i].name];\n        }\n    }\n\n    return this;\n};\n\n/**\n * Generate the complete zip file\n * @param {Object} options the options to generate the zip file :\n * - compression, \"STORE\" by default.\n * - type, \"base64\" by default. Values are : string, base64, uint8array, arraybuffer, blob.\n * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file\n */\nJSZip.prototype.generate = function generate (options) {\n    throw new Error(\"This method has been removed in JSZip 3.0, please check the upgrade guide.\");\n};\n\n/**\n * Generate the complete zip file as an internal stream.\n * @param {Object} options the options to generate the zip file :\n * - compression, \"STORE\" by default.\n * - type, \"base64\" by default. Values are : string, base64, uint8array, arraybuffer, blob.\n * @return {StreamHelper} the streamed zip file.\n */\nJSZip.prototype.generateInternalStream = function generateInternalStream (options) {\n  var worker, opts = {};\n  try {\n      opts = extend(options || {}, {\n          streamFiles: false,\n          compression: \"STORE\",\n          compressionOptions : null,\n          type: \"\",\n          platform: \"DOS\",\n          comment: null,\n          mimeType: 'application/zip',\n          encodeFileName: utf8encode\n      });\n\n      opts.type = opts.type.toLowerCase();\n      opts.compression = opts.compression.toUpperCase();\n\n      // \"binarystring\" is preferred but the internals use \"string\".\n      if(opts.type === \"binarystring\") {\n        opts.type = \"string\";\n      }\n\n      if (!opts.type) {\n        throw new Error(\"No output type specified.\");\n      }\n\n      checkSupport(opts.type);\n\n      // accept nodejs `process.platform`\n      if(\n          opts.platform === 'darwin' ||\n          opts.platform === 'freebsd' ||\n          opts.platform === 'linux' ||\n          opts.platform === 'sunos'\n      ) {\n          opts.platform = \"UNIX\";\n      }\n      if (opts.platform === 'win32') {\n          opts.platform = \"DOS\";\n      }\n\n      var comment = opts.comment || this.comment || \"\";\n      worker = generateWorker(this, opts, comment);\n  } catch (e) {\n    worker = new GenericWorker(\"error\");\n    worker.error(e);\n  }\n  return new StreamHelper(worker, opts.type || \"string\", opts.mimeType);\n};\n\n/**\n * Generate the complete zip file asynchronously.\n * @see generateInternalStream\n */\nJSZip.prototype.generateAsync = function generateAsync (options, onUpdate) {\n    return this.generateInternalStream(options).accumulate(onUpdate);\n};\n\nJSZip.prototype.loadAsync = function loadAsync (data, options) {\n    return load.apply(this, [data, options]);\n};\n\nJSZip.loadAsync = function loadAsync (content, options) {\n    return new JSZip().loadAsync(content, options);\n};\n    \nstaticAccessors.support.get = function () {\n    return support;\n};\n\nstaticAccessors.defaults.get = function () {\n    return defaults;\n};\n\nstaticAccessors.version.get = function () {\n    return \"3.2.2-esm\";\n};\n\nstaticAccessors.external.get = function () {\n    return external;\n};\n\nObject.defineProperties( JSZip, staticAccessors );\n\nexport { JSZip as default };\n","(function(a,b){if(\"function\"==typeof define&&define.amd)define([],b);else if(\"undefined\"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){\"use strict\";function b(a,b){return\"undefined\"==typeof b?b={autoBom:!1}:\"object\"!=typeof b&&(console.warn(\"Deprecated: Expected third argument to be a object\"),b={autoBom:!b}),b.autoBom&&/^\\s*(?:text\\/\\S*|application\\/xml|\\S*\\/\\S*\\+xml)\\s*;.*charset\\s*=\\s*utf-8/i.test(a.type)?new Blob([\"\\uFEFF\",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open(\"GET\",a),d.responseType=\"blob\",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error(\"could not download file\")},d.send()}function d(a){var b=new XMLHttpRequest;b.open(\"HEAD\",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent(\"click\"))}catch(c){var b=document.createEvent(\"MouseEvents\");b.initMouseEvent(\"click\",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f=\"object\"==typeof window&&window.window===window?window:\"object\"==typeof self&&self.self===self?self:\"object\"==typeof global&&global.global===global?global:void 0,a=f.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||(\"object\"!=typeof window||window!==f?function(){}:\"download\"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement(\"a\");g=g||b.name||\"download\",j.download=g,j.rel=\"noopener\",\"string\"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target=\"_blank\")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:\"msSaveOrOpenBlob\"in navigator?function(f,g,h){if(g=g||f.name||\"download\",\"string\"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement(\"a\");i.href=f,i.target=\"_blank\",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open(\"\",\"_blank\"),g&&(g.document.title=g.document.body.innerText=\"downloading...\"),\"string\"==typeof b)return c(b,d,e);var h=\"application/octet-stream\"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\\/[\\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&\"undefined\"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,\"data:attachment/file;\"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,\"undefined\"!=typeof module&&(module.exports=g)});\n\n//# sourceMappingURL=FileSaver.min.js.map","import JSZip from \"@progress/jszip-esm\";\r\n\r\nimport * as FileSaver from \"file-saver\";\r\n\r\nimport { Dates, Texts } from \"@salaxy/core\";\r\n\r\n/**\r\n * Copied and modified from https://github.com/egeriis/zipcelx#readme\r\n */\r\nclass Zipcelx {\r\n  private CELL_TYPE_STRING = \"string\";\r\n  private CELL_TYPE_NUMBER = \"number\";\r\n  private CELL_TYPE_DATE = \"date\";\r\n  private CELL_TYPE_BOOLEAN = \"boolean\";\r\n\r\n  private MISSING_KEY_FILENAME = \"Zipclex config missing property filename\";\r\n  private INVALID_TYPE_FILENAME = \"Zipclex filename can only be of type string\";\r\n  private INVALID_TYPE_SHEET = \"Zipcelx sheet data is not of type array\";\r\n  private INVALID_TYPE_SHEET_DATA = \"Zipclex sheet data childs is not of type array\";\r\n\r\n  private stylesXML = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" >\r\n    <fonts count=\"1\">\r\n      <font>\r\n        <sz val=\"11\" />\r\n        <color theme=\"1\" />\r\n        <name val=\"Calibri\" />\r\n        <family val=\"2\" />\r\n        <scheme val=\"minor\" />\r\n      </font>\r\n    </fonts>\r\n    <fills count=\"2\">\r\n      <fill>\r\n        <patternFill patternType=\"none\" />\r\n      </fill>\r\n      <fill>\r\n        <patternFill patternType=\"gray125\" />\r\n      </fill>\r\n    </fills>\r\n    <borders count=\"1\">\r\n      <border>\r\n        <left />\r\n        <right />\r\n        <top />\r\n        <bottom />\r\n        <diagonal />\r\n      </border>\r\n    </borders>\r\n    <cellStyleXfs count=\"1\">\r\n      <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" />\r\n    </cellStyleXfs>\r\n    <cellXfs count=\"2\">\r\n      <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" />\r\n      <xf numFmtId=\"14\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\" />\r\n    </cellXfs>\r\n    <cellStyles count=\"1\">\r\n      <cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\" />\r\n    </cellStyles>\r\n  </styleSheet>\r\n  `;\r\n  private workbookXML = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"\r\n           xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\r\n    <sheets>\r\n      <sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\" />\r\n    </sheets>\r\n  </workbook>`;\r\n  private workbookXMLRels = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\r\n    <Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\" />\r\n    <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\" />\r\n  </Relationships>`;\r\n  private rels = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\r\n    <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\" />\r\n  </Relationships>`;\r\n  private contentTypes = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\r\n    <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" />\r\n    <Default Extension=\"xml\" ContentType=\"application/xml\" />\r\n    <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" />\r\n    <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" />\r\n    <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" />\r\n  </Types>`;\r\n  private templateSheet = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n  <worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"\r\n             xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\r\n    <cols>{cols}</cols>\r\n    <sheetData>{rows}</sheetData>\r\n  </worksheet>`;\r\n\r\n  /**\r\n   * Generates excel blob from the configuration\r\n   */\r\n  public generateExcel = (config): Promise<any> => {\r\n    if (!this.validator(config)) {\r\n      throw new Error(\"Validation failed.\");\r\n    }\r\n\r\n    const zip = new JSZip();\r\n    const xl = zip.folder(\"xl\");\r\n    xl.file(\"workbook.xml\", this.workbookXML);\r\n    xl.file(\"styles.xml\", this.stylesXML);\r\n    xl.file(\"_rels/workbook.xml.rels\", this.workbookXMLRels);\r\n    zip.file(\"_rels/.rels\", this.rels);\r\n    zip.file(\"[Content_Types].xml\", this.contentTypes);\r\n\r\n    const worksheet = this.generateXMLWorksheet(config.sheet.data);\r\n    xl.file(\"worksheets/sheet1.xml\", worksheet);\r\n\r\n    return zip.generateAsync({\r\n      type: \"blob\",\r\n      mimeType:\r\n        \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\r\n    });\r\n  };\r\n\r\n  private childValidator = (array) => {\r\n    return array.every( (item) => Array.isArray(item));\r\n  };\r\n\r\n  private validator = (config) => {\r\n    if (!config.filename) {\r\n      console.error(this.MISSING_KEY_FILENAME);\r\n      return false;\r\n    }\r\n\r\n    if (typeof config.filename !== \"string\") {\r\n      console.error(this.INVALID_TYPE_FILENAME);\r\n      return false;\r\n    }\r\n\r\n    if (!Array.isArray(config.sheet.data)) {\r\n      console.error(this.INVALID_TYPE_SHEET);\r\n      return false;\r\n    }\r\n\r\n    if (!this.childValidator(config.sheet.data)) {\r\n      console.error(this.INVALID_TYPE_SHEET_DATA);\r\n      return false;\r\n    }\r\n\r\n    return true;\r\n  };\r\n\r\n  private generateColumnLetter = (colIndex) => {\r\n    if (typeof colIndex !== \"number\") {\r\n      return \"\";\r\n    }\r\n\r\n    const prefix = Math.floor(colIndex / 26);\r\n    const letter = String.fromCharCode(97 + (colIndex % 26)).toUpperCase();\r\n    if (prefix === 0) {\r\n      return letter;\r\n    }\r\n    return this.generateColumnLetter(prefix - 1) + letter;\r\n  };\r\n\r\n  private generatorCellNumber = (index, rowNumber) => (\r\n    `${this.generateColumnLetter(index)}${rowNumber}`\r\n  );\r\n\r\n  private generatorStringCell = (index, value, rowIndex) => (`<c r=\"${this.generatorCellNumber(index, rowIndex)}\" t=\"inlineStr\"><is><t>${Texts.escapeHtml(value)}</t></is></c>`);\r\n  private generatorNumberCell = (index, value, rowIndex) => (`<c r=\"${this.generatorCellNumber(index, rowIndex)}\" t=\"n\"><v>${value}</v></c>`);\r\n  private generatorDateCell =  (index, value, rowIndex) => (`<c r=\"${this.generatorCellNumber(index, rowIndex)}\" t=\"d\" s=\"1\"><v>${value}</v></c>`);\r\n  private generatorBooleanCell = (index, value, rowIndex) => (`<c r=\"${this.generatorCellNumber(index, rowIndex)}\" t=\"b\"><v>${value}</v></c>`);\r\n  private generatorEmptyCell = (index, value, rowIndex) => (`<c r=\"${this.generatorCellNumber(index, rowIndex)}\"><v></v></c>`);\r\n\r\n  private formatCell = (cell, index, rowIndex) => {\r\n    return (\r\n      cell.type === this.CELL_TYPE_STRING ?\r\n         this.generatorStringCell(index, cell.value, rowIndex) :\r\n      cell.type === this.CELL_TYPE_NUMBER ?\r\n         this.generatorNumberCell(index, cell.value, rowIndex) :\r\n      cell.type === this.CELL_TYPE_DATE ?\r\n         this.generatorDateCell(index, cell.value, rowIndex) :\r\n      cell.type === this.CELL_TYPE_BOOLEAN ?\r\n         this.generatorBooleanCell(index, cell.value, rowIndex) :\r\n         this.generatorEmptyCell(index, cell.value, rowIndex)\r\n    );\r\n  };\r\n\r\n  private formatRow = (row, index) => {\r\n    // To ensure the row number starts as in excel.\r\n    const rowIndex = index + 1;\r\n    const rowCells = row\r\n      .map((cell, cellIndex) => this.formatCell(cell, cellIndex, rowIndex))\r\n      .join(\"\");\r\n\r\n    return `<row r=\"${rowIndex}\">${rowCells}</row>`;\r\n  };\r\n\r\n  private generatorRows = (rows) => (\r\n    rows\r\n      .map((row, index) => this.formatRow(row, index))\r\n      .join(\"\")\r\n  );\r\n\r\n  private formatCol = (col, index) => {\r\n    // To ensure the row number starts as in excel.\r\n    const colIndex = index + 1;\r\n    return `<col min=\"${colIndex}\" max=\"${colIndex}\" width=\"30\" customWidth=\"1\"/>`;\r\n  };\r\n\r\n  private generatorCols = (cols) => (\r\n    cols\r\n      .map((col, index) => this.formatCol(col, index))\r\n      .join(\"\")\r\n  );\r\n\r\n  private generateXMLWorksheet = (rows) => {\r\n    const xmlCols = this.generatorCols(rows.length > 0 ? rows[0] : []);\r\n    const xmlRows = this.generatorRows(rows);\r\n    return this.templateSheet.replace(\"{rows}\", xmlRows).replace(\"{cols}\", xmlCols);\r\n  };\r\n}\r\n\r\n/** Utility service for generating excel files. */\r\nexport class ExcelHelpers {\r\n\r\n  /**\r\n   * Converts a data table to an excel file.\r\n   * @param tableData Array of rows to convert to an excel file. Each row consists of an array of cell values.\r\n   * @param fileName Name for the excel file without the file extension.\r\n   */\r\n  public static export(tableData: any[], fileName: string): Promise<void> {\r\n    const rowMapper = this.getRowMapper();\r\n    const config = {\r\n      filename: fileName,\r\n      sheet: {\r\n        data: tableData.map(rowMapper),\r\n      },\r\n    };\r\n    return this.zipcelx.generateExcel(config).then( (blob) => {\r\n      FileSaver.saveAs(blob, `${config.filename}.xlsx`);\r\n      return;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Converts multiple data tables to a zip file containing excel files.\r\n   * @param tablesData Multiple data tables. Each table contains an array of rows to convert to a excel file. Each row consists of an array of cell values.\r\n   * @param zipName Name for the zip file without the file extension.\r\n   */\r\n  public static exportMany(\r\n    tablesData: {\r\n      /** Array of rows to convert to an excel file. Each row consists of an array of cell values. */\r\n      tableData: any[],\r\n      /** Name for the excel file without the file extension. */\r\n      fileName: string,\r\n    }[],\r\n    zipName: string): Promise<void> {\r\n\r\n    const rowMapper = this.getRowMapper();\r\n    let counter = 0;\r\n    const zip = new JSZip();\r\n    const next = (): Promise<void> => {\r\n      if (counter === tablesData.length) {\r\n        return Promise.resolve();\r\n      }\r\n      const item = tablesData[counter++];\r\n      const config = {\r\n        filename: item.fileName,\r\n        sheet: {\r\n          data: item.tableData.map(rowMapper),\r\n        },\r\n      };\r\n      return this.zipcelx.generateExcel(config).then( (blob) => {\r\n        zip.file(`${config.filename}.xlsx`, blob);\r\n        return next();\r\n      });\r\n    };\r\n\r\n    return next().then ( () => {\r\n      return zip.generateAsync({\r\n        type: \"blob\",\r\n        mimeType:\r\n          \"application/zip\",\r\n      }).then( (blob) => {\r\n        FileSaver.saveAs(blob, `${zipName}.zip`);\r\n        return;\r\n      });\r\n    });\r\n  }\r\n\r\n  private static zipcelx = new Zipcelx();\r\n\r\n  private static getRowMapper() {\r\n    const fieldMapper = this.getFieldMapper();\r\n    return (row) => {\r\n      return row.map(fieldMapper);\r\n    };\r\n  }\r\n\r\n  private static getFieldMapper() {\r\n    return (value) => {\r\n      if (value == null) { // we want to catch anything null-ish, hence just == not ===\r\n        return { value, type: null };\r\n      }\r\n      if (typeof (value) === \"number\") {\r\n        return { value, type: \"number\" };\r\n      }\r\n      if (typeof (value) === \"boolean\") {\r\n        return { value: (value ? \"true\" : \"false\"), type: \"boolean\" };\r\n      }\r\n      if (typeof (value) === \"string\") {\r\n        return { value: value.replace(/\"/g, \"\\\"\\\"\"), type: \"string\" };\r\n      }\r\n      if (typeof (value) === \"object\" && (value instanceof Date)) {\r\n        return { value: Dates.format(value,\"YYYY-MM-DD\"), type: \"date\" };\r\n      }\r\n\r\n      return { value: JSON.stringify(value), type: \"string\" };\r\n    };\r\n  }\r\n}\r\n","import * as FileSaver from \"file-saver\";\r\n\r\nimport { Dates, ExportMethod, FileExporter, TableFormat, Tables, Translations } from \"@salaxy/core\";\r\nimport { AlertService } from \"./AlertService\";\r\nimport { ExcelHelpers } from \"./ExcelHelpers\";\r\nimport angular from \"angular\";\r\n\r\n/**\r\n * Provides functionality related to working with files: Download, copy-paste etc.\r\n */\r\nexport class FileService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AlertService\", \"$timeout\"];\r\n\r\n  constructor(private alertService: AlertService, private $timeout: angular.ITimeoutService) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Copies given data to the clipboard. */\r\n  public copyToClipboard(data: string): Promise<void> {\r\n    return (navigator as any).clipboard.writeText(data).then(() => {\r\n      return this.$timeout(() => {\r\n        return;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Gets the default exporters available in the current environment / account  */\r\n  public getDefaultExporters(): FileExporter[] {\r\n    return [\r\n      {\r\n        id: ExportMethod.CopyExcel,\r\n        label: Translations.get(\"SALAXY.NG1.ODataActionsComponent.getDefaults.copyExcel\"),\r\n        hasLocales: true,\r\n        export: (rows, locale) => {\r\n          const tabbedData = Tables.export(rows as any, TableFormat.Txt, locale);\r\n          this.copyToClipboard(tabbedData);\r\n          this.alertService.addSuccess(`${rows.length} ${Translations.get(\"SALAXY.NG1.ExportComponent.export.rowsCopiedOnClipboard\")}`);\r\n        }\r\n      },\r\n      {\r\n        id: ExportMethod.FileExcel,\r\n        label: Translations.get(\"SALAXY.NG1.ODataActionsComponent.getDefaults.fileExcel\"),\r\n        hasLocales: false,\r\n        export: (rows) => {\r\n          return ExcelHelpers.export(Tables.exportAsArrays(rows as any), this.getFileName());\r\n        }\r\n      },\r\n      {\r\n        id: ExportMethod.CopyCsv,\r\n        label: Translations.get(\"SALAXY.NG1.ODataActionsComponent.getDefaults.copyCsv\"),\r\n        hasLocales: true,\r\n        export: (rows, locale) => {\r\n          const csvData = Tables.export(rows as any, TableFormat.Csv, locale);\r\n          this.copyToClipboard(csvData);\r\n          this.alertService.addSuccess(`${rows.length} ${Translations.get(\"SALAXY.NG1.ExportComponent.export.rowsCopiedOnClipboard\")}`);\r\n        }\r\n      },\r\n      {\r\n        id: ExportMethod.FileCsv,\r\n        label: Translations.get(\"SALAXY.NG1.ODataActionsComponent.getDefaults.fileCsv\"),\r\n        hasLocales: true,\r\n        export: (rows, locale) => {\r\n          const csvFileData = Tables.export(rows as any, TableFormat.Csv, locale);\r\n          FileSaver.saveAs(new Blob([csvFileData], { type: \"application/octet-stream;charset=utf-8\" }), `${this.getFileName()}.csv`);\r\n        }\r\n      }\r\n    ];\r\n  }\r\n\r\n  /** Gets a filename as ¨export_[YYYYMMDD]¨. */\r\n  private getFileName() {\r\n    return `export_${Dates.format(\"today\", \"YYYYMMDD\")}`;\r\n  }\r\n\r\n}","/* eslint-disable no-bitwise */\r\n\r\n/** Copied and modified from https://css-tricks.com/snippets/javascript/javascript-md5 */\r\nexport class GravatarHelpers {\r\n\r\n  /** Create gravatar url from the given email. */\r\n  public static getGravatarUrl(email: string): string {\r\n    return `https://www.gravatar.com/avatar/${this.md5((email + \"\").trim().toLowerCase())}?d=identicon`;\r\n  }\r\n\r\n  /** Returns true if the url is gravatar url. */\r\n  public static isGravatarUrl(url: string): boolean {\r\n    return (url + \"\").trim().toLowerCase().startsWith(\"https://www.gravatar.com/avatar/\");\r\n  }\r\n\r\n  /**\r\n   * Calculates md5.\r\n   */\r\n  private static md5(str: string): string {\r\n    const rotateLeft = (lValue, iShiftBits) => {\r\n      return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));\r\n    };\r\n    const addUnsigned = (lX, lY) => {\r\n      const lX8 = (lX & 0x80000000);\r\n      const lY8 = (lY & 0x80000000);\r\n      const lX4 = (lX & 0x40000000);\r\n      const lY4 = (lY & 0x40000000);\r\n      const lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);\r\n      if (lX4 & lY4) {\r\n        return (lResult ^ 0x80000000 ^ lX8 ^ lY8);\r\n      }\r\n      if (lX4 | lY4) {\r\n        if (lResult & 0x40000000) {\r\n          return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);\r\n        } else {\r\n          return (lResult ^ 0x40000000 ^ lX8 ^ lY8);\r\n        }\r\n      } else {\r\n        return (lResult ^ lX8 ^ lY8);\r\n      }\r\n    };\r\n    const f = (x, y, z) => (x & y) | ((~x) & z);\r\n    const g = (x, y, z) => (x & z) | (y & (~z));\r\n    const h = (x, y, z) => (x ^ y ^ z);\r\n    const i = (x, y, z) => (y ^ (x | (~z)));\r\n    const ff = (a, b, c, d, x, s, ac) => {\r\n      a = addUnsigned(a, addUnsigned(addUnsigned(f(b, c, d), x), ac));\r\n      return addUnsigned(rotateLeft(a, s), b);\r\n    };\r\n    const gg = (a, b, c, d, x, s, ac) => {\r\n      a = addUnsigned(a, addUnsigned(addUnsigned(g(b, c, d), x), ac));\r\n      return addUnsigned(rotateLeft(a, s), b);\r\n    };\r\n    const hh = (a, b, c, d, x, s, ac) => {\r\n      a = addUnsigned(a, addUnsigned(addUnsigned(h(b, c, d), x), ac));\r\n      return addUnsigned(rotateLeft(a, s), b);\r\n    };\r\n    const ii = (a, b, c, d, x, s, ac) => {\r\n      a = addUnsigned(a, addUnsigned(addUnsigned(i(b, c, d), x), ac));\r\n      return addUnsigned(rotateLeft(a, s), b);\r\n    };\r\n    const convertToWordArray = (str) => {\r\n      let lWordCount;\r\n      const lMessageLength = str.length;\r\n      const lNumberOfWordsTemp1 = lMessageLength + 8;\r\n      const lNumberOfWordsTemp2 = (lNumberOfWordsTemp1 - (lNumberOfWordsTemp1 % 64)) / 64;\r\n      const lNumberOfWords = (lNumberOfWordsTemp2 + 1) * 16;\r\n      const lWordArray = Array(lNumberOfWords - 1);\r\n      let lBytePosition = 0;\r\n      let lByteCount = 0;\r\n      while (lByteCount < lMessageLength) {\r\n        lWordCount = (lByteCount - (lByteCount % 4)) / 4;\r\n        lBytePosition = (lByteCount % 4) * 8;\r\n        lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));\r\n        lByteCount++;\r\n      }\r\n      lWordCount = (lByteCount - (lByteCount % 4)) / 4;\r\n      lBytePosition = (lByteCount % 4) * 8;\r\n      lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);\r\n      lWordArray[lNumberOfWords - 2] = lMessageLength << 3;\r\n      lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;\r\n      return lWordArray;\r\n    };\r\n    const wordToHex = (lValue) => {\r\n      let wordToHexValue = \"\";\r\n      let wordToHexValueTemp = \"\";\r\n      let lByte;\r\n      let lCount;\r\n      for (lCount = 0; lCount <= 3; lCount++) {\r\n        lByte = (lValue >>> (lCount * 8)) & 255;\r\n        wordToHexValueTemp = \"0\" + lByte.toString(16);\r\n        wordToHexValue = wordToHexValue + wordToHexValueTemp.substr(wordToHexValueTemp.length - 2, 2);\r\n      }\r\n      return wordToHexValue;\r\n    };\r\n    const utf8Encode = (str) => {\r\n      str = str.replace(/\\r\\n/g, \"\\n\");\r\n      let utftext = \"\";\r\n      for (let n = 0; n < str.length; n++) {\r\n        const c = str.charCodeAt(n);\r\n        if (c < 128) {\r\n          utftext += String.fromCharCode(c);\r\n        } else if ((c > 127) && (c < 2048)) {\r\n          utftext += String.fromCharCode((c >> 6) | 192);\r\n          utftext += String.fromCharCode((c & 63) | 128);\r\n        } else {\r\n          utftext += String.fromCharCode((c >> 12) | 224);\r\n          utftext += String.fromCharCode(((c >> 6) & 63) | 128);\r\n          utftext += String.fromCharCode((c & 63) | 128);\r\n        }\r\n      }\r\n      return utftext;\r\n    };\r\n\r\n    let aa;\r\n    let bb;\r\n    let cc;\r\n    let dd;\r\n    let a;\r\n    let b;\r\n    let c;\r\n    let d;\r\n    const s11 = 7;\r\n    const s12 = 12;\r\n    const s13 = 17;\r\n    const s14 = 22;\r\n    const s21 = 5;\r\n    const s22 = 9;\r\n    const s23 = 14;\r\n    const s24 = 20;\r\n    const s31 = 4;\r\n    const s32 = 11;\r\n    const s33 = 16;\r\n    const s34 = 23;\r\n    const s41 = 6;\r\n    const s42 = 10;\r\n    const s43 = 15;\r\n    const s44 = 21;\r\n\r\n    str = utf8Encode(str);\r\n    const x = convertToWordArray(str);\r\n    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;\r\n    for (let k = 0; k < x.length; k += 16) {\r\n      aa = a; bb = b; cc = c; dd = d;\r\n      a = ff(a, b, c, d, x[k + 0], s11, 0xD76AA478);\r\n      d = ff(d, a, b, c, x[k + 1], s12, 0xE8C7B756);\r\n      c = ff(c, d, a, b, x[k + 2], s13, 0x242070DB);\r\n      b = ff(b, c, d, a, x[k + 3], s14, 0xC1BDCEEE);\r\n      a = ff(a, b, c, d, x[k + 4], s11, 0xF57C0FAF);\r\n      d = ff(d, a, b, c, x[k + 5], s12, 0x4787C62A);\r\n      c = ff(c, d, a, b, x[k + 6], s13, 0xA8304613);\r\n      b = ff(b, c, d, a, x[k + 7], s14, 0xFD469501);\r\n      a = ff(a, b, c, d, x[k + 8], s11, 0x698098D8);\r\n      d = ff(d, a, b, c, x[k + 9], s12, 0x8B44F7AF);\r\n      c = ff(c, d, a, b, x[k + 10], s13, 0xFFFF5BB1);\r\n      b = ff(b, c, d, a, x[k + 11], s14, 0x895CD7BE);\r\n      a = ff(a, b, c, d, x[k + 12], s11, 0x6B901122);\r\n      d = ff(d, a, b, c, x[k + 13], s12, 0xFD987193);\r\n      c = ff(c, d, a, b, x[k + 14], s13, 0xA679438E);\r\n      b = ff(b, c, d, a, x[k + 15], s14, 0x49B40821);\r\n      a = gg(a, b, c, d, x[k + 1], s21, 0xF61E2562);\r\n      d = gg(d, a, b, c, x[k + 6], s22, 0xC040B340);\r\n      c = gg(c, d, a, b, x[k + 11], s23, 0x265E5A51);\r\n      b = gg(b, c, d, a, x[k + 0], s24, 0xE9B6C7AA);\r\n      a = gg(a, b, c, d, x[k + 5], s21, 0xD62F105D);\r\n      d = gg(d, a, b, c, x[k + 10], s22, 0x2441453);\r\n      c = gg(c, d, a, b, x[k + 15], s23, 0xD8A1E681);\r\n      b = gg(b, c, d, a, x[k + 4], s24, 0xE7D3FBC8);\r\n      a = gg(a, b, c, d, x[k + 9], s21, 0x21E1CDE6);\r\n      d = gg(d, a, b, c, x[k + 14], s22, 0xC33707D6);\r\n      c = gg(c, d, a, b, x[k + 3], s23, 0xF4D50D87);\r\n      b = gg(b, c, d, a, x[k + 8], s24, 0x455A14ED);\r\n      a = gg(a, b, c, d, x[k + 13], s21, 0xA9E3E905);\r\n      d = gg(d, a, b, c, x[k + 2], s22, 0xFCEFA3F8);\r\n      c = gg(c, d, a, b, x[k + 7], s23, 0x676F02D9);\r\n      b = gg(b, c, d, a, x[k + 12], s24, 0x8D2A4C8A);\r\n      a = hh(a, b, c, d, x[k + 5], s31, 0xFFFA3942);\r\n      d = hh(d, a, b, c, x[k + 8], s32, 0x8771F681);\r\n      c = hh(c, d, a, b, x[k + 11], s33, 0x6D9D6122);\r\n      b = hh(b, c, d, a, x[k + 14], s34, 0xFDE5380C);\r\n      a = hh(a, b, c, d, x[k + 1], s31, 0xA4BEEA44);\r\n      d = hh(d, a, b, c, x[k + 4], s32, 0x4BDECFA9);\r\n      c = hh(c, d, a, b, x[k + 7], s33, 0xF6BB4B60);\r\n      b = hh(b, c, d, a, x[k + 10], s34, 0xBEBFBC70);\r\n      a = hh(a, b, c, d, x[k + 13], s31, 0x289B7EC6);\r\n      d = hh(d, a, b, c, x[k + 0], s32, 0xEAA127FA);\r\n      c = hh(c, d, a, b, x[k + 3], s33, 0xD4EF3085);\r\n      b = hh(b, c, d, a, x[k + 6], s34, 0x4881D05);\r\n      a = hh(a, b, c, d, x[k + 9], s31, 0xD9D4D039);\r\n      d = hh(d, a, b, c, x[k + 12], s32, 0xE6DB99E5);\r\n      c = hh(c, d, a, b, x[k + 15], s33, 0x1FA27CF8);\r\n      b = hh(b, c, d, a, x[k + 2], s34, 0xC4AC5665);\r\n      a = ii(a, b, c, d, x[k + 0], s41, 0xF4292244);\r\n      d = ii(d, a, b, c, x[k + 7], s42, 0x432AFF97);\r\n      c = ii(c, d, a, b, x[k + 14], s43, 0xAB9423A7);\r\n      b = ii(b, c, d, a, x[k + 5], s44, 0xFC93A039);\r\n      a = ii(a, b, c, d, x[k + 12], s41, 0x655B59C3);\r\n      d = ii(d, a, b, c, x[k + 3], s42, 0x8F0CCC92);\r\n      c = ii(c, d, a, b, x[k + 10], s43, 0xFFEFF47D);\r\n      b = ii(b, c, d, a, x[k + 1], s44, 0x85845DD1);\r\n      a = ii(a, b, c, d, x[k + 8], s41, 0x6FA87E4F);\r\n      d = ii(d, a, b, c, x[k + 15], s42, 0xFE2CE6E0);\r\n      c = ii(c, d, a, b, x[k + 6], s43, 0xA3014314);\r\n      b = ii(b, c, d, a, x[k + 13], s44, 0x4E0811A1);\r\n      a = ii(a, b, c, d, x[k + 4], s41, 0xF7537E82);\r\n      d = ii(d, a, b, c, x[k + 11], s42, 0xBD3AF235);\r\n      c = ii(c, d, a, b, x[k + 2], s43, 0x2AD7D2BB);\r\n      b = ii(b, c, d, a, x[k + 9], s44, 0xEB86D391);\r\n      a = addUnsigned(a, aa);\r\n      b = addUnsigned(b, bb);\r\n      c = addUnsigned(c, cc);\r\n      d = addUnsigned(d, dd);\r\n    }\r\n\r\n    const temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);\r\n\r\n    return temp.toLowerCase();\r\n  }\r\n\r\n}\r\n","import { OpenAPIV3 } from \"@salaxy/core\";\r\n\r\nimport { InputMetadata, JsonInputType, JsonSchemaCache, JsonSchemaCacheItem, JsonSchemaProperty, JsonSchemaUtils } from \"@salaxy/core\";\r\n\r\nimport { AjaxNg1 } from \"../../ajax\";\r\n\r\n/**\r\n * Service for caching JSON schemas and creating user interfaces based on them.\r\n */\r\nexport class JsonSchemaService {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\"];\r\n\r\n  private cache: JsonSchemaCache;\r\n\r\n  constructor(private ajax: AjaxNg1) {\r\n    this.cache = new JsonSchemaCache(ajax);\r\n  }\r\n\r\n  /** Gets the currently loaded schema documents. */\r\n  public getSchemas(): JsonSchemaCacheItem[] {\r\n    return this.cache.schemaCache.filter((x) => !!x.doc);\r\n  }\r\n\r\n  /** Gets the raw schema cache, mainly for injecting to other classes that may need it. */\r\n  public getCache(): JsonSchemaCache {\r\n    return this.cache;\r\n  }\r\n\r\n  /**\r\n   * Assures that a schema document identified by URL is loaded from server to the cache\r\n   * Currently, supports only OpenApi 3, but we may later support OpenApi 2 and/or plain JSON schema.\r\n   * @param openApiUrl URL to the open API document.\r\n   * @returns A promise that resolves when the document has been loaded and you can call other methods on it.\r\n   */\r\n  public assureSchemaDocument (openApiUrl: string): Promise<OpenAPIV3.Document> {\r\n    return this.cache.assureSchemaDocument(openApiUrl);\r\n  }\r\n\r\n  /**\r\n   * Adds a schema document to cache\r\n   * TODO: Reconsider the signature.\r\n   */\r\n  public addSchemaDocument (openApiUrl: string, doc: OpenAPIV3.Document): OpenAPIV3.Document {\r\n    return this.cache.addSchemaDocument(openApiUrl, doc);\r\n  }\r\n\r\n  /**\r\n   * Finds a schema document from the cache.\r\n   * This method is syncronous base method for other schema operations\r\n   * Make sure that the schme document has been loaded before calling as this will not load the document,\r\n   * but will fail instead if the schema document is not there.\r\n   * @param openApiUrl URL to the open API document.\r\n   * @param throwIfNotFound If true, will throw an error if the document is not found in the cache.\r\n   */\r\n  public findSchemaDoc (openApiUrl: string, throwIfNotFound: boolean): JsonSchemaCacheItem {\r\n    return this.cache.findSchemaDoc(openApiUrl, throwIfNotFound);\r\n  }\r\n\r\n  /**\r\n   * Finds a single schema (Data model) within a schema document\r\n   * Make sure that the schme document has been loaded before calling as this will not load the document,\r\n   * but will fail instead if the schema document is not there.\r\n   * @param openApiUrl URL to the open API document.\r\n   * @param name Name of the schema (data model)\r\n   */\r\n  public findSchema (openApiUrl: string, name: string): OpenAPIV3.SchemaObject | null {\r\n    return this.cache.findSchema(openApiUrl, name);\r\n  }\r\n\r\n  /**\r\n   * Gets a property from a schema document. Supports single property names or longer property paths.\r\n   * @param openApiUrl URL to the open API document.\r\n   * @param schemaName The root type from which the property is found.\r\n   * @param path Property path starting with the root schema.\r\n   */\r\n  public getProperty (openApiUrl: string, schemaName: string, path: string): JsonSchemaProperty {\r\n    const schema = this.findSchema(openApiUrl, schemaName);\r\n    return JsonSchemaUtils.getProperty(schema, path);\r\n  }\r\n\r\n  /**\r\n   * Registers a new custom input for type/format combination\r\n   * @param type JSON type\r\n   * @param format Format in the JSON schema\r\n   * @param template Template for the type/foramt combination.\r\n   * Special key \"sxy\" can be used to set default templates based on type/format,\r\n   * e.g. (\"boolean\", \"default\", \"sxy\") => \"salaxy-components/sxy-form/boolean/default.html\".\r\n   */\r\n  public registerInput (type: JsonInputType, format: \"default\" | string, template: \"sxy\" | string) {\r\n    this._registeredInputs[type][format] = (template === \"sxy\" ?\r\n      `salaxy-components/sxy-form/${type}/${format}.html` : template);\r\n  }\r\n\r\n  /** Gets the AngularJS tempalte for the input. */\r\n  public getTemplate (input: InputMetadata): string {\r\n    const type = this._registeredInputs[input.type];\r\n    if (!type) {\r\n      input.content = `Unregistered type: ${input.type}`;\r\n      return \"salaxy-components/sxy-form/error/default.html\";\r\n    }\r\n    if (type[input.format]) {\r\n      return type[input.format].template === \"sxy\" ? `salaxy-components/sxy-form/${input.type}/${input.format}.html` : type[input.format].template;\r\n    }\r\n    return `salaxy-components/sxy-form/${input.type}/${(input.isEnum ? \"enum\" : \"default\")}.html`;\r\n  }\r\n\r\n  /** Gets the registered inputs */\r\n  public getRegisteredInputs(): { [key: string]: { [key: string]: any } } {\r\n    return this._registeredInputs;\r\n  }\r\n\r\n  /**\r\n   * Maps the types and formats to templates.\r\n   */\r\n   private _registeredInputs = {\r\n    \"array\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"PercentDimension\": {\r\n        template: \"sxy\"\r\n      },\r\n    },\r\n    \"boolean\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"select\": {\r\n        template: \"salaxy-components/sxy-form/boolean/default.html\"\r\n      },\r\n      \"radio\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"checkbox\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"switch\": {\r\n        template: \"sxy\"\r\n      },\r\n    },\r\n    \"integer\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n    },\r\n    \"number\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"count\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n      \"percent\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n      \"days\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n      \"kilometers\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n      \"hours\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n      \"undefined\": {\r\n        template: \"salaxy-components/sxy-form/number/default.html\"\r\n      },\r\n    },\r\n    \"object\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"Avatar\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"DateRange\": {\r\n        template: \"sxy\"\r\n      },\r\n    },\r\n    \"string\": {\r\n      \"default\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"multiline\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"email\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"password\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"telephone\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"date\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"date-time\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"enum\": {\r\n        template: \"sxy\"\r\n      },\r\n      \"radio\": {\r\n        template: \"salaxy-components/sxy-form/string/enum.html\"\r\n      },\r\n      \"typeahead\": {\r\n        template: \"salaxy-components/sxy-form/string/enum.html\"\r\n      },\r\n      \"list\": {\r\n        template: \"salaxy-components/sxy-form/string/enum.html\"\r\n      },\r\n      \"pension-contract-number\": {\r\n        template: \"salaxy-components/sxy-form/string/pension-contract-number.html\",\r\n      }\r\n    },\r\n  };\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Configs } from \"@salaxy/core\";\r\n\r\n/** Exception tracking with AppInsight */\r\nexport class AppInsightExceptionTracking {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  protected static $inject = [\"$provide\"];\r\n\r\n  constructor($provide: angular.auto.IProvideService) {\r\n    $provide.decorator(\"$exceptionHandler\", [\"$delegate\", ($delegate: angular.IExceptionHandlerService) => {\r\n      return (exception: Error, cause?: string) => {\r\n        $delegate(exception, cause);\r\n        const appInsights = Configs.global.appInsights;\r\n        const config = Configs.current;\r\n        if (appInsights && config && config.instrumentationKey) {\r\n          try {\r\n            appInsights.trackException({ exception });\r\n            appInsights.flush();\r\n          } catch (err) {\r\n            console.debug(\"Application insight\", err);\r\n          }\r\n        }\r\n      };\r\n    }]);\r\n  }\r\n}\r\n","import { CalendarSeries } from \"@salaxy/core\";\r\n\r\n/** Helper component for calendar related user interfaces: Dates and Times formatting etc. */\r\nexport class CalendarHelper {\r\n\r\n  /** Periods / date ranges plotted on the chart. */\r\n  public calendarPeriods: CalendarSeries[];\r\n\r\n  constructor(private $sce: angular.ISCEService) {}\r\n\r\n  /**\r\n   * Gets a HTML formatted version of the description.\r\n   * @param description Description text to format\r\n   */\r\n   public formatDescription(description): any\r\n   {\r\n     if (!description) {\r\n       return null;\r\n     }\r\n     const html = description.replace(/<(http[^>]*)>/g, (match: string, p1: string) => {\r\n       if (p1.endsWith(\".jpg\") || p1.endsWith(\".jpeg\") || p1.endsWith(\".png\") || p1.endsWith(\".gif\"))\r\n       {\r\n         return `<a href=\"${p1}\" title=\"${p1}\" target=\"_blank\"><img src=\"${p1}\" alt=\"External image\" style=\"max-width: 400px\"></a>`;\r\n       }\r\n       return `<a href=\"${p1}\" title=\"${p1}\" target=\"_blank\">LINK</a>`;\r\n     });\r\n     return this.$sce.getTrustedHtml(html);\r\n   }\r\n\r\n}","import { SitemapNode } from \"@salaxy/core\";\r\n\r\n/**\r\n * The additional root nodes that should be added in PRO site only\r\n * when the selected account is a Person: Household or Worker (in Raksa/Palkkamylly).\r\n */\r\nexport const sitemap_PersonLeafs: SitemapNode[] = [\r\n  {\r\n    title: \"Laskelmat (henkilö)\",\r\n    url: \"#/person-calc\",\r\n    id: \"personCalc\",\r\n    roles: \"person\",\r\n    children: [\r\n      {\r\n        title: \"Viimeisimmät\",\r\n        url: \"#/calc\",\r\n        id: \"index\",\r\n      },\r\n      {\r\n        title: \"Luonnokset\",\r\n        url: \"#/calc/draft\",\r\n        id: \"draft\",\r\n      },\r\n      {\r\n        title: \"Lähetetyt\",\r\n        url: \"#/calc/shared\",\r\n        id: \"shared\",\r\n      },\r\n      {\r\n        title: \"Palkkalaskelma\",\r\n        url: \"#/calc/details/*\",\r\n        visibility: \"hidden\",\r\n        id: \"details\",\r\n      },\r\n      {\r\n        title: \"Uusi laskelma\",\r\n        url: \"#/calc/details/*/new-for-worker\",\r\n        visibility: \"hidden\",\r\n        id: \"newForWorker\",\r\n      },\r\n      {\r\n        title: \"Laskelman kopio\",\r\n        url: \"#/calc/details/*/copy-as-new\",\r\n        visibility: \"hidden\",\r\n        id: \"copyAsNew\",\r\n      },\r\n      {\r\n        title: \"Työntekijälle maksetut\",\r\n        url: \"#/person-calc/paid-worker\",\r\n        id: \"paidWorker\",\r\n        roles: \"person\"\r\n      },\r\n      {\r\n        title: \"Kotitalouden maksamat\",\r\n        url: \"#/person-calc/paid-household\",\r\n        id: \"paidHousehold\",\r\n        roles: \"person\"\r\n      },\r\n      {\r\n        title: \"Työntekijän lähetetyt\",\r\n        url: \"#/person-calc/sent\",\r\n        roles: \"person\",\r\n        id: \"sent\",\r\n      },\r\n      {\r\n        title: \"Perutut ja virheet\",\r\n        url: \"#/calc/error\",\r\n        roles: \"person\",\r\n        id: \"error\",\r\n      },\r\n    ]\r\n  },\r\n  {\r\n    title: \"Raportit (henkilö)\",\r\n    url: \"#/person-archive/employer-report\",\r\n    id: \"reports\",\r\n    roles: \"person\",\r\n    children: [\r\n      {\r\n        title: \"Työnantajan maksamat palkat\",\r\n        url: \"#/person-archive/employer-report\",\r\n        id: \"personEmployerReport\",\r\n      },\r\n      {\r\n        title: \"Kotitalousvähennys\",\r\n        url: \"#/household-years/active\",\r\n        id: \"householdYears\",\r\n        roles: \"householdService\",\r\n        children: [\r\n          {\r\n            title: \"Kotitalousvähennyksen tiedot\",\r\n            url: \"#/household-years/details/*\",\r\n            visibility: \"hidden\",\r\n            roles: \"householdService\",\r\n            id: \"details\",\r\n          },\r\n        ],\r\n      },\r\n      {\r\n        title: \"Työntekijälle maksetut palkat\",\r\n        url: \"#/person-archive/worker-report\",\r\n        id: \"personWorkerReport\",\r\n      },\r\n      {\r\n        url: \"#/reports/yearly-summary\",\r\n        id: \"yearlySummary\",\r\n      },\r\n      {\r\n        url: \"#/reports/pay-certificate\",\r\n        roles: \"test\",\r\n        id: \"payCertificate\",\r\n      },\r\n      {\r\n        title: \"Laskut\",\r\n        url: \"#/invoices\",\r\n        id: \"invoices\",\r\n        children: [\r\n          {\r\n            title: \"Laskun tiedot\",\r\n            url: \"#/invoices/details/*\",\r\n            visibility: \"hidden\",\r\n            id: \"details\",\r\n          },\r\n        ],\r\n      },\r\n      {\r\n        title: \"Palkkatietoilmoitukset\",\r\n        url: \"#/irepr\",\r\n        children: [{\r\n          title: \"Palkkatietoilmoitus\",\r\n          url: \"#/irepr/details/*\",\r\n        }],\r\n      },\r\n      {\r\n        title: \"Erillisilmoitukset\",\r\n        url: \"#/irpsr\",\r\n        id: \"irpsr\",\r\n        children: [{\r\n          title: \"Erillisilmoitus\",\r\n          url: \"#/irpsr/details/*\",\r\n          id: \"details\",\r\n        }],\r\n      },\r\n    ]\r\n  },\r\n  {\r\n    title: \"Asetukset (henkilö)\",\r\n    url: \"#/person-account\",\r\n    id: \"settings\",\r\n    roles: \"person\",\r\n    children: [\r\n      {\r\n        title: \"Omat tiedot\",\r\n        url: \"#/person-account\",\r\n        id: \"personAccount\",\r\n      },\r\n      {\r\n        url: \"#/settings\",\r\n        id: \"index\",\r\n      },\r\n      {\r\n        title: \"Oma verokortti (työntekijä)\",\r\n        url: \"#/person-taxcards/worker\",\r\n        id: \"workerTaxcard\",\r\n      },\r\n      {\r\n        title: \"Työntekijöiden verokortit\",\r\n        url: \"#/person-taxcards/household\",\r\n        id: \"householdTaxcards\",\r\n      },\r\n      {\r\n        url: \"#/settings/pro-settings\",\r\n        roles: \"test\",\r\n        id: \"proSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/service-settings\",\r\n        id: \"serviceSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/authorizations\",\r\n        id: \"authorizations\",\r\n      },\r\n      {\r\n        title: \"Asiakaspalvelu\",\r\n        id: \"accountants\",\r\n        url: \"#/settings/accountants\",\r\n      },\r\n      {\r\n        id: \"accountReset\",\r\n        url: \"#/settings/account-reset\",\r\n        roles: \"test\",\r\n      },\r\n    ]\r\n  },\r\n];","import { SitemapNode } from \"@salaxy/core\";\r\n\r\n/** The default sitemap tree for Company accounts / users. */\r\nexport const sitemap_Company: SitemapNode[] = [\r\n  {\r\n    url: \"#/\",\r\n    id: \"home\",\r\n    roles: \"company\",\r\n    i18n: [\"SALAXY.NG1_Pages.Home\", \"SALAXY.NG1.WorkerListComponent\", \"SALAXY.NG1.WelcomeComponent\", \"SALAXY.NG1.SigningComponent\", \"SALAXY.NG1.ContactInfoComponent\"],\r\n    params: {\r\n      features: {\r\n        title: \"Features\",\r\n        type: \"array\",\r\n        default: [\"welcome\", \"workerList\", \"contact\"],\r\n        items: {\r\n          type: \"string\",\r\n          enum: [\"welcome\", \"workerList\", \"messages\", \"contact\"]\r\n        }\r\n      },\r\n      newCalcDisabled: {\r\n        title: \"Palkanmaksu estetty\",\r\n        type: \"boolean\",\r\n      },\r\n      newMessageThreadDisabled: {\r\n        title: \"Uuden viestiketjun luonti estetty\",\r\n        type: \"boolean\",\r\n      },\r\n    }\r\n  },\r\n  {\r\n    url: \"#/calc\",\r\n    id: \"calculations\",\r\n    i18n: [\"SALAXY.NG1.CalcListComponent.panel\"],\r\n    roles: \"company\",\r\n    children: [\r\n      {\r\n        url: \"#/calc\",\r\n        id: \"index\",\r\n      },\r\n      {\r\n        url: \"#/payroll\",\r\n        id: \"payroll\",\r\n        children: [\r\n          {\r\n            url: \"#/payroll/details/*\",\r\n            visibility: \"hidden\",\r\n            id: \"details\",\r\n            params: {\r\n              actions: {\r\n                title: \"Readonly actions\",\r\n                type: \"array\",\r\n                default: [],\r\n                items: {\r\n                  type: \"string\",\r\n                  enum: [\"none\", \"copy\", \"pay\", \"cancel\"],\r\n                }\r\n              }\r\n            }\r\n          },\r\n          {\r\n            url: \"#/payroll/import/*\",\r\n            visibility: \"hidden\",\r\n            id: \"import\",\r\n            isFullWidth: true,\r\n          }\r\n        ],\r\n      },\r\n      {\r\n        url: \"#/calc/details/*/new-for-worker\",\r\n        visibility: \"hidden\",\r\n        id: \"newForWorker\",\r\n      },\r\n      {\r\n        url: \"#/calc/details/*/copy-as-new\",\r\n        visibility: \"hidden\",\r\n        id: \"copyAsNew\",\r\n      },\r\n      {\r\n        url: \"#/calc/details/*\",\r\n        visibility: \"hidden\",\r\n        id: \"details\",\r\n        i18n:[\"SALAXY.NG1.CalcComponent\",\"SALAXY.NG1.CalcNewIntroComponent\", \"SALAXY.NG1.CalcDetailsDialogComponent\",  \"SALAXY.NG1.CalcDetailsWorkerComponent\", \"SALAXY.NG1.CalcWorktimeComponent\", \"SALAXY.NG1.CalcDetailsWorktimeProComponent\",  \"SALAXY.NG1.CalcDetailsSalaryComponent\", \"SALAXY.NG1.CalcDetailsExpensesComponent\",\"SALAXY.NG1.CalcRowsComponent\", \"SALAXY.NG1.CalcResultsComponent\", \"SALAXY.NG1.CalcChartComponent\", \"SALAXY.NG1.CalcReportsComponent\"],\r\n      },\r\n      {\r\n        url: \"#/calc/paid\",\r\n        id: \"paid\",\r\n        roles: \"company\",\r\n        i18n:[\"SALAXY.NG1.CalcListComponent\"]\r\n      },\r\n      {\r\n        url: \"#/calc/draft\",\r\n        id: \"draft\",\r\n        i18n:[\"SALAXY.NG1.CalcListComponent\"]\r\n      },\r\n      {\r\n        url: \"#/calc/shared\",\r\n        id: \"shared\",\r\n        i18n:[\"SALAXY.NG1.CalcListComponent\"]\r\n      },\r\n      {\r\n        url: \"#/invoices/sepa\",\r\n        isFullWidth: true,\r\n        id: \"sepaInvoices\",\r\n        roles: \"sepaPartner\",\r\n      },\r\n      {\r\n        url: \"#/invoices/company\",\r\n        id: \"companyInvoices\",\r\n        roles: \"test\",\r\n      },\r\n      {\r\n        title:\"Laskelman muokkaus\",\r\n        url: \"#/calc/editor/*\",\r\n        visibility: \"disabled\",\r\n        isFullWidth: true,\r\n        id: \"editor\",\r\n      },\r\n      {\r\n        url: \"#/calc/import-calcs\",\r\n        id: \"importCalcs\",\r\n        isFullWidth: true,\r\n        roles: \"test\",\r\n      }\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/payroll\",\r\n    id: \"payroll\",\r\n    roles: \"company\",\r\n    visibility: \"hidden\",\r\n    i18n: [\"SALAXY.NG1.PayrollComponent.payrollList\"],\r\n    children: [\r\n      {\r\n        url: \"#/payroll/details/*\",\r\n        visibility: \"hidden\",\r\n        id: \"payrollDetails\",\r\n        i18n: [\"SALAXY.NG1.PayrollComponent.payrollEdit\", \"SALAXY.NG1.PayrollComponent.payrollCalcs\"],\r\n      },\r\n      {\r\n        url: \"#/payroll/import/*\",\r\n        visibility: \"hidden\",\r\n        id: \"import\",\r\n        isFullWidth: true,\r\n      }\r\n    ],\r\n  },\r\n  {\r\n    id: \"messages\",\r\n    url: \"#/messages\",\r\n    roles: \"partnerMessaging\",\r\n    children: [\r\n      {\r\n      url: \"#/messages\",\r\n      id: \"index\",\r\n      i18n:[\"SALAXY.NG1.ActionButtonComponent.startNewMessage\",\"SALAXY.NG1_Pages.Messages.newMessage.title\", \"SALAXY.NG1_Pages.Messages.newMessage.description.html\"]\r\n    },\r\n    {\r\n      id: \"omapalkka\",\r\n      url: \"#/messages/omapalkka\",\r\n      title: \"Omapalkka\",\r\n      roles: \"test\",\r\n      isFullWidth: true,\r\n    },\r\n    {\r\n      title: \"Hyväksyntä\",\r\n      url: \"#/messages/approval-list\",\r\n      id: \"approval\",\r\n      visibility: \"disabled\",\r\n      children: [{\r\n        title: \"Hyväksy / hylkää\",\r\n        url: \"#/messages/approval/*\",\r\n        visibility: \"hidden\",\r\n        isFullWidth: true,\r\n        id: \"details\",\r\n      }],\r\n    },\r\n    {\r\n      url: \"#/messages/details/new\",\r\n      id: \"new\",\r\n      i18n: [\"SALAXY.NG1_Pages.Messages.newMessageDetails.title\",\"SALAXY.NG1_Pages.Messages.newMessageDetails.description.html\"]\r\n    },\r\n    {\r\n      url: \"#/messages/details/*\",\r\n      visibility: \"hidden\",\r\n      id: \"details\",\r\n    }],\r\n  },\r\n  {\r\n    url: \"#/workers\",\r\n    id: \"workers\",\r\n    roles: \"company\",\r\n    children: [\r\n      {\r\n        url: \"#/workers\",\r\n        id: \"index\",\r\n        params: {\r\n          hidden: {\r\n            title: \"Parts to hide from page\",\r\n            type: \"array\",\r\n            default: [],\r\n            items: {\r\n              type: \"string\",\r\n              enum: [\"workers.employments.records.badge\", \"workers.employments.taxCard\", \"workers.employments.buttons.newCalc\", \"workers.employments.employmentId\"]\r\n            }\r\n          }\r\n        }\r\n      },\r\n      {\r\n        url: \"#/employments\",\r\n        visibility: \"hidden\",\r\n        id: \"index\",\r\n        children: [\r\n          {\r\n            url: \"#/employments/index\",\r\n            id: \"index\",\r\n            visibility: \"hidden\",\r\n          },\r\n        ]\r\n      },\r\n      {\r\n        url: \"#/employments/details/*\",\r\n        visibility: \"hidden\",\r\n        id: \"details\",\r\n        i18n:[\"SALAXY.NG1.WorkerDetailsComponent\", \"SALAXY.NG1.WorkerHolidaysComponent\", \"SALAXY.NG1.WorkerAbsencesComponent\"],\r\n        params: {\r\n          features: {\r\n            title: \"Features\",\r\n            type: \"array\",\r\n            default: [\"detailsEdit\", \"employment\", \"calcRows\", \"calculations\", \"taxcards\", \"holidays\", \"absences\"],\r\n            items: {\r\n              type: \"string\",\r\n              enum: [\"detailsEdit\", \"employment\", \"calcRows\", \"calculations\", \"taxcards\", \"holidays\", \"absences\"],\r\n            }\r\n          },\r\n          hidden: {\r\n            title: \"Parts to hide from page\",\r\n            type: \"array\",\r\n            default: [],\r\n            items: {\r\n              type: \"string\",\r\n              enum: [\"detailsEdit\", \"employment\", \"calcRows\", \"calculations\", \"taxcards\", \"holidays\", \"absences\", \"employments.defaultCalcRows.features\", \"employments.calcs.copyAsNew\"]\r\n            }\r\n          }\r\n        },\r\n      },\r\n      {\r\n        url: \"#/workers/details/*\",\r\n        visibility: \"hidden\",\r\n        id: \"details\",\r\n        i18n:[\"SALAXY.NG1.WorkerDetailsComponent\", \"SALAXY.NG1.WorkerHolidaysComponent\", \"SALAXY.NG1.WorkerAbsencesComponent\"],\r\n        params: {\r\n          features: {\r\n            title: \"Features\",\r\n            type: \"array\",\r\n            default: [\"detailsEdit\", \"employment\", \"calcRows\", \"calculations\", \"taxcards\", \"holidays\", \"absences\"],\r\n            items: {\r\n              type: \"string\",\r\n              enum: [\"detailsEdit\", \"employment\", \"calcRows\", \"calculations\", \"taxcards\", \"holidays\", \"absences\"],\r\n            }\r\n          },\r\n        },\r\n      },\r\n      {\r\n        url: \"#/workers/taxcards\",\r\n        id: \"taxcards\",\r\n        i18n:[\"SALAXY.NG1_Pages.Workers.Taxcards.lead\"]\r\n      },\r\n      {\r\n        title: \"Lisää työntekijätili\",\r\n        url: \"#/partners/assure-worker-account\",\r\n        id: \"assureWorkerAccount\",\r\n        isFullWidth: true,\r\n        roles: \"assureWorkerAccount\",\r\n      },\r\n      {\r\n        url: \"#/workers/import-workers\",\r\n        id: \"importWorkers\",\r\n        isFullWidth: true,\r\n        roles: \"test\",\r\n      },\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/reports/holidays\",\r\n    id: \"worktime\",\r\n    isFullWidth: true,\r\n    roles: \"company&&!disableHolidays\",\r\n    children: [\r\n      {\r\n        id: \"holidays\",\r\n        url: \"#/reports/holidays\",\r\n        isFullWidth: true,\r\n      },\r\n      {\r\n        id: \"absences\",\r\n        url: \"#/reports/absences\",\r\n        isFullWidth: true,\r\n      },\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/reports\",\r\n    id: \"reports\",\r\n    roles: \"company\",\r\n    children: [\r\n      {\r\n        url: \"#/reports\",\r\n        id: \"index\",\r\n        i18n: [\"SALAXY.NG1_Pages.Reports.latestReports\", \"SALAXY.NG1.SalaryReportsComponent.calculations\",\"SALAXY.NG1.SalaryReportsComponent.noCalculations\", \"SALAXY.NG1.AccountingReportsComponent.accountingReports\",\"SALAXY.NG1.AccountingReportsComponent.noAccountingReports\", \"SALAXY.NG1.InvoicesComponent.invoices\", \"SALAXY.NG1.InvoicesComponent.noInvoices\"],\r\n        params: {\r\n          features: {\r\n            title: \"Features\",\r\n            type: \"array\",\r\n            default: [\"salaryReportList\", \"accountingReportList\"],\r\n            items: {\r\n              type: \"string\",\r\n              enum: [\"salaryReportList\", \"accountingReportList\", \"invoiceList\"],\r\n            }\r\n          },\r\n        },\r\n      },\r\n      {\r\n        url: \"#/accounting\",\r\n        id: \"accounting\",\r\n        isFullWidth: true,\r\n        children: [{\r\n            url: \"#/accounting/details/*\",\r\n            isFullWidth: true,\r\n            id: \"details\",\r\n            hidden:true,\r\n          }],\r\n      },\r\n      {\r\n        url: \"#/accounting/query\",\r\n        isFullWidth: true,\r\n        id: \"accountingQuery\",\r\n        visibility: \"hidden\",\r\n      },\r\n      {\r\n        url: \"#/accounting/holiday-pay-debt-query\",\r\n        isFullWidth: true,\r\n        id: \"accountingHolidayPayDebtQuery\",\r\n        visibility: \"hidden\",\r\n      },\r\n      {\r\n        url: \"#/reports/salary-reports\",\r\n        id: \"salaryReports\",\r\n      },\r\n      {\r\n        url: \"#/reports/summary-report-query\",\r\n        isFullWidth: true,\r\n        id: \"summaryReportQuery\",\r\n      },\r\n      {\r\n        url: \"#/reports/yearly-summary\",\r\n        id: \"yearlySummary\",\r\n        i18n:[\"SALAXY.NG1_Pages.Reports.yearlySummary\",\"SALAXY.NG1_Pages.Reports.yearlyTitle\"],\r\n      },\r\n      {\r\n        url: \"#/reports/pay-certificate\",\r\n        roles: \"pro\",\r\n        id: \"payCertificate\",\r\n      },\r\n      {\r\n        url: \"#/reports/accounting-legacy\",\r\n        // id: \"accountingLegacy\",\r\n        i18n:[\"SALAXY.NG1_Pages.Reports.accountingIntro\",\"SALAXY.NG1_Pages.Reports.accountingMonthly\", \"SALAXY.NG1_Pages.Reports.accountingYearly\", \"SALAXY.NG1_Sitemap.reports.archive\"],\r\n\r\n        title:\"SALAXY.NG1_Sitemap.personalWeb.archive.main\" // TODO: fix the id and translation\r\n      },\r\n      {\r\n        url: \"#/reports/archive-2018\",\r\n        id: \"archive\",\r\n        visibility: \"hidden\",\r\n      },\r\n      {\r\n        url: \"#/reports/ad-hoc-list\",\r\n        id: \"ad-hoc\",\r\n        roles: \"pro,test\",\r\n        children: [\r\n          {\r\n            url: \"#/reports/ad-hoc/*\",\r\n            isFullWidth: true,\r\n            visibility: \"hidden\",\r\n            id: \"details\",\r\n          },\r\n        ],\r\n      },\r\n      {\r\n        url: \"#/invoices\",\r\n        title:\"Maksut\",\r\n        id: \"invoices\",\r\n        visibility: \"hidden\",\r\n        children: [\r\n          {\r\n            url: \"#/invoices/details/*\",\r\n            visibility: \"hidden\",\r\n            id: \"details\",\r\n            title:\"Maksun tiedot\",\r\n            i18n:[\"SALAXY.NG1_Pages.Invoices\"],\r\n            params: {\r\n              features: {\r\n                title: \"Tabs\",\r\n                type: \"array\",\r\n                default: [\"preview\", \"calc\"],\r\n                items: {\r\n                  type: \"string\",\r\n                  enum: [\"preview\", \"calc\", \"printAndBarCode\", \"actions\"]\r\n                }\r\n              },\r\n            }\r\n          },\r\n        ],\r\n      },\r\n      {\r\n        url: \"#/reports/holiday-report\",\r\n        id: \"holidayReport\",\r\n        visibility: \"visible\",\r\n        isFullWidth: true,\r\n      },\r\n      {\r\n        url: \"#/reports/holiday-pay-report-query/*\",\r\n        isFullWidth: true,\r\n        id: \"holidayPayReportQuery\",\r\n        visibility: \"hidden\",\r\n      },\r\n      {\r\n        url: \"#/irepr\",\r\n        id: \"irepr\",\r\n        roles: \"pro\",\r\n        children: [{\r\n          url: \"#/irepr/details/*\",\r\n          id: \"details\"\r\n        }],\r\n      },\r\n      {\r\n        url: \"#/irpsr\",\r\n        id: \"irpsr\",\r\n        roles: \"pro\",\r\n        children: [{\r\n          url: \"#/irpsr/details/*\",\r\n          id: \"details\",\r\n        }],\r\n      },\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/settings\",\r\n    id: \"settings\",\r\n    roles: \"company\",\r\n    children: [\r\n      {\r\n        url: \"#/settings\",\r\n        id: \"index\",\r\n        params: {\r\n          features: {\r\n            title: \"Features\",\r\n            type: \"array\",\r\n            default: [\"account\", \"insurances\", \"accountant\", \"paymentChannels\"],\r\n            items: {\r\n              type: \"string\",\r\n              enum:  [\"account\", \"insurances\", \"accountant\", \"paymentChannels\"],\r\n            }\r\n          }\r\n        },\r\n      },\r\n      {\r\n        url: \"#/settings/payment-settings\",\r\n        id: \"paymentSettings\",\r\n        i18n: [ \"SALAXY.NG1.PaymentSettingsComponent\"],\r\n\r\n      },\r\n      {\r\n        url: \"#/settings/insurances\",\r\n        id: \"insurances\",\r\n        i18n: [ \"SALAXY.NG1.InsuranceSettingsComponent\"],\r\n      },\r\n      {\r\n        url: \"#/settings/row-types-settings\",\r\n        roles: \"test\",\r\n        id: \"rowTypesSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/payment-channel-settings\",\r\n        id: \"paymentChannelSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/accounting-target-settings\",\r\n        id: \"accountingTargetSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/owner-settings\",\r\n        id: \"ownerSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/service-settings\",\r\n        id: \"serviceSettings\",\r\n      },\r\n      {\r\n        url: \"#/settings/authorizations\",\r\n        id: \"authorizations\",\r\n      },\r\n      {\r\n        id: \"accountants\",\r\n        url: \"#/settings/accountants\",\r\n        roles: \"company\",\r\n        i18n:[\"SALAXY.NG1.AccountantComponent\",\"SALAXY.NG1.AccountantSelectionComponent\"],\r\n        params: {\r\n          \"accountantRemovalDisabled\": {\r\n            title: \"Tilitoimiston poistaminen estetty\",\r\n            type: \"boolean\",\r\n          }\r\n        }\r\n      },\r\n      {\r\n        id: \"integrations\",\r\n        url: \"#/settings/integrations\",\r\n      },\r\n      {\r\n        id: \"accountReset\",\r\n        url: \"#/settings/account-reset\",\r\n        roles: \"test\",\r\n      },\r\n      {\r\n        id: \"paymentChannel\",\r\n        url: \"#/payment-channel\",\r\n        visibility: \"hidden\",\r\n      },\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/service-models/index\",\r\n    id: \"pro-service\",\r\n    roles: \"test&&company\",\r\n    children: [\r\n      {\r\n        url: \"#/service-models/details/*\",\r\n        id: \"details\",\r\n        visibility: \"hidden\",\r\n        isFullWidth: true,\r\n      },\r\n      {\r\n        url: \"#/settings/pro-settings\",\r\n        id: \"proSettings\",\r\n      },\r\n      {\r\n        id: \"usecases\",\r\n        url: \"#/usecases\",\r\n        children: [\r\n          {\r\n            id: \"details\",\r\n            url: \"#/usecases/details/*\",\r\n            isFullWidth: true,\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        id: \"worktime-imports\",\r\n        url: \"#/worktime-imports\",\r\n        isFullWidth: true,\r\n        children: []\r\n      },\r\n      {\r\n        id: \"datasets\",\r\n        title: \"Datasets\",\r\n        url: \"#/datasets\",\r\n        children: [\r\n          {\r\n            id: \"details\",\r\n            title: \"Dataset\",\r\n            url: \"#/datasets/details/*\",\r\n            isFullWidth: true,\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        id: \"calendar-occurences\",\r\n        url: \"#/calendar/occurences\",\r\n        children: []\r\n      },\r\n      {\r\n        id: \"calendar\",\r\n        url: \"#/calendar\",\r\n        children: [\r\n          {\r\n            id: \"details\",\r\n            url: \"#/calendar/details/*\",\r\n          },\r\n          {\r\n            id: \"upload\",\r\n            url: \"#/calendar/upload/*\",\r\n          },\r\n        ]\r\n      },\r\n      {\r\n        url: \"#/accounting-targets\",\r\n        id: \"accountingTargets\",\r\n        children: [{\r\n          url: \"#/accounting-targets/details/*\",\r\n          isFullWidth: true,\r\n          id: \"details\",\r\n        }]\r\n      },\r\n      {\r\n        url: \"#/customer-invoices\",\r\n        id: \"customerInvoices\",\r\n        children: [{\r\n          url: \"#/customer-invoices/details/*\",\r\n          isFullWidth: false,\r\n          id: \"details\",\r\n        }]\r\n      },\r\n    ],\r\n  },\r\n  {\r\n    url: \"#/info\", // info\r\n    id: \"info\",\r\n    children: [\r\n      {\r\n        url: \"#/info\",\r\n        id: \"index\",\r\n        hidden:true,\r\n        i18n:[\"SALAXY.NG1_Pages.Info\", \"SALAXY.NG1.ContactInfoComponent\"],\r\n        params: {\r\n          \"hideButtons\": {\r\n            title: \"Piilota palkkaus.fi-napit\",\r\n            type: \"boolean\",\r\n          },\r\n          \"hideContactInfo\": {\r\n            title: \"Piilota Aspan yhteystiedot\",\r\n            type: \"boolean\",\r\n          },\r\n        },\r\n      },\r\n      {\r\n        url: \"#/info/abc\", // temporary fallback\r\n        id: \"abc\",\r\n        visibility: \"hidden\",\r\n      }\r\n    ],\r\n  },\r\n];","import { Arrays, OpenAPIV3, ServiceModelSite, SitemapNode, SitemapVisibility, UserSession } from \"@salaxy/core\";\r\nimport angular from \"angular\";\r\nimport { sitemap_PersonLeafs } from \"./sitemap_PersonLeafs\";\r\nimport { sitemap_Company } from \"./sitemap_Company\";\r\n\r\n/**\r\n * Helper for managing standard web sitemaps in navigation.\r\n */\r\nexport class SitemapHelper {\r\n\r\n  public constructor() {\r\n    console.debug(\"snowpackHack constructor\");\r\n  }\r\n\r\n  /**\r\n   * Gets logical visibility, as used in the views an UI logic, i.e.:\r\n   *\r\n   * - hidden: Node is null or visibility is Hidden, HiddenReadOnly or Disabled.\r\n   * - readOnly: Node is null or visibility is ReadOnly, HiddenReadOnly.\r\n   * - disabled: Visibility is Disabled.\r\n   * - Visible: Visibility is Visible or null, node is not null.\r\n   * - isFullWidth: The node has an isFullWidth boolean flag set to true.\r\n   * Supports exclamation mark (!) in the beginning to denote negation (true <=> false).\r\n   * @param node Node to evaluate\r\n   * @param evaluateFor The visibility value to evaluate for.\r\n   */\r\n  public static getVisibility(node: SitemapNode, evaluateFor: SitemapVisibility | \"isFullWidth\" | string): boolean {\r\n    if (evaluateFor?.[0] == \"!\") {\r\n      return !this.getVisibility(node, evaluateFor.substring(1));\r\n    }\r\n    switch (evaluateFor) {\r\n      case SitemapVisibility.Disabled:\r\n        return node?.visibility == SitemapVisibility.Disabled;\r\n      case SitemapVisibility.Hidden:\r\n        return node == null || node.visibility == SitemapVisibility.Disabled ||\r\n          node.visibility == SitemapVisibility.Hidden || node.visibility == SitemapVisibility.HiddenReadOnly;\r\n      case SitemapVisibility.HiddenReadOnly:\r\n        // Probably does not really make sense, just for copleteness.\r\n        return this.getVisibility(node, SitemapVisibility.Hidden) || this.getVisibility(node, SitemapVisibility.ReadOnly);\r\n      case SitemapVisibility.ReadOnly:\r\n        return node == null || node.visibility == SitemapVisibility.ReadOnly || node.visibility == SitemapVisibility.HiddenReadOnly;\r\n      case SitemapVisibility.Visible:\r\n        return node != null && (!node.visibility || node.visibility == SitemapVisibility.Visible);\r\n      case \"isFullWidth\":\r\n        return !!node?.isFullWidth;\r\n      default:\r\n        throw new Error(\"Unknown visibility value to evaluate:\" + evaluateFor);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the standard company sitemap for Company web sites.\r\n   */\r\n  public static getCompanySiteMap(): SitemapNode[] {\r\n    return this.setSitemapTitles(sitemap_Company);\r\n  }\r\n\r\n  /**\r\n   * Gets the editable version of the sitemap: Full ID's etc.\r\n   * @param site The Site as customized in the Service model.\r\n   * @param nodes Root nodes to start from. If null, a copy of the baseTree is used.\r\n   * @param parentId Identifier of the parent. Used in recursive calls to add fully qualified ID's to all nodes.\r\n   * @returns An editable sitemap.\r\n   */\r\n  public static getEditableSitemap(site: ServiceModelSite, nodes: SitemapNode[] = null, parentId: string = null): SitemapNode[] {\r\n    const i18Prefix = \"SALAXY.NG1_Sitemap\";\r\n    nodes = nodes || angular.copy(sitemap_Company);\r\n    (nodes || []).forEach((node) => {\r\n      let hasChildrenChanges = false;\r\n      const id = parentId ? `${parentId}.${node.id || \"undefined\"}` : node.id;\r\n      if (node.children) {\r\n        hasChildrenChanges = !!this.getEditableSitemap(site, node.children, id).find((x => x.$edit.$hasChanges || x.$edit.$hasTextChanges || x.$edit.$hasChildrenChanges));\r\n      }\r\n      const isOpen = !!node.$edit?.$isOpen;\r\n      node.$edit = site.sitemap?.[id] ? angular.copy(site.sitemap?.[id]) : {};\r\n      if (Object.keys(node.$edit).length) {\r\n        node.$edit.$hasChanges = true;\r\n      }\r\n      node.$edit.$hasChildrenChanges = hasChildrenChanges;\r\n      node.$edit.$isOpen = isOpen;\r\n      node.$edit.$id = id;\r\n      const sectionPostFix = node.children ? \".main\" : \"\";\r\n      node.$edit.$i18nKey = `${i18Prefix}.${id}${sectionPostFix}`;\r\n      if (Object.keys(site.texts ?? {}).find((x) => x.endsWith(node.$edit.$i18nKey))) {\r\n        node.$edit.$hasTextChanges = true;\r\n      }\r\n      switch (node.$edit.visibility || node.visibility) {\r\n        case SitemapVisibility.Disabled:\r\n          node.$edit.$faIcons = [\"fa-ban\"];\r\n          break;\r\n        case SitemapVisibility.Hidden:\r\n          node.$edit.$faIcons = [\"fa-eye-slash\"];\r\n          break;\r\n        case SitemapVisibility.HiddenReadOnly:\r\n          node.$edit.$faIcons = [\"fa-eye-slash\", \"fa-lock\"];\r\n          break;\r\n        case SitemapVisibility.ReadOnly:\r\n          node.$edit.$faIcons = [\"fa-lock\"];\r\n          break;\r\n        case SitemapVisibility.Visible:\r\n        default:\r\n          node.$edit.$faIcons = [];\r\n          break;\r\n      }\r\n      if (node.isFullWidth || node.$edit.isFullWidth) {\r\n        node.$edit.$faIcons.push(\"fa-arrows-h\");\r\n      }\r\n      node.$edit.visibility = node.$edit.visibility || \"default\";\r\n      // TODO: Add proper Array editor and remove this (also in commitSitemapNode()).\r\n      node.$edit.roles = Arrays.assureArray(node.$edit.roles).join(\",\");\r\n      // Direct title is not supported in translations, but it may be used development time.\r\n      node.title = node.title ? node.title : node.$edit.$i18nKey;\r\n    });\r\n    return nodes;\r\n  }\r\n\r\n  /**\r\n   * Applies custom properties from service model to set of sitemap nodes.\r\n   * Also does backward compatibility from old SalaxySitemapNode format to current SitemapNode.\r\n   * @param session User session that potentially contains the service model.\r\n   * If null or no partner.serviceModel.sitemap, the method does nothing.\r\n   * @param nodes Nodes that are being updated.\r\n   * @param parentId Identifier of the parent. Used in recursive calls to add fully qualified ID's to all nodes.\r\n   */\r\n  public static setCustomProperties(session: UserSession, nodes: SitemapNode[], parentId: string = null): void {\r\n    if (!nodes?.length) {\r\n      return;\r\n    }\r\n    const sitemapProps = session?.settings?.partner?.serviceModel?.site?.sitemap;\r\n    nodes.forEach((node) => {\r\n      // \"company-site\" is special root id for the situation when the company site is not the root, e.g. developers.salaxy.com (webs/ng1-dev)\r\n      const id = (parentId && parentId != \"company-site\") ? `${parentId}.${node.id || \"undefined\"}` : node.id;\r\n\r\n      // Backward compatibility\r\n      if (node.hidden && !node.visibility) {\r\n        node.visibility = SitemapVisibility.Hidden;\r\n      }\r\n\r\n      // Set custom properties.\r\n      if (sitemapProps) {\r\n        if (sitemapProps[id]) {\r\n          Object.keys(sitemapProps[id]).forEach((key) => {\r\n            const value = sitemapProps[id][key];\r\n            if (value) {\r\n              node[key] = value;\r\n            }\r\n          });\r\n        }\r\n      }\r\n      this.setCustomProperties(session, node.children, id);\r\n    });\r\n  }\r\n\r\n  /** This just to get snowpack working. */\r\n  public snowpackHack(): string {\r\n    return \"snowpackHack\";\r\n  }\r\n\r\n  /**\r\n   * Gets the combined sitemap that contains the structure for both company\r\n   * and personal (Worker, Household). this is used mainly in development and PRO service:\r\n   * typically, company and personal sites are separate and this tree is not used.\r\n   */\r\n   public static getAllRolesSiteMap(): SitemapNode[] {\r\n     const tree = angular.copy(sitemap_Company);\r\n     tree.splice(tree.length - 1, 0, ...sitemap_PersonLeafs);\r\n     return this.setSitemapTitles(tree);\r\n  }\r\n\r\n  /**\r\n   * Sets the titles for each node in given sitemap based on node id from the given tranlsation.\r\n   * @param sitemap Selected sitemap to add titles to\r\n   * @param currentPath Current node in sitemap object\r\n   * @param i18Prefix Translation key prefix (defaults to SALAXY.NG1_Sitemap)\r\n   */\r\n  public static setSitemapTitles(sitemap: SitemapNode[], currentPath = \"\", i18Prefix = \"SALAXY.NG1_Sitemap\"): SitemapNode[] {\r\n    for (const node of sitemap) {\r\n      const newPath = currentPath ? `${currentPath}.${node.id}` : node.id;\r\n      const sectionPostFix = node.children ? \".main\" : \"\";\r\n      node.title = node.title ? node.title : `${i18Prefix}.${newPath}${sectionPostFix}`;\r\n      if (node.children) {\r\n        this.setSitemapTitles(node.children, newPath, i18Prefix);\r\n      }\r\n    }\r\n    return sitemap;\r\n  }\r\n\r\n\r\n  /**\r\n   * Removes a section based on id.\r\n   * @param sitemap Sitemap from which the section is removed.\r\n   * @param sectionId Identifier for finding the section to remove.\r\n   */\r\n  public static removeSection(sitemap: SitemapNode[], sectionId: string): void {\r\n    const index = sitemap.findIndex((x) => x.id === sectionId);\r\n    if (index >= 0) {\r\n      sitemap.splice(index, 1);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets a section based on id.\r\n   * @param sitemap Sitemap from which the section is fetched.\r\n   * @param sectionId Identifier for finding the section to remove.\r\n   */\r\n  public static getSection(sitemap: SitemapNode[], sectionId: string): SitemapNode {\r\n    return sitemap.find((x) => x.id === sectionId);\r\n  }\r\n\r\n  /**\r\n   * Gets a node (subpage) based on id.\r\n   * @param sitemap Sitemap from which the section is fetched.\r\n   * @param sectionId Identifier for finding the section.\r\n   * @param nodeId Identifier for finding the node (subpage to modify or hide).\r\n   */\r\n  public static getNode(sitemap: SitemapNode[], sectionId: string, nodeId: string): SitemapNode {\r\n    const section = this.getSection(sitemap, sectionId);\r\n    if (!section || !section.children) {\r\n      return null;\r\n    }\r\n    return section.children.find((x) => x.id === nodeId);\r\n  }\r\n\r\n  /**\r\n   * Gets a JSON schema of a sitemap node using the params property.\r\n   * NOTE: Advanced properties (i18n, children and params) are not included in this schema. Add if needed.\r\n   */\r\n  public static getSchema(node: SitemapNode): OpenAPIV3.SchemaObject {\r\n    const result: OpenAPIV3.SchemaObject = {\r\n      title: \"Current sitemap node\",\r\n      type: \"object\",\r\n      properties: {\r\n        id: {\r\n          title: \"Identifier for the node: Should be unique within one set of children.\",\r\n          type: \"string\",\r\n        },\r\n        title: {\r\n          title: \"Hard-coded single-language title. This should be used in dev/testing only\",\r\n          type: \"string\",\r\n        },\r\n        url: {\r\n          title: \"Navigation URL for the node.\",\r\n          type: \"string\",\r\n        },\r\n        roles: {\r\n          title: \"Roles for limiting the visibility of the node.\",\r\n          anyOf: [\r\n            {\r\n                \"type\": \"string\",\r\n            },\r\n            {\r\n              type: \"array\",\r\n              items: { type: \"string\" }\r\n            }\r\n          ]\r\n        },\r\n        visibility: {\r\n          title: \"Specifies how the node is shown in the navi / UI. Default / null is 'visible'.\",\r\n          type: \"string\",\r\n        },\r\n        isFullWidth: {\r\n          title: \"If true, sets container class to container-fluid\",\r\n          type: \"string\",\r\n        },\r\n        /*\r\n        i18n: {\r\n          title: \"\",\r\n          type: \"array\",\r\n          items: {\r\n            type: \"string\",\r\n          }\r\n        },\r\n        children: {\r\n          title: \"Array of child nodes.\",\r\n          type: \"object\",\r\n        },\r\n        params: {\r\n          title: \"Defines the json schema for parameters that may be defined for a single node/page.\",\r\n          type: \"object\",\r\n        }\r\n        */\r\n      }\r\n    };\r\n    if (node.params) {\r\n      result.properties = {...result.properties, ...node.params};\r\n    }\r\n    return result;\r\n  }\r\n}\r\n","import { JsonSchemaUtils, Objects, SitemapNode, SitemapVisibility } from \"@salaxy/core\";\r\nimport { SitemapHelper } from \"./SitemapHelper\";\r\n\r\n/** Contains information about the current sitemap node (if resoved) and other data related to route. */\r\nexport class CurrentRoute {\r\n  constructor(currentPath: SitemapNode[]) {\r\n    if (currentPath?.length) {\r\n      this.isResolved = true;\r\n      this.path = currentPath;\r\n      this.node = currentPath[currentPath.length - 1],\r\n      this.section = currentPath[0];\r\n    } else {\r\n      this.isResolved = false;\r\n      this.node = null;\r\n      this.path = [];\r\n      this.section = null;\r\n    }\r\n  }\r\n\r\n  /** The current path if resolved, otherwise an empty array */\r\n  public path: SitemapNode[];\r\n\r\n  /** The current sitemap node */\r\n  public node: SitemapNode;\r\n\r\n  /** The current section if resolved. */\r\n  public section: SitemapNode;\r\n\r\n  /** If true, the route is resolved to current sitemap node. */\r\n  public isResolved: boolean;\r\n\r\n  /**\r\n   * Gets logical visibility, as used in the views an UI logic, i.e.:\r\n   *\r\n   * - hidden: Node is null or visibility is Hidden, HiddenReadOnly or Disabled.\r\n   * - readOnly: Node is null or visibility is ReadOnly, HiddenReadOnly.\r\n   * - disabled: Visibility is Disabled.\r\n   * - Visible: Visibility is Visible or null, node is not null.\r\n   * - isFullWidth: The node has an isFullWidth boolean flag set to true.\r\n   *\r\n   * Supports exclamation mark (!) in the beginning to denote negation (true <=> false).\r\n   * @param visibility The visibility value to evaluate for.\r\n   */\r\n  public getVisibility(visibility: SitemapVisibility | string): boolean {\r\n    return SitemapHelper.getVisibility(this.node, visibility);\r\n  }\r\n\r\n  /** Returns true if the page should be displayed read-only */\r\n  public get readOnly(): boolean {\r\n    return SitemapHelper.getVisibility(this.node, SitemapVisibility.ReadOnly);\r\n  }\r\n\r\n  /**\r\n   * Gets a parameter checking the default value from the schema.\r\n   * The method fails if the parameter is not defined in the schema.\r\n   * @param path Path to the sitemap value / schema definition.\r\n   */\r\n  public getParam(path: string) {\r\n    if (!this.node?.params) {\r\n      throw new Error(`The current node ${this.node?.url} does not have parameters defined (path: '${path}').`);\r\n    }\r\n    const prop = JsonSchemaUtils.getProperty(SitemapHelper.getSchema(this.node), path);\r\n    if (!prop) {\r\n      throw new Error(`The current node ${this.node.url} does not have property ${path} defined in the schema.`);\r\n    }\r\n    const value = Objects.getProperty(this.node, path);\r\n    if (value != null) {\r\n      return value; // Nullish values go to default.\r\n    }\r\n    if (prop.schema.default !== undefined) {\r\n      return prop.schema.default; // Default may be null?\r\n    }\r\n    return null; // Should boolean values default to false?\r\n  }\r\n\r\n  /**\r\n   * Checks if the value contain the given flag value.\r\n   * Typically the value is an array of enum strings and this method checks if it contains an item,\r\n   * but the method also checks for a direct match (without being an array).\r\n   * @param path Path to the sitemap value / schema definition.\r\n   * @param flagValue Text value (typically a string enum) that should be present in the array.\r\n   */\r\n  public getFlag(path: string, flagValue: string): boolean {\r\n    const val = this.getParam(path);\r\n    if (Array.isArray(val)) {\r\n      return !!val.find((x) => x == flagValue);\r\n    }\r\n    return val == flagValue;\r\n  }\r\n\r\n}","import angular from \"angular\";\r\n\r\n/**\r\n * Polyfill which replaces ES6 promises with $q.\r\n * This is required, for example if Promise.resolve -methods are used.\r\n * They are not correctly digested using ES6 promises only.\r\n */\r\nexport class PromisePolyfill {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n\r\n   /** Dependencies */\r\n  public static $inject = [\"$q\", \"$window\"];\r\n  constructor($q: angular.IQService, $window: angular.IWindowService) {\r\n    $window.Promise = function (resolver) {\r\n      return $q(resolver);\r\n    };\r\n\r\n    $window.Promise.all = $q.all.bind($q);\r\n    $window.Promise.reject = $q.reject.bind($q);\r\n    $window.Promise.resolve = $q.resolve.bind($q);\r\n    $window.Promise.race = $q.race.bind($q);\r\n    $window.Promise.allSettled = ((promises) => $window.Promise.all(promises.map(p => p\r\n      .then(value => ({\r\n          status: \"fulfilled\", value\r\n      }))\r\n      .catch(reason => ({\r\n          status: \"rejected\", reason\r\n      }))\r\n    )));\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Configs} from \"@salaxy/core\";\r\n\r\n/** Helps creating Salaxy standard routing. */\r\nexport class RouteHelperProvider implements angular.IServiceProvider {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  protected static $inject = [\"$routeProvider\"];\r\n\r\n  /** The root folder that contains the custom views. Default is \"./views\" */\r\n  public customSectionRoot = \"./views\";\r\n\r\n  /**\r\n   * TODO: Consider implementing the IServiceProvider interface\r\n   */\r\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n  public $get = [\"$rootScope\" , ($rootScope: any) => {\r\n    return \"todo\";\r\n  }];\r\n\r\n  public constructor(private $routeProvider: angular.route.IRouteProvider) {\r\n  }\r\n\r\n  /**\r\n   * Adds a routing section where views are coming by default from custom folder.\r\n   * @param section Navigation section in routing.\r\n   * Also used as default for views folder.\r\n   * @param defaultViews Exceptions to the rule: Individual views / pages that should be mapped\r\n   * to default views stored in ng1 library under \"salaxy-components/pages/\".\r\n   * @param defaultViewsFolder The name of the default views folder if not the same as section.\r\n   * If not specified, the folder is \"salaxy-components/pages/[section]\".\r\n   * If the paths starts with \"salaxy-components\", \"/\" or \".\", the path is assumed being a full path.\r\n   * Otherwise the \"salaxy-components/pages/\" is added before defaultViewsFolder. So typically this can be just a folder / section name (e.g. \"calc\").\r\n   * @param customViewsFolder If specified, this is the path to the custom folder where the views are.\r\n   * If NOT specified, \"[customSectionRoot]/[section]\" is used.\r\n   * If the paths starts with \"/\" or \".\", the path is assumed being a full path.\r\n   * Otherwise the customSectionRoot (default \"./views/\") is added before customViewsFolder. So typically this can be just a folder / section name (e.g. \"calc\").\r\n   * @example\r\n   * RouteHelperProvider.customSection(\"calc\", [\"details\"]).\r\n   * // Adds a route as \"/calc/:viewName?/:crudItemId*?\" where all views are located in \"./views/calc/[:viewName].html\",\r\n   * // except \"/calc/details/:crudItemId*?\", which is mapped to \"salaxy-components/pages/calc/details.html\"\r\n   */\r\n  public customSection(section: string, defaultViews?: string[], defaultViewsFolder?: string, customViewsFolder?: string): RouteHelperProvider {\r\n    defaultViewsFolder = defaultViewsFolder || section;\r\n    if (!defaultViewsFolder.startsWith(\".\") && !defaultViewsFolder.startsWith(\"/\") && !defaultViewsFolder.startsWith(\"salaxy-components/\")) {\r\n      defaultViewsFolder = \"salaxy-components/pages/\" + defaultViewsFolder;\r\n    }\r\n    customViewsFolder = customViewsFolder || section;\r\n    if (!customViewsFolder.startsWith(\".\") && !customViewsFolder.startsWith(\"/\") && !customViewsFolder.startsWith(\"salaxy-components/\")) {\r\n      customViewsFolder = this.customSectionRoot + \"/\" + customViewsFolder;\r\n    }\r\n    if (defaultViews && Array.isArray(defaultViews)) {\r\n      defaultViews.forEach((view) => {\r\n        this.when(`/${section}/${view}/:crudItemId*?`, { templateUrl: `${defaultViewsFolder}/${view}.html` }, section);\r\n      });\r\n    }\r\n    this.when(`/${section}/:viewName?/:crudItemId*?`, {\r\n      templateUrl: (path) => `${customViewsFolder}/${path.viewName || \"index\"}.html`,\r\n    }, section);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Adds a routing section where views are coming by default from the product ng1 library compiled to \"salaxy-components/pages/\".\r\n   * @param section Section for the views, e.g. \"calc\" for \"salaxy-components/pages/calc\"\r\n   * @param customViews Exceptions to the rule:\r\n   * Individual views that should be mapped to custom folder under customSectionRoot.\r\n   * @param customViewsFolder The name of the custom views folder if not the same as section.\r\n   * If the paths starts with \"/\" or \".\", the path is assumed being a full path.\r\n   * Otherwise the customSectionRoot (default \"./views/\") is added before customViewsFolder. So typically this can be just a folder / section name (e.g. \"calc\").\r\n   * @param defaultViewsFolder The name of the default views folder if not the same as section.\r\n   * If not specified, the folder is \"salaxy-components/pages/[section]\".\r\n   * If the paths starts with \"salaxy-components\", \"/\" or \".\", the path is assumed being a full path.\r\n   * Otherwise the \"salaxy-components/pages/\" is added before defaultViewsFolder. So typically this can be just a folder / section name (e.g. \"calc\").\r\n   * @example\r\n   * RouteHelperProvider.defaultSection(\"calc\", [\"details\"], \"ng1/calc\").\r\n   * // Adds a route as \"/calc/:viewName?/:crudItemId*?\" where all views are located in \"salaxy-components/pages/calc/\" folder\r\n   * // except \"/calc/details/:crudItemId*?\", which is mapped to \"./views/ng1/calc/details.html\".\r\n   */\r\n  public defaultSection(section: string, customViews?: string[], customViewsFolder?: string, defaultViewsFolder?: string): RouteHelperProvider {\r\n    customViewsFolder = customViewsFolder || section;\r\n    if (!customViewsFolder.startsWith(\".\") && !customViewsFolder.startsWith(\"/\") && !customViewsFolder.startsWith(\"salaxy-components/\")) {\r\n      customViewsFolder = this.customSectionRoot + \"/\" + customViewsFolder;\r\n    }\r\n    defaultViewsFolder = defaultViewsFolder || section;\r\n    if (!defaultViewsFolder.startsWith(\".\") && !defaultViewsFolder.startsWith(\"/\") && !defaultViewsFolder.startsWith(\"salaxy-components/\")) {\r\n      defaultViewsFolder = \"salaxy-components/pages/\" + defaultViewsFolder;\r\n    }\r\n    if (customViews && Array.isArray(customViews)) {\r\n      customViews.forEach((view) => {\r\n        if (view === \"index\") {\r\n          this.when(`/${section}/index/:crudItemId*?`, { templateUrl: `${customViewsFolder || section}/index.html` }, section);\r\n          this.when(`/${section}`, { templateUrl: `${customViewsFolder || section}/index.html` }, section);\r\n        } else {\r\n          this.when(`/${section}/${view}/:crudItemId*?`, { templateUrl: `${customViewsFolder || section}/${view}.html` }, section);\r\n        }\r\n      });\r\n    }\r\n    this.when(`/${section}/:viewName?/:crudItemId*?`, {\r\n      templateUrl: (path) => `${defaultViewsFolder}/${path.viewName || \"index\"}.html`,\r\n    }, section);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Fluid syntax for setting customSectionRoot.\r\n   * @param customSectionRoot Root folder for the custom views.\r\n   * You can use null to set the customSection to default \"./views\", empty string to none.\r\n   * No trailing dashes i.e. \"./views\", not \"./views/\".\r\n   */\r\n  public setCustomSectionRoot(customSectionRoot: string | null): RouteHelperProvider {\r\n    if (customSectionRoot == null) {\r\n      customSectionRoot = \"./views\";\r\n    }\r\n    this.customSectionRoot = customSectionRoot;\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Adds the standard index/home pages: \"/\", \"/index\" and \"/welcome\".\r\n   * May later contain special pages like standard error etc.\r\n   * NOTE: If any of the sections already exists, will not add them.\r\n   * @param customViewsFolder if set, uses the given custom folder. Otherwise, sets the paths from library.\r\n   */\r\n  public homeDefault(customViewsFolder?: string): RouteHelperProvider {\r\n    const homePage = customViewsFolder ? `${this.customSectionRoot}/${customViewsFolder}/index.html` : \"salaxy-components/pages/home/index.html\";\r\n    if (!this.sectionExists(\"\")) {\r\n      this.when(\"/\", { templateUrl: homePage }, \"\");\r\n    }\r\n    if (!this.sectionExists(\"index\")) {\r\n      this.when(\"/index\", { templateUrl: homePage }, \"index\");\r\n    }\r\n    if (!this.sectionExists(\"welcome\")) {\r\n      this.when(\"/welcome\", { templateUrl: homePage }, \"welcome\");\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * For backward compatibility only: Use commit() instead.\r\n   * @deprecated For backward compatibility only: Use commit() instead.\r\n   */\r\n  public otherwiseDefault(): void {\r\n    this.commit();\r\n  }\r\n\r\n  /**\r\n   * Equivalent for calling $routeProvider.when(): Adds a new route definition to the $route service.\r\n   * Call commit() method for these configurations to have an effect.\r\n   * @param path Route path (matched against $location.path). If $location.path contains redundant trailing slash or is missing one, the route will still match and the $location.path will be updated to add or drop the trailing slash to exactly match the route definition.\r\n   *\r\n   * - path can contain named groups starting with a colon: e.g. :name. All characters up to the next slash are matched and stored in $routeParams under the given name when the route matches.\r\n   * - path can contain named groups starting with a colon and ending with a star: e.g.:name*. All characters are eagerly stored in $routeParams under the given name when the route matches.\r\n   * - path can contain optional named groups with a question mark: e.g.:name?.\r\n   *\r\n   * For example, routes like /color/:color/largecode/:largecode*\\/edit will match /color/brown/largecode/code/with/slashes/edit and extract: color: brown and largecode: code/with/slashes.\r\n   * @param route Mapping information to be assigned to $route.current on route match.\r\n   * @param section identifies the section for later evaluating whether a certain section has been defined or not:\r\n   * This is used in adding the deafults at the commit(): If section is found, it is not filled with defaults\r\n   * E.g. for path \"/calc/details\" this would be \"calc\" and \"/\", it would be \"\".\r\n   * Please note that in the \"calc\" case you would need to make sure all the other \"calc section\" routes are handled,\r\n   * typically by calling defaultSection(\"calc\") or customSection(\"calc\") within the router config.\r\n   */\r\n  public when(path: string, route: angular.route.IRoute, section: string): RouteHelperProvider {\r\n    this.routeModel.when.push({ section, path, route });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Equivalent for calling $routeProvider.otherwise():\r\n   * Sets route definition that will be used on route change when no other route definition is matched.\r\n   * Call commit() method for these configurations to have an effect.\r\n   * @param params information to be assigned to $route.current.\r\n   */\r\n  public otherwise(params: angular.route.IRoute | string): RouteHelperProvider {\r\n    this.routeModel.otherwise = params;\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Used in Development and PRO sites to add the Person (Worker/Household) related routes.\r\n   * Typically, sites that target Person accounts are specialized and will not use this method.\r\n   */\r\n  public addPersonRoutes() : RouteHelperProvider {\r\n    this.customSection(\"person-archive\", [], \"salaxy-components/pages-personal/archive\", \"salaxy-components/pages-personal/archive\");\r\n    this.customSection(\"person-account\", [], \"salaxy-components/pages-personal/account\", \"salaxy-components/pages-personal/account\");\r\n    this.customSection(\"person-calc\", [], \"salaxy-components/pages-personal/calc\", \"salaxy-components/pages-personal/calc\");\r\n    this.customSection(\"person-taxcards\", [], \"salaxy-components/pages-personal/taxcards\", \"salaxy-components/pages-personal/taxcards\");\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Commits the intermediary routeModel to the AngularJS $routeProvider.\r\n   * If skipDefault is not set to true, will set the defaults by calling\r\n   * homeDefault(), defaultSection for each product section and otherwiseDefault\r\n   * if the corresponding sections have not already been defined.\r\n   * @param skipDefaults By default, the method first adds all the product-defined\r\n   * default routes to the routeModel. If true, will not add the default routes.\r\n   */\r\n  public commit(skipDefaults = false): void {\r\n    if (this.routeModel.isCommitted) {\r\n      throw new Error(\"RouteHelperProvider.commit() called more than once. This is not supported. Are you calling both otherwiseDefault() and commit()? The first is obsolete since the introduction of commit().\");\r\n    }\r\n    if (!skipDefaults) {\r\n      this.homeDefault();\r\n      this.addIfNotExists(\"home\");\r\n      this.addIfNotExists(\"accounting\");\r\n      this.addIfNotExists(\"calc\");\r\n      this.addIfNotExists(\"customer-invoices\");\r\n      this.addIfNotExists(\"datasets\");\r\n      this.addIfNotExists(\"messages\");\r\n      this.addIfNotExists(\"service\");\r\n      this.addIfNotExists(\"payroll\");\r\n      this.addIfNotExists(\"reports\");\r\n      this.addIfNotExists(\"irepr\");\r\n      this.addIfNotExists(\"irpsr\");\r\n      this.addIfNotExists(\"settings\");\r\n      this.addIfNotExists(\"accounting-targets\");\r\n      this.addIfNotExists(\"info\");\r\n      this.addIfNotExists(\"welcome\");\r\n      this.addIfNotExists(\"employments\");\r\n      this.addIfNotExists(\"workers\");\r\n      this.addIfNotExists(\"partners\");\r\n      this.addIfNotExists(\"invoices\");\r\n      this.addIfNotExists(\"payment-channel\");\r\n      this.addIfNotExists(\"earnings-payments\");\r\n      this.addIfNotExists(\"salary-reports\");\r\n      this.addIfNotExists(\"test\");\r\n      this.addIfNotExists(\"calendar\");\r\n      this.addIfNotExists(\"usecases\");\r\n      this.addIfNotExists(\"worktime-imports\");\r\n      this.addIfNotExists(\"service-models\");\r\n      this.addIfNotExists(\"household-years\");\r\n      this.addIfNotExists(\"worktime-imports\");\r\n      if (Configs.current?.isTestData) {\r\n        this.addIfNotExists(\"reference-objects\");\r\n      }\r\n\r\n      if (!this.routeModel.otherwise) {\r\n        this.routeModel.otherwise = { templateUrl: \"salaxy-components/pages/home/error404.html\" };\r\n      }\r\n    }\r\n    for (const when of this.routeModel.when) {\r\n      this.$routeProvider.when(when.path, when.route);\r\n    }\r\n    if (this.routeModel.otherwise) {\r\n      this.$routeProvider.otherwise(this.routeModel.otherwise);\r\n    }\r\n    this.routeModel.isCommitted = true;\r\n  }\r\n\r\n  /** Stores the route definition until Commit is being called. */\r\n  public routeModel: routeProviderModel = {\r\n    when: [],\r\n  };\r\n\r\n  /**\r\n   * Returns true if the sction is already defined in the route model.\r\n   * @param section Section for the views, e.g. \"calc\" for \"salaxy-components/pages/calc\"\r\n   */\r\n  public sectionExists(section: string): boolean {\r\n    return !!this.routeModel.when.find((x) => x.section === section);\r\n  }\r\n\r\n  /**\r\n   * Calls the defaultSection(section), but only if the sectrion has not been defined with custom values.\r\n   */\r\n  public addIfNotExists(section: string): boolean {\r\n    if (this.sectionExists(section)) {\r\n      return false;\r\n    }\r\n    this.defaultSection(section);\r\n    return true;\r\n  }\r\n}\r\n\r\n/** Defines a model that sotres the route until Commit is called to really register the route to Angular. */\r\nexport interface routeProviderModel {\r\n\r\n  /** Array of when statements that make up the route */\r\n  when: {\r\n    /** Identifies the section as simple string (e.g. 'calc'). */\r\n    section: string,\r\n    /**\r\n     * Route path (matched against $location.path). If $location.path contains redundant trailing slash or is missing one, the route will still match and the $location.path will be updated to add or drop the trailing slash to exactly match the route definition.\r\n     *\r\n     * - path can contain named groups starting with a colon: e.g. :name. All characters up to the next slash are matched and stored in $routeParams under the given name when the route matches.\r\n     * - path can contain named groups starting with a colon and ending with a star: e.g.:name*. All characters are eagerly stored in $routeParams under the given name when the route matches.\r\n     * - path can contain optional named groups with a question mark: e.g.:name?.\r\n     *\r\n     * For example, routes like /color/:color/largecode/:largecode*\\/edit will match /color/brown/largecode/code/with/slashes/edit and extract: color: brown and largecode: code/with/slashes.\r\n     */\r\n    path: string,\r\n\r\n    /** Mapping information to be assigned to $route.current on route match. */\r\n    route: angular.route.IRoute,\r\n  }[]\r\n\r\n  /** The deafult route (otherwise) */\r\n  otherwise?: angular.route.IRoute | string,\r\n  /** True if the route has been committed to Angular. */\r\n  isCommitted?: boolean;\r\n\r\n}\r\n","export const RRuleFinnish: {\r\n  /** Names of days */\r\n  dayNames: string[]\r\n  /** Names of months */\r\n  monthNames: string[]\r\n  /** Tokens for natural language parsing (NOT IN USE!) */\r\n  tokens: {\r\n    [k: string]: RegExp\r\n  }\r\n  /** The key texts that are used by the gettext method. */\r\n  texts: {\r\n    [k: string]: string\r\n  }\r\n} = {\r\n  dayNames: [\r\n    \"Sunnuntai\", \"Maanantai\", \"Tiisatai\", \"Keskiviikko\",\r\n    \"Torstai\", \"Perjantai\", \"Lauantai\"\r\n  ],\r\n  monthNames: [\r\n    \"Tammikuu\", \"Helmikuu\", \"Maaliskuu\", \"Huhtikuu\", \"Toukokuu\",\r\n    \"Kesäkuu\", \"Heinäkuu\", \"Elokuu\", \"Syyskuu\", \"Lokakuu\",\r\n    \"Marraskuu\", \"Joulukuu\"\r\n  ],\r\n  tokens: {},\r\n  texts: {\r\n    \"(~ approximate)\": \"(~ noin)\",\r\n    \"and\": \"ja\",\r\n    \"at\": \"klo\",\r\n    \"day\": \"päivä\",\r\n    \"days\": \"päivä\",\r\n    \"every\": \"joka\",\r\n    \"for\": \",\",\r\n    \"hour\": \"tunti\",\r\n    \"hours\": \"tunti\",\r\n    \"in\": \", vain kuukausina:\", // TODO: Is this used in other cases\r\n    \"last\": \"viimeisenä päivänä\",\r\n    \"minutes\": \"min\",\r\n    \"month\": \"kuukausi\",\r\n    \"months\": \"kuukausi\",\r\n    \"nd\": \".\",\r\n    \"on the\": \"aina\",\r\n    \"on\": \"on\", // TODO\r\n    \"or\": \"tai\",\r\n    \"rd\": \".\",\r\n    \"st\": \".\",\r\n    \"th\": \".\",\r\n    \"the\": \"\",\r\n    \"time\": \"kerta\",\r\n    \"times\": \"kertaa\",\r\n    \"until\": \"päättyen\",\r\n    \"week\": \"viikko\",\r\n    \"weekday\": \"viikonpäivä\",\r\n    \"weekdays\": \"viikonpäivä\",\r\n    \"weeks\": \"viikko\",\r\n    \"year\": \"vuosi\",\r\n    \"years\": \"vuosi\",\r\n    \"RRule error: Unable to fully convert this rrule to text\": \"Virhe: En ymmärrä tekstiä\"\r\n  }\r\n};\r\n","import angular from \"angular\";\r\n\r\nimport { Arrays, AppStatus, RoleLogic, SitemapNode, UserSession } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"./../SessionService\";\r\nimport { CurrentRoute, SitemapHelper } from \"../../helpers\";\r\n\r\n\r\n/**\r\n * Helper service to generate navigation controls:\r\n * Top- and side-menus, paths and controls that show the current title.\r\n * These controls take the navigation logic from an object (sitemap) and are aware of current node / open page on that sitemap.\r\n * NOTE: This is just an optional helper to make creating simple demo sites easier.\r\n * There is no need to use NaviService, NaviController or components in your custom site!\r\n * You can use something completely different.\r\n */\r\nexport class NaviService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\", \"$location\", \"SessionService\", \"$injector\"];\r\n\r\n  /**\r\n   * Contains information about the current sitemap node (if resoved) and other data related to route.\r\n   * This property takes into account that the current node may not be found,\r\n   * i.e. current.node may be null, current.path may be [].\r\n   * However, the \"route\" as an object should never be null.\r\n   * Most other properties in NaviService use first node as default for historical reasons.\r\n   */\r\n  public current: CurrentRoute = new CurrentRoute(null);\r\n\r\n  /**\r\n   * Section where the current node is located.\r\n   * If current node cannot be resolved, this property defaults to first Sitemap node.\r\n   */\r\n  public currentSection: SitemapNode;\r\n\r\n  /**\r\n   * Currently selected sitemap node.\r\n   * If current node cannot be resolved, this property defaults to first Sitemap node.\r\n   */\r\n  public currentNode: SitemapNode;\r\n\r\n  /**\r\n   * Current path from root to the current node.\r\n   * If current node cannot be resolved, this property defaults to first Sitemap node.\r\n   */\r\n  public currentPath: SitemapNode[];\r\n\r\n  /**\r\n   * Title of the section (first level in the sitemap).\r\n   * If current node cannot be resolved, this property defaults to first Sitemap node.\r\n   */\r\n  public sectionTitle: string;\r\n\r\n  /**\r\n   * Title of the current sitemap node.\r\n   * If current node cannot be resolved, this property defaults to first Sitemap node.\r\n   */\r\n  public title: string;\r\n\r\n  /**\r\n   * True if the navigation (e.g. left sidebar) is open.\r\n   * Typically, this property is used only in narrow (mobile) view, otherwise the sidebar is always shown.\r\n   */\r\n  public isNaviOpen = false;\r\n\r\n  /**\r\n   * True if the secondary sidebar (e.g. right sidebar) is open.\r\n   */\r\n  public isSidebarOpen = false;\r\n\r\n  /** Sitemap that describes the structure of this application: For all roles. */\r\n  private sitemapForAllRoles: SitemapNode[];\r\n\r\n  /** Sitemap filtered for the roles of the current user. */\r\n  private sitemapInRole: SitemapNode[];\r\n\r\n  /** Cache for whether the system is using test data. */\r\n  private isTest: boolean;\r\n\r\n  constructor(\r\n    $rootScope: angular.IRootScopeService,\r\n    private $location: angular.ILocationService,\r\n    private sessionService: SessionService,\r\n    $injector: angular.auto.IInjectorService,\r\n  ) {\r\n    if ($injector.has(\"SITEMAP\")) {\r\n      this.setSitemap($injector.get(\"SITEMAP\"));\r\n    } else {\r\n      this.setSitemap([]);\r\n    }\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    $rootScope.$on(\"$routeChangeSuccess\", (event, current, previous) => {\r\n      this.resolveAndSetCurrentNode();\r\n    });\r\n    sessionService.subscribe($rootScope, () => {\r\n      this.updateSitemapInRole();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the current sitemap.\r\n   * @returns Sitemap filtered for the roles of the current user.\r\n   */\r\n  public getSitemap(): SitemapNode[] {\r\n    return this.sitemapInRole;\r\n  }\r\n\r\n  /**\r\n   * Sets the sitemap any time during the application lifecycle.\r\n   * Alternative way is to set angular constant \"SITEMAP\", but that must be done before config.\r\n   * @param newSitemap New sitemap to use.\r\n   */\r\n  public setSitemap(newSitemap: SitemapNode[]) {\r\n    this.sitemapForAllRoles = SitemapHelper.setSitemapTitles(newSitemap);\r\n    this.updateSitemapInRole();\r\n  }\r\n\r\n  /**\r\n   * Gets the current section: The first level node in the sitemap\r\n   * @returns Section filtered by the roles.\r\n   */\r\n  public getCurrentSection(): SitemapNode {\r\n    return this.currentSection;\r\n  }\r\n\r\n  /** Determines if a given node is the current node */\r\n  public isCurrent(siteMapNode: SitemapNode): boolean {\r\n    if (!siteMapNode || !this.currentPath) {\r\n      return false;\r\n    }\r\n    return !!this.currentPath.find((x) => x === siteMapNode);\r\n  }\r\n\r\n  /** Determines if a given section is the current section */\r\n  public isCurrentSection(section: SitemapNode): boolean {\r\n    return this.currentSection && section && this.currentSection.url === section.url;\r\n  }\r\n\r\n  /**\r\n   * Get sitemap node using path.\r\n   * @param path - Page URL path for the node.\r\n   * @returns - Node if exists, otherwise null.\r\n   */\r\n  public getNodeByPath(path: string): SitemapNode | null {\r\n    const sitemap = this.sitemapInRole;\r\n\r\n    for (const section of sitemap) {\r\n      const node = this.findNode(section, path);\r\n      if (node) {\r\n        return node;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Get sitemap nodes using path.\r\n   * @param path - Page URL path for the node.\r\n   * @returns - Nodes path if exists, otherwise null.\r\n   */\r\n  public getNodesByPath(path: string): SitemapNode[] | null {\r\n    const targetNode = this.getNodeByPath(path);\r\n    if (!targetNode) {\r\n      return null;\r\n    }\r\n\r\n    const sitemap = this.sitemapInRole;\r\n    const targetNodePath = [targetNode];\r\n\r\n    /*eslint-disable no-constant-condition */\r\n    main:\r\n    while(true) {\r\n      const child = targetNodePath[0];\r\n      for (const section of sitemap) {\r\n        const parent = this.findParentNode(section, child);\r\n        if (parent) {\r\n          targetNodePath.unshift(parent);\r\n          continue main;\r\n        }\r\n      }\r\n      break;\r\n    }\r\n    return targetNodePath;\r\n  }\r\n\r\n  /**\r\n   * Filters the sitemap using the role-restrictions in the sitemap\r\n   * @param session - Optional explicitely given session for filtering the sitemap.\r\n   * @param appStatus - Optional explicitely given appStatus for filtering the sitemap. This must be given with explicitely given session.\r\n   */\r\n  public updateSitemapInRole(session: UserSession = null, appStatus: AppStatus = null): void {\r\n    const newSitemap: SitemapNode[] = angular.copy(this.sitemapForAllRoles);\r\n    this.isTest = session ? RoleLogic.isInRole(session, appStatus, \"test\") : this.sessionService.isInRole(\"test\");\r\n    if (!this.sessionService.isInSomeRole(\"pro,admin\")) {\r\n      // TODO: PRO should have its own service model (service model by role). Until that is implemented, we disable customizations here.\r\n      SitemapHelper.setCustomProperties(session || this.sessionService.session, newSitemap);\r\n    }\r\n    this.sitemapInRole = this.filterSitemapSectionsByRole(newSitemap, session, appStatus);\r\n    this.resolveAndSetCurrentNode();\r\n  }\r\n\r\n  /**\r\n   * Resolve current node from location path\r\n   */\r\n  public resolveAndSetCurrentNode(): void {\r\n    const urlFromPath = \"#\" + this.$location.path().toLowerCase();\r\n    const currentPath = this.resolveCurrent(urlFromPath, this.sitemapInRole);\r\n    this.current = new CurrentRoute(currentPath);\r\n    // Legacy mapping defaults to first sitemap node\r\n    this.currentPath = currentPath || [this.sitemapInRole[0]];\r\n    this.currentSection = this.currentPath[0];\r\n    this.currentNode = this.currentPath[this.currentPath.length - 1];\r\n    this.sectionTitle = this.currentSection?.title;\r\n    this.title = this.currentNode?.title;\r\n  }\r\n\r\n  /**\r\n   * Navigate to given path\r\n   * @param path - Path to navigate.\r\n   * @param checkSession - If true, triggers session refresh\r\n   */\r\n   public navigateTo(path: string, checkSession = false) {\r\n    const check = (): Promise<void> => {\r\n      if (!checkSession) {\r\n        return Promise.resolve();\r\n      } else {\r\n        return this.sessionService.checkSession().then( () => {\r\n          return;\r\n        });\r\n      }\r\n    };\r\n    check().then( () => {\r\n      this.$location.path(path);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Evaluates wildcard string.\r\n   * @param nodeUrl - URL in the sitemap file (e.g. \"filename.html#/this/is/nodeUrl\"). From this, we take only the hash part (\"#/this/is/nodeUrl\").\r\n   * @param pathUrl - URL to evaluate - this is the hash path (e.g. \"#/this/is/pathUrl\")\r\n   * @returns Boolean whether the path url resides within the given node url.\r\n   */\r\n  private checkUrl(nodeUrl: string, pathUrl: string): boolean {\r\n    if (nodeUrl.indexOf(\"#\") !== -1) {\r\n      nodeUrl = nodeUrl.substr(nodeUrl.indexOf(\"#\"));\r\n    }\r\n    // Check and replace route parameters (:-strings) with wildcard *\r\n    const parts: string[] = nodeUrl.split(\"/\");\r\n    // eslint-disable-next-line @typescript-eslint/no-for-in-array\r\n    for (const i in parts) {\r\n      if (parts[i].indexOf(\":\") === 0) {\r\n        parts[i] = \"*\";\r\n      }\r\n    }\r\n    const newNodeUrl = parts.join(\"/\");\r\n    return this.wildCardMatch(newNodeUrl, pathUrl);\r\n  }\r\n\r\n  /**\r\n   * Evaluates wildcard string\r\n   * @param rule - Wildcard rule\r\n   * @param str - String to evaluate\r\n   * @returns Boolean whether the string matches the given wildcard rule.\r\n   */\r\n  private wildCardMatch(rule: string, str: string): boolean {\r\n    // \".\"  => Find a single character, except newline or line terminator\r\n    // \".*\" => Matches any string that contains zero or more characters\r\n    rule = rule.split(\"*\").join(\".*\");\r\n\r\n    // \"^\"  => Matches any string with the following at the beginning of it\r\n    // \"$\"  => Matches any string with that in front at the end of it\r\n    rule = \"^\" + rule + \"$\";\r\n\r\n    // Create a regular expression object for matching string\r\n    const regex = new RegExp(rule, \"i\");\r\n\r\n    // Returns true if it finds a match, otherwise it returns false\r\n    return regex.test(str);\r\n  }\r\n\r\n  /**\r\n   * Recursive resolver for any depth of sitemap nodes.\r\n   * @param url Url to check for.\r\n   * Note that in AngularJS paths, this should be the NG path starting with \"#\".\r\n   * @param nodes Nodes to check (typically the whole sitemap).\r\n   * @returns The path to current node or null if the current node cannot be resolved.\r\n   */\r\n  private resolveCurrent(url: string, nodes: SitemapNode[] | null): SitemapNode[] | null {\r\n    if (!nodes || nodes.length === 0) {\r\n      return null;\r\n    }\r\n    // home alias for root, this does not have any routeparameters\r\n    for (const node of nodes) {\r\n      const childMatch = this.resolveCurrent(url, node.children);\r\n      if (childMatch) {\r\n        return [node, ...childMatch];\r\n      }\r\n      if (this.checkUrl(node.url, url)) {\r\n        return [node];\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Filters a node tree bases on user roles.\r\n   * @param nodes - Array of nodes to filter\r\n   * @param session - Optional explicitely given session for filtering the sitemap.\r\n   * @param appStatus - Optional explicitely given appStatus for filtering the sitemap. This must be given with explicitely given session.\r\n   * @returns Filtered list of nodes.\r\n   */\r\n  private filterSitemapSectionsByRole(nodes: SitemapNode[], session: UserSession = null, appStatus: AppStatus = null): SitemapNode[] {\r\n    if (!nodes) {\r\n      return [];\r\n    }\r\n\r\n    const isInSomeRole = (roles: string | string[]) => {\r\n      return session ?\r\n        RoleLogic.isInSomeRole(session, appStatus,  Arrays.assureArray(roles)):\r\n        this.sessionService.isInSomeRole(roles);\r\n    };\r\n\r\n    const filteredNodes = nodes.filter((node) => {\r\n      const roles = Arrays.assureArray(node.roles);\r\n      if (isInSomeRole(roles)) {\r\n        if (this.isTest && roles.length) {\r\n          // Add marker that this node is visible only because we are in test mode.\r\n          const rolesWithoutTest = roles.filter((x) => x.trim().toLowerCase() !== \"test\");\r\n          if (rolesWithoutTest.length == 0 ||\r\n             (rolesWithoutTest.length !== roles.length && !isInSomeRole(rolesWithoutTest))\r\n            ) {\r\n              node.visibleTestOnly = true;\r\n          }\r\n        }\r\n        return true;\r\n      } else {\r\n        return false;\r\n      }\r\n    });\r\n    filteredNodes.forEach((node) => {\r\n      node.children = this.filterSitemapSectionsByRole(node.children, session, appStatus);\r\n    });\r\n    return filteredNodes;\r\n  }\r\n\r\n  private findNode(parent: SitemapNode, path: string): SitemapNode | null {\r\n    if (parent && path) {\r\n      if (this.checkUrl(parent.url, path)) {\r\n        return parent;\r\n      }\r\n      if (parent.children) {\r\n        for (const child of parent.children) {\r\n          const childNode = this.findNode(child, path);\r\n          if (childNode) {\r\n            return childNode;\r\n          }\r\n        }\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private findParentNode(parent: SitemapNode, node: SitemapNode): SitemapNode | null  {\r\n    if (parent.children) {\r\n      for(const child of parent.children) {\r\n        if (child == node) {\r\n          return parent;\r\n        }\r\n        const childParent = this.findParentNode(child, node);\r\n        if (childParent) {\r\n          return childParent;\r\n        }\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n}\r\n","import { DatelyObject, Employment, EmploymentRelationTaxcard, Employments, Taxcard, TaxCard2019Logic, TaxcardKind, TaxcardListItem, Taxcards, Translations } from \"@salaxy/core\";\r\n\r\nimport { EditDialogResult } from \"./model\";\r\nimport type { EmploymentDetailsTabs } from \"./model\";\r\nimport { UiHelpers } from \"./UiHelpers\";\r\n\r\n/** Extends UiHelpers methods with business logic (typically save, load etc.) */\r\nexport class UiCrudHelpers {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"Taxcards\", \"Employments\"];\r\n\r\n  /**\r\n   * Creates a new UiCrudHelpers with dependency injection.\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private taxcards: Taxcards,\r\n    private employments: Employments\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for editing an existing employment.\r\n   * If user clicks OK, the changes are saved.\r\n   * @param employmentId - Identifier of the Workers employment.\r\n   * @param buttonTypes \"default\" shows standard save button,\r\n   * \"updateCalc\" shows two buttons \"ok\" for full calc update and \"ok-no-rows\" update without touching default rows.\r\n   * @param initialTab - Tab to open.\r\n   * @returns Dialog result. Note that OK result may be either \"ok\" or \"ok-no-rows\".\r\n   * The latter means that for calculation only worker info should be updated, not the default rows.\r\n   */\r\n  public openEditEmploymentDialog(\r\n    employmentId: string,\r\n    buttonTypes: \"default\" | \"updateCalc\",\r\n    initialTab: EmploymentDetailsTabs = null,\r\n  ): Promise<EditDialogResult<Employment>> {\r\n    const loader = this.uiHelpers.showLoading(\"Ladataan työntekijän tietoja...\");\r\n    return this.employments.getSingle(employmentId).then((employment) => {\r\n      loader.dismiss();\r\n      return this.uiHelpers.openEditEmploymentDialog(employment, initialTab, buttonTypes).then((result) => {\r\n        if (result.action === \"ok\" || result.action === \"ok-no-rows\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n          return this.employments.save(result.item).then((savedEmployment) => {\r\n            loader.dismiss();\r\n            result.item = savedEmployment;\r\n            return result;\r\n          });\r\n        } else {\r\n          return result;\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Opens a wizard dialog for creating a new Employment relation and potentially a manual Taxcard.\r\n   * If user commits at the end, the changes are saved to both items.\r\n   * @returns Result only has the Employment item (not taxcard - add if necessary).\r\n   */\r\n  public async createNewEmployment(): Promise<EditDialogResult<Employment>> {\r\n    const innerResult = await this.uiHelpers.openNewEmploymentWizard();\r\n\r\n    const result: EditDialogResult<Employment> = {\r\n      action: innerResult.action,\r\n      hasChanges: innerResult.hasChanges,\r\n      item: undefined,\r\n      logic: innerResult.logic,\r\n      result: innerResult.result,\r\n    };\r\n    if (innerResult.action === \"ok\") {\r\n      const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n      result.item = await this.employments.save(innerResult.item.employment);\r\n      const personalId = result.item.identity.personalId;\r\n\r\n      switch (result.item.info.taxcard) {\r\n        case EmploymentRelationTaxcard.NoTaxCard:\r\n          // TODO: Should be handled on server-side.\r\n          await this.taxcards.save(TaxCard2019Logic.getBlank(personalId, TaxcardKind.NoTaxCard));\r\n          break;\r\n        case EmploymentRelationTaxcard.Manual: {\r\n          const kind = innerResult.item.taxcard.card.kind;\r\n          if (kind == TaxcardKind.DefaultYearly || kind == TaxcardKind.NoWithholdingHousehold\r\n            || kind == TaxcardKind.Replacement || kind == TaxcardKind.NoTaxCard) {\r\n            await this.taxcards.save(innerResult.item.taxcard);\r\n          }\r\n          break;\r\n        }\r\n        case EmploymentRelationTaxcard.Auto:\r\n          // TODO: May be moved as a separate button in dialog and then assure handled in payment.\r\n          await this.taxcards.setAuto(personalId);\r\n          break;\r\n        case EmploymentRelationTaxcard.TaxAtSource:\r\n        case EmploymentRelationTaxcard.Undefined:\r\n        default:\r\n          // No taxcard defintion OR info set in employment.\r\n          break;\r\n      }\r\n      loader.dismiss();\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Shows the add new taxcard dialog.\r\n   * If user commits at the end, the changes are saved and the ite is the stored taxcard from server.\r\n   * @param personalId Worker personal id is required.\r\n   */\r\n  public createNewTaxcard(personalId: string): Promise<EditDialogResult<Taxcard>> {\r\n    return this.uiHelpers.openNewTaxcardDialog(personalId)\r\n      .then((result) => {\r\n        if (result.action === \"ok\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n          return this.taxcards.save(result.item).then((savedTaxcard) => {\r\n            result.item = savedTaxcard;\r\n            loader.dismiss();\r\n            if (!savedTaxcard) {\r\n              this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1_Services.UiCrudHelpers.taxcards.noTaxcardTitle\"),\r\n                Translations.get(\"SALAXY.NG1_Services.UiCrudHelpers.taxcards.noTaxcardText\"));\r\n            }\r\n            if (savedTaxcard?.incomeLog.find((x) => x.diff && x.diff !== \"default\")) {\r\n              return this.uiHelpers.openEditDialog(\"salaxy-components/modals/worker/taxcard-income-log.html\", savedTaxcard, {}, \"lg\")\r\n                .then((incomeLogResult) => {\r\n                  if (incomeLogResult.action === \"ok\") {\r\n                    const loader = this.uiHelpers.showLoading(\"Tallennetaan laskelmia...\");\r\n                    return this.taxcards.commitDiff(savedTaxcard).then((commitResult) => {\r\n                      loader.dismiss();\r\n                      result.item = commitResult;\r\n                      return result;\r\n                    });\r\n                  } else {\r\n                    return result;\r\n                  }\r\n                });\r\n            }\r\n            return result;\r\n          });\r\n        } else {\r\n          return result;\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Refreshes the automatic taxcard.\r\n   * @param taxcardId Automatic taxcard id to refresh.\r\n   * @param salaryDate Salary date for the taxcard.\r\n   */\r\n  public refreshAutoTaxcard(taxcardId: string, salaryDate?: DatelyObject): Promise<TaxcardListItem[]> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\", \"Verokorttia tarkistetaan.\");\r\n    return this.taxcards.refreshAuto(taxcardId, salaryDate, true).then((taxcards) => {\r\n      loading.dismiss();\r\n      return taxcards;\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport * as FileSaver from \"file-saver\";\r\nimport {\r\n  Calculation, CalculationListItem, CalendarEvent, DatasetListItem, DateRange, Employment, EmploymentListItem, EmploymentLogic, EmploymentRelationTaxcard, ExternalDialogData,\r\n  TaxCard2019Logic,\r\n  Taxcard, Translations\r\n} from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, EditDialogResult, ExternalDialogConfig } from \"./model\";\r\nimport type { EmploymentDetailsTabs } from \"./model\";\r\n\r\nimport { CrudControllerBase } from \"../../controllers/bases/CrudControllerBase\";\r\nimport { SessionService } from \"../SessionService\";\r\n\r\n/**\r\n * Provides misc. user interface helper methods that are related to AngularJS.\r\n * Please note that these methods do NOT connect to API (load/save) to separate UI logic from business logic:\r\n * The business logic is in separate UiCrudHelpers class.\r\n */\r\nexport class UiHelpers {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$uibModal\", \"$location\", \"$rootScope\", \"$window\", \"$timeout\", \"SessionService\", \"$uibModalStack\"];\r\n\r\n  /**\r\n   * Creates a new UiHelpers with dependency injection.\r\n   */\r\n  constructor(\r\n    private $uibModal: angular.ui.bootstrap.IModalService,\r\n    private $location: angular.ILocationService,\r\n    private $rootScope: angular.IRootScopeService,\r\n    private $window: angular.IWindowService,\r\n\r\n    private $timeout: angular.ITimeoutService,\r\n    private sessionService: SessionService,\r\n    private $uibModalStack: angular.ui.bootstrap.IModalStackService,\r\n  ) {\r\n    this.init();\r\n  }\r\n\r\n  /**\r\n   * Shows an edit dialog - typically for a list item, but potentially for some other editable item.\r\n   * Alternatively, you may use showDialog() if you wish to specify your own controller (with more logic)\r\n   * @param templateUrl - Template url.\r\n   * @param item - The item that is being edited. The logic will support change tracking and reset on this item.\r\n   * @param logic - Additional logic: Helper functions, metadata etc. that view can use to contruct the UI.\r\n   * @param size - Optional size parameter: sm, lg or ''. Default is empty string (normal size).\r\n   * @param controller Optional controller for the modal instance.\r\n   * The item and logic are passed to controller with dependency injection name \"EditDialogParameters\".\r\n   * @param options Rarely used dialog options.\r\n   * @param options.template If set, ignores the templateUrl and uses this inline HTML template instead.\r\n   * @returns A promise that resolves to the result from the dialog.\r\n   * @example\r\n   * this.uiHelpers.showDialog(\"salaxy-components/modals/account/AuthorizedAccountAdd.html\", \"AccountAuthorizationController\")\r\n   */\r\n  public openEditDialog<TItem>(templateUrl: string, item: TItem, logic: any, size: \"sm\" | \"lg\" | \"\" = \"\",\r\n    controller = \"EditDialogController\", options: {\r\n      template?: string,\r\n    } = {},\r\n  )\r\n    : Promise<EditDialogResult<TItem>> {\r\n    const current = angular.copy(item);\r\n    const modalOptions: angular.ui.bootstrap.IModalSettings = {\r\n      backdrop: \"static\",\r\n      ariaLabelledBy: \"modal-title\",\r\n      ariaDescribedBy: \"modal-body\",\r\n      template: options.template,\r\n      templateUrl: options.template ? null : templateUrl,\r\n      windowTemplateUrl: \"salaxy-components/modals/ui/DialogWindow.html\",\r\n      controller,\r\n      controllerAs: \"$ctrl\",\r\n      size,\r\n      resolve: {\r\n        EditDialogParameters: () => {\r\n          return {\r\n            current,\r\n            logic,\r\n          };\r\n        },\r\n        $element: null,\r\n        $attrs: null,\r\n      },\r\n    };\r\n    const modal = this.$uibModal.open(modalOptions);\r\n    return Promise.resolve(modal.result\r\n      .then((modalResult) => {\r\n        const action = (angular.isString(modalResult) ? modalResult : (modalResult || {}).action) || EditDialogKnownActions.Cancel;\r\n        const hasChanges = !angular.equals(current, item);\r\n        if (action !== EditDialogKnownActions.Cancel && hasChanges) {\r\n          angular.copy(current, item);\r\n        }\r\n        const result: EditDialogResult<TItem> = {\r\n          action,\r\n          result: modalResult,\r\n          item,\r\n          logic,\r\n          hasChanges,\r\n        };\r\n        return result;\r\n      })\r\n      .catch(() => {\r\n        const result: EditDialogResult<TItem> = {\r\n          action: EditDialogKnownActions.Cancel,\r\n          result: null,\r\n          item,\r\n          logic,\r\n          hasChanges: false,\r\n        };\r\n        return result;\r\n      }));\r\n  }\r\n\r\n  private externalWindows: {\r\n    [name: string]: {\r\n      win: any,\r\n      url: string,\r\n      listener: (this: Window, ev: {\r\n        /** The object passed from the other window. */\r\n        data: any,\r\n        /** The origin of the window that sent the message at the time postMessage was called. */\r\n        origin: string,\r\n        /** A reference to the window object that sent the message */\r\n        source: MessageEventSource | null,\r\n      }) => any,\r\n    }\r\n  } = {};\r\n\r\n  /**\r\n   * Shows an external dialog that may be in an untrusted domain.\r\n   * Enables cross-site communication using postMessage events.\r\n   * @param name Name of the unique window\r\n   * @param url Url to show in the Window\r\n   * @param item The item that is being edited. The logic will support change tracking and reset on this item.\r\n   * @param config Configuration of the opened window.\r\n   * @param resolver Optional function for checking if the promise is resolved.\r\n   */\r\n  public showExternalDialog<TData>(name: string, url: string, item: TData, config?: ExternalDialogConfig, resolver?: (ev: {\r\n    /** The object passed from the other window. */\r\n    data: ExternalDialogData<TData>,\r\n    /** The origin of the window that sent the message at the time postMessage was called. */\r\n    origin: string,\r\n    /** A reference to the window object that sent the message */\r\n    source: MessageEventSource | null,\r\n  }) => boolean)\r\n    : Promise<ExternalDialogData<TData>> {\r\n    const browserWindow = window;\r\n    config = config || {};\r\n\r\n    if (this.externalWindows[name]?.listener) {\r\n      // Cancel the previous promise and unregister event.\r\n      this.externalWindows[name].listener.call(browserWindow, {\r\n        data: {\r\n          action: \"cancel\",\r\n        },\r\n        origin: null,\r\n        source: null,\r\n      });\r\n      browserWindow.removeEventListener(\"message\", this.externalWindows[name].listener);\r\n    }\r\n\r\n    const width = config.width || 600;\r\n    const height = config.height || 700;\r\n    // access to browserWindow.top is blocked if the site is run in an iframe in a cross domain environment\r\n    // have to use current window only\r\n    const y = browserWindow.outerHeight / 2 + browserWindow.screenY - (height / 2);\r\n    const x = browserWindow.outerWidth / 2 + browserWindow.screenX - (width / 2);\r\n    const windowFeatures = `toolbar=no, menubar=no, width=${width}, height=${height}, top=${y}, left=${x}`;\r\n\r\n    const hostUrl = new URL(url);\r\n    const popupBaseUrl = `${hostUrl.protocol}//${hostUrl.host}`;\r\n    url += (url.indexOf(\"?\") > 0 ? \"&\" : \"?\") + \"data=\" + encodeURIComponent(btoa(JSON.stringify(item)));\r\n    if (url.indexOf(\"http\") !== 0) {\r\n      url += \"&access_token=\" + this.sessionService.getCurrentToken();\r\n    }\r\n\r\n    if (!this.externalWindows[name]?.win || this.externalWindows[name].win.closed || this.externalWindows[name].url !== url) {\r\n      // According to best practice in https://developer.mozilla.org/en-US/docs/Web/API/Window/open\r\n      this.externalWindows[name] = {\r\n        url,\r\n        win: window.open(url, name, windowFeatures),\r\n        listener: null,\r\n      };\r\n    }\r\n    // Focus and check if popup blocked\r\n    try {\r\n      this.externalWindows[name].win.focus();\r\n    }\r\n    catch (e) {\r\n      return this.showAlert(\"Ponnahdusikkuna estetty selaimen asetuksissa\", \"Toiminto edellyttää, että sallit ponnahdusikkunan avattavan osoitteeseen \" + popupBaseUrl + \".\", \"Sulje\").then(() => {\r\n        return Promise.resolve({\r\n          action: \"cancel\",\r\n          hasChanges: false,\r\n          item,\r\n        });\r\n      });\r\n    }\r\n\r\n    return new Promise<ExternalDialogData<TData>>((resolve) => {\r\n      this.externalWindows[name].listener = (ev: {\r\n        /** The object passed from the other window. */\r\n        data: ExternalDialogData<TData>,\r\n        /** The origin of the window that sent the message at the time postMessage was called. */\r\n        origin: string,\r\n        /** A reference to the window object that sent the message */\r\n        source: MessageEventSource | null,\r\n      }) => {\r\n        console.debug(\"Message received\", ev);\r\n        if (!resolver ||\r\n          resolver(ev)) {\r\n          // HACK: Check origin/source.\r\n          const action = ev.data.action || \"cancel\";\r\n          const hasChanges = !angular.equals(ev.data.item, item);\r\n          if (action !== EditDialogKnownActions.Cancel && hasChanges) {\r\n            angular.copy(ev.data.item, item);\r\n          }\r\n\r\n          browserWindow.removeEventListener(\"message\", this.externalWindows[name].listener);\r\n\r\n          resolve({\r\n            action,\r\n            hasChanges,\r\n            item,\r\n          });\r\n        }\r\n      };\r\n      // add the listener for receiving a message from the popup\r\n      browserWindow.addEventListener(\"message\", this.externalWindows[name].listener, { once: !resolver });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a custom dialog using the given controller and templateUrl.\r\n   * Optionally injects the given data into the controller as 'data'.\r\n   * NOTE: There is an alternative - more simple - modal dialog pattern openEditDialog() if you do not need a custom controller or windowTemplateUrl.\r\n   * @param templateUrl - Template url.\r\n   * @param controller  - Controller for the dialog.\r\n   * @param data - Optional data to inject into the controller.\r\n   * @param windowTemplateUrl - Optional template url for the window. Defaults to 'salaxy-components/modals/ui/DialogWindow.html'. If \"none\", no window is used.\r\n   * @param size - Optional size parameter: sm, lg or ''.\r\n   * @param backdrop - Optional. Controls the presence of a backdrop. Allowed value true, false (no backdrop) 'static' (default) backdrop is present but modal window is not closed when clicking outside of the modal window.\r\n   * @returns A promise that resolves to the result from the dialog.\r\n   * @example\r\n   * this.uiHelpers.showDialog(\"salaxy-components/modals/account/AuthorizedAccountAdd.html\", \"AccountAuthorizationController\")\r\n   */\r\n  public showDialog(\r\n    templateUrl: string,\r\n    controller?: string | any,\r\n    data?: any,\r\n    windowTemplateUrl?: string,\r\n    size?: \"sm\" | \"lg\" | \"landscape\" | \"xl\" | \"\",\r\n    backdrop: string | boolean = \"static\",\r\n  ): Promise<any> {\r\n\r\n    const $attrs: any = {};\r\n    if (controller instanceof CrudControllerBase) {\r\n      $attrs.onCreateNew = controller.onCreateNew;\r\n      $attrs.onListSelect = controller.onListSelect;\r\n      $attrs.onDelete = controller.onDelete;\r\n    }\r\n\r\n    const options: angular.ui.bootstrap.IModalSettings = {\r\n      backdrop,\r\n      ariaLabelledBy: \"modal-title\",\r\n      ariaDescribedBy: \"modal-body\",\r\n      templateUrl,\r\n      windowTemplateUrl: windowTemplateUrl || \"salaxy-components/modals/ui/DialogWindow.html\",\r\n      controller: controller || \"ModalGenericDialogController\",\r\n      controllerAs: \"$ctrl\",\r\n      size,\r\n      resolve: {\r\n        data: () => {\r\n          return data;\r\n        },\r\n        $attrs,\r\n      },\r\n    };\r\n    if (options.windowTemplateUrl === \"none\") {\r\n      delete options.windowTemplateUrl;\r\n    }\r\n    const modal = this.$uibModal.open(options);\r\n\r\n    return Promise.resolve(modal.result)\r\n      .then((value) => {\r\n        return value;\r\n      })\r\n      .catch((reason) => {\r\n        if (reason === \"backdrop click\" || reason === \"dismissAll\") {\r\n          return null;\r\n        }\r\n        throw new Error(\"\" + reason);\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Close all existing modals from modal stack\r\n   */\r\n  public dismissAllModals() {\r\n    if (this.$uibModalStack) {\r\n      this.$uibModalStack.dismissAll(\"dismissAll\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Shows a customized loading component (spinner) with an optional message.\r\n   * Returns an object with a dismiss function to call for closing the dialog.\r\n   * Note that there is a separate generic directive 'salaxy-loader' for indicating\r\n   * http-traffic.\r\n   * @param heading Translation key for heading text for the loader.\r\n   * Default text is \"SALAXY.UI_Terms.loading\", but you may set this to null for just the spinner.\r\n   * @param text Optional translation key for additional text paragraph describing what is happening.\r\n   * @returns An object with dismiss function to close the dialog.\r\n   * @example\r\n   * ```ts\r\n   * const loader = this.uiHelper.showLoading(\"SALAXY.UI_Terms.isSaving\", \"SALAXY.UI_Terms.pleaseWait\");\r\n   * setTimeout(() => {\r\n   *   loader.dismiss();\r\n   * }, 2000);\r\n   * ```\r\n   */\r\n  public showLoading(heading = \"SALAXY.UI_Terms.loading\", text?: string): {\r\n    /** Closes the dialog */\r\n    dismiss: () => void,\r\n    /** Changes the heading text after opening */\r\n    setHeading: (heading: string) => void,\r\n    /** Changes the text after opening */\r\n    setText: (text: string) => void,\r\n  } {\r\n    const data = {\r\n      heading,\r\n      text,\r\n    };\r\n    const options: angular.ui.bootstrap.IModalSettings = {\r\n      ariaLabelledBy: \"modal-title\",\r\n      ariaDescribedBy: \"modal-body\",\r\n      templateUrl: \"salaxy-components/modals/ui/Loading.html\",\r\n      controller: \"ModalGenericDialogController\",\r\n      controllerAs: \"$ctrl\",\r\n      windowClass: \"salaxy-component\",\r\n      size: \"sm\",\r\n      resolve: { data },\r\n    };\r\n    const modal = this.$uibModal.open(options);\r\n\r\n    // prevent possibly unhandled rejection errors\r\n    modal.result\r\n      .then(() => {\r\n        // do nothing\r\n      })\r\n      .catch(() => {\r\n        // do nothing\r\n      });\r\n\r\n    return {\r\n      dismiss: () => {\r\n        this.$timeout(() => modal.dismiss());\r\n      },\r\n      setHeading: (heading: string) => {\r\n        this.$timeout(() => { data.heading = heading; });\r\n      },\r\n      setText: (text: string) => {\r\n        this.$timeout(() => { data.text = text; });\r\n      },\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Shows a confirm dialog. Like window.confirm() in JavaScript.\r\n   * Returns true if a user clicks OK -button. Otherwise (cancel or close) returns false.\r\n   * @param heading Heading text of the confirm question as translation key.\r\n   * @param text Optional additional text paragraph describing what is happening.\r\n   * @param okText Possibility to override the OK button text. The given text is run through translation.\r\n   * @param cancelText Possibility to override the Cancel button text. The given text is run through translation.\r\n   * @param html Optional HTML content to show in the dialog. If provided, text parameter is ignored.\r\n   * @returns A promise that resolves to true if user clicks OK, otherwise false.\r\n   * @example\r\n   * ```ts\r\n   * this.uiHelpers\r\n   *     .showConfirm(\"SALAXY.UI_Terms.areYouSure\", \"SALAXY.UI_Terms.sureToDeleteRecord\")\r\n   *     .then((result) => { this.uiHelpers.showAlert(\"result\", result); })\r\n   * ```\r\n   */\r\n  public showConfirm(heading: string, text?: string, okText = \"SALAXY.UI_Terms.ok\", cancelText = \"SALAXY.UI_Terms.cancel\", html: string = null): Promise<boolean> {\r\n    const options: angular.ui.bootstrap.IModalSettings = {\r\n      ariaLabelledBy: \"modal-title\",\r\n      ariaDescribedBy: \"modal-body\",\r\n      templateUrl: \"salaxy-components/modals/ui/Confirm.html\",\r\n      windowTemplateUrl: \"salaxy-components/modals/ui/DialogWindow.html\",\r\n      controller: \"ModalGenericDialogController\",\r\n      controllerAs: \"$ctrl\",\r\n      resolve: {\r\n        data: {\r\n          heading,\r\n          text,\r\n          okText,\r\n          cancelText,\r\n          html\r\n        },\r\n      },\r\n    };\r\n    const modal = this.$uibModal.open(options);\r\n    return Promise.resolve(modal.result)\r\n      .then((result) => {\r\n        return result;\r\n      })\r\n      .catch(() => {\r\n        return false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows a date range dialog that modifies the date range of the given object.\r\n   * @param target Target object, currently both DateRange and Calculation are supported.\r\n   * Please note that the resulting EditDialogResult is always a DateRange though.\r\n   * @param title Title text for the dialog\r\n   * @param okText Possibility to override the button text. The given text is run through translation.\r\n   * @param cancelText Possibility to override the button text. The given text is run through translation.\r\n   * @returns EditDialogResult with the edited DateRange. Note that this is DateRange even if the object to edit is Calculation.\r\n   */\r\n  public showDateRange(target: DateRange | Calculation, title: string, okText = \"SALAXY.UI_Terms.save\", cancelText = \"SALAXY.UI_Terms.cancel\"): Promise<EditDialogResult<DateRange>> {\r\n    let dateRange: DateRange;\r\n    const calc = (target as Calculation).info ? (target as Calculation) : null;\r\n    if (calc) {\r\n      dateRange = {\r\n        start: calc.info.workStartDate,\r\n        end: calc.info.workEndDate,\r\n        daysCount: calc.framework.numberOfDays,\r\n      };\r\n    } else {\r\n      dateRange = target as DateRange;\r\n    }\r\n    return this.openEditDialog(\"salaxy-components/modals/date-range/DateRange.html\", dateRange, {\r\n      title,\r\n      okText,\r\n      cancelText,\r\n    }, \"sm\").then((dialogResult) => {\r\n      if (dialogResult.action === \"ok\" && calc) {\r\n        // If the editable item was DateRange, those changes are already committed.\r\n        calc.info.workStartDate = dialogResult.item.start;\r\n        calc.info.workEndDate = dialogResult.item.end;\r\n        calc.framework.numberOfDays = dialogResult.item.daysCount;\r\n      }\r\n      return dialogResult;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows an alert dialog. Like window.alert() in JavaScript.\r\n   * @param heading Heading text as translation key\r\n   * @param text Optional additional text paragraph describing what is happening.\r\n   * @param okText Possibility to override the button text. The given text is run through translation.\r\n   * @returns A promise with boolean: True if OK button was clicked, false if the dialog is closed / dismissed in another way.\r\n   * @example this.uiHelpers.showAlert(\"Please note\", \"There is this thing that we want to tell you.\");\r\n   */\r\n  public showAlert(heading: string, text?: string, okText = \"SALAXY.UI_Terms.ok\"): Promise<boolean> {\r\n    const options: angular.ui.bootstrap.IModalSettings = {\r\n      ariaLabelledBy: \"modal-title\",\r\n      ariaDescribedBy: \"modal-body\",\r\n      templateUrl: \"salaxy-components/modals/ui/Alert.html\",\r\n      controller: \"ModalGenericDialogController\",\r\n      controllerAs: \"$ctrl\",\r\n      windowTemplateUrl: \"salaxy-components/modals/ui/DialogWindow.html\",\r\n      resolve: {\r\n        data: {\r\n          heading,\r\n          text,\r\n          okText,\r\n        },\r\n      },\r\n    };\r\n    const modal = this.$uibModal.open(options);\r\n    return Promise.resolve(modal.result)\r\n      .then((result) => {\r\n        return result;\r\n      })\r\n      .catch(() => {\r\n        return false;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for editing an existing employment.\r\n   * NOTE: This method does not Save the Worker: The caller must do it separately.\r\n   * @param employment - Worker Employment edited in dialog.\r\n   * @param initialTab - Tab to open.\r\n   * @param buttonTypes \"default\" shows standard save button,\r\n   * \"updateCalc\" shows two buttons \"ok\" for full calc update and \"ok-no-rows\" update without touching default rows.\r\n   * @returns Dialog result. Note that OK result may be either \"ok\" or \"ok-no-rows\".\r\n   * The latter means that for calculation only worker info should be updated, not the default rows.\r\n   */\r\n  public openEditEmploymentDialog(\r\n    employment: Employment,\r\n    initialTab: EmploymentDetailsTabs = null,\r\n    buttonTypes: \"default\" | \"updateCalc\" = \"default\",\r\n  ): Promise<EditDialogResult<Employment>> {\r\n    return this.openEditDialog(\r\n      \"salaxy-components/worker/EmploymentEditModal.html\", employment, {\r\n      initialTab,\r\n      buttonTypes,\r\n      title: Translations.get(\"SALAXY.NG1.WorkerDetailsComponent.workerEdit.title\"),\r\n    }, \"lg\");\r\n  }\r\n\r\n  /**\r\n   * Opens wizard for creating a new employment relation in a modal dialog.\r\n   * NOTE: This method does not Save the Employment relation: The caller must do it separately.\r\n   * @returns Dialog result with the new employment relation data and potential Taxcard (if manual) that should be created.\r\n   * Only create if action is \"ok\".\r\n   */\r\n  public openNewEmploymentWizard(): Promise<EditDialogResult<{\r\n    /** Employment relation that should be created */\r\n    employment: Employment,\r\n    /** Taxcard that should be created (if it should be created). */\r\n    taxcard?: Taxcard,\r\n  }>> {\r\n    const employment = EmploymentLogic.getBlank();\r\n    return this.openEditDialog(\"salaxy-components/worker/EmploymentWizard/index.html\", employment, null, \"lg\", \"EmploymentWizardController\")\r\n      .then((dialogResult) => {\r\n        const employment: Employment = dialogResult.result.employment;\r\n        let taxcard: Taxcard | undefined = undefined;\r\n        if (dialogResult.action == EditDialogKnownActions.Ok && employment.info.taxcard == EmploymentRelationTaxcard.Manual) {\r\n          taxcard = dialogResult.result.taxcard;\r\n        }\r\n        return {\r\n          action: dialogResult.action,\r\n          item: { employment, taxcard },\r\n          hasChanges: true,\r\n          logic: dialogResult.logic,\r\n          result: dialogResult.action = EditDialogKnownActions.Ok ? EditDialogKnownActions.Ok : EditDialogKnownActions.Cancel,\r\n        };\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Opens a new dialog for adding a new taxcard.\r\n   * @param personalId Worker personal id is required.\r\n   */\r\n  public openNewTaxcardDialog(personalId: string): Promise<EditDialogResult<Taxcard>> {\r\n    if (!personalId) {\r\n      throw new Error(\"Personal ID is required.\");\r\n    }\r\n    const item = TaxCard2019Logic.getBlank(personalId);\r\n    return this.openEditDialog(\"salaxy-components/modals/worker/taxcard-new.html\", item, {});\r\n  }\r\n\r\n  /**\r\n   * Opens a dialog for editing a calendar event.\r\n   * @param calEvent The calendar event that should be created / edited.\r\n   * @param title Title for the dialog.\r\n   * @param template Template to use in create / editing.\r\n   * Simplified is designed for adding scheduling to Calculation / Payroll.\r\n   * @returns Standard dialog result for calendar event.\r\n   */\r\n  public openEditCalendarEvent(calEvent: CalendarEvent, title: string, template: \"default\" | \"simplified\" = \"default\"): Promise<EditDialogResult<CalendarEvent>> {\r\n    const okText = \"SALAXY.UI_Terms.save\";\r\n    const cancelText = \"SALAXY.UI_Terms.cancel\";\r\n    const isSimplified = template === \"simplified\";\r\n    return this.openEditDialog(\"salaxy-components/modals/workflow/CalendarEventEdit.html\", calEvent, { title, okText, cancelText, isSimplified }, \"lg\");\r\n  }\r\n\r\n  /**\r\n   * Opens the list of calculations into a dialog window for selecting a set of them.\r\n   * NOTE: If necessary, add functionality to select only one.\r\n   * @param category Either \"paid\": Read-only or \"draft\": Editable or \"shared\": Shared for approval.\r\n   * @param title Title for the dialog.\r\n   */\r\n  public openSelectCalcs(category: \"paid\" | \"draft\" | \"shared\" = \"draft\", title: string = null): Promise<EditDialogResult<CalculationListItem[]>> {\r\n    const calculations: CalculationListItem[] = [];\r\n    title = title || (category === \"paid\" ? \"Valitse maksetut palkat\" : category == \"shared\" ? \"Valitse lähetetyt\":  \"Valitse luonnokset\" );\r\n    return this.openEditDialog(\"salaxy-components/modals/calc/CalcList.html\", calculations, { title, category });\r\n  }\r\n\r\n  /**\r\n   * Opens the list of employment relations into a dialog window for selecting a set of them.\r\n   * @param title Title for the dialog\r\n   * @returns A set of selected item in dialog result.\r\n   */\r\n  public openSelectEmployments(title: string = null): Promise<EditDialogResult<EmploymentListItem[]>> {\r\n    // HACK: The item now binds to old Worker API (that is really Employment based). Change to the latest Employment API.\r\n    const workerList: EmploymentListItem[] = [];\r\n    title = title || \"Valitse työntekijät\";\r\n    return this.openEditDialog(\"salaxy-components/modals/calc/WorkerList.html\", workerList, { title });\r\n  }\r\n\r\n  /**\r\n   * Opens a search list of specified payload and returns one item.\r\n   * @param title Title for the dialog\r\n   * @returns Selected item or null if none was selected\r\n   */\r\n  public openSelect(title: string = null): Promise<DatasetListItem> {\r\n    const workerList: DatasetListItem[] = [];\r\n    title = title || \"Valitse datasetti\";\r\n    return this.openEditDialog(\"salaxy-components/modals/ui/SelectListItem.html\", workerList, { title }).then((result) => {\r\n      if (result.action === EditDialogKnownActions.Ok && result.item.length) {\r\n        return result.item[0];\r\n      } else {\r\n        return null;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Caches data to controller: This is needed to avoid $digest loops in AngularJS controllers.\r\n   * NOTE: Default data diff method uses angular.equals(), so it will not recognize difference in properties starting with \"$\" - most notably OData options.\r\n   * @param controller Controller that is used for caching. A property $salaxyCache is added for caching if not there already.\r\n   * @param cacheKey Name for the object that is being cached. Must be unique within the controller scope.\r\n   * @param dataMethod Method that gets the data that is being cached.\r\n   * @param dataDiffMethod Optional method that is used for determining whether the data has changed.\r\n   * If not specified, the dataMethod is used for diff. Should be used if dataMethod returns a lot of data or if it is resource intensive.\r\n   */\r\n  public cache<T>(controller: angular.IController, cacheKey: string, dataMethod: () => T, dataDiffMethod?: () => any): T {\r\n    if (!controller.$salaxyCache) {\r\n      controller.$salaxyCache = {} as any;\r\n    }\r\n    const cache = controller.$salaxyCache;\r\n    if (dataDiffMethod) {\r\n      const keyValue = dataDiffMethod();\r\n      if (!cache[cacheKey] || !angular.equals(cache[cacheKey].key, keyValue)) {\r\n        cache[cacheKey] = {\r\n          key: keyValue,\r\n          data: dataMethod(),\r\n        };\r\n      }\r\n      return cache[cacheKey].data;\r\n    } else {\r\n      const data = dataMethod();\r\n      if (!angular.equals(cache[cacheKey], data)) {\r\n        cache[cacheKey] = data;\r\n      }\r\n      return cache[cacheKey];\r\n    }\r\n  }\r\n  /**\r\n   * Download provide file\r\n   * @param file File blob\r\n   * @param fileName downloaded file name\r\n   */\r\n  public downloadFile(file: Blob, fileName: string) {\r\n    FileSaver.saveAs(file, fileName);\r\n  }\r\n\r\n  /**\r\n   * Opens browser internally generated Blob url\r\n   * @param file File blob\r\n   */\r\n  public openFile(file: Blob) {\r\n    this.$window.open(URL.createObjectURL(file), \"_blank\", \"fullscreen=yes\");\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for running a batch process.\r\n   * @param header Header text for the dialog\r\n   * @param list List of items for the batch process: The method is run to each of these items.\r\n   * @param method Method that is run for each of the items.\r\n   * @param batchParamsTemplateUrl Template for user input of data about the action: The parameters for the batch process.\r\n   * @param data Usecase specific data that is bound in the controller and can be used in the template and method.\r\n   * @param columns Columns shown from the list may be specified here. Leave null for default columns.\r\n   * @param chunkSize Optional chunk size for the batch process. This is used if the method supports arrays.\r\n   * @param autoStart Optional. If true, the batch process starts immediately after the dialog is opened.\r\n   * @param autoClose Optional. If true, the batch process dialog closes automatically after the process is done.\r\n   * @param silent Optional. If autoStart and autoClose are true, the dialog is not shown if the list size is smaller than the chunk size.\r\n   * This Tabulator configuration.\r\n   */\r\n  public showBatchProcessDialog<T>(\r\n    header: string,\r\n    list: T[],\r\n    method: (\r\n      /** Single item or array (for supporting chunks) in the list that is being processed. */\r\n      itemOrArray: T | T[],\r\n      /** Usecase specific data that is bound in the controller and can be used in the template and method.  */\r\n      data: any\r\n    ) => Promise<{ message: string, result: any}[]>,\r\n    batchParamsTemplateUrl = \"salaxy-components/modals/batch/default.html\",\r\n    data?: any,\r\n    columns?: Array<any>,\r\n    chunkSize?: number,\r\n    autoStart?: boolean,\r\n    autoClose?: boolean,\r\n    silent?: boolean\r\n  ) : Promise<({ done: boolean, results: { message: string, result: any}[] })> {\r\n    data = data || {};\r\n    data.dialogHeader = header;\r\n    data.dialogList = list;\r\n    data.gridColumns = columns;\r\n    data.batchMethod = method;\r\n    data.chunkSize = chunkSize;\r\n    data.batchTemplateUrl = batchParamsTemplateUrl;\r\n    data.autoStart = autoStart ?? false;\r\n    data.autoClose = autoClose ?? false;\r\n    data.silent = silent ?? false;\r\n    data.done = false;\r\n\r\n    if (data.autoStart && data.autoClose && data.silent && data.chunkSize && data.dialogList.length <= data.chunkSize) {\r\n      const loader = this.showLoading(header ?? \"SALAXY.UI_Terms.wait\");\r\n      data.dialogList.forEach((itemToProcess) => {\r\n        itemToProcess.processed = \"Processing...\";\r\n      });\r\n      return method(data.dialogList, data).then((results) => {\r\n        let i = 0;\r\n        for (const itemToProcess of data.dialogList) {\r\n          itemToProcess.processed = \"OK \" + (results[i].message);\r\n          itemToProcess.processedResult = { message: results[i].message, result: results[i].result };\r\n          i++;\r\n        }\r\n        loader.dismiss();\r\n        return { done: true, results: data.dialogList.map((item) => item.processedResult ) };\r\n      });\r\n    }\r\n    else\r\n    {\r\n      return this.showDialog(\"salaxy-components/modals/batch/dialog.html\", \"BatchProcessController\", data, null, \"xl\").then(() => {\r\n        if (data.done) {\r\n          return { done: true, results: data.dialogList.map((item) => item.processedResult ) };\r\n        }\r\n        else\r\n        {\r\n          return { done: false, results: [] };\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Converts bytes to blob.\r\n   * @param bytes Bytes encoded in base64.\r\n   * @param mimeType Mime type for the blob.\r\n   */\r\n  public bytes2Blob(bytes: string, mimeType: string): Blob {\r\n    const byteArray = Uint8Array.from(\r\n      atob(bytes)\r\n        .split(\"\") // to char array\r\n        .map((char) => char.charCodeAt(0))\r\n    );\r\n    return new Blob([byteArray], { type: mimeType });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog based on returnUrl parameter from the current url.\r\n   */\r\n  private showReturnUrlDialog() {\r\n    const returnUrlParameters = this.getReturnUrlParameters();\r\n    if (returnUrlParameters) {\r\n      if (returnUrlParameters.returnUrl &&\r\n        (returnUrlParameters.returnUrl.toLowerCase().startsWith(\"http:\") ||\r\n          returnUrlParameters.returnUrl.toLowerCase().startsWith(\"https:\")\r\n        )) {\r\n        this.showDialog(\r\n          \"salaxy-components/modals/\" + returnUrlParameters.componentTemplate + \".html\",\r\n          null).then(() => {\r\n            this.$window.location.assign(returnUrlParameters.returnUrl);\r\n          });\r\n        this.$rootScope.$evalAsync(() => {\r\n          this.$location.url(\"/\");\r\n        });\r\n      } else {\r\n        this.showDialog(\r\n          \"salaxy-components/modals/\" + returnUrlParameters.componentTemplate + \".html\",\r\n          null);\r\n        // async redirect immediately with dialog\r\n        this.$rootScope.$evalAsync(() => {\r\n          this.$location.url(returnUrlParameters.returnUrl);\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  private getReturnUrlParameters() {\r\n    const url = this.$location.url();\r\n    if (url.indexOf(\"/dialog/\") !== 0) {\r\n      return null;\r\n    }\r\n    const dialog = url.substring(\"/dialog/\".length, url.indexOf(\"?\"));\r\n    const returnUrl = this.$location.search().returnUrl;\r\n    return {\r\n      componentTemplate: dialog,\r\n      returnUrl,\r\n    };\r\n  }\r\n\r\n  private init() {\r\n    this.$rootScope.$on(\"$locationChangeStart\", () => {\r\n      this.showReturnUrlDialog();\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Numeric } from \"@salaxy/core\";\r\n\r\n/**\r\n * Defines a step in wizard\r\n */\r\nexport interface WizardStep {\r\n  /** A number for the step, typically set by the counter */\r\n  number?: number;\r\n\r\n  /** Short title that is displayed with the Wizard buttons */\r\n  title: string;\r\n\r\n  /** If true, the step is active/selected. Typically, there is only one step active at any given time. */\r\n  active?: boolean;\r\n\r\n  /** If true, the step cannot be clicked/activated */\r\n  disabled?: boolean;\r\n\r\n  /** Path to the view that is shown in the wizard */\r\n  view?: string;\r\n\r\n  /** Path to the buttons view that is shown in the footer of the wizard */\r\n  buttonsView?: string;\r\n\r\n  /** Heading for the step */\r\n  heading?: string;\r\n\r\n  /** Intro text at the top of the wizard */\r\n  intro?: string;\r\n}\r\n\r\n/**\r\n * Manages the state and pages of a Wizard that potentially has multiple\r\n * controllers views etc. in it.\r\n */\r\nexport class WizardService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\"];\r\n\r\n  private steps: WizardStep[] = [];\r\n  private activeStep: number = null;\r\n\r\n  /**\r\n   * Creates a new instance of WizardService\r\n   * @param $rootScope - Angular root scope. Used for event routing\r\n   */\r\n  constructor(private $rootScope: angular.IRootScopeService, newSteps: WizardStep[]) {\r\n    this.setSteps(newSteps, true);\r\n  }\r\n\r\n  /** Gets the Wizard steps as collection */\r\n  public getSteps(): WizardStep[] {\r\n    return this.steps;\r\n  }\r\n\r\n  /**\r\n   * Sets the Wizard steps\r\n   * @param newSteps - the new collection of steps for the wizard.\r\n   * @param skipNotify - If true will not send the the Notify event to Subscribed controllers.\r\n   */\r\n  public setSteps(newSteps: WizardStep[] = [], skipNotify = false): void {\r\n    if (angular.equals(newSteps, this.steps)) {\r\n      return;\r\n    }\r\n    for (let n = 0; n < newSteps.length; n++) {\r\n      if (!Numeric.isNumber(newSteps[n].number)) {\r\n        newSteps[n].number = n + 1;\r\n      }\r\n    }\r\n    this.steps = newSteps;\r\n    this.activeStep = newSteps.length > 0 ? 1 : 0;\r\n    if (!skipNotify) {\r\n      this.notify();\r\n    }\r\n  }\r\n\r\n  /** Gets the number of the currently active step */\r\n  public get activeStepNumber() {\r\n    return this.activeStep;\r\n  }\r\n  /** Sets the number of the currently active step */\r\n  public set activeStepNumber(stepNumber: number) {\r\n    for (const step of this.steps) {\r\n      step.active = false;\r\n    }\r\n    this.steps[stepNumber - 1].active = true;\r\n    this.activeStep = stepNumber;\r\n    this.notify();\r\n  }\r\n\r\n  /**\r\n   * Gets the current step object\r\n   */\r\n  public getCurrentStepObject(): WizardStep {\r\n    return this.activeStep ? this.steps[this.activeStep - 1] : null;\r\n  }\r\n\r\n  /**\r\n   * Controllers can subscribe to changes in service data using this method.\r\n   * Read more about the pattern in: http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/\r\n   * @param scope - Controller scope for the subscribing controller (or directive etc.)\r\n   * @param callback - The event listener function. See $on documentation for details\r\n   */\r\n  public subscribe(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n    const handler = this.$rootScope.$on(\"wizard-service-event\", callback);\r\n    scope.$on(\"$destroy\", handler);\r\n  }\r\n\r\n  private notify(): void {\r\n    this.$rootScope.$emit(\"wizard-service-event\");\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CrudApiBase } from \"@salaxy/core\";\r\n\r\nimport { IService } from \"./IService\";\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/**\r\n * Legacy service model: Stores the edited items in browser session context.\r\n * Most new implementations should use the new API CRUD model instead.\r\n * However, this service model may still be the right choice in certain circumstances where the editable data should be\r\n * cached or is already in session (like account data).\r\n */\r\nexport abstract class BaseService<T> implements IService<T> {\r\n\r\n    /**\r\n     * List of items loaded to the service.\r\n     * Empty list if items are still been loaded.\r\n     */\r\n    public list: T[] = [];\r\n\r\n    /** Currently selected item. */\r\n    public current: T = null;\r\n\r\n    /** Set to true when the initial data hase been loaded from the server (not the anonymous dummy data). */\r\n    public isInitialDataLoaded: boolean;\r\n\r\n    /** Intial data owner */\r\n    private initialOwner: string;\r\n\r\n    /**\r\n     * String that identifies the service event (onChange/notify).\r\n     * Must be unique for the service class.\r\n     */\r\n    protected abstract eventPrefix;\r\n\r\n    constructor(\r\n        private $rootScope: angular.IRootScopeService,\r\n        protected sessionService: SessionService,\r\n\r\n        private api: CrudApiBase<T, never>,\r\n    ) {\r\n      this.init();\r\n\r\n      sessionService.subscribe($rootScope, () => {\r\n        this.init();\r\n      });\r\n    }\r\n\r\n    /**\r\n     * Reloads the list from the server - called in init and e.g. after Delete and Add new\r\n     * @returns A Promise with result data\r\n     */\r\n    public reloadList(): Promise<T[]> {\r\n        return this.api.getAll().then((result) => {\r\n          this.list = result;\r\n          this.isInitialDataLoaded = true;\r\n          this.notify();\r\n          return this.list;\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Client-side (synchronous) method for getting a new blank item as bases for UI binding.\r\n     * @returns A Blank item with default values.\r\n     */\r\n    public getBlank(): T {\r\n        return this.api.getBlank();\r\n    }\r\n\r\n    /**\r\n     * Get the identifier of the current item, null if none is selected.\r\n     * @returns The identifier of current item, or null if not set\r\n     */\r\n    public getCurrentId(): string | null {\r\n        // TODO: Consider typing T either as IIdentifiable or IApiCrudObject\r\n        return this.current ? (this.current as any).id : null;\r\n    }\r\n\r\n    /**\r\n     * Set the current item by id.\r\n     * If id parameter is \"new\", the item is set to a new blank item.\r\n     * If id paramter is null, the current item is set to null.\r\n     * @param id - The Identifier for the item to set as current\r\n     */\r\n    public setCurrentId(id: \"new\" | string): void {\r\n        if (!id) {\r\n            this.setCurrent(null);\r\n            return;\r\n        }\r\n        if (id === \"new\") {\r\n          this.newCurrent();\r\n          return;\r\n        }\r\n        if (id != null && this.list.length > 0) {\r\n            const matches = this.list.filter((x) => (x as any).id === id);\r\n            if (matches.length > 0) {\r\n                this.setCurrent(matches[0]);\r\n            } else {\r\n                throw Error(`Item ${id} could not be set as current.`);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Set the current item to given item\r\n     * @param item - The item to set as current\r\n     */\r\n    public setCurrent(item: T): void {\r\n        this.current = item;\r\n        this.notify();\r\n    }\r\n\r\n    /**\r\n     * Sets the current item to a new blank item.\r\n     */\r\n    public newCurrent(): void {\r\n        this.setCurrent(this.getBlank());\r\n    }\r\n\r\n    /**\r\n     * Saves the current item to database.\r\n     * @returns A Promise with result data: The current object after round-trip to server.\r\n     */\r\n    public saveCurrent(): Promise<T> {\r\n        if (this.current) {\r\n            return this.save(this.current);\r\n        } else {\r\n            throw new Error(\"SaveCurrent called when current is not set.\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Saves the given item to database.\r\n     * @param item - Item to be saved\r\n     * @returns A Promise with the item after the round-trip to server.\r\n     */\r\n    public save(item: T): Promise<T> {\r\n        return this.api.save(item).then((result) => {\r\n            this.setCurrent(result);\r\n            return this.reloadList().then(() => {\r\n                return result;\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Deletes the specified item.\r\n     * @param id - The identifier for the item to be deleted\r\n     * @returns A Promise with result data (\"Object deleted\")\r\n     */\r\n    public delete(id: string): Promise<string> {\r\n        return this.api.delete(id).then((result) => {\r\n            return this.reloadList().then(() => {\r\n                return result;\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Creates a copy of a given item.\r\n     * This method does not yet set the item as current.\r\n     * @param copySource Item to copy as new.\r\n     */\r\n    public copyAsNew(copySource: T): T {\r\n        const copy = JSON.parse(JSON.stringify(copySource)) as T;\r\n        (copy as any).id = null;\r\n        return copy;\r\n    }\r\n\r\n    /**\r\n     * INTERNAL ONLY: This functionality is under consideration.\r\n     * We may not support it in the future and we may remove it without it being a breaking change.\r\n     *\r\n     * Controllers can subscribe to changes in service data using this method.\r\n     * Read more about the pattern in: http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/\r\n     * @param scope - Controller scope for the subscribing controller (or directive etc.)\r\n     * @param callback - The event listener function. See $on documentation for details\r\n     * @ignore\r\n     */\r\n    public onChange(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n        const handler = this.$rootScope.$on(this.eventPrefix + \"-service-event\", callback);\r\n        scope.$on(\"$destroy\", handler);\r\n    }\r\n\r\n    /** INTERNAL ONLY: Emits the service event (typically list reload). This functionality may be dropped in future versions without warning. */\r\n    protected notify(): void {\r\n        this.$rootScope.$emit(this.eventPrefix + \"-service-event\");\r\n    }\r\n\r\n    private init() {\r\n      if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n        const owner = this.sessionService.session.currentAccount.owner;\r\n        if (this.initialOwner != owner){\r\n          this.list = [];\r\n          this.isInitialDataLoaded = false;\r\n          this.initialOwner = owner;\r\n          this.reloadList();\r\n        }\r\n      } else {\r\n        this.current = null;\r\n        this.list = [];\r\n        this.isInitialDataLoaded = false;\r\n        this.initialOwner = null;\r\n      }\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AuthorizedAccounts, AuthorizedAvatar, CompanyAccount, PersonAccount, Translations } from \"@salaxy/core\";\r\n\r\nimport { BaseService } from \"./BaseService\";\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/** TODO: Move the data model and data to server-side. */\r\ntype Partner = {\r\n  /** Name of the partner service */\r\n  title?: string,\r\n  /** Unique identifier */\r\n  id: string,\r\n  /** Palkkaus.fi account ID (IBAN) that is authorized. */\r\n  accountId: string,\r\n  /** Square logo image */\r\n  img: string,\r\n  /** Status text: Short description */\r\n  status?: string,\r\n  /** If true, the integration is enabled. */\r\n  enabled?: boolean,\r\n};\r\n\r\n/**\r\n * CRUD functionality for the authorized accounts.\r\n * Additionally listing of authorizing accounts.\r\n */\r\nexport class AuthorizedAccountService extends BaseService<AuthorizedAvatar> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\", \"SessionService\", \"AuthorizedAccounts\"];\r\n\r\n  /**\r\n   * String that identifies the service event (onChange/notify).\r\n   * Must be unique for the service class.\r\n   */\r\n  protected eventPrefix = \"authorizedAccount\";\r\n\r\n  private authorizingAccounts: (PersonAccount | CompanyAccount)[] = [];\r\n\r\n  /** Intial data owner */\r\n  private initialAuthorizingAccountsOwner: string;\r\n\r\n  private currentPartnerSite: any;\r\n\r\n  /**\r\n   * List of Software/Integration partner sites\r\n   */\r\n  private partnerIntegrationSiteList: Partner[] = [\r\n    {\r\n      id: \"askelma\",\r\n      accountId: \"FI14POYA0028382282\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/askelma/logo.png\",\r\n    },\r\n    {\r\n      id: \"easoft\",\r\n      accountId: \"FI11POY10030958375\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/easoft/logo.png\",\r\n    },\r\n    {\r\n      id: \"domus\",\r\n      accountId: \"FI23POY10006460809\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/domus/logo.png\",\r\n    },\r\n    {\r\n      id: \"holvi\",\r\n      accountId: \"FI24POYH0021937564\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/holvi/logo.png\",\r\n    },\r\n    {\r\n      id: \"isolta\",\r\n      accountId: \"FI24POYI0018540478\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/isolta/logo.svg\",\r\n    },\r\n    {\r\n      id: \"finago\",\r\n      accountId: \"FI15POYA0008369224\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/finago-solo/logo.png\",\r\n    },\r\n    {\r\n      id: \"accountor\",\r\n      accountId: \"FI03POYA0003689675\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/accountor-go/logo.png\",\r\n    },\r\n    {\r\n      id: \"briox\",\r\n      accountId: \"FI33POYB0024403824\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/briox/logo.png\",\r\n    },\r\n    {\r\n      id: \"nocfo\",\r\n      accountId: \"FI45POYN0031497697\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/nocfo/logo.png\",\r\n    },\r\n    {\r\n      id: \"passeliMerit\",\r\n      accountId: \"FI43POY10010435606\",\r\n      img: \"https://cdn.salaxy.com/img/salaxy/customer/passelimerit/logo.png\",\r\n    }\r\n  ];\r\n\r\n  constructor(\r\n    $rootScope: angular.IRootScopeService,\r\n    sessionService: SessionService,\r\n    private authorizedAccountsApi: AuthorizedAccounts,\r\n  ) {\r\n    super($rootScope, sessionService, authorizedAccountsApi);\r\n\r\n    this.refreshAuthorizingAccounts();\r\n\r\n    sessionService.subscribe($rootScope, () => {\r\n      this.refreshAuthorizingAccounts();\r\n    });\r\n\r\n    this.partnerIntegrationSiteList.forEach((x) => {\r\n      x.title = Translations.get(`SALAXY.NG1_Services.AuthorizedAccountService.partnerIntegrationSiteList.${x.id}.title`);\r\n      x.status = Translations.get(`SALAXY.NG1_Services.AuthorizedAccountService.partnerIntegrationSiteList.${x.id}.description`);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Refreshes existing authorizing accounts.\r\n   * @returns A Promise with result data (PersonAccount|CompanyAccount)[]\r\n   */\r\n  public reloadAuthorizingAccounts(): Promise<(PersonAccount | CompanyAccount)[]> {\r\n    return this.authorizedAccountsApi.getAuthorizingAccounts().then((data) => this.authorizingAccounts = data);\r\n  }\r\n\r\n  /**\r\n   * Lists all accounts on behalf of which this account has been authorized to act.\r\n   * @returns A Promise with result data (PersonAccount|CompanyAccount)[]\r\n   */\r\n  public getAuthorizingAccounts(): (PersonAccount | CompanyAccount)[] {\r\n    return this.authorizingAccounts;\r\n  }\r\n\r\n  /**\r\n   * Sets the current partner site\r\n   * @param partnerSite A partner site to be set as current\r\n   */\r\n  public setCurrentPartnerSite(partnerSite: any): void {\r\n    this.currentPartnerSite = partnerSite;\r\n  }\r\n\r\n  /**\r\n   * Returns the current partner site\r\n   */\r\n  public getCurrentPartnerSite(): any {\r\n    return this.currentPartnerSite;\r\n  }\r\n\r\n  /**\r\n   * Return a list of all possible Integration partner sites\r\n   *\r\n   * Partner sites are services that have Salaxy or Palkkaus functionality in them. Others are services that have a different sign-in method,\r\n   * and these services need an authorization to access user's Salaxy/Palkkaus account. Others use the Salaxy/Palkkaus sign-in method, so they don't\r\n   * need separate authorization. Due to some services needing an authorization and others not needing it, all partner services need to be stored in a\r\n   * separate property, simply listing authorizations does not suffice.\r\n   *\r\n   * Partner services that need an authorization have a property accountId, that is the IBAN for their Salaxy acccount\r\n   * @returns List of partner site objects.\r\n   */\r\n  public getPartnerIntegrationSiteList(): any {\r\n    this.partnerIntegrationSiteList.forEach((x) => x.enabled = !!this.list.find((y) => y.id === x.accountId));\r\n    return this.partnerIntegrationSiteList;\r\n  }\r\n\r\n  /**\r\n   * Returns the partner site with given id\r\n   * @param id The name of the partner site\r\n   * @returns Partner site object with the given id, or undefined.\r\n   */\r\n  public getPartnerSite(id): any {\r\n    const sites = this.getPartnerIntegrationSiteList().filter((x) => x.id === id);\r\n    return sites.length > 0 ? sites[0] : null;\r\n  }\r\n\r\n  private refreshAuthorizingAccounts() {\r\n    if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n      const owner = this.sessionService.session.currentAccount.owner;\r\n      if (this.initialAuthorizingAccountsOwner != owner){\r\n        this.authorizingAccounts = [];\r\n        this.initialAuthorizingAccountsOwner = owner;\r\n        this.reloadAuthorizingAccounts();\r\n      }\r\n    } else {\r\n      this.authorizingAccounts = [];\r\n      this.initialAuthorizingAccountsOwner = null;\r\n    }\r\n  }\r\n}\r\n","/** Provides a way to cache lists and items to centralized cache. */\r\nexport class CacheService {\r\n  /** The raw cache array */\r\n  private rawCache: { [key: string]: {\r\n    /**\r\n     * URL that was called to fetch the cache.\r\n     * Technically, this can be any string that just determines whether the URL / query has changed.\r\n     */\r\n    url: string,\r\n\r\n    /** The payload for the cache. */\r\n    data: any,\r\n\r\n    /**\r\n     * Time when the cache expires.\r\n     * This is time in milliseconds, i.e. Date().getTime().\r\n     */\r\n    validMs: number,\r\n  }; } = {};\r\n\r\n  /** Return true if the given item is in the cache. */\r\n  public hasData(key: string, url: string): boolean {\r\n    if (!key) {\r\n      return false;\r\n    }\r\n    const cacheItem = this.rawCache[key];\r\n    if (!cacheItem) {\r\n      return false;\r\n    }\r\n    if (cacheItem.validMs < + new Date().getTime()) {\r\n      this.clear(key);\r\n      return false;\r\n    }\r\n    return cacheItem.url === url;\r\n  }\r\n\r\n  /** Returns the data if exists / is valid. */\r\n  public getData(key: string, url: string): any {\r\n    if (!key) {\r\n      return null;\r\n    }\r\n    if (this.hasData(key, url)) {\r\n      return this.rawCache[key].data;\r\n    }\r\n  }\r\n\r\n  /** Returns the full cache data based on key without any validation. */\r\n  public getFullCache(key: string) {\r\n    if (!key) {\r\n      return null;\r\n    }\r\n    return this.rawCache[key] || {\r\n      data: null,\r\n      key,\r\n      url: null,\r\n      validMs: null,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Sets the new data to the cache.\r\n   * @param key The cache key. Defining the instance where the cache is being used.\r\n   * If null, does nothing.\r\n   * @param url URL that was called to fetch the cache.\r\n   * Technically, this can be any string that just determines whether the URL / query has changed.\r\n   * @param data Data that is cached\r\n   * @param expiresSeconds Time to live for the data in seconds starting from the current time.\r\n   */\r\n  public setData(key: string, url: string, data: any, expiresSeconds: number): void {\r\n    if (!key) {\r\n      return null;\r\n    }\r\n    data.$loaded = new Date().getTime();\r\n    this.rawCache[key] = {\r\n      data,\r\n      url,\r\n      validMs: new Date().getTime() + (expiresSeconds * 1000),\r\n    };\r\n  }\r\n\r\n  /** Clears the entire cache - all keys. */\r\n  public clearAllKeys() {\r\n    this.rawCache = {};\r\n  }\r\n\r\n  /** Clears a given cache key */\r\n  public clear(key: string) {\r\n    if (!key) {\r\n      return;\r\n    }\r\n    this.rawCache[key] = null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Certificate, Certificates } from \"@salaxy/core\";\r\n\r\nimport { BaseService } from \"./BaseService\";\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/**\r\n * CRUD functionality for the Payroll objects and functionality for payroll in general.\r\n */\r\nexport class CertificateService extends BaseService<Certificate> {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$rootScope\", \"SessionService\", \"Certificates\"];\r\n\r\n    /**\r\n     * String that identifies the service event (onChange/notify).\r\n     * Must be unique for the service class.\r\n     */\r\n    protected eventPrefix = \"certificate\";\r\n\r\n    constructor(\r\n        $rootScope: angular.IRootScopeService,\r\n        sessionService: SessionService,\r\n        private certificateApi: Certificates,\r\n    ) {\r\n        super($rootScope, sessionService, certificateApi);\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Credentials, SessionUserCredential } from \"@salaxy/core\";\r\n\r\nimport { BaseService } from \"./BaseService\";\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/**\r\n * CRUD functionality for the Credentials objects and functionality for Credentials in general.\r\n */\r\nexport class CredentialService extends BaseService<SessionUserCredential> {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$rootScope\", \"SessionService\", \"Credentials\"];\r\n\r\n    /**\r\n     * String that identifies the service event (onChange/notify).\r\n     * Must be unique for the service class.\r\n     */\r\n    protected eventPrefix = \"certificate\";\r\n\r\n    constructor(\r\n        $rootScope: angular.IRootScopeService,\r\n        sessionService: SessionService,\r\n        private credentialsApi: Credentials,\r\n    ) {\r\n        super($rootScope, sessionService, credentialsApi);\r\n    }\r\n\r\n    /**\r\n     * Returns the url for uploading the avatar image file to the database\r\n     * @returns Id of the credential\r\n     */\r\n    public getAvatarUploadUrl(credentialId): string {\r\n      return this.credentialsApi.getAvatarUploadUrl(credentialId);\r\n  }\r\n}\r\n","import { Arrays, Calculation, CalculatorLogic, Numeric, Payroll03Info, PayrollDetails, Payrolls } from \"@salaxy/core\";\r\n\r\n/**\r\n * Payroll logic that is independent from UI log (AngularJS).\r\n * TODO: Move to @salaxy/core\r\n */\r\nexport class PayrollLogic {\r\n\r\n  /**\r\n   * Gets the Payroll03Info object based on current data (without going to server).\r\n   * @param payroll Payroll object, where info may be outdated.\r\n   * @param calcs Calculations that may be loaded from the server.\r\n   */\r\n  public static getInfo(payroll: PayrollDetails, calcs: Calculation[]): Payroll03Info {\r\n    if (!payroll) {\r\n      return new Payrolls(null).getBlank().info;\r\n    }\r\n    if (!calcs || calcs.length === 0) {\r\n      return payroll.info;\r\n    }\r\n    return {\r\n      calcCount: calcs.length, // Should this be input.calcs.length? Probably does not really matter.\r\n      fees: Arrays.sum(calcs, (x) => x.result.employerCalc.palkkaus),\r\n      totalGrossSalary: Arrays.sum(calcs, (x) => Numeric.round(x.result.totals.totalGrossSalary)),\r\n      totalPayment: Arrays.sum(calcs, (x) => Numeric.round(x.result.employerCalc.totalPayment)),\r\n      // We could potentially do some client-side validation here, but it may not make sense: Real validation is on the server.\r\n      isReadyForPayment: payroll.info.isReadyForPayment,\r\n      // Not updated by this logic:\r\n      date: payroll.info.date,\r\n      salaryDate: payroll.info.salaryDate,\r\n      paymentDate: payroll.info.paymentDate,\r\n      paymentId: payroll.info.paymentId,\r\n      status: payroll.info.status,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Returns true if there is no net salary payment to worker at all.\r\n   * @param calcs - Calculation objects\r\n   */\r\n  public static isZeroPayment(calcs: Calculation[]): boolean {\r\n    if (!calcs || !calcs.length) {\r\n      return false;\r\n    }\r\n    return calcs.every((x) => CalculatorLogic.isZeroPayment(x));\r\n  }\r\n}\r\n","import {\r\n  Ajax, Avatar, Calculation, CalculationCollection, CalculationResultLogic, Calculations, CalculationStatus, CalculatorLogic,\r\n  Dates, InputEnumOption, ExternalDialogData, Invoice, InvoicePreview, Invoices, InvoiceStatus, InvoicesLogic, InvoiceType, LegalEntityType, Numeric,\r\n  PaymentChannel, PayrollDetails, PayrollStatus, Translations, SalaryDateLogic, InvoiceListItem, SalaryDateKind, Payrolls4, Configs\r\n} from \"@salaxy/core\";\r\nimport angular from \"angular\";\r\n\r\nimport { SessionService } from \"./SessionService\";\r\nimport { SettingsService } from \"./SettingsService\";\r\nimport { OnboardingService } from \"./OnboardingService\";\r\nimport { PayrollLogic } from \"../controllers/calc/PayrollLogic\";\r\nimport { EditDialogKnownActions, UiHelpers } from \"./ui\";\r\n\r\n/** Implements the user interface logic for new Invoices: Salary and side-cost payments. */\r\nexport class InvoicesService {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Invoices\", \"SessionService\", \"UiHelpers\", \"SettingsService\", \"AjaxNg1\", \"$location\", \"$timeout\", \"Calculations\", \"OnboardingService\"];\r\n\r\n  constructor(\r\n    private invoicesApi: Invoices,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n    private settingsService: SettingsService,\r\n    private ajax: Ajax,\r\n    private $location: angular.ILocationService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private calculations: Calculations,\r\n    private onboardingService: OnboardingService,\r\n\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Application level setting of the default payment channel.\r\n   */\r\n  public get defaultChannel(): PaymentChannel {\r\n    if (this.channels) {\r\n      const defaultChannel = this.sessionService.getSession().settings.defaultPaymentChannel;\r\n      const confirmedChannel = this.channels.filter(x => x.id === defaultChannel).concat(this.channels).find(() => true)?.id as PaymentChannel;\r\n      return confirmedChannel;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Gets the enabled payment channels as avatars for the current session.\r\n   */\r\n  public get channels(): Avatar[] {\r\n    const channelsForRole = () => this.sessionService.getSession().settings?.paymentChannels.filter((x) =>\r\n      x !== PaymentChannel.PalkkausManual ||\r\n      (x === PaymentChannel.PalkkausManual && this.sessionService.isInSomeRole(\"pro,sepaPartner\"))\r\n    );\r\n    return this.uiHelpers.cache(this, \"channels\",\r\n      () => channelsForRole()?.map((x) => InvoicesLogic.getChannelAvatar(x))?.filter(x => !!x),\r\n      () => channelsForRole());\r\n  }\r\n\r\n  /**\r\n   * Gets the enabled payment channels as input enum options for the current session.\r\n   */\r\n  public get channelEnumOptions(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"channelEnumOptions\",\r\n      () => this.channels?.map((x) => ({ text: x.displayName, value: x.id, title: x.description })),\r\n      () => this.sessionService.getSession()?.settings.paymentChannels);\r\n  }\r\n\r\n  /**\r\n   * Shows the paymment page as dialog.\r\n   * @param paymentObject - The object to pay: Either Calculation or Payroll\r\n   */\r\n  public showPaymentDialog(paymentObject: Calculation | PayrollDetails) {\r\n    if (!this.checkAccountVerificationForPayment()) {\r\n        this.showMissingSignatureAlert();\r\n        return;\r\n    }\r\n\r\n    if (!this.checkChangedSalaryDate(paymentObject)) {\r\n      this.showChangedSalaryDateAlert();\r\n      return;\r\n    }\r\n\r\n    let channel = null;\r\n    if (InvoicesLogic.isPayroll(paymentObject)) {\r\n      channel = paymentObject.input.paymentChannel;\r\n     } else if (InvoicesLogic.isCalculation(paymentObject)) {\r\n      if (this.sessionService.isInRole(\"person\")) {\r\n        paymentObject.info.paymentChannel = PaymentChannel.PalkkausPersonal;\r\n      }\r\n      channel = paymentObject.info.paymentChannel;\r\n    }\r\n\r\n    if(InvoicesLogic.isEcfa(channel)) {\r\n      if(!this.checkKycForPayment()) {\r\n        this.showMissingKycAlert();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const logic = {\r\n      title:\r\n        channel === PaymentChannel.HolviCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.title.holviCfa\") :\r\n        channel === PaymentChannel.TalenomCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.title.talenomCfa\") :\r\n        channel === PaymentChannel.PalkkausInvoices  ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.title.palkkausInvoices\") :\r\n        channel === PaymentChannel.Kitsas ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.title.palkkausInvoices\") :\r\n        Translations.get(\"SALAXY.NG1.InvoicesService.logic.title.default\"),\r\n      type: InvoicesLogic.isPayroll(paymentObject) ? \"payroll\" : \"calc\",\r\n      okButtonText:\r\n        channel === PaymentChannel.HolviCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.holviCfa\") :\r\n        channel === PaymentChannel.TalenomCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.talenomCfa\") :\r\n        channel === PaymentChannel.PalkkausInvoices ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.palkkausInvoices\") :\r\n        channel === PaymentChannel.Kitsas ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.palkkausInvoices\") :\r\n        InvoicesLogic.isCfa(channel) ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.isCfaChannel\") : Translations.get(\"SALAXY.NG1.InvoicesService.logic.okButtonText.default\"),\r\n      channel,\r\n      paymentFunc: null,\r\n      isNullPayment: () => ( InvoicesLogic.isCalculation(paymentObject) && Numeric.round(paymentObject.result.employerCalc.totalPayment) == 0 )\r\n                       ||\r\n                      ( InvoicesLogic.isPayroll(paymentObject) && Numeric.round(paymentObject.info.totalPayment) == 0),\r\n      isReadyForPayment: () => InvoicesLogic.isPayroll(paymentObject) ?\r\n      paymentObject.info &&\r\n      paymentObject.info.isReadyForPayment :\r\n        InvoicesLogic.isCalculation(paymentObject) ?\r\n        paymentObject.worker &&\r\n        paymentObject.worker.tax.isValid &&\r\n          !paymentObject.result.validation.errors.find((e) => (e.type !== \"warning\")) :\r\n          false,\r\n      instructions:\r\n        channel === PaymentChannel.HolviCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.instructions.holviCfa\") :\r\n        channel === PaymentChannel.TalenomCfa ? Translations.get(\"SALAXY.NG1.InvoicesService.logic.instructions.talenomCfa\") :\r\n        null,\r\n    };\r\n\r\n    const saveForPreview = (): Promise<Calculation | PayrollDetails> => {\r\n      if (InvoicesLogic.isCalculation(paymentObject) &&\r\n          (\r\n            channel == PaymentChannel.PalkkausPersonal ||\r\n            channel == PaymentChannel.PalkkausCfaPaytrail ||\r\n            channel == PaymentChannel.PalkkausEcfaPaytrail\r\n          )) {\r\n        if (!paymentObject.workflow?.status || paymentObject.workflow.status === CalculationStatus.Draft) {\r\n          const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.InvoicesService.saving\") + \"...\");\r\n          return this.calculations.save(paymentObject).then((savedCalculation) => {\r\n            loader.dismiss();\r\n            angular.copy(savedCalculation, paymentObject);\r\n            this.$location.path(\"/calc/details/\" + paymentObject.id + \"&refresh=\" + new Date().getTime());\r\n            return paymentObject;\r\n          });\r\n        }\r\n        else\r\n        {\r\n          return Promise.resolve(paymentObject);\r\n        }\r\n      }\r\n      else\r\n      {\r\n        return Promise.resolve(paymentObject);\r\n      }\r\n    };\r\n\r\n    const paymentObjectForCfa = (): Promise<Calculation | PayrollDetails> => {\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        if (paymentObject.calcs.length > 0 ) {\r\n          return Promise.resolve(paymentObject);\r\n        }\r\n        else\r\n        {\r\n          const payrolls4Api = new Payrolls4(this.ajax);\r\n          return payrolls4Api.getCalcsOData(paymentObject.id, null).then((listItemResult) => {\r\n            const calcs = listItemResult.items;\r\n            const data: any = {};\r\n            data.listItemType = \"CalculationListItem\";\r\n            const columns = undefined;\r\n            const paramsTemplate = undefined;\r\n            const action = (items /*, data */) => {\r\n              const itemIds = items.map((x) => x.id);\r\n              return this.calculations.getMulti(itemIds).then((result) => {\r\n                const results = items.map(() => ({ message: \"\", result: [] }));\r\n                results[0].result = result;\r\n                return results;\r\n              });\r\n            };\r\n            return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.UI_Terms.wait\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n              const payrollCalcs = [];\r\n              if (dialogResult.done) {\r\n                dialogResult.results.forEach((result) => {\r\n                  payrollCalcs.push(...result.result);\r\n                });\r\n              }\r\n              const newPaymentObject:any = angular.copy(paymentObject);\r\n              newPaymentObject.calcs = payrollCalcs;\r\n              newPaymentObject[\"V4\"] = true;\r\n\r\n              return newPaymentObject;\r\n            });\r\n        });\r\n      }\r\n    }\r\n    else\r\n    {\r\n        return Promise.resolve(paymentObject);\r\n    }\r\n    };\r\n\r\n    if (InvoicesLogic.isCfa(channel) && channel !== PaymentChannel.PalkkausCfaPaytrail && channel !== PaymentChannel.PalkkausEcfaPaytrail) {\r\n        paymentObjectForCfa().then((reportingPaymentObject) => {\r\n          paymentObject = reportingPaymentObject;\r\n          this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/CfaPaymentOverview.html\", paymentObject, logic, \"lg\").then((result) => {\r\n          if (result.action !== EditDialogKnownActions.Ok) {\r\n            return;\r\n          }\r\n          this.createCfaInvoice(channel, paymentObject);\r\n        });\r\n      });\r\n    } else {\r\n      switch (channel) {\r\n        case PaymentChannel.PalkkausCfaPaytrail:\r\n        case PaymentChannel.PalkkausEcfaPaytrail:\r\n          {\r\n            paymentObjectForCfa().then((reportingPaymentObject) => {\r\n              paymentObject = reportingPaymentObject;\r\n              logic.paymentFunc = (pObj) => this.createPalkkausCfaPaytrailInvoice(pObj);\r\n              saveForPreview().then(() => this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/CfaPaymentOverview.html\", paymentObject, logic, \"lg\"));\r\n            });\r\n          }\r\n          break;\r\n        case PaymentChannel.PalkkausPersonal:\r\n          {\r\n            saveForPreview().then(() => {\r\n              this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/PalkkausPersonalPaymentOverview.html\", paymentObject, logic, \"lg\", \"PalkkausPersonalPaymentOverviewController\").then((result) => {\r\n                if (result.action) {\r\n                  if (result.action == InvoiceStatus.Canceled) {\r\n                    this.createPalkkausPersonalInvoice(channel, paymentObject, InvoiceStatus.Canceled);\r\n                    this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.headingCancelled\"), `${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.cancel.infotext1\")}.\\r\\n${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.cancel.infotext2\")}.`\r\n                    , Translations.get(\"SALAXY.UI_Terms.ok\"));\r\n                  } else if (result.action === InvoiceStatus.Paid) {\r\n                    this.createPalkkausPersonalInvoice(channel, paymentObject, InvoiceStatus.Paid);\r\n                    this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.headingPaid\"), `${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.paid.text\")}\\r\\n${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.paid.infoText1\")}\\r\\n${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.paid.infoText2\")}\\r\\n${Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.alerts.paid.infoText3\")}`\r\n                    , Translations.get(\"SALAXY.UI_Terms.ok\"));\r\n                  }\r\n                }\r\n              });\r\n            });\r\n          }\r\n          break;\r\n        default:\r\n          this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/PaymentOverview.html\", paymentObject, logic, \"lg\");\r\n          break;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Shows the payment invoice inspection page as dialog.\r\n   * @param paymentObject - Paid calculation\r\n   */\r\n  public showPalkkausPersonalInvoicesDialog(paymentObject: Calculation) {\r\n    const logic = {isInspectingPaidInvoices: true};\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/PalkkausPersonalPaymentOverview.html\", paymentObject, logic, \"lg\", \"PalkkausPersonalPaymentOverviewController\");\r\n  }\r\n\r\n  /**\r\n   * Querys item and opens paymentdialog\r\n   * @param item InvoiceListItem used to query calculation\r\n   */\r\n  public showPaymentDialogForCalculation(item: InvoiceListItem) {\r\n    this.calculations.getSingle(item.businessObjects[0]).then(calculation => {\r\n      this.showPaymentDialog(calculation);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows an alert if the signature is missing.\r\n   */\r\n   public showMissingSignatureAlert() {\r\n    this.uiHelpers.showConfirm(Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.signatureMissing\"),\r\n    Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.creationCompleteBeforePay\") + \"\\n\" +\r\n    Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.signSignature\") + \"\\n\\n\" +\r\n    Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.continueToSignature\"),\r\n    Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.continue\"), Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.close\")).then((ok: boolean) => {\r\n        if (ok) {\r\n          if (this.sessionService.getCurrentAccount().entityType === LegalEntityType.Person ) {\r\n            this.onboardingService.launchHouseholdOnboarding();\r\n          } else {\r\n            this.onboardingService.launchCompanyOnboarding();\r\n          }\r\n        }\r\n      });\r\n  }\r\n\r\n\r\n  /**\r\n   * Checks if the company's KYC (Know Your Customer) is completed for payment.\r\n   * @returns {boolean} Returns true if the KYC is completed, otherwise false.\r\n   */\r\n  public checkKycForPayment(): boolean {\r\n    //TODO: Remove type casting to any when model is updated\r\n    return !!(this.sessionService?.companyAccount?.identity as any)?.kycUpdatedAt;\r\n  }\r\n\r\n  /**\r\n   * Shows an alert if the kyc is missing.\r\n   */\r\n  public showMissingKycAlert() {\r\n    this.uiHelpers.showConfirm(\r\n    \"Asiakkaan tuntemistiedot puuttuvat\",\r\n    null,\r\n    \"Päivitä asiakkaan tuntemistiedot nyt\",\r\n    Translations.get(\"SALAXY.NG1.InvoicesService.missingSignatureAlert.close\"),\r\n    \"Asiakasvaratilin kautta maksaminen edellyttää asiakkaan tuntemistietojen päivittämistä. Päivitä KYC-tiedot oheisesta linkistä tai lue ohjeet, kuinka voit välittää päivityslinkin yhtiön nimenkirjoitusoikeudelliselle henkilölle täältä: <a href=\\\"https://help.palkkaus.fi/hc/fi/articles/19590957330589-Asiakkaan-tuntemistietojen-päivitys-KYC\\\" target=\\\"_blank\\\">Asiakkaan tuntemistietojen päivittäminen</a>\"\r\n  ).then((ok: boolean) => {\r\n        if (ok) {\r\n          window.open(Configs.current.isTestData ? \"https://rc-iam.palkkaus.fi/wizard/index.html\" : \"https://iam.palkkaus.fi/wizard/index.html\", \"_blank\");\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current authenticated user has\r\n   * required verification for the payment.\r\n   */\r\n   public checkAccountVerificationForPayment(): boolean {\r\n    return this.sessionService.checkAccountVerification();\r\n  }\r\n\r\n  /** Returns warning message text for the invoice if reported late.*/\r\n  public getEprWarningForPayment(salaryDate: string): string {\r\n    const warning = this.isDelayed(salaryDate) ? Translations.get(\"SALAXY.NG1.InvoicesService.eprWarningForPayment.isDelayed\") : \"\";\r\n    return warning;\r\n  }\r\n\r\n  /** Returns warning message text for the invoice if reported late.*/\r\n  public getEprWarningForCancellation(salaryDate: string, isPaid: boolean): string {\r\n    if (!isPaid) {\r\n      return null;\r\n    }\r\n    const warning = this.isDelayed(salaryDate) ? Translations.get(\"SALAXY.NG1.InvoicesService.eprWarningForCancellation.isDelayed\") + \"\\n\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.eprWarningForCancellation.infoText\") : \"\";\r\n    return warning;\r\n  }\r\n\r\n /**\r\n  * Checks the salary date validity before payment.\r\n  * @param paymentObject - The object to pay: Either Calculation or Payroll\r\n  */\r\n public checkChangedSalaryDate(paymentObject: Calculation | PayrollDetails) {\r\n  const role =  this.sessionService.isInRole(\"pro\") ? \"pro\" :\r\n                this.sessionService.isInRole(\"admin\") ? \"admin\" : null;\r\n  if (InvoicesLogic.isPayroll(paymentObject)) {\r\n    if (paymentObject.info.status != PayrollStatus.Draft &&\r\n        paymentObject.info.status != PayrollStatus.WaitingApproval)\r\n    {\r\n      return true;\r\n    }\r\n    if (!paymentObject.input.salaryDate) {\r\n      return true;\r\n    }\r\n    if (paymentObject.input.salaryDate != paymentObject.info.salaryDate) {\r\n      return false;\r\n    }\r\n    if (paymentObject.input.salaryDateKind == SalaryDateKind.InPast) {\r\n      return true;\r\n    }\r\n    return SalaryDateLogic.isValidSalaryDate(paymentObject.info.salaryDate, null, null, !!paymentObject.input.salaryDate, paymentObject.input.paymentChannel, PayrollLogic.isZeroPayment(paymentObject.calcs), role);\r\n  } else if (InvoicesLogic.isCalculation(paymentObject)) {\r\n    if (this.sessionService.isInRole(\"person\")) {\r\n      paymentObject.info.paymentChannel = PaymentChannel.PalkkausPersonal;\r\n    }\r\n    if (paymentObject.workflow.status != CalculationStatus.Draft &&\r\n        paymentObject.workflow.status != CalculationStatus.WaitingApproval &&\r\n        paymentObject.workflow.status != CalculationStatus.ProDraft\r\n      ) {\r\n      return true;\r\n    }\r\n    if (!paymentObject.workflow.requestedSalaryDate) {\r\n      return true;\r\n    }\r\n    if (paymentObject.workflow.requestedSalaryDate != paymentObject.workflow.salaryDate) {\r\n      return false;\r\n    }\r\n    if (paymentObject.workflow.salaryDateKind == SalaryDateKind.InPast) {\r\n      return true;\r\n    }\r\n    return SalaryDateLogic.isValidSalaryDate(paymentObject.workflow.salaryDate, paymentObject.worker?.paymentData?.ibanNumber, null, !!paymentObject.workflow.requestedSalaryDate, paymentObject.info.paymentChannel, CalculatorLogic.isZeroPayment(paymentObject), role);\r\n  }\r\n  return true;\r\n }\r\n\r\n  /**\r\n   * Shows an alert for invalid salary date.\r\n   */\r\n   public showChangedSalaryDateAlert() {\r\n    this.uiHelpers.showAlert(Translations.get(\"SALAXY.VALIDATION.Calc.SalaryDateChanged.label\"),Translations.get(\"SALAXY.VALIDATION.Calc.SalaryDateChanged.description\") );\r\n   }\r\n\r\n  /** Checks if the Epr report is delayed. */\r\n  private isDelayed(salaryDate?: string): boolean {\r\n      const officialDate = Dates.add((salaryDate ?? \"today\"),5, \"day\");\r\n      const expiresAt = Dates.addWorkdays(officialDate, 0);\r\n      const today = Dates.asDate(\"today\");\r\n      return today > expiresAt;\r\n}\r\n\r\n  private createCfaInvoice(channel: PaymentChannel, paymentObject: Calculation | PayrollDetails) {\r\n\r\n    const previewInvoices = (): Promise<InvoicePreview[]> => {\r\n      const coll: CalculationCollection = {};\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        if ((paymentObject as any).V4) {\r\n          const payrolls4Api = new Payrolls4(this.ajax);\r\n          return payrolls4Api.previewInvoices(paymentObject.id, [], false);\r\n        }\r\n        else\r\n        {\r\n          coll.payrollIds = [paymentObject.id];\r\n          return this.invoicesApi.previewInvoices(channel, coll);\r\n        }\r\n      } else {\r\n        coll.calcs = [paymentObject];\r\n        return this.invoicesApi.previewInvoices(channel, coll);\r\n      }\r\n    };\r\n\r\n    const createNewInvoice = () => {\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        if ((paymentObject as any).V4) {\r\n          const payrolls4Api = new Payrolls4(this.ajax);\r\n          return payrolls4Api.createInvoices(paymentObject.id, [], false);\r\n        }\r\n        else\r\n        {\r\n          return this.invoicesApi.createInvoicesForPayroll(channel, paymentObject.id);\r\n        }\r\n      } else {\r\n        return this.invoicesApi.createInvoices(paymentObject, channel);\r\n      }\r\n    };\r\n\r\n    const createInvoice = (): Promise<Invoice> => {\r\n      return previewInvoices().then((previews) => {\r\n        const grossInvoicePreview = previews.find((x) => x.invoice.entityType == InvoiceType.Gross);\r\n        if (!grossInvoicePreview) {\r\n          return null;\r\n        }\r\n        if (grossInvoicePreview.exists) {\r\n          return this.invoicesApi.getSingle(grossInvoicePreview.invoice.id);\r\n        }\r\n        return createNewInvoice().then((invoices) => {\r\n          return invoices.find((x) => x.header.type == InvoiceType.Gross);\r\n        });\r\n      });\r\n    };\r\n\r\n    const navigateToPaymentObject = (businessObjectId) => {\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        this.$location.path(\"/payroll/details/\" + businessObjectId + \"&refresh=\" + new Date().getTime());\r\n      } else {\r\n        this.$location.path(\"/calc/details/\" + businessObjectId + \"&refresh=\" + new Date().getTime());\r\n      }\r\n    };\r\n\r\n    const isPaid = (invoice: Invoice) => {\r\n      if (invoice.header.status === InvoiceStatus.Paid) {\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.isPaid.payment\"), Translations.get(\"SALAXY.NG1.InvoicesService.isPaid.paid\"));\r\n        return true;\r\n      }\r\n      else if (invoice.header.status !== InvoiceStatus.PaymentStarted && invoice.header.status !== InvoiceStatus.Unread)\r\n      {\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.isPaid.cantCreatePayment\"), Translations.get(\"SALAXY.NG1.InvoicesService.isPaid.cantCreatePaymentAlreadyPaid\"));\r\n        return true;\r\n      }\r\n      return false;\r\n    };\r\n\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.InvoicesService.creatingPayment\")+ \"...\");\r\n    createInvoice().then((grossInvoice) => {\r\n      if (!grossInvoice) {\r\n        loader.dismiss();\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.createInvoice.cantCreateInvoice\"), Translations.get(\"SALAXY.NG1.InvoicesService.createInvoice.cantCreateInvoiceCheck\"));\r\n        return;\r\n      }\r\n      switch (channel) {\r\n        case PaymentChannel.PalkkausCfaFinvoice:\r\n        case PaymentChannel.PalkkausEcfaFinvoice:\r\n          {\r\n            if (isPaid(grossInvoice)) {\r\n              loader.dismiss();\r\n              navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n            } else {\r\n              loader.dismiss();\r\n              const settingsReceiver = this.settingsService.current.payments.invoice.eInvoiceReceiver;\r\n              const settingsIntermediator = this.settingsService.current.payments.invoice.eInvoiceIntermediator;\r\n              const item = {\r\n                eInvoiceReceiver: settingsReceiver,\r\n                eInvoiceIntermediator: settingsIntermediator,\r\n              };\r\n              const showAddressSelection = !settingsReceiver || !settingsIntermediator;\r\n\r\n              const sendEInvoice = (address: { eInvoiceReceiver: string, eInvoiceIntermediator: string }): Promise<any> => {\r\n                const sendLoader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.InvoicesService.sending\")+ \"...\");\r\n                if (address.eInvoiceReceiver !== settingsReceiver || address.eInvoiceIntermediator !== settingsIntermediator) {\r\n                  const settings = this.settingsService.current;\r\n                  settings.payments.invoice.eInvoiceReceiver = address.eInvoiceReceiver;\r\n                  settings.payments.invoice.eInvoiceIntermediator = address.eInvoiceIntermediator;\r\n                  this.settingsService.save();\r\n                }\r\n                const path = `/v03/api/invoices/${grossInvoice.id}/einvoice?receiver=${encodeURIComponent(address.eInvoiceReceiver)}&intermediator=${encodeURIComponent(address.eInvoiceIntermediator)}`;\r\n\r\n                return this.ajax.postJSON(path, {}).then((result) => {\r\n                  sendLoader.dismiss();\r\n                  let title = Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.ajax.title\");\r\n                  let msg = `${Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.ajax.msg\")} ${address.eInvoiceIntermediator}/${address.eInvoiceReceiver}.`;\r\n                  let freeText = \"\";\r\n                  if (result.Response.Status !== \"OK\") {\r\n                    title = Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.ajax.error.title\");\r\n                    msg = Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.ajax.error.msg\");\r\n                    if (result.Response.FreeText) {\r\n                      for (const ft of result.Response.FreeText) {\r\n                        freeText += ft[\"#text\"] + \"\\n\";\r\n                      }\r\n                    }\r\n                  }\r\n                  freeText = this.textToRows(freeText, 80, \"\\n\");\r\n                  this.uiHelpers.showAlert(title, msg + \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.ajax.operatorStatus\") + \":\" + \"\\n\" + result.Response.Status + \" \" + result.Response.StatusCode + \"\\n\" + freeText);\r\n                  return result;\r\n                });\r\n              };\r\n\r\n              if (showAddressSelection) {\r\n                const eInvoiceLogic = {\r\n                  selectEInvoiceAddress: (itemRef) => {\r\n                    this.settingsService.selectEInvoiceAddress(itemRef);\r\n                  },\r\n                };\r\n\r\n                this.uiHelpers.openEditDialog(\"salaxy-components/modals/payment/cfa/EInvoice.html\", item, eInvoiceLogic, null).then((result) => {\r\n                  if (result.action !== EditDialogKnownActions.Ok) {\r\n                    navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n                  } else {\r\n                    sendEInvoice(result.item).then(() => {\r\n                      navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n                    });\r\n                  }\r\n                });\r\n              } else {\r\n                sendEInvoice(item).then(() => {\r\n                  navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n                });\r\n              }\r\n            }\r\n          }\r\n          break;\r\n        case PaymentChannel.PalkkausCfaReference:\r\n        case PaymentChannel.PalkkausEcfaReference:\r\n          {\r\n            loader.dismiss();\r\n\r\n            const cfaReferenceCalculations = [];\r\n            if (InvoicesLogic.isPayroll(paymentObject)) {\r\n              cfaReferenceCalculations.push(...paymentObject.calcs);\r\n            } else if (InvoicesLogic.isCalculation(paymentObject)) {\r\n              cfaReferenceCalculations.push(paymentObject);\r\n            }\r\n\r\n            const cfaReferenceTotalResultCalculation = CalculatorLogic.getBlank();\r\n            cfaReferenceTotalResultCalculation.worker.tax = cfaReferenceTotalResultCalculation.worker.tax || {};\r\n            cfaReferenceTotalResultCalculation.result = CalculationResultLogic.add(cfaReferenceCalculations.map((x) => x.result));\r\n\r\n            const referenceLogic = {\r\n              printClass: \"sxyFullPrint\",\r\n              print: (pcls: \"sxyFullPrint\" | \"sxySecurePrint\") => {\r\n                referenceLogic.printClass = pcls;\r\n                setTimeout(() => {\r\n                  window.print();\r\n                }, 0);\r\n              },\r\n              calculations: cfaReferenceCalculations,\r\n              totalResultCalculation: cfaReferenceTotalResultCalculation,\r\n            };\r\n            // show dialog for every invoice status, for paid too\r\n            this.uiHelpers.openEditDialog(\"salaxy-components/modals/payment/cfa/Transfer.html\", grossInvoice, referenceLogic, \"lg\").then(() => {\r\n              navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n            });\r\n          }\r\n          break;\r\n        case PaymentChannel.PalkkausCfaTest:\r\n          {\r\n            if (isPaid(grossInvoice)) {\r\n              loader.dismiss();\r\n              navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n            } else {\r\n              loader.setHeading(Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.palkkausCfaTest.paying\") + \"...\");\r\n              this.invoicesApi.requestStatusUpdate(grossInvoice.id, InvoiceStatus.Paid).then(() => {\r\n                loader.dismiss();\r\n                navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n              });\r\n            }\r\n          }\r\n          break;\r\n        case PaymentChannel.HolviCfa:\r\n          {\r\n            if (isPaid(grossInvoice)) {\r\n              loader.dismiss();\r\n              navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n            } else {\r\n              loader.setHeading(Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.paying\") + \"...\");\r\n              this.ajax.postJSON(this.ajax.getServerAddress() + \"/partner/holvi/invoice/\" + grossInvoice.id, null).then((holviResult) => {\r\n                loader.dismiss();\r\n                if (holviResult) {\r\n                  this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.salariesMovedToPay\"), Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.holviConfirm\") + \".\" +  \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.afterConfirmation\") +  \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.accountsToWorker\") + \".\" + \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.holviCfa.palkkausIr\") + \".\");\r\n                }\r\n                navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n              });\r\n            }\r\n          }\r\n          break;\r\n        case PaymentChannel.TalenomCfa:\r\n          {\r\n            if (isPaid(grossInvoice)) {\r\n              loader.dismiss();\r\n              navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n            } else {\r\n              loader.setHeading(Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.talenomCfa.paying\") + \"...\");\r\n              this.ajax.postJSON(this.ajax.getServerAddress() + \"/partner/talenom/invoice/\" + grossInvoice.id, null).then((talenomResult) => {\r\n                loader.dismiss();\r\n                if (talenomResult) {\r\n                  this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.talenomCfa.salariesMovedToPay\"), Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.talenomCfa.talenomConfirm\") + \".\" + \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.talenomCfa.afterConfirmation\") + \".\" + \"\\n\" + Translations.get(\"SALAXY.NG1.InvoicesService.sendEInvoice.paymentChannel.talenomCfa.confirm\") + \"!\");\r\n                }\r\n                navigateToPaymentObject(grossInvoice.header.businessObjects[0]);\r\n              });\r\n            }\r\n          }\r\n          break;\r\n      }\r\n    });\r\n  }\r\n\r\n  private createPalkkausCfaPaytrailInvoice(paymentObject: Calculation | PayrollDetails) {\r\n\r\n    const navigateToPaymentObject = (businessObjectId) => {\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        this.$location.path(\"/payroll/details/\" + businessObjectId + \"&refresh=\" + new Date().getTime());\r\n      } else {\r\n        this.$location.path(\"/calc/details/\" + businessObjectId + \"&refresh=\" + new Date().getTime());\r\n      }\r\n    };\r\n\r\n    const getPaytrailUrl = (businessObjectId) => {\r\n      if (InvoicesLogic.isPayroll(paymentObject)) {\r\n        return this.ajax.getServerAddress() + `/SalaryPayment/PayInvoiceForPayroll/${businessObjectId}?access_token=${this.ajax.getCurrentToken()}`;\r\n      } else {\r\n        return this.ajax.getServerAddress() + `/SalaryPayment/PayInvoiceForCalculation/${businessObjectId}?access_token=${this.ajax.getCurrentToken()}`;\r\n      }\r\n    };\r\n\r\n    const paytrailUrl = getPaytrailUrl(paymentObject.id);\r\n    const resolver = (ev: {\r\n      /** The object passed from the other window. */\r\n      data: ExternalDialogData<any>,\r\n      /** The origin of the window that sent the message at the time postMessage was called. */\r\n      origin: string,\r\n      /** A reference to the window object that sent the message */\r\n      source: MessageEventSource | null,\r\n    }) => {\r\n      if (ev?.data.action == \"refresh\") {\r\n        this.$timeout(() => {\r\n          navigateToPaymentObject(paymentObject.id);\r\n        });\r\n        return false;\r\n      }\r\n      return true;\r\n    };\r\n\r\n    this.uiHelpers.showExternalDialog(\"PaytrailPayment\", paytrailUrl, {}, null, resolver).then((result) => {\r\n        if (result.action == \"user-cancel\") {\r\n          this.uiHelpers.showDialog(\"salaxy-components/modals/payment/PaymentCancel.html\").then(() => {\r\n            navigateToPaymentObject(paymentObject.id);\r\n          });\r\n        } else if (result.action == \"invoice-paid\") {\r\n          this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.paytrail.invoicePaid.heading\"), Translations.get(\"SALAXY.NG1.InvoicesService.paytrail.invoicePaid.text\") + \".\").then(() => {\r\n            navigateToPaymentObject(paymentObject.id);\r\n          });\r\n        } else if (result.action == \"invoice-missing\") {\r\n          this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.paytrail.invoiceMissing.heading\"), Translations.get(\"SALAXY.NG1.InvoicesService.paytrail.invoiceMissing.text\") + \".\").then(() => {\r\n          navigateToPaymentObject(paymentObject.id);\r\n          });\r\n        } else if (result.action == EditDialogKnownActions.Ok) {\r\n          this.uiHelpers.showDialog(\"salaxy-components/modals/payment/PaymentConfirm.html\").then(() => {\r\n            navigateToPaymentObject(paymentObject.id);\r\n          });\r\n        }\r\n    });\r\n  }\r\n\r\n  private createPalkkausPersonalInvoice(channel: PaymentChannel, paymentObject: Calculation | PayrollDetails, status: InvoiceStatus) {\r\n    if (InvoicesLogic.isPayroll(paymentObject)) {\r\n      this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.palkkausPersonalInvoice.isPayroll.heading\"), Translations.get(\"SALAXY.NG1.InvoicesService.palkkausPersonalInvoice.isPayroll.text\") + \".\");\r\n      return;\r\n    }\r\n\r\n    const updateInvoiceStatus = (invoice: Invoice, newStatus: InvoiceStatus): Promise<Invoice> => {\r\n      if (invoice.header.status === newStatus) {\r\n        return Promise.resolve(invoice);\r\n      }\r\n      return this.invoicesApi.requestStatusUpdate(invoice.id, newStatus);\r\n    };\r\n\r\n    const previewInvoices = (): Promise<InvoicePreview[]> => {\r\n      return this.invoicesApi.previewInvoices(channel, {\r\n        calcs: [paymentObject],\r\n      });\r\n    };\r\n\r\n    const createNewInvoice = (): Promise<Invoice[]> => {\r\n      return this.invoicesApi.createInvoices(paymentObject, channel);\r\n    };\r\n\r\n    const createInvoice = (): Promise<{netInvoice: Invoice, taxInvoice: Invoice}> => {\r\n      const netAndTaxInvoices: {netInvoice: Invoice, taxInvoice: Invoice} = {netInvoice: null, taxInvoice: null};\r\n      return previewInvoices().then((previews) => {\r\n        const netInvoicePreview = previews.find((x) => x.invoice.entityType == InvoiceType.Net && x.invoice.status !== InvoiceStatus.Canceled && x.invoice.status !== InvoiceStatus.Error);\r\n        if (!netInvoicePreview) {\r\n          return Promise.resolve(netAndTaxInvoices);\r\n        }\r\n        const taxInvoicePreview = previews.find((x) => x.invoice.entityType == InvoiceType.Tax && x.invoice.status !== InvoiceStatus.Canceled && x.invoice.status !== InvoiceStatus.Error);\r\n\r\n        const getNetInvoice = (): Promise<void> => {\r\n          return this.invoicesApi.getSingle(netInvoicePreview.invoice.id).then((netInvoice) => {\r\n            netAndTaxInvoices.netInvoice = netInvoice;\r\n          });\r\n        };\r\n\r\n        const getTaxInvoice = (): Promise<void> => {\r\n          if (!taxInvoicePreview || !taxInvoicePreview.exists) {\r\n            return Promise.resolve(null);\r\n          }\r\n          return this.invoicesApi.getSingle(taxInvoicePreview.invoice.id).then((taxInvoice) => {\r\n            netAndTaxInvoices.taxInvoice = taxInvoice;\r\n          });\r\n        };\r\n\r\n        if (netInvoicePreview.exists) {\r\n          return Promise.all([getNetInvoice(), getTaxInvoice()]).then(() => {\r\n            return netAndTaxInvoices;\r\n          });\r\n        }\r\n\r\n        return createNewInvoice().then((invoices) => {\r\n          netAndTaxInvoices.netInvoice = invoices.find((x) => x.header.type == InvoiceType.Net);\r\n          netAndTaxInvoices.taxInvoice = invoices.find((x) => x.header.type == InvoiceType.Tax);\r\n          return netAndTaxInvoices;\r\n        });\r\n      });\r\n    };\r\n\r\n    const navigateToPaymentObject = (businessObjectId) => {\r\n      this.$location.path(\"/calc/details/\" + businessObjectId + \"&refresh=\" + new Date().getTime());\r\n    };\r\n\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.InvoicesService.palkkausPersonalInvoice.updatingPaymentStatus\") + \"...\");\r\n    createInvoice().then((invoices) => {\r\n      if (!invoices.netInvoice) {\r\n        loader.dismiss();\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.InvoicesService.palkkausPersonalInvoice.createInvoice.heading\"), Translations.get(\"SALAXY.NG1.InvoicesService.palkkausPersonalInvoice.createInvoice.text\") + \"...\");\r\n        return;\r\n      }\r\n\r\n      // If status is Canceled, update only net invoice, backend will handle other invoices cancellation\r\n      if (status === InvoiceStatus.Canceled) {\r\n        updateInvoiceStatus(invoices.netInvoice, status).then(() => {\r\n          loader.dismiss();\r\n          navigateToPaymentObject(invoices.netInvoice.header.businessObjects[0]);\r\n        });\r\n      }\r\n\r\n      // if status is not canceled, update net and tax invoices\r\n      if (status !== InvoiceStatus.Canceled) {\r\n        const promises = [\r\n          updateInvoiceStatus(invoices.netInvoice, status)\r\n        ];\r\n\r\n        if (invoices.taxInvoice) {\r\n          promises.push(updateInvoiceStatus(invoices.taxInvoice, status));\r\n        }\r\n\r\n        Promise.all(promises).then(() => {\r\n          loader.dismiss();\r\n          navigateToPaymentObject(invoices.netInvoice.header.businessObjects[0]);\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n  private textToRows(text: string, rowLength: number, separator: string): string {\r\n    if (!text) {\r\n      return text;\r\n    }\r\n    const result = [];\r\n    const rows = text.split(separator);\r\n    for (const row of rows) {\r\n      let remaining = row;\r\n      while (remaining.length > rowLength) {\r\n        result.push(remaining.substr(0, rowLength));\r\n        remaining = remaining.slice(rowLength);\r\n      }\r\n      if (remaining.length > 0) {\r\n        result.push(remaining);\r\n      }\r\n    }\r\n    return result.join(separator);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { Ajax, Onboarding, Onboardings, WebSiteUserRole } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"./SessionService\";\r\nimport { UiHelpers } from \"./ui\";\r\n\r\n/**\r\n * Manages the onboarding process where an account is created.\r\n */\r\nexport class OnboardingService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\", \"$sce\", \"Onboardings\", \"SessionService\", \"UiHelpers\", \"AjaxNg1\", \"$location\"];\r\n\r\n  /** The current onboarding model */\r\n  public model: Onboarding;\r\n\r\n  /** Unique identifier of the onboarding data in storage */\r\n  public id: string;\r\n\r\n  /** Server address for onboarding pages etc. */\r\n  public serverAddress: string;\r\n\r\n  private lastPdfPreviewUrl;\r\n\r\n  constructor(\r\n    private $rootScope: angular.IRootScopeService,\r\n    private $sce: angular.ISCEService,\r\n    private onboardingsApi: Onboardings,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n    private ajax: Ajax,\r\n    private $location: angular.ILocationService,\r\n  ) {\r\n    this.init();\r\n  }\r\n\r\n  /** Gets / refreshes the onboarding data from the server  */\r\n  public getOnboardingData(id: string = null): Promise<Onboarding> {\r\n    return this.onboardingsApi.getOnboarding(id || \"latest\").then((result) => {\r\n      this.model = result;\r\n      this.id = result.id;\r\n      this.notify();\r\n      return this.model;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get the onboarding object for given account.\r\n   * @param accountId - Account id for existing account.\r\n   */\r\n  public getOnboardingDataForAccount(accountId: string): Promise<Onboarding> {\r\n    return this.onboardingsApi.getOnboardingForAccount(accountId).then((data) => {\r\n      if (data) {\r\n        this.id = data.id;\r\n      } else {\r\n        this.id = null;\r\n      }\r\n      this.model = data;\r\n      return this.model;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Saves the current onboarding to database.\r\n   * @returns A Promise with result data (Onboarding)\r\n   */\r\n  public save(): Promise<Onboarding> {\r\n    const method = (this.model.signature as any).method;\r\n    return this.onboardingsApi.saveOnboarding(this.model).then((result) => {\r\n      if (this.id !== result.id) {\r\n        this.id = result.id;\r\n      }\r\n      this.model = result;\r\n      (this.model.signature as any).method = method;\r\n      return this.model;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Commits current onboarding  and creates/changes the account.\r\n   * @returns A Promise with result data (Onboarding)\r\n   */\r\n  public commit(): Promise<Onboarding> {\r\n    return this.onboardingsApi.commitOnboarding(this.model).then((data: Onboarding) => {\r\n      this.model = data;\r\n      return this.model;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Return the new URL for digital signature: Telia and Singicat\r\n   * @param authService Select the signature service (bank / mobile auth).\r\n   * This is only supported for Telia / Persons (not companies Signicat)\r\n   * @param signerPersonalId Possibility to override the signer personal Id.\r\n   * @param testSignerPersonalId Signer personal id for test.\r\n   * @param successUrl Optional success url for the signature.\r\n   * Leaving this empty will return the brower to the current page (path, not query params / hash)\r\n   * @param cancelUrl Optional cancel / error url for the signature. Default is successUrl.\r\n   */\r\n  public getDigitalSignUrl(authService: string = null, signerPersonalId: string = null, testSignerPersonalId: string = null, successUrl = null, cancelUrl = null): string {\r\n    const returnUrl = successUrl ? successUrl :  (parent !== window) ? document.referrer : null;\r\n    return this.getServerAddress() + \"/onboarding/DigitalSignatureBegin?id=\"\r\n      + this.model.owner + \"|\" + this.id\r\n      + \"&signerPersonalId=\" + (signerPersonalId || this.model.signature.personalId || \"\")\r\n      + \"&testSignerPersonalId=\" + (testSignerPersonalId ||\"\")\r\n      + \"&authService=\" + (authService || \"\")\r\n      + \"&timestamp=\" + Date.now()\r\n      + (returnUrl ? \"&successUrl=\" + encodeURIComponent(returnUrl) : \"\")\r\n      + (cancelUrl ? \"&cancelUrl=\" + encodeURIComponent(cancelUrl) : \"\")\r\n      ;\r\n  }\r\n\r\n  /**\r\n   * Gets the PDF preview address taking into account potential changes in the model.\r\n   * @param asUntrusted - Boolean indicating if the return url should be returned as untrusted (not wrapped).\r\n   * By default, the url is returned as trusted url.\r\n   * @returns Url address\r\n   */\r\n  public getPdfPreviewAddress(asUntrusted = false): string {\r\n    let id = \"\";\r\n    if (this.model?.owner && this.id) {\r\n      id = this.model.owner + \"|\" + this.id;\r\n    }\r\n    const url = `${this.getServerAddress()}/onboarding/GetAuthorizationPdfPreview?id=${id}&signer.personalId=${this.model.signature.personalId || \"\"}`;\r\n    if (!this.lastPdfPreviewUrl || this.lastPdfPreviewUrl.url !== url) {\r\n      this.lastPdfPreviewUrl = {\r\n        url,\r\n        sce: this.$sce.trustAsResourceUrl(url),\r\n      };\r\n    }\r\n    if (asUntrusted) {\r\n      return this.lastPdfPreviewUrl.url;\r\n    }\r\n    return this.lastPdfPreviewUrl.sce;\r\n  }\r\n\r\n  /**\r\n   * Controllers can subscribe to changes in service data using this method.\r\n   * Read more about the pattern in: http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/\r\n   * @param scope Controller scope for the subscribing controller (or directive etc.)\r\n   * @param callback The event listener function. See $on documentation for details\r\n   */\r\n  public subscribe(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n    const handler = this.$rootScope.$on(\"onboarding-service-event\", callback);\r\n    scope.$on(\"$destroy\", handler);\r\n  }\r\n\r\n  /**\r\n   * Opens customer wizard as modal dialog.\r\n   * @param accountId - Optional accountId for existing company.\r\n   */\r\n  public launchCustomerOnboarding(accountId: string): Promise<any> {\r\n\r\n    const getModel = () => {\r\n      return this.getOnboardingDataForAccount(accountId).then(() => {\r\n        if (!this.model) {\r\n          this.model = {\r\n            accountType: WebSiteUserRole.Company,\r\n            signature: {},\r\n          };\r\n          this.id = null;\r\n          return this.save();\r\n        } else {\r\n          return this.model;\r\n        }\r\n      });\r\n    };\r\n\r\n    return getModel().then(() => {\r\n      // ensure correct role\r\n      this.model.accountType = WebSiteUserRole.Company;\r\n      return this.uiHelpers.showDialog(\r\n        \"salaxy-components/modals/onboarding/customer/index.html\",\r\n        \"CustomerOnboardingController\",\r\n        null,\r\n        null,\r\n        \"lg\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the current customer invitation as modal dialog.\r\n   * @param accountId - AccountId for existing company.\r\n   */\r\n   public showCustomerInvitation(accountId: string) {\r\n    const getModel = () => {\r\n      return this.getOnboardingDataForAccount(accountId).then(() => {\r\n        if (!this.model.id) {\r\n          return this.save();\r\n        } else {\r\n          return this.model;\r\n        }\r\n      });\r\n    };\r\n\r\n    return getModel().then(() => {\r\n      return this.uiHelpers.showDialog(\r\n        \"salaxy-components/modals/onboarding/customer/invitation.html\",\r\n        \"CustomerOnboardingController\",\r\n        null, null, \"lg\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Opens a generic wizard as modal dialog.\r\n   * If account type is known, opens the the wizard for that type.\r\n   * @param id - Optional onboarding id for existing onboarding.\r\n   * @param isModelLoaded  - If true, the method does not load the model from backend any more.\r\n   */\r\n  public launchGenericOnboarding(id: string = null, isModelLoaded = false): void {\r\n    const getModel = () => {\r\n      if (isModelLoaded) {\r\n        return Promise.resolve(this.model);\r\n      }\r\n      return this.getOnboardingData(id);\r\n    };\r\n\r\n    getModel().then(() => {\r\n      if (this.launchOnboardingOfType(this.model.accountType, id, true)) {\r\n        return;\r\n      }\r\n      this.uiHelpers.showDialog(\r\n        \"salaxy-components/modals/onboarding/generic/index.html\",\r\n        null,\r\n        {\r\n          launch: (close) => {\r\n            if (this.launchOnboardingOfType(this.model.accountType, id, true)) {\r\n              close();\r\n            }\r\n          },\r\n          model: this.model,\r\n        },\r\n        null);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Launches an onboarding of a type if type is specific.\r\n   * @param role Role that is evaluated: Launched if it matches one of the specific roles.\r\n   * Does not start onboarding if role is None / null etc.\r\n   * @param id Identifier of onboarding object.\r\n   * @param isModelLoaded If true, the model is already loaded.\r\n   * @returns True if the dialog is launched.\r\n   */\r\n  public launchOnboardingOfType(role: WebSiteUserRole, id: string = null, isModelLoaded = false) {\r\n    switch (this.model.accountType) {\r\n      case WebSiteUserRole.Company:\r\n        this.launchCompanyOnboarding(id, isModelLoaded);\r\n        return true;\r\n      case WebSiteUserRole.Household:\r\n        this.launchHouseholdOnboarding(id, isModelLoaded);\r\n        return true;\r\n      case WebSiteUserRole.Worker:\r\n        this.launchWorkerOnboarding(id, isModelLoaded);\r\n        return true;\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens worker wizard as modal dialog.\r\n   * @param id - Optional onboarding id for existing worker.\r\n   * @param isModelLoaded  - If true, the method does not load the model from backend any more.\r\n   */\r\n  public launchWorkerOnboarding(id: string = null, isModelLoaded = false): Promise<any> {\r\n    return this.launchOnboarding(WebSiteUserRole.Worker, \"salaxy-components/modals/onboarding/worker/index.html\", \"WorkerOnboardingController\", id, isModelLoaded);\r\n  }\r\n\r\n  /**\r\n   * Opens company wizard as modal dialog.\r\n   * @param id - Optioanl onboarding id for existing company.\r\n   * @param isModelLoaded  - If true, the method does not load the model from backend any more.\r\n   */\r\n  public launchCompanyOnboarding(id: string = null, isModelLoaded = false): Promise<any> {\r\n    return this.launchOnboarding(WebSiteUserRole.Company, \"salaxy-components/modals/onboarding/company/index.html\", \"CompanyOnboardingController\", id, isModelLoaded);\r\n  }\r\n\r\n  /**\r\n   * Opens household wizard as modal dialog.\r\n   * @param id - Optioanl onboarding id for existing company.\r\n   * @param isModelLoaded  - If true, the method does not load the model from backend any more.\r\n   */\r\n  public launchHouseholdOnboarding(id: string = null, isModelLoaded = false): Promise<any> {\r\n    return this.launchOnboarding(WebSiteUserRole.Household, \"salaxy-components/modals/onboarding/household/index.html\", \"HouseholdOnboardingController\", id, isModelLoaded);\r\n  }\r\n\r\n  /**\r\n   * Opens a simple signature page for federation (currently for Raksa / Palkkamylly only)\r\n   * @param id - Optioanl onboarding id for existing person.\r\n   * @param isModelLoaded  - If true, the method does not load the model from backend any more.\r\n   */\r\n   public launchFederateSign(id: string = null, isModelLoaded = false): Promise<any> {\r\n    return this.launchOnboarding(WebSiteUserRole.Worker, \"salaxy-components/modals/onboarding/palkkamylly/federate-sign.html\", \"WorkerOnboardingController\", id, isModelLoaded);\r\n  }\r\n\r\n  private launchOnboarding(role: WebSiteUserRole, index: string, ctrl: string, id: string = null, isModelLoaded = false, data: any = null): Promise<any> {\r\n    const getModel = () => {\r\n      if (isModelLoaded) {\r\n        return Promise.resolve(this.model);\r\n      }\r\n\r\n      return this.getOnboardingData(id);\r\n    };\r\n\r\n    return getModel().then(() => {\r\n      // ensure correct role\r\n      this.model.accountType = role;\r\n      return this.uiHelpers.showDialog(\r\n        index,\r\n        ctrl,\r\n        data,\r\n        null,\r\n        \"lg\");\r\n    });\r\n  }\r\n\r\n  private notify(): void {\r\n    this.$rootScope.$emit(\"onboarding-service-event\");\r\n  }\r\n\r\n  private getServerAddress(): string {\r\n    if (this.serverAddress) {\r\n      return this.serverAddress.replace(/\\/+$/, \"\");\r\n    }\r\n    return this.sessionService.getServerAddress();\r\n  }\r\n\r\n  /**\r\n   * Continues based on returnUrl parameter from the current url.\r\n   */\r\n  private launchReturnUrlOnboarding() {\r\n    const returnUrlParameters = this.getReturnUrlOnboardingParameters();\r\n\r\n    if (returnUrlParameters) {\r\n\r\n      const authenticate = (): Promise<any> => {\r\n        const token = this.readTokenFromUrl(\"ob_token=\");\r\n        if (token) {\r\n          this.ajax.setCurrentToken(token);\r\n          return this.sessionService.checkSession();\r\n        } else {\r\n          return Promise.resolve();\r\n        }\r\n      };\r\n\r\n      authenticate().then(() => {\r\n        switch (returnUrlParameters.onboardingType) {\r\n          case \"company\":\r\n            this.launchCompanyOnboarding(returnUrlParameters.id);\r\n            break;\r\n          case \"household\":\r\n            this.launchHouseholdOnboarding(returnUrlParameters.id);\r\n            break;\r\n          case \"worker\":\r\n            this.launchWorkerOnboarding(returnUrlParameters.id);\r\n            break;\r\n          case \"customer\":\r\n            this.launchOnboarding(WebSiteUserRole.Company, \"salaxy-components/modals/onboarding/customer/index.html\", \"CustomerOnboardingController\", returnUrlParameters.id);\r\n            break;\r\n          default:\r\n            break; // do nothing\r\n        }\r\n        this.$rootScope.$evalAsync(() => {\r\n          this.$location.path(\"/\");\r\n        });\r\n\r\n      });\r\n    }\r\n  }\r\n\r\n  private getReturnUrlOnboardingParameters() {\r\n    let url = this.$location.url();\r\n    if (url.indexOf(\"/onboarding/\") !== 0) {\r\n      url = this.readTokenFromUrl(\"url=\");\r\n      if (!url || url.indexOf(\"/onboarding/\") !== 0) {\r\n        return null;\r\n      }\r\n    }\r\n    // onboarding/company/xyz\r\n    // use regex...\r\n    const params = url.substr(\"/onboarding/\".length).split(\"/\");\r\n    if (params.length < 2) {\r\n      return;\r\n    }\r\n    const onboardingType = params[0];\r\n    const id = params[1].split(\"&\")[0];\r\n    return {\r\n      onboardingType,\r\n      id,\r\n    };\r\n  }\r\n\r\n  private readTokenFromUrl(key: string): string {\r\n    // shoud use regex...\r\n    const url = this.$location.url();\r\n    const start = url.toLowerCase().indexOf(key);\r\n    if (start >= 0) {\r\n      const end = url.indexOf(\"&\", start);\r\n      return end >= 0\r\n        ? url.substring(start + key.length, end)\r\n        : url.substring(start + key.length);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private init() {\r\n    this.$rootScope.$on(\"$locationChangeStart\", () => {\r\n      this.launchReturnUrlOnboarding();\r\n    });\r\n  }\r\n}\r\n","import { BrandListItem } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"./SessionService\";\r\nimport { EditDialogKnownActions, EditDialogResult } from \"./ui\";\r\nimport { UiHelpers } from \"./ui/UiHelpers\";\r\n\r\n/**\r\n * Provides methods for managing the Primary partner,\r\n * which is primary source of service in payroll matters.\r\n * Typically, this would be customer's primary Accounting company.\r\n */\r\nexport class PartnerService {\r\n\r\n  /**\r\n   * For NG-dependency injection.\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\", \"UiHelpers\"];\r\n\r\n  /** Skin that is currently in use as a temporary override (for preview purposes) or null if default skin is used. */\r\n  public overrideSkin: string;\r\n\r\n  /** Partner id that is currently in use as a temporary override (for preview purposes) or null if real id used. */\r\n  public overridePartnerId: string;\r\n\r\n  /**\r\n   * Creates a new instance of the PartnerService with dependency injection.\r\n   */\r\n  constructor(private sessionService: SessionService, private uiHelpers: UiHelpers) {\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for brand selection.\r\n   * The result may be \"ok\" for selected brand or \"set-default\" for reset to original brand.\r\n   */\r\n  public showBrandSelection() : Promise<EditDialogResult<BrandListItem>> {\r\n    const item: {\r\n      brand: BrandListItem\r\n    } = {\r\n      brand: null\r\n    };\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/modals/settings/BrandSelection.html\", item, null).then((dialog) => {\r\n      const result: EditDialogResult<BrandListItem> = {\r\n        action: dialog.action,\r\n        hasChanges: dialog.hasChanges,\r\n        logic: dialog.logic,\r\n        result: dialog.result,\r\n        item: dialog.result == EditDialogKnownActions.Ok ? dialog.item.brand : null,\r\n      };\r\n      return result;\r\n    });\r\n  }\r\n\r\n\r\n  /**\r\n   * Shows a dialog for switching the CSS.\r\n   */\r\n   public showSwitchCss(): void {\r\n     this.showBrandSelection().then((dialog) => {\r\n      if (dialog.result == EditDialogKnownActions.Ok) {\r\n        this.overrideSkin = dialog.item.data.skin;\r\n        this.overridePartnerId = dialog.item.id;\r\n        this.sessionService.switchCss(dialog.item.data.skin);\r\n      } else if (dialog.result == \"set-default\") {\r\n        this.overrideSkin = null;\r\n        this.overridePartnerId = null;\r\n        this.sessionService.switchCss(null);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Temporary method only used in development\r\n   * Shows a dialog for switching the CSS.\r\n   */\r\n  public showSwitchCssDev(): void {\r\n    this.showBrandSelection().then((dialog) => {\r\n     if (dialog.result == EditDialogKnownActions.Ok) {\r\n       this.overrideSkin = dialog.item.data.skin;\r\n       this.overridePartnerId = dialog.item.id;\r\n       this.sessionService.switchCss(dialog.item.data.skin, true);\r\n     } else if (dialog.result == \"set-default\") {\r\n       this.overrideSkin = null;\r\n       this.overridePartnerId = null;\r\n       this.sessionService.switchCss(null, true);\r\n     }\r\n   });\r\n }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingReportTable, AccountingReportTableType, calcReportType, Calculation, PeriodType, Report, reportPartial, Reports, ReportsLogic, ReportType } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"./SessionService\";\r\nimport { UiHelpers } from \"./ui\";\r\n\r\n/**\r\n * Methods for viewing and later also generating different reports.\r\n */\r\nexport class ReportsService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\", \"SessionService\", \"UiHelpers\", \"Reports\", \"$sce\"];\r\n\r\n  /**\r\n   * Convenience property for navigation controls to set a current report type.\r\n   * Checked, when getReports is called with null or \"current\"\r\n   */\r\n  public currentReportType: ReportType = null;\r\n\r\n  /** Cache for reports-by-type as generated on the server */\r\n  private reportMetadataCache: { owner?: string, [key:string]: any} = {};\r\n\r\n  /**\r\n   * Creates a new instance of ReportsService\r\n   * @param $rootScope - Angular rootscope.\r\n   * @param sessionService - Session service notifies when the user is known to be authenticated.\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   * @param reportsApi - The Reports API that is used to communicating with the server.\r\n   * @param $sce - $sce is a service that provides Strict Contextual Escaping services to AngularJS\r\n   */\r\n  constructor(\r\n    $rootScope: angular.IRootScopeService,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n    private reportsApi: Reports,\r\n\r\n    private $sce: angular.ISCEService,\r\n  ) {\r\n    this.refresh();\r\n\r\n    sessionService.subscribe($rootScope, () => {\r\n      this.refresh();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Clear metadata cache.\r\n   */\r\n  public refresh() {\r\n    if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n      const owner = this.sessionService.session.currentAccount.owner;\r\n      if (this.reportMetadataCache.owner != owner){\r\n        this.reportMetadataCache = { owner };\r\n      }\r\n    } else {\r\n      this.reportMetadataCache = {};\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets a list of reports (metadata only) filtered by a report type.\r\n   * @param type - Type of report. See type (string enumeration) for possible values.\r\n   * Also supports value \"current\" for showing reports defined by currentReportType.\r\n   * @returns A Promise with result data (<Report[]) if dataset not fetched, else the fetched dataset\r\n   */\r\n  public getReports(type: ReportType | \"current\"): Promise<Report[]> | Report[] {\r\n    if (!type || type === \"current\") {\r\n      type = this.currentReportType;\r\n    }\r\n    if (!type || type as any === \"undefined\") {\r\n      return [];\r\n    }\r\n    let list = this.reportMetadataCache[type];\r\n    if (!list) {\r\n      list = [];\r\n      this.reportMetadataCache[type] = [];\r\n      return this.reportsApi.getReportsByType(type).then((result) => {\r\n        this.reportMetadataCache[type] = result;\r\n        return result;\r\n      });\r\n    }\r\n    return list;\r\n  }\r\n\r\n  /**\r\n   * Gets a link URL for a yearly report. This is a full link with token and absolute URL.\r\n   * @param type - Type of the report must be one of the yearly reports\r\n   * @param year - Year for the report\r\n   * @param id - Worker ID for those reports that are specific to one Worker.\r\n   * @param id2 - Second Worker ID for those reports that have two Workers in one report\r\n   * @returns Yearly report URL string\r\n   */\r\n  public getYearlyReportUrl(type: ReportType, year: number, id?: string, id2?: string): string {\r\n    return this.sessionService.getServerAddress()\r\n      + ReportsLogic.getYearlyReportUrl(type, year, this.sessionService.getCurrentToken(), id, id2);\r\n  }\r\n\r\n\r\n  /**\r\n   * Gets a. URL for a calculation pdf.\r\n   * If report has not been saved (ID is null), returns null.\r\n   * @param reportType - Type of report\r\n   * @param calcId - Identifier of the calculation. This method requires that the calculation has been saved.\r\n   * @param inline - If true, the Content-Disposition header is returned with inline parameter.\r\n   * @returns Url for specified report\r\n   */\r\n  public getPdfUrlForCalc(reportType: calcReportType, calcId: string, inline = false): string {\r\n    if (!calcId) {\r\n      return null;\r\n    }\r\n    return this.sessionService.getServerAddress()\r\n      + ReportsLogic.getCalcPdfUrl(reportType, calcId, inline, this.sessionService.getCurrentToken());\r\n  }\r\n\r\n  /**\r\n   * Gets an URL for pdf report for one or more calculations.\r\n   * @param type - Type of report\r\n   * @param ids - Identifiers of the calculations. This method requires that the calculations have been saved.\r\n   * @param inline - If true, the Content-Disposition header is returned with inline parameter.\r\n   * @returns Url for specified report\r\n   */\r\n   public getPdfUrlForCalcs(type: \"salarySlip\" | \"employerReport\" | \"paymentReport\", ids: string[], inline = false): string {\r\n    if (!ids || ids.length === 0) {\r\n      return null;\r\n    }\r\n\r\n    return this.sessionService.getServerAddress() +\r\n    `/v03/api/reports/assure-pdf/${type}?ids=${ids.join(\"&ids=\")}&disposition=${inline ? \"inline\" : \"attachment\"}&access_token=${encodeURIComponent(this.sessionService.getCurrentToken())}`;\r\n  }\r\n\r\n  /**\r\n   * Show a report modal (a preview modal dialog) for a given calculation.\r\n   * The calculation may not be stored to backend. I.e. this reporting method is available also to\r\n   * non-authenticated users unlike the more resource intensive methods that generate PDF-files and require CRUD rights.\r\n   * @param reportType - Type of the report to show.\r\n   * @param calculation - Calculation to show in the report.\r\n   * @param view - The default view shown in the UI: \"page1\" (default), \"partial\" or \"full\".\r\n   * @param preview - If true, adds the preview watermark to the report.\r\n   */\r\n  public showReportModalForCalc(reportType: calcReportType, calculation: any, view: \"partial\" | \"page1\" | \"full\" = \"page1\", preview = false): void {\r\n\r\n    const calcs: Calculation[] = [calculation];\r\n\r\n    const data = {\r\n      reportType,\r\n      calcs,\r\n      view,\r\n      preview,\r\n    };\r\n\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/calc/CalcReports.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"xl\",\r\n      true);\r\n  }\r\n\r\n  /**\r\n   * Gets the monthly / quarterly/ yearly accounting data for the current account.\r\n   * @param refDate - Reference date for the period. Please note that even if the date is not the first day of the given period, the entire period is returned.\r\n   * @param tableType  - Accounting table type.\r\n   * @param periodType - Month, quarter, year or a custom period. The custom period requires endDate. Default value is the month.\r\n   * @param endDate - End date for the period. Required only for the custom period.\r\n   * @returns A Promise with result data (Raw data for accounting purposes).\r\n   */\r\n  public getAccountingReportTableForPeriod(refDate: string, tableType: AccountingReportTableType = AccountingReportTableType.Classic, periodType: PeriodType = PeriodType.Month, endDate: string = null): Promise<AccountingReportTable> {\r\n    return this.reportsApi.getAccountingReportTableForPeriod(refDate, tableType, periodType, endDate);\r\n  }\r\n\r\n  /**\r\n   * Experimental: Gets the accounting report based on given set of calculations.\r\n   * @param calculationIds - Calculations that are the bases for the report.\r\n   * @param tableType  - Accounting table type.\r\n   * @returns Account report based on the calculations.\r\n   * @ignore\r\n   */\r\n  public getAccountingReportTableForCalculationIds(calculationIds: string[], tableType: AccountingReportTableType = AccountingReportTableType.Classic): Promise<AccountingReportTable> {\r\n    return this.reportsApi.getAccountingReportTableForCalculationIds(calculationIds, tableType);\r\n  }\r\n\r\n  /**\r\n   * Experimental: Gets the accounting report based on given set of calculations.\r\n   * @param calculations - Calculations that are the bases for the report.\r\n   * @param tableType  - Accounting table type.\r\n   * @returns Account report based on the calculations.\r\n   * @ignore\r\n   */\r\n  public getAccountingReportTableForCalculations(calculations: Calculation[], tableType: AccountingReportTableType = AccountingReportTableType.Classic): Promise<AccountingReportTable> {\r\n    return this.reportsApi.getAccountingReportTableForCalculations(calculations, tableType);\r\n  }\r\n\r\n  /**\r\n   * Gets an HTML report based on Calculation ID and runs it through $sce.\r\n   * @param reportType - Type of the report to fetch. See the HtmlReportType enumeration for possible values.\r\n   * @param calculationId - GUID for the calculation\r\n   * @returns A Promise with result HTML - already run through $sce.\r\n   */\r\n  public getReportHtmlById(reportType: reportPartial, calculationId: string): Promise<any> {\r\n    return this.reportsApi.getReportHtmlById(reportType, calculationId).then((html) => {\r\n      return this.$sce.getTrustedHtml(html);\r\n    });\r\n  }\r\n}\r\n","import { SettingsService } from \"./SettingsService\";\r\nimport { CalcRowConfig, CalcRowsLogic, CalculationRowCategories, CalculationRowSource, CalculationRowType, RowTypeDefinition, UserDefinedRow, Years } from \"@salaxy/core\";\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/**\r\n * Provides access to the row types including the company specific custom row types.\r\n */\r\nexport class RowTypeService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SettingsService\", \"SessionService\"];\r\n\r\n  /** A key that signals when the settings were last updated => Used by downstream caches to refresh.  */\r\n  public timestamp: string;\r\n\r\n\r\n  /** Cached version of the CalcRowsLogic */\r\n  private _logic?: CalcRowsLogic;\r\n\r\n  /**\r\n   * Creates a new instance of RowTypeService\r\n   */\r\n  constructor(private settingsService: SettingsService, private session: SessionService) {\r\n  }\r\n\r\n  /**\r\n   * Gets a cached version of CalcRowsLogic with current settings (if available).\r\n   */\r\n  public get logic(): CalcRowsLogic {\r\n    if (this.session.isInRole(\"household\")) {\r\n      if (!this._logic) {\r\n        this.refresh();\r\n        this._logic = new CalcRowsLogic(\"household\");\r\n      }\r\n      return this._logic;\r\n    }\r\n    if (!this.isReady) {\r\n      // Just provide dynamic, should not neede to be cached.\r\n      return new CalcRowsLogic(\"company\");\r\n    }\r\n    if (!this._logic) {\r\n      this.refresh();\r\n      this._logic = new CalcRowsLogic(this.settingsService.current);\r\n    }\r\n    return this._logic;\r\n  }\r\n\r\n  /** Clears the cache and reloads the row types (from settings service singleton, not all the way from the server). */\r\n  public refresh(): void {\r\n    this._logic = null;\r\n    this.timestamp = new Date().toLocaleTimeString();\r\n  }\r\n\r\n  /**\r\n   * If true, the custom row types (currently in settings) have been loaded from the server.\r\n   */\r\n  public get isReady(): boolean {\r\n    return !!this.settingsService.current;\r\n  }\r\n\r\n  /**\r\n   * Gets a filtered list of row types configs\r\n   * @param group If specified, filters the configs by group (builtIn, custom).\r\n   */\r\n  public getConfigs(group?: \"builtIn\" | \"custom\", categories?: CalculationRowCategories[]): CalcRowConfig[] {\r\n    let result = this.configs;\r\n    if (group) {\r\n      result = result.filter((x) => x.group === group);\r\n    }\r\n    if (categories && categories.length > 0) {\r\n      result = result.filter((x) => categories.indexOf(x.category) >= 0);\r\n      // TODO: Old logic removed IR IncomeType from the list. why was that? And why is it in such a hacky way?\r\n      /*\r\n      // Remove kind from IrIncomeType: prevent listing of income types in category based lists\r\n        const irIncomeType = value.find((x) => x.name === CalculationRowType.IrIncomeType);\r\n        if (irIncomeType != null) {\r\n          irIncomeType.kind = null;\r\n        }\r\n      */\r\n    }\r\n\r\n    const obsolete: string[] = [\r\n      CalculationRowType.PaidSickLeaveSalary,\r\n      CalculationRowType.PaidSickLeaveHourlySalary,\r\n      CalculationRowType.PaidSickLeaveMonthlySalary,\r\n      CalculationRowType.TrainingSalary,\r\n      CalculationRowType.TrainingHourlySalary,\r\n      CalculationRowType.TrainingMonthlySalary,\r\n      CalculationRowType.ServiceCharge\r\n    ];\r\n    result = result.filter((x) => !(obsolete.indexOf(x.name) >= 0));\r\n\r\n    // For pro and admin only\r\n    if (!this.session.isInSomeRole(\"pro,admin\")) {\r\n      result = result.filter((x) => x.name != CalculationRowType.Service);\r\n    }\r\n\r\n    return result;\r\n  }\r\n\r\n  private listCache: {\r\n    /** Cache key */\r\n    key: string,\r\n    /** Cache value */\r\n    value: CalcRowConfig[],\r\n  } = null;\r\n\r\n  /** Gets a cached list of all configs (even the ones that should typically be hidden from the list by role or because they are obsolete). */\r\n  public get configs(): CalcRowConfig[] {\r\n    if (!this.listCache || this.listCache.key !== this.timestamp) {\r\n      const value = this.logic.getRowConfigs();\r\n      this.listCache = { key: this.timestamp, value };\r\n    }\r\n    return this.listCache.value;\r\n  }\r\n\r\n  /** Gets the editble rows collection. */\r\n  public get allCustomRows(): RowTypeDefinition[] {\r\n    return this.settingsService.current?.calc.salaryDefaults as RowTypeDefinition[] ?? [];\r\n  }\r\n\r\n  /**\r\n   * Gets the configuration for a row: May be built-in or custom row type..\r\n   * @param row Row for which to get the configuration.\r\n   * @returns A configuration if found, otherwise undefined.\r\n   */\r\n  public getConfig(row: UserDefinedRow): CalcRowConfig | undefined {\r\n    if (!row) {\r\n      return undefined;\r\n    }\r\n    if (row.source == CalculationRowSource.CustomRowtype) {\r\n      return (row as RowTypeDefinition).config;\r\n    }\r\n    let result: CalcRowConfig;\r\n    if (row.type?.startsWith(\"/\")) {\r\n      result = this.logic.getRowConfigs().find((x) => x.type == row.type);\r\n      if (result) {\r\n        return result;\r\n      }\r\n      console.warn(`Unable to find the row based on the new type '${row.type}' => Fall back to rowType based resolve.`);\r\n    }\r\n\r\n    result = this.logic.getRowConfig(row.rowType);\r\n    if (!result) {\r\n      console.error(`Row type '${row.rowType}' not found in the row type definitions.`);\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Deletes an item in the allCustomRows collection.\r\n   * This does not yet save the changes or even refresh the cache.\r\n   */\r\n  public deleteRow(row: RowTypeDefinition): void {\r\n    const index = this.allCustomRows.indexOf(row);\r\n    if (index >= 0) {\r\n      this.allCustomRows.splice(index, 1);\r\n    }\r\n  }\r\n\r\n  /** Saves the current, potentitally modified set of custom rows. */\r\n  public async save(): Promise<void> {\r\n    this.settingsService.saveWithoutSessionCheck();\r\n    this.refresh();\r\n  }\r\n\r\n  /**\r\n   * Call this method when a new row is created to apply the default values.\r\n   */\r\n  public applyDefaultsToNewRow(row: UserDefinedRow, salaryDate: string): void {\r\n    if (!row || !row.rowType) {\r\n      return;\r\n    }\r\n    const config = this.getConfig(row);\r\n    if (config.amount.default) {\r\n      row.count = config.amount.default;\r\n    }\r\n    if (config.price.default) {\r\n      row.price = config.price.default;\r\n    }\r\n\r\n    const specialKnownRowTypes = this.specialKnownRowTypesAtSalaryDate(salaryDate);\r\n    if (specialKnownRowTypes[config.name]) {\r\n      row.price = specialKnownRowTypes[config.name];\r\n    }\r\n\r\n    if (config.group == \"custom\") {\r\n      const customRow = this.allCustomRows.find((x) => x.source == CalculationRowSource.CustomRowtype && x.type == config.type);\r\n      if (customRow) {\r\n        if (customRow.count) {\r\n          row.count = customRow.count;\r\n        }\r\n        if (customRow.price) {\r\n          row.price = customRow.price;\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  private specialKnownRowTypesAtSalaryDate(salaryDate): { [key: string]: number } {\r\n    const yearlyNumbers = Years.getYearlyChangingNumbers(salaryDate ?? \"today\");\r\n    return {\r\n      dailyAllowance: yearlyNumbers.sideCosts.taxFreeDailyAllowance,\r\n      dailyAllowanceHalf: yearlyNumbers.sideCosts.taxFreeDailyHalfAllowance,\r\n      mealCompensation: yearlyNumbers.sideCosts.taxFreeMealAllowance,\r\n    };\r\n  }\r\n\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  AccountBase,\r\n  Accounts,\r\n  Ajax,\r\n  AppStatus,\r\n  Arrays,\r\n  Avatar,\r\n  CompanyAccount,\r\n  Configs,\r\n  Language,\r\n  OAuthSalaxyAuthorizeMode,\r\n  PaymentChannel,\r\n  PersonAccount,\r\n  Role,\r\n  RoleLogic,\r\n  Session,\r\n  SystemRole,\r\n  Token,\r\n  Translations,\r\n  UserSession,\r\n  Workers\r\n} from \"@salaxy/core\";\r\nimport { AlertService } from \"./ui\";\r\n\r\n/**\r\n * Helps in managing the login process and provides information of the current session\r\n */\r\nexport class SessionService {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"$rootScope\",\r\n    \"Session\",\r\n    \"Accounts\",\r\n    \"$window\",\r\n    \"$location\",\r\n    \"AjaxNg1\",\r\n    \"$timeout\",\r\n    \"AlertService\",\r\n    \"Workers\",\r\n    \"$locale\"\r\n  ];\r\n\r\n  /** If true, the user is authenticated */\r\n  public isAuthenticated: boolean;\r\n\r\n  /** If true, the session has been checked from the server */\r\n  public isSessionChecked: boolean;\r\n\r\n  /** If true, the session call is progressing  */\r\n  public isSessionChecking: boolean;\r\n\r\n  /** Avatar to show in the login screen */\r\n  public avatar: Avatar;\r\n\r\n  /** The full session objcet */\r\n  public session: UserSession;\r\n\r\n  /** The person account object if the currently selected account is a person */\r\n  public personAccount: PersonAccount = null;\r\n\r\n  /** The company account object if the currently selected account is a company */\r\n  public companyAccount: CompanyAccount = null;\r\n\r\n  /** Sign in error */\r\n  public signInError: string;\r\n\r\n  /** Sign in error description */\r\n  public signInErrorDescription: string;\r\n\r\n  /** Sign in error page url */\r\n  public signInErrorUrl: string;\r\n\r\n  /** Partner site */\r\n  public partnerSite: string;\r\n\r\n  /**\r\n   * Application specific roles that are set on the client (browser code)\r\n   * as opposed to normal server-side defined roles.\r\n   */\r\n  public clientRoles: string[] = [];\r\n\r\n  private _isLoading: boolean;\r\n  public workerLangs: { [key: string]: Language } = {};\r\n  private static SKIN_SESSION_STORAGE = \"salaxy.skin\";\r\n\r\n  constructor(\r\n    private $rootScope: angular.IRootScopeService,\r\n    private sessionApi: Session,\r\n    private accountApi: Accounts,\r\n    private $window: angular.IWindowService,\r\n    private $location: angular.ILocationService,\r\n    private ajax: Ajax,\r\n\r\n    private $timeout: angular.ITimeoutService,\r\n    private alertService: AlertService,\r\n    private workers: Workers,\r\n\r\n    private $locale: any,\r\n  ) {\r\n    this.subscribeToLocationChange();\r\n  }\r\n\r\n  /**\r\n   * Initializes the session service.\r\n   * Note that the session loading will currently begin already in constructor.\r\n   */\r\n  public init(): void {\r\n    this.alertService.init(); // This should be done automatically in constructor, but we make sure here so that there is an explicit reference.\r\n  }\r\n\r\n  /**\r\n   * Controllers can subscribe to changes in service data using this method.\r\n   * Read more about the pattern in: http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/\r\n   * @param scope - Controller scope for the subscribing controller (or directive etc.)\r\n   * @param callback - The event listener function. See $on documentation for details\r\n   */\r\n  public subscribe(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n    const handler = this.$rootScope.$on(\"session-service-event\", callback);\r\n    scope.$on(\"$destroy\", handler);\r\n  }\r\n\r\n  /**\r\n   * Services can subscribe to this event to be notified when it is known that there is an authenticated session\r\n   * (as opposed to anonymous session). Uses the same pattern as subscribe.\r\n   * @param scope - Controller scope for the subscribing controller (or directive etc.)\r\n   * @param callback - The event listener function. See $on documentation for details\r\n   */\r\n  public onAuthenticatedSession(scope: angular.IScope, callback: (event: angular.IAngularEvent, ...args: any[]) => any): void {\r\n    const handler = this.$rootScope.$on(\"session-auth-session-event\", callback);\r\n    scope.$on(\"$destroy\", handler);\r\n  }\r\n\r\n  /**\r\n   * If true, the session is loading: Session, i18n files, service model or something else\r\n   * that may break the entire user interface is (re)loading: User interface should show a loader.\r\n   * Note that isSessionChecking overrides the set value in getter.\r\n   */\r\n  public get isLoading(): boolean {\r\n    return this._isLoading || this.isSessionChecking;\r\n  }\r\n  public set isLoading(value: boolean) {\r\n    this._isLoading = value;\r\n  }\r\n\r\n  /** If true, the user is authenticated */\r\n  public getIsAuthenticated(): boolean {\r\n    return this.isAuthenticated;\r\n  }\r\n\r\n  /** If true, the session has been checked from the server */\r\n  public getIsSessionChecked(): boolean {\r\n    return this.isSessionChecked;\r\n  }\r\n\r\n  /** If true, the session call is progressing */\r\n  public getIsSessionChecking(): boolean {\r\n    return this.isSessionChecking;\r\n  }\r\n\r\n  /** Avatar to show in the login screen */\r\n  public getAvatar(): Avatar {\r\n    return this.avatar;\r\n  }\r\n\r\n  /** The full session objcet */\r\n  public getSession(): UserSession {\r\n    return this.session;\r\n  }\r\n\r\n  /** Gets either the Company account or PErson account depending of the type of the current account. */\r\n  public getCurrentAccount(): AccountBase {\r\n    return this.getCompanyAccount() || this.getPersonAccount();\r\n  }\r\n\r\n  /** Get the person account object if the currently selected account is a person */\r\n  public getPersonAccount(): PersonAccount {\r\n    return this.personAccount;\r\n  }\r\n\r\n  /** The company account object if the currently selected account is a company */\r\n  public getCompanyAccount(): CompanyAccount {\r\n    return this.companyAccount;\r\n  }\r\n\r\n  /** Gets the address for the API server where the session is connected */\r\n  public getServerAddress(): string {\r\n    return this.sessionApi.getServerAddress();\r\n  }\r\n\r\n  /**\r\n   * Returns current access token\r\n   */\r\n  public getCurrentToken(): string {\r\n    return this.ajax.getCurrentToken();\r\n  }\r\n\r\n  /**\r\n   * Checks whether the user is in a given role\r\n   * @param role - One of the known roles or role from server.\r\n   * You can also use exclamation mark for negative (e.g. \"!test\")\r\n   * @returns True if user is in the given role,\r\n   * or if given roles is null/empty.\r\n   */\r\n  public isInRole(role: SystemRole | Role | string): boolean {\r\n    return RoleLogic.isInRole(this.getSession(), this.getAppStatus(), role);\r\n  }\r\n\r\n  /**\r\n   * Checks if the user is in ANY of the roles.\r\n   * @param commaSeparatedRolesList - Array of roles or comma separated string containing role names.\r\n   * @returns True if user is in one of the given roles,\r\n   * or if given roles is null or an empty array.\r\n   */\r\n  public isInSomeRole(commaSeparatedRolesList: (SystemRole | Role | string)[] | string): any {\r\n    return RoleLogic.isInSomeRole(this.session, this.getAppStatus(), Arrays.assureArray(commaSeparatedRolesList));\r\n  }\r\n\r\n  /**\r\n   * Tests if the current account has ALL the given roles.\r\n   * @param accountRoles - Array of roles.\r\n   * @returns Returns true if the account has all the given roles,\r\n   * or if given roles is null or an empty array.\r\n   */\r\n  public isInAllRoles(accountRoles: (SystemRole | Role | string)[]): boolean {\r\n    return RoleLogic.isInAllRoles(this.session, this.getAppStatus(), accountRoles);\r\n  }\r\n\r\n  /** Posts a message to the parent window. The message is sent as salaxySessionEvent  */\r\n  public postMessageToParent(message: string) {\r\n    if (window.parent !== window && window.parent.postMessage) {\r\n      window.parent.postMessage({ salaxySessionEvent: message }, \"*\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Checks the current session from the server if user has token (either in-memory or in cookie)\r\n   * @returns A Promise with result data (UserSession)\r\n   */\r\n  public checkSession(): Promise<UserSession> {\r\n    this.isSessionChecking = true;\r\n    let token = this.ajax.getCurrentToken();\r\n    if (Token.validate(token) !== \"ok\") {\r\n      token = null;\r\n      this.ajax.setCurrentToken(token);\r\n    }\r\n\r\n    if (!token) {\r\n      this.isSessionChecked = true;\r\n      this.isAuthenticated = false;\r\n      this.avatar = null;\r\n      this.session = null;\r\n      this.setLanguageForSession();\r\n      this.companyAccount = null;\r\n      this.notify();\r\n      this.isSessionChecking = false;\r\n      return new Promise((resolve) => {\r\n        this.$timeout(() => {\r\n          resolve(null);\r\n        });\r\n      });\r\n    }\r\n\r\n    // Use always real partner css first in production\r\n    const cssUrl = this.resolveCss();\r\n    const isDev = (cssUrl?.startsWith(\"/dev-skins\"));\r\n    this.switchCss(cssUrl, isDev);\r\n\r\n    return this.sessionApi.getSession().then((result: UserSession) => {\r\n      return this.setSession(result);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the session to a session object that has already been fetched from the server.\r\n   * Note that the caller should also set the token to Ajax.\r\n   * @param session - Session object to set as current session.\r\n   */\r\n  public setSession(session: UserSession | undefined): UserSession {\r\n    this.isSessionChecking = false;\r\n    this.isSessionChecked = true;\r\n    if (session) {\r\n      this.isAuthenticated = session.isAuthorized;\r\n      this.avatar = session.avatar;\r\n      this.session = session;\r\n      this.setLanguageForSession();\r\n      if (this.session.isAuthorized) {\r\n        const entityType = (session.currentAccount as AccountBase).entityType;\r\n        if (entityType === \"company\") {\r\n          this.companyAccount = this.session.currentAccount;\r\n        } else if (entityType === \"person\") {\r\n          this.personAccount = this.session.currentAccount;\r\n        }\r\n        this.notify();\r\n        this.notifyAuthenticatedSession();\r\n        this.postMessageToParent(\"success\");\r\n        return this.session;\r\n      } else {\r\n        this.notify();\r\n        this.postMessageToParent(\"failure\");\r\n        return this.session;\r\n      }\r\n    } else {\r\n      this.isAuthenticated = false;\r\n      this.avatar = null;\r\n      this.session = null;\r\n      this.companyAccount = null;\r\n      this.notify();\r\n      this.postMessageToParent(\"failure\");\r\n      return session;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Switches the current web site usage role and refreshes the session.\r\n   * @param role - household or worker.\r\n   * @returns A Promise with result data (new role as string)\r\n   */\r\n  public switchRole(role: \"household\" | \"worker\"): Promise<\"household\" | \"worker\"> {\r\n    return this.accountApi.switchRole(role).then((result) => {\r\n      return this.checkSession().then(() => {\r\n        return result;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sends the browser to standard Sign-in page on Salaxy API server.\r\n   * @param redirectUrl - The URL where the user is taken after a successfull login\r\n   * @param role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   * @param partnerSite Identifier of the partner or service model from which the login UI is fetched.\r\n   * @param urlPostfix Additional string that is added to the OAuth2 URL.\r\n   * Used in adding other parameters to the URL, e.g. \"&salaxy_language=en\"\r\n   */\r\n  public signIn(redirectUrl: string = null, role: string = null, partnerSite: string = null, urlPostfix: string = null): void {\r\n    this.authorize(redirectUrl, role, partnerSite, OAuthSalaxyAuthorizeMode.Sign_in, urlPostfix);\r\n  }\r\n\r\n  /**\r\n   * Sends the browser to standard signUp / register page on Salaxy API server.\r\n   * @param redirectUrl - The URL where the user is taken after a successfull login\r\n   * @param role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   * @param partnerSite Identifier of the certified partner which should be granted access rights in account creation.\r\n   * Also sets SignIn dialog and onboarding wizard UI skin.\r\n   * @param urlPostfix Additional string that is added to the OAuth2 URL.\r\n   * Used in adding other parameters to the URL, e.g. \"&salaxy_language=en\"\r\n   */\r\n  public register(redirectUrl: string = null, role: string = null, partnerSite: string = null, urlPostfix: string = null): void {\r\n    this.authorize(redirectUrl, role, partnerSite, OAuthSalaxyAuthorizeMode.Sign_up, urlPostfix);\r\n  }\r\n\r\n  /**\r\n   * Sends the user to the Sign-out page\r\n   * @param redirectUrl - URL where user is redirected after log out.\r\n   * Must be absolute URL. Default is the root of the current server.\r\n   */\r\n  public signOut(redirectUrl?: string): void {\r\n    this.ajax.setCurrentToken(null);\r\n\r\n    const getOrigin = () =>\r\n      window.location.protocol +\r\n      \"//\" +\r\n      window.location.hostname +\r\n      (window.location.port ? \":\" + window.location.port : \"\");\r\n\r\n    const regEx = new RegExp(/www2\\./, \"ig\");\r\n    redirectUrl = (redirectUrl || getOrigin()).replace(regEx, \"www.\");\r\n    this.checkSession().then(() => {\r\n      this.$window.location.href = redirectUrl;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current authenticated user has signed the contract.\r\n   */\r\n  public isSigningOk(): boolean {\r\n    if (this.session\r\n      && this.session.currentAccount\r\n      && this.session.currentAccount.identity.contract\r\n      && this.session.currentAccount.identity.contract.isSigned) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current authenticated user has signed the contract\r\n   * OR if the user does not have session OR if user is anonymous.\r\n   */\r\n  public checkAccountVerification(): boolean {\r\n    // Anon user cannot have contract, return always true\r\n    if (!this.session || !this.session.currentAccount) {\r\n      return true;\r\n    }\r\n    // Return true if session and signing\r\n    if (this.session.currentAccount.identity.contract\r\n      && this.session.currentAccount.identity.contract.isSigned) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Gets the application status that supports the UserSession object by providing additional\r\n   * information about the status of fetching the session, data, expiration etc.\r\n   */\r\n  public getAppStatus(): AppStatus {\r\n    // TODO: We should probably add isTestData to Ajax, but that needs changes in all environments.\r\n    // Fetching from config should work fine in NG as is compatible with future changes.\r\n    let isTestData: boolean = null;\r\n    const config = Configs.current;\r\n    if (config && config.isTestData != null) {\r\n      isTestData = config.isTestData;\r\n    }\r\n\r\n    const clientRoles = angular.copy(this.clientRoles ?? []);\r\n    /*\r\n      if (clientRoles.indexOf(\"pro\") < 0 && this.parseRoleFromAccessToken(\"pro\")) {\r\n        clientRoles.push(\"pro\");\r\n      }\r\n      if (clientRoles.indexOf(\"admin\") < 0 && this.parseRoleFromAccessToken(\"admin\")) {\r\n        clientRoles.push(\"admin\");\r\n      }\r\n    */\r\n    return {\r\n      sessionCheckInProgress: this.getIsSessionChecking() || !this.getIsSessionChecked(),\r\n      clientRoles,\r\n      isTestData,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * TODO: Encapsulate this functionality to Ui-customization service. MJ\r\n   *\r\n   * Switches the CSS link to partner-specific CSS.\r\n   * @param cssUrl URL for the CSS file. Typically, \"css/skins/${skin}.css\"\r\n   * @param useDevelopmentFolder If true, uses the local css file (development environment only).\r\n   * By default, uses the CDN.\r\n   */\r\n  public switchCss(cssUrl: string, useDevelopmentFolder = false) {\r\n    const linkId = \"salaxyMainCss\";\r\n    const link = document.getElementById(linkId) as HTMLLinkElement;\r\n    // If link id exists, we can customize the css\r\n    if (link) {\r\n      cssUrl = cssUrl || \"css/skins/palkkaus.css\";\r\n      if (useDevelopmentFolder) {\r\n        cssUrl = cssUrl.replace(\"css/skins\", \"/dev-skins\");\r\n      } else {\r\n        cssUrl = this.convertSkinPath(cssUrl || \"css/skins/palkkaus.css\");\r\n      }\r\n      if (link.href !== cssUrl) {\r\n        // Save the selected skin in session storage to survive over page reloads\r\n        if (this.isInRole(\"test\") && !this.isInRole(\"pro\")) {\r\n          window.sessionStorage.setItem(SessionService.SKIN_SESSION_STORAGE, cssUrl);\r\n        }\r\n        link.href = cssUrl;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Resolves current css cdn url with following priority:\r\n   * 1. Url (https://test-yritys.palkkaus.fi/embedded.html?skin=emu#/)\r\n   * 2. Token (Token.parsePayload(token))\r\n   * @returns cdn url to css\r\n   */\r\n  public resolveCss(): string {\r\n    if (this.isInRole(\"test\")) {\r\n      const urlParams = new URLSearchParams(window.location.search);\r\n      if (urlParams.has(\"skin\")) {\r\n        return `https://cdn.salaxy.com/skins/${urlParams.get(\"skin\")}.css`;\r\n      }\r\n      if (urlParams.has(\"skin-dev\")) {\r\n        // skins with dynamic compile\r\n        return `/dev-skins/${urlParams.get(\"skin-dev\")}.css`;\r\n      }\r\n    }\r\n    const token = this.ajax.getCurrentToken();\r\n    return (this.isInRole(\"test\") && !this.isInRole(\"pro\")) ?\r\n      (window.sessionStorage.getItem(SessionService.SKIN_SESSION_STORAGE) ||\r\n        Token.parsePayload(token).account_partner_css)\r\n      :\r\n      Token.parsePayload(token).account_partner_css;\r\n  }\r\n\r\n  /**\r\n   * Parses name of current skin from cdn url\r\n   * @returns name of current skin\r\n   */\r\n  public getCurrentCss(): string {\r\n    const cssUrl = (document.getElementById(\"salaxyMainCss\") as HTMLLinkElement)?.href ||\r\n    (document.getElementById(\"salaxyForcedCss\") as HTMLLinkElement)?.href;\r\n    return cssUrl?.substring(cssUrl?.lastIndexOf(\"/\") + 1)?.replace(/\\.[^/.]+$/, \"\");\r\n  }\r\n\r\n  /**\r\n   * Get report lang\r\n   * @param workerId optional workerId to get worker\r\n   * @returns report lang\r\n   */\r\n  public getReportLang(workerId = null): Promise<Language> {\r\n    let lang = (this.session?.currentAccount as any)?.language ?? Language.Fi;\r\n    lang = lang === Language.Default ? Language.Fi : lang;\r\n    if (!workerId) {\r\n      return Promise.resolve(lang);\r\n    }\r\n\r\n    // Check if workerId already exists in workerLangs\r\n    if (this.workerLangs[workerId]) {\r\n      return Promise.resolve(this.workerLangs[workerId]);\r\n    }\r\n    // Get worker with id (io)\r\n    return this.workers.getSingle(workerId).then((worker) => {\r\n      const workerLang = worker?.language ?? lang;\r\n      this.workerLangs[workerId] = workerLang === Language.Default ? lang : workerLang;\r\n      return this.workerLangs[workerId];\r\n    });\r\n  }\r\n\r\n  // TODO: This method should return an array of channels\r\n  /** Returns the owned payment channel for the current account. */\r\n  public getOwnedPaymentChannel(): PaymentChannel {\r\n\r\n    const channelAccounts = {\r\n      FI03POYA0003689675: PaymentChannel.AccountorGo, // Accountor\r\n      FI15POYA0008369224: PaymentChannel.FinagoSolo, // FinagoSolo\r\n      FI06POYT0009439335: PaymentChannel.Kevytyrittaja, // Kevytyrittaja\r\n      FI14POYA0028382282: PaymentChannel.Askelma, // Askelma\r\n      FI33POYB0024403824: PaymentChannel.Briox, // Briox\r\n      FI42POYT0025991058: PaymentChannel.Lemonaid, // LemonTree\r\n      FI71POYL0029361387: PaymentChannel.Laskupiste, // Laskupiste\r\n      FI43POY10010435606: PaymentChannel.PasseliMerit, // PasseliMerit\r\n      FI79POYA0034612101: PaymentChannel.Odoo, // Odoo\r\n      FI11POYE0009680831: PaymentChannel.Ecom, // Ecom\r\n      ... (Configs.current?.isTestData === true ? { FI88POYP0010378082: PaymentChannel.Kompassi } : { FI15POYY0010378082: PaymentChannel.Kompassi }), // Kompassi\r\n      FI23POY10006460809: PaymentChannel.Domus, // Tietoaika\r\n      FI24POYH0021937564: PaymentChannel.Holvi, // Holvi\r\n      FI88POYT0025514542: PaymentChannel.TalenomOnline, // Talenom\r\n      FI53POYS0025543933: PaymentChannel.PalkkausWS // SPL\r\n    };\r\n    if (this.session && this.session.currentAccount) {\r\n      return channelAccounts[this.session.currentAccount.id] || null;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Does a \"soft refresh\" of the AngularJS user interface by setting isLoading flag to\r\n   * true and then false after digest loop has run. Layouts should implement this in a way\r\n   * that all views are destroyed and then recreated.\r\n   */\r\n  public refreshUi() {\r\n    this.isLoading = true;\r\n    this.$timeout(() => {\r\n      this.isLoading = false;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the language of the session for the given language.\r\n   * Also loads the dictionary for the language if not already loaded.\r\n   * @param lang Language to set.\r\n   */\r\n  public setLanguage(lang: Language) {\r\n    if (!lang || lang === Language.Default) {\r\n      lang = Language.Fi;\r\n    }\r\n    this.isLoading = true;\r\n    Translations.loadLanguage(lang)\r\n      .then(() => {\r\n        Translations.setLanguage(lang as \"fi\" | \"en\" | \"sv\");\r\n        // TODO: This is unnecessary if the language is already loaded (Translations.loadedLanguages)\r\n        Translations.instance.setTerms(this.session?.settings?.partner?.serviceModel?.site?.texts);\r\n        // Override texts use by the components (not the entire culture) in the AngularJS locales\r\n        this.$locale.DATETIME_FORMATS.MONTH = Arrays.getRange(1, 12).map((x) => Translations.get(`SALAXY.ENUM.CalendarMonth.month${x}.label`));\r\n        this.$locale.DATETIME_FORMATS.SHORTDAY = [Translations.get(`SALAXY.ENUM.Weekday.day7.short`), ...Arrays.getRange(1, 6).map((x) => Translations.get(`SALAXY.ENUM.Weekday.day${x}.short`))];\r\n        this.refreshUi();\r\n      });\r\n  }\r\n  /** Parses origin url from $location*/\r\n  public getOrigin(): string {\r\n    let url = this.$location.absUrl();\r\n    // If not in root remove $location.path from $location.absUrl\r\n    if(this.$location.path() != \"/\") {\r\n      url = url.replace(this.$location.path(), \"\");\r\n    }\r\n    // If last character of url is /, remove\r\n    if(url.charAt(url.length - 1) == \"/\") {\r\n      url = url.slice(0, -1);\r\n    }\r\n    // If last character of url is #, remove\r\n    if (url.charAt(url.length - 1) == \"#\") {\r\n      url = url.slice(0, -1);\r\n    }\r\n    // Split url by / and if splits contains .html or .aspx remove it\r\n    const splits = url.split(\"/\");\r\n    if(splits[splits.length - 1].toLowerCase().includes(\".html\") || splits[splits.length - 1].toLowerCase().includes(\".aspx\")) {\r\n      url = url.replace(splits[splits.length - 1], \"\");\r\n    }\r\n    // if last char is not /, add it\r\n    if (url.charAt(url.length - 1) != \"/\") {\r\n      url = url + \"/\";\r\n    }\r\n\r\n    return url;\r\n  }\r\n\r\n  /**\r\n   * Parsers given roles from the access token.\r\n   * Returns the first found role from the list in order.\r\n   * @param roles Comma separated list of roles or array of roles.\r\n   */\r\n  private parseRoleFromAccessToken(roles: string | string[]): string {\r\n    if (!roles) {\r\n      return null;\r\n    }\r\n    const roleList = Arrays.assureArray(roles);\r\n    if (!roles.length) {\r\n      return null;\r\n    }\r\n\r\n    const token = this.ajax.getCurrentToken();\r\n    if (!token) {\r\n      return null;\r\n    }\r\n    const parsedToken = Token.parsePayload(token);\r\n    const scopes = (parsedToken.scope ?? \"\").split(\" \");\r\n    for (const role of roleList) {\r\n      switch (role) {\r\n        case \"pro\":\r\n          if (scopes.indexOf(\"pro:on_behalf_of\") > -1) {\r\n            return role;\r\n          }\r\n          break;\r\n        case \"admin\":\r\n          if (scopes.indexOf(\"admin:on_behalf_of\") > -1) {\r\n            return role;\r\n          }\r\n          break;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private notify(): void {\r\n    this.$rootScope.$emit(\"session-service-event\");\r\n  }\r\n\r\n  private notifyAuthenticatedSession() {\r\n    this.$rootScope.$emit(\"session-auth-session-event\");\r\n  }\r\n\r\n  /**\r\n   * Sends the browser to standard Sign-in page on Salaxy API server.\r\n   * @param redirectUrl The URL where the user is taken after a successfull login.\r\n   * @param role Optional role (household, worker or company) for the situations where it is known - mainly for new users.\r\n   * @param partnerSite The partner site is passed as client_id to the sign-in process.\r\n   * @param mode Salaxy login mode: \"sign_in\" or \"sign_up\".\r\n   * @param urlPostfix Additional string that is added to tha URL.\r\n   * Used in adding other parameters to the URL, e.g. \"&salaxy_language=en\"\r\n   */\r\n  private authorize(\r\n    redirectUrl: string = null,\r\n    role: string = null,\r\n    partnerSite: string = null,\r\n    mode: OAuthSalaxyAuthorizeMode = null,\r\n    urlPostfix: string = null,\r\n  ): void {\r\n    const config = Configs.current;\r\n    const partner = partnerSite || this.partnerSite || config?.partnerSite || \"unknown\";\r\n\r\n    if ((urlPostfix || \"\").indexOf(\"salaxy_skin\") === -1) {\r\n      const skin = this.getCurrentCss();\r\n      if (skin) {\r\n        urlPostfix = `${urlPostfix}&salaxy_skin=${skin}`;\r\n      }\r\n    }\r\n    const url = this.sessionApi.getSignInAddress(redirectUrl, role, partner, mode, urlPostfix);\r\n    this.$window.location.href = url;\r\n  }\r\n\r\n  private readTokenFromUrl(key: string, path: string): string {\r\n    // use regex...\r\n    const start = path.toLowerCase().indexOf(key);\r\n    if (start >= 0) {\r\n      const end = path.indexOf(\"&\", start);\r\n      return end >= 0\r\n        ? path.substring(start + key.length, end)\r\n        : path.substring(start + key.length);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private checkSessionFromUrl() {\r\n    const url = this.$location.url();\r\n    const token = this.readTokenFromUrl(\"access_token=\", url);\r\n    if (token) {\r\n      this.ajax.setCurrentToken(token);\r\n      const removeTokensFromPath = ((tt: string[], p: string) => {\r\n        for (const t of tt) {\r\n          const rg = new RegExp(`\\\\b${t}\\\\=[^&]+&?`);\r\n          p = p.replace(rg, \"\");\r\n        }\r\n        return p;\r\n      });\r\n      const cleanPath = (path: string) => {\r\n        // remove trailing & and ?\r\n        path = path.replace(/[?&]$/, \"\").trim();\r\n        // remove trailing slash if not following hash, cannot use backward looking regex, not supported in Safari\r\n        if (path.endsWith(\"/\") && !path.endsWith(\"#/\")) {\r\n          path = path.replace(/\\/$/, \"\").trim();\r\n        }\r\n        return path;\r\n      };\r\n\r\n      this.$rootScope.$evalAsync(() => {\r\n        this.$location\r\n          .path(cleanPath(removeTokensFromPath([\"access_token\", \"token_type\", \"state\", \"expires_in\", \"scope\"], this.$location.path())))\r\n          .search(\"access_token\", null)\r\n          .search(\"token_type\", null)\r\n          .search(\"state\", null)\r\n          .search(\"expires_in\", null)\r\n          .search(\"scope\", null);\r\n      });\r\n      return this.checkSession();\r\n    } else {\r\n      const error = this.readTokenFromUrl(\"error=\", url);\r\n      if (error) {\r\n        const errorDescription =\r\n          this.readTokenFromUrl(\"error_description=\", url) || \"\";\r\n        const errorUri = this.readTokenFromUrl(\"error_uri=\", url) || \"\";\r\n        const state = this.readTokenFromUrl(\"state=\", url) || \"\";\r\n        this.signInError = decodeURIComponent(error);\r\n        this.signInErrorDescription = decodeURIComponent(errorDescription.replace(/\\+/g, \"%20\"));\r\n\r\n        this.$rootScope.$evalAsync(() => {\r\n          this.$location\r\n            .path(this.signInErrorUrl || \"/\")\r\n            .search(\"error\", decodeURIComponent(error.replace(/\\+/g, \"%20\")))\r\n            .search(\"error_description\", decodeURIComponent(errorDescription.replace(/\\+/g, \"%20\")))\r\n            .search(\"error_uri\", decodeURIComponent(errorUri.replace(/\\+/g, \"%20\")))\r\n            .search(\"state\", decodeURIComponent(state.replace(/\\+/g, \"%20\")));\r\n        });\r\n        return this.checkSession();\r\n      }\r\n    }\r\n    return Promise.resolve(null);\r\n  }\r\n\r\n  private subscribeToLocationChange() {\r\n    this.$rootScope.$on(\"$locationChangeStart\", () => {\r\n      this.checkSessionFromUrl().then(() => {\r\n        if (!this.isSessionChecked && !this.isSessionChecking) {\r\n          this.checkSession();\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Temporary fix to replace old skin paths \"ng1/css/something.css\" with the new monorepo\r\n   * style \"/skins/css/something.css\" until the skin paths are fixed at the source.\r\n   */\r\n  private convertSkinPath(path: string): string {\r\n    // Check if the path is null or already converted\r\n    if (!path || path.indexOf(\"skins/css/\") >= 0) {\r\n      return path;\r\n    }\r\n    // Convert to new format\r\n    return path ? \"https://cdn.salaxy.com/skins/\" + path.substr(path.lastIndexOf(\"/\") + 1) : path;\r\n  }\r\n\r\n  private setLanguageForSession(): void {\r\n    // Possibility to override the language in query string\r\n    const params = new URLSearchParams(window.location.search);\r\n    if (params.has(\"lang\")) {\r\n      const lang = params.get(\"lang\")?.toLowerCase() as Language;\r\n      if (lang) {\r\n        this.setLanguage(lang);\r\n        return;\r\n      }\r\n    }\r\n    if (this.session?.currentAccount && this.session.currentAccount.language) {\r\n      this.setLanguage(this.session.currentAccount.language);\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountSettings, Ajax, CompanyAccountSettings, LegalEntityType } from \"@salaxy/core\";\r\nimport { ReportOptions } from \"@salaxy/reports\";\r\nimport { SessionService } from \"./SessionService\";\r\nimport { EditDialogResult, UiHelpers } from \"./ui\";\r\n\r\n/**\r\n * Provides singleton for the full editable settings object:\r\n * Mainly for editing, but may also be used by other parts that require access to settings.\r\n * This implementation is for Company employers. There may be a specialized Household employers and/or Worker, Pro version later.\r\n */\r\nexport class SettingsService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$rootScope\", \"SessionService\", \"AccountSettings\", \"UiHelpers\", \"AjaxNg1\", \"$timeout\"];\r\n\r\n  /**\r\n   * The current settings object or null if the object is still being loaded.\r\n   * The loading starts as soon as the settings service is loaded in the first controller.\r\n   */\r\n  public current: CompanyAccountSettings;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private _reportOptionsLoading = false;\r\n\r\n  constructor($rootScope: angular.IRootScopeService, private sessionService: SessionService, private accountSettings: AccountSettings, private uiHelpers: UiHelpers, private ajax: Ajax, private $timeout: angular.ITimeoutService) {\r\n    this.refresh();\r\n\r\n    sessionService.subscribe($rootScope, () => {\r\n      this.refresh();\r\n    });\r\n  }\r\n\r\n  /** Saves the session and does the refresh, but not a complete sessionService.checkSession() as in default save().  */\r\n  public saveWithoutSessionCheck(): Promise<CompanyAccountSettings> {\r\n    return this.accountSettings.save(this.current).then((result) => {\r\n      this.current = result;\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /** Refreshes the current settings from the server. */\r\n  public refresh() {\r\n    if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n      const owner = this.sessionService.session.currentAccount.owner;\r\n      if (this.current?.owner != owner){\r\n        this.reportOptions = null;\r\n        this.current = null;\r\n        this._reportOptionsLoading = false;\r\n      }\r\n      return this.accountSettings.get().then((result) => {\r\n        this.current = result;\r\n        return this.current;\r\n      });\r\n    } else {\r\n      this.reportOptions = null;\r\n      this.current = null;\r\n      this._reportOptionsLoading = false;\r\n    }\r\n  }\r\n\r\n  /** Saves the current settings back to storage. */\r\n  public save(): Promise<CompanyAccountSettings> {\r\n    return this.accountSettings.save(this.current).then((result) => {\r\n      this.current = result;\r\n      return this.sessionService.checkSession().then(() => {\r\n        return result;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Sets the eInvoice address using a dialog */\r\n  public selectEInvoiceAddress(address: { eInvoiceReceiver?: string, eInvoiceIntermediator?: string }): Promise<EditDialogResult<any>> {\r\n    const item = {\r\n      receiver: address.eInvoiceReceiver,\r\n      intermediator: address.eInvoiceIntermediator,\r\n    };\r\n    const logic = {\r\n      title: \"Hae osoite Y-tunnuksella\",\r\n      officialId: this.sessionService.session.currentAccount.identity.officialId,\r\n      isLoading: false,\r\n      addresses: [],\r\n      isSelected: (current, item) => {\r\n        return current.receiver === item.receiver;\r\n      },\r\n      isAnySelected: (current) => {\r\n        return logic.addresses.some((x) => logic.isSelected(current, x));\r\n      },\r\n      setCurrent: (current, item) => {\r\n        current.receiver = item.receiver;\r\n        current.intermediator = item.intermediator;\r\n      },\r\n      search: () => {\r\n        logic.isLoading = true;\r\n        const path = `/payments/einvoice/receiver?officialId=${encodeURIComponent(logic.officialId)}`;\r\n        this.ajax.getJSON(path).then((items) => {\r\n          logic.addresses = items;\r\n          logic.isLoading = false;\r\n        });\r\n      },\r\n    };\r\n    logic.search();\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/modals/account/EInvoiceAddressList.html\", item, logic).then((result) => {\r\n\r\n      if (result.action === \"ok\") {\r\n        address.eInvoiceReceiver = result.item.receiver;\r\n        address.eInvoiceIntermediator = result.item.intermediator;\r\n      } else if (result.action === \"reset\") {\r\n        address.eInvoiceReceiver = null;\r\n        address.eInvoiceIntermediator = null;\r\n      }\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets ReportOptions\r\n   * @returns returns tempalte ReportOptions\r\n   */\r\n  public getReportOptions(): Promise<ReportOptions> {\r\n    if (this.reportOptions) {\r\n      return Promise.resolve(this.reportOptions);\r\n    }\r\n\r\n    if (!this.sessionService?.session?.currentAccount ||\r\n      this.sessionService.session.currentAccount.avatar.entityType !== LegalEntityType.Company) {\r\n      return Promise.resolve({});\r\n    }\r\n    if (!this._reportOptionsLoading) {\r\n      this._reportOptionsLoading = true;\r\n      let reportOptions: any = {};\r\n      const settings = this.current;\r\n      const reporting = settings?.reporting;\r\n      if (reporting?.layoutTemplateId) {\r\n        this.ajax.getJSON(`${this.ajax.serverAddress}/v03/api/settings/layout/${reporting.layoutTemplateId}`).then((template) => {\r\n          if (template) {\r\n            reportOptions = template;\r\n            if (reporting.logo && reporting.layoutTemplateId.toLowerCase() === \"logo-report-options@FI53POYS0025543933\".toLowerCase()) {\r\n              if (!reporting.logo.trim().startsWith(\"<\")) {\r\n                this.ajax.getJSON(`${this.ajax.serverAddress}/v03/api/settings/logo/${reporting.logo}`).then((logoMarkup) => {\r\n                  if (logoMarkup != null) {\r\n                    reportOptions.logo = logoMarkup;\r\n                  } else {\r\n                    reportOptions.logo = reporting.logo;\r\n                  }\r\n                  this.reportOptions = reportOptions;\r\n                });\r\n              } else {\r\n                reportOptions.logo = reporting.logo;\r\n                this.reportOptions = reportOptions;\r\n              }\r\n            } else {\r\n              this.reportOptions = reportOptions;\r\n            }\r\n          } else {\r\n            this.reportOptions = reportOptions;\r\n          }\r\n        });\r\n      } else {\r\n        this.reportOptions = reportOptions;\r\n      }\r\n    }\r\n\r\n    const getOptions = (): Promise<ReportOptions> => {\r\n      return new Promise((resolve) => {\r\n        const check = () => {\r\n          if (this.reportOptions) {\r\n            return resolve(this.reportOptions);\r\n          }\r\n          this.$timeout(() => check(), 50);\r\n        };\r\n\r\n        check();\r\n      });\r\n    };\r\n    return getOptions();\r\n  }\r\n}\r\n\r\n","import angular from \"angular\";\r\n\r\nimport { OnboardingLogic } from \"@salaxy/core\";\r\n\r\n/**\r\n * Defines a supported signature method.\r\n */\r\nexport class SignatureMethod {\r\n    /** Title for the signing method. */\r\n    public title?: string;\r\n    /** Name for the signing method. */\r\n    public name: string;\r\n    /** Id for the signing method. */\r\n    public value: string;\r\n    /** Image url for the signing method. */\r\n    public img: string;\r\n    /** Boolean to indicate that the method is popular and should be shown among first methods. */\r\n    public isPopular?: boolean;\r\n}\r\n\r\n/**\r\n * Handles Digital Signature scenarios to Onnistuu.fi-service.\r\n */\r\nexport class SignatureService {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$rootScope\"];\r\n\r\n    private tupasMethods: SignatureMethod[] = null;\r\n\r\n    private teliaMethods: SignatureMethod[] = null;\r\n\r\n    /**\r\n     * Creates a new instance of SignatureService\r\n     * @param $rootScope - Angular root scope. Used for event routing\r\n     */\r\n    constructor(\r\n        private $rootScope: angular.IRootScopeService,\r\n    ) {\r\n    }\r\n\r\n    /**\r\n     * Gets a list of available signature methods. Use img-property to show.\r\n     * @param methodGroup - Method group \"telia\" for Telia Tunnistus and \"tupas\" for Visma Sign. Default is \"tupas\".\r\n     */\r\n    public getMethods(methodGroup: \"tupas\" | \"telia\" = \"tupas\"): SignatureMethod[] {\r\n        methodGroup ??= \"tupas\";\r\n        switch (methodGroup) {\r\n          case \"tupas\":\r\n            this.tupasMethods ??= OnboardingLogic.getTupasMethods().map((x) => (\r\n              {\r\n                  id: x.id,\r\n                  title: x.title,\r\n                  name: x.id.substr(6), // for backward compatibility\r\n                  value: x.id,\r\n                  img: x.img,\r\n                  isPopular: x.isPopular,\r\n              }));\r\n            return this.tupasMethods;\r\n          case \"telia\":\r\n            this.teliaMethods ??= OnboardingLogic.getTeliaMethods().map((x) => (\r\n              {\r\n                  id: x.id,\r\n                  title: x.title,\r\n                  name: x.title,\r\n                  value: x.id,\r\n                  img: x.img,\r\n                  isPopular: x.isPopular,\r\n              }));\r\n            return this.teliaMethods;\r\n          default:\r\n            return [];\r\n        }\r\n    }\r\n}\r\n","import { UiTranslatorDictionaryItem } from \"./ui/model/UiTranslatorDictionaryItem\";\r\n\r\n/**\r\n * Stores the state of editable i18n dictionary and related translation methods.\r\n */\r\nexport class UiTranslatorService {\r\n  private dictionary: Array<UiTranslatorDictionaryItem> = [];\r\n  /**\r\n   * Get dictionary\r\n   * @returns UiTranslatorDictionaryItem array\r\n   */\r\n  public getDictionary() {\r\n    return this.dictionary;\r\n  }\r\n\r\n  /**\r\n   * Adds item to dictionary\r\n   * @param item item to be added to dictionary\r\n   */\r\n  public addToDictionary(item: UiTranslatorDictionaryItem) {\r\n    this.dictionary.push(item);\r\n  }\r\n}","import { Numeric, Translations, Files } from \"@salaxy/core\";\r\n\r\nimport { AjaxNg1 } from \"../ajax\";\r\n\r\n/** Abstracts the Upload process to a helper class instead of using upload directly. */\r\nexport class UploadService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Upload\", \"AjaxNg1\", \"$q\", \"Files\"];\r\n\r\n  constructor(\r\n    private angularUpload: angular.angularFileUpload.IUploadService,\r\n    private ajax: AjaxNg1,\r\n    private $q: angular.IQService,\r\n\r\n    private files: Files\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Standard upload method that uploads data as form POST (multipart/form-data)\r\n   * @param url Service URL that receives the upload.\r\n   * @param data The form data (including the files) that is sent to the server.\r\n   * @param notify Optional function that is called for upload notifications: Progress and error.\r\n   * @returns Message from server as defined by IReturnType.\r\n   */\r\n  public upload<IReturnType>(url: string, data: any, notify?: (\r\n    /** Upload progress is a number between 0-100 */\r\n    progress: number,\r\n    /** In the case of error, the english error message is returned here and progress is null. */\r\n    error?: string,\r\n  ) => any): angular.IPromise<IReturnType> {\r\n    return this.$q((resolve, reject) => {\r\n      this.angularUpload.upload<IReturnType>({\r\n        method: \"POST\",\r\n        url,\r\n        data,\r\n        headers: { Authorization: \"Bearer \" + this.ajax.getCurrentToken() },\r\n      }).then((response) => {\r\n        resolve(response.data);\r\n      }, (response) => {\r\n        response = response || {};\r\n        const error = (response.status || \"ERROR\") + \": \" + (response.data || \"No data\");\r\n        if (notify){\r\n          notify(null, error);\r\n        }\r\n        reject(error);\r\n      }, (evt) => {\r\n        const progress = Math.min(100, Numeric.round(100.0 * evt.loaded / evt.total, 0));\r\n        if (notify) {\r\n          notify(progress);\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a the URL (with token) for a stream of given uploaded file.\r\n   * @param fileId Identifier of the file.\r\n   */\r\n  public getFileUrl(fileId: string) {\r\n    return `${this.files.getContentUrl(fileId)}?access_token=${this.ajax.getCurrentToken()}`;\r\n  }\r\n\r\n  /**\r\n   * Gets a preview URL (with token) for a given uploaded file.\r\n   * @param fileId Identifier of the file.\r\n   */\r\n  public getPreviewUrl(fileId: string) {\r\n    return `${this.files.getPreviewUrl(fileId)}?access_token=${this.ajax.getCurrentToken()}`;\r\n  }\r\n\r\n  /**\r\n   * Gets a language versined error description ng-file-upload invalidFile errors (client-side before actual upload).\r\n   * @param invalidFile Invalid file of ng-file-upload component.\r\n   * @param invalidFile.$error Error key, e.g. 'pattern', minSize' or  'maxSize'\r\n   * @param invalidFile.$errorParam Additional error param, e.g. '50KB' or '10MB' for file sizes.\r\n   */\r\n  public getInvalidFileDescription(invalidFile: {\r\n    $error: string,\r\n    $errorParam: string,\r\n  }): string {\r\n    if (!invalidFile || !invalidFile.$error) {\r\n      return null;\r\n    }\r\n    // TODO: Error messages should be moved to the right path in dictionary.\r\n    switch (invalidFile.$error) {\r\n      case \"pattern\":\r\n        return Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.uploadErrorFormat\");\r\n      case \"minSize\":\r\n        // $errorParam contains the size, e.g '50KB' if that is needed.\r\n        return Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.uploadErrorSmall\");\r\n      case \"maxSize\":\r\n        // $errorParam contains the size, e.g '10MB' if that is needed.\r\n        return Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.uploadErrorLarge\");\r\n      default:\r\n        return Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.uploadError\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets a font-awesome icon for supported file types.\r\n   * @param fileName The extension of the file name is used for determining the icon.\r\n   */\r\n  public getFileIcon(fileName: string): string {\r\n    if (!fileName || fileName.indexOf(\".\") < 0) {\r\n      return \"fa-exclamation-triangle\";\r\n    }\r\n    const extension = fileName.substring(fileName.lastIndexOf(\".\") + 1);\r\n    switch (extension) {\r\n      case \"txt\":\r\n      case \"text\":\r\n      case \"csv\":\r\n      case \"cs\":  // If these are really used at some point, you probalby want to reconsider theses\r\n      case \"css\":\r\n      case \"htm\":\r\n      case \"html\":\r\n      case \"js\":\r\n      case \"json\":\r\n      case \"xml\":\r\n        return \"fa-file-text-o\";\r\n      case \"bmp\":\r\n      case \"gif\":\r\n      case \"jpg\":\r\n      case \"jpeg\":\r\n      case \"png\":\r\n      case \"svg\":\r\n      case \"tif\":\r\n      case \"tiff\":\r\n        return \"fa-file-image-o\";\r\n      case \"pdf\":\r\n        return \"fa-file-pdf-o\";\r\n      case \"xls\":\r\n      case \"xlsx\":\r\n        return \"fa-file-excel-o\";\r\n      case \"doc\":\r\n      case \"docx\":\r\n        return \"fa-file-word-o\";\r\n      case \"zip\":\r\n        return \"fa-file-archive-o\";\r\n      case \"ppt\":\r\n      case \"pptx\":\r\n        return \"fa-file-powerpoint-o\";\r\n      default:\r\n        return \"fa-file-o\";\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiItemType, StorageLogic, Usecase, UsecaseInSettings, UsecaseStatus, Usecases, UsecaseListItem } from \"@salaxy/core\";\r\n\r\nimport { SessionUsecase } from \"./model\";\r\nimport { SessionService } from \"./SessionService\";\r\nimport { UsecaseApiCrudObject } from \"./ui/model\";\r\n\r\n/** Provides caching for usecases and resolves them to business objects. */\r\nexport class UsecasesService {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Usecases\", \"SessionService\", \"$sce\"];\r\n\r\n  constructor(private usecases: Usecases, private sessionService: SessionService, private $sce: angular.ISCEService) {\r\n  }\r\n\r\n  /**\r\n   * Gets active usecases that are shown in listings (selection of usecase)\r\n   * including type-specific default usecases (applied if no other usecase is defined).\r\n   */\r\n  public getActiveUsecases(type: ApiItemType = null, defaultOnly = false): UsecaseInSettings[] {\r\n    const listInSettings: UsecaseInSettings[] = this.sessionService.session?.settings?.usecases || [];\r\n    let filteredList = listInSettings.filter((x) => !type || type == x.itemType);\r\n    if (defaultOnly) {\r\n      filteredList = filteredList.filter((x) => x.status === UsecaseStatus.Default);\r\n    }\r\n    return filteredList;\r\n  }\r\n\r\n  /**\r\n   * Gets the active items as list items. The list of all usecases is cached.\r\n   * @param type Type of items to fetch.\r\n   * TODO: The method currently supports max 50 active usecases (of all types).\r\n   */\r\n  public getActiveUsecaseListItems(type: ApiItemType = null): Promise<UsecaseListItem[]> {\r\n    const filter = (x: UsecaseListItem) => (!type || type == x.entityType) && (x.status == UsecaseStatus.Active || x.status == UsecaseStatus.Default);\r\n    if (this.cachedActiveListItems) {\r\n      return Promise.resolve(this.cachedActiveListItems.filter(filter));\r\n    }\r\n    return this.usecases.getOData({ $filter: `status eq 'active' or status eq 'default'` }).then((result) => {\r\n      this.cachedActiveListItems = result.items;\r\n      return this.cachedActiveListItems.filter(filter);\r\n    });\r\n  }\r\n\r\n  private cachedActiveListItems: UsecaseListItem[];\r\n\r\n  /**\r\n   * Gets the activity type of usecase from the settings.\r\n   * @param uri Usecase URI\r\n   * @returns Information on whether the usecase is active or not - or default usecase (also active).\r\n   */\r\n  public getActive(uri: string): UsecaseStatus {\r\n    if (!uri) {\r\n      return UsecaseStatus.Inactive;\r\n    }\r\n    if (uri.startsWith(\"http\")) {\r\n      uri = new URL(uri).pathname;\r\n    }\r\n    const item = this.sessionService.session?.settings?.usecases?.find((x) => x.uri == uri);\r\n    if (!item || item.status === UsecaseStatus.Undefined ) {\r\n      return UsecaseStatus.Inactive;\r\n    }\r\n    return item.status;\r\n  }\r\n\r\n  /**\r\n   * Gets the order  of usecase from the settings.\r\n   * @param uri Usecase URI\r\n   * @returns Order number for the usecase, 0 if not set.\r\n   */\r\n   public getOrder(uri: string): number {\r\n    if (!uri) {\r\n      return 0;\r\n    }\r\n    if (uri.startsWith(\"http\")) {\r\n      uri = new URL(uri).pathname;\r\n    }\r\n    const item = this.sessionService.session?.settings?.usecases?.find((x) => x.uri == uri);\r\n    return item?.order ?? 0;\r\n  }\r\n\r\n  /**\r\n   * Assures that the usecase model is fetched and data model is initialized according to usecase.\r\n   * @param type Type of business object\r\n   * @param item Business object to initialize.\r\n   * @param defaultUri Usecase uri if passed by the calling component (e.g. in URL or component attribute).\r\n   * @returns The usecase with session / role related data or null if none is set.\r\n   */\r\n  public assureUsecase(type: ApiItemType, item: UsecaseApiCrudObject, defaultUri: string): Promise<SessionUsecase> {\r\n    if (!item) {\r\n      return Promise.resolve(null);\r\n    }\r\n    return this.getUsecaseForObject(type, item, defaultUri).then((usecase) => {\r\n      // Prepare the usecase data model for data binding: Should either be in Core or in data binding logic (sxy-forms).\r\n      item.usecase = item.usecase || {};\r\n      item.usecase.data = item.usecase.data || {};\r\n      if (!usecase) {\r\n        return null;\r\n      }\r\n      if (usecase) {\r\n        item.usecase.uri = usecase.uri;\r\n        item.usecase.label = usecase.label;\r\n        item.usecase.description = usecase.description;\r\n      }\r\n      return usecase;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a usecase definition based on business object (that has usecase data item).\r\n   * @param type Business object type\r\n   * @param item The business objec to evaluate.\r\n   * @param defaultUri Usecase uri if passed by the calling component (e.g. in URL or component attribute).\r\n   * @returns The usecase with session / role related data or null if none is set.\r\n   */\r\n  public getUsecaseForObject(type: ApiItemType, item: UsecaseApiCrudObject, defaultUri: string): Promise<SessionUsecase> {\r\n    if (!item) {\r\n      return Promise.resolve(null);\r\n    }\r\n    if (type == ApiItemType.Calculation) {\r\n      // HACK: Handle these exceptions on product level.\r\n      const considerEmpty = [\r\n        \"palkkaus.fi/usecases/payroll-service/pro-calc\",\r\n        \"palkkaus.fi/usecases/payroll-service/calc\",\r\n      ];\r\n      if (item?.usecase?.uri && !considerEmpty.find((x) => item.usecase.uri == x)) {\r\n        return this.getUsecase(item.usecase.uri);\r\n      }\r\n    }\r\n    else if (item?.usecase?.uri) {\r\n      return this.getUsecase(item.usecase.uri);\r\n    }\r\n    defaultUri = defaultUri || this.getActiveUsecases(type, true)[0]?.uri;\r\n    return defaultUri ? this.getUsecase(defaultUri) : Promise.resolve(null);\r\n  }\r\n\r\n  /** Clears the usecase cache: Will be fetched from the server in next getUsecase(). */\r\n  public clearCache(): void {\r\n    this.cachedUsecases = {};\r\n  }\r\n\r\n  /**\r\n   * Adds abilitity to set the contents of a usecase in cache.\r\n   * This is used in dynamic preview in edit usecase scenarios.\r\n   * @param newVersion A version of the usecase that is set into usecases cache.\r\n   */\r\n  public setToCache(newVersion: Usecase): void {\r\n    const sessionUsecase = newVersion as SessionUsecase;\r\n    sessionUsecase.isLoaded = true;\r\n    sessionUsecase.exists = true;\r\n    if (sessionUsecase.views?.length && newVersion.uri) {\r\n      // Later, we may have some profiling logic here: Different UI for different roles etc.\r\n      sessionUsecase.defaultView = this.$sce.trustAsResourceUrl(this.usecases.getResourceUrl(newVersion.uri, \"html\"));\r\n    }\r\n    this.cachedUsecases[newVersion.uri] = newVersion;\r\n  }\r\n\r\n  /**\r\n   * Gets a usecase based on URI using the session cache.\r\n   * @param uri Uri of the usecase\r\n   * @returns The usecase, typically cached in session.\r\n   */\r\n  public getUsecase(uri: string): Promise<SessionUsecase> {\r\n    // Note that current implementation is not completely optimal: If several queries to one usecase uri\r\n    // are made before first query returns, several http calls are made.\r\n\r\n    uri = StorageLogic.getLocalUri(uri);\r\n    const usecasesInProduct = [\"/UsecaseDefinition/FI53POYS0025543933/costcenter-percentages\"];\r\n    if (usecasesInProduct.indexOf(uri) >= 0) {\r\n      return Promise.resolve({\r\n        isLoaded: true,\r\n        exists: true,\r\n        uri: uri,\r\n      });\r\n    }\r\n    const usecase = this.cachedUsecases[uri];\r\n    if (usecase) {\r\n      if (usecase.exists) {\r\n        return Promise.resolve(usecase);\r\n      }\r\n      // Just a marker that the item has already been checked from server.\r\n      return Promise.resolve(null);\r\n    }\r\n    return this.usecases.getSingle(StorageLogic.getIdAtOwner(uri)).then((usecase: SessionUsecase) => {\r\n      if (usecase) {\r\n        this.setToCache(usecase);\r\n        return usecase;\r\n      } else {\r\n        this.cachedUsecases[uri] = {\r\n          isLoaded: true,\r\n          exists: false,\r\n          uri: uri,\r\n        };\r\n        return null;\r\n      }\r\n    });\r\n  }\r\n\r\n  private cachedUsecases: { [key: string]: SessionUsecase } = {};\r\n}","/**\r\n * Manages user-specific settings which are currently stored in the local storage (browser).\r\n * User settigns are mostly UI, such as default selections, filters, column orders, etc.\r\n * Later implementations may store the settings in the server do that they transfer from one browser to another\r\n * within the same user.\r\n */\r\nexport class UserSettingsService {\r\n\r\n  private settings: { [key: string]: any };\r\n\r\n  /**\r\n   * Returns an object with one property \"val\" that is bound to the given key.\r\n   * Used for easier data binding in AngularJS models.\r\n   * @param key Key for the property.\r\n   * @returns An object with one property \"val\" that is bound to the given key (getter and setter).\r\n   * @example\r\n   * <salaxy-input-boolean name=\"myInput\" ng-model=\"$ctrl.userSettings.ng1Binder('payroll.newVersion').val\" label=\"Uusi versio\"></salaxy-input>\r\n   */\r\n  public ng1Binder(key: string) {\r\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n    const that = this; // Cannot use lambda in getter/setter. Other warkarounds to preserve \"this\" would probably be more complex.\r\n    return {\r\n      /** Property the is bound to the given key. */\r\n      get val() {\r\n        return that.get(key);\r\n      },\r\n      set val(value: any) {\r\n        that.set(key, value);\r\n      }\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Gets a setting value from local storage\r\n   * @param key String key for the value\r\n   * @returns The value\r\n   */\r\n  public get<T>(key: string): T {\r\n    key = key.toLowerCase().trim();\r\n    return this.getAll()[key];\r\n  }\r\n\r\n  /**\r\n   * Sets a setting value to local sotrage\r\n   * @param key String key for the value\r\n   * @param value The value.\r\n   */\r\n  public set<T>(key: string, value: T): void {\r\n    key = key.toLowerCase().trim();\r\n    if (!key) {\r\n      throw new Error(\"Key cannot be empty\");\r\n    }\r\n    const all = this.getAll();\r\n    all[key] = value;\r\n    this.setAll(all);\r\n  }\r\n\r\n  private getAll(): { [key: string]: any } {\r\n    if (!this.settings) {\r\n      if (!localStorage[\"salaxy-user-settings\"]) {\r\n        localStorage[\"salaxy-user-settings\"] = JSON.stringify({});\r\n      }\r\n      this.settings = JSON.parse(localStorage[\"salaxy-user-settings\"]);\r\n    }\r\n    return this.settings;\r\n  }\r\n\r\n  private setAll(settings: { [key: string]: any }): void {\r\n    localStorage[\"salaxy-user-settings\"] = JSON.stringify(settings);\r\n    this.settings = settings;\r\n  }\r\n\r\n}","import { PartnerServices, VarmaPensionOrder } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"./SessionService\";\r\n\r\n/**\r\n * Varma pension service. Contains methods for getting order template, validating the order\r\n * and sending the order.\r\n */\r\nexport class VarmaPensionService {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"SessionService\", \"PartnerServices\"];\r\n\r\n    /** Current order  */\r\n    private current: VarmaPensionOrder & { owner?: string | null };\r\n\r\n    constructor(\r\n        private sessionService: SessionService,\r\n        private partnerServicesApi: PartnerServices,\r\n    ) {\r\n    }\r\n\r\n    /** Lazy loading of current pension order template */\r\n    public getCurrent(): VarmaPensionOrder {\r\n        const getEmptyOrder = () => ({\r\n            owner: null,\r\n            orderer: {\r\n                contact: {},\r\n            },\r\n            tyel: {},\r\n            yel: {},\r\n            validation: {},\r\n            });\r\n        if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n              const owner = this.sessionService.session.currentAccount.owner;\r\n              if (this.current?.owner != owner) {\r\n                  this.current = getEmptyOrder();\r\n                  this.current.owner = owner;\r\n                  // trigger loading\r\n                  this.partnerServicesApi.getNewVarmaPensionOrder().then((order) => {\r\n                    this.current = { ...order, owner };\r\n                  });\r\n              }\r\n        } else {\r\n            this.current = null;\r\n        }\r\n        return this.current ??= getEmptyOrder();\r\n    }\r\n\r\n    /**\r\n     * Sends order for processing.\r\n     */\r\n    public send(): Promise<VarmaPensionOrder> {\r\n        const owner = this.sessionService.session.currentAccount.owner;\r\n        return this.partnerServicesApi.sendVarmaPensionOrder(this.current).then((order) => {\r\n            this.current = order;\r\n            this.current.owner = owner;\r\n            // refresh products\r\n            return this.sessionService.checkSession().then ( () => {\r\n                return  this.current;\r\n            });\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Validates the order.\r\n     */\r\n    public validate(): Promise<VarmaPensionOrder> {\r\n      const owner = this.sessionService.session.currentAccount.owner;\r\n      return this.partnerServicesApi.validateVarmaPensionOrder(this.current).then((order) => {\r\n          this.current = order;\r\n          this.current.owner = owner;\r\n          return this.current;\r\n      });\r\n    }\r\n\r\n    /**\r\n     * Resets the current order.\r\n     */\r\n    public reset() {\r\n        this.current = null;\r\n    }\r\n}\r\n","import { ApiCrudObject, SessionUserCredential, WorkflowEvent } from \"@salaxy/core\";\r\n\r\nimport {CredentialService} from \"./CredentialService\";\r\nimport {SessionService} from \"./SessionService\";\r\n\r\nimport {ApiCrudObjectController} from \"../controllers/bases/ApiCrudObjectController\";\r\n\r\n/**\r\n * Service for workflow logic.\r\n * For implementation specific workflows you shoud extend this class\r\n * and inject the extended class as a WorkflowService.\r\n */\r\nexport class WorkflowService {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"SessionService\", \"CredentialService\"];\r\n\r\n   /**\r\n    * Creates a new instance of WorkflowService.\r\n    */\r\n    constructor(protected sessionService: SessionService, protected credentialService: CredentialService) { }\r\n\r\n  /**\r\n   * Returns credentials for the current account.\r\n   * Override this in the pro environment.\r\n   */\r\n  public get credentials(): SessionUserCredential[] {\r\n    return this.credentialService.list;\r\n  }\r\n\r\n  /**\r\n   * Returns the credential for current session.\r\n   * Override this in the pro environment.\r\n   */\r\n  public get self(): SessionUserCredential {\r\n    return this.sessionService.session.currentCredential;\r\n  }\r\n\r\n  /**\r\n   * Adds/updates the workflow event for the current item.\r\n   * @param apiCtrl API CRUD object controller for the item.\r\n   * @param wfEvent Workflow event to add/update.\r\n   * @returns Reloaded item.\r\n   */\r\n  public saveWorkflowEvent<TItem extends ApiCrudObject>(apiCtrl: ApiCrudObjectController<TItem, any>, wfEvent: WorkflowEvent): Promise<TItem> {\r\n    return apiCtrl.saveWorkflowEvent(wfEvent);\r\n  }\r\n\r\n  /**\r\n   * Deletes the given event or all events with given type.\r\n   * @param apiCtrl API CRUD object controller for the item.\r\n   * @param wfIdOrType Id or type of the workflow event.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public deleteWorkflowEvent<TItem extends ApiCrudObject>(apiCtrl: ApiCrudObjectController<TItem, any>, wfIdOrType: string): Promise<TItem> {\r\n    return apiCtrl.deleteWorkflowEvent(wfIdOrType);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Avatar, AvatarPictureType, SessionUserCredential, Translations } from \"@salaxy/core\";\r\n\r\nimport { CredentialService, GravatarHelpers, SessionService, UiHelpers, UploadService } from \"../../services\";\r\nimport { CrudControllerBase } from \"../bases/CrudControllerBase\";\r\n\r\n/** Credential controller for listing credentials and removing existing credentials. */\r\nexport class CredentialController extends CrudControllerBase<SessionUserCredential> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UploadService\", \"CredentialService\", \"SessionService\", \"$location\", \"$attrs\", \"UiHelpers\"];\r\n\r\n  /**\r\n   * Translated color options for input enum\r\n   */\r\n  public colorOptions: any = {\r\n    \"#7F2C2A\": Translations.get(\"SALAXY.NG1.CredentialsComponent.color.brown\"),\r\n    \"#91D214\": Translations.get(\"SALAXY.NG1.CredentialsComponent.color.lime\"),\r\n    \"#61703B\": Translations.get(\"SALAXY.NG1.CredentialsComponent.color.darkGreen\"),\r\n    \"#D10074\": Translations.get(\"SALAXY.NG1.CredentialsComponent.color.pink\"),\r\n  };\r\n\r\n  private originalAvatar: Avatar = null;\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    private uploadService: UploadService,\r\n    private credentialService: CredentialService,\r\n    private sessionService: SessionService,\r\n    $location: angular.ILocationService,\r\n    $attrs: angular.IAttributes,\r\n    uiHelpers: UiHelpers,\r\n  ) {\r\n    super(credentialService, $location, $attrs, uiHelpers);\r\n  }\r\n\r\n  /**\r\n   * Uploads avatar image file to the server.\r\n   * @param file - selected file\r\n   */\r\n  public uploadAvatarImage(file: any) {\r\n    if (!file) {\r\n      return;\r\n    }\r\n    this.uploadService.upload<SessionUserCredential>(this.credentialService.getAvatarUploadUrl(this.current.id), { file })\r\n      .then((resp) => {\r\n        this.current.avatar.url = resp.avatar.url;\r\n        this.current.avatar.pictureType = resp.avatar.pictureType;\r\n      });\r\n  }\r\n\r\n  /** Called when avatar changes */\r\n  public emailForAvatarChanged() {\r\n    if (!this.current || !this.current.avatar) {\r\n      return;\r\n    }\r\n    if (this.current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      this.current.avatar.url = GravatarHelpers.getGravatarUrl(this.current.email);\r\n    }\r\n  }\r\n  /** Called when avatar changes */\r\n  public typeForAvatarChanged() {\r\n    if (!this.current || !this.current.avatar) {\r\n      return;\r\n    }\r\n\r\n    if (this.current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      this.current.avatar.url = GravatarHelpers.getGravatarUrl(this.current.email);\r\n    } else {\r\n      if (GravatarHelpers.isGravatarUrl(this.current.avatar.url)) {\r\n        this.current.avatar.url = null;\r\n      }\r\n      if (this.current.avatar.pictureType === AvatarPictureType.Uploaded) {\r\n        if (!this.current.avatar.url && this.originalAvatar && this.originalAvatar.url) {\r\n          if (this.originalAvatar.pictureType === AvatarPictureType.Uploaded &&\r\n            !GravatarHelpers.isGravatarUrl(this.originalAvatar.url)) {\r\n            this.current.avatar.url = this.originalAvatar.url;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Set current credential for edit. */\r\n  public setCurrent(item: SessionUserCredential) {\r\n    if (item) {\r\n      this.originalAvatar = angular.copy(item.avatar);\r\n    }\r\n    super.setCurrent(item);\r\n  }\r\n\r\n  /** Saves a new credential */\r\n  public saveCurrent(): Promise<SessionUserCredential> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return super.saveCurrent().then((credential: SessionUserCredential) => {\r\n      this.originalAvatar = angular.copy(credential.avatar);\r\n      return this.sessionService.checkSession().then(() => {\r\n        loading.dismiss();\r\n        return credential;\r\n      });\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { SessionService, UserSettingsService } from \"../../services\";\r\nimport { AjaxNg1 } from \"../../ajax\";\r\nimport { UserSession } from \"@salaxy/core\";\r\n\r\n/**\r\n * The controller is used in creating embedded UI:s: When this NG1 based SPA is run in an iframe\r\n * and the parent sends token, session and settings as window messages.\r\n */\r\nexport class EmbeddedUiController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\", \"$timeout\", \"AjaxNg1\", \"$location\", \"UserSettingsService\"];\r\n\r\n  private _isLoading = true;\r\n\r\n  /**\r\n   * Creates a new EmbeddedUiController\r\n   * @ignore\r\n   */\r\n  constructor(private sessionService: SessionService, private $timeout: angular.ITimeoutService, private ajax: AjaxNg1, private $location: angular.ILocationService, private userSettingsService: UserSettingsService) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    this.startListening();\r\n  };\r\n\r\n  /**\r\n   * If true, the layout should show a full-page loader instead of normal pages.\r\n   * Controllers in normal pages should be destoyed (e.g. using ng-if) so that this can also\r\n   * be used in reloading the AngularJS user interface without full Browser reload.\r\n   */\r\n  public get showFullPageLoader(): boolean {\r\n    return this._isLoading || this.sessionService.isLoading;\r\n  }\r\n\r\n  /**\r\n   * Gets the user-specific setting (service), stored in the local storage.\r\n   */\r\n  public get userSettings() {\r\n    return this.userSettingsService;\r\n  }\r\n\r\n  private firstMessageTimeout: number |undefined;\r\n  private parentOrigin: string | undefined;\r\n\r\n  /**\r\n   * Starts listening for the session change events from the parent frame.\r\n   */\r\n  public startListening(): void {\r\n      if (window.parent === window) {\r\n        throw new Error(\"This is the parent window.\");\r\n      }\r\n      window.addEventListener(\"message\", this.onMessageReceived);\r\n      this.firstMessageTimeout = window.setTimeout(() => {\r\n        throw new Error(\"Timeout while waiting for session.\");\r\n      }, 4000);\r\n      // This does not work in refresh => Can we determine the parent referrer in some other way?\r\n      // this.parentOrigin = document.referrer.replace(/\\/[^/]*$/, \"\");\r\n      this.parentOrigin = \"*\";\r\n      window.parent.postMessage({ action: \"sxy-iframe-ready\" }, this.parentOrigin);\r\n  }\r\n\r\n  private onMessageReceived = (ev: MessageEvent<SessionChangeEventData>) => {\r\n    if (ev.data.action === \"sxy-iframe-change-session\") {\r\n      if (this.firstMessageTimeout) {\r\n        clearTimeout(this.firstMessageTimeout);\r\n        this.firstMessageTimeout = undefined;\r\n      }\r\n      if (ev.origin !== this.parentOrigin && this.parentOrigin !== \"*\") {\r\n        console.error(`Invalid origin ${ev.origin} vs ${this.parentOrigin}.`);\r\n        return;\r\n      }\r\n      const data: SessionChangeEventData = ev.data;\r\n      if (!data.session || !data.token) {\r\n        throw new Error(\"Session or token not defined in sxy-session-response event.\");\r\n      }\r\n      if ( this.sessionService.session?.currentAccount?.id !== data.session.currentAccount.id || this.sessionService.getCurrentToken() !== data.token ) {\r\n        this.ajax.useCookie = false;\r\n        this.ajax.setCurrentToken(data.token);\r\n        // Set the isLoading flag to true to show the loader even if _isLoading will be false for the short time period before sessionService loads the en/sv language file.\r\n        this.sessionService.isLoading = true;\r\n        this.sessionService.setSession(data.session);\r\n      }\r\n      if (data.route) {\r\n        this.$location.url(data.route);\r\n      }\r\n      this._isLoading = false;\r\n      this.$timeout();\r\n    } else {\r\n      // throw new Error(`Invalid action ${ev.data.action}.`);\r\n    }\r\n  };\r\n\r\n}\r\n\r\n/**\r\n * Structure of Session event as passed from Vue-based new UI to AngularJS-based old embedded UI (NG1).\r\n */\r\ntype SessionChangeEventData = {\r\n\r\n  /** Identifies the event. */\r\n  action: \"sxy-iframe-change-session\";\r\n\r\n  /** User session data. */\r\n  session: UserSession;\r\n\r\n  /** Token for the new session. */\r\n  token: string;\r\n\r\n  /** Route to which the application should go to. */\r\n  route: string;\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Configs } from \"@salaxy/core\";\r\nimport { PartnerService, SessionService } from \"../../services\";\r\n\r\n/**\r\n * User interface logic for brand selection,\r\n */\r\nexport class PartnerController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"PartnerService\", \"SessionService\"];\r\n\r\n  /** If true, the all partners all shown */\r\n  private showAll = false;\r\n\r\n  /**\r\n   * Creates a new PartnerController using dependency injection.\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private partnerService: PartnerService,\r\n    private sessionService: SessionService,\r\n    ) {}\r\n\r\n  /** Controller initialization. */\r\n  public $onInit = () => {\r\n    // empty\r\n  };\r\n\r\n  /** Shows the skin that is currently in use: \"default\" for the real skin or overriden preview skin for preview purposes. */\r\n  public get skin() {\r\n    return this.partnerService.overrideSkin || \"default\";\r\n  }\r\n\r\n  /**\r\n   * Shows the Brand ID that should be used for preview purposes: Either real service model or temporary override ID.\r\n   * Note that the service model may also be null, if there is no partner\r\n   */\r\n  public get brandId() {\r\n    return this.partnerService.overridePartnerId || this.sessionService.getSession()?.settings.partner?.serviceModelId;\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for brand selection.\r\n   */\r\n  public showSwitchCss() {\r\n    this.partnerService.showSwitchCss();\r\n  }\r\n\r\n  /**\r\n   * Temporary method only used in development\r\n   * Shows a dialog for brand selection.\r\n   */\r\n  public showSwitchCssDev() {\r\n    this.partnerService.showSwitchCssDev();\r\n  }\r\n\r\n  /**\r\n   * Gets the URL for the login screen. Mainly for testing / preview purposes.\r\n   */\r\n  public getLoginUrl() {\r\n    const server = Configs.current.wwwServer || \"https://test-www.palkkaus.fi\";\r\n    return server +  \"/Security/Authorize?client_id=\" + (this.brandId || \"\");\r\n  }\r\n\r\n  /**\r\n   * Gets the URL for the onboarding screen. Mainly for testing / preview purposes.\r\n   */\r\n   public getOnboardingUrl() {\r\n    const server = Configs.current.apiServer || \"https://test-secure.palkkaus.fi\";\r\n    let url = `${server}/Onboarding/Wizard?id=test&role=company`;\r\n    if (this.brandId) {\r\n      url = url + \"&partner=\" + this.brandId;\r\n    }\r\n    return url;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, Configs, Language, PaymentChannel, SystemRole, Translations } from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * User interaction with the current session: UserCredentials, Current Account(s) and Login/Logout.\r\n */\r\nexport class SessionController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"SessionService\",\r\n    \"$location\",\r\n    \"AjaxNg1\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  /** Default redirect URL for signIn and register if not specified by the method */\r\n  public redirectUrl: string;\r\n\r\n  constructor(\r\n    private sessionService: SessionService,\r\n    private $location: angular.ILocationService,\r\n    private ajax: Ajax,\r\n\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    //\r\n  };\r\n\r\n  /** If true, the session has been checked from theserver - i.e. isAuthenticated = false means that the user really cannot be authenticated. */\r\n  public get isSessionChecked() {\r\n    return this.sessionService.getIsSessionChecked();\r\n  }\r\n\r\n  /** If true, the session check call is progressing. */\r\n  public get isSessionChecking() {\r\n    return this.sessionService.getIsSessionChecking();\r\n  }\r\n\r\n  /** If true, the user is authenticated */\r\n  public get isAuthenticated() {\r\n    return this.sessionService.getIsAuthenticated();\r\n  }\r\n\r\n  /** Avatar to show in the login screen */\r\n  public get avatar(): any {\r\n    return this.sessionService.getAvatar();\r\n  }\r\n\r\n  /** The full session objcet */\r\n  public get session(): any {\r\n    return this.sessionService.getSession();\r\n  }\r\n\r\n  /** The company account if the current account is company - and if the full account info is fetched */\r\n  public get company(): any {\r\n    return this.sessionService.getCompanyAccount();\r\n  }\r\n\r\n  /** The person account if the current account is person - and if the full account info is fetched */\r\n  public get person(): any {\r\n    return this.sessionService.getPersonAccount();\r\n  }\r\n\r\n  /**\r\n   * Opens the login form for the current user\r\n   * @param redirectUrl - The URL where the user is taken after a successfull login.\r\n   * @param role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   * @param partnerSite Identifier of the partner or service model from which the login UI is fetched.\r\n   * @param urlPostfix Additional string that is added to the OAuth2 URL.\r\n   * Used in adding other parameters to the URL, e.g. \"&salaxy_language=en\"\r\n   */\r\n  public signIn(redirectUrl: string = null, role: string = null, partnerSite: string = null, urlPostfix: string = null) {\r\n    this.sessionService.signIn(redirectUrl || this.redirectUrl, role, partnerSite, urlPostfix);\r\n  }\r\n\r\n  /**\r\n   * Opens the login dialog with signUp / register functionality\r\n   * @param  redirectUrl - The URL where the user is taken after a successfull login\r\n   * @param  role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   * @param partnerSite Identifier of the certified partner which should be granted access rights in account creation.\r\n   * Also sets register dialog and onboarding wizard UI skin.\r\n   * @param urlPostfix Additional string that is added to the OAuth2 URL.\r\n   * Used in adding other parameters to the URL, e.g. \"&salaxy_language=en\"\r\n   */\r\n\r\n  public register(redirectUrl: string = null, role: string = null, partnerSite: string = null, urlPostfix: string = null) {\r\n    this.sessionService.register(redirectUrl || this.redirectUrl, role, partnerSite, urlPostfix);\r\n  }\r\n\r\n  /** If false, the current authenticated user has not signed the contract. */\r\n  public get isAccountVerified(): boolean {\r\n    return this.sessionService.checkAccountVerification();\r\n  }\r\n\r\n  /**\r\n   * Sends the user to the Sign-out page\r\n   * @param redirectUrl - URL where user is redirected after log out.\r\n   * Must be absolute URL. Default is the root of the current server.\r\n   */\r\n  public signOut(redirectUrl?: string) {\r\n    this.sessionService.signOut(redirectUrl);\r\n  }\r\n\r\n  /**\r\n   * Switches the current web site usage role between household and worker.\r\n   * @param role - household or worker.\r\n   * @returns A Promise with result data (new role as string)\r\n   */\r\n  public switchRole(role: \"worker\" | \"household\"): Promise<\"household\" | \"worker\"> {\r\n    return this.sessionService.switchRole(role).then((resultRole) => {\r\n      if (role === \"worker\") {\r\n        window.location.href = \"/Worker#/\";\r\n      } else {\r\n        window.location.href = \"/Household#/\";\r\n      }\r\n      return resultRole;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * When called, will show the login screen if the user is not logged in\r\n   */\r\n  public checkAuthenticated() {\r\n    if (this.isSessionChecked && !this.isAuthenticated) {\r\n      this.signIn(window.location.href);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Checks whether the user is in a given role\r\n   * @param  role - One of the known roles\r\n   */\r\n  public isInRole(role: SystemRole): boolean {\r\n    return this.sessionService.isInRole(role);\r\n  }\r\n\r\n  /**\r\n   * Set the language for UI in the current session.\r\n   * @param lang - Language to select: fi, en, sv.\r\n   */\r\n  public setLanguage(lang: Language) {\r\n    this.sessionService.setLanguage(lang);\r\n  }\r\n\r\n  /**\r\n   * Get the current language for UI in the current session.\r\n   */\r\n  public getLanguage() {\r\n    return Translations.getLanguage();\r\n  }\r\n\r\n  /**\r\n   * Switches the CSS link to partner-specific CSS.\r\n   * @param cssUrl URL for the CSS file.\r\n   */\r\n  public switchCss(cssUrl: string) {\r\n    this.sessionService.switchCss(cssUrl);\r\n  }\r\n\r\n  /** Sign in error */\r\n  public get signInError(): string {\r\n    return this.sessionService.signInError;\r\n  }\r\n  /** Sign in error description */\r\n  public get signInErrorDescription(): string {\r\n    return this.sessionService.signInErrorDescription;\r\n  }\r\n  /** Sign in error page url */\r\n  public get signInErrorPageUrl(): string {\r\n    return this.sessionService.signInErrorUrl;\r\n  }\r\n\r\n  /** Returns current token if exists. */\r\n  public get currentToken(): string {\r\n    return this.ajax.getCurrentToken();\r\n  }\r\n\r\n  /** Returns the url to the authorization pdf. */\r\n  public get authorizationPdfUrl() {\r\n    return `${Configs.current.apiServer}/Onboarding/GetAuthorizationPdf?access_token=${encodeURIComponent(this.ajax.getCurrentToken())}`;\r\n  }\r\n\r\n  /** Returns owned payment channel for current account */\r\n  public get ownedPaymentChannel(): PaymentChannel {\r\n    return this.sessionService.getOwnedPaymentChannel();\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Accounts, Ajax, Avatar, AvatarPictureType, CompanyAccount, WorkflowEvent } from \"@salaxy/core\";\r\n\r\nimport { GravatarHelpers, SessionService, UiHelpers, UploadService } from \"../../services\";\r\n\r\n/** Company account controller for editing basic information. */\r\nexport class CompanyAccountController implements angular.IComponentController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Accounts\", \"SessionService\", \"AjaxNg1\", \"UiHelpers\", \"UploadService\"];\r\n\r\n  /** Current company account */\r\n  public current: CompanyAccount = null;\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    private accounts: Accounts,\r\n    private sessionService: SessionService,\r\n    private ajax: Ajax,\r\n    private uiHelpers: UiHelpers,\r\n    private uploadService: UploadService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    if (!this.current) {\r\n      this.accounts.getCompany().then((company) => {\r\n        this.current = company;\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Gets the language of the current company */\r\n  public getAccountLanguage() {\r\n    return this.current?.language;\r\n  }\r\n  /** Updates the company */\r\n  public saveCurrent(): Promise<CompanyAccount> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return this.ajax.postJSON(\"/accounts/company\", this.current).then((company: CompanyAccount) => {\r\n      this.current = company;\r\n      return this.sessionService.checkSession().then(() => {\r\n        loading.dismiss();\r\n        return company;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Uploads avatar image file to the server.\r\n   * @param avatar - selected file\r\n   */\r\n  public uploadAvatarImage(avatar: any, current: CompanyAccount = null) {\r\n    if (!avatar) {\r\n      return;\r\n    }\r\n    current = current ?? this.current;\r\n    this.uploadService.upload<Avatar>(this.accounts.getAvatarUploadUrl(), { avatar })\r\n      .then((resp) => {\r\n        current.avatar.url = resp.url;\r\n        current.avatar.pictureType = resp.pictureType;\r\n      });\r\n  }\r\n\r\n  /** Called when avatar changes */\r\n  public emailForAvatarChanged(current: CompanyAccount = null) {\r\n    current = current  ?? this.current;\r\n    if (!current || !current.avatar) {\r\n      return;\r\n    }\r\n    if (current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      current.avatar.url = GravatarHelpers.getGravatarUrl(current.contact.email);\r\n    }\r\n  }\r\n  /** Called when avatar changes */\r\n  public typeForAvatarChanged(current: CompanyAccount = null) {\r\n    current = current  ?? this.current;\r\n    if (!current || !current.avatar) {\r\n      return;\r\n    }\r\n    if (current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      current.avatar.url = GravatarHelpers.getGravatarUrl(current.contact.email);\r\n    } else {\r\n      if (GravatarHelpers.isGravatarUrl(current.avatar.url)) {\r\n        current.avatar.url = null;\r\n      }\r\n      if (current.avatar.pictureType === AvatarPictureType.Uploaded) {\r\n        const originalAvatar = (this.sessionService.getPersonAccount() || {}).avatar;\r\n        if (!current.avatar.url && originalAvatar && originalAvatar.url) {\r\n          if (originalAvatar.pictureType === AvatarPictureType.Uploaded &&\r\n            !GravatarHelpers.isGravatarUrl(originalAvatar.url)) {\r\n            current.avatar.url = originalAvatar.url;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Adds/updates the workflow event for the current using API.\r\n   * @param wfEvent - Workflow event to add/update.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public saveWorkflowEvent(wfEvent: WorkflowEvent): Promise<void | CompanyAccount> {\r\n    return this.accounts.saveWorkflowEvent(this.current, wfEvent).then(() => {\r\n      return this.accounts.getCompany().then((company) => {\r\n        this.current = company;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes the given event or all events with given type using API.\r\n   * @param wfIdOrType Id or type of the workflow event.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public deleteWorkflowEvent(wfIdOrType: string): Promise<void | CompanyAccount> {\r\n    return this.accounts.deleteWorkflowEvent(this.current, wfIdOrType).then(() => {\r\n      return this.accounts.getCompany().then((company) => {\r\n        this.current = company;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a single workflow event for the item.\r\n   * @param wfId Id the workflow event.\r\n   * @returns - Workflow event.\r\n   */\r\n  public getWorkflowEvent(wfId: string): Promise<WorkflowEvent> {\r\n    return this.accounts.getWorkflowEvent(this.current, wfId);\r\n  }\r\n\r\n  /**\r\n   * Opens modal for avatar edit\r\n   */\r\n  public openEditDialog(editType: \"avatar\" | \"contactInfo\"): void {\r\n    const logic = {\r\n      typeForAvatarChanged: (current) => this.typeForAvatarChanged(current),\r\n      uploadAvatarImage: (file, current) => this.uploadAvatarImage(file, current),\r\n      emailForAvatarChanged: (current) => this.emailForAvatarChanged(current)\r\n    };\r\n    this.uiHelpers.openEditDialog(\r\n      editType === \"avatar\" ? \"salaxy-components/modals/account/AccountAvatarEdit.html\" : \"salaxy-components/modals/account/AccountContactEdit.html\",\r\n      this.current,\r\n      logic\r\n      ).then((result) => {\r\n        if (result.action === \"ok\") {\r\n          this.current = result.item;\r\n          this.saveCurrent();\r\n        }\r\n      });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Calculation } from \"@salaxy/core\";\r\nimport { UiCrudHelpers, UiHelpers } from \"../../../services\";\r\nimport { CalculationCrudController } from \"../CalculationCrudController\";\r\n\r\n/**\r\n * Allows editing the employmen\r\n */\r\nexport class CalcEmploymentController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"UiCrudHelpers\"];\r\n\r\n  /**\r\n   * Setter for the calculations controller that edits the current item.\r\n   * Possibility to support other data types.\r\n   */\r\n  public model: CalculationCrudController;\r\n\r\n  /**\r\n   * If true, will also update the calculation rows from employment relation when the employment\r\n   * relation is selected. By default, does not update the rows.\r\n   */\r\n  public updateRows: boolean;\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Gets the current calculation. By convention, set in model. */\r\n  public get current(): Calculation {\r\n    return this.model.current;\r\n  }\r\n\r\n  /**\r\n   * Opens a dialog that shows the wizard to create a new Employment relation.\r\n   */\r\n  public launchEmploymentWizard(): void {\r\n    this.uiCrudHelpers.createNewEmployment().then((result) => {\r\n      if (result.action === \"ok\") {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n        this.model.updateFromEmployment(result.item.id, this.updateRows || false).then(() => {\r\n          loader.dismiss();\r\n        });\r\n      }\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Calculation, Calculations, CalculationStatus, CalculatorLogic, PaymentChannel, Translations, CalculationListItem, SystemRole } from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, ReportsService, SessionService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * The new ApiCrudObject type of CRUD controller for the calculations.\r\n */\r\nexport class CalculationCrudController extends ApiCrudObjectController<Calculation, CalculationListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"ReportsService\", \"UiHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"InvoicesService\"];\r\n\r\n  /**\r\n   * If true, will also update the calculation rows from employment relation when the employment\r\n   * relation is selected. Note that this value is true by default for historical reasons.\r\n   */\r\n   public updateRows: boolean;\r\n\r\n  constructor(\r\n    private calculationsApi: Calculations,\r\n    protected reportsService: ReportsService,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    protected sessionService: SessionService,\r\n    protected invoicesService: InvoicesService,\r\n  ) {\r\n    // Dependency injection\r\n    super(calculationsApi, uiHelpers, $location, $routeParams);\r\n  }\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (this.updateRows == null) {\r\n      this.updateRows = true;\r\n    }\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/calc\",\r\n      detailsUrl: this.detailsUrl || \"/calc/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/CalculationsAll.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Recalculates the current calculation */\r\n  public recalculate() {\r\n    this.setStatus(this.calculationsApi.recalculate(this.current))\r\n      .then((calc) => {\r\n        this.setCurrentValue(calc);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the URL for a calculation pdf.\r\n   * If report has not been saved (ID is null), returns null.s\r\n   * @param calc - Calculation. This method requires that the calculation has been saved.\r\n   * @returns Url for specified report\r\n   */\r\n  public getPdfUrl(calc: Calculation) {\r\n    if (!calc) {\r\n      return null;\r\n    }\r\n    return this.reportsService.getPdfUrlForCalc(\"salarySlip\", calc.id, true);\r\n  }\r\n\r\n  /**\r\n   * If true, this is a new unsaved object.\r\n   * Adds \"new-for-employment\" actions as new item.\r\n   */\r\n  public isNew(): boolean {\r\n    if (this.parentController) {\r\n      return this.parentController.isNew();\r\n    }\r\n    return this.action === \"new-for-worker\" || this.action === \"new-for-employment\" || super.isNew();\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process depending on the bindingMode:\r\n   * Overrides a different load process for \"new-for-employment\".\r\n   */\r\n  public reload(): Promise<Calculation> {\r\n    if (this.action === \"new-for-worker\" || this.action === \"new-for-employment\") {\r\n      if (this.parentController) {\r\n        return this.parentController.reload().then((item) => {\r\n          this._currentId = null;\r\n          return item;\r\n        });\r\n      } else {\r\n        const calc = this.api.getBlank();\r\n        if (this.currentId === \"new\") {\r\n          this._currentId = null;\r\n        }\r\n        if (this.action === \"new-for-worker\") {\r\n          calc.worker.accountId = this.currentId;\r\n        } else {\r\n          calc.worker.employmentId = this.currentId;\r\n        }\r\n        this._currentId = null;\r\n        this.setDefaultPaymentChannel(calc);\r\n        return this.setStatus(this.calculationsApi.updateFromEmployment(calc, false, this.updateRows))\r\n          .then((item) => {\r\n            this.setCurrentRef(item);\r\n            return item;\r\n          });\r\n      }\r\n    } else {\r\n      if (this.isNew() && this.sessionService.isInRole(\"worker\")) {\r\n        if (this.parentController) {\r\n          return this.parentController.reload().then((item) => {\r\n            this._currentId = null;\r\n            return item;\r\n          });\r\n        } else {\r\n          const getNewCalc = (): Promise<Calculation> => {\r\n            if (this.action === \"copy-as-new\") {\r\n              return this.setStatus(this.api.getSingle(this.currentId)).then((item) => {\r\n                return this.copyItem( item || this.api.getBlank());\r\n              });\r\n            } else {\r\n              return Promise.resolve(this.api.getBlank());\r\n            }\r\n          };\r\n          return getNewCalc().then((newCalc) => {\r\n            newCalc.worker.isSelf = true;\r\n            newCalc.employer.isSelf = false;\r\n            this._currentId = null;\r\n            this.setDefaultPaymentChannel(newCalc);\r\n            return this.setStatus(this.calculationsApi.recalculate(newCalc)).then((calc) => {\r\n              this.setCurrentRef(calc);\r\n              return calc;\r\n          });\r\n        });\r\n        }\r\n      }\r\n\r\n      return super.reload().then( (reloaded) => {\r\n        if (super.isNew()) {\r\n          this.setDefaultPaymentChannel(reloaded);\r\n        }\r\n        return reloaded;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creates a copy of a given item.\r\n   * This is a synchronous method that should basically convert a saved item to a new item.\r\n   * @param copySource Item (container item) to copy as new.\r\n   */\r\n  public copyItem(copySource: Calculation): Calculation {\r\n    const copy = super.copyItem(copySource);\r\n    copy.id = null;\r\n    copy.info.workStartDate = null;\r\n    copy.info.workEndDate = null;\r\n    copy.info.workerMessage = null;\r\n    copy.info.paymentId = null;\r\n    copy.info.payrollId = null;\r\n    copy.info.backofficeNotes = null;\r\n    copy.info.pensionPaymentDate = null;\r\n    copy.info.pensionPaymentRef = null;\r\n    copy.info.pensionPaymentSpecifier = null;\r\n    copy.info.paymentChannel = PaymentChannel.Undefined;\r\n    copy.info.messageThreadId = null;\r\n    copy.worktime = {};\r\n    copy.workflow.status = CalculationStatus.Draft;\r\n    copy.workflow.paidAt = null;\r\n    copy.workflow.salaryDate = null;\r\n    copy.workflow.requestedSalaryDate = null;\r\n    copy.workflow.salaryPaidAt = null;\r\n    copy.createdAt = null;\r\n    copy.updatedAt = null;\r\n    if (copy.framework) {\r\n      copy.framework.numberOfDays = 0;\r\n    }\r\n    // HACK: remove payroll-service flag. This will be replaced with invoicing flags eventually.\r\n    if (copy.usecase &&\r\n      ( copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/pro-calc\" ||\r\n      copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/calc\")) {\r\n      copy.usecase = {};\r\n    }\r\n    copy.isReadOnly = false;\r\n    this.setDefaultPaymentChannel(copy);\r\n    return copy;\r\n  }\r\n\r\n  /** Shows the paymentd dialog / the invoices UI. */\r\n  public showPaymentDialog() {\r\n    this.invoicesService.showPaymentDialog(this.current);\r\n  }\r\n\r\n  /** Shows inspection dialog for invoices of paid calculation*/\r\n  public showInvoicesDialog() {\r\n    this.invoicesService.showPalkkausPersonalInvoicesDialog(this.current);\r\n  }\r\n\r\n  /**\r\n   * Updates the calculation from Employment ID by deleting all the rows and re-setting the employment.\r\n   * @param employmentId Employement Id to set.\r\n   * If null, the employment Id already in calculation is used:\r\n   * This method cannot be used to remove the Worker (extend if necessary).\r\n   * @param updateRows If true, updates also the calc rows from the default rows in\r\n   * employment relation. If false, the rows are kept as is.\r\n   * @returns The Calculation after recalc (no saving).\r\n   */\r\n   public updateFromEmployment(employmentId: string = null, updateRows: boolean): Promise<Calculation> {\r\n    if (employmentId) {\r\n      this.current.worker.employmentId = employmentId;\r\n    }\r\n    return this.calculationsApi.updateFromEmployment(this.current, false, updateRows).then((calc) => {\r\n      super.setCurrentValue(calc);\r\n      return calc;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Cancels the payment or invoice processing for the current calculation.\r\n   */\r\n  public cancel(): Promise<Calculation> {\r\n    const eprWarningMessage = this.invoicesService.getEprWarningForCancellation(this.current.workflow?.salaryDate, this.current.workflow?.status == CalculationStatus.PaymentSucceeded);\r\n    const eprText = eprWarningMessage ? \"\\n\" + eprWarningMessage : \"\";\r\n    return this.uiHelpers.showConfirm(Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogTitle\")+\"?\", Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogDescr\") + `${eprText}`, \"SALAXY.NG1.CalcResultsComponent.cancelDialogYes\", \"SALAXY.NG1.CalcResultsComponent.cancelDialogNo\").then( (result ) => {\r\n      if (result) {\r\n        const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n        return this.calculationsApi.cancel(this.currentId).then( (item: Calculation) => {\r\n          this.setCurrentValue(item);\r\n          loading.dismiss();\r\n          return this.current;\r\n        });\r\n      } else {\r\n        return this.current;\r\n      }\r\n    });\r\n  }\r\n\r\n   /**\r\n    * If true, the form controls should be read-only (no control at all).\r\n    */\r\n  public get isReadOnly() {\r\n    return super.isReadOnly || this.current.workflow?.status === CalculationStatus.PaymentStarted;\r\n  }\r\n\r\n  /**\r\n   * Returns true if there is no net salary payment to worker at all.\r\n   */\r\n  public get isCurrentZeroPayment(): boolean {\r\n      return CalculatorLogic.isZeroPayment(this.current);\r\n  }\r\n\r\n  private setDefaultPaymentChannel(calc: Calculation) {\r\n    if (calc && calc.info && this.sessionService.getSession() && (!calc.info.paymentChannel || calc.info.paymentChannel === PaymentChannel.Undefined) ) {\r\n      calc.info.paymentChannel = this.invoicesService.defaultChannel;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * HACK: This will be removed after moved to useCase based calculators.\r\n   * Temporary redirecting to correct details view.\r\n   * TODO: Should be replaced with full usecase logic based implementation.\r\n   */\r\n  public showDetails(item: Calculation | CalculationListItem) {\r\n    // HACK: This implementation is a bit hacky, but it should work.\r\n    // This is to be replaced with logic that checks the usecase and makes the redirect accordingly.\r\n    if(!this.sessionService.isInRole(SystemRole.Test)) {\r\n      if ((item as Calculation)?.workflow?.status == CalculationStatus.History) {\r\n        this.detailsUrl = \"/calc/history/\";\r\n      }\r\n      if ((item as CalculationListItem)?.status == CalculationStatus.History) {\r\n        this.detailsUrl = \"/calc/history/\";\r\n      }\r\n    }\r\n    return super.showDetails(item);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiItemType, Arrays, calcReportType, Calculation, CalculationRowType, Calculations, Usecase, UsecaseListItem, CalculationStatus, SalaryDateKind, PaymentChannel } from \"@salaxy/core\";\r\n\r\nimport { CalculationCrudController } from \"../CalculationCrudController\";\r\nimport { EditDialogKnownActions, InvoicesService, ReportsService, SessionService, UiCrudHelpers, UiHelpers, UsecasesService } from \"../../../services\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../bases\";\r\n\r\n/** Enumerations for calculator actions */\r\nenum CalculatorActions {\r\n  AllowForcePay = \"allowForcePay\",\r\n  Approve = \"approve\",\r\n  Cancel = \"cancel\",\r\n  CopyAsNew = \"copyAsNew\",\r\n  Delete = \"delete\",\r\n  Pay = \"pay\",\r\n  Recalculate = \"recalculate\",\r\n  Reject = \"reject\",\r\n  Save = \"save\",\r\n  SendToPro = \"sendToPro\",\r\n  ShowPaymentDialog = \"showPaymentDialog\",\r\n  SetSalaryDateKind = \"setSalaryDateKind\",\r\n}\r\n/**\r\n * Year 2022 version of the Calculator controller designed for customized calculator UI's (usecases).\r\n * Removes old methods that are no longer necessary (household, old calculator UI)\r\n * and adds more support for customization.\r\n */\r\nexport class Calculator2022Controller extends CalculationCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"ReportsService\", \"UiHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"InvoicesService\", \"UiCrudHelpers\", \"UsecasesService\"];\r\n\r\n  /** Component bindings */\r\n  public static crudBindings = (new class extends ApiCrudObjectControllerBindings {\r\n  }());\r\n\r\n  /**\r\n   * The usecase definition if specified and loaded.\r\n   * Check the usecaseState if the.\r\n   */\r\n  public usecase: null | Usecase = null;\r\n\r\n  /** Available usecases if the user needs to make a selection of which usecase to take. */\r\n  public usecases: UsecaseListItem[];\r\n\r\n\r\n  /** If true, additional worker info is displayed in the UI */\r\n  public isWorkerInfoOpen: boolean;\r\n\r\n\r\n  constructor(\r\n    calcApi: Calculations,\r\n    reportsService: ReportsService,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    protected invoicesService: InvoicesService,\r\n    protected uiCrudHelpers: UiCrudHelpers,\r\n    private usecasesService: UsecasesService,\r\n  ) {\r\n    // Dependency injection\r\n    super(calcApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    this.isWorkerInfoOpen = false;\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Overrides the reload to assure that usecase is also loaded. */\r\n  public reload(): Promise<Calculation> {\r\n    return super.reload().then((calc) => {\r\n      const usecaseUri = this.$location?.search().usecase;\r\n      if (!usecaseUri && this.isNew()) {\r\n        return this.showUsecasesSelection();\r\n      }\r\n      return this.usecasesService.assureUsecase(ApiItemType.Calculation, calc, usecaseUri).then((usecase) => {\r\n        this.usecase = usecase;\r\n        //this.callEvent(\"onLoad\");\r\n        return calc;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * If true, the given action (button) is displayed.\r\n   * @param action One of the action values.\r\n   * For now, validation and role based action logic is in UI.\r\n   * Todo: some edge cases, i.e. isForcePayAllAllowed (for pay-button) are still in UI.\r\n   */\r\n  public showAction(action: CalculatorActions): boolean {\r\n\r\n    if (!this.current) {\r\n      return false;\r\n    }\r\n    // In read only mode\r\n    if (this.isReadOnlyForced && action != CalculatorActions.ShowPaymentDialog) {\r\n      return false;\r\n    }\r\n    if (this.isReadOnlyForced && action == CalculatorActions.ShowPaymentDialog) {\r\n      return true;\r\n    }\r\n    if (this.current.workflow.status == CalculationStatus.PayrollDraft) {\r\n      // Not possible to make changes to editable payroll calculation\r\n      return false;\r\n    }\r\n    if (this.current.isReadOnly) {\r\n      switch (action) {\r\n        case CalculatorActions.Cancel:\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted &&\r\n            [\r\n              PaymentChannel.PalkkausManual,\r\n              PaymentChannel.PalkkausPersonal,\r\n              PaymentChannel.PalkkausInvoices,\r\n              PaymentChannel.PalkkausCfaPaytrail,\r\n              PaymentChannel.PalkkausEcfaPaytrail,\r\n              PaymentChannel.PalkkausCfaReference,\r\n              PaymentChannel.PalkkausEcfaReference,\r\n              PaymentChannel.PalkkausCfaFinvoice,\r\n              PaymentChannel.PalkkausEcfaFinvoice,\r\n              PaymentChannel.PalkkausCfaTest,\r\n            ].indexOf(this.current.info.paymentChannel) > -1;\r\n        case CalculatorActions.CopyAsNew:\r\n          return !this.isReadOnlyForced; // Not needed?\r\n        case CalculatorActions.ShowPaymentDialog:\r\n          return true;\r\n        case CalculatorActions.AllowForcePay: // \"Allow forcepay\" action is payment action when calculation is not valid. Logic handled in UI for now.\r\n        case CalculatorActions.Pay:\r\n        case CalculatorActions.Recalculate:\r\n        default:\r\n          return false;\r\n      }\r\n    } else {\r\n      switch (action) {\r\n        case CalculatorActions.AllowForcePay:\r\n\r\n          return this.isForcePayAllAllowed &&\r\n            (this.current.workflow.status != CalculationStatus.WaitingApproval &&\r\n              this.current.workflow.status != CalculationStatus.SharedRejected &&\r\n              this.current.workflow.status != CalculationStatus.SharedWaiting);\r\n        case CalculatorActions.Pay:\r\n          // add here isValid?\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved;\r\n        case CalculatorActions.Save:\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved ||\r\n            this.current.workflow.status == CalculationStatus.History;\r\n        case CalculatorActions.Delete:\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedRejected ||\r\n            this.current.workflow.status == CalculationStatus.History;\r\n        case CalculatorActions.SendToPro:\r\n          return this.current.workflow.status == CalculationStatus.WaitingApproval;\r\n        case CalculatorActions.Recalculate:\r\n          return true;\r\n        case CalculatorActions.Reject:\r\n          return this.current.workflow.status == CalculationStatus.SharedApproved ||\r\n            this.current.workflow.status == CalculationStatus.SharedWaiting;\r\n        case CalculatorActions.Approve:\r\n          return this.current.workflow.status == CalculationStatus.SharedRejected ||\r\n            this.current.workflow.status == CalculationStatus.SharedWaiting;\r\n        case CalculatorActions.SetSalaryDateKind:\r\n          return (this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved) &&\r\n            (\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausManual ||\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausInvoices ||\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausCfaTest ||\r\n              this.current.info.paymentChannel == PaymentChannel.Briox ||\r\n              this.current.info.paymentChannel == PaymentChannel.Askelma ||\r\n              this.current.info.paymentChannel == PaymentChannel.Kitsas ||\r\n              this.current.info.paymentChannel == PaymentChannel.PasseliMerit\r\n            );\r\n        default:\r\n          return false;\r\n      }\r\n    }\r\n\r\n  }\r\n\r\n  /**\r\n   * Returns true, if action (button) is disabled\r\n   * TODO: Add rules based on roles and validation? Pay button logic is in UI.\r\n   */\r\n  public isActionDisabled(action: CalculatorActions): boolean {\r\n    if (!this.current) {\r\n      return true;\r\n    }\r\n    // In read only mode\r\n    if (this.isReadOnlyForced) {\r\n      return true;\r\n    }\r\n\r\n    if (this.current.isReadOnly) {\r\n      switch (action) {\r\n        case CalculatorActions.Delete:\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted;\r\n        case CalculatorActions.Save:\r\n          // add here isValid?\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted;\r\n        default:\r\n          return true;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Loads the available usecases => The UI shows them as selection. */\r\n  public showUsecasesSelection(): Promise<Calculation> {\r\n    this.usecases = [];\r\n    return this.setStatus(this.usecasesService.getActiveUsecaseListItems(ApiItemType.Calculation).then((list) => {\r\n      if (list.length) {\r\n        this.usecases = list.sort((a, b) => (a.data.order || 100) - (b.data.order || 100));\r\n      } else {\r\n        // No usecases => use default\r\n        this.usecases = null;\r\n      }\r\n      return this.current;\r\n    }));\r\n  }\r\n\r\n  /**\r\n   * Sets the given usecase to the current calculation.\r\n   * @param uri Uri for the new usecase.\r\n   */\r\n  public setUsecase(uri: string): void {\r\n    this.setStatus(this.usecasesService.assureUsecase(ApiItemType.Calculation, this.current, uri).then((uc) => {\r\n      this.usecase = uc;\r\n      //this.callEvent(\"onLoad\");\r\n      this.usecases = null;\r\n      return this.current;\r\n    }));\r\n  }\r\n\r\n\r\n  /**\r\n   * Gets a total of row type(s)\r\n   * @param types A single row type or array of types to filter for calculation.\r\n   */\r\n  public getRowTotal(types: CalculationRowType | CalculationRowType[]) {\r\n    if (!types) {\r\n      return 0;\r\n    }\r\n    if (!Array.isArray(types)) {\r\n      types = [types];\r\n    }\r\n    return Arrays.sum(this.current?.result?.rows || [], (x) => types.indexOf(x.rowType) >= 0 ? x.total : 0);\r\n  }\r\n\r\n  /**\r\n   * Shows a report for the current calculation using a modal dialog.\r\n   * @param reportType - Type of report to show\r\n   */\r\n  public showReportDialog(reportType: calcReportType) {\r\n    this.reportsService.showReportModalForCalc(reportType, this.current);\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for modifying an existing Worker:\r\n   * Saves changes and updates the calculation.\r\n   */\r\n  public showWorkerEditDialog() {\r\n    this.uiCrudHelpers.openEditEmploymentDialog(this.current.worker.employmentId, \"updateCalc\")\r\n      .then((result) => {\r\n        if (result.action === \"ok\" || result.action === \"ok-no-rows\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.CalcComponent.dialog.showWorkerEditDialogLoading\");\r\n          this.updateFromEmployment(result.item.id, result.action === \"ok\").then(() => {\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Shows infor dialog about the current usecase in the calculation. */\r\n  public showUsecaseInfo(): void {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/workflow/UsecaseInfo.html\", this.usecase, {\r\n      objUsecase: this.current.usecase,\r\n      canDelete: this.isNew(),\r\n    }, \"lg\").then((result) => {\r\n      if (result.action == EditDialogKnownActions.Delete && this.isNew()) {\r\n        this.usecase = null;\r\n        this.current.usecase = {};\r\n        return this.showUsecasesSelection();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog during the check of auto taxcard.\r\n   */\r\n  public showRefreshAutoTaxcardDialog() {\r\n    const loader = this.uiHelpers.showLoading();\r\n    this.uiCrudHelpers.refreshAutoTaxcard(this.current.worker.tax?.taxcardId, this.current.workflow?.salaryDate).then(() => {\r\n      loader.dismiss();\r\n      this.recalculate();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for adding a new Employment relation.\r\n   * If user goes through the wizard the employment relation is saved and set to the calculation.\r\n   */\r\n  public showNewWorkerDialog() {\r\n    this.uiCrudHelpers.createNewEmployment().then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.updateFromEmployment(result.item.id, true);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns validation for current calculation or empty validation object if the calculation has not been recalculated (validated).\r\n   */\r\n  public get validation() {\r\n    return this.current?.result?.validation || { errors: [], hasAllRequiredFields: true, isValid: true };\r\n  }\r\n\r\n  /** Returns true if the payment is possible when the employer pays all.  */\r\n  public get isForcePayAllAllowed(): boolean {\r\n    const obj = this.validation.errors.find((x) =>\r\n      (x.type !== \"warning\"));\r\n    return !obj;\r\n  }\r\n  /** HACK: This will be removed after moved to useCase based calculators. Placeholder for usecase specific logic in history calculation. */\r\n  public historyUsecase = {\r\n    save: () => {\r\n      this.detailsUrl = \"/calc/history/\";\r\n      this.current.workflow.status = CalculationStatus.History,\r\n        this.current.workflow.salaryDateKind = SalaryDateKind.InPast;\r\n      this.save();\r\n    },\r\n    recalculate: () => {\r\n      this.current.workflow.status = CalculationStatus.History,\r\n        this.current.workflow.salaryDateKind = SalaryDateKind.InPast;\r\n      this.recalculate();\r\n    }\r\n  };\r\n}","import angular from \"angular\";\r\n\r\nimport { ApiValidation, CalculationRowType, DataMapper, Dataset, DatasetListItem, Datasets, Employment, Employments, FileParser, HrSuuntiImportLogic, Importable, RowTypeMatch, SalaryBasesRow, ValidationHelper } from \"@salaxy/core\";\r\nimport { SalaryBases } from \"./SalaryBases\";\r\nimport { EditDialogKnownActions, JsonSchemaService, UiCrudHelpers, UiHelpers } from \"../../../services\";\r\nimport { PayrollCrudController } from \"../PayrollCrudController\";\r\nimport { AjaxNg1 } from \"../../../ajax\";\r\nimport { ImportController } from \"../../helpers/ImportController\";\r\n\r\n/**\r\n * Controller for employer and worker charts using angular-chart\r\n */\r\nexport class SalaryBasesController implements angular.IController {\r\n\r\n  /*\r\n  TODO-lista:\r\n  - Uuden rivin luominen: Eri tyypit (ignore, warning etc.)\r\n  - Warning ja Error toimimaan\r\n  - TODO ja HACK\r\n  - Saako rivin muokkauksen dialogiin (Usecase)\r\n  - Rivin muokkaus Rivit-näkymään (rowType-dialogi)\r\n  */\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Employments\", \"UiCrudHelpers\", \"UiHelpers\", \"AjaxNg1\", \"JsonSchemaService\", \"Datasets\"];\r\n\r\n  /** Source data that is mapped to salary bases suitable to creating calculations etc. */\r\n  public current: SalaryBases;\r\n\r\n  /** Full set of employments for binding to data. */\r\n  public employments: Employment[];\r\n\r\n  /** Datasets that define the import pattern / settings. */\r\n  public datasets: DatasetListItem[];\r\n\r\n  /** Current dataset that contains the definition data for the import. */\r\n  public dataset: Dataset;\r\n\r\n  /** Payroll controller that contains the payroll that is being edited. */\r\n  public payrollController: PayrollCrudController;\r\n\r\n  public importController: ImportController;\r\n\r\n  /** Active tab: set by the import operations. */\r\n  public currentTab: string;\r\n\r\n  /** TODO: Move to enum, also add descriptions */\r\n  public matchTypes = {\r\n    row: \"Oletusrivi\",\r\n    hourlyRow: \"Tuntipalkkaan perustuva rivi\",\r\n    monthlySalary: \"Kuukausipalkka\",\r\n    ignore: \"Ohitetaan\",\r\n    warning: \"Varoitus\",\r\n    error: \"Virhe\",\r\n  };\r\n\r\n  /**\r\n   * Creates a new SalaryBasesController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private employmentsApi: Employments,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    private uiHelpers: UiHelpers,\r\n    private ajax: AjaxNg1,\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private datasetsApi: Datasets\r\n    ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller. */\r\n  public $onInit() {\r\n    this.current = {};\r\n    this.datasetsApi.getOData({\r\n      // TODO: Perhaps add `status eq \"draft/instance/template\"`\r\n      $filter: `entityType eq 'import'`,\r\n    }).then((result) => {\r\n      this.datasets = result.items;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Loads the given dataset.\r\n   * @param datasetToLoad List item for which the whole dataset should be loaded.\r\n   */\r\n  public loadDataset(datasetToLoad: DatasetListItem): void {\r\n    const loader = this.uiHelpers.showLoading();\r\n    this.datasetsApi.getSingle(datasetToLoad.id).then((result) => {\r\n      this.dataset = result;\r\n      loader.dismiss();\r\n    });\r\n  }\r\n\r\n  /** The row types mapper from the dataset */\r\n  public getRowTypeMapper(): RowTypeMatch[] {\r\n    if (!this.dataset.data[0]?.content?.length) {\r\n      this.dataset.data[0].content = HrSuuntiImportLogic.getRowTypeMapperEditable();\r\n    }\r\n    return this.dataset.data[0].content;\r\n  }\r\n\r\n  /** Fetches the employment relations for operations on this UI. */\r\n  public getEmployments() {\r\n    const loader = this.uiHelpers.showLoading(\"Ladataan työsuhteita...\");\r\n    this.employmentsApi.getActiveFullObject(null).then((result) => {\r\n      if (this.payrollController?.current) {\r\n        const payrollEmployments = this.payrollController.current.calcs.map((x) => x.worker.employmentId);\r\n        result.forEach((x) => {\r\n          if (payrollEmployments.find((id) => x.id == id)) {\r\n            x.usecase.data = x.usecase.data || {};\r\n            x.usecase.data.isPayroll = true;\r\n          }\r\n        });\r\n      }\r\n      this.employments = result;\r\n      this.currentTab = \"employments\";\r\n      loader.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Gets the importable interface for importing the SalaryBasesRows */\r\n  public getImportable(): Importable<SalaryBasesRow> {\r\n    const result: Importable<SalaryBasesRow> = {\r\n      getImportMappers() {\r\n        return [{\r\n          value: \"NG1/SalaryBasesController/HRSuunti\",\r\n          text: \"HR Suunti / Tikon tuonti\",\r\n        }];\r\n      },\r\n      getImportMapper: async () => {\r\n        const mapper = new DataMapper<any, SalaryBasesRow>(\"NG1/SalaryBasesController/HRSuunti\", \"HR Suunti / Tikon tuonti\");\r\n        const map = {\r\n          PVM: \"date\",\r\n          TYNRO: \"srcEmploymentId\",\r\n          PLNRO: \"srcRowTypeId\",\r\n          TVR: null,\r\n          \"KPL/MISTÄ\": \"count\",\r\n          \"AIKA/MIHIN\": null,\r\n          \"MK/EUR\": null,\r\n          \"OSASTO\": \"costCenter\",\r\n        };\r\n        await mapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"SalaryBasesRow\", \"target\");\r\n        mapper.setPaths(map);\r\n        mapper.generateSchema(\"HRSuuntiTikon\", \"source\");\r\n        return mapper;\r\n      },\r\n      parsers: FileParser.getDefaultParsers(),\r\n      finalize: (items) => {\r\n        this.current.rows = items;\r\n        this.currentTab = \"rows\";\r\n        return Promise.resolve();\r\n      },\r\n      validate: (item: SalaryBasesRow, ix): Promise<{item: SalaryBasesRow, validation: ApiValidation }> => {\r\n        const validation: ApiValidation = {};\r\n        const helper = new ValidationHelper(validation);\r\n        if (this.employments?.length) {\r\n          HrSuuntiImportLogic.resolveEmployment(item, this.employments);\r\n          helper.checkNotEmpty(item, \"employmentId\", `Työntekijää ei löydy: ${item.srcEmploymentId}.`);\r\n        } else {\r\n          if (ix == 0) {\r\n            helper.error(\"Ei työsuhteita - tietoja ei voi tuoda! Hae ensin työsuhteet ja tuo rivit vasta sen jälkeen.\", \"Ei työsuhteita\");\r\n          }\r\n        }\r\n\r\n        helper.checkNotEmpty(item, \"srcRowTypeId\", \"TYNRO (srcRowTypeId) puuttuu\");\r\n        helper.checkNotEmpty(item, \"date\", \"PVM (date) puuttuu\");\r\n        helper.checkNotEmpty(item, \"srcRowTypeId\", \"PLNRO (srcRowTypeId) puuttuu\");\r\n        helper.checkNotEmpty(item, \"count\", \"KPL/MISTÄ (count) puuttuu\");\r\n        helper.checkNotEmpty(item, \"costCenter\", \"OSASTO (costCenter) puuttuu\");\r\n        helper.recalc();\r\n        return Promise.resolve({ item, validation });\r\n      },\r\n    };\r\n    return result;\r\n  }\r\n\r\n  /** Saves the dataset. */\r\n  public save(): void {\r\n    const loader = this.uiHelpers.showLoading(\"Tallennetaan\");\r\n    this.dataset.data[0].content.forEach((row) => {\r\n      Object.keys(row).filter((key) => key[0] == \"$\") .forEach((key) => {\r\n        delete row[key];\r\n      });\r\n    });\r\n    this.datasetsApi.save(this.dataset).then((result) => {\r\n      this.dataset = result;\r\n      loader.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Processes the import  */\r\n  public processImport() {\r\n    if (!this.current.rows?.length) {\r\n      alert(\"Hae ensin työsuhteet (1.) ja lataa data (2.)!\");\r\n      return;\r\n    }\r\n\r\n    // TODO: Copying is done so that String => RegEx is not saved. Handle this in core.\r\n    const mapper = angular.copy(this.getRowTypeMapper());\r\n    HrSuuntiImportLogic.resolveTypesAndPrices(this.current.rows, mapper);\r\n    this.currentTab = \"rows\";\r\n  }\r\n\r\n  /** Saves the rows to the given payroll */\r\n  public saveToPayroll() {\r\n    if ((this.payrollController?.currentId || \"new\") == \"new\") {\r\n      alert(\"Palkkalista ei ole vielä ladattu! Ei voi tallentaa!\");\r\n      return;\r\n    }\r\n    if (!this.current?.rows?.length) {\r\n      alert(\"Ei rivejä!\");\r\n      return;\r\n    }\r\n    const rows = this.current.rows.filter((x) => x.rowType && x.rowType != CalculationRowType.Unknown);\r\n    const loader = this.uiHelpers.showLoading(\"Tallennetaan palkkalistaa\");\r\n    HrSuuntiImportLogic.addToPayroll(this.payrollController.currentId, rows, this.employments, this.ajax).then((x) => {\r\n      loader.dismiss();\r\n      alert(\"Rivit on tallennettu palkkalistaan: \" + x.id);\r\n      this.currentTab = \"payroll\";\r\n      this.payrollController.reload();\r\n    });\r\n  }\r\n\r\n\r\n  /** Shows a dialog box for editing the employment. */\r\n  public editEmployment(row: Employment) {\r\n    this.uiCrudHelpers.openEditEmploymentDialog(row.id, \"updateCalc\").then((result) => {\r\n      if (result.action == EditDialogKnownActions.Ok) {\r\n        angular.merge(row, result.item);\r\n      }\r\n    });\r\n  }\r\n}\r\n","/*!\n * @kurkle/color v0.3.2\n * https://github.com/kurkle/color#readme\n * (c) 2023 Jukka Kurkela\n * Released under the MIT License\n */\nfunction round(v) {\n  return v + 0.5 | 0;\n}\nconst lim = (v, l, h) => Math.max(Math.min(v, h), l);\nfunction p2b(v) {\n  return lim(round(v * 2.55), 0, 255);\n}\nfunction b2p(v) {\n  return lim(round(v / 2.55), 0, 100);\n}\nfunction n2b(v) {\n  return lim(round(v * 255), 0, 255);\n}\nfunction b2n(v) {\n  return lim(round(v / 2.55) / 100, 0, 1);\n}\nfunction n2p(v) {\n  return lim(round(v * 100), 0, 100);\n}\n\nconst map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15};\nconst hex = [...'0123456789ABCDEF'];\nconst h1 = b => hex[b & 0xF];\nconst h2 = b => hex[(b & 0xF0) >> 4] + hex[b & 0xF];\nconst eq = b => ((b & 0xF0) >> 4) === (b & 0xF);\nconst isShort = v => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a);\nfunction hexParse(str) {\n  var len = str.length;\n  var ret;\n  if (str[0] === '#') {\n    if (len === 4 || len === 5) {\n      ret = {\n        r: 255 & map$1[str[1]] * 17,\n        g: 255 & map$1[str[2]] * 17,\n        b: 255 & map$1[str[3]] * 17,\n        a: len === 5 ? map$1[str[4]] * 17 : 255\n      };\n    } else if (len === 7 || len === 9) {\n      ret = {\n        r: map$1[str[1]] << 4 | map$1[str[2]],\n        g: map$1[str[3]] << 4 | map$1[str[4]],\n        b: map$1[str[5]] << 4 | map$1[str[6]],\n        a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255\n      };\n    }\n  }\n  return ret;\n}\nconst alpha = (a, f) => a < 255 ? f(a) : '';\nfunction hexString(v) {\n  var f = isShort(v) ? h1 : h2;\n  return v\n    ? '#' + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f)\n    : undefined;\n}\n\nconst HUE_RE = /^(hsla?|hwb|hsv)\\(\\s*([-+.e\\d]+)(?:deg)?[\\s,]+([-+.e\\d]+)%[\\s,]+([-+.e\\d]+)%(?:[\\s,]+([-+.e\\d]+)(%)?)?\\s*\\)$/;\nfunction hsl2rgbn(h, s, l) {\n  const a = s * Math.min(l, 1 - l);\n  const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n  return [f(0), f(8), f(4)];\n}\nfunction hsv2rgbn(h, s, v) {\n  const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);\n  return [f(5), f(3), f(1)];\n}\nfunction hwb2rgbn(h, w, b) {\n  const rgb = hsl2rgbn(h, 1, 0.5);\n  let i;\n  if (w + b > 1) {\n    i = 1 / (w + b);\n    w *= i;\n    b *= i;\n  }\n  for (i = 0; i < 3; i++) {\n    rgb[i] *= 1 - w - b;\n    rgb[i] += w;\n  }\n  return rgb;\n}\nfunction hueValue(r, g, b, d, max) {\n  if (r === max) {\n    return ((g - b) / d) + (g < b ? 6 : 0);\n  }\n  if (g === max) {\n    return (b - r) / d + 2;\n  }\n  return (r - g) / d + 4;\n}\nfunction rgb2hsl(v) {\n  const range = 255;\n  const r = v.r / range;\n  const g = v.g / range;\n  const b = v.b / range;\n  const max = Math.max(r, g, b);\n  const min = Math.min(r, g, b);\n  const l = (max + min) / 2;\n  let h, s, d;\n  if (max !== min) {\n    d = max - min;\n    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n    h = hueValue(r, g, b, d, max);\n    h = h * 60 + 0.5;\n  }\n  return [h | 0, s || 0, l];\n}\nfunction calln(f, a, b, c) {\n  return (\n    Array.isArray(a)\n      ? f(a[0], a[1], a[2])\n      : f(a, b, c)\n  ).map(n2b);\n}\nfunction hsl2rgb(h, s, l) {\n  return calln(hsl2rgbn, h, s, l);\n}\nfunction hwb2rgb(h, w, b) {\n  return calln(hwb2rgbn, h, w, b);\n}\nfunction hsv2rgb(h, s, v) {\n  return calln(hsv2rgbn, h, s, v);\n}\nfunction hue(h) {\n  return (h % 360 + 360) % 360;\n}\nfunction hueParse(str) {\n  const m = HUE_RE.exec(str);\n  let a = 255;\n  let v;\n  if (!m) {\n    return;\n  }\n  if (m[5] !== v) {\n    a = m[6] ? p2b(+m[5]) : n2b(+m[5]);\n  }\n  const h = hue(+m[2]);\n  const p1 = +m[3] / 100;\n  const p2 = +m[4] / 100;\n  if (m[1] === 'hwb') {\n    v = hwb2rgb(h, p1, p2);\n  } else if (m[1] === 'hsv') {\n    v = hsv2rgb(h, p1, p2);\n  } else {\n    v = hsl2rgb(h, p1, p2);\n  }\n  return {\n    r: v[0],\n    g: v[1],\n    b: v[2],\n    a: a\n  };\n}\nfunction rotate(v, deg) {\n  var h = rgb2hsl(v);\n  h[0] = hue(h[0] + deg);\n  h = hsl2rgb(h);\n  v.r = h[0];\n  v.g = h[1];\n  v.b = h[2];\n}\nfunction hslString(v) {\n  if (!v) {\n    return;\n  }\n  const a = rgb2hsl(v);\n  const h = a[0];\n  const s = n2p(a[1]);\n  const l = n2p(a[2]);\n  return v.a < 255\n    ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})`\n    : `hsl(${h}, ${s}%, ${l}%)`;\n}\n\nconst map = {\n  x: 'dark',\n  Z: 'light',\n  Y: 're',\n  X: 'blu',\n  W: 'gr',\n  V: 'medium',\n  U: 'slate',\n  A: 'ee',\n  T: 'ol',\n  S: 'or',\n  B: 'ra',\n  C: 'lateg',\n  D: 'ights',\n  R: 'in',\n  Q: 'turquois',\n  E: 'hi',\n  P: 'ro',\n  O: 'al',\n  N: 'le',\n  M: 'de',\n  L: 'yello',\n  F: 'en',\n  K: 'ch',\n  G: 'arks',\n  H: 'ea',\n  I: 'ightg',\n  J: 'wh'\n};\nconst names$1 = {\n  OiceXe: 'f0f8ff',\n  antiquewEte: 'faebd7',\n  aqua: 'ffff',\n  aquamarRe: '7fffd4',\n  azuY: 'f0ffff',\n  beige: 'f5f5dc',\n  bisque: 'ffe4c4',\n  black: '0',\n  blanKedOmond: 'ffebcd',\n  Xe: 'ff',\n  XeviTet: '8a2be2',\n  bPwn: 'a52a2a',\n  burlywood: 'deb887',\n  caMtXe: '5f9ea0',\n  KartYuse: '7fff00',\n  KocTate: 'd2691e',\n  cSO: 'ff7f50',\n  cSnflowerXe: '6495ed',\n  cSnsilk: 'fff8dc',\n  crimson: 'dc143c',\n  cyan: 'ffff',\n  xXe: '8b',\n  xcyan: '8b8b',\n  xgTMnPd: 'b8860b',\n  xWay: 'a9a9a9',\n  xgYF: '6400',\n  xgYy: 'a9a9a9',\n  xkhaki: 'bdb76b',\n  xmagFta: '8b008b',\n  xTivegYF: '556b2f',\n  xSange: 'ff8c00',\n  xScEd: '9932cc',\n  xYd: '8b0000',\n  xsOmon: 'e9967a',\n  xsHgYF: '8fbc8f',\n  xUXe: '483d8b',\n  xUWay: '2f4f4f',\n  xUgYy: '2f4f4f',\n  xQe: 'ced1',\n  xviTet: '9400d3',\n  dAppRk: 'ff1493',\n  dApskyXe: 'bfff',\n  dimWay: '696969',\n  dimgYy: '696969',\n  dodgerXe: '1e90ff',\n  fiYbrick: 'b22222',\n  flSOwEte: 'fffaf0',\n  foYstWAn: '228b22',\n  fuKsia: 'ff00ff',\n  gaRsbSo: 'dcdcdc',\n  ghostwEte: 'f8f8ff',\n  gTd: 'ffd700',\n  gTMnPd: 'daa520',\n  Way: '808080',\n  gYF: '8000',\n  gYFLw: 'adff2f',\n  gYy: '808080',\n  honeyMw: 'f0fff0',\n  hotpRk: 'ff69b4',\n  RdianYd: 'cd5c5c',\n  Rdigo: '4b0082',\n  ivSy: 'fffff0',\n  khaki: 'f0e68c',\n  lavFMr: 'e6e6fa',\n  lavFMrXsh: 'fff0f5',\n  lawngYF: '7cfc00',\n  NmoncEffon: 'fffacd',\n  ZXe: 'add8e6',\n  ZcSO: 'f08080',\n  Zcyan: 'e0ffff',\n  ZgTMnPdLw: 'fafad2',\n  ZWay: 'd3d3d3',\n  ZgYF: '90ee90',\n  ZgYy: 'd3d3d3',\n  ZpRk: 'ffb6c1',\n  ZsOmon: 'ffa07a',\n  ZsHgYF: '20b2aa',\n  ZskyXe: '87cefa',\n  ZUWay: '778899',\n  ZUgYy: '778899',\n  ZstAlXe: 'b0c4de',\n  ZLw: 'ffffe0',\n  lime: 'ff00',\n  limegYF: '32cd32',\n  lRF: 'faf0e6',\n  magFta: 'ff00ff',\n  maPon: '800000',\n  VaquamarRe: '66cdaa',\n  VXe: 'cd',\n  VScEd: 'ba55d3',\n  VpurpN: '9370db',\n  VsHgYF: '3cb371',\n  VUXe: '7b68ee',\n  VsprRggYF: 'fa9a',\n  VQe: '48d1cc',\n  VviTetYd: 'c71585',\n  midnightXe: '191970',\n  mRtcYam: 'f5fffa',\n  mistyPse: 'ffe4e1',\n  moccasR: 'ffe4b5',\n  navajowEte: 'ffdead',\n  navy: '80',\n  Tdlace: 'fdf5e6',\n  Tive: '808000',\n  TivedBb: '6b8e23',\n  Sange: 'ffa500',\n  SangeYd: 'ff4500',\n  ScEd: 'da70d6',\n  pOegTMnPd: 'eee8aa',\n  pOegYF: '98fb98',\n  pOeQe: 'afeeee',\n  pOeviTetYd: 'db7093',\n  papayawEp: 'ffefd5',\n  pHKpuff: 'ffdab9',\n  peru: 'cd853f',\n  pRk: 'ffc0cb',\n  plum: 'dda0dd',\n  powMrXe: 'b0e0e6',\n  purpN: '800080',\n  YbeccapurpN: '663399',\n  Yd: 'ff0000',\n  Psybrown: 'bc8f8f',\n  PyOXe: '4169e1',\n  saddNbPwn: '8b4513',\n  sOmon: 'fa8072',\n  sandybPwn: 'f4a460',\n  sHgYF: '2e8b57',\n  sHshell: 'fff5ee',\n  siFna: 'a0522d',\n  silver: 'c0c0c0',\n  skyXe: '87ceeb',\n  UXe: '6a5acd',\n  UWay: '708090',\n  UgYy: '708090',\n  snow: 'fffafa',\n  sprRggYF: 'ff7f',\n  stAlXe: '4682b4',\n  tan: 'd2b48c',\n  teO: '8080',\n  tEstN: 'd8bfd8',\n  tomato: 'ff6347',\n  Qe: '40e0d0',\n  viTet: 'ee82ee',\n  JHt: 'f5deb3',\n  wEte: 'ffffff',\n  wEtesmoke: 'f5f5f5',\n  Lw: 'ffff00',\n  LwgYF: '9acd32'\n};\nfunction unpack() {\n  const unpacked = {};\n  const keys = Object.keys(names$1);\n  const tkeys = Object.keys(map);\n  let i, j, k, ok, nk;\n  for (i = 0; i < keys.length; i++) {\n    ok = nk = keys[i];\n    for (j = 0; j < tkeys.length; j++) {\n      k = tkeys[j];\n      nk = nk.replace(k, map[k]);\n    }\n    k = parseInt(names$1[ok], 16);\n    unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF];\n  }\n  return unpacked;\n}\n\nlet names;\nfunction nameParse(str) {\n  if (!names) {\n    names = unpack();\n    names.transparent = [0, 0, 0, 0];\n  }\n  const a = names[str.toLowerCase()];\n  return a && {\n    r: a[0],\n    g: a[1],\n    b: a[2],\n    a: a.length === 4 ? a[3] : 255\n  };\n}\n\nconst RGB_RE = /^rgba?\\(\\s*([-+.\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?[\\s,]+([-+.e\\d]+)(%)?(?:[\\s,/]+([-+.e\\d]+)(%)?)?\\s*\\)$/;\nfunction rgbParse(str) {\n  const m = RGB_RE.exec(str);\n  let a = 255;\n  let r, g, b;\n  if (!m) {\n    return;\n  }\n  if (m[7] !== r) {\n    const v = +m[7];\n    a = m[8] ? p2b(v) : lim(v * 255, 0, 255);\n  }\n  r = +m[1];\n  g = +m[3];\n  b = +m[5];\n  r = 255 & (m[2] ? p2b(r) : lim(r, 0, 255));\n  g = 255 & (m[4] ? p2b(g) : lim(g, 0, 255));\n  b = 255 & (m[6] ? p2b(b) : lim(b, 0, 255));\n  return {\n    r: r,\n    g: g,\n    b: b,\n    a: a\n  };\n}\nfunction rgbString(v) {\n  return v && (\n    v.a < 255\n      ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`\n      : `rgb(${v.r}, ${v.g}, ${v.b})`\n  );\n}\n\nconst to = v => v <= 0.0031308 ? v * 12.92 : Math.pow(v, 1.0 / 2.4) * 1.055 - 0.055;\nconst from = v => v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\nfunction interpolate(rgb1, rgb2, t) {\n  const r = from(b2n(rgb1.r));\n  const g = from(b2n(rgb1.g));\n  const b = from(b2n(rgb1.b));\n  return {\n    r: n2b(to(r + t * (from(b2n(rgb2.r)) - r))),\n    g: n2b(to(g + t * (from(b2n(rgb2.g)) - g))),\n    b: n2b(to(b + t * (from(b2n(rgb2.b)) - b))),\n    a: rgb1.a + t * (rgb2.a - rgb1.a)\n  };\n}\n\nfunction modHSL(v, i, ratio) {\n  if (v) {\n    let tmp = rgb2hsl(v);\n    tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));\n    tmp = hsl2rgb(tmp);\n    v.r = tmp[0];\n    v.g = tmp[1];\n    v.b = tmp[2];\n  }\n}\nfunction clone(v, proto) {\n  return v ? Object.assign(proto || {}, v) : v;\n}\nfunction fromObject(input) {\n  var v = {r: 0, g: 0, b: 0, a: 255};\n  if (Array.isArray(input)) {\n    if (input.length >= 3) {\n      v = {r: input[0], g: input[1], b: input[2], a: 255};\n      if (input.length > 3) {\n        v.a = n2b(input[3]);\n      }\n    }\n  } else {\n    v = clone(input, {r: 0, g: 0, b: 0, a: 1});\n    v.a = n2b(v.a);\n  }\n  return v;\n}\nfunction functionParse(str) {\n  if (str.charAt(0) === 'r') {\n    return rgbParse(str);\n  }\n  return hueParse(str);\n}\nclass Color {\n  constructor(input) {\n    if (input instanceof Color) {\n      return input;\n    }\n    const type = typeof input;\n    let v;\n    if (type === 'object') {\n      v = fromObject(input);\n    } else if (type === 'string') {\n      v = hexParse(input) || nameParse(input) || functionParse(input);\n    }\n    this._rgb = v;\n    this._valid = !!v;\n  }\n  get valid() {\n    return this._valid;\n  }\n  get rgb() {\n    var v = clone(this._rgb);\n    if (v) {\n      v.a = b2n(v.a);\n    }\n    return v;\n  }\n  set rgb(obj) {\n    this._rgb = fromObject(obj);\n  }\n  rgbString() {\n    return this._valid ? rgbString(this._rgb) : undefined;\n  }\n  hexString() {\n    return this._valid ? hexString(this._rgb) : undefined;\n  }\n  hslString() {\n    return this._valid ? hslString(this._rgb) : undefined;\n  }\n  mix(color, weight) {\n    if (color) {\n      const c1 = this.rgb;\n      const c2 = color.rgb;\n      let w2;\n      const p = weight === w2 ? 0.5 : weight;\n      const w = 2 * p - 1;\n      const a = c1.a - c2.a;\n      const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\n      w2 = 1 - w1;\n      c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;\n      c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;\n      c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;\n      c1.a = p * c1.a + (1 - p) * c2.a;\n      this.rgb = c1;\n    }\n    return this;\n  }\n  interpolate(color, t) {\n    if (color) {\n      this._rgb = interpolate(this._rgb, color._rgb, t);\n    }\n    return this;\n  }\n  clone() {\n    return new Color(this.rgb);\n  }\n  alpha(a) {\n    this._rgb.a = n2b(a);\n    return this;\n  }\n  clearer(ratio) {\n    const rgb = this._rgb;\n    rgb.a *= 1 - ratio;\n    return this;\n  }\n  greyscale() {\n    const rgb = this._rgb;\n    const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);\n    rgb.r = rgb.g = rgb.b = val;\n    return this;\n  }\n  opaquer(ratio) {\n    const rgb = this._rgb;\n    rgb.a *= 1 + ratio;\n    return this;\n  }\n  negate() {\n    const v = this._rgb;\n    v.r = 255 - v.r;\n    v.g = 255 - v.g;\n    v.b = 255 - v.b;\n    return this;\n  }\n  lighten(ratio) {\n    modHSL(this._rgb, 2, ratio);\n    return this;\n  }\n  darken(ratio) {\n    modHSL(this._rgb, 2, -ratio);\n    return this;\n  }\n  saturate(ratio) {\n    modHSL(this._rgb, 1, ratio);\n    return this;\n  }\n  desaturate(ratio) {\n    modHSL(this._rgb, 1, -ratio);\n    return this;\n  }\n  rotate(deg) {\n    rotate(this._rgb, deg);\n    return this;\n  }\n}\n\nfunction index_esm(input) {\n  return new Color(input);\n}\n\nexport { Color, b2n, b2p, index_esm as default, hexParse, hexString, hsl2rgb, hslString, hsv2rgb, hueParse, hwb2rgb, lim, n2b, n2p, nameParse, p2b, rgb2hsl, rgbParse, rgbString, rotate, round };\n","/*!\n * Chart.js v4.4.2\n * https://www.chartjs.org\n * (c) 2024 Chart.js Contributors\n * Released under the MIT License\n */\nimport { Color } from '@kurkle/color';\n\n/**\n * @namespace Chart.helpers\n */ /**\n * An empty function that can be used, for example, for optional callback.\n */ function noop() {\n/* noop */ }\n/**\n * Returns a unique id, sequentially generated from a global variable.\n */ const uid = (()=>{\n    let id = 0;\n    return ()=>id++;\n})();\n/**\n * Returns true if `value` is neither null nor undefined, else returns false.\n * @param value - The value to test.\n * @since 2.7.0\n */ function isNullOrUndef(value) {\n    return value === null || typeof value === 'undefined';\n}\n/**\n * Returns true if `value` is an array (including typed arrays), else returns false.\n * @param value - The value to test.\n * @function\n */ function isArray(value) {\n    if (Array.isArray && Array.isArray(value)) {\n        return true;\n    }\n    const type = Object.prototype.toString.call(value);\n    if (type.slice(0, 7) === '[object' && type.slice(-6) === 'Array]') {\n        return true;\n    }\n    return false;\n}\n/**\n * Returns true if `value` is an object (excluding null), else returns false.\n * @param value - The value to test.\n * @since 2.7.0\n */ function isObject(value) {\n    return value !== null && Object.prototype.toString.call(value) === '[object Object]';\n}\n/**\n * Returns true if `value` is a finite number, else returns false\n * @param value  - The value to test.\n */ function isNumberFinite(value) {\n    return (typeof value === 'number' || value instanceof Number) && isFinite(+value);\n}\n/**\n * Returns `value` if finite, else returns `defaultValue`.\n * @param value - The value to return if defined.\n * @param defaultValue - The value to return if `value` is not finite.\n */ function finiteOrDefault(value, defaultValue) {\n    return isNumberFinite(value) ? value : defaultValue;\n}\n/**\n * Returns `value` if defined, else returns `defaultValue`.\n * @param value - The value to return if defined.\n * @param defaultValue - The value to return if `value` is undefined.\n */ function valueOrDefault(value, defaultValue) {\n    return typeof value === 'undefined' ? defaultValue : value;\n}\nconst toPercentage = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 : +value / dimension;\nconst toDimension = (value, dimension)=>typeof value === 'string' && value.endsWith('%') ? parseFloat(value) / 100 * dimension : +value;\n/**\n * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the\n * value returned by `fn`. If `fn` is not a function, this method returns undefined.\n * @param fn - The function to call.\n * @param args - The arguments with which `fn` should be called.\n * @param [thisArg] - The value of `this` provided for the call to `fn`.\n */ function callback(fn, args, thisArg) {\n    if (fn && typeof fn.call === 'function') {\n        return fn.apply(thisArg, args);\n    }\n}\nfunction each(loopable, fn, thisArg, reverse) {\n    let i, len, keys;\n    if (isArray(loopable)) {\n        len = loopable.length;\n        if (reverse) {\n            for(i = len - 1; i >= 0; i--){\n                fn.call(thisArg, loopable[i], i);\n            }\n        } else {\n            for(i = 0; i < len; i++){\n                fn.call(thisArg, loopable[i], i);\n            }\n        }\n    } else if (isObject(loopable)) {\n        keys = Object.keys(loopable);\n        len = keys.length;\n        for(i = 0; i < len; i++){\n            fn.call(thisArg, loopable[keys[i]], keys[i]);\n        }\n    }\n}\n/**\n * Returns true if the `a0` and `a1` arrays have the same content, else returns false.\n * @param a0 - The array to compare\n * @param a1 - The array to compare\n * @private\n */ function _elementsEqual(a0, a1) {\n    let i, ilen, v0, v1;\n    if (!a0 || !a1 || a0.length !== a1.length) {\n        return false;\n    }\n    for(i = 0, ilen = a0.length; i < ilen; ++i){\n        v0 = a0[i];\n        v1 = a1[i];\n        if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {\n            return false;\n        }\n    }\n    return true;\n}\n/**\n * Returns a deep copy of `source` without keeping references on objects and arrays.\n * @param source - The value to clone.\n */ function clone(source) {\n    if (isArray(source)) {\n        return source.map(clone);\n    }\n    if (isObject(source)) {\n        const target = Object.create(null);\n        const keys = Object.keys(source);\n        const klen = keys.length;\n        let k = 0;\n        for(; k < klen; ++k){\n            target[keys[k]] = clone(source[keys[k]]);\n        }\n        return target;\n    }\n    return source;\n}\nfunction isValidKey(key) {\n    return [\n        '__proto__',\n        'prototype',\n        'constructor'\n    ].indexOf(key) === -1;\n}\n/**\n * The default merger when Chart.helpers.merge is called without merger option.\n * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.\n * @private\n */ function _merger(key, target, source, options) {\n    if (!isValidKey(key)) {\n        return;\n    }\n    const tval = target[key];\n    const sval = source[key];\n    if (isObject(tval) && isObject(sval)) {\n        // eslint-disable-next-line @typescript-eslint/no-use-before-define\n        merge(tval, sval, options);\n    } else {\n        target[key] = clone(sval);\n    }\n}\nfunction merge(target, source, options) {\n    const sources = isArray(source) ? source : [\n        source\n    ];\n    const ilen = sources.length;\n    if (!isObject(target)) {\n        return target;\n    }\n    options = options || {};\n    const merger = options.merger || _merger;\n    let current;\n    for(let i = 0; i < ilen; ++i){\n        current = sources[i];\n        if (!isObject(current)) {\n            continue;\n        }\n        const keys = Object.keys(current);\n        for(let k = 0, klen = keys.length; k < klen; ++k){\n            merger(keys[k], target, current, options);\n        }\n    }\n    return target;\n}\nfunction mergeIf(target, source) {\n    // eslint-disable-next-line @typescript-eslint/no-use-before-define\n    return merge(target, source, {\n        merger: _mergerIf\n    });\n}\n/**\n * Merges source[key] in target[key] only if target[key] is undefined.\n * @private\n */ function _mergerIf(key, target, source) {\n    if (!isValidKey(key)) {\n        return;\n    }\n    const tval = target[key];\n    const sval = source[key];\n    if (isObject(tval) && isObject(sval)) {\n        mergeIf(tval, sval);\n    } else if (!Object.prototype.hasOwnProperty.call(target, key)) {\n        target[key] = clone(sval);\n    }\n}\n/**\n * @private\n */ function _deprecated(scope, value, previous, current) {\n    if (value !== undefined) {\n        console.warn(scope + ': \"' + previous + '\" is deprecated. Please use \"' + current + '\" instead');\n    }\n}\n// resolveObjectKey resolver cache\nconst keyResolvers = {\n    // Chart.helpers.core resolveObjectKey should resolve empty key to root object\n    '': (v)=>v,\n    // default resolvers\n    x: (o)=>o.x,\n    y: (o)=>o.y\n};\n/**\n * @private\n */ function _splitKey(key) {\n    const parts = key.split('.');\n    const keys = [];\n    let tmp = '';\n    for (const part of parts){\n        tmp += part;\n        if (tmp.endsWith('\\\\')) {\n            tmp = tmp.slice(0, -1) + '.';\n        } else {\n            keys.push(tmp);\n            tmp = '';\n        }\n    }\n    return keys;\n}\nfunction _getKeyResolver(key) {\n    const keys = _splitKey(key);\n    return (obj)=>{\n        for (const k of keys){\n            if (k === '') {\n                break;\n            }\n            obj = obj && obj[k];\n        }\n        return obj;\n    };\n}\nfunction resolveObjectKey(obj, key) {\n    const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key));\n    return resolver(obj);\n}\n/**\n * @private\n */ function _capitalize(str) {\n    return str.charAt(0).toUpperCase() + str.slice(1);\n}\nconst defined = (value)=>typeof value !== 'undefined';\nconst isFunction = (value)=>typeof value === 'function';\n// Adapted from https://stackoverflow.com/questions/31128855/comparing-ecma6-sets-for-equality#31129384\nconst setsEqual = (a, b)=>{\n    if (a.size !== b.size) {\n        return false;\n    }\n    for (const item of a){\n        if (!b.has(item)) {\n            return false;\n        }\n    }\n    return true;\n};\n/**\n * @param e - The event\n * @private\n */ function _isClickEvent(e) {\n    return e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu';\n}\n\n/**\n * @alias Chart.helpers.math\n * @namespace\n */ const PI = Math.PI;\nconst TAU = 2 * PI;\nconst PITAU = TAU + PI;\nconst INFINITY = Number.POSITIVE_INFINITY;\nconst RAD_PER_DEG = PI / 180;\nconst HALF_PI = PI / 2;\nconst QUARTER_PI = PI / 4;\nconst TWO_THIRDS_PI = PI * 2 / 3;\nconst log10 = Math.log10;\nconst sign = Math.sign;\nfunction almostEquals(x, y, epsilon) {\n    return Math.abs(x - y) < epsilon;\n}\n/**\n * Implementation of the nice number algorithm used in determining where axis labels will go\n */ function niceNum(range) {\n    const roundedRange = Math.round(range);\n    range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range;\n    const niceRange = Math.pow(10, Math.floor(log10(range)));\n    const fraction = range / niceRange;\n    const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;\n    return niceFraction * niceRange;\n}\n/**\n * Returns an array of factors sorted from 1 to sqrt(value)\n * @private\n */ function _factorize(value) {\n    const result = [];\n    const sqrt = Math.sqrt(value);\n    let i;\n    for(i = 1; i < sqrt; i++){\n        if (value % i === 0) {\n            result.push(i);\n            result.push(value / i);\n        }\n    }\n    if (sqrt === (sqrt | 0)) {\n        result.push(sqrt);\n    }\n    result.sort((a, b)=>a - b).pop();\n    return result;\n}\nfunction isNumber(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n}\nfunction almostWhole(x, epsilon) {\n    const rounded = Math.round(x);\n    return rounded - epsilon <= x && rounded + epsilon >= x;\n}\n/**\n * @private\n */ function _setMinAndMaxByKey(array, target, property) {\n    let i, ilen, value;\n    for(i = 0, ilen = array.length; i < ilen; i++){\n        value = array[i][property];\n        if (!isNaN(value)) {\n            target.min = Math.min(target.min, value);\n            target.max = Math.max(target.max, value);\n        }\n    }\n}\nfunction toRadians(degrees) {\n    return degrees * (PI / 180);\n}\nfunction toDegrees(radians) {\n    return radians * (180 / PI);\n}\n/**\n * Returns the number of decimal places\n * i.e. the number of digits after the decimal point, of the value of this Number.\n * @param x - A number.\n * @returns The number of decimal places.\n * @private\n */ function _decimalPlaces(x) {\n    if (!isNumberFinite(x)) {\n        return;\n    }\n    let e = 1;\n    let p = 0;\n    while(Math.round(x * e) / e !== x){\n        e *= 10;\n        p++;\n    }\n    return p;\n}\n// Gets the angle from vertical upright to the point about a centre.\nfunction getAngleFromPoint(centrePoint, anglePoint) {\n    const distanceFromXCenter = anglePoint.x - centrePoint.x;\n    const distanceFromYCenter = anglePoint.y - centrePoint.y;\n    const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\n    let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);\n    if (angle < -0.5 * PI) {\n        angle += TAU; // make sure the returned angle is in the range of (-PI/2, 3PI/2]\n    }\n    return {\n        angle,\n        distance: radialDistanceFromCenter\n    };\n}\nfunction distanceBetweenPoints(pt1, pt2) {\n    return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));\n}\n/**\n * Shortest distance between angles, in either direction.\n * @private\n */ function _angleDiff(a, b) {\n    return (a - b + PITAU) % TAU - PI;\n}\n/**\n * Normalize angle to be between 0 and 2*PI\n * @private\n */ function _normalizeAngle(a) {\n    return (a % TAU + TAU) % TAU;\n}\n/**\n * @private\n */ function _angleBetween(angle, start, end, sameAngleIsFullCircle) {\n    const a = _normalizeAngle(angle);\n    const s = _normalizeAngle(start);\n    const e = _normalizeAngle(end);\n    const angleToStart = _normalizeAngle(s - a);\n    const angleToEnd = _normalizeAngle(e - a);\n    const startToAngle = _normalizeAngle(a - s);\n    const endToAngle = _normalizeAngle(a - e);\n    return a === s || a === e || sameAngleIsFullCircle && s === e || angleToStart > angleToEnd && startToAngle < endToAngle;\n}\n/**\n * Limit `value` between `min` and `max`\n * @param value\n * @param min\n * @param max\n * @private\n */ function _limitValue(value, min, max) {\n    return Math.max(min, Math.min(max, value));\n}\n/**\n * @param {number} value\n * @private\n */ function _int16Range(value) {\n    return _limitValue(value, -32768, 32767);\n}\n/**\n * @param value\n * @param start\n * @param end\n * @param [epsilon]\n * @private\n */ function _isBetween(value, start, end, epsilon = 1e-6) {\n    return value >= Math.min(start, end) - epsilon && value <= Math.max(start, end) + epsilon;\n}\n\nfunction _lookup(table, value, cmp) {\n    cmp = cmp || ((index)=>table[index] < value);\n    let hi = table.length - 1;\n    let lo = 0;\n    let mid;\n    while(hi - lo > 1){\n        mid = lo + hi >> 1;\n        if (cmp(mid)) {\n            lo = mid;\n        } else {\n            hi = mid;\n        }\n    }\n    return {\n        lo,\n        hi\n    };\n}\n/**\n * Binary search\n * @param table - the table search. must be sorted!\n * @param key - property name for the value in each entry\n * @param value - value to find\n * @param last - lookup last index\n * @private\n */ const _lookupByKey = (table, key, value, last)=>_lookup(table, value, last ? (index)=>{\n        const ti = table[index][key];\n        return ti < value || ti === value && table[index + 1][key] === value;\n    } : (index)=>table[index][key] < value);\n/**\n * Reverse binary search\n * @param table - the table search. must be sorted!\n * @param key - property name for the value in each entry\n * @param value - value to find\n * @private\n */ const _rlookupByKey = (table, key, value)=>_lookup(table, value, (index)=>table[index][key] >= value);\n/**\n * Return subset of `values` between `min` and `max` inclusive.\n * Values are assumed to be in sorted order.\n * @param values - sorted array of values\n * @param min - min value\n * @param max - max value\n */ function _filterBetween(values, min, max) {\n    let start = 0;\n    let end = values.length;\n    while(start < end && values[start] < min){\n        start++;\n    }\n    while(end > start && values[end - 1] > max){\n        end--;\n    }\n    return start > 0 || end < values.length ? values.slice(start, end) : values;\n}\nconst arrayEvents = [\n    'push',\n    'pop',\n    'shift',\n    'splice',\n    'unshift'\n];\nfunction listenArrayEvents(array, listener) {\n    if (array._chartjs) {\n        array._chartjs.listeners.push(listener);\n        return;\n    }\n    Object.defineProperty(array, '_chartjs', {\n        configurable: true,\n        enumerable: false,\n        value: {\n            listeners: [\n                listener\n            ]\n        }\n    });\n    arrayEvents.forEach((key)=>{\n        const method = '_onData' + _capitalize(key);\n        const base = array[key];\n        Object.defineProperty(array, key, {\n            configurable: true,\n            enumerable: false,\n            value (...args) {\n                const res = base.apply(this, args);\n                array._chartjs.listeners.forEach((object)=>{\n                    if (typeof object[method] === 'function') {\n                        object[method](...args);\n                    }\n                });\n                return res;\n            }\n        });\n    });\n}\nfunction unlistenArrayEvents(array, listener) {\n    const stub = array._chartjs;\n    if (!stub) {\n        return;\n    }\n    const listeners = stub.listeners;\n    const index = listeners.indexOf(listener);\n    if (index !== -1) {\n        listeners.splice(index, 1);\n    }\n    if (listeners.length > 0) {\n        return;\n    }\n    arrayEvents.forEach((key)=>{\n        delete array[key];\n    });\n    delete array._chartjs;\n}\n/**\n * @param items\n */ function _arrayUnique(items) {\n    const set = new Set(items);\n    if (set.size === items.length) {\n        return items;\n    }\n    return Array.from(set);\n}\n\nfunction fontString(pixelSize, fontStyle, fontFamily) {\n    return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;\n}\n/**\n* Request animation polyfill\n*/ const requestAnimFrame = function() {\n    if (typeof window === 'undefined') {\n        return function(callback) {\n            return callback();\n        };\n    }\n    return window.requestAnimationFrame;\n}();\n/**\n * Throttles calling `fn` once per animation frame\n * Latest arguments are used on the actual call\n */ function throttled(fn, thisArg) {\n    let argsToUse = [];\n    let ticking = false;\n    return function(...args) {\n        // Save the args for use later\n        argsToUse = args;\n        if (!ticking) {\n            ticking = true;\n            requestAnimFrame.call(window, ()=>{\n                ticking = false;\n                fn.apply(thisArg, argsToUse);\n            });\n        }\n    };\n}\n/**\n * Debounces calling `fn` for `delay` ms\n */ function debounce(fn, delay) {\n    let timeout;\n    return function(...args) {\n        if (delay) {\n            clearTimeout(timeout);\n            timeout = setTimeout(fn, delay, args);\n        } else {\n            fn.apply(this, args);\n        }\n        return delay;\n    };\n}\n/**\n * Converts 'start' to 'left', 'end' to 'right' and others to 'center'\n * @private\n */ const _toLeftRightCenter = (align)=>align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';\n/**\n * Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center`\n * @private\n */ const _alignStartEnd = (align, start, end)=>align === 'start' ? start : align === 'end' ? end : (start + end) / 2;\n/**\n * Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left`\n * @private\n */ const _textX = (align, left, right, rtl)=>{\n    const check = rtl ? 'left' : 'right';\n    return align === check ? right : align === 'center' ? (left + right) / 2 : left;\n};\n/**\n * Return start and count of visible points.\n * @private\n */ function _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) {\n    const pointCount = points.length;\n    let start = 0;\n    let count = pointCount;\n    if (meta._sorted) {\n        const { iScale , _parsed  } = meta;\n        const axis = iScale.axis;\n        const { min , max , minDefined , maxDefined  } = iScale.getUserBounds();\n        if (minDefined) {\n            start = _limitValue(Math.min(// @ts-expect-error Need to type _parsed\n            _lookupByKey(_parsed, axis, min).lo, // @ts-expect-error Need to fix types on _lookupByKey\n            animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo), 0, pointCount - 1);\n        }\n        if (maxDefined) {\n            count = _limitValue(Math.max(// @ts-expect-error Need to type _parsed\n            _lookupByKey(_parsed, iScale.axis, max, true).hi + 1, // @ts-expect-error Need to fix types on _lookupByKey\n            animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max), true).hi + 1), start, pointCount) - start;\n        } else {\n            count = pointCount - start;\n        }\n    }\n    return {\n        start,\n        count\n    };\n}\n/**\n * Checks if the scale ranges have changed.\n * @param {object} meta - dataset meta.\n * @returns {boolean}\n * @private\n */ function _scaleRangesChanged(meta) {\n    const { xScale , yScale , _scaleRanges  } = meta;\n    const newRanges = {\n        xmin: xScale.min,\n        xmax: xScale.max,\n        ymin: yScale.min,\n        ymax: yScale.max\n    };\n    if (!_scaleRanges) {\n        meta._scaleRanges = newRanges;\n        return true;\n    }\n    const changed = _scaleRanges.xmin !== xScale.min || _scaleRanges.xmax !== xScale.max || _scaleRanges.ymin !== yScale.min || _scaleRanges.ymax !== yScale.max;\n    Object.assign(_scaleRanges, newRanges);\n    return changed;\n}\n\nconst atEdge = (t)=>t === 0 || t === 1;\nconst elasticIn = (t, s, p)=>-(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p));\nconst elasticOut = (t, s, p)=>Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1;\n/**\n * Easing functions adapted from Robert Penner's easing equations.\n * @namespace Chart.helpers.easing.effects\n * @see http://www.robertpenner.com/easing/\n */ const effects = {\n    linear: (t)=>t,\n    easeInQuad: (t)=>t * t,\n    easeOutQuad: (t)=>-t * (t - 2),\n    easeInOutQuad: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1),\n    easeInCubic: (t)=>t * t * t,\n    easeOutCubic: (t)=>(t -= 1) * t * t + 1,\n    easeInOutCubic: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2),\n    easeInQuart: (t)=>t * t * t * t,\n    easeOutQuart: (t)=>-((t -= 1) * t * t * t - 1),\n    easeInOutQuart: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2),\n    easeInQuint: (t)=>t * t * t * t * t,\n    easeOutQuint: (t)=>(t -= 1) * t * t * t * t + 1,\n    easeInOutQuint: (t)=>(t /= 0.5) < 1 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2),\n    easeInSine: (t)=>-Math.cos(t * HALF_PI) + 1,\n    easeOutSine: (t)=>Math.sin(t * HALF_PI),\n    easeInOutSine: (t)=>-0.5 * (Math.cos(PI * t) - 1),\n    easeInExpo: (t)=>t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),\n    easeOutExpo: (t)=>t === 1 ? 1 : -Math.pow(2, -10 * t) + 1,\n    easeInOutExpo: (t)=>atEdge(t) ? t : t < 0.5 ? 0.5 * Math.pow(2, 10 * (t * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2),\n    easeInCirc: (t)=>t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1),\n    easeOutCirc: (t)=>Math.sqrt(1 - (t -= 1) * t),\n    easeInOutCirc: (t)=>(t /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),\n    easeInElastic: (t)=>atEdge(t) ? t : elasticIn(t, 0.075, 0.3),\n    easeOutElastic: (t)=>atEdge(t) ? t : elasticOut(t, 0.075, 0.3),\n    easeInOutElastic (t) {\n        const s = 0.1125;\n        const p = 0.45;\n        return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p);\n    },\n    easeInBack (t) {\n        const s = 1.70158;\n        return t * t * ((s + 1) * t - s);\n    },\n    easeOutBack (t) {\n        const s = 1.70158;\n        return (t -= 1) * t * ((s + 1) * t + s) + 1;\n    },\n    easeInOutBack (t) {\n        let s = 1.70158;\n        if ((t /= 0.5) < 1) {\n            return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));\n        }\n        return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);\n    },\n    easeInBounce: (t)=>1 - effects.easeOutBounce(1 - t),\n    easeOutBounce (t) {\n        const m = 7.5625;\n        const d = 2.75;\n        if (t < 1 / d) {\n            return m * t * t;\n        }\n        if (t < 2 / d) {\n            return m * (t -= 1.5 / d) * t + 0.75;\n        }\n        if (t < 2.5 / d) {\n            return m * (t -= 2.25 / d) * t + 0.9375;\n        }\n        return m * (t -= 2.625 / d) * t + 0.984375;\n    },\n    easeInOutBounce: (t)=>t < 0.5 ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5\n};\n\nfunction isPatternOrGradient(value) {\n    if (value && typeof value === 'object') {\n        const type = value.toString();\n        return type === '[object CanvasPattern]' || type === '[object CanvasGradient]';\n    }\n    return false;\n}\nfunction color(value) {\n    return isPatternOrGradient(value) ? value : new Color(value);\n}\nfunction getHoverColor(value) {\n    return isPatternOrGradient(value) ? value : new Color(value).saturate(0.5).darken(0.1).hexString();\n}\n\nconst numbers = [\n    'x',\n    'y',\n    'borderWidth',\n    'radius',\n    'tension'\n];\nconst colors = [\n    'color',\n    'borderColor',\n    'backgroundColor'\n];\nfunction applyAnimationsDefaults(defaults) {\n    defaults.set('animation', {\n        delay: undefined,\n        duration: 1000,\n        easing: 'easeOutQuart',\n        fn: undefined,\n        from: undefined,\n        loop: undefined,\n        to: undefined,\n        type: undefined\n    });\n    defaults.describe('animation', {\n        _fallback: false,\n        _indexable: false,\n        _scriptable: (name)=>name !== 'onProgress' && name !== 'onComplete' && name !== 'fn'\n    });\n    defaults.set('animations', {\n        colors: {\n            type: 'color',\n            properties: colors\n        },\n        numbers: {\n            type: 'number',\n            properties: numbers\n        }\n    });\n    defaults.describe('animations', {\n        _fallback: 'animation'\n    });\n    defaults.set('transitions', {\n        active: {\n            animation: {\n                duration: 400\n            }\n        },\n        resize: {\n            animation: {\n                duration: 0\n            }\n        },\n        show: {\n            animations: {\n                colors: {\n                    from: 'transparent'\n                },\n                visible: {\n                    type: 'boolean',\n                    duration: 0\n                }\n            }\n        },\n        hide: {\n            animations: {\n                colors: {\n                    to: 'transparent'\n                },\n                visible: {\n                    type: 'boolean',\n                    easing: 'linear',\n                    fn: (v)=>v | 0\n                }\n            }\n        }\n    });\n}\n\nfunction applyLayoutsDefaults(defaults) {\n    defaults.set('layout', {\n        autoPadding: true,\n        padding: {\n            top: 0,\n            right: 0,\n            bottom: 0,\n            left: 0\n        }\n    });\n}\n\nconst intlCache = new Map();\nfunction getNumberFormat(locale, options) {\n    options = options || {};\n    const cacheKey = locale + JSON.stringify(options);\n    let formatter = intlCache.get(cacheKey);\n    if (!formatter) {\n        formatter = new Intl.NumberFormat(locale, options);\n        intlCache.set(cacheKey, formatter);\n    }\n    return formatter;\n}\nfunction formatNumber(num, locale, options) {\n    return getNumberFormat(locale, options).format(num);\n}\n\nconst formatters = {\n values (value) {\n        return isArray(value) ?  value : '' + value;\n    },\n numeric (tickValue, index, ticks) {\n        if (tickValue === 0) {\n            return '0';\n        }\n        const locale = this.chart.options.locale;\n        let notation;\n        let delta = tickValue;\n        if (ticks.length > 1) {\n            const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));\n            if (maxTick < 1e-4 || maxTick > 1e+15) {\n                notation = 'scientific';\n            }\n            delta = calculateDelta(tickValue, ticks);\n        }\n        const logDelta = log10(Math.abs(delta));\n        const numDecimal = isNaN(logDelta) ? 1 : Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);\n        const options = {\n            notation,\n            minimumFractionDigits: numDecimal,\n            maximumFractionDigits: numDecimal\n        };\n        Object.assign(options, this.options.ticks.format);\n        return formatNumber(tickValue, locale, options);\n    },\n logarithmic (tickValue, index, ticks) {\n        if (tickValue === 0) {\n            return '0';\n        }\n        const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue)));\n        if ([\n            1,\n            2,\n            3,\n            5,\n            10,\n            15\n        ].includes(remain) || index > 0.8 * ticks.length) {\n            return formatters.numeric.call(this, tickValue, index, ticks);\n        }\n        return '';\n    }\n};\nfunction calculateDelta(tickValue, ticks) {\n    let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;\n    if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {\n        delta = tickValue - Math.floor(tickValue);\n    }\n    return delta;\n}\n var Ticks = {\n    formatters\n};\n\nfunction applyScaleDefaults(defaults) {\n    defaults.set('scale', {\n        display: true,\n        offset: false,\n        reverse: false,\n        beginAtZero: false,\n bounds: 'ticks',\n        clip: true,\n grace: 0,\n        grid: {\n            display: true,\n            lineWidth: 1,\n            drawOnChartArea: true,\n            drawTicks: true,\n            tickLength: 8,\n            tickWidth: (_ctx, options)=>options.lineWidth,\n            tickColor: (_ctx, options)=>options.color,\n            offset: false\n        },\n        border: {\n            display: true,\n            dash: [],\n            dashOffset: 0.0,\n            width: 1\n        },\n        title: {\n            display: false,\n            text: '',\n            padding: {\n                top: 4,\n                bottom: 4\n            }\n        },\n        ticks: {\n            minRotation: 0,\n            maxRotation: 50,\n            mirror: false,\n            textStrokeWidth: 0,\n            textStrokeColor: '',\n            padding: 3,\n            display: true,\n            autoSkip: true,\n            autoSkipPadding: 3,\n            labelOffset: 0,\n            callback: Ticks.formatters.values,\n            minor: {},\n            major: {},\n            align: 'center',\n            crossAlign: 'near',\n            showLabelBackdrop: false,\n            backdropColor: 'rgba(255, 255, 255, 0.75)',\n            backdropPadding: 2\n        }\n    });\n    defaults.route('scale.ticks', 'color', '', 'color');\n    defaults.route('scale.grid', 'color', '', 'borderColor');\n    defaults.route('scale.border', 'color', '', 'borderColor');\n    defaults.route('scale.title', 'color', '', 'color');\n    defaults.describe('scale', {\n        _fallback: false,\n        _scriptable: (name)=>!name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser',\n        _indexable: (name)=>name !== 'borderDash' && name !== 'tickBorderDash' && name !== 'dash'\n    });\n    defaults.describe('scales', {\n        _fallback: 'scale'\n    });\n    defaults.describe('scale.ticks', {\n        _scriptable: (name)=>name !== 'backdropPadding' && name !== 'callback',\n        _indexable: (name)=>name !== 'backdropPadding'\n    });\n}\n\nconst overrides = Object.create(null);\nconst descriptors = Object.create(null);\n function getScope$1(node, key) {\n    if (!key) {\n        return node;\n    }\n    const keys = key.split('.');\n    for(let i = 0, n = keys.length; i < n; ++i){\n        const k = keys[i];\n        node = node[k] || (node[k] = Object.create(null));\n    }\n    return node;\n}\nfunction set(root, scope, values) {\n    if (typeof scope === 'string') {\n        return merge(getScope$1(root, scope), values);\n    }\n    return merge(getScope$1(root, ''), scope);\n}\n class Defaults {\n    constructor(_descriptors, _appliers){\n        this.animation = undefined;\n        this.backgroundColor = 'rgba(0,0,0,0.1)';\n        this.borderColor = 'rgba(0,0,0,0.1)';\n        this.color = '#666';\n        this.datasets = {};\n        this.devicePixelRatio = (context)=>context.chart.platform.getDevicePixelRatio();\n        this.elements = {};\n        this.events = [\n            'mousemove',\n            'mouseout',\n            'click',\n            'touchstart',\n            'touchmove'\n        ];\n        this.font = {\n            family: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n            size: 12,\n            style: 'normal',\n            lineHeight: 1.2,\n            weight: null\n        };\n        this.hover = {};\n        this.hoverBackgroundColor = (ctx, options)=>getHoverColor(options.backgroundColor);\n        this.hoverBorderColor = (ctx, options)=>getHoverColor(options.borderColor);\n        this.hoverColor = (ctx, options)=>getHoverColor(options.color);\n        this.indexAxis = 'x';\n        this.interaction = {\n            mode: 'nearest',\n            intersect: true,\n            includeInvisible: false\n        };\n        this.maintainAspectRatio = true;\n        this.onHover = null;\n        this.onClick = null;\n        this.parsing = true;\n        this.plugins = {};\n        this.responsive = true;\n        this.scale = undefined;\n        this.scales = {};\n        this.showLine = true;\n        this.drawActiveElementsOnTop = true;\n        this.describe(_descriptors);\n        this.apply(_appliers);\n    }\n set(scope, values) {\n        return set(this, scope, values);\n    }\n get(scope) {\n        return getScope$1(this, scope);\n    }\n describe(scope, values) {\n        return set(descriptors, scope, values);\n    }\n    override(scope, values) {\n        return set(overrides, scope, values);\n    }\n route(scope, name, targetScope, targetName) {\n        const scopeObject = getScope$1(this, scope);\n        const targetScopeObject = getScope$1(this, targetScope);\n        const privateName = '_' + name;\n        Object.defineProperties(scopeObject, {\n            [privateName]: {\n                value: scopeObject[name],\n                writable: true\n            },\n            [name]: {\n                enumerable: true,\n                get () {\n                    const local = this[privateName];\n                    const target = targetScopeObject[targetName];\n                    if (isObject(local)) {\n                        return Object.assign({}, target, local);\n                    }\n                    return valueOrDefault(local, target);\n                },\n                set (value) {\n                    this[privateName] = value;\n                }\n            }\n        });\n    }\n    apply(appliers) {\n        appliers.forEach((apply)=>apply(this));\n    }\n}\nvar defaults = /* #__PURE__ */ new Defaults({\n    _scriptable: (name)=>!name.startsWith('on'),\n    _indexable: (name)=>name !== 'events',\n    hover: {\n        _fallback: 'interaction'\n    },\n    interaction: {\n        _scriptable: false,\n        _indexable: false\n    }\n}, [\n    applyAnimationsDefaults,\n    applyLayoutsDefaults,\n    applyScaleDefaults\n]);\n\n/**\n * Converts the given font object into a CSS font string.\n * @param font - A font object.\n * @return The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font\n * @private\n */ function toFontString(font) {\n    if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {\n        return null;\n    }\n    return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family;\n}\n/**\n * @private\n */ function _measureText(ctx, data, gc, longest, string) {\n    let textWidth = data[string];\n    if (!textWidth) {\n        textWidth = data[string] = ctx.measureText(string).width;\n        gc.push(string);\n    }\n    if (textWidth > longest) {\n        longest = textWidth;\n    }\n    return longest;\n}\n/**\n * @private\n */ // eslint-disable-next-line complexity\nfunction _longestText(ctx, font, arrayOfThings, cache) {\n    cache = cache || {};\n    let data = cache.data = cache.data || {};\n    let gc = cache.garbageCollect = cache.garbageCollect || [];\n    if (cache.font !== font) {\n        data = cache.data = {};\n        gc = cache.garbageCollect = [];\n        cache.font = font;\n    }\n    ctx.save();\n    ctx.font = font;\n    let longest = 0;\n    const ilen = arrayOfThings.length;\n    let i, j, jlen, thing, nestedThing;\n    for(i = 0; i < ilen; i++){\n        thing = arrayOfThings[i];\n        // Undefined strings and arrays should not be measured\n        if (thing !== undefined && thing !== null && !isArray(thing)) {\n            longest = _measureText(ctx, data, gc, longest, thing);\n        } else if (isArray(thing)) {\n            // if it is an array lets measure each element\n            // to do maybe simplify this function a bit so we can do this more recursively?\n            for(j = 0, jlen = thing.length; j < jlen; j++){\n                nestedThing = thing[j];\n                // Undefined strings and arrays should not be measured\n                if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) {\n                    longest = _measureText(ctx, data, gc, longest, nestedThing);\n                }\n            }\n        }\n    }\n    ctx.restore();\n    const gcLen = gc.length / 2;\n    if (gcLen > arrayOfThings.length) {\n        for(i = 0; i < gcLen; i++){\n            delete data[gc[i]];\n        }\n        gc.splice(0, gcLen);\n    }\n    return longest;\n}\n/**\n * Returns the aligned pixel value to avoid anti-aliasing blur\n * @param chart - The chart instance.\n * @param pixel - A pixel value.\n * @param width - The width of the element.\n * @returns The aligned pixel value.\n * @private\n */ function _alignPixel(chart, pixel, width) {\n    const devicePixelRatio = chart.currentDevicePixelRatio;\n    const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;\n    return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;\n}\n/**\n * Clears the entire canvas.\n */ function clearCanvas(canvas, ctx) {\n    ctx = ctx || canvas.getContext('2d');\n    ctx.save();\n    // canvas.width and canvas.height do not consider the canvas transform,\n    // while clearRect does\n    ctx.resetTransform();\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n    ctx.restore();\n}\nfunction drawPoint(ctx, options, x, y) {\n    // eslint-disable-next-line @typescript-eslint/no-use-before-define\n    drawPointLegend(ctx, options, x, y, null);\n}\n// eslint-disable-next-line complexity\nfunction drawPointLegend(ctx, options, x, y, w) {\n    let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW;\n    const style = options.pointStyle;\n    const rotation = options.rotation;\n    const radius = options.radius;\n    let rad = (rotation || 0) * RAD_PER_DEG;\n    if (style && typeof style === 'object') {\n        type = style.toString();\n        if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\n            ctx.save();\n            ctx.translate(x, y);\n            ctx.rotate(rad);\n            ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);\n            ctx.restore();\n            return;\n        }\n    }\n    if (isNaN(radius) || radius <= 0) {\n        return;\n    }\n    ctx.beginPath();\n    switch(style){\n        // Default includes circle\n        default:\n            if (w) {\n                ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU);\n            } else {\n                ctx.arc(x, y, radius, 0, TAU);\n            }\n            ctx.closePath();\n            break;\n        case 'triangle':\n            width = w ? w / 2 : radius;\n            ctx.moveTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n            rad += TWO_THIRDS_PI;\n            ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n            rad += TWO_THIRDS_PI;\n            ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);\n            ctx.closePath();\n            break;\n        case 'rectRounded':\n            // NOTE: the rounded rect implementation changed to use `arc` instead of\n            // `quadraticCurveTo` since it generates better results when rect is\n            // almost a circle. 0.516 (instead of 0.5) produces results with visually\n            // closer proportion to the previous impl and it is inscribed in the\n            // circle with `radius`. For more details, see the following PRs:\n            // https://github.com/chartjs/Chart.js/issues/5597\n            // https://github.com/chartjs/Chart.js/issues/5858\n            cornerRadius = radius * 0.516;\n            size = radius - cornerRadius;\n            xOffset = Math.cos(rad + QUARTER_PI) * size;\n            xOffsetW = Math.cos(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);\n            yOffset = Math.sin(rad + QUARTER_PI) * size;\n            yOffsetW = Math.sin(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);\n            ctx.arc(x - xOffsetW, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);\n            ctx.arc(x + yOffsetW, y - xOffset, cornerRadius, rad - HALF_PI, rad);\n            ctx.arc(x + xOffsetW, y + yOffset, cornerRadius, rad, rad + HALF_PI);\n            ctx.arc(x - yOffsetW, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);\n            ctx.closePath();\n            break;\n        case 'rect':\n            if (!rotation) {\n                size = Math.SQRT1_2 * radius;\n                width = w ? w / 2 : size;\n                ctx.rect(x - width, y - size, 2 * width, 2 * size);\n                break;\n            }\n            rad += QUARTER_PI;\n        /* falls through */ case 'rectRot':\n            xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n            xOffset = Math.cos(rad) * radius;\n            yOffset = Math.sin(rad) * radius;\n            yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n            ctx.moveTo(x - xOffsetW, y - yOffset);\n            ctx.lineTo(x + yOffsetW, y - xOffset);\n            ctx.lineTo(x + xOffsetW, y + yOffset);\n            ctx.lineTo(x - yOffsetW, y + xOffset);\n            ctx.closePath();\n            break;\n        case 'crossRot':\n            rad += QUARTER_PI;\n        /* falls through */ case 'cross':\n            xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n            xOffset = Math.cos(rad) * radius;\n            yOffset = Math.sin(rad) * radius;\n            yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n            ctx.moveTo(x - xOffsetW, y - yOffset);\n            ctx.lineTo(x + xOffsetW, y + yOffset);\n            ctx.moveTo(x + yOffsetW, y - xOffset);\n            ctx.lineTo(x - yOffsetW, y + xOffset);\n            break;\n        case 'star':\n            xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n            xOffset = Math.cos(rad) * radius;\n            yOffset = Math.sin(rad) * radius;\n            yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n            ctx.moveTo(x - xOffsetW, y - yOffset);\n            ctx.lineTo(x + xOffsetW, y + yOffset);\n            ctx.moveTo(x + yOffsetW, y - xOffset);\n            ctx.lineTo(x - yOffsetW, y + xOffset);\n            rad += QUARTER_PI;\n            xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);\n            xOffset = Math.cos(rad) * radius;\n            yOffset = Math.sin(rad) * radius;\n            yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);\n            ctx.moveTo(x - xOffsetW, y - yOffset);\n            ctx.lineTo(x + xOffsetW, y + yOffset);\n            ctx.moveTo(x + yOffsetW, y - xOffset);\n            ctx.lineTo(x - yOffsetW, y + xOffset);\n            break;\n        case 'line':\n            xOffset = w ? w / 2 : Math.cos(rad) * radius;\n            yOffset = Math.sin(rad) * radius;\n            ctx.moveTo(x - xOffset, y - yOffset);\n            ctx.lineTo(x + xOffset, y + yOffset);\n            break;\n        case 'dash':\n            ctx.moveTo(x, y);\n            ctx.lineTo(x + Math.cos(rad) * (w ? w / 2 : radius), y + Math.sin(rad) * radius);\n            break;\n        case false:\n            ctx.closePath();\n            break;\n    }\n    ctx.fill();\n    if (options.borderWidth > 0) {\n        ctx.stroke();\n    }\n}\n/**\n * Returns true if the point is inside the rectangle\n * @param point - The point to test\n * @param area - The rectangle\n * @param margin - allowed margin\n * @private\n */ function _isPointInArea(point, area, margin) {\n    margin = margin || 0.5; // margin - default is to match rounded decimals\n    return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin;\n}\nfunction clipArea(ctx, area) {\n    ctx.save();\n    ctx.beginPath();\n    ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);\n    ctx.clip();\n}\nfunction unclipArea(ctx) {\n    ctx.restore();\n}\n/**\n * @private\n */ function _steppedLineTo(ctx, previous, target, flip, mode) {\n    if (!previous) {\n        return ctx.lineTo(target.x, target.y);\n    }\n    if (mode === 'middle') {\n        const midpoint = (previous.x + target.x) / 2.0;\n        ctx.lineTo(midpoint, previous.y);\n        ctx.lineTo(midpoint, target.y);\n    } else if (mode === 'after' !== !!flip) {\n        ctx.lineTo(previous.x, target.y);\n    } else {\n        ctx.lineTo(target.x, previous.y);\n    }\n    ctx.lineTo(target.x, target.y);\n}\n/**\n * @private\n */ function _bezierCurveTo(ctx, previous, target, flip) {\n    if (!previous) {\n        return ctx.lineTo(target.x, target.y);\n    }\n    ctx.bezierCurveTo(flip ? previous.cp1x : previous.cp2x, flip ? previous.cp1y : previous.cp2y, flip ? target.cp2x : target.cp1x, flip ? target.cp2y : target.cp1y, target.x, target.y);\n}\nfunction setRenderOpts(ctx, opts) {\n    if (opts.translation) {\n        ctx.translate(opts.translation[0], opts.translation[1]);\n    }\n    if (!isNullOrUndef(opts.rotation)) {\n        ctx.rotate(opts.rotation);\n    }\n    if (opts.color) {\n        ctx.fillStyle = opts.color;\n    }\n    if (opts.textAlign) {\n        ctx.textAlign = opts.textAlign;\n    }\n    if (opts.textBaseline) {\n        ctx.textBaseline = opts.textBaseline;\n    }\n}\nfunction decorateText(ctx, x, y, line, opts) {\n    if (opts.strikethrough || opts.underline) {\n        /**\n     * Now that IE11 support has been dropped, we can use more\n     * of the TextMetrics object. The actual bounding boxes\n     * are unflagged in Chrome, Firefox, Edge, and Safari so they\n     * can be safely used.\n     * See https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics#Browser_compatibility\n     */ const metrics = ctx.measureText(line);\n        const left = x - metrics.actualBoundingBoxLeft;\n        const right = x + metrics.actualBoundingBoxRight;\n        const top = y - metrics.actualBoundingBoxAscent;\n        const bottom = y + metrics.actualBoundingBoxDescent;\n        const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom;\n        ctx.strokeStyle = ctx.fillStyle;\n        ctx.beginPath();\n        ctx.lineWidth = opts.decorationWidth || 2;\n        ctx.moveTo(left, yDecoration);\n        ctx.lineTo(right, yDecoration);\n        ctx.stroke();\n    }\n}\nfunction drawBackdrop(ctx, opts) {\n    const oldColor = ctx.fillStyle;\n    ctx.fillStyle = opts.color;\n    ctx.fillRect(opts.left, opts.top, opts.width, opts.height);\n    ctx.fillStyle = oldColor;\n}\n/**\n * Render text onto the canvas\n */ function renderText(ctx, text, x, y, font, opts = {}) {\n    const lines = isArray(text) ? text : [\n        text\n    ];\n    const stroke = opts.strokeWidth > 0 && opts.strokeColor !== '';\n    let i, line;\n    ctx.save();\n    ctx.font = font.string;\n    setRenderOpts(ctx, opts);\n    for(i = 0; i < lines.length; ++i){\n        line = lines[i];\n        if (opts.backdrop) {\n            drawBackdrop(ctx, opts.backdrop);\n        }\n        if (stroke) {\n            if (opts.strokeColor) {\n                ctx.strokeStyle = opts.strokeColor;\n            }\n            if (!isNullOrUndef(opts.strokeWidth)) {\n                ctx.lineWidth = opts.strokeWidth;\n            }\n            ctx.strokeText(line, x, y, opts.maxWidth);\n        }\n        ctx.fillText(line, x, y, opts.maxWidth);\n        decorateText(ctx, x, y, line, opts);\n        y += Number(font.lineHeight);\n    }\n    ctx.restore();\n}\n/**\n * Add a path of a rectangle with rounded corners to the current sub-path\n * @param ctx - Context\n * @param rect - Bounding rect\n */ function addRoundedRectPath(ctx, rect) {\n    const { x , y , w , h , radius  } = rect;\n    // top left arc\n    ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, 1.5 * PI, PI, true);\n    // line from top left to bottom left\n    ctx.lineTo(x, y + h - radius.bottomLeft);\n    // bottom left arc\n    ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);\n    // line from bottom left to bottom right\n    ctx.lineTo(x + w - radius.bottomRight, y + h);\n    // bottom right arc\n    ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);\n    // line from bottom right to top right\n    ctx.lineTo(x + w, y + radius.topRight);\n    // top right arc\n    ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true);\n    // line from top right to top left\n    ctx.lineTo(x + radius.topLeft, y);\n}\n\nconst LINE_HEIGHT = /^(normal|(\\d+(?:\\.\\d+)?)(px|em|%)?)$/;\nconst FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;\n/**\n * @alias Chart.helpers.options\n * @namespace\n */ /**\n * Converts the given line height `value` in pixels for a specific font `size`.\n * @param value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').\n * @param size - The font size (in pixels) used to resolve relative `value`.\n * @returns The effective line height in pixels (size * 1.2 if value is invalid).\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\n * @since 2.7.0\n */ function toLineHeight(value, size) {\n    const matches = ('' + value).match(LINE_HEIGHT);\n    if (!matches || matches[1] === 'normal') {\n        return size * 1.2;\n    }\n    value = +matches[2];\n    switch(matches[3]){\n        case 'px':\n            return value;\n        case '%':\n            value /= 100;\n            break;\n    }\n    return size * value;\n}\nconst numberOrZero = (v)=>+v || 0;\nfunction _readValueToProps(value, props) {\n    const ret = {};\n    const objProps = isObject(props);\n    const keys = objProps ? Object.keys(props) : props;\n    const read = isObject(value) ? objProps ? (prop)=>valueOrDefault(value[prop], value[props[prop]]) : (prop)=>value[prop] : ()=>value;\n    for (const prop of keys){\n        ret[prop] = numberOrZero(read(prop));\n    }\n    return ret;\n}\n/**\n * Converts the given value into a TRBL object.\n * @param value - If a number, set the value to all TRBL component,\n *  else, if an object, use defined properties and sets undefined ones to 0.\n *  x / y are shorthands for same value for left/right and top/bottom.\n * @returns The padding values (top, right, bottom, left)\n * @since 3.0.0\n */ function toTRBL(value) {\n    return _readValueToProps(value, {\n        top: 'y',\n        right: 'x',\n        bottom: 'y',\n        left: 'x'\n    });\n}\n/**\n * Converts the given value into a TRBL corners object (similar with css border-radius).\n * @param value - If a number, set the value to all TRBL corner components,\n *  else, if an object, use defined properties and sets undefined ones to 0.\n * @returns The TRBL corner values (topLeft, topRight, bottomLeft, bottomRight)\n * @since 3.0.0\n */ function toTRBLCorners(value) {\n    return _readValueToProps(value, [\n        'topLeft',\n        'topRight',\n        'bottomLeft',\n        'bottomRight'\n    ]);\n}\n/**\n * Converts the given value into a padding object with pre-computed width/height.\n * @param value - If a number, set the value to all TRBL component,\n *  else, if an object, use defined properties and sets undefined ones to 0.\n *  x / y are shorthands for same value for left/right and top/bottom.\n * @returns The padding values (top, right, bottom, left, width, height)\n * @since 2.7.0\n */ function toPadding(value) {\n    const obj = toTRBL(value);\n    obj.width = obj.left + obj.right;\n    obj.height = obj.top + obj.bottom;\n    return obj;\n}\n/**\n * Parses font options and returns the font object.\n * @param options - A object that contains font options to be parsed.\n * @param fallback - A object that contains fallback font options.\n * @return The font object.\n * @private\n */ function toFont(options, fallback) {\n    options = options || {};\n    fallback = fallback || defaults.font;\n    let size = valueOrDefault(options.size, fallback.size);\n    if (typeof size === 'string') {\n        size = parseInt(size, 10);\n    }\n    let style = valueOrDefault(options.style, fallback.style);\n    if (style && !('' + style).match(FONT_STYLE)) {\n        console.warn('Invalid font style specified: \"' + style + '\"');\n        style = undefined;\n    }\n    const font = {\n        family: valueOrDefault(options.family, fallback.family),\n        lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),\n        size,\n        style,\n        weight: valueOrDefault(options.weight, fallback.weight),\n        string: ''\n    };\n    font.string = toFontString(font);\n    return font;\n}\n/**\n * Evaluates the given `inputs` sequentially and returns the first defined value.\n * @param inputs - An array of values, falling back to the last value.\n * @param context - If defined and the current value is a function, the value\n * is called with `context` as first argument and the result becomes the new input.\n * @param index - If defined and the current value is an array, the value\n * at `index` become the new input.\n * @param info - object to return information about resolution in\n * @param info.cacheable - Will be set to `false` if option is not cacheable.\n * @since 2.7.0\n */ function resolve(inputs, context, index, info) {\n    let cacheable = true;\n    let i, ilen, value;\n    for(i = 0, ilen = inputs.length; i < ilen; ++i){\n        value = inputs[i];\n        if (value === undefined) {\n            continue;\n        }\n        if (context !== undefined && typeof value === 'function') {\n            value = value(context);\n            cacheable = false;\n        }\n        if (index !== undefined && isArray(value)) {\n            value = value[index % value.length];\n            cacheable = false;\n        }\n        if (value !== undefined) {\n            if (info && !cacheable) {\n                info.cacheable = false;\n            }\n            return value;\n        }\n    }\n}\n/**\n * @param minmax\n * @param grace\n * @param beginAtZero\n * @private\n */ function _addGrace(minmax, grace, beginAtZero) {\n    const { min , max  } = minmax;\n    const change = toDimension(grace, (max - min) / 2);\n    const keepZero = (value, add)=>beginAtZero && value === 0 ? 0 : value + add;\n    return {\n        min: keepZero(min, -Math.abs(change)),\n        max: keepZero(max, change)\n    };\n}\nfunction createContext(parentContext, context) {\n    return Object.assign(Object.create(parentContext), context);\n}\n\n/**\n * Creates a Proxy for resolving raw values for options.\n * @param scopes - The option scopes to look for values, in resolution order\n * @param prefixes - The prefixes for values, in resolution order.\n * @param rootScopes - The root option scopes\n * @param fallback - Parent scopes fallback\n * @param getTarget - callback for getting the target for changed values\n * @returns Proxy\n * @private\n */ function _createResolver(scopes, prefixes = [\n    ''\n], rootScopes, fallback, getTarget = ()=>scopes[0]) {\n    const finalRootScopes = rootScopes || scopes;\n    if (typeof fallback === 'undefined') {\n        fallback = _resolve('_fallback', scopes);\n    }\n    const cache = {\n        [Symbol.toStringTag]: 'Object',\n        _cacheable: true,\n        _scopes: scopes,\n        _rootScopes: finalRootScopes,\n        _fallback: fallback,\n        _getTarget: getTarget,\n        override: (scope)=>_createResolver([\n                scope,\n                ...scopes\n            ], prefixes, finalRootScopes, fallback)\n    };\n    return new Proxy(cache, {\n        /**\n     * A trap for the delete operator.\n     */ deleteProperty (target, prop) {\n            delete target[prop]; // remove from cache\n            delete target._keys; // remove cached keys\n            delete scopes[0][prop]; // remove from top level scope\n            return true;\n        },\n        /**\n     * A trap for getting property values.\n     */ get (target, prop) {\n            return _cached(target, prop, ()=>_resolveWithPrefixes(prop, prefixes, scopes, target));\n        },\n        /**\n     * A trap for Object.getOwnPropertyDescriptor.\n     * Also used by Object.hasOwnProperty.\n     */ getOwnPropertyDescriptor (target, prop) {\n            return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);\n        },\n        /**\n     * A trap for Object.getPrototypeOf.\n     */ getPrototypeOf () {\n            return Reflect.getPrototypeOf(scopes[0]);\n        },\n        /**\n     * A trap for the in operator.\n     */ has (target, prop) {\n            return getKeysFromAllScopes(target).includes(prop);\n        },\n        /**\n     * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.\n     */ ownKeys (target) {\n            return getKeysFromAllScopes(target);\n        },\n        /**\n     * A trap for setting property values.\n     */ set (target, prop, value) {\n            const storage = target._storage || (target._storage = getTarget());\n            target[prop] = storage[prop] = value; // set to top level scope + cache\n            delete target._keys; // remove cached keys\n            return true;\n        }\n    });\n}\n/**\n * Returns an Proxy for resolving option values with context.\n * @param proxy - The Proxy returned by `_createResolver`\n * @param context - Context object for scriptable/indexable options\n * @param subProxy - The proxy provided for scriptable options\n * @param descriptorDefaults - Defaults for descriptors\n * @private\n */ function _attachContext(proxy, context, subProxy, descriptorDefaults) {\n    const cache = {\n        _cacheable: false,\n        _proxy: proxy,\n        _context: context,\n        _subProxy: subProxy,\n        _stack: new Set(),\n        _descriptors: _descriptors(proxy, descriptorDefaults),\n        setContext: (ctx)=>_attachContext(proxy, ctx, subProxy, descriptorDefaults),\n        override: (scope)=>_attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)\n    };\n    return new Proxy(cache, {\n        /**\n     * A trap for the delete operator.\n     */ deleteProperty (target, prop) {\n            delete target[prop]; // remove from cache\n            delete proxy[prop]; // remove from proxy\n            return true;\n        },\n        /**\n     * A trap for getting property values.\n     */ get (target, prop, receiver) {\n            return _cached(target, prop, ()=>_resolveWithContext(target, prop, receiver));\n        },\n        /**\n     * A trap for Object.getOwnPropertyDescriptor.\n     * Also used by Object.hasOwnProperty.\n     */ getOwnPropertyDescriptor (target, prop) {\n            return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {\n                enumerable: true,\n                configurable: true\n            } : undefined : Reflect.getOwnPropertyDescriptor(proxy, prop);\n        },\n        /**\n     * A trap for Object.getPrototypeOf.\n     */ getPrototypeOf () {\n            return Reflect.getPrototypeOf(proxy);\n        },\n        /**\n     * A trap for the in operator.\n     */ has (target, prop) {\n            return Reflect.has(proxy, prop);\n        },\n        /**\n     * A trap for Object.getOwnPropertyNames and Object.getOwnPropertySymbols.\n     */ ownKeys () {\n            return Reflect.ownKeys(proxy);\n        },\n        /**\n     * A trap for setting property values.\n     */ set (target, prop, value) {\n            proxy[prop] = value; // set to proxy\n            delete target[prop]; // remove from cache\n            return true;\n        }\n    });\n}\n/**\n * @private\n */ function _descriptors(proxy, defaults = {\n    scriptable: true,\n    indexable: true\n}) {\n    const { _scriptable =defaults.scriptable , _indexable =defaults.indexable , _allKeys =defaults.allKeys  } = proxy;\n    return {\n        allKeys: _allKeys,\n        scriptable: _scriptable,\n        indexable: _indexable,\n        isScriptable: isFunction(_scriptable) ? _scriptable : ()=>_scriptable,\n        isIndexable: isFunction(_indexable) ? _indexable : ()=>_indexable\n    };\n}\nconst readKey = (prefix, name)=>prefix ? prefix + _capitalize(name) : name;\nconst needsSubResolver = (prop, value)=>isObject(value) && prop !== 'adapters' && (Object.getPrototypeOf(value) === null || value.constructor === Object);\nfunction _cached(target, prop, resolve) {\n    if (Object.prototype.hasOwnProperty.call(target, prop)) {\n        return target[prop];\n    }\n    const value = resolve();\n    // cache the resolved value\n    target[prop] = value;\n    return value;\n}\nfunction _resolveWithContext(target, prop, receiver) {\n    const { _proxy , _context , _subProxy , _descriptors: descriptors  } = target;\n    let value = _proxy[prop]; // resolve from proxy\n    // resolve with context\n    if (isFunction(value) && descriptors.isScriptable(prop)) {\n        value = _resolveScriptable(prop, value, target, receiver);\n    }\n    if (isArray(value) && value.length) {\n        value = _resolveArray(prop, value, target, descriptors.isIndexable);\n    }\n    if (needsSubResolver(prop, value)) {\n        // if the resolved value is an object, create a sub resolver for it\n        value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors);\n    }\n    return value;\n}\nfunction _resolveScriptable(prop, getValue, target, receiver) {\n    const { _proxy , _context , _subProxy , _stack  } = target;\n    if (_stack.has(prop)) {\n        throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop);\n    }\n    _stack.add(prop);\n    let value = getValue(_context, _subProxy || receiver);\n    _stack.delete(prop);\n    if (needsSubResolver(prop, value)) {\n        // When scriptable option returns an object, create a resolver on that.\n        value = createSubResolver(_proxy._scopes, _proxy, prop, value);\n    }\n    return value;\n}\nfunction _resolveArray(prop, value, target, isIndexable) {\n    const { _proxy , _context , _subProxy , _descriptors: descriptors  } = target;\n    if (typeof _context.index !== 'undefined' && isIndexable(prop)) {\n        return value[_context.index % value.length];\n    } else if (isObject(value[0])) {\n        // Array of objects, return array or resolvers\n        const arr = value;\n        const scopes = _proxy._scopes.filter((s)=>s !== arr);\n        value = [];\n        for (const item of arr){\n            const resolver = createSubResolver(scopes, _proxy, prop, item);\n            value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors));\n        }\n    }\n    return value;\n}\nfunction resolveFallback(fallback, prop, value) {\n    return isFunction(fallback) ? fallback(prop, value) : fallback;\n}\nconst getScope = (key, parent)=>key === true ? parent : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined;\nfunction addScopes(set, parentScopes, key, parentFallback, value) {\n    for (const parent of parentScopes){\n        const scope = getScope(key, parent);\n        if (scope) {\n            set.add(scope);\n            const fallback = resolveFallback(scope._fallback, key, value);\n            if (typeof fallback !== 'undefined' && fallback !== key && fallback !== parentFallback) {\n                // When we reach the descriptor that defines a new _fallback, return that.\n                // The fallback will resume to that new scope.\n                return fallback;\n            }\n        } else if (scope === false && typeof parentFallback !== 'undefined' && key !== parentFallback) {\n            // Fallback to `false` results to `false`, when falling back to different key.\n            // For example `interaction` from `hover` or `plugins.tooltip` and `animation` from `animations`\n            return null;\n        }\n    }\n    return false;\n}\nfunction createSubResolver(parentScopes, resolver, prop, value) {\n    const rootScopes = resolver._rootScopes;\n    const fallback = resolveFallback(resolver._fallback, prop, value);\n    const allScopes = [\n        ...parentScopes,\n        ...rootScopes\n    ];\n    const set = new Set();\n    set.add(value);\n    let key = addScopesFromKey(set, allScopes, prop, fallback || prop, value);\n    if (key === null) {\n        return false;\n    }\n    if (typeof fallback !== 'undefined' && fallback !== prop) {\n        key = addScopesFromKey(set, allScopes, fallback, key, value);\n        if (key === null) {\n            return false;\n        }\n    }\n    return _createResolver(Array.from(set), [\n        ''\n    ], rootScopes, fallback, ()=>subGetTarget(resolver, prop, value));\n}\nfunction addScopesFromKey(set, allScopes, key, fallback, item) {\n    while(key){\n        key = addScopes(set, allScopes, key, fallback, item);\n    }\n    return key;\n}\nfunction subGetTarget(resolver, prop, value) {\n    const parent = resolver._getTarget();\n    if (!(prop in parent)) {\n        parent[prop] = {};\n    }\n    const target = parent[prop];\n    if (isArray(target) && isObject(value)) {\n        // For array of objects, the object is used to store updated values\n        return value;\n    }\n    return target || {};\n}\nfunction _resolveWithPrefixes(prop, prefixes, scopes, proxy) {\n    let value;\n    for (const prefix of prefixes){\n        value = _resolve(readKey(prefix, prop), scopes);\n        if (typeof value !== 'undefined') {\n            return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value;\n        }\n    }\n}\nfunction _resolve(key, scopes) {\n    for (const scope of scopes){\n        if (!scope) {\n            continue;\n        }\n        const value = scope[key];\n        if (typeof value !== 'undefined') {\n            return value;\n        }\n    }\n}\nfunction getKeysFromAllScopes(target) {\n    let keys = target._keys;\n    if (!keys) {\n        keys = target._keys = resolveKeysFromAllScopes(target._scopes);\n    }\n    return keys;\n}\nfunction resolveKeysFromAllScopes(scopes) {\n    const set = new Set();\n    for (const scope of scopes){\n        for (const key of Object.keys(scope).filter((k)=>!k.startsWith('_'))){\n            set.add(key);\n        }\n    }\n    return Array.from(set);\n}\nfunction _parseObjectDataRadialScale(meta, data, start, count) {\n    const { iScale  } = meta;\n    const { key ='r'  } = this._parsing;\n    const parsed = new Array(count);\n    let i, ilen, index, item;\n    for(i = 0, ilen = count; i < ilen; ++i){\n        index = i + start;\n        item = data[index];\n        parsed[i] = {\n            r: iScale.parse(resolveObjectKey(item, key), index)\n        };\n    }\n    return parsed;\n}\n\nconst EPSILON = Number.EPSILON || 1e-14;\nconst getPoint = (points, i)=>i < points.length && !points[i].skip && points[i];\nconst getValueAxis = (indexAxis)=>indexAxis === 'x' ? 'y' : 'x';\nfunction splineCurve(firstPoint, middlePoint, afterPoint, t) {\n    // Props to Rob Spencer at scaled innovation for his post on splining between points\n    // http://scaledinnovation.com/analytics/splines/aboutSplines.html\n    // This function must also respect \"skipped\" points\n    const previous = firstPoint.skip ? middlePoint : firstPoint;\n    const current = middlePoint;\n    const next = afterPoint.skip ? middlePoint : afterPoint;\n    const d01 = distanceBetweenPoints(current, previous);\n    const d12 = distanceBetweenPoints(next, current);\n    let s01 = d01 / (d01 + d12);\n    let s12 = d12 / (d01 + d12);\n    // If all points are the same, s01 & s02 will be inf\n    s01 = isNaN(s01) ? 0 : s01;\n    s12 = isNaN(s12) ? 0 : s12;\n    const fa = t * s01; // scaling factor for triangle Ta\n    const fb = t * s12;\n    return {\n        previous: {\n            x: current.x - fa * (next.x - previous.x),\n            y: current.y - fa * (next.y - previous.y)\n        },\n        next: {\n            x: current.x + fb * (next.x - previous.x),\n            y: current.y + fb * (next.y - previous.y)\n        }\n    };\n}\n/**\n * Adjust tangents to ensure monotonic properties\n */ function monotoneAdjust(points, deltaK, mK) {\n    const pointsLen = points.length;\n    let alphaK, betaK, tauK, squaredMagnitude, pointCurrent;\n    let pointAfter = getPoint(points, 0);\n    for(let i = 0; i < pointsLen - 1; ++i){\n        pointCurrent = pointAfter;\n        pointAfter = getPoint(points, i + 1);\n        if (!pointCurrent || !pointAfter) {\n            continue;\n        }\n        if (almostEquals(deltaK[i], 0, EPSILON)) {\n            mK[i] = mK[i + 1] = 0;\n            continue;\n        }\n        alphaK = mK[i] / deltaK[i];\n        betaK = mK[i + 1] / deltaK[i];\n        squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);\n        if (squaredMagnitude <= 9) {\n            continue;\n        }\n        tauK = 3 / Math.sqrt(squaredMagnitude);\n        mK[i] = alphaK * tauK * deltaK[i];\n        mK[i + 1] = betaK * tauK * deltaK[i];\n    }\n}\nfunction monotoneCompute(points, mK, indexAxis = 'x') {\n    const valueAxis = getValueAxis(indexAxis);\n    const pointsLen = points.length;\n    let delta, pointBefore, pointCurrent;\n    let pointAfter = getPoint(points, 0);\n    for(let i = 0; i < pointsLen; ++i){\n        pointBefore = pointCurrent;\n        pointCurrent = pointAfter;\n        pointAfter = getPoint(points, i + 1);\n        if (!pointCurrent) {\n            continue;\n        }\n        const iPixel = pointCurrent[indexAxis];\n        const vPixel = pointCurrent[valueAxis];\n        if (pointBefore) {\n            delta = (iPixel - pointBefore[indexAxis]) / 3;\n            pointCurrent[`cp1${indexAxis}`] = iPixel - delta;\n            pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i];\n        }\n        if (pointAfter) {\n            delta = (pointAfter[indexAxis] - iPixel) / 3;\n            pointCurrent[`cp2${indexAxis}`] = iPixel + delta;\n            pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i];\n        }\n    }\n}\n/**\n * This function calculates Bézier control points in a similar way than |splineCurve|,\n * but preserves monotonicity of the provided data and ensures no local extremums are added\n * between the dataset discrete points due to the interpolation.\n * See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation\n */ function splineCurveMonotone(points, indexAxis = 'x') {\n    const valueAxis = getValueAxis(indexAxis);\n    const pointsLen = points.length;\n    const deltaK = Array(pointsLen).fill(0);\n    const mK = Array(pointsLen);\n    // Calculate slopes (deltaK) and initialize tangents (mK)\n    let i, pointBefore, pointCurrent;\n    let pointAfter = getPoint(points, 0);\n    for(i = 0; i < pointsLen; ++i){\n        pointBefore = pointCurrent;\n        pointCurrent = pointAfter;\n        pointAfter = getPoint(points, i + 1);\n        if (!pointCurrent) {\n            continue;\n        }\n        if (pointAfter) {\n            const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis];\n            // In the case of two points that appear at the same x pixel, slopeDeltaX is 0\n            deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0;\n        }\n        mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : sign(deltaK[i - 1]) !== sign(deltaK[i]) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2;\n    }\n    monotoneAdjust(points, deltaK, mK);\n    monotoneCompute(points, mK, indexAxis);\n}\nfunction capControlPoint(pt, min, max) {\n    return Math.max(Math.min(pt, max), min);\n}\nfunction capBezierPoints(points, area) {\n    let i, ilen, point, inArea, inAreaPrev;\n    let inAreaNext = _isPointInArea(points[0], area);\n    for(i = 0, ilen = points.length; i < ilen; ++i){\n        inAreaPrev = inArea;\n        inArea = inAreaNext;\n        inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area);\n        if (!inArea) {\n            continue;\n        }\n        point = points[i];\n        if (inAreaPrev) {\n            point.cp1x = capControlPoint(point.cp1x, area.left, area.right);\n            point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom);\n        }\n        if (inAreaNext) {\n            point.cp2x = capControlPoint(point.cp2x, area.left, area.right);\n            point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom);\n        }\n    }\n}\n/**\n * @private\n */ function _updateBezierControlPoints(points, options, area, loop, indexAxis) {\n    let i, ilen, point, controlPoints;\n    // Only consider points that are drawn in case the spanGaps option is used\n    if (options.spanGaps) {\n        points = points.filter((pt)=>!pt.skip);\n    }\n    if (options.cubicInterpolationMode === 'monotone') {\n        splineCurveMonotone(points, indexAxis);\n    } else {\n        let prev = loop ? points[points.length - 1] : points[0];\n        for(i = 0, ilen = points.length; i < ilen; ++i){\n            point = points[i];\n            controlPoints = splineCurve(prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension);\n            point.cp1x = controlPoints.previous.x;\n            point.cp1y = controlPoints.previous.y;\n            point.cp2x = controlPoints.next.x;\n            point.cp2y = controlPoints.next.y;\n            prev = point;\n        }\n    }\n    if (options.capBezierPoints) {\n        capBezierPoints(points, area);\n    }\n}\n\n/**\n * Note: typedefs are auto-exported, so use a made-up `dom` namespace where\n * necessary to avoid duplicates with `export * from './helpers`; see\n * https://github.com/microsoft/TypeScript/issues/46011\n * @typedef { import('../core/core.controller.js').default } dom.Chart\n * @typedef { import('../../types').ChartEvent } ChartEvent\n */ /**\n * @private\n */ function _isDomSupported() {\n    return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n/**\n * @private\n */ function _getParentNode(domNode) {\n    let parent = domNode.parentNode;\n    if (parent && parent.toString() === '[object ShadowRoot]') {\n        parent = parent.host;\n    }\n    return parent;\n}\n/**\n * convert max-width/max-height values that may be percentages into a number\n * @private\n */ function parseMaxStyle(styleValue, node, parentProperty) {\n    let valueInPixels;\n    if (typeof styleValue === 'string') {\n        valueInPixels = parseInt(styleValue, 10);\n        if (styleValue.indexOf('%') !== -1) {\n            // percentage * size in dimension\n            valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];\n        }\n    } else {\n        valueInPixels = styleValue;\n    }\n    return valueInPixels;\n}\nconst getComputedStyle = (element)=>element.ownerDocument.defaultView.getComputedStyle(element, null);\nfunction getStyle(el, property) {\n    return getComputedStyle(el).getPropertyValue(property);\n}\nconst positions = [\n    'top',\n    'right',\n    'bottom',\n    'left'\n];\nfunction getPositionedStyle(styles, style, suffix) {\n    const result = {};\n    suffix = suffix ? '-' + suffix : '';\n    for(let i = 0; i < 4; i++){\n        const pos = positions[i];\n        result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;\n    }\n    result.width = result.left + result.right;\n    result.height = result.top + result.bottom;\n    return result;\n}\nconst useOffsetPos = (x, y, target)=>(x > 0 || y > 0) && (!target || !target.shadowRoot);\n/**\n * @param e\n * @param canvas\n * @returns Canvas position\n */ function getCanvasPosition(e, canvas) {\n    const touches = e.touches;\n    const source = touches && touches.length ? touches[0] : e;\n    const { offsetX , offsetY  } = source;\n    let box = false;\n    let x, y;\n    if (useOffsetPos(offsetX, offsetY, e.target)) {\n        x = offsetX;\n        y = offsetY;\n    } else {\n        const rect = canvas.getBoundingClientRect();\n        x = source.clientX - rect.left;\n        y = source.clientY - rect.top;\n        box = true;\n    }\n    return {\n        x,\n        y,\n        box\n    };\n}\n/**\n * Gets an event's x, y coordinates, relative to the chart area\n * @param event\n * @param chart\n * @returns x and y coordinates of the event\n */ function getRelativePosition(event, chart) {\n    if ('native' in event) {\n        return event;\n    }\n    const { canvas , currentDevicePixelRatio  } = chart;\n    const style = getComputedStyle(canvas);\n    const borderBox = style.boxSizing === 'border-box';\n    const paddings = getPositionedStyle(style, 'padding');\n    const borders = getPositionedStyle(style, 'border', 'width');\n    const { x , y , box  } = getCanvasPosition(event, canvas);\n    const xOffset = paddings.left + (box && borders.left);\n    const yOffset = paddings.top + (box && borders.top);\n    let { width , height  } = chart;\n    if (borderBox) {\n        width -= paddings.width + borders.width;\n        height -= paddings.height + borders.height;\n    }\n    return {\n        x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio),\n        y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio)\n    };\n}\nfunction getContainerSize(canvas, width, height) {\n    let maxWidth, maxHeight;\n    if (width === undefined || height === undefined) {\n        const container = _getParentNode(canvas);\n        if (!container) {\n            width = canvas.clientWidth;\n            height = canvas.clientHeight;\n        } else {\n            const rect = container.getBoundingClientRect(); // this is the border box of the container\n            const containerStyle = getComputedStyle(container);\n            const containerBorder = getPositionedStyle(containerStyle, 'border', 'width');\n            const containerPadding = getPositionedStyle(containerStyle, 'padding');\n            width = rect.width - containerPadding.width - containerBorder.width;\n            height = rect.height - containerPadding.height - containerBorder.height;\n            maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth');\n            maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight');\n        }\n    }\n    return {\n        width,\n        height,\n        maxWidth: maxWidth || INFINITY,\n        maxHeight: maxHeight || INFINITY\n    };\n}\nconst round1 = (v)=>Math.round(v * 10) / 10;\n// eslint-disable-next-line complexity\nfunction getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {\n    const style = getComputedStyle(canvas);\n    const margins = getPositionedStyle(style, 'margin');\n    const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY;\n    const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY;\n    const containerSize = getContainerSize(canvas, bbWidth, bbHeight);\n    let { width , height  } = containerSize;\n    if (style.boxSizing === 'content-box') {\n        const borders = getPositionedStyle(style, 'border', 'width');\n        const paddings = getPositionedStyle(style, 'padding');\n        width -= paddings.width + borders.width;\n        height -= paddings.height + borders.height;\n    }\n    width = Math.max(0, width - margins.width);\n    height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height);\n    width = round1(Math.min(width, maxWidth, containerSize.maxWidth));\n    height = round1(Math.min(height, maxHeight, containerSize.maxHeight));\n    if (width && !height) {\n        // https://github.com/chartjs/Chart.js/issues/4659\n        // If the canvas has width, but no height, default to aspectRatio of 2 (canvas default)\n        height = round1(width / 2);\n    }\n    const maintainHeight = bbWidth !== undefined || bbHeight !== undefined;\n    if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) {\n        height = containerSize.height;\n        width = round1(Math.floor(height * aspectRatio));\n    }\n    return {\n        width,\n        height\n    };\n}\n/**\n * @param chart\n * @param forceRatio\n * @param forceStyle\n * @returns True if the canvas context size or transformation has changed.\n */ function retinaScale(chart, forceRatio, forceStyle) {\n    const pixelRatio = forceRatio || 1;\n    const deviceHeight = Math.floor(chart.height * pixelRatio);\n    const deviceWidth = Math.floor(chart.width * pixelRatio);\n    chart.height = Math.floor(chart.height);\n    chart.width = Math.floor(chart.width);\n    const canvas = chart.canvas;\n    // If no style has been set on the canvas, the render size is used as display size,\n    // making the chart visually bigger, so let's enforce it to the \"correct\" values.\n    // See https://github.com/chartjs/Chart.js/issues/3575\n    if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) {\n        canvas.style.height = `${chart.height}px`;\n        canvas.style.width = `${chart.width}px`;\n    }\n    if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) {\n        chart.currentDevicePixelRatio = pixelRatio;\n        canvas.height = deviceHeight;\n        canvas.width = deviceWidth;\n        chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n        return true;\n    }\n    return false;\n}\n/**\n * Detects support for options object argument in addEventListener.\n * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support\n * @private\n */ const supportsEventListenerOptions = function() {\n    let passiveSupported = false;\n    try {\n        const options = {\n            get passive () {\n                passiveSupported = true;\n                return false;\n            }\n        };\n        if (_isDomSupported()) {\n            window.addEventListener('test', null, options);\n            window.removeEventListener('test', null, options);\n        }\n    } catch (e) {\n    // continue regardless of error\n    }\n    return passiveSupported;\n}();\n/**\n * The \"used\" size is the final value of a dimension property after all calculations have\n * been performed. This method uses the computed style of `element` but returns undefined\n * if the computed style is not expressed in pixels. That can happen in some cases where\n * `element` has a size relative to its parent and this last one is not yet displayed,\n * for example because of `display: none` on a parent node.\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value\n * @returns Size in pixels or undefined if unknown.\n */ function readUsedSize(element, property) {\n    const value = getStyle(element, property);\n    const matches = value && value.match(/^(\\d+)(\\.\\d+)?px$/);\n    return matches ? +matches[1] : undefined;\n}\n\n/**\n * @private\n */ function _pointInLine(p1, p2, t, mode) {\n    return {\n        x: p1.x + t * (p2.x - p1.x),\n        y: p1.y + t * (p2.y - p1.y)\n    };\n}\n/**\n * @private\n */ function _steppedInterpolation(p1, p2, t, mode) {\n    return {\n        x: p1.x + t * (p2.x - p1.x),\n        y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y : mode === 'after' ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y\n    };\n}\n/**\n * @private\n */ function _bezierInterpolation(p1, p2, t, mode) {\n    const cp1 = {\n        x: p1.cp2x,\n        y: p1.cp2y\n    };\n    const cp2 = {\n        x: p2.cp1x,\n        y: p2.cp1y\n    };\n    const a = _pointInLine(p1, cp1, t);\n    const b = _pointInLine(cp1, cp2, t);\n    const c = _pointInLine(cp2, p2, t);\n    const d = _pointInLine(a, b, t);\n    const e = _pointInLine(b, c, t);\n    return _pointInLine(d, e, t);\n}\n\nconst getRightToLeftAdapter = function(rectX, width) {\n    return {\n        x (x) {\n            return rectX + rectX + width - x;\n        },\n        setWidth (w) {\n            width = w;\n        },\n        textAlign (align) {\n            if (align === 'center') {\n                return align;\n            }\n            return align === 'right' ? 'left' : 'right';\n        },\n        xPlus (x, value) {\n            return x - value;\n        },\n        leftForLtr (x, itemWidth) {\n            return x - itemWidth;\n        }\n    };\n};\nconst getLeftToRightAdapter = function() {\n    return {\n        x (x) {\n            return x;\n        },\n        setWidth (w) {},\n        textAlign (align) {\n            return align;\n        },\n        xPlus (x, value) {\n            return x + value;\n        },\n        leftForLtr (x, _itemWidth) {\n            return x;\n        }\n    };\n};\nfunction getRtlAdapter(rtl, rectX, width) {\n    return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();\n}\nfunction overrideTextDirection(ctx, direction) {\n    let style, original;\n    if (direction === 'ltr' || direction === 'rtl') {\n        style = ctx.canvas.style;\n        original = [\n            style.getPropertyValue('direction'),\n            style.getPropertyPriority('direction')\n        ];\n        style.setProperty('direction', direction, 'important');\n        ctx.prevTextDirection = original;\n    }\n}\nfunction restoreTextDirection(ctx, original) {\n    if (original !== undefined) {\n        delete ctx.prevTextDirection;\n        ctx.canvas.style.setProperty('direction', original[0], original[1]);\n    }\n}\n\nfunction propertyFn(property) {\n    if (property === 'angle') {\n        return {\n            between: _angleBetween,\n            compare: _angleDiff,\n            normalize: _normalizeAngle\n        };\n    }\n    return {\n        between: _isBetween,\n        compare: (a, b)=>a - b,\n        normalize: (x)=>x\n    };\n}\nfunction normalizeSegment({ start , end , count , loop , style  }) {\n    return {\n        start: start % count,\n        end: end % count,\n        loop: loop && (end - start + 1) % count === 0,\n        style\n    };\n}\nfunction getSegment(segment, points, bounds) {\n    const { property , start: startBound , end: endBound  } = bounds;\n    const { between , normalize  } = propertyFn(property);\n    const count = points.length;\n    let { start , end , loop  } = segment;\n    let i, ilen;\n    if (loop) {\n        start += count;\n        end += count;\n        for(i = 0, ilen = count; i < ilen; ++i){\n            if (!between(normalize(points[start % count][property]), startBound, endBound)) {\n                break;\n            }\n            start--;\n            end--;\n        }\n        start %= count;\n        end %= count;\n    }\n    if (end < start) {\n        end += count;\n    }\n    return {\n        start,\n        end,\n        loop,\n        style: segment.style\n    };\n}\n function _boundSegment(segment, points, bounds) {\n    if (!bounds) {\n        return [\n            segment\n        ];\n    }\n    const { property , start: startBound , end: endBound  } = bounds;\n    const count = points.length;\n    const { compare , between , normalize  } = propertyFn(property);\n    const { start , end , loop , style  } = getSegment(segment, points, bounds);\n    const result = [];\n    let inside = false;\n    let subStart = null;\n    let value, point, prevValue;\n    const startIsBefore = ()=>between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0;\n    const endIsBefore = ()=>compare(endBound, value) === 0 || between(endBound, prevValue, value);\n    const shouldStart = ()=>inside || startIsBefore();\n    const shouldStop = ()=>!inside || endIsBefore();\n    for(let i = start, prev = start; i <= end; ++i){\n        point = points[i % count];\n        if (point.skip) {\n            continue;\n        }\n        value = normalize(point[property]);\n        if (value === prevValue) {\n            continue;\n        }\n        inside = between(value, startBound, endBound);\n        if (subStart === null && shouldStart()) {\n            subStart = compare(value, startBound) === 0 ? i : prev;\n        }\n        if (subStart !== null && shouldStop()) {\n            result.push(normalizeSegment({\n                start: subStart,\n                end: i,\n                loop,\n                count,\n                style\n            }));\n            subStart = null;\n        }\n        prev = i;\n        prevValue = value;\n    }\n    if (subStart !== null) {\n        result.push(normalizeSegment({\n            start: subStart,\n            end,\n            loop,\n            count,\n            style\n        }));\n    }\n    return result;\n}\n function _boundSegments(line, bounds) {\n    const result = [];\n    const segments = line.segments;\n    for(let i = 0; i < segments.length; i++){\n        const sub = _boundSegment(segments[i], line.points, bounds);\n        if (sub.length) {\n            result.push(...sub);\n        }\n    }\n    return result;\n}\n function findStartAndEnd(points, count, loop, spanGaps) {\n    let start = 0;\n    let end = count - 1;\n    if (loop && !spanGaps) {\n        while(start < count && !points[start].skip){\n            start++;\n        }\n    }\n    while(start < count && points[start].skip){\n        start++;\n    }\n    start %= count;\n    if (loop) {\n        end += start;\n    }\n    while(end > start && points[end % count].skip){\n        end--;\n    }\n    end %= count;\n    return {\n        start,\n        end\n    };\n}\n function solidSegments(points, start, max, loop) {\n    const count = points.length;\n    const result = [];\n    let last = start;\n    let prev = points[start];\n    let end;\n    for(end = start + 1; end <= max; ++end){\n        const cur = points[end % count];\n        if (cur.skip || cur.stop) {\n            if (!prev.skip) {\n                loop = false;\n                result.push({\n                    start: start % count,\n                    end: (end - 1) % count,\n                    loop\n                });\n                start = last = cur.stop ? end : null;\n            }\n        } else {\n            last = end;\n            if (prev.skip) {\n                start = end;\n            }\n        }\n        prev = cur;\n    }\n    if (last !== null) {\n        result.push({\n            start: start % count,\n            end: last % count,\n            loop\n        });\n    }\n    return result;\n}\n function _computeSegments(line, segmentOptions) {\n    const points = line.points;\n    const spanGaps = line.options.spanGaps;\n    const count = points.length;\n    if (!count) {\n        return [];\n    }\n    const loop = !!line._loop;\n    const { start , end  } = findStartAndEnd(points, count, loop, spanGaps);\n    if (spanGaps === true) {\n        return splitByStyles(line, [\n            {\n                start,\n                end,\n                loop\n            }\n        ], points, segmentOptions);\n    }\n    const max = end < start ? end + count : end;\n    const completeLoop = !!line._fullLoop && start === 0 && end === count - 1;\n    return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions);\n}\n function splitByStyles(line, segments, points, segmentOptions) {\n    if (!segmentOptions || !segmentOptions.setContext || !points) {\n        return segments;\n    }\n    return doSplitByStyles(line, segments, points, segmentOptions);\n}\n function doSplitByStyles(line, segments, points, segmentOptions) {\n    const chartContext = line._chart.getContext();\n    const baseStyle = readStyle(line.options);\n    const { _datasetIndex: datasetIndex , options: { spanGaps  }  } = line;\n    const count = points.length;\n    const result = [];\n    let prevStyle = baseStyle;\n    let start = segments[0].start;\n    let i = start;\n    function addStyle(s, e, l, st) {\n        const dir = spanGaps ? -1 : 1;\n        if (s === e) {\n            return;\n        }\n        s += count;\n        while(points[s % count].skip){\n            s -= dir;\n        }\n        while(points[e % count].skip){\n            e += dir;\n        }\n        if (s % count !== e % count) {\n            result.push({\n                start: s % count,\n                end: e % count,\n                loop: l,\n                style: st\n            });\n            prevStyle = st;\n            start = e % count;\n        }\n    }\n    for (const segment of segments){\n        start = spanGaps ? start : segment.start;\n        let prev = points[start % count];\n        let style;\n        for(i = start + 1; i <= segment.end; i++){\n            const pt = points[i % count];\n            style = readStyle(segmentOptions.setContext(createContext(chartContext, {\n                type: 'segment',\n                p0: prev,\n                p1: pt,\n                p0DataIndex: (i - 1) % count,\n                p1DataIndex: i % count,\n                datasetIndex\n            })));\n            if (styleChanged(style, prevStyle)) {\n                addStyle(start, i - 1, segment.loop, prevStyle);\n            }\n            prev = pt;\n            prevStyle = style;\n        }\n        if (start < i - 1) {\n            addStyle(start, i - 1, segment.loop, prevStyle);\n        }\n    }\n    return result;\n}\nfunction readStyle(options) {\n    return {\n        backgroundColor: options.backgroundColor,\n        borderCapStyle: options.borderCapStyle,\n        borderDash: options.borderDash,\n        borderDashOffset: options.borderDashOffset,\n        borderJoinStyle: options.borderJoinStyle,\n        borderWidth: options.borderWidth,\n        borderColor: options.borderColor\n    };\n}\nfunction styleChanged(style, prevStyle) {\n    if (!prevStyle) {\n        return false;\n    }\n    const cache = [];\n    const replacer = function(key, value) {\n        if (!isPatternOrGradient(value)) {\n            return value;\n        }\n        if (!cache.includes(value)) {\n            cache.push(value);\n        }\n        return cache.indexOf(value);\n    };\n    return JSON.stringify(style, replacer) !== JSON.stringify(prevStyle, replacer);\n}\n\nexport { unclipArea as $, _rlookupByKey as A, _lookupByKey as B, _isPointInArea as C, getAngleFromPoint as D, toPadding as E, each as F, getMaximumSize as G, HALF_PI as H, _getParentNode as I, readUsedSize as J, supportsEventListenerOptions as K, throttled as L, _isDomSupported as M, _factorize as N, finiteOrDefault as O, PI as P, callback as Q, _addGrace as R, _limitValue as S, TAU as T, toDegrees as U, _measureText as V, _int16Range as W, _alignPixel as X, clipArea as Y, renderText as Z, _arrayUnique as _, resolve as a, fontString as a$, toFont as a0, _toLeftRightCenter as a1, _alignStartEnd as a2, overrides as a3, merge as a4, _capitalize as a5, descriptors as a6, isFunction as a7, _attachContext as a8, _createResolver as a9, overrideTextDirection as aA, _textX as aB, restoreTextDirection as aC, drawPointLegend as aD, distanceBetweenPoints as aE, noop as aF, _setMinAndMaxByKey as aG, niceNum as aH, almostWhole as aI, almostEquals as aJ, _decimalPlaces as aK, Ticks as aL, log10 as aM, _longestText as aN, _filterBetween as aO, _lookup as aP, isPatternOrGradient as aQ, getHoverColor as aR, clone as aS, _merger as aT, _mergerIf as aU, _deprecated as aV, _splitKey as aW, toFontString as aX, splineCurve as aY, splineCurveMonotone as aZ, getStyle as a_, _descriptors as aa, mergeIf as ab, uid as ac, debounce as ad, retinaScale as ae, clearCanvas as af, setsEqual as ag, _elementsEqual as ah, _isClickEvent as ai, _isBetween as aj, _readValueToProps as ak, _updateBezierControlPoints as al, _computeSegments as am, _boundSegments as an, _steppedInterpolation as ao, _bezierInterpolation as ap, _pointInLine as aq, _steppedLineTo as ar, _bezierCurveTo as as, drawPoint as at, addRoundedRectPath as au, toTRBL as av, toTRBLCorners as aw, _boundSegment as ax, _normalizeAngle as ay, getRtlAdapter as az, isArray as b, toLineHeight as b0, PITAU as b1, INFINITY as b2, RAD_PER_DEG as b3, QUARTER_PI as b4, TWO_THIRDS_PI as b5, _angleDiff as b6, color as c, defaults as d, effects as e, resolveObjectKey as f, isNumberFinite as g, defined as h, isObject as i, createContext as j, isNullOrUndef as k, listenArrayEvents as l, toPercentage as m, toDimension as n, formatNumber as o, _angleBetween as p, _getStartAndCountOfVisiblePoints as q, requestAnimFrame as r, sign as s, toRadians as t, unlistenArrayEvents as u, valueOrDefault as v, _scaleRangesChanged as w, isNumber as x, _parseObjectDataRadialScale as y, getRelativePosition as z };\n//# sourceMappingURL=helpers.segment.js.map\n","/*!\n * Chart.js v4.4.2\n * https://www.chartjs.org\n * (c) 2024 Chart.js Contributors\n * Released under the MIT License\n */\nimport { r as requestAnimFrame, a as resolve, e as effects, c as color, i as isObject, d as defaults, b as isArray, v as valueOrDefault, u as unlistenArrayEvents, l as listenArrayEvents, f as resolveObjectKey, g as isNumberFinite, h as defined, s as sign, j as createContext, k as isNullOrUndef, _ as _arrayUnique, t as toRadians, m as toPercentage, n as toDimension, T as TAU, o as formatNumber, p as _angleBetween, H as HALF_PI, P as PI, q as _getStartAndCountOfVisiblePoints, w as _scaleRangesChanged, x as isNumber, y as _parseObjectDataRadialScale, z as getRelativePosition, A as _rlookupByKey, B as _lookupByKey, C as _isPointInArea, D as getAngleFromPoint, E as toPadding, F as each, G as getMaximumSize, I as _getParentNode, J as readUsedSize, K as supportsEventListenerOptions, L as throttled, M as _isDomSupported, N as _factorize, O as finiteOrDefault, Q as callback, R as _addGrace, S as _limitValue, U as toDegrees, V as _measureText, W as _int16Range, X as _alignPixel, Y as clipArea, Z as renderText, $ as unclipArea, a0 as toFont, a1 as _toLeftRightCenter, a2 as _alignStartEnd, a3 as overrides, a4 as merge, a5 as _capitalize, a6 as descriptors, a7 as isFunction, a8 as _attachContext, a9 as _createResolver, aa as _descriptors, ab as mergeIf, ac as uid, ad as debounce, ae as retinaScale, af as clearCanvas, ag as setsEqual, ah as _elementsEqual, ai as _isClickEvent, aj as _isBetween, ak as _readValueToProps, al as _updateBezierControlPoints, am as _computeSegments, an as _boundSegments, ao as _steppedInterpolation, ap as _bezierInterpolation, aq as _pointInLine, ar as _steppedLineTo, as as _bezierCurveTo, at as drawPoint, au as addRoundedRectPath, av as toTRBL, aw as toTRBLCorners, ax as _boundSegment, ay as _normalizeAngle, az as getRtlAdapter, aA as overrideTextDirection, aB as _textX, aC as restoreTextDirection, aD as drawPointLegend, aE as distanceBetweenPoints, aF as noop, aG as _setMinAndMaxByKey, aH as niceNum, aI as almostWhole, aJ as almostEquals, aK as _decimalPlaces, aL as Ticks, aM as log10, aN as _longestText, aO as _filterBetween, aP as _lookup } from './chunks/helpers.segment.js';\nimport '@kurkle/color';\n\nclass Animator {\n    constructor(){\n        this._request = null;\n        this._charts = new Map();\n        this._running = false;\n        this._lastDate = undefined;\n    }\n _notify(chart, anims, date, type) {\n        const callbacks = anims.listeners[type];\n        const numSteps = anims.duration;\n        callbacks.forEach((fn)=>fn({\n                chart,\n                initial: anims.initial,\n                numSteps,\n                currentStep: Math.min(date - anims.start, numSteps)\n            }));\n    }\n _refresh() {\n        if (this._request) {\n            return;\n        }\n        this._running = true;\n        this._request = requestAnimFrame.call(window, ()=>{\n            this._update();\n            this._request = null;\n            if (this._running) {\n                this._refresh();\n            }\n        });\n    }\n _update(date = Date.now()) {\n        let remaining = 0;\n        this._charts.forEach((anims, chart)=>{\n            if (!anims.running || !anims.items.length) {\n                return;\n            }\n            const items = anims.items;\n            let i = items.length - 1;\n            let draw = false;\n            let item;\n            for(; i >= 0; --i){\n                item = items[i];\n                if (item._active) {\n                    if (item._total > anims.duration) {\n                        anims.duration = item._total;\n                    }\n                    item.tick(date);\n                    draw = true;\n                } else {\n                    items[i] = items[items.length - 1];\n                    items.pop();\n                }\n            }\n            if (draw) {\n                chart.draw();\n                this._notify(chart, anims, date, 'progress');\n            }\n            if (!items.length) {\n                anims.running = false;\n                this._notify(chart, anims, date, 'complete');\n                anims.initial = false;\n            }\n            remaining += items.length;\n        });\n        this._lastDate = date;\n        if (remaining === 0) {\n            this._running = false;\n        }\n    }\n _getAnims(chart) {\n        const charts = this._charts;\n        let anims = charts.get(chart);\n        if (!anims) {\n            anims = {\n                running: false,\n                initial: true,\n                items: [],\n                listeners: {\n                    complete: [],\n                    progress: []\n                }\n            };\n            charts.set(chart, anims);\n        }\n        return anims;\n    }\n listen(chart, event, cb) {\n        this._getAnims(chart).listeners[event].push(cb);\n    }\n add(chart, items) {\n        if (!items || !items.length) {\n            return;\n        }\n        this._getAnims(chart).items.push(...items);\n    }\n has(chart) {\n        return this._getAnims(chart).items.length > 0;\n    }\n start(chart) {\n        const anims = this._charts.get(chart);\n        if (!anims) {\n            return;\n        }\n        anims.running = true;\n        anims.start = Date.now();\n        anims.duration = anims.items.reduce((acc, cur)=>Math.max(acc, cur._duration), 0);\n        this._refresh();\n    }\n    running(chart) {\n        if (!this._running) {\n            return false;\n        }\n        const anims = this._charts.get(chart);\n        if (!anims || !anims.running || !anims.items.length) {\n            return false;\n        }\n        return true;\n    }\n stop(chart) {\n        const anims = this._charts.get(chart);\n        if (!anims || !anims.items.length) {\n            return;\n        }\n        const items = anims.items;\n        let i = items.length - 1;\n        for(; i >= 0; --i){\n            items[i].cancel();\n        }\n        anims.items = [];\n        this._notify(chart, anims, Date.now(), 'complete');\n    }\n remove(chart) {\n        return this._charts.delete(chart);\n    }\n}\nvar animator = /* #__PURE__ */ new Animator();\n\nconst transparent = 'transparent';\nconst interpolators = {\n    boolean (from, to, factor) {\n        return factor > 0.5 ? to : from;\n    },\n color (from, to, factor) {\n        const c0 = color(from || transparent);\n        const c1 = c0.valid && color(to || transparent);\n        return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to;\n    },\n    number (from, to, factor) {\n        return from + (to - from) * factor;\n    }\n};\nclass Animation {\n    constructor(cfg, target, prop, to){\n        const currentValue = target[prop];\n        to = resolve([\n            cfg.to,\n            to,\n            currentValue,\n            cfg.from\n        ]);\n        const from = resolve([\n            cfg.from,\n            currentValue,\n            to\n        ]);\n        this._active = true;\n        this._fn = cfg.fn || interpolators[cfg.type || typeof from];\n        this._easing = effects[cfg.easing] || effects.linear;\n        this._start = Math.floor(Date.now() + (cfg.delay || 0));\n        this._duration = this._total = Math.floor(cfg.duration);\n        this._loop = !!cfg.loop;\n        this._target = target;\n        this._prop = prop;\n        this._from = from;\n        this._to = to;\n        this._promises = undefined;\n    }\n    active() {\n        return this._active;\n    }\n    update(cfg, to, date) {\n        if (this._active) {\n            this._notify(false);\n            const currentValue = this._target[this._prop];\n            const elapsed = date - this._start;\n            const remain = this._duration - elapsed;\n            this._start = date;\n            this._duration = Math.floor(Math.max(remain, cfg.duration));\n            this._total += elapsed;\n            this._loop = !!cfg.loop;\n            this._to = resolve([\n                cfg.to,\n                to,\n                currentValue,\n                cfg.from\n            ]);\n            this._from = resolve([\n                cfg.from,\n                currentValue,\n                to\n            ]);\n        }\n    }\n    cancel() {\n        if (this._active) {\n            this.tick(Date.now());\n            this._active = false;\n            this._notify(false);\n        }\n    }\n    tick(date) {\n        const elapsed = date - this._start;\n        const duration = this._duration;\n        const prop = this._prop;\n        const from = this._from;\n        const loop = this._loop;\n        const to = this._to;\n        let factor;\n        this._active = from !== to && (loop || elapsed < duration);\n        if (!this._active) {\n            this._target[prop] = to;\n            this._notify(true);\n            return;\n        }\n        if (elapsed < 0) {\n            this._target[prop] = from;\n            return;\n        }\n        factor = elapsed / duration % 2;\n        factor = loop && factor > 1 ? 2 - factor : factor;\n        factor = this._easing(Math.min(1, Math.max(0, factor)));\n        this._target[prop] = this._fn(from, to, factor);\n    }\n    wait() {\n        const promises = this._promises || (this._promises = []);\n        return new Promise((res, rej)=>{\n            promises.push({\n                res,\n                rej\n            });\n        });\n    }\n    _notify(resolved) {\n        const method = resolved ? 'res' : 'rej';\n        const promises = this._promises || [];\n        for(let i = 0; i < promises.length; i++){\n            promises[i][method]();\n        }\n    }\n}\n\nclass Animations {\n    constructor(chart, config){\n        this._chart = chart;\n        this._properties = new Map();\n        this.configure(config);\n    }\n    configure(config) {\n        if (!isObject(config)) {\n            return;\n        }\n        const animationOptions = Object.keys(defaults.animation);\n        const animatedProps = this._properties;\n        Object.getOwnPropertyNames(config).forEach((key)=>{\n            const cfg = config[key];\n            if (!isObject(cfg)) {\n                return;\n            }\n            const resolved = {};\n            for (const option of animationOptions){\n                resolved[option] = cfg[option];\n            }\n            (isArray(cfg.properties) && cfg.properties || [\n                key\n            ]).forEach((prop)=>{\n                if (prop === key || !animatedProps.has(prop)) {\n                    animatedProps.set(prop, resolved);\n                }\n            });\n        });\n    }\n _animateOptions(target, values) {\n        const newOptions = values.options;\n        const options = resolveTargetOptions(target, newOptions);\n        if (!options) {\n            return [];\n        }\n        const animations = this._createAnimations(options, newOptions);\n        if (newOptions.$shared) {\n            awaitAll(target.options.$animations, newOptions).then(()=>{\n                target.options = newOptions;\n            }, ()=>{\n            });\n        }\n        return animations;\n    }\n _createAnimations(target, values) {\n        const animatedProps = this._properties;\n        const animations = [];\n        const running = target.$animations || (target.$animations = {});\n        const props = Object.keys(values);\n        const date = Date.now();\n        let i;\n        for(i = props.length - 1; i >= 0; --i){\n            const prop = props[i];\n            if (prop.charAt(0) === '$') {\n                continue;\n            }\n            if (prop === 'options') {\n                animations.push(...this._animateOptions(target, values));\n                continue;\n            }\n            const value = values[prop];\n            let animation = running[prop];\n            const cfg = animatedProps.get(prop);\n            if (animation) {\n                if (cfg && animation.active()) {\n                    animation.update(cfg, value, date);\n                    continue;\n                } else {\n                    animation.cancel();\n                }\n            }\n            if (!cfg || !cfg.duration) {\n                target[prop] = value;\n                continue;\n            }\n            running[prop] = animation = new Animation(cfg, target, prop, value);\n            animations.push(animation);\n        }\n        return animations;\n    }\n update(target, values) {\n        if (this._properties.size === 0) {\n            Object.assign(target, values);\n            return;\n        }\n        const animations = this._createAnimations(target, values);\n        if (animations.length) {\n            animator.add(this._chart, animations);\n            return true;\n        }\n    }\n}\nfunction awaitAll(animations, properties) {\n    const running = [];\n    const keys = Object.keys(properties);\n    for(let i = 0; i < keys.length; i++){\n        const anim = animations[keys[i]];\n        if (anim && anim.active()) {\n            running.push(anim.wait());\n        }\n    }\n    return Promise.all(running);\n}\nfunction resolveTargetOptions(target, newOptions) {\n    if (!newOptions) {\n        return;\n    }\n    let options = target.options;\n    if (!options) {\n        target.options = newOptions;\n        return;\n    }\n    if (options.$shared) {\n        target.options = options = Object.assign({}, options, {\n            $shared: false,\n            $animations: {}\n        });\n    }\n    return options;\n}\n\nfunction scaleClip(scale, allowedOverflow) {\n    const opts = scale && scale.options || {};\n    const reverse = opts.reverse;\n    const min = opts.min === undefined ? allowedOverflow : 0;\n    const max = opts.max === undefined ? allowedOverflow : 0;\n    return {\n        start: reverse ? max : min,\n        end: reverse ? min : max\n    };\n}\nfunction defaultClip(xScale, yScale, allowedOverflow) {\n    if (allowedOverflow === false) {\n        return false;\n    }\n    const x = scaleClip(xScale, allowedOverflow);\n    const y = scaleClip(yScale, allowedOverflow);\n    return {\n        top: y.end,\n        right: x.end,\n        bottom: y.start,\n        left: x.start\n    };\n}\nfunction toClip(value) {\n    let t, r, b, l;\n    if (isObject(value)) {\n        t = value.top;\n        r = value.right;\n        b = value.bottom;\n        l = value.left;\n    } else {\n        t = r = b = l = value;\n    }\n    return {\n        top: t,\n        right: r,\n        bottom: b,\n        left: l,\n        disabled: value === false\n    };\n}\nfunction getSortedDatasetIndices(chart, filterVisible) {\n    const keys = [];\n    const metasets = chart._getSortedDatasetMetas(filterVisible);\n    let i, ilen;\n    for(i = 0, ilen = metasets.length; i < ilen; ++i){\n        keys.push(metasets[i].index);\n    }\n    return keys;\n}\nfunction applyStack(stack, value, dsIndex, options = {}) {\n    const keys = stack.keys;\n    const singleMode = options.mode === 'single';\n    let i, ilen, datasetIndex, otherValue;\n    if (value === null) {\n        return;\n    }\n    for(i = 0, ilen = keys.length; i < ilen; ++i){\n        datasetIndex = +keys[i];\n        if (datasetIndex === dsIndex) {\n            if (options.all) {\n                continue;\n            }\n            break;\n        }\n        otherValue = stack.values[datasetIndex];\n        if (isNumberFinite(otherValue) && (singleMode || value === 0 || sign(value) === sign(otherValue))) {\n            value += otherValue;\n        }\n    }\n    return value;\n}\nfunction convertObjectDataToArray(data) {\n    const keys = Object.keys(data);\n    const adata = new Array(keys.length);\n    let i, ilen, key;\n    for(i = 0, ilen = keys.length; i < ilen; ++i){\n        key = keys[i];\n        adata[i] = {\n            x: key,\n            y: data[key]\n        };\n    }\n    return adata;\n}\nfunction isStacked(scale, meta) {\n    const stacked = scale && scale.options.stacked;\n    return stacked || stacked === undefined && meta.stack !== undefined;\n}\nfunction getStackKey(indexScale, valueScale, meta) {\n    return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;\n}\nfunction getUserBounds(scale) {\n    const { min , max , minDefined , maxDefined  } = scale.getUserBounds();\n    return {\n        min: minDefined ? min : Number.NEGATIVE_INFINITY,\n        max: maxDefined ? max : Number.POSITIVE_INFINITY\n    };\n}\nfunction getOrCreateStack(stacks, stackKey, indexValue) {\n    const subStack = stacks[stackKey] || (stacks[stackKey] = {});\n    return subStack[indexValue] || (subStack[indexValue] = {});\n}\nfunction getLastIndexInStack(stack, vScale, positive, type) {\n    for (const meta of vScale.getMatchingVisibleMetas(type).reverse()){\n        const value = stack[meta.index];\n        if (positive && value > 0 || !positive && value < 0) {\n            return meta.index;\n        }\n    }\n    return null;\n}\nfunction updateStacks(controller, parsed) {\n    const { chart , _cachedMeta: meta  } = controller;\n    const stacks = chart._stacks || (chart._stacks = {});\n    const { iScale , vScale , index: datasetIndex  } = meta;\n    const iAxis = iScale.axis;\n    const vAxis = vScale.axis;\n    const key = getStackKey(iScale, vScale, meta);\n    const ilen = parsed.length;\n    let stack;\n    for(let i = 0; i < ilen; ++i){\n        const item = parsed[i];\n        const { [iAxis]: index , [vAxis]: value  } = item;\n        const itemStacks = item._stacks || (item._stacks = {});\n        stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);\n        stack[datasetIndex] = value;\n        stack._top = getLastIndexInStack(stack, vScale, true, meta.type);\n        stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);\n        const visualValues = stack._visualValues || (stack._visualValues = {});\n        visualValues[datasetIndex] = value;\n    }\n}\nfunction getFirstScaleId(chart, axis) {\n    const scales = chart.scales;\n    return Object.keys(scales).filter((key)=>scales[key].axis === axis).shift();\n}\nfunction createDatasetContext(parent, index) {\n    return createContext(parent, {\n        active: false,\n        dataset: undefined,\n        datasetIndex: index,\n        index,\n        mode: 'default',\n        type: 'dataset'\n    });\n}\nfunction createDataContext(parent, index, element) {\n    return createContext(parent, {\n        active: false,\n        dataIndex: index,\n        parsed: undefined,\n        raw: undefined,\n        element,\n        index,\n        mode: 'default',\n        type: 'data'\n    });\n}\nfunction clearStacks(meta, items) {\n    const datasetIndex = meta.controller.index;\n    const axis = meta.vScale && meta.vScale.axis;\n    if (!axis) {\n        return;\n    }\n    items = items || meta._parsed;\n    for (const parsed of items){\n        const stacks = parsed._stacks;\n        if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) {\n            return;\n        }\n        delete stacks[axis][datasetIndex];\n        if (stacks[axis]._visualValues !== undefined && stacks[axis]._visualValues[datasetIndex] !== undefined) {\n            delete stacks[axis]._visualValues[datasetIndex];\n        }\n    }\n}\nconst isDirectUpdateMode = (mode)=>mode === 'reset' || mode === 'none';\nconst cloneIfNotShared = (cached, shared)=>shared ? cached : Object.assign({}, cached);\nconst createStack = (canStack, meta, chart)=>canStack && !meta.hidden && meta._stacked && {\n        keys: getSortedDatasetIndices(chart, true),\n        values: null\n    };\nclass DatasetController {\n static defaults = {};\n static datasetElementType = null;\n static dataElementType = null;\n constructor(chart, datasetIndex){\n        this.chart = chart;\n        this._ctx = chart.ctx;\n        this.index = datasetIndex;\n        this._cachedDataOpts = {};\n        this._cachedMeta = this.getMeta();\n        this._type = this._cachedMeta.type;\n        this.options = undefined;\n         this._parsing = false;\n        this._data = undefined;\n        this._objectData = undefined;\n        this._sharedOptions = undefined;\n        this._drawStart = undefined;\n        this._drawCount = undefined;\n        this.enableOptionSharing = false;\n        this.supportsDecimation = false;\n        this.$context = undefined;\n        this._syncList = [];\n        this.datasetElementType = new.target.datasetElementType;\n        this.dataElementType = new.target.dataElementType;\n        this.initialize();\n    }\n    initialize() {\n        const meta = this._cachedMeta;\n        this.configure();\n        this.linkScales();\n        meta._stacked = isStacked(meta.vScale, meta);\n        this.addElements();\n        if (this.options.fill && !this.chart.isPluginEnabled('filler')) {\n            console.warn(\"Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options\");\n        }\n    }\n    updateIndex(datasetIndex) {\n        if (this.index !== datasetIndex) {\n            clearStacks(this._cachedMeta);\n        }\n        this.index = datasetIndex;\n    }\n    linkScales() {\n        const chart = this.chart;\n        const meta = this._cachedMeta;\n        const dataset = this.getDataset();\n        const chooseId = (axis, x, y, r)=>axis === 'x' ? x : axis === 'r' ? r : y;\n        const xid = meta.xAxisID = valueOrDefault(dataset.xAxisID, getFirstScaleId(chart, 'x'));\n        const yid = meta.yAxisID = valueOrDefault(dataset.yAxisID, getFirstScaleId(chart, 'y'));\n        const rid = meta.rAxisID = valueOrDefault(dataset.rAxisID, getFirstScaleId(chart, 'r'));\n        const indexAxis = meta.indexAxis;\n        const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);\n        const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);\n        meta.xScale = this.getScaleForId(xid);\n        meta.yScale = this.getScaleForId(yid);\n        meta.rScale = this.getScaleForId(rid);\n        meta.iScale = this.getScaleForId(iid);\n        meta.vScale = this.getScaleForId(vid);\n    }\n    getDataset() {\n        return this.chart.data.datasets[this.index];\n    }\n    getMeta() {\n        return this.chart.getDatasetMeta(this.index);\n    }\n getScaleForId(scaleID) {\n        return this.chart.scales[scaleID];\n    }\n _getOtherScale(scale) {\n        const meta = this._cachedMeta;\n        return scale === meta.iScale ? meta.vScale : meta.iScale;\n    }\n    reset() {\n        this._update('reset');\n    }\n _destroy() {\n        const meta = this._cachedMeta;\n        if (this._data) {\n            unlistenArrayEvents(this._data, this);\n        }\n        if (meta._stacked) {\n            clearStacks(meta);\n        }\n    }\n _dataCheck() {\n        const dataset = this.getDataset();\n        const data = dataset.data || (dataset.data = []);\n        const _data = this._data;\n        if (isObject(data)) {\n            this._data = convertObjectDataToArray(data);\n        } else if (_data !== data) {\n            if (_data) {\n                unlistenArrayEvents(_data, this);\n                const meta = this._cachedMeta;\n                clearStacks(meta);\n                meta._parsed = [];\n            }\n            if (data && Object.isExtensible(data)) {\n                listenArrayEvents(data, this);\n            }\n            this._syncList = [];\n            this._data = data;\n        }\n    }\n    addElements() {\n        const meta = this._cachedMeta;\n        this._dataCheck();\n        if (this.datasetElementType) {\n            meta.dataset = new this.datasetElementType();\n        }\n    }\n    buildOrUpdateElements(resetNewElements) {\n        const meta = this._cachedMeta;\n        const dataset = this.getDataset();\n        let stackChanged = false;\n        this._dataCheck();\n        const oldStacked = meta._stacked;\n        meta._stacked = isStacked(meta.vScale, meta);\n        if (meta.stack !== dataset.stack) {\n            stackChanged = true;\n            clearStacks(meta);\n            meta.stack = dataset.stack;\n        }\n        this._resyncElements(resetNewElements);\n        if (stackChanged || oldStacked !== meta._stacked) {\n            updateStacks(this, meta._parsed);\n        }\n    }\n configure() {\n        const config = this.chart.config;\n        const scopeKeys = config.datasetScopeKeys(this._type);\n        const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);\n        this.options = config.createResolver(scopes, this.getContext());\n        this._parsing = this.options.parsing;\n        this._cachedDataOpts = {};\n    }\n parse(start, count) {\n        const { _cachedMeta: meta , _data: data  } = this;\n        const { iScale , _stacked  } = meta;\n        const iAxis = iScale.axis;\n        let sorted = start === 0 && count === data.length ? true : meta._sorted;\n        let prev = start > 0 && meta._parsed[start - 1];\n        let i, cur, parsed;\n        if (this._parsing === false) {\n            meta._parsed = data;\n            meta._sorted = true;\n            parsed = data;\n        } else {\n            if (isArray(data[start])) {\n                parsed = this.parseArrayData(meta, data, start, count);\n            } else if (isObject(data[start])) {\n                parsed = this.parseObjectData(meta, data, start, count);\n            } else {\n                parsed = this.parsePrimitiveData(meta, data, start, count);\n            }\n            const isNotInOrderComparedToPrev = ()=>cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis];\n            for(i = 0; i < count; ++i){\n                meta._parsed[i + start] = cur = parsed[i];\n                if (sorted) {\n                    if (isNotInOrderComparedToPrev()) {\n                        sorted = false;\n                    }\n                    prev = cur;\n                }\n            }\n            meta._sorted = sorted;\n        }\n        if (_stacked) {\n            updateStacks(this, parsed);\n        }\n    }\n parsePrimitiveData(meta, data, start, count) {\n        const { iScale , vScale  } = meta;\n        const iAxis = iScale.axis;\n        const vAxis = vScale.axis;\n        const labels = iScale.getLabels();\n        const singleScale = iScale === vScale;\n        const parsed = new Array(count);\n        let i, ilen, index;\n        for(i = 0, ilen = count; i < ilen; ++i){\n            index = i + start;\n            parsed[i] = {\n                [iAxis]: singleScale || iScale.parse(labels[index], index),\n                [vAxis]: vScale.parse(data[index], index)\n            };\n        }\n        return parsed;\n    }\n parseArrayData(meta, data, start, count) {\n        const { xScale , yScale  } = meta;\n        const parsed = new Array(count);\n        let i, ilen, index, item;\n        for(i = 0, ilen = count; i < ilen; ++i){\n            index = i + start;\n            item = data[index];\n            parsed[i] = {\n                x: xScale.parse(item[0], index),\n                y: yScale.parse(item[1], index)\n            };\n        }\n        return parsed;\n    }\n parseObjectData(meta, data, start, count) {\n        const { xScale , yScale  } = meta;\n        const { xAxisKey ='x' , yAxisKey ='y'  } = this._parsing;\n        const parsed = new Array(count);\n        let i, ilen, index, item;\n        for(i = 0, ilen = count; i < ilen; ++i){\n            index = i + start;\n            item = data[index];\n            parsed[i] = {\n                x: xScale.parse(resolveObjectKey(item, xAxisKey), index),\n                y: yScale.parse(resolveObjectKey(item, yAxisKey), index)\n            };\n        }\n        return parsed;\n    }\n getParsed(index) {\n        return this._cachedMeta._parsed[index];\n    }\n getDataElement(index) {\n        return this._cachedMeta.data[index];\n    }\n applyStack(scale, parsed, mode) {\n        const chart = this.chart;\n        const meta = this._cachedMeta;\n        const value = parsed[scale.axis];\n        const stack = {\n            keys: getSortedDatasetIndices(chart, true),\n            values: parsed._stacks[scale.axis]._visualValues\n        };\n        return applyStack(stack, value, meta.index, {\n            mode\n        });\n    }\n updateRangeFromParsed(range, scale, parsed, stack) {\n        const parsedValue = parsed[scale.axis];\n        let value = parsedValue === null ? NaN : parsedValue;\n        const values = stack && parsed._stacks[scale.axis];\n        if (stack && values) {\n            stack.values = values;\n            value = applyStack(stack, parsedValue, this._cachedMeta.index);\n        }\n        range.min = Math.min(range.min, value);\n        range.max = Math.max(range.max, value);\n    }\n getMinMax(scale, canStack) {\n        const meta = this._cachedMeta;\n        const _parsed = meta._parsed;\n        const sorted = meta._sorted && scale === meta.iScale;\n        const ilen = _parsed.length;\n        const otherScale = this._getOtherScale(scale);\n        const stack = createStack(canStack, meta, this.chart);\n        const range = {\n            min: Number.POSITIVE_INFINITY,\n            max: Number.NEGATIVE_INFINITY\n        };\n        const { min: otherMin , max: otherMax  } = getUserBounds(otherScale);\n        let i, parsed;\n        function _skip() {\n            parsed = _parsed[i];\n            const otherValue = parsed[otherScale.axis];\n            return !isNumberFinite(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;\n        }\n        for(i = 0; i < ilen; ++i){\n            if (_skip()) {\n                continue;\n            }\n            this.updateRangeFromParsed(range, scale, parsed, stack);\n            if (sorted) {\n                break;\n            }\n        }\n        if (sorted) {\n            for(i = ilen - 1; i >= 0; --i){\n                if (_skip()) {\n                    continue;\n                }\n                this.updateRangeFromParsed(range, scale, parsed, stack);\n                break;\n            }\n        }\n        return range;\n    }\n    getAllParsedValues(scale) {\n        const parsed = this._cachedMeta._parsed;\n        const values = [];\n        let i, ilen, value;\n        for(i = 0, ilen = parsed.length; i < ilen; ++i){\n            value = parsed[i][scale.axis];\n            if (isNumberFinite(value)) {\n                values.push(value);\n            }\n        }\n        return values;\n    }\n getMaxOverflow() {\n        return false;\n    }\n getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const iScale = meta.iScale;\n        const vScale = meta.vScale;\n        const parsed = this.getParsed(index);\n        return {\n            label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',\n            value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''\n        };\n    }\n _update(mode) {\n        const meta = this._cachedMeta;\n        this.update(mode || 'default');\n        meta._clip = toClip(valueOrDefault(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));\n    }\n update(mode) {}\n    draw() {\n        const ctx = this._ctx;\n        const chart = this.chart;\n        const meta = this._cachedMeta;\n        const elements = meta.data || [];\n        const area = chart.chartArea;\n        const active = [];\n        const start = this._drawStart || 0;\n        const count = this._drawCount || elements.length - start;\n        const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop;\n        let i;\n        if (meta.dataset) {\n            meta.dataset.draw(ctx, area, start, count);\n        }\n        for(i = start; i < start + count; ++i){\n            const element = elements[i];\n            if (element.hidden) {\n                continue;\n            }\n            if (element.active && drawActiveElementsOnTop) {\n                active.push(element);\n            } else {\n                element.draw(ctx, area);\n            }\n        }\n        for(i = 0; i < active.length; ++i){\n            active[i].draw(ctx, area);\n        }\n    }\n getStyle(index, active) {\n        const mode = active ? 'active' : 'default';\n        return index === undefined && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode);\n    }\n getContext(index, active, mode) {\n        const dataset = this.getDataset();\n        let context;\n        if (index >= 0 && index < this._cachedMeta.data.length) {\n            const element = this._cachedMeta.data[index];\n            context = element.$context || (element.$context = createDataContext(this.getContext(), index, element));\n            context.parsed = this.getParsed(index);\n            context.raw = dataset.data[index];\n            context.index = context.dataIndex = index;\n        } else {\n            context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index));\n            context.dataset = dataset;\n            context.index = context.datasetIndex = this.index;\n        }\n        context.active = !!active;\n        context.mode = mode;\n        return context;\n    }\n resolveDatasetElementOptions(mode) {\n        return this._resolveElementOptions(this.datasetElementType.id, mode);\n    }\n resolveDataElementOptions(index, mode) {\n        return this._resolveElementOptions(this.dataElementType.id, mode, index);\n    }\n _resolveElementOptions(elementType, mode = 'default', index) {\n        const active = mode === 'active';\n        const cache = this._cachedDataOpts;\n        const cacheKey = elementType + '-' + mode;\n        const cached = cache[cacheKey];\n        const sharing = this.enableOptionSharing && defined(index);\n        if (cached) {\n            return cloneIfNotShared(cached, sharing);\n        }\n        const config = this.chart.config;\n        const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);\n        const prefixes = active ? [\n            `${elementType}Hover`,\n            'hover',\n            elementType,\n            ''\n        ] : [\n            elementType,\n            ''\n        ];\n        const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);\n        const names = Object.keys(defaults.elements[elementType]);\n        const context = ()=>this.getContext(index, active, mode);\n        const values = config.resolveNamedOptions(scopes, names, context, prefixes);\n        if (values.$shared) {\n            values.$shared = sharing;\n            cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));\n        }\n        return values;\n    }\n _resolveAnimations(index, transition, active) {\n        const chart = this.chart;\n        const cache = this._cachedDataOpts;\n        const cacheKey = `animation-${transition}`;\n        const cached = cache[cacheKey];\n        if (cached) {\n            return cached;\n        }\n        let options;\n        if (chart.options.animation !== false) {\n            const config = this.chart.config;\n            const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);\n            const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);\n            options = config.createResolver(scopes, this.getContext(index, active, transition));\n        }\n        const animations = new Animations(chart, options && options.animations);\n        if (options && options._cacheable) {\n            cache[cacheKey] = Object.freeze(animations);\n        }\n        return animations;\n    }\n getSharedOptions(options) {\n        if (!options.$shared) {\n            return;\n        }\n        return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));\n    }\n includeOptions(mode, sharedOptions) {\n        return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;\n    }\n _getSharedOptions(start, mode) {\n        const firstOpts = this.resolveDataElementOptions(start, mode);\n        const previouslySharedOptions = this._sharedOptions;\n        const sharedOptions = this.getSharedOptions(firstOpts);\n        const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions;\n        this.updateSharedOptions(sharedOptions, mode, firstOpts);\n        return {\n            sharedOptions,\n            includeOptions\n        };\n    }\n updateElement(element, index, properties, mode) {\n        if (isDirectUpdateMode(mode)) {\n            Object.assign(element, properties);\n        } else {\n            this._resolveAnimations(index, mode).update(element, properties);\n        }\n    }\n updateSharedOptions(sharedOptions, mode, newOptions) {\n        if (sharedOptions && !isDirectUpdateMode(mode)) {\n            this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions);\n        }\n    }\n _setStyle(element, index, mode, active) {\n        element.active = active;\n        const options = this.getStyle(index, active);\n        this._resolveAnimations(index, mode, active).update(element, {\n            options: !active && this.getSharedOptions(options) || options\n        });\n    }\n    removeHoverStyle(element, datasetIndex, index) {\n        this._setStyle(element, index, 'active', false);\n    }\n    setHoverStyle(element, datasetIndex, index) {\n        this._setStyle(element, index, 'active', true);\n    }\n _removeDatasetHoverStyle() {\n        const element = this._cachedMeta.dataset;\n        if (element) {\n            this._setStyle(element, undefined, 'active', false);\n        }\n    }\n _setDatasetHoverStyle() {\n        const element = this._cachedMeta.dataset;\n        if (element) {\n            this._setStyle(element, undefined, 'active', true);\n        }\n    }\n _resyncElements(resetNewElements) {\n        const data = this._data;\n        const elements = this._cachedMeta.data;\n        for (const [method, arg1, arg2] of this._syncList){\n            this[method](arg1, arg2);\n        }\n        this._syncList = [];\n        const numMeta = elements.length;\n        const numData = data.length;\n        const count = Math.min(numData, numMeta);\n        if (count) {\n            this.parse(0, count);\n        }\n        if (numData > numMeta) {\n            this._insertElements(numMeta, numData - numMeta, resetNewElements);\n        } else if (numData < numMeta) {\n            this._removeElements(numData, numMeta - numData);\n        }\n    }\n _insertElements(start, count, resetNewElements = true) {\n        const meta = this._cachedMeta;\n        const data = meta.data;\n        const end = start + count;\n        let i;\n        const move = (arr)=>{\n            arr.length += count;\n            for(i = arr.length - 1; i >= end; i--){\n                arr[i] = arr[i - count];\n            }\n        };\n        move(data);\n        for(i = start; i < end; ++i){\n            data[i] = new this.dataElementType();\n        }\n        if (this._parsing) {\n            move(meta._parsed);\n        }\n        this.parse(start, count);\n        if (resetNewElements) {\n            this.updateElements(data, start, count, 'reset');\n        }\n    }\n    updateElements(element, start, count, mode) {}\n _removeElements(start, count) {\n        const meta = this._cachedMeta;\n        if (this._parsing) {\n            const removed = meta._parsed.splice(start, count);\n            if (meta._stacked) {\n                clearStacks(meta, removed);\n            }\n        }\n        meta.data.splice(start, count);\n    }\n _sync(args) {\n        if (this._parsing) {\n            this._syncList.push(args);\n        } else {\n            const [method, arg1, arg2] = args;\n            this[method](arg1, arg2);\n        }\n        this.chart._dataChanges.push([\n            this.index,\n            ...args\n        ]);\n    }\n    _onDataPush() {\n        const count = arguments.length;\n        this._sync([\n            '_insertElements',\n            this.getDataset().data.length - count,\n            count\n        ]);\n    }\n    _onDataPop() {\n        this._sync([\n            '_removeElements',\n            this._cachedMeta.data.length - 1,\n            1\n        ]);\n    }\n    _onDataShift() {\n        this._sync([\n            '_removeElements',\n            0,\n            1\n        ]);\n    }\n    _onDataSplice(start, count) {\n        if (count) {\n            this._sync([\n                '_removeElements',\n                start,\n                count\n            ]);\n        }\n        const newCount = arguments.length - 2;\n        if (newCount) {\n            this._sync([\n                '_insertElements',\n                start,\n                newCount\n            ]);\n        }\n    }\n    _onDataUnshift() {\n        this._sync([\n            '_insertElements',\n            0,\n            arguments.length\n        ]);\n    }\n}\n\nfunction getAllScaleValues(scale, type) {\n    if (!scale._cache.$bar) {\n        const visibleMetas = scale.getMatchingVisibleMetas(type);\n        let values = [];\n        for(let i = 0, ilen = visibleMetas.length; i < ilen; i++){\n            values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale));\n        }\n        scale._cache.$bar = _arrayUnique(values.sort((a, b)=>a - b));\n    }\n    return scale._cache.$bar;\n}\n function computeMinSampleSize(meta) {\n    const scale = meta.iScale;\n    const values = getAllScaleValues(scale, meta.type);\n    let min = scale._length;\n    let i, ilen, curr, prev;\n    const updateMinAndPrev = ()=>{\n        if (curr === 32767 || curr === -32768) {\n            return;\n        }\n        if (defined(prev)) {\n            min = Math.min(min, Math.abs(curr - prev) || min);\n        }\n        prev = curr;\n    };\n    for(i = 0, ilen = values.length; i < ilen; ++i){\n        curr = scale.getPixelForValue(values[i]);\n        updateMinAndPrev();\n    }\n    prev = undefined;\n    for(i = 0, ilen = scale.ticks.length; i < ilen; ++i){\n        curr = scale.getPixelForTick(i);\n        updateMinAndPrev();\n    }\n    return min;\n}\n function computeFitCategoryTraits(index, ruler, options, stackCount) {\n    const thickness = options.barThickness;\n    let size, ratio;\n    if (isNullOrUndef(thickness)) {\n        size = ruler.min * options.categoryPercentage;\n        ratio = options.barPercentage;\n    } else {\n        size = thickness * stackCount;\n        ratio = 1;\n    }\n    return {\n        chunk: size / stackCount,\n        ratio,\n        start: ruler.pixels[index] - size / 2\n    };\n}\n function computeFlexCategoryTraits(index, ruler, options, stackCount) {\n    const pixels = ruler.pixels;\n    const curr = pixels[index];\n    let prev = index > 0 ? pixels[index - 1] : null;\n    let next = index < pixels.length - 1 ? pixels[index + 1] : null;\n    const percent = options.categoryPercentage;\n    if (prev === null) {\n        prev = curr - (next === null ? ruler.end - ruler.start : next - curr);\n    }\n    if (next === null) {\n        next = curr + curr - prev;\n    }\n    const start = curr - (curr - Math.min(prev, next)) / 2 * percent;\n    const size = Math.abs(next - prev) / 2 * percent;\n    return {\n        chunk: size / stackCount,\n        ratio: options.barPercentage,\n        start\n    };\n}\nfunction parseFloatBar(entry, item, vScale, i) {\n    const startValue = vScale.parse(entry[0], i);\n    const endValue = vScale.parse(entry[1], i);\n    const min = Math.min(startValue, endValue);\n    const max = Math.max(startValue, endValue);\n    let barStart = min;\n    let barEnd = max;\n    if (Math.abs(min) > Math.abs(max)) {\n        barStart = max;\n        barEnd = min;\n    }\n    item[vScale.axis] = barEnd;\n    item._custom = {\n        barStart,\n        barEnd,\n        start: startValue,\n        end: endValue,\n        min,\n        max\n    };\n}\nfunction parseValue(entry, item, vScale, i) {\n    if (isArray(entry)) {\n        parseFloatBar(entry, item, vScale, i);\n    } else {\n        item[vScale.axis] = vScale.parse(entry, i);\n    }\n    return item;\n}\nfunction parseArrayOrPrimitive(meta, data, start, count) {\n    const iScale = meta.iScale;\n    const vScale = meta.vScale;\n    const labels = iScale.getLabels();\n    const singleScale = iScale === vScale;\n    const parsed = [];\n    let i, ilen, item, entry;\n    for(i = start, ilen = start + count; i < ilen; ++i){\n        entry = data[i];\n        item = {};\n        item[iScale.axis] = singleScale || iScale.parse(labels[i], i);\n        parsed.push(parseValue(entry, item, vScale, i));\n    }\n    return parsed;\n}\nfunction isFloatBar(custom) {\n    return custom && custom.barStart !== undefined && custom.barEnd !== undefined;\n}\nfunction barSign(size, vScale, actualBase) {\n    if (size !== 0) {\n        return sign(size);\n    }\n    return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);\n}\nfunction borderProps(properties) {\n    let reverse, start, end, top, bottom;\n    if (properties.horizontal) {\n        reverse = properties.base > properties.x;\n        start = 'left';\n        end = 'right';\n    } else {\n        reverse = properties.base < properties.y;\n        start = 'bottom';\n        end = 'top';\n    }\n    if (reverse) {\n        top = 'end';\n        bottom = 'start';\n    } else {\n        top = 'start';\n        bottom = 'end';\n    }\n    return {\n        start,\n        end,\n        reverse,\n        top,\n        bottom\n    };\n}\nfunction setBorderSkipped(properties, options, stack, index) {\n    let edge = options.borderSkipped;\n    const res = {};\n    if (!edge) {\n        properties.borderSkipped = res;\n        return;\n    }\n    if (edge === true) {\n        properties.borderSkipped = {\n            top: true,\n            right: true,\n            bottom: true,\n            left: true\n        };\n        return;\n    }\n    const { start , end , reverse , top , bottom  } = borderProps(properties);\n    if (edge === 'middle' && stack) {\n        properties.enableBorderRadius = true;\n        if ((stack._top || 0) === index) {\n            edge = top;\n        } else if ((stack._bottom || 0) === index) {\n            edge = bottom;\n        } else {\n            res[parseEdge(bottom, start, end, reverse)] = true;\n            edge = top;\n        }\n    }\n    res[parseEdge(edge, start, end, reverse)] = true;\n    properties.borderSkipped = res;\n}\nfunction parseEdge(edge, a, b, reverse) {\n    if (reverse) {\n        edge = swap(edge, a, b);\n        edge = startEnd(edge, b, a);\n    } else {\n        edge = startEnd(edge, a, b);\n    }\n    return edge;\n}\nfunction swap(orig, v1, v2) {\n    return orig === v1 ? v2 : orig === v2 ? v1 : orig;\n}\nfunction startEnd(v, start, end) {\n    return v === 'start' ? start : v === 'end' ? end : v;\n}\nfunction setInflateAmount(properties, { inflateAmount  }, ratio) {\n    properties.inflateAmount = inflateAmount === 'auto' ? ratio === 1 ? 0.33 : 0 : inflateAmount;\n}\nclass BarController extends DatasetController {\n    static id = 'bar';\n static defaults = {\n        datasetElementType: false,\n        dataElementType: 'bar',\n        categoryPercentage: 0.8,\n        barPercentage: 0.9,\n        grouped: true,\n        animations: {\n            numbers: {\n                type: 'number',\n                properties: [\n                    'x',\n                    'y',\n                    'base',\n                    'width',\n                    'height'\n                ]\n            }\n        }\n    };\n static overrides = {\n        scales: {\n            _index_: {\n                type: 'category',\n                offset: true,\n                grid: {\n                    offset: true\n                }\n            },\n            _value_: {\n                type: 'linear',\n                beginAtZero: true\n            }\n        }\n    };\n parsePrimitiveData(meta, data, start, count) {\n        return parseArrayOrPrimitive(meta, data, start, count);\n    }\n parseArrayData(meta, data, start, count) {\n        return parseArrayOrPrimitive(meta, data, start, count);\n    }\n parseObjectData(meta, data, start, count) {\n        const { iScale , vScale  } = meta;\n        const { xAxisKey ='x' , yAxisKey ='y'  } = this._parsing;\n        const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey;\n        const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey;\n        const parsed = [];\n        let i, ilen, item, obj;\n        for(i = start, ilen = start + count; i < ilen; ++i){\n            obj = data[i];\n            item = {};\n            item[iScale.axis] = iScale.parse(resolveObjectKey(obj, iAxisKey), i);\n            parsed.push(parseValue(resolveObjectKey(obj, vAxisKey), item, vScale, i));\n        }\n        return parsed;\n    }\n updateRangeFromParsed(range, scale, parsed, stack) {\n        super.updateRangeFromParsed(range, scale, parsed, stack);\n        const custom = parsed._custom;\n        if (custom && scale === this._cachedMeta.vScale) {\n            range.min = Math.min(range.min, custom.min);\n            range.max = Math.max(range.max, custom.max);\n        }\n    }\n getMaxOverflow() {\n        return 0;\n    }\n getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const { iScale , vScale  } = meta;\n        const parsed = this.getParsed(index);\n        const custom = parsed._custom;\n        const value = isFloatBar(custom) ? '[' + custom.start + ', ' + custom.end + ']' : '' + vScale.getLabelForValue(parsed[vScale.axis]);\n        return {\n            label: '' + iScale.getLabelForValue(parsed[iScale.axis]),\n            value\n        };\n    }\n    initialize() {\n        this.enableOptionSharing = true;\n        super.initialize();\n        const meta = this._cachedMeta;\n        meta.stack = this.getDataset().stack;\n    }\n    update(mode) {\n        const meta = this._cachedMeta;\n        this.updateElements(meta.data, 0, meta.data.length, mode);\n    }\n    updateElements(bars, start, count, mode) {\n        const reset = mode === 'reset';\n        const { index , _cachedMeta: { vScale  }  } = this;\n        const base = vScale.getBasePixel();\n        const horizontal = vScale.isHorizontal();\n        const ruler = this._getRuler();\n        const { sharedOptions , includeOptions  } = this._getSharedOptions(start, mode);\n        for(let i = start; i < start + count; i++){\n            const parsed = this.getParsed(i);\n            const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {\n                base,\n                head: base\n            } : this._calculateBarValuePixels(i);\n            const ipixels = this._calculateBarIndexPixels(i, ruler);\n            const stack = (parsed._stacks || {})[vScale.axis];\n            const properties = {\n                horizontal,\n                base: vpixels.base,\n                enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom,\n                x: horizontal ? vpixels.head : ipixels.center,\n                y: horizontal ? ipixels.center : vpixels.head,\n                height: horizontal ? ipixels.size : Math.abs(vpixels.size),\n                width: horizontal ? Math.abs(vpixels.size) : ipixels.size\n            };\n            if (includeOptions) {\n                properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);\n            }\n            const options = properties.options || bars[i].options;\n            setBorderSkipped(properties, options, stack, index);\n            setInflateAmount(properties, options, ruler.ratio);\n            this.updateElement(bars[i], i, properties, mode);\n        }\n    }\n _getStacks(last, dataIndex) {\n        const { iScale  } = this._cachedMeta;\n        const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta)=>meta.controller.options.grouped);\n        const stacked = iScale.options.stacked;\n        const stacks = [];\n        const skipNull = (meta)=>{\n            const parsed = meta.controller.getParsed(dataIndex);\n            const val = parsed && parsed[meta.vScale.axis];\n            if (isNullOrUndef(val) || isNaN(val)) {\n                return true;\n            }\n        };\n        for (const meta of metasets){\n            if (dataIndex !== undefined && skipNull(meta)) {\n                continue;\n            }\n            if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === undefined && meta.stack === undefined) {\n                stacks.push(meta.stack);\n            }\n            if (meta.index === last) {\n                break;\n            }\n        }\n        if (!stacks.length) {\n            stacks.push(undefined);\n        }\n        return stacks;\n    }\n _getStackCount(index) {\n        return this._getStacks(undefined, index).length;\n    }\n _getStackIndex(datasetIndex, name, dataIndex) {\n        const stacks = this._getStacks(datasetIndex, dataIndex);\n        const index = name !== undefined ? stacks.indexOf(name) : -1;\n        return index === -1 ? stacks.length - 1 : index;\n    }\n _getRuler() {\n        const opts = this.options;\n        const meta = this._cachedMeta;\n        const iScale = meta.iScale;\n        const pixels = [];\n        let i, ilen;\n        for(i = 0, ilen = meta.data.length; i < ilen; ++i){\n            pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));\n        }\n        const barThickness = opts.barThickness;\n        const min = barThickness || computeMinSampleSize(meta);\n        return {\n            min,\n            pixels,\n            start: iScale._startPixel,\n            end: iScale._endPixel,\n            stackCount: this._getStackCount(),\n            scale: iScale,\n            grouped: opts.grouped,\n            ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage\n        };\n    }\n _calculateBarValuePixels(index) {\n        const { _cachedMeta: { vScale , _stacked , index: datasetIndex  } , options: { base: baseValue , minBarLength  }  } = this;\n        const actualBase = baseValue || 0;\n        const parsed = this.getParsed(index);\n        const custom = parsed._custom;\n        const floating = isFloatBar(custom);\n        let value = parsed[vScale.axis];\n        let start = 0;\n        let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;\n        let head, size;\n        if (length !== value) {\n            start = length - value;\n            length = value;\n        }\n        if (floating) {\n            value = custom.barStart;\n            length = custom.barEnd - custom.barStart;\n            if (value !== 0 && sign(value) !== sign(custom.barEnd)) {\n                start = 0;\n            }\n            start += value;\n        }\n        const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start;\n        let base = vScale.getPixelForValue(startValue);\n        if (this.chart.getDataVisibility(index)) {\n            head = vScale.getPixelForValue(start + length);\n        } else {\n            head = base;\n        }\n        size = head - base;\n        if (Math.abs(size) < minBarLength) {\n            size = barSign(size, vScale, actualBase) * minBarLength;\n            if (value === actualBase) {\n                base -= size / 2;\n            }\n            const startPixel = vScale.getPixelForDecimal(0);\n            const endPixel = vScale.getPixelForDecimal(1);\n            const min = Math.min(startPixel, endPixel);\n            const max = Math.max(startPixel, endPixel);\n            base = Math.max(Math.min(base, max), min);\n            head = base + size;\n            if (_stacked && !floating) {\n                parsed._stacks[vScale.axis]._visualValues[datasetIndex] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base);\n            }\n        }\n        if (base === vScale.getPixelForValue(actualBase)) {\n            const halfGrid = sign(size) * vScale.getLineWidthForValue(actualBase) / 2;\n            base += halfGrid;\n            size -= halfGrid;\n        }\n        return {\n            size,\n            base,\n            head,\n            center: head + size / 2\n        };\n    }\n _calculateBarIndexPixels(index, ruler) {\n        const scale = ruler.scale;\n        const options = this.options;\n        const skipNull = options.skipNull;\n        const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);\n        let center, size;\n        if (ruler.grouped) {\n            const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;\n            const range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options, stackCount) : computeFitCategoryTraits(index, ruler, options, stackCount);\n            const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined);\n            center = range.start + range.chunk * stackIndex + range.chunk / 2;\n            size = Math.min(maxBarThickness, range.chunk * range.ratio);\n        } else {\n            center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);\n            size = Math.min(maxBarThickness, ruler.min * ruler.ratio);\n        }\n        return {\n            base: center - size / 2,\n            head: center + size / 2,\n            center,\n            size\n        };\n    }\n    draw() {\n        const meta = this._cachedMeta;\n        const vScale = meta.vScale;\n        const rects = meta.data;\n        const ilen = rects.length;\n        let i = 0;\n        for(; i < ilen; ++i){\n            if (this.getParsed(i)[vScale.axis] !== null) {\n                rects[i].draw(this._ctx);\n            }\n        }\n    }\n}\n\nclass BubbleController extends DatasetController {\n    static id = 'bubble';\n static defaults = {\n        datasetElementType: false,\n        dataElementType: 'point',\n        animations: {\n            numbers: {\n                type: 'number',\n                properties: [\n                    'x',\n                    'y',\n                    'borderWidth',\n                    'radius'\n                ]\n            }\n        }\n    };\n static overrides = {\n        scales: {\n            x: {\n                type: 'linear'\n            },\n            y: {\n                type: 'linear'\n            }\n        }\n    };\n    initialize() {\n        this.enableOptionSharing = true;\n        super.initialize();\n    }\n parsePrimitiveData(meta, data, start, count) {\n        const parsed = super.parsePrimitiveData(meta, data, start, count);\n        for(let i = 0; i < parsed.length; i++){\n            parsed[i]._custom = this.resolveDataElementOptions(i + start).radius;\n        }\n        return parsed;\n    }\n parseArrayData(meta, data, start, count) {\n        const parsed = super.parseArrayData(meta, data, start, count);\n        for(let i = 0; i < parsed.length; i++){\n            const item = data[start + i];\n            parsed[i]._custom = valueOrDefault(item[2], this.resolveDataElementOptions(i + start).radius);\n        }\n        return parsed;\n    }\n parseObjectData(meta, data, start, count) {\n        const parsed = super.parseObjectData(meta, data, start, count);\n        for(let i = 0; i < parsed.length; i++){\n            const item = data[start + i];\n            parsed[i]._custom = valueOrDefault(item && item.r && +item.r, this.resolveDataElementOptions(i + start).radius);\n        }\n        return parsed;\n    }\n getMaxOverflow() {\n        const data = this._cachedMeta.data;\n        let max = 0;\n        for(let i = data.length - 1; i >= 0; --i){\n            max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);\n        }\n        return max > 0 && max;\n    }\n getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const labels = this.chart.data.labels || [];\n        const { xScale , yScale  } = meta;\n        const parsed = this.getParsed(index);\n        const x = xScale.getLabelForValue(parsed.x);\n        const y = yScale.getLabelForValue(parsed.y);\n        const r = parsed._custom;\n        return {\n            label: labels[index] || '',\n            value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')'\n        };\n    }\n    update(mode) {\n        const points = this._cachedMeta.data;\n        this.updateElements(points, 0, points.length, mode);\n    }\n    updateElements(points, start, count, mode) {\n        const reset = mode === 'reset';\n        const { iScale , vScale  } = this._cachedMeta;\n        const { sharedOptions , includeOptions  } = this._getSharedOptions(start, mode);\n        const iAxis = iScale.axis;\n        const vAxis = vScale.axis;\n        for(let i = start; i < start + count; i++){\n            const point = points[i];\n            const parsed = !reset && this.getParsed(i);\n            const properties = {};\n            const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]);\n            const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]);\n            properties.skip = isNaN(iPixel) || isNaN(vPixel);\n            if (includeOptions) {\n                properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n                if (reset) {\n                    properties.options.radius = 0;\n                }\n            }\n            this.updateElement(point, i, properties, mode);\n        }\n    }\n resolveDataElementOptions(index, mode) {\n        const parsed = this.getParsed(index);\n        let values = super.resolveDataElementOptions(index, mode);\n        if (values.$shared) {\n            values = Object.assign({}, values, {\n                $shared: false\n            });\n        }\n        const radius = values.radius;\n        if (mode !== 'active') {\n            values.radius = 0;\n        }\n        values.radius += valueOrDefault(parsed && parsed._custom, radius);\n        return values;\n    }\n}\n\nfunction getRatioAndOffset(rotation, circumference, cutout) {\n    let ratioX = 1;\n    let ratioY = 1;\n    let offsetX = 0;\n    let offsetY = 0;\n    if (circumference < TAU) {\n        const startAngle = rotation;\n        const endAngle = startAngle + circumference;\n        const startX = Math.cos(startAngle);\n        const startY = Math.sin(startAngle);\n        const endX = Math.cos(endAngle);\n        const endY = Math.sin(endAngle);\n        const calcMax = (angle, a, b)=>_angleBetween(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout);\n        const calcMin = (angle, a, b)=>_angleBetween(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout);\n        const maxX = calcMax(0, startX, endX);\n        const maxY = calcMax(HALF_PI, startY, endY);\n        const minX = calcMin(PI, startX, endX);\n        const minY = calcMin(PI + HALF_PI, startY, endY);\n        ratioX = (maxX - minX) / 2;\n        ratioY = (maxY - minY) / 2;\n        offsetX = -(maxX + minX) / 2;\n        offsetY = -(maxY + minY) / 2;\n    }\n    return {\n        ratioX,\n        ratioY,\n        offsetX,\n        offsetY\n    };\n}\nclass DoughnutController extends DatasetController {\n    static id = 'doughnut';\n static defaults = {\n        datasetElementType: false,\n        dataElementType: 'arc',\n        animation: {\n            animateRotate: true,\n            animateScale: false\n        },\n        animations: {\n            numbers: {\n                type: 'number',\n                properties: [\n                    'circumference',\n                    'endAngle',\n                    'innerRadius',\n                    'outerRadius',\n                    'startAngle',\n                    'x',\n                    'y',\n                    'offset',\n                    'borderWidth',\n                    'spacing'\n                ]\n            }\n        },\n        cutout: '50%',\n        rotation: 0,\n        circumference: 360,\n        radius: '100%',\n        spacing: 0,\n        indexAxis: 'r'\n    };\n    static descriptors = {\n        _scriptable: (name)=>name !== 'spacing',\n        _indexable: (name)=>name !== 'spacing' && !name.startsWith('borderDash') && !name.startsWith('hoverBorderDash')\n    };\n static overrides = {\n        aspectRatio: 1,\n        plugins: {\n            legend: {\n                labels: {\n                    generateLabels (chart) {\n                        const data = chart.data;\n                        if (data.labels.length && data.datasets.length) {\n                            const { labels: { pointStyle , color  }  } = chart.legend.options;\n                            return data.labels.map((label, i)=>{\n                                const meta = chart.getDatasetMeta(0);\n                                const style = meta.controller.getStyle(i);\n                                return {\n                                    text: label,\n                                    fillStyle: style.backgroundColor,\n                                    strokeStyle: style.borderColor,\n                                    fontColor: color,\n                                    lineWidth: style.borderWidth,\n                                    pointStyle: pointStyle,\n                                    hidden: !chart.getDataVisibility(i),\n                                    index: i\n                                };\n                            });\n                        }\n                        return [];\n                    }\n                },\n                onClick (e, legendItem, legend) {\n                    legend.chart.toggleDataVisibility(legendItem.index);\n                    legend.chart.update();\n                }\n            }\n        }\n    };\n    constructor(chart, datasetIndex){\n        super(chart, datasetIndex);\n        this.enableOptionSharing = true;\n        this.innerRadius = undefined;\n        this.outerRadius = undefined;\n        this.offsetX = undefined;\n        this.offsetY = undefined;\n    }\n    linkScales() {}\n parse(start, count) {\n        const data = this.getDataset().data;\n        const meta = this._cachedMeta;\n        if (this._parsing === false) {\n            meta._parsed = data;\n        } else {\n            let getter = (i)=>+data[i];\n            if (isObject(data[start])) {\n                const { key ='value'  } = this._parsing;\n                getter = (i)=>+resolveObjectKey(data[i], key);\n            }\n            let i, ilen;\n            for(i = start, ilen = start + count; i < ilen; ++i){\n                meta._parsed[i] = getter(i);\n            }\n        }\n    }\n _getRotation() {\n        return toRadians(this.options.rotation - 90);\n    }\n _getCircumference() {\n        return toRadians(this.options.circumference);\n    }\n _getRotationExtents() {\n        let min = TAU;\n        let max = -TAU;\n        for(let i = 0; i < this.chart.data.datasets.length; ++i){\n            if (this.chart.isDatasetVisible(i) && this.chart.getDatasetMeta(i).type === this._type) {\n                const controller = this.chart.getDatasetMeta(i).controller;\n                const rotation = controller._getRotation();\n                const circumference = controller._getCircumference();\n                min = Math.min(min, rotation);\n                max = Math.max(max, rotation + circumference);\n            }\n        }\n        return {\n            rotation: min,\n            circumference: max - min\n        };\n    }\n update(mode) {\n        const chart = this.chart;\n        const { chartArea  } = chart;\n        const meta = this._cachedMeta;\n        const arcs = meta.data;\n        const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;\n        const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);\n        const cutout = Math.min(toPercentage(this.options.cutout, maxSize), 1);\n        const chartWeight = this._getRingWeight(this.index);\n        const { circumference , rotation  } = this._getRotationExtents();\n        const { ratioX , ratioY , offsetX , offsetY  } = getRatioAndOffset(rotation, circumference, cutout);\n        const maxWidth = (chartArea.width - spacing) / ratioX;\n        const maxHeight = (chartArea.height - spacing) / ratioY;\n        const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);\n        const outerRadius = toDimension(this.options.radius, maxRadius);\n        const innerRadius = Math.max(outerRadius * cutout, 0);\n        const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();\n        this.offsetX = offsetX * outerRadius;\n        this.offsetY = offsetY * outerRadius;\n        meta.total = this.calculateTotal();\n        this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);\n        this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);\n        this.updateElements(arcs, 0, arcs.length, mode);\n    }\n _circumference(i, reset) {\n        const opts = this.options;\n        const meta = this._cachedMeta;\n        const circumference = this._getCircumference();\n        if (reset && opts.animation.animateRotate || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {\n            return 0;\n        }\n        return this.calculateCircumference(meta._parsed[i] * circumference / TAU);\n    }\n    updateElements(arcs, start, count, mode) {\n        const reset = mode === 'reset';\n        const chart = this.chart;\n        const chartArea = chart.chartArea;\n        const opts = chart.options;\n        const animationOpts = opts.animation;\n        const centerX = (chartArea.left + chartArea.right) / 2;\n        const centerY = (chartArea.top + chartArea.bottom) / 2;\n        const animateScale = reset && animationOpts.animateScale;\n        const innerRadius = animateScale ? 0 : this.innerRadius;\n        const outerRadius = animateScale ? 0 : this.outerRadius;\n        const { sharedOptions , includeOptions  } = this._getSharedOptions(start, mode);\n        let startAngle = this._getRotation();\n        let i;\n        for(i = 0; i < start; ++i){\n            startAngle += this._circumference(i, reset);\n        }\n        for(i = start; i < start + count; ++i){\n            const circumference = this._circumference(i, reset);\n            const arc = arcs[i];\n            const properties = {\n                x: centerX + this.offsetX,\n                y: centerY + this.offsetY,\n                startAngle,\n                endAngle: startAngle + circumference,\n                circumference,\n                outerRadius,\n                innerRadius\n            };\n            if (includeOptions) {\n                properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);\n            }\n            startAngle += circumference;\n            this.updateElement(arc, i, properties, mode);\n        }\n    }\n    calculateTotal() {\n        const meta = this._cachedMeta;\n        const metaData = meta.data;\n        let total = 0;\n        let i;\n        for(i = 0; i < metaData.length; i++){\n            const value = meta._parsed[i];\n            if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {\n                total += Math.abs(value);\n            }\n        }\n        return total;\n    }\n    calculateCircumference(value) {\n        const total = this._cachedMeta.total;\n        if (total > 0 && !isNaN(value)) {\n            return TAU * (Math.abs(value) / total);\n        }\n        return 0;\n    }\n    getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const chart = this.chart;\n        const labels = chart.data.labels || [];\n        const value = formatNumber(meta._parsed[index], chart.options.locale);\n        return {\n            label: labels[index] || '',\n            value\n        };\n    }\n    getMaxBorderWidth(arcs) {\n        let max = 0;\n        const chart = this.chart;\n        let i, ilen, meta, controller, options;\n        if (!arcs) {\n            for(i = 0, ilen = chart.data.datasets.length; i < ilen; ++i){\n                if (chart.isDatasetVisible(i)) {\n                    meta = chart.getDatasetMeta(i);\n                    arcs = meta.data;\n                    controller = meta.controller;\n                    break;\n                }\n            }\n        }\n        if (!arcs) {\n            return 0;\n        }\n        for(i = 0, ilen = arcs.length; i < ilen; ++i){\n            options = controller.resolveDataElementOptions(i);\n            if (options.borderAlign !== 'inner') {\n                max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0);\n            }\n        }\n        return max;\n    }\n    getMaxOffset(arcs) {\n        let max = 0;\n        for(let i = 0, ilen = arcs.length; i < ilen; ++i){\n            const options = this.resolveDataElementOptions(i);\n            max = Math.max(max, options.offset || 0, options.hoverOffset || 0);\n        }\n        return max;\n    }\n _getRingWeightOffset(datasetIndex) {\n        let ringWeightOffset = 0;\n        for(let i = 0; i < datasetIndex; ++i){\n            if (this.chart.isDatasetVisible(i)) {\n                ringWeightOffset += this._getRingWeight(i);\n            }\n        }\n        return ringWeightOffset;\n    }\n _getRingWeight(datasetIndex) {\n        return Math.max(valueOrDefault(this.chart.data.datasets[datasetIndex].weight, 1), 0);\n    }\n _getVisibleDatasetWeightTotal() {\n        return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;\n    }\n}\n\nclass LineController extends DatasetController {\n    static id = 'line';\n static defaults = {\n        datasetElementType: 'line',\n        dataElementType: 'point',\n        showLine: true,\n        spanGaps: false\n    };\n static overrides = {\n        scales: {\n            _index_: {\n                type: 'category'\n            },\n            _value_: {\n                type: 'linear'\n            }\n        }\n    };\n    initialize() {\n        this.enableOptionSharing = true;\n        this.supportsDecimation = true;\n        super.initialize();\n    }\n    update(mode) {\n        const meta = this._cachedMeta;\n        const { dataset: line , data: points = [] , _dataset  } = meta;\n        const animationsDisabled = this.chart._animationsDisabled;\n        let { start , count  } = _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled);\n        this._drawStart = start;\n        this._drawCount = count;\n        if (_scaleRangesChanged(meta)) {\n            start = 0;\n            count = points.length;\n        }\n        line._chart = this.chart;\n        line._datasetIndex = this.index;\n        line._decimated = !!_dataset._decimated;\n        line.points = points;\n        const options = this.resolveDatasetElementOptions(mode);\n        if (!this.options.showLine) {\n            options.borderWidth = 0;\n        }\n        options.segment = this.options.segment;\n        this.updateElement(line, undefined, {\n            animated: !animationsDisabled,\n            options\n        }, mode);\n        this.updateElements(points, start, count, mode);\n    }\n    updateElements(points, start, count, mode) {\n        const reset = mode === 'reset';\n        const { iScale , vScale , _stacked , _dataset  } = this._cachedMeta;\n        const { sharedOptions , includeOptions  } = this._getSharedOptions(start, mode);\n        const iAxis = iScale.axis;\n        const vAxis = vScale.axis;\n        const { spanGaps , segment  } = this.options;\n        const maxGapLength = isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;\n        const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';\n        const end = start + count;\n        const pointsCount = points.length;\n        let prevParsed = start > 0 && this.getParsed(start - 1);\n        for(let i = 0; i < pointsCount; ++i){\n            const point = points[i];\n            const properties = directUpdate ? point : {};\n            if (i < start || i >= end) {\n                properties.skip = true;\n                continue;\n            }\n            const parsed = this.getParsed(i);\n            const nullData = isNullOrUndef(parsed[vAxis]);\n            const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);\n            const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);\n            properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;\n            properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;\n            if (segment) {\n                properties.parsed = parsed;\n                properties.raw = _dataset.data[i];\n            }\n            if (includeOptions) {\n                properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n            }\n            if (!directUpdate) {\n                this.updateElement(point, i, properties, mode);\n            }\n            prevParsed = parsed;\n        }\n    }\n getMaxOverflow() {\n        const meta = this._cachedMeta;\n        const dataset = meta.dataset;\n        const border = dataset.options && dataset.options.borderWidth || 0;\n        const data = meta.data || [];\n        if (!data.length) {\n            return border;\n        }\n        const firstPoint = data[0].size(this.resolveDataElementOptions(0));\n        const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));\n        return Math.max(border, firstPoint, lastPoint) / 2;\n    }\n    draw() {\n        const meta = this._cachedMeta;\n        meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis);\n        super.draw();\n    }\n}\n\nclass PolarAreaController extends DatasetController {\n    static id = 'polarArea';\n static defaults = {\n        dataElementType: 'arc',\n        animation: {\n            animateRotate: true,\n            animateScale: true\n        },\n        animations: {\n            numbers: {\n                type: 'number',\n                properties: [\n                    'x',\n                    'y',\n                    'startAngle',\n                    'endAngle',\n                    'innerRadius',\n                    'outerRadius'\n                ]\n            }\n        },\n        indexAxis: 'r',\n        startAngle: 0\n    };\n static overrides = {\n        aspectRatio: 1,\n        plugins: {\n            legend: {\n                labels: {\n                    generateLabels (chart) {\n                        const data = chart.data;\n                        if (data.labels.length && data.datasets.length) {\n                            const { labels: { pointStyle , color  }  } = chart.legend.options;\n                            return data.labels.map((label, i)=>{\n                                const meta = chart.getDatasetMeta(0);\n                                const style = meta.controller.getStyle(i);\n                                return {\n                                    text: label,\n                                    fillStyle: style.backgroundColor,\n                                    strokeStyle: style.borderColor,\n                                    fontColor: color,\n                                    lineWidth: style.borderWidth,\n                                    pointStyle: pointStyle,\n                                    hidden: !chart.getDataVisibility(i),\n                                    index: i\n                                };\n                            });\n                        }\n                        return [];\n                    }\n                },\n                onClick (e, legendItem, legend) {\n                    legend.chart.toggleDataVisibility(legendItem.index);\n                    legend.chart.update();\n                }\n            }\n        },\n        scales: {\n            r: {\n                type: 'radialLinear',\n                angleLines: {\n                    display: false\n                },\n                beginAtZero: true,\n                grid: {\n                    circular: true\n                },\n                pointLabels: {\n                    display: false\n                },\n                startAngle: 0\n            }\n        }\n    };\n    constructor(chart, datasetIndex){\n        super(chart, datasetIndex);\n        this.innerRadius = undefined;\n        this.outerRadius = undefined;\n    }\n    getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const chart = this.chart;\n        const labels = chart.data.labels || [];\n        const value = formatNumber(meta._parsed[index].r, chart.options.locale);\n        return {\n            label: labels[index] || '',\n            value\n        };\n    }\n    parseObjectData(meta, data, start, count) {\n        return _parseObjectDataRadialScale.bind(this)(meta, data, start, count);\n    }\n    update(mode) {\n        const arcs = this._cachedMeta.data;\n        this._updateRadius();\n        this.updateElements(arcs, 0, arcs.length, mode);\n    }\n getMinMax() {\n        const meta = this._cachedMeta;\n        const range = {\n            min: Number.POSITIVE_INFINITY,\n            max: Number.NEGATIVE_INFINITY\n        };\n        meta.data.forEach((element, index)=>{\n            const parsed = this.getParsed(index).r;\n            if (!isNaN(parsed) && this.chart.getDataVisibility(index)) {\n                if (parsed < range.min) {\n                    range.min = parsed;\n                }\n                if (parsed > range.max) {\n                    range.max = parsed;\n                }\n            }\n        });\n        return range;\n    }\n _updateRadius() {\n        const chart = this.chart;\n        const chartArea = chart.chartArea;\n        const opts = chart.options;\n        const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\n        const outerRadius = Math.max(minSize / 2, 0);\n        const innerRadius = Math.max(opts.cutoutPercentage ? outerRadius / 100 * opts.cutoutPercentage : 1, 0);\n        const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();\n        this.outerRadius = outerRadius - radiusLength * this.index;\n        this.innerRadius = this.outerRadius - radiusLength;\n    }\n    updateElements(arcs, start, count, mode) {\n        const reset = mode === 'reset';\n        const chart = this.chart;\n        const opts = chart.options;\n        const animationOpts = opts.animation;\n        const scale = this._cachedMeta.rScale;\n        const centerX = scale.xCenter;\n        const centerY = scale.yCenter;\n        const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * PI;\n        let angle = datasetStartAngle;\n        let i;\n        const defaultAngle = 360 / this.countVisibleElements();\n        for(i = 0; i < start; ++i){\n            angle += this._computeAngle(i, mode, defaultAngle);\n        }\n        for(i = start; i < start + count; i++){\n            const arc = arcs[i];\n            let startAngle = angle;\n            let endAngle = angle + this._computeAngle(i, mode, defaultAngle);\n            let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(this.getParsed(i).r) : 0;\n            angle = endAngle;\n            if (reset) {\n                if (animationOpts.animateScale) {\n                    outerRadius = 0;\n                }\n                if (animationOpts.animateRotate) {\n                    startAngle = endAngle = datasetStartAngle;\n                }\n            }\n            const properties = {\n                x: centerX,\n                y: centerY,\n                innerRadius: 0,\n                outerRadius,\n                startAngle,\n                endAngle,\n                options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)\n            };\n            this.updateElement(arc, i, properties, mode);\n        }\n    }\n    countVisibleElements() {\n        const meta = this._cachedMeta;\n        let count = 0;\n        meta.data.forEach((element, index)=>{\n            if (!isNaN(this.getParsed(index).r) && this.chart.getDataVisibility(index)) {\n                count++;\n            }\n        });\n        return count;\n    }\n _computeAngle(index, mode, defaultAngle) {\n        return this.chart.getDataVisibility(index) ? toRadians(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0;\n    }\n}\n\nclass PieController extends DoughnutController {\n    static id = 'pie';\n static defaults = {\n        cutout: 0,\n        rotation: 0,\n        circumference: 360,\n        radius: '100%'\n    };\n}\n\nclass RadarController extends DatasetController {\n    static id = 'radar';\n static defaults = {\n        datasetElementType: 'line',\n        dataElementType: 'point',\n        indexAxis: 'r',\n        showLine: true,\n        elements: {\n            line: {\n                fill: 'start'\n            }\n        }\n    };\n static overrides = {\n        aspectRatio: 1,\n        scales: {\n            r: {\n                type: 'radialLinear'\n            }\n        }\n    };\n getLabelAndValue(index) {\n        const vScale = this._cachedMeta.vScale;\n        const parsed = this.getParsed(index);\n        return {\n            label: vScale.getLabels()[index],\n            value: '' + vScale.getLabelForValue(parsed[vScale.axis])\n        };\n    }\n    parseObjectData(meta, data, start, count) {\n        return _parseObjectDataRadialScale.bind(this)(meta, data, start, count);\n    }\n    update(mode) {\n        const meta = this._cachedMeta;\n        const line = meta.dataset;\n        const points = meta.data || [];\n        const labels = meta.iScale.getLabels();\n        line.points = points;\n        if (mode !== 'resize') {\n            const options = this.resolveDatasetElementOptions(mode);\n            if (!this.options.showLine) {\n                options.borderWidth = 0;\n            }\n            const properties = {\n                _loop: true,\n                _fullLoop: labels.length === points.length,\n                options\n            };\n            this.updateElement(line, undefined, properties, mode);\n        }\n        this.updateElements(points, 0, points.length, mode);\n    }\n    updateElements(points, start, count, mode) {\n        const scale = this._cachedMeta.rScale;\n        const reset = mode === 'reset';\n        for(let i = start; i < start + count; i++){\n            const point = points[i];\n            const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n            const pointPosition = scale.getPointPositionForValue(i, this.getParsed(i).r);\n            const x = reset ? scale.xCenter : pointPosition.x;\n            const y = reset ? scale.yCenter : pointPosition.y;\n            const properties = {\n                x,\n                y,\n                angle: pointPosition.angle,\n                skip: isNaN(x) || isNaN(y),\n                options\n            };\n            this.updateElement(point, i, properties, mode);\n        }\n    }\n}\n\nclass ScatterController extends DatasetController {\n    static id = 'scatter';\n static defaults = {\n        datasetElementType: false,\n        dataElementType: 'point',\n        showLine: false,\n        fill: false\n    };\n static overrides = {\n        interaction: {\n            mode: 'point'\n        },\n        scales: {\n            x: {\n                type: 'linear'\n            },\n            y: {\n                type: 'linear'\n            }\n        }\n    };\n getLabelAndValue(index) {\n        const meta = this._cachedMeta;\n        const labels = this.chart.data.labels || [];\n        const { xScale , yScale  } = meta;\n        const parsed = this.getParsed(index);\n        const x = xScale.getLabelForValue(parsed.x);\n        const y = yScale.getLabelForValue(parsed.y);\n        return {\n            label: labels[index] || '',\n            value: '(' + x + ', ' + y + ')'\n        };\n    }\n    update(mode) {\n        const meta = this._cachedMeta;\n        const { data: points = []  } = meta;\n        const animationsDisabled = this.chart._animationsDisabled;\n        let { start , count  } = _getStartAndCountOfVisiblePoints(meta, points, animationsDisabled);\n        this._drawStart = start;\n        this._drawCount = count;\n        if (_scaleRangesChanged(meta)) {\n            start = 0;\n            count = points.length;\n        }\n        if (this.options.showLine) {\n            if (!this.datasetElementType) {\n                this.addElements();\n            }\n            const { dataset: line , _dataset  } = meta;\n            line._chart = this.chart;\n            line._datasetIndex = this.index;\n            line._decimated = !!_dataset._decimated;\n            line.points = points;\n            const options = this.resolveDatasetElementOptions(mode);\n            options.segment = this.options.segment;\n            this.updateElement(line, undefined, {\n                animated: !animationsDisabled,\n                options\n            }, mode);\n        } else if (this.datasetElementType) {\n            delete meta.dataset;\n            this.datasetElementType = false;\n        }\n        this.updateElements(points, start, count, mode);\n    }\n    addElements() {\n        const { showLine  } = this.options;\n        if (!this.datasetElementType && showLine) {\n            this.datasetElementType = this.chart.registry.getElement('line');\n        }\n        super.addElements();\n    }\n    updateElements(points, start, count, mode) {\n        const reset = mode === 'reset';\n        const { iScale , vScale , _stacked , _dataset  } = this._cachedMeta;\n        const firstOpts = this.resolveDataElementOptions(start, mode);\n        const sharedOptions = this.getSharedOptions(firstOpts);\n        const includeOptions = this.includeOptions(mode, sharedOptions);\n        const iAxis = iScale.axis;\n        const vAxis = vScale.axis;\n        const { spanGaps , segment  } = this.options;\n        const maxGapLength = isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;\n        const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';\n        let prevParsed = start > 0 && this.getParsed(start - 1);\n        for(let i = start; i < start + count; ++i){\n            const point = points[i];\n            const parsed = this.getParsed(i);\n            const properties = directUpdate ? point : {};\n            const nullData = isNullOrUndef(parsed[vAxis]);\n            const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);\n            const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);\n            properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;\n            properties.stop = i > 0 && Math.abs(parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;\n            if (segment) {\n                properties.parsed = parsed;\n                properties.raw = _dataset.data[i];\n            }\n            if (includeOptions) {\n                properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);\n            }\n            if (!directUpdate) {\n                this.updateElement(point, i, properties, mode);\n            }\n            prevParsed = parsed;\n        }\n        this.updateSharedOptions(sharedOptions, mode, firstOpts);\n    }\n getMaxOverflow() {\n        const meta = this._cachedMeta;\n        const data = meta.data || [];\n        if (!this.options.showLine) {\n            let max = 0;\n            for(let i = data.length - 1; i >= 0; --i){\n                max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);\n            }\n            return max > 0 && max;\n        }\n        const dataset = meta.dataset;\n        const border = dataset.options && dataset.options.borderWidth || 0;\n        if (!data.length) {\n            return border;\n        }\n        const firstPoint = data[0].size(this.resolveDataElementOptions(0));\n        const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));\n        return Math.max(border, firstPoint, lastPoint) / 2;\n    }\n}\n\nvar controllers = /*#__PURE__*/Object.freeze({\n__proto__: null,\nBarController: BarController,\nBubbleController: BubbleController,\nDoughnutController: DoughnutController,\nLineController: LineController,\nPieController: PieController,\nPolarAreaController: PolarAreaController,\nRadarController: RadarController,\nScatterController: ScatterController\n});\n\n/**\n * @namespace Chart._adapters\n * @since 2.8.0\n * @private\n */ function abstract() {\n    throw new Error('This method is not implemented: Check that a complete date adapter is provided.');\n}\n/**\n * Date adapter (current used by the time scale)\n * @namespace Chart._adapters._date\n * @memberof Chart._adapters\n * @private\n */ class DateAdapterBase {\n    /**\n   * Override default date adapter methods.\n   * Accepts type parameter to define options type.\n   * @example\n   * Chart._adapters._date.override<{myAdapterOption: string}>({\n   *   init() {\n   *     console.log(this.options.myAdapterOption);\n   *   }\n   * })\n   */ static override(members) {\n        Object.assign(DateAdapterBase.prototype, members);\n    }\n    options;\n    constructor(options){\n        this.options = options || {};\n    }\n    // eslint-disable-next-line @typescript-eslint/no-empty-function\n    init() {}\n    formats() {\n        return abstract();\n    }\n    parse() {\n        return abstract();\n    }\n    format() {\n        return abstract();\n    }\n    add() {\n        return abstract();\n    }\n    diff() {\n        return abstract();\n    }\n    startOf() {\n        return abstract();\n    }\n    endOf() {\n        return abstract();\n    }\n}\nvar adapters = {\n    _date: DateAdapterBase\n};\n\nfunction binarySearch(metaset, axis, value, intersect) {\n    const { controller , data , _sorted  } = metaset;\n    const iScale = controller._cachedMeta.iScale;\n    if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) {\n        const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;\n        if (!intersect) {\n            return lookupMethod(data, axis, value);\n        } else if (controller._sharedOptions) {\n            const el = data[0];\n            const range = typeof el.getRange === 'function' && el.getRange(axis);\n            if (range) {\n                const start = lookupMethod(data, axis, value - range);\n                const end = lookupMethod(data, axis, value + range);\n                return {\n                    lo: start.lo,\n                    hi: end.hi\n                };\n            }\n        }\n    }\n    return {\n        lo: 0,\n        hi: data.length - 1\n    };\n}\n function evaluateInteractionItems(chart, axis, position, handler, intersect) {\n    const metasets = chart.getSortedVisibleDatasetMetas();\n    const value = position[axis];\n    for(let i = 0, ilen = metasets.length; i < ilen; ++i){\n        const { index , data  } = metasets[i];\n        const { lo , hi  } = binarySearch(metasets[i], axis, value, intersect);\n        for(let j = lo; j <= hi; ++j){\n            const element = data[j];\n            if (!element.skip) {\n                handler(element, index, j);\n            }\n        }\n    }\n}\n function getDistanceMetricForAxis(axis) {\n    const useX = axis.indexOf('x') !== -1;\n    const useY = axis.indexOf('y') !== -1;\n    return function(pt1, pt2) {\n        const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;\n        const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;\n        return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n    };\n}\n function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {\n    const items = [];\n    if (!includeInvisible && !chart.isPointInArea(position)) {\n        return items;\n    }\n    const evaluationFunc = function(element, datasetIndex, index) {\n        if (!includeInvisible && !_isPointInArea(element, chart.chartArea, 0)) {\n            return;\n        }\n        if (element.inRange(position.x, position.y, useFinalPosition)) {\n            items.push({\n                element,\n                datasetIndex,\n                index\n            });\n        }\n    };\n    evaluateInteractionItems(chart, axis, position, evaluationFunc, true);\n    return items;\n}\n function getNearestRadialItems(chart, position, axis, useFinalPosition) {\n    let items = [];\n    function evaluationFunc(element, datasetIndex, index) {\n        const { startAngle , endAngle  } = element.getProps([\n            'startAngle',\n            'endAngle'\n        ], useFinalPosition);\n        const { angle  } = getAngleFromPoint(element, {\n            x: position.x,\n            y: position.y\n        });\n        if (_angleBetween(angle, startAngle, endAngle)) {\n            items.push({\n                element,\n                datasetIndex,\n                index\n            });\n        }\n    }\n    evaluateInteractionItems(chart, axis, position, evaluationFunc);\n    return items;\n}\n function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {\n    let items = [];\n    const distanceMetric = getDistanceMetricForAxis(axis);\n    let minDistance = Number.POSITIVE_INFINITY;\n    function evaluationFunc(element, datasetIndex, index) {\n        const inRange = element.inRange(position.x, position.y, useFinalPosition);\n        if (intersect && !inRange) {\n            return;\n        }\n        const center = element.getCenterPoint(useFinalPosition);\n        const pointInArea = !!includeInvisible || chart.isPointInArea(center);\n        if (!pointInArea && !inRange) {\n            return;\n        }\n        const distance = distanceMetric(position, center);\n        if (distance < minDistance) {\n            items = [\n                {\n                    element,\n                    datasetIndex,\n                    index\n                }\n            ];\n            minDistance = distance;\n        } else if (distance === minDistance) {\n            items.push({\n                element,\n                datasetIndex,\n                index\n            });\n        }\n    }\n    evaluateInteractionItems(chart, axis, position, evaluationFunc);\n    return items;\n}\n function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {\n    if (!includeInvisible && !chart.isPointInArea(position)) {\n        return [];\n    }\n    return axis === 'r' && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);\n}\n function getAxisItems(chart, position, axis, intersect, useFinalPosition) {\n    const items = [];\n    const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange';\n    let intersectsItem = false;\n    evaluateInteractionItems(chart, axis, position, (element, datasetIndex, index)=>{\n        if (element[rangeMethod](position[axis], useFinalPosition)) {\n            items.push({\n                element,\n                datasetIndex,\n                index\n            });\n            intersectsItem = intersectsItem || element.inRange(position.x, position.y, useFinalPosition);\n        }\n    });\n    if (intersect && !intersectsItem) {\n        return [];\n    }\n    return items;\n}\n var Interaction = {\n    evaluateInteractionItems,\n    modes: {\n index (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            const axis = options.axis || 'x';\n            const includeInvisible = options.includeInvisible || false;\n            const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);\n            const elements = [];\n            if (!items.length) {\n                return [];\n            }\n            chart.getSortedVisibleDatasetMetas().forEach((meta)=>{\n                const index = items[0].index;\n                const element = meta.data[index];\n                if (element && !element.skip) {\n                    elements.push({\n                        element,\n                        datasetIndex: meta.index,\n                        index\n                    });\n                }\n            });\n            return elements;\n        },\n dataset (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            const axis = options.axis || 'xy';\n            const includeInvisible = options.includeInvisible || false;\n            let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);\n            if (items.length > 0) {\n                const datasetIndex = items[0].datasetIndex;\n                const data = chart.getDatasetMeta(datasetIndex).data;\n                items = [];\n                for(let i = 0; i < data.length; ++i){\n                    items.push({\n                        element: data[i],\n                        datasetIndex,\n                        index: i\n                    });\n                }\n            }\n            return items;\n        },\n point (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            const axis = options.axis || 'xy';\n            const includeInvisible = options.includeInvisible || false;\n            return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);\n        },\n nearest (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            const axis = options.axis || 'xy';\n            const includeInvisible = options.includeInvisible || false;\n            return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);\n        },\n x (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            return getAxisItems(chart, position, 'x', options.intersect, useFinalPosition);\n        },\n y (chart, e, options, useFinalPosition) {\n            const position = getRelativePosition(e, chart);\n            return getAxisItems(chart, position, 'y', options.intersect, useFinalPosition);\n        }\n    }\n};\n\nconst STATIC_POSITIONS = [\n    'left',\n    'top',\n    'right',\n    'bottom'\n];\nfunction filterByPosition(array, position) {\n    return array.filter((v)=>v.pos === position);\n}\nfunction filterDynamicPositionByAxis(array, axis) {\n    return array.filter((v)=>STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis);\n}\nfunction sortByWeight(array, reverse) {\n    return array.sort((a, b)=>{\n        const v0 = reverse ? b : a;\n        const v1 = reverse ? a : b;\n        return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;\n    });\n}\nfunction wrapBoxes(boxes) {\n    const layoutBoxes = [];\n    let i, ilen, box, pos, stack, stackWeight;\n    for(i = 0, ilen = (boxes || []).length; i < ilen; ++i){\n        box = boxes[i];\n        ({ position: pos , options: { stack , stackWeight =1  }  } = box);\n        layoutBoxes.push({\n            index: i,\n            box,\n            pos,\n            horizontal: box.isHorizontal(),\n            weight: box.weight,\n            stack: stack && pos + stack,\n            stackWeight\n        });\n    }\n    return layoutBoxes;\n}\nfunction buildStacks(layouts) {\n    const stacks = {};\n    for (const wrap of layouts){\n        const { stack , pos , stackWeight  } = wrap;\n        if (!stack || !STATIC_POSITIONS.includes(pos)) {\n            continue;\n        }\n        const _stack = stacks[stack] || (stacks[stack] = {\n            count: 0,\n            placed: 0,\n            weight: 0,\n            size: 0\n        });\n        _stack.count++;\n        _stack.weight += stackWeight;\n    }\n    return stacks;\n}\n function setLayoutDims(layouts, params) {\n    const stacks = buildStacks(layouts);\n    const { vBoxMaxWidth , hBoxMaxHeight  } = params;\n    let i, ilen, layout;\n    for(i = 0, ilen = layouts.length; i < ilen; ++i){\n        layout = layouts[i];\n        const { fullSize  } = layout.box;\n        const stack = stacks[layout.stack];\n        const factor = stack && layout.stackWeight / stack.weight;\n        if (layout.horizontal) {\n            layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;\n            layout.height = hBoxMaxHeight;\n        } else {\n            layout.width = vBoxMaxWidth;\n            layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;\n        }\n    }\n    return stacks;\n}\nfunction buildLayoutBoxes(boxes) {\n    const layoutBoxes = wrapBoxes(boxes);\n    const fullSize = sortByWeight(layoutBoxes.filter((wrap)=>wrap.box.fullSize), true);\n    const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true);\n    const right = sortByWeight(filterByPosition(layoutBoxes, 'right'));\n    const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true);\n    const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom'));\n    const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x');\n    const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y');\n    return {\n        fullSize,\n        leftAndTop: left.concat(top),\n        rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal),\n        chartArea: filterByPosition(layoutBoxes, 'chartArea'),\n        vertical: left.concat(right).concat(centerVertical),\n        horizontal: top.concat(bottom).concat(centerHorizontal)\n    };\n}\nfunction getCombinedMax(maxPadding, chartArea, a, b) {\n    return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);\n}\nfunction updateMaxPadding(maxPadding, boxPadding) {\n    maxPadding.top = Math.max(maxPadding.top, boxPadding.top);\n    maxPadding.left = Math.max(maxPadding.left, boxPadding.left);\n    maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);\n    maxPadding.right = Math.max(maxPadding.right, boxPadding.right);\n}\nfunction updateDims(chartArea, params, layout, stacks) {\n    const { pos , box  } = layout;\n    const maxPadding = chartArea.maxPadding;\n    if (!isObject(pos)) {\n        if (layout.size) {\n            chartArea[pos] -= layout.size;\n        }\n        const stack = stacks[layout.stack] || {\n            size: 0,\n            count: 1\n        };\n        stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);\n        layout.size = stack.size / stack.count;\n        chartArea[pos] += layout.size;\n    }\n    if (box.getPadding) {\n        updateMaxPadding(maxPadding, box.getPadding());\n    }\n    const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right'));\n    const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom'));\n    const widthChanged = newWidth !== chartArea.w;\n    const heightChanged = newHeight !== chartArea.h;\n    chartArea.w = newWidth;\n    chartArea.h = newHeight;\n    return layout.horizontal ? {\n        same: widthChanged,\n        other: heightChanged\n    } : {\n        same: heightChanged,\n        other: widthChanged\n    };\n}\nfunction handleMaxPadding(chartArea) {\n    const maxPadding = chartArea.maxPadding;\n    function updatePos(pos) {\n        const change = Math.max(maxPadding[pos] - chartArea[pos], 0);\n        chartArea[pos] += change;\n        return change;\n    }\n    chartArea.y += updatePos('top');\n    chartArea.x += updatePos('left');\n    updatePos('right');\n    updatePos('bottom');\n}\nfunction getMargins(horizontal, chartArea) {\n    const maxPadding = chartArea.maxPadding;\n    function marginForPositions(positions) {\n        const margin = {\n            left: 0,\n            top: 0,\n            right: 0,\n            bottom: 0\n        };\n        positions.forEach((pos)=>{\n            margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);\n        });\n        return margin;\n    }\n    return horizontal ? marginForPositions([\n        'left',\n        'right'\n    ]) : marginForPositions([\n        'top',\n        'bottom'\n    ]);\n}\nfunction fitBoxes(boxes, chartArea, params, stacks) {\n    const refitBoxes = [];\n    let i, ilen, layout, box, refit, changed;\n    for(i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i){\n        layout = boxes[i];\n        box = layout.box;\n        box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));\n        const { same , other  } = updateDims(chartArea, params, layout, stacks);\n        refit |= same && refitBoxes.length;\n        changed = changed || other;\n        if (!box.fullSize) {\n            refitBoxes.push(layout);\n        }\n    }\n    return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;\n}\nfunction setBoxDims(box, left, top, width, height) {\n    box.top = top;\n    box.left = left;\n    box.right = left + width;\n    box.bottom = top + height;\n    box.width = width;\n    box.height = height;\n}\nfunction placeBoxes(boxes, chartArea, params, stacks) {\n    const userPadding = params.padding;\n    let { x , y  } = chartArea;\n    for (const layout of boxes){\n        const box = layout.box;\n        const stack = stacks[layout.stack] || {\n            count: 1,\n            placed: 0,\n            weight: 1\n        };\n        const weight = layout.stackWeight / stack.weight || 1;\n        if (layout.horizontal) {\n            const width = chartArea.w * weight;\n            const height = stack.size || box.height;\n            if (defined(stack.start)) {\n                y = stack.start;\n            }\n            if (box.fullSize) {\n                setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height);\n            } else {\n                setBoxDims(box, chartArea.left + stack.placed, y, width, height);\n            }\n            stack.start = y;\n            stack.placed += width;\n            y = box.bottom;\n        } else {\n            const height = chartArea.h * weight;\n            const width = stack.size || box.width;\n            if (defined(stack.start)) {\n                x = stack.start;\n            }\n            if (box.fullSize) {\n                setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top);\n            } else {\n                setBoxDims(box, x, chartArea.top + stack.placed, width, height);\n            }\n            stack.start = x;\n            stack.placed += height;\n            x = box.right;\n        }\n    }\n    chartArea.x = x;\n    chartArea.y = y;\n}\nvar layouts = {\n addBox (chart, item) {\n        if (!chart.boxes) {\n            chart.boxes = [];\n        }\n        item.fullSize = item.fullSize || false;\n        item.position = item.position || 'top';\n        item.weight = item.weight || 0;\n        item._layers = item._layers || function() {\n            return [\n                {\n                    z: 0,\n                    draw (chartArea) {\n                        item.draw(chartArea);\n                    }\n                }\n            ];\n        };\n        chart.boxes.push(item);\n    },\n removeBox (chart, layoutItem) {\n        const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;\n        if (index !== -1) {\n            chart.boxes.splice(index, 1);\n        }\n    },\n configure (chart, item, options) {\n        item.fullSize = options.fullSize;\n        item.position = options.position;\n        item.weight = options.weight;\n    },\n update (chart, width, height, minPadding) {\n        if (!chart) {\n            return;\n        }\n        const padding = toPadding(chart.options.layout.padding);\n        const availableWidth = Math.max(width - padding.width, 0);\n        const availableHeight = Math.max(height - padding.height, 0);\n        const boxes = buildLayoutBoxes(chart.boxes);\n        const verticalBoxes = boxes.vertical;\n        const horizontalBoxes = boxes.horizontal;\n        each(chart.boxes, (box)=>{\n            if (typeof box.beforeLayout === 'function') {\n                box.beforeLayout();\n            }\n        });\n        const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap)=>wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;\n        const params = Object.freeze({\n            outerWidth: width,\n            outerHeight: height,\n            padding,\n            availableWidth,\n            availableHeight,\n            vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,\n            hBoxMaxHeight: availableHeight / 2\n        });\n        const maxPadding = Object.assign({}, padding);\n        updateMaxPadding(maxPadding, toPadding(minPadding));\n        const chartArea = Object.assign({\n            maxPadding,\n            w: availableWidth,\n            h: availableHeight,\n            x: padding.left,\n            y: padding.top\n        }, padding);\n        const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);\n        fitBoxes(boxes.fullSize, chartArea, params, stacks);\n        fitBoxes(verticalBoxes, chartArea, params, stacks);\n        if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {\n            fitBoxes(verticalBoxes, chartArea, params, stacks);\n        }\n        handleMaxPadding(chartArea);\n        placeBoxes(boxes.leftAndTop, chartArea, params, stacks);\n        chartArea.x += chartArea.w;\n        chartArea.y += chartArea.h;\n        placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);\n        chart.chartArea = {\n            left: chartArea.left,\n            top: chartArea.top,\n            right: chartArea.left + chartArea.w,\n            bottom: chartArea.top + chartArea.h,\n            height: chartArea.h,\n            width: chartArea.w\n        };\n        each(boxes.chartArea, (layout)=>{\n            const box = layout.box;\n            Object.assign(box, chart.chartArea);\n            box.update(chartArea.w, chartArea.h, {\n                left: 0,\n                top: 0,\n                right: 0,\n                bottom: 0\n            });\n        });\n    }\n};\n\nclass BasePlatform {\n acquireContext(canvas, aspectRatio) {}\n releaseContext(context) {\n        return false;\n    }\n addEventListener(chart, type, listener) {}\n removeEventListener(chart, type, listener) {}\n getDevicePixelRatio() {\n        return 1;\n    }\n getMaximumSize(element, width, height, aspectRatio) {\n        width = Math.max(0, width || element.width);\n        height = height || element.height;\n        return {\n            width,\n            height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)\n        };\n    }\n isAttached(canvas) {\n        return true;\n    }\n updateConfig(config) {\n    }\n}\n\nclass BasicPlatform extends BasePlatform {\n    acquireContext(item) {\n        return item && item.getContext && item.getContext('2d') || null;\n    }\n    updateConfig(config) {\n        config.options.animation = false;\n    }\n}\n\nconst EXPANDO_KEY = '$chartjs';\n const EVENT_TYPES = {\n    touchstart: 'mousedown',\n    touchmove: 'mousemove',\n    touchend: 'mouseup',\n    pointerenter: 'mouseenter',\n    pointerdown: 'mousedown',\n    pointermove: 'mousemove',\n    pointerup: 'mouseup',\n    pointerleave: 'mouseout',\n    pointerout: 'mouseout'\n};\nconst isNullOrEmpty = (value)=>value === null || value === '';\n function initCanvas(canvas, aspectRatio) {\n    const style = canvas.style;\n    const renderHeight = canvas.getAttribute('height');\n    const renderWidth = canvas.getAttribute('width');\n    canvas[EXPANDO_KEY] = {\n        initial: {\n            height: renderHeight,\n            width: renderWidth,\n            style: {\n                display: style.display,\n                height: style.height,\n                width: style.width\n            }\n        }\n    };\n    style.display = style.display || 'block';\n    style.boxSizing = style.boxSizing || 'border-box';\n    if (isNullOrEmpty(renderWidth)) {\n        const displayWidth = readUsedSize(canvas, 'width');\n        if (displayWidth !== undefined) {\n            canvas.width = displayWidth;\n        }\n    }\n    if (isNullOrEmpty(renderHeight)) {\n        if (canvas.style.height === '') {\n            canvas.height = canvas.width / (aspectRatio || 2);\n        } else {\n            const displayHeight = readUsedSize(canvas, 'height');\n            if (displayHeight !== undefined) {\n                canvas.height = displayHeight;\n            }\n        }\n    }\n    return canvas;\n}\nconst eventListenerOptions = supportsEventListenerOptions ? {\n    passive: true\n} : false;\nfunction addListener(node, type, listener) {\n    if (node) {\n        node.addEventListener(type, listener, eventListenerOptions);\n    }\n}\nfunction removeListener(chart, type, listener) {\n    if (chart && chart.canvas) {\n        chart.canvas.removeEventListener(type, listener, eventListenerOptions);\n    }\n}\nfunction fromNativeEvent(event, chart) {\n    const type = EVENT_TYPES[event.type] || event.type;\n    const { x , y  } = getRelativePosition(event, chart);\n    return {\n        type,\n        chart,\n        native: event,\n        x: x !== undefined ? x : null,\n        y: y !== undefined ? y : null\n    };\n}\nfunction nodeListContains(nodeList, canvas) {\n    for (const node of nodeList){\n        if (node === canvas || node.contains(canvas)) {\n            return true;\n        }\n    }\n}\nfunction createAttachObserver(chart, type, listener) {\n    const canvas = chart.canvas;\n    const observer = new MutationObserver((entries)=>{\n        let trigger = false;\n        for (const entry of entries){\n            trigger = trigger || nodeListContains(entry.addedNodes, canvas);\n            trigger = trigger && !nodeListContains(entry.removedNodes, canvas);\n        }\n        if (trigger) {\n            listener();\n        }\n    });\n    observer.observe(document, {\n        childList: true,\n        subtree: true\n    });\n    return observer;\n}\nfunction createDetachObserver(chart, type, listener) {\n    const canvas = chart.canvas;\n    const observer = new MutationObserver((entries)=>{\n        let trigger = false;\n        for (const entry of entries){\n            trigger = trigger || nodeListContains(entry.removedNodes, canvas);\n            trigger = trigger && !nodeListContains(entry.addedNodes, canvas);\n        }\n        if (trigger) {\n            listener();\n        }\n    });\n    observer.observe(document, {\n        childList: true,\n        subtree: true\n    });\n    return observer;\n}\nconst drpListeningCharts = new Map();\nlet oldDevicePixelRatio = 0;\nfunction onWindowResize() {\n    const dpr = window.devicePixelRatio;\n    if (dpr === oldDevicePixelRatio) {\n        return;\n    }\n    oldDevicePixelRatio = dpr;\n    drpListeningCharts.forEach((resize, chart)=>{\n        if (chart.currentDevicePixelRatio !== dpr) {\n            resize();\n        }\n    });\n}\nfunction listenDevicePixelRatioChanges(chart, resize) {\n    if (!drpListeningCharts.size) {\n        window.addEventListener('resize', onWindowResize);\n    }\n    drpListeningCharts.set(chart, resize);\n}\nfunction unlistenDevicePixelRatioChanges(chart) {\n    drpListeningCharts.delete(chart);\n    if (!drpListeningCharts.size) {\n        window.removeEventListener('resize', onWindowResize);\n    }\n}\nfunction createResizeObserver(chart, type, listener) {\n    const canvas = chart.canvas;\n    const container = canvas && _getParentNode(canvas);\n    if (!container) {\n        return;\n    }\n    const resize = throttled((width, height)=>{\n        const w = container.clientWidth;\n        listener(width, height);\n        if (w < container.clientWidth) {\n            listener();\n        }\n    }, window);\n    const observer = new ResizeObserver((entries)=>{\n        const entry = entries[0];\n        const width = entry.contentRect.width;\n        const height = entry.contentRect.height;\n        if (width === 0 && height === 0) {\n            return;\n        }\n        resize(width, height);\n    });\n    observer.observe(container);\n    listenDevicePixelRatioChanges(chart, resize);\n    return observer;\n}\nfunction releaseObserver(chart, type, observer) {\n    if (observer) {\n        observer.disconnect();\n    }\n    if (type === 'resize') {\n        unlistenDevicePixelRatioChanges(chart);\n    }\n}\nfunction createProxyAndListen(chart, type, listener) {\n    const canvas = chart.canvas;\n    const proxy = throttled((event)=>{\n        if (chart.ctx !== null) {\n            listener(fromNativeEvent(event, chart));\n        }\n    }, chart);\n    addListener(canvas, type, proxy);\n    return proxy;\n}\n class DomPlatform extends BasePlatform {\n acquireContext(canvas, aspectRatio) {\n        const context = canvas && canvas.getContext && canvas.getContext('2d');\n        if (context && context.canvas === canvas) {\n            initCanvas(canvas, aspectRatio);\n            return context;\n        }\n        return null;\n    }\n releaseContext(context) {\n        const canvas = context.canvas;\n        if (!canvas[EXPANDO_KEY]) {\n            return false;\n        }\n        const initial = canvas[EXPANDO_KEY].initial;\n        [\n            'height',\n            'width'\n        ].forEach((prop)=>{\n            const value = initial[prop];\n            if (isNullOrUndef(value)) {\n                canvas.removeAttribute(prop);\n            } else {\n                canvas.setAttribute(prop, value);\n            }\n        });\n        const style = initial.style || {};\n        Object.keys(style).forEach((key)=>{\n            canvas.style[key] = style[key];\n        });\n        canvas.width = canvas.width;\n        delete canvas[EXPANDO_KEY];\n        return true;\n    }\n addEventListener(chart, type, listener) {\n        this.removeEventListener(chart, type);\n        const proxies = chart.$proxies || (chart.$proxies = {});\n        const handlers = {\n            attach: createAttachObserver,\n            detach: createDetachObserver,\n            resize: createResizeObserver\n        };\n        const handler = handlers[type] || createProxyAndListen;\n        proxies[type] = handler(chart, type, listener);\n    }\n removeEventListener(chart, type) {\n        const proxies = chart.$proxies || (chart.$proxies = {});\n        const proxy = proxies[type];\n        if (!proxy) {\n            return;\n        }\n        const handlers = {\n            attach: releaseObserver,\n            detach: releaseObserver,\n            resize: releaseObserver\n        };\n        const handler = handlers[type] || removeListener;\n        handler(chart, type, proxy);\n        proxies[type] = undefined;\n    }\n    getDevicePixelRatio() {\n        return window.devicePixelRatio;\n    }\n getMaximumSize(canvas, width, height, aspectRatio) {\n        return getMaximumSize(canvas, width, height, aspectRatio);\n    }\n isAttached(canvas) {\n        const container = _getParentNode(canvas);\n        return !!(container && container.isConnected);\n    }\n}\n\nfunction _detectPlatform(canvas) {\n    if (!_isDomSupported() || typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) {\n        return BasicPlatform;\n    }\n    return DomPlatform;\n}\n\nclass Element {\n    static defaults = {};\n    static defaultRoutes = undefined;\n    x;\n    y;\n    active = false;\n    options;\n    $animations;\n    tooltipPosition(useFinalPosition) {\n        const { x , y  } = this.getProps([\n            'x',\n            'y'\n        ], useFinalPosition);\n        return {\n            x,\n            y\n        };\n    }\n    hasValue() {\n        return isNumber(this.x) && isNumber(this.y);\n    }\n    getProps(props, final) {\n        const anims = this.$animations;\n        if (!final || !anims) {\n            // let's not create an object, if not needed\n            return this;\n        }\n        const ret = {};\n        props.forEach((prop)=>{\n            ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];\n        });\n        return ret;\n    }\n}\n\nfunction autoSkip(scale, ticks) {\n    const tickOpts = scale.options.ticks;\n    const determinedMaxTicks = determineMaxTicks(scale);\n    const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks);\n    const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];\n    const numMajorIndices = majorIndices.length;\n    const first = majorIndices[0];\n    const last = majorIndices[numMajorIndices - 1];\n    const newTicks = [];\n    if (numMajorIndices > ticksLimit) {\n        skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);\n        return newTicks;\n    }\n    const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);\n    if (numMajorIndices > 0) {\n        let i, ilen;\n        const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;\n        skip(ticks, newTicks, spacing, isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);\n        for(i = 0, ilen = numMajorIndices - 1; i < ilen; i++){\n            skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);\n        }\n        skip(ticks, newTicks, spacing, last, isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);\n        return newTicks;\n    }\n    skip(ticks, newTicks, spacing);\n    return newTicks;\n}\nfunction determineMaxTicks(scale) {\n    const offset = scale.options.offset;\n    const tickLength = scale._tickSize();\n    const maxScale = scale._length / tickLength + (offset ? 0 : 1);\n    const maxChart = scale._maxLength / tickLength;\n    return Math.floor(Math.min(maxScale, maxChart));\n}\n function calculateSpacing(majorIndices, ticks, ticksLimit) {\n    const evenMajorSpacing = getEvenSpacing(majorIndices);\n    const spacing = ticks.length / ticksLimit;\n    if (!evenMajorSpacing) {\n        return Math.max(spacing, 1);\n    }\n    const factors = _factorize(evenMajorSpacing);\n    for(let i = 0, ilen = factors.length - 1; i < ilen; i++){\n        const factor = factors[i];\n        if (factor > spacing) {\n            return factor;\n        }\n    }\n    return Math.max(spacing, 1);\n}\n function getMajorIndices(ticks) {\n    const result = [];\n    let i, ilen;\n    for(i = 0, ilen = ticks.length; i < ilen; i++){\n        if (ticks[i].major) {\n            result.push(i);\n        }\n    }\n    return result;\n}\n function skipMajors(ticks, newTicks, majorIndices, spacing) {\n    let count = 0;\n    let next = majorIndices[0];\n    let i;\n    spacing = Math.ceil(spacing);\n    for(i = 0; i < ticks.length; i++){\n        if (i === next) {\n            newTicks.push(ticks[i]);\n            count++;\n            next = majorIndices[count * spacing];\n        }\n    }\n}\n function skip(ticks, newTicks, spacing, majorStart, majorEnd) {\n    const start = valueOrDefault(majorStart, 0);\n    const end = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);\n    let count = 0;\n    let length, i, next;\n    spacing = Math.ceil(spacing);\n    if (majorEnd) {\n        length = majorEnd - majorStart;\n        spacing = length / Math.floor(length / spacing);\n    }\n    next = start;\n    while(next < 0){\n        count++;\n        next = Math.round(start + count * spacing);\n    }\n    for(i = Math.max(start, 0); i < end; i++){\n        if (i === next) {\n            newTicks.push(ticks[i]);\n            count++;\n            next = Math.round(start + count * spacing);\n        }\n    }\n}\n function getEvenSpacing(arr) {\n    const len = arr.length;\n    let i, diff;\n    if (len < 2) {\n        return false;\n    }\n    for(diff = arr[0], i = 1; i < len; ++i){\n        if (arr[i] - arr[i - 1] !== diff) {\n            return false;\n        }\n    }\n    return diff;\n}\n\nconst reverseAlign = (align)=>align === 'left' ? 'right' : align === 'right' ? 'left' : align;\nconst offsetFromEdge = (scale, edge, offset)=>edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset;\nconst getTicksLimit = (ticksLength, maxTicksLimit)=>Math.min(maxTicksLimit || ticksLength, ticksLength);\n function sample(arr, numItems) {\n    const result = [];\n    const increment = arr.length / numItems;\n    const len = arr.length;\n    let i = 0;\n    for(; i < len; i += increment){\n        result.push(arr[Math.floor(i)]);\n    }\n    return result;\n}\n function getPixelForGridLine(scale, index, offsetGridLines) {\n    const length = scale.ticks.length;\n    const validIndex = Math.min(index, length - 1);\n    const start = scale._startPixel;\n    const end = scale._endPixel;\n    const epsilon = 1e-6;\n    let lineValue = scale.getPixelForTick(validIndex);\n    let offset;\n    if (offsetGridLines) {\n        if (length === 1) {\n            offset = Math.max(lineValue - start, end - lineValue);\n        } else if (index === 0) {\n            offset = (scale.getPixelForTick(1) - lineValue) / 2;\n        } else {\n            offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2;\n        }\n        lineValue += validIndex < index ? offset : -offset;\n        if (lineValue < start - epsilon || lineValue > end + epsilon) {\n            return;\n        }\n    }\n    return lineValue;\n}\n function garbageCollect(caches, length) {\n    each(caches, (cache)=>{\n        const gc = cache.gc;\n        const gcLen = gc.length / 2;\n        let i;\n        if (gcLen > length) {\n            for(i = 0; i < gcLen; ++i){\n                delete cache.data[gc[i]];\n            }\n            gc.splice(0, gcLen);\n        }\n    });\n}\n function getTickMarkLength(options) {\n    return options.drawTicks ? options.tickLength : 0;\n}\n function getTitleHeight(options, fallback) {\n    if (!options.display) {\n        return 0;\n    }\n    const font = toFont(options.font, fallback);\n    const padding = toPadding(options.padding);\n    const lines = isArray(options.text) ? options.text.length : 1;\n    return lines * font.lineHeight + padding.height;\n}\nfunction createScaleContext(parent, scale) {\n    return createContext(parent, {\n        scale,\n        type: 'scale'\n    });\n}\nfunction createTickContext(parent, index, tick) {\n    return createContext(parent, {\n        tick,\n        index,\n        type: 'tick'\n    });\n}\nfunction titleAlign(align, position, reverse) {\n     let ret = _toLeftRightCenter(align);\n    if (reverse && position !== 'right' || !reverse && position === 'right') {\n        ret = reverseAlign(ret);\n    }\n    return ret;\n}\nfunction titleArgs(scale, offset, position, align) {\n    const { top , left , bottom , right , chart  } = scale;\n    const { chartArea , scales  } = chart;\n    let rotation = 0;\n    let maxWidth, titleX, titleY;\n    const height = bottom - top;\n    const width = right - left;\n    if (scale.isHorizontal()) {\n        titleX = _alignStartEnd(align, left, right);\n        if (isObject(position)) {\n            const positionAxisID = Object.keys(position)[0];\n            const value = position[positionAxisID];\n            titleY = scales[positionAxisID].getPixelForValue(value) + height - offset;\n        } else if (position === 'center') {\n            titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset;\n        } else {\n            titleY = offsetFromEdge(scale, position, offset);\n        }\n        maxWidth = right - left;\n    } else {\n        if (isObject(position)) {\n            const positionAxisID = Object.keys(position)[0];\n            const value = position[positionAxisID];\n            titleX = scales[positionAxisID].getPixelForValue(value) - width + offset;\n        } else if (position === 'center') {\n            titleX = (chartArea.left + chartArea.right) / 2 - width + offset;\n        } else {\n            titleX = offsetFromEdge(scale, position, offset);\n        }\n        titleY = _alignStartEnd(align, bottom, top);\n        rotation = position === 'left' ? -HALF_PI : HALF_PI;\n    }\n    return {\n        titleX,\n        titleY,\n        maxWidth,\n        rotation\n    };\n}\nclass Scale extends Element {\n    constructor(cfg){\n        super();\n         this.id = cfg.id;\n         this.type = cfg.type;\n         this.options = undefined;\n         this.ctx = cfg.ctx;\n         this.chart = cfg.chart;\n         this.top = undefined;\n         this.bottom = undefined;\n         this.left = undefined;\n         this.right = undefined;\n         this.width = undefined;\n         this.height = undefined;\n        this._margins = {\n            left: 0,\n            right: 0,\n            top: 0,\n            bottom: 0\n        };\n         this.maxWidth = undefined;\n         this.maxHeight = undefined;\n         this.paddingTop = undefined;\n         this.paddingBottom = undefined;\n         this.paddingLeft = undefined;\n         this.paddingRight = undefined;\n         this.axis = undefined;\n         this.labelRotation = undefined;\n        this.min = undefined;\n        this.max = undefined;\n        this._range = undefined;\n         this.ticks = [];\n         this._gridLineItems = null;\n         this._labelItems = null;\n         this._labelSizes = null;\n        this._length = 0;\n        this._maxLength = 0;\n        this._longestTextCache = {};\n         this._startPixel = undefined;\n         this._endPixel = undefined;\n        this._reversePixels = false;\n        this._userMax = undefined;\n        this._userMin = undefined;\n        this._suggestedMax = undefined;\n        this._suggestedMin = undefined;\n        this._ticksLength = 0;\n        this._borderValue = 0;\n        this._cache = {};\n        this._dataLimitsCached = false;\n        this.$context = undefined;\n    }\n init(options) {\n        this.options = options.setContext(this.getContext());\n        this.axis = options.axis;\n        this._userMin = this.parse(options.min);\n        this._userMax = this.parse(options.max);\n        this._suggestedMin = this.parse(options.suggestedMin);\n        this._suggestedMax = this.parse(options.suggestedMax);\n    }\n parse(raw, index) {\n        return raw;\n    }\n getUserBounds() {\n        let { _userMin , _userMax , _suggestedMin , _suggestedMax  } = this;\n        _userMin = finiteOrDefault(_userMin, Number.POSITIVE_INFINITY);\n        _userMax = finiteOrDefault(_userMax, Number.NEGATIVE_INFINITY);\n        _suggestedMin = finiteOrDefault(_suggestedMin, Number.POSITIVE_INFINITY);\n        _suggestedMax = finiteOrDefault(_suggestedMax, Number.NEGATIVE_INFINITY);\n        return {\n            min: finiteOrDefault(_userMin, _suggestedMin),\n            max: finiteOrDefault(_userMax, _suggestedMax),\n            minDefined: isNumberFinite(_userMin),\n            maxDefined: isNumberFinite(_userMax)\n        };\n    }\n getMinMax(canStack) {\n        let { min , max , minDefined , maxDefined  } = this.getUserBounds();\n        let range;\n        if (minDefined && maxDefined) {\n            return {\n                min,\n                max\n            };\n        }\n        const metas = this.getMatchingVisibleMetas();\n        for(let i = 0, ilen = metas.length; i < ilen; ++i){\n            range = metas[i].controller.getMinMax(this, canStack);\n            if (!minDefined) {\n                min = Math.min(min, range.min);\n            }\n            if (!maxDefined) {\n                max = Math.max(max, range.max);\n            }\n        }\n        min = maxDefined && min > max ? max : min;\n        max = minDefined && min > max ? min : max;\n        return {\n            min: finiteOrDefault(min, finiteOrDefault(max, min)),\n            max: finiteOrDefault(max, finiteOrDefault(min, max))\n        };\n    }\n getPadding() {\n        return {\n            left: this.paddingLeft || 0,\n            top: this.paddingTop || 0,\n            right: this.paddingRight || 0,\n            bottom: this.paddingBottom || 0\n        };\n    }\n getTicks() {\n        return this.ticks;\n    }\n getLabels() {\n        const data = this.chart.data;\n        return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];\n    }\n getLabelItems(chartArea = this.chart.chartArea) {\n        const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));\n        return items;\n    }\n    beforeLayout() {\n        this._cache = {};\n        this._dataLimitsCached = false;\n    }\n    beforeUpdate() {\n        callback(this.options.beforeUpdate, [\n            this\n        ]);\n    }\n update(maxWidth, maxHeight, margins) {\n        const { beginAtZero , grace , ticks: tickOpts  } = this.options;\n        const sampleSize = tickOpts.sampleSize;\n        this.beforeUpdate();\n        this.maxWidth = maxWidth;\n        this.maxHeight = maxHeight;\n        this._margins = margins = Object.assign({\n            left: 0,\n            right: 0,\n            top: 0,\n            bottom: 0\n        }, margins);\n        this.ticks = null;\n        this._labelSizes = null;\n        this._gridLineItems = null;\n        this._labelItems = null;\n        this.beforeSetDimensions();\n        this.setDimensions();\n        this.afterSetDimensions();\n        this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom;\n        if (!this._dataLimitsCached) {\n            this.beforeDataLimits();\n            this.determineDataLimits();\n            this.afterDataLimits();\n            this._range = _addGrace(this, grace, beginAtZero);\n            this._dataLimitsCached = true;\n        }\n        this.beforeBuildTicks();\n        this.ticks = this.buildTicks() || [];\n        this.afterBuildTicks();\n        const samplingEnabled = sampleSize < this.ticks.length;\n        this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);\n        this.configure();\n        this.beforeCalculateLabelRotation();\n        this.calculateLabelRotation();\n        this.afterCalculateLabelRotation();\n        if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {\n            this.ticks = autoSkip(this, this.ticks);\n            this._labelSizes = null;\n            this.afterAutoSkip();\n        }\n        if (samplingEnabled) {\n            this._convertTicksToLabels(this.ticks);\n        }\n        this.beforeFit();\n        this.fit();\n        this.afterFit();\n        this.afterUpdate();\n    }\n configure() {\n        let reversePixels = this.options.reverse;\n        let startPixel, endPixel;\n        if (this.isHorizontal()) {\n            startPixel = this.left;\n            endPixel = this.right;\n        } else {\n            startPixel = this.top;\n            endPixel = this.bottom;\n            reversePixels = !reversePixels;\n        }\n        this._startPixel = startPixel;\n        this._endPixel = endPixel;\n        this._reversePixels = reversePixels;\n        this._length = endPixel - startPixel;\n        this._alignToPixels = this.options.alignToPixels;\n    }\n    afterUpdate() {\n        callback(this.options.afterUpdate, [\n            this\n        ]);\n    }\n    beforeSetDimensions() {\n        callback(this.options.beforeSetDimensions, [\n            this\n        ]);\n    }\n    setDimensions() {\n        if (this.isHorizontal()) {\n            this.width = this.maxWidth;\n            this.left = 0;\n            this.right = this.width;\n        } else {\n            this.height = this.maxHeight;\n            this.top = 0;\n            this.bottom = this.height;\n        }\n        this.paddingLeft = 0;\n        this.paddingTop = 0;\n        this.paddingRight = 0;\n        this.paddingBottom = 0;\n    }\n    afterSetDimensions() {\n        callback(this.options.afterSetDimensions, [\n            this\n        ]);\n    }\n    _callHooks(name) {\n        this.chart.notifyPlugins(name, this.getContext());\n        callback(this.options[name], [\n            this\n        ]);\n    }\n    beforeDataLimits() {\n        this._callHooks('beforeDataLimits');\n    }\n    determineDataLimits() {}\n    afterDataLimits() {\n        this._callHooks('afterDataLimits');\n    }\n    beforeBuildTicks() {\n        this._callHooks('beforeBuildTicks');\n    }\n buildTicks() {\n        return [];\n    }\n    afterBuildTicks() {\n        this._callHooks('afterBuildTicks');\n    }\n    beforeTickToLabelConversion() {\n        callback(this.options.beforeTickToLabelConversion, [\n            this\n        ]);\n    }\n generateTickLabels(ticks) {\n        const tickOpts = this.options.ticks;\n        let i, ilen, tick;\n        for(i = 0, ilen = ticks.length; i < ilen; i++){\n            tick = ticks[i];\n            tick.label = callback(tickOpts.callback, [\n                tick.value,\n                i,\n                ticks\n            ], this);\n        }\n    }\n    afterTickToLabelConversion() {\n        callback(this.options.afterTickToLabelConversion, [\n            this\n        ]);\n    }\n    beforeCalculateLabelRotation() {\n        callback(this.options.beforeCalculateLabelRotation, [\n            this\n        ]);\n    }\n    calculateLabelRotation() {\n        const options = this.options;\n        const tickOpts = options.ticks;\n        const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit);\n        const minRotation = tickOpts.minRotation || 0;\n        const maxRotation = tickOpts.maxRotation;\n        let labelRotation = minRotation;\n        let tickWidth, maxHeight, maxLabelDiagonal;\n        if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {\n            this.labelRotation = minRotation;\n            return;\n        }\n        const labelSizes = this._getLabelSizes();\n        const maxLabelWidth = labelSizes.widest.width;\n        const maxLabelHeight = labelSizes.highest.height;\n        const maxWidth = _limitValue(this.chart.width - maxLabelWidth, 0, this.maxWidth);\n        tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);\n        if (maxLabelWidth + 6 > tickWidth) {\n            tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));\n            maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);\n            maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);\n            labelRotation = toDegrees(Math.min(Math.asin(_limitValue((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin(_limitValue(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin(_limitValue(maxLabelHeight / maxLabelDiagonal, -1, 1))));\n            labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));\n        }\n        this.labelRotation = labelRotation;\n    }\n    afterCalculateLabelRotation() {\n        callback(this.options.afterCalculateLabelRotation, [\n            this\n        ]);\n    }\n    afterAutoSkip() {}\n    beforeFit() {\n        callback(this.options.beforeFit, [\n            this\n        ]);\n    }\n    fit() {\n        const minSize = {\n            width: 0,\n            height: 0\n        };\n        const { chart , options: { ticks: tickOpts , title: titleOpts , grid: gridOpts  }  } = this;\n        const display = this._isVisible();\n        const isHorizontal = this.isHorizontal();\n        if (display) {\n            const titleHeight = getTitleHeight(titleOpts, chart.options.font);\n            if (isHorizontal) {\n                minSize.width = this.maxWidth;\n                minSize.height = getTickMarkLength(gridOpts) + titleHeight;\n            } else {\n                minSize.height = this.maxHeight;\n                minSize.width = getTickMarkLength(gridOpts) + titleHeight;\n            }\n            if (tickOpts.display && this.ticks.length) {\n                const { first , last , widest , highest  } = this._getLabelSizes();\n                const tickPadding = tickOpts.padding * 2;\n                const angleRadians = toRadians(this.labelRotation);\n                const cos = Math.cos(angleRadians);\n                const sin = Math.sin(angleRadians);\n                if (isHorizontal) {\n                    const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;\n                    minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);\n                } else {\n                    const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;\n                    minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);\n                }\n                this._calculatePadding(first, last, sin, cos);\n            }\n        }\n        this._handleMargins();\n        if (isHorizontal) {\n            this.width = this._length = chart.width - this._margins.left - this._margins.right;\n            this.height = minSize.height;\n        } else {\n            this.width = minSize.width;\n            this.height = this._length = chart.height - this._margins.top - this._margins.bottom;\n        }\n    }\n    _calculatePadding(first, last, sin, cos) {\n        const { ticks: { align , padding  } , position  } = this.options;\n        const isRotated = this.labelRotation !== 0;\n        const labelsBelowTicks = position !== 'top' && this.axis === 'x';\n        if (this.isHorizontal()) {\n            const offsetLeft = this.getPixelForTick(0) - this.left;\n            const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);\n            let paddingLeft = 0;\n            let paddingRight = 0;\n            if (isRotated) {\n                if (labelsBelowTicks) {\n                    paddingLeft = cos * first.width;\n                    paddingRight = sin * last.height;\n                } else {\n                    paddingLeft = sin * first.height;\n                    paddingRight = cos * last.width;\n                }\n            } else if (align === 'start') {\n                paddingRight = last.width;\n            } else if (align === 'end') {\n                paddingLeft = first.width;\n            } else if (align !== 'inner') {\n                paddingLeft = first.width / 2;\n                paddingRight = last.width / 2;\n            }\n            this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);\n            this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);\n        } else {\n            let paddingTop = last.height / 2;\n            let paddingBottom = first.height / 2;\n            if (align === 'start') {\n                paddingTop = 0;\n                paddingBottom = first.height;\n            } else if (align === 'end') {\n                paddingTop = last.height;\n                paddingBottom = 0;\n            }\n            this.paddingTop = paddingTop + padding;\n            this.paddingBottom = paddingBottom + padding;\n        }\n    }\n _handleMargins() {\n        if (this._margins) {\n            this._margins.left = Math.max(this.paddingLeft, this._margins.left);\n            this._margins.top = Math.max(this.paddingTop, this._margins.top);\n            this._margins.right = Math.max(this.paddingRight, this._margins.right);\n            this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);\n        }\n    }\n    afterFit() {\n        callback(this.options.afterFit, [\n            this\n        ]);\n    }\n isHorizontal() {\n        const { axis , position  } = this.options;\n        return position === 'top' || position === 'bottom' || axis === 'x';\n    }\n isFullSize() {\n        return this.options.fullSize;\n    }\n _convertTicksToLabels(ticks) {\n        this.beforeTickToLabelConversion();\n        this.generateTickLabels(ticks);\n        let i, ilen;\n        for(i = 0, ilen = ticks.length; i < ilen; i++){\n            if (isNullOrUndef(ticks[i].label)) {\n                ticks.splice(i, 1);\n                ilen--;\n                i--;\n            }\n        }\n        this.afterTickToLabelConversion();\n    }\n _getLabelSizes() {\n        let labelSizes = this._labelSizes;\n        if (!labelSizes) {\n            const sampleSize = this.options.ticks.sampleSize;\n            let ticks = this.ticks;\n            if (sampleSize < ticks.length) {\n                ticks = sample(ticks, sampleSize);\n            }\n            this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit);\n        }\n        return labelSizes;\n    }\n _computeLabelSizes(ticks, length, maxTicksLimit) {\n        const { ctx , _longestTextCache: caches  } = this;\n        const widths = [];\n        const heights = [];\n        const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit));\n        let widestLabelSize = 0;\n        let highestLabelSize = 0;\n        let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel;\n        for(i = 0; i < length; i += increment){\n            label = ticks[i].label;\n            tickFont = this._resolveTickFontOptions(i);\n            ctx.font = fontString = tickFont.string;\n            cache = caches[fontString] = caches[fontString] || {\n                data: {},\n                gc: []\n            };\n            lineHeight = tickFont.lineHeight;\n            width = height = 0;\n            if (!isNullOrUndef(label) && !isArray(label)) {\n                width = _measureText(ctx, cache.data, cache.gc, width, label);\n                height = lineHeight;\n            } else if (isArray(label)) {\n                for(j = 0, jlen = label.length; j < jlen; ++j){\n                    nestedLabel =  label[j];\n                    if (!isNullOrUndef(nestedLabel) && !isArray(nestedLabel)) {\n                        width = _measureText(ctx, cache.data, cache.gc, width, nestedLabel);\n                        height += lineHeight;\n                    }\n                }\n            }\n            widths.push(width);\n            heights.push(height);\n            widestLabelSize = Math.max(width, widestLabelSize);\n            highestLabelSize = Math.max(height, highestLabelSize);\n        }\n        garbageCollect(caches, length);\n        const widest = widths.indexOf(widestLabelSize);\n        const highest = heights.indexOf(highestLabelSize);\n        const valueAt = (idx)=>({\n                width: widths[idx] || 0,\n                height: heights[idx] || 0\n            });\n        return {\n            first: valueAt(0),\n            last: valueAt(length - 1),\n            widest: valueAt(widest),\n            highest: valueAt(highest),\n            widths,\n            heights\n        };\n    }\n getLabelForValue(value) {\n        return value;\n    }\n getPixelForValue(value, index) {\n        return NaN;\n    }\n getValueForPixel(pixel) {}\n getPixelForTick(index) {\n        const ticks = this.ticks;\n        if (index < 0 || index > ticks.length - 1) {\n            return null;\n        }\n        return this.getPixelForValue(ticks[index].value);\n    }\n getPixelForDecimal(decimal) {\n        if (this._reversePixels) {\n            decimal = 1 - decimal;\n        }\n        const pixel = this._startPixel + decimal * this._length;\n        return _int16Range(this._alignToPixels ? _alignPixel(this.chart, pixel, 0) : pixel);\n    }\n getDecimalForPixel(pixel) {\n        const decimal = (pixel - this._startPixel) / this._length;\n        return this._reversePixels ? 1 - decimal : decimal;\n    }\n getBasePixel() {\n        return this.getPixelForValue(this.getBaseValue());\n    }\n getBaseValue() {\n        const { min , max  } = this;\n        return min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0;\n    }\n getContext(index) {\n        const ticks = this.ticks || [];\n        if (index >= 0 && index < ticks.length) {\n            const tick = ticks[index];\n            return tick.$context || (tick.$context = createTickContext(this.getContext(), index, tick));\n        }\n        return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this));\n    }\n _tickSize() {\n        const optionTicks = this.options.ticks;\n        const rot = toRadians(this.labelRotation);\n        const cos = Math.abs(Math.cos(rot));\n        const sin = Math.abs(Math.sin(rot));\n        const labelSizes = this._getLabelSizes();\n        const padding = optionTicks.autoSkipPadding || 0;\n        const w = labelSizes ? labelSizes.widest.width + padding : 0;\n        const h = labelSizes ? labelSizes.highest.height + padding : 0;\n        return this.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin;\n    }\n _isVisible() {\n        const display = this.options.display;\n        if (display !== 'auto') {\n            return !!display;\n        }\n        return this.getMatchingVisibleMetas().length > 0;\n    }\n _computeGridLineItems(chartArea) {\n        const axis = this.axis;\n        const chart = this.chart;\n        const options = this.options;\n        const { grid , position , border  } = options;\n        const offset = grid.offset;\n        const isHorizontal = this.isHorizontal();\n        const ticks = this.ticks;\n        const ticksLength = ticks.length + (offset ? 1 : 0);\n        const tl = getTickMarkLength(grid);\n        const items = [];\n        const borderOpts = border.setContext(this.getContext());\n        const axisWidth = borderOpts.display ? borderOpts.width : 0;\n        const axisHalfWidth = axisWidth / 2;\n        const alignBorderValue = function(pixel) {\n            return _alignPixel(chart, pixel, axisWidth);\n        };\n        let borderValue, i, lineValue, alignedLineValue;\n        let tx1, ty1, tx2, ty2, x1, y1, x2, y2;\n        if (position === 'top') {\n            borderValue = alignBorderValue(this.bottom);\n            ty1 = this.bottom - tl;\n            ty2 = borderValue - axisHalfWidth;\n            y1 = alignBorderValue(chartArea.top) + axisHalfWidth;\n            y2 = chartArea.bottom;\n        } else if (position === 'bottom') {\n            borderValue = alignBorderValue(this.top);\n            y1 = chartArea.top;\n            y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;\n            ty1 = borderValue + axisHalfWidth;\n            ty2 = this.top + tl;\n        } else if (position === 'left') {\n            borderValue = alignBorderValue(this.right);\n            tx1 = this.right - tl;\n            tx2 = borderValue - axisHalfWidth;\n            x1 = alignBorderValue(chartArea.left) + axisHalfWidth;\n            x2 = chartArea.right;\n        } else if (position === 'right') {\n            borderValue = alignBorderValue(this.left);\n            x1 = chartArea.left;\n            x2 = alignBorderValue(chartArea.right) - axisHalfWidth;\n            tx1 = borderValue + axisHalfWidth;\n            tx2 = this.left + tl;\n        } else if (axis === 'x') {\n            if (position === 'center') {\n                borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);\n            } else if (isObject(position)) {\n                const positionAxisID = Object.keys(position)[0];\n                const value = position[positionAxisID];\n                borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));\n            }\n            y1 = chartArea.top;\n            y2 = chartArea.bottom;\n            ty1 = borderValue + axisHalfWidth;\n            ty2 = ty1 + tl;\n        } else if (axis === 'y') {\n            if (position === 'center') {\n                borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);\n            } else if (isObject(position)) {\n                const positionAxisID = Object.keys(position)[0];\n                const value = position[positionAxisID];\n                borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));\n            }\n            tx1 = borderValue - axisHalfWidth;\n            tx2 = tx1 - tl;\n            x1 = chartArea.left;\n            x2 = chartArea.right;\n        }\n        const limit = valueOrDefault(options.ticks.maxTicksLimit, ticksLength);\n        const step = Math.max(1, Math.ceil(ticksLength / limit));\n        for(i = 0; i < ticksLength; i += step){\n            const context = this.getContext(i);\n            const optsAtIndex = grid.setContext(context);\n            const optsAtIndexBorder = border.setContext(context);\n            const lineWidth = optsAtIndex.lineWidth;\n            const lineColor = optsAtIndex.color;\n            const borderDash = optsAtIndexBorder.dash || [];\n            const borderDashOffset = optsAtIndexBorder.dashOffset;\n            const tickWidth = optsAtIndex.tickWidth;\n            const tickColor = optsAtIndex.tickColor;\n            const tickBorderDash = optsAtIndex.tickBorderDash || [];\n            const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;\n            lineValue = getPixelForGridLine(this, i, offset);\n            if (lineValue === undefined) {\n                continue;\n            }\n            alignedLineValue = _alignPixel(chart, lineValue, lineWidth);\n            if (isHorizontal) {\n                tx1 = tx2 = x1 = x2 = alignedLineValue;\n            } else {\n                ty1 = ty2 = y1 = y2 = alignedLineValue;\n            }\n            items.push({\n                tx1,\n                ty1,\n                tx2,\n                ty2,\n                x1,\n                y1,\n                x2,\n                y2,\n                width: lineWidth,\n                color: lineColor,\n                borderDash,\n                borderDashOffset,\n                tickWidth,\n                tickColor,\n                tickBorderDash,\n                tickBorderDashOffset\n            });\n        }\n        this._ticksLength = ticksLength;\n        this._borderValue = borderValue;\n        return items;\n    }\n _computeLabelItems(chartArea) {\n        const axis = this.axis;\n        const options = this.options;\n        const { position , ticks: optionTicks  } = options;\n        const isHorizontal = this.isHorizontal();\n        const ticks = this.ticks;\n        const { align , crossAlign , padding , mirror  } = optionTicks;\n        const tl = getTickMarkLength(options.grid);\n        const tickAndPadding = tl + padding;\n        const hTickAndPadding = mirror ? -padding : tickAndPadding;\n        const rotation = -toRadians(this.labelRotation);\n        const items = [];\n        let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;\n        let textBaseline = 'middle';\n        if (position === 'top') {\n            y = this.bottom - hTickAndPadding;\n            textAlign = this._getXAxisLabelAlignment();\n        } else if (position === 'bottom') {\n            y = this.top + hTickAndPadding;\n            textAlign = this._getXAxisLabelAlignment();\n        } else if (position === 'left') {\n            const ret = this._getYAxisLabelAlignment(tl);\n            textAlign = ret.textAlign;\n            x = ret.x;\n        } else if (position === 'right') {\n            const ret = this._getYAxisLabelAlignment(tl);\n            textAlign = ret.textAlign;\n            x = ret.x;\n        } else if (axis === 'x') {\n            if (position === 'center') {\n                y = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding;\n            } else if (isObject(position)) {\n                const positionAxisID = Object.keys(position)[0];\n                const value = position[positionAxisID];\n                y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;\n            }\n            textAlign = this._getXAxisLabelAlignment();\n        } else if (axis === 'y') {\n            if (position === 'center') {\n                x = (chartArea.left + chartArea.right) / 2 - tickAndPadding;\n            } else if (isObject(position)) {\n                const positionAxisID = Object.keys(position)[0];\n                const value = position[positionAxisID];\n                x = this.chart.scales[positionAxisID].getPixelForValue(value);\n            }\n            textAlign = this._getYAxisLabelAlignment(tl).textAlign;\n        }\n        if (axis === 'y') {\n            if (align === 'start') {\n                textBaseline = 'top';\n            } else if (align === 'end') {\n                textBaseline = 'bottom';\n            }\n        }\n        const labelSizes = this._getLabelSizes();\n        for(i = 0, ilen = ticks.length; i < ilen; ++i){\n            tick = ticks[i];\n            label = tick.label;\n            const optsAtIndex = optionTicks.setContext(this.getContext(i));\n            pixel = this.getPixelForTick(i) + optionTicks.labelOffset;\n            font = this._resolveTickFontOptions(i);\n            lineHeight = font.lineHeight;\n            lineCount = isArray(label) ? label.length : 1;\n            const halfCount = lineCount / 2;\n            const color = optsAtIndex.color;\n            const strokeColor = optsAtIndex.textStrokeColor;\n            const strokeWidth = optsAtIndex.textStrokeWidth;\n            let tickTextAlign = textAlign;\n            if (isHorizontal) {\n                x = pixel;\n                if (textAlign === 'inner') {\n                    if (i === ilen - 1) {\n                        tickTextAlign = !this.options.reverse ? 'right' : 'left';\n                    } else if (i === 0) {\n                        tickTextAlign = !this.options.reverse ? 'left' : 'right';\n                    } else {\n                        tickTextAlign = 'center';\n                    }\n                }\n                if (position === 'top') {\n                    if (crossAlign === 'near' || rotation !== 0) {\n                        textOffset = -lineCount * lineHeight + lineHeight / 2;\n                    } else if (crossAlign === 'center') {\n                        textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;\n                    } else {\n                        textOffset = -labelSizes.highest.height + lineHeight / 2;\n                    }\n                } else {\n                    if (crossAlign === 'near' || rotation !== 0) {\n                        textOffset = lineHeight / 2;\n                    } else if (crossAlign === 'center') {\n                        textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;\n                    } else {\n                        textOffset = labelSizes.highest.height - lineCount * lineHeight;\n                    }\n                }\n                if (mirror) {\n                    textOffset *= -1;\n                }\n                if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) {\n                    x += lineHeight / 2 * Math.sin(rotation);\n                }\n            } else {\n                y = pixel;\n                textOffset = (1 - lineCount) * lineHeight / 2;\n            }\n            let backdrop;\n            if (optsAtIndex.showLabelBackdrop) {\n                const labelPadding = toPadding(optsAtIndex.backdropPadding);\n                const height = labelSizes.heights[i];\n                const width = labelSizes.widths[i];\n                let top = textOffset - labelPadding.top;\n                let left = 0 - labelPadding.left;\n                switch(textBaseline){\n                    case 'middle':\n                        top -= height / 2;\n                        break;\n                    case 'bottom':\n                        top -= height;\n                        break;\n                }\n                switch(textAlign){\n                    case 'center':\n                        left -= width / 2;\n                        break;\n                    case 'right':\n                        left -= width;\n                        break;\n                    case 'inner':\n                        if (i === ilen - 1) {\n                            left -= width;\n                        } else if (i > 0) {\n                            left -= width / 2;\n                        }\n                        break;\n                }\n                backdrop = {\n                    left,\n                    top,\n                    width: width + labelPadding.width,\n                    height: height + labelPadding.height,\n                    color: optsAtIndex.backdropColor\n                };\n            }\n            items.push({\n                label,\n                font,\n                textOffset,\n                options: {\n                    rotation,\n                    color,\n                    strokeColor,\n                    strokeWidth,\n                    textAlign: tickTextAlign,\n                    textBaseline,\n                    translation: [\n                        x,\n                        y\n                    ],\n                    backdrop\n                }\n            });\n        }\n        return items;\n    }\n    _getXAxisLabelAlignment() {\n        const { position , ticks  } = this.options;\n        const rotation = -toRadians(this.labelRotation);\n        if (rotation) {\n            return position === 'top' ? 'left' : 'right';\n        }\n        let align = 'center';\n        if (ticks.align === 'start') {\n            align = 'left';\n        } else if (ticks.align === 'end') {\n            align = 'right';\n        } else if (ticks.align === 'inner') {\n            align = 'inner';\n        }\n        return align;\n    }\n    _getYAxisLabelAlignment(tl) {\n        const { position , ticks: { crossAlign , mirror , padding  }  } = this.options;\n        const labelSizes = this._getLabelSizes();\n        const tickAndPadding = tl + padding;\n        const widest = labelSizes.widest.width;\n        let textAlign;\n        let x;\n        if (position === 'left') {\n            if (mirror) {\n                x = this.right + padding;\n                if (crossAlign === 'near') {\n                    textAlign = 'left';\n                } else if (crossAlign === 'center') {\n                    textAlign = 'center';\n                    x += widest / 2;\n                } else {\n                    textAlign = 'right';\n                    x += widest;\n                }\n            } else {\n                x = this.right - tickAndPadding;\n                if (crossAlign === 'near') {\n                    textAlign = 'right';\n                } else if (crossAlign === 'center') {\n                    textAlign = 'center';\n                    x -= widest / 2;\n                } else {\n                    textAlign = 'left';\n                    x = this.left;\n                }\n            }\n        } else if (position === 'right') {\n            if (mirror) {\n                x = this.left + padding;\n                if (crossAlign === 'near') {\n                    textAlign = 'right';\n                } else if (crossAlign === 'center') {\n                    textAlign = 'center';\n                    x -= widest / 2;\n                } else {\n                    textAlign = 'left';\n                    x -= widest;\n                }\n            } else {\n                x = this.left + tickAndPadding;\n                if (crossAlign === 'near') {\n                    textAlign = 'left';\n                } else if (crossAlign === 'center') {\n                    textAlign = 'center';\n                    x += widest / 2;\n                } else {\n                    textAlign = 'right';\n                    x = this.right;\n                }\n            }\n        } else {\n            textAlign = 'right';\n        }\n        return {\n            textAlign,\n            x\n        };\n    }\n _computeLabelArea() {\n        if (this.options.ticks.mirror) {\n            return;\n        }\n        const chart = this.chart;\n        const position = this.options.position;\n        if (position === 'left' || position === 'right') {\n            return {\n                top: 0,\n                left: this.left,\n                bottom: chart.height,\n                right: this.right\n            };\n        }\n        if (position === 'top' || position === 'bottom') {\n            return {\n                top: this.top,\n                left: 0,\n                bottom: this.bottom,\n                right: chart.width\n            };\n        }\n    }\n drawBackground() {\n        const { ctx , options: { backgroundColor  } , left , top , width , height  } = this;\n        if (backgroundColor) {\n            ctx.save();\n            ctx.fillStyle = backgroundColor;\n            ctx.fillRect(left, top, width, height);\n            ctx.restore();\n        }\n    }\n    getLineWidthForValue(value) {\n        const grid = this.options.grid;\n        if (!this._isVisible() || !grid.display) {\n            return 0;\n        }\n        const ticks = this.ticks;\n        const index = ticks.findIndex((t)=>t.value === value);\n        if (index >= 0) {\n            const opts = grid.setContext(this.getContext(index));\n            return opts.lineWidth;\n        }\n        return 0;\n    }\n drawGrid(chartArea) {\n        const grid = this.options.grid;\n        const ctx = this.ctx;\n        const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));\n        let i, ilen;\n        const drawLine = (p1, p2, style)=>{\n            if (!style.width || !style.color) {\n                return;\n            }\n            ctx.save();\n            ctx.lineWidth = style.width;\n            ctx.strokeStyle = style.color;\n            ctx.setLineDash(style.borderDash || []);\n            ctx.lineDashOffset = style.borderDashOffset;\n            ctx.beginPath();\n            ctx.moveTo(p1.x, p1.y);\n            ctx.lineTo(p2.x, p2.y);\n            ctx.stroke();\n            ctx.restore();\n        };\n        if (grid.display) {\n            for(i = 0, ilen = items.length; i < ilen; ++i){\n                const item = items[i];\n                if (grid.drawOnChartArea) {\n                    drawLine({\n                        x: item.x1,\n                        y: item.y1\n                    }, {\n                        x: item.x2,\n                        y: item.y2\n                    }, item);\n                }\n                if (grid.drawTicks) {\n                    drawLine({\n                        x: item.tx1,\n                        y: item.ty1\n                    }, {\n                        x: item.tx2,\n                        y: item.ty2\n                    }, {\n                        color: item.tickColor,\n                        width: item.tickWidth,\n                        borderDash: item.tickBorderDash,\n                        borderDashOffset: item.tickBorderDashOffset\n                    });\n                }\n            }\n        }\n    }\n drawBorder() {\n        const { chart , ctx , options: { border , grid  }  } = this;\n        const borderOpts = border.setContext(this.getContext());\n        const axisWidth = border.display ? borderOpts.width : 0;\n        if (!axisWidth) {\n            return;\n        }\n        const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;\n        const borderValue = this._borderValue;\n        let x1, x2, y1, y2;\n        if (this.isHorizontal()) {\n            x1 = _alignPixel(chart, this.left, axisWidth) - axisWidth / 2;\n            x2 = _alignPixel(chart, this.right, lastLineWidth) + lastLineWidth / 2;\n            y1 = y2 = borderValue;\n        } else {\n            y1 = _alignPixel(chart, this.top, axisWidth) - axisWidth / 2;\n            y2 = _alignPixel(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;\n            x1 = x2 = borderValue;\n        }\n        ctx.save();\n        ctx.lineWidth = borderOpts.width;\n        ctx.strokeStyle = borderOpts.color;\n        ctx.beginPath();\n        ctx.moveTo(x1, y1);\n        ctx.lineTo(x2, y2);\n        ctx.stroke();\n        ctx.restore();\n    }\n drawLabels(chartArea) {\n        const optionTicks = this.options.ticks;\n        if (!optionTicks.display) {\n            return;\n        }\n        const ctx = this.ctx;\n        const area = this._computeLabelArea();\n        if (area) {\n            clipArea(ctx, area);\n        }\n        const items = this.getLabelItems(chartArea);\n        for (const item of items){\n            const renderTextOptions = item.options;\n            const tickFont = item.font;\n            const label = item.label;\n            const y = item.textOffset;\n            renderText(ctx, label, 0, y, tickFont, renderTextOptions);\n        }\n        if (area) {\n            unclipArea(ctx);\n        }\n    }\n drawTitle() {\n        const { ctx , options: { position , title , reverse  }  } = this;\n        if (!title.display) {\n            return;\n        }\n        const font = toFont(title.font);\n        const padding = toPadding(title.padding);\n        const align = title.align;\n        let offset = font.lineHeight / 2;\n        if (position === 'bottom' || position === 'center' || isObject(position)) {\n            offset += padding.bottom;\n            if (isArray(title.text)) {\n                offset += font.lineHeight * (title.text.length - 1);\n            }\n        } else {\n            offset += padding.top;\n        }\n        const { titleX , titleY , maxWidth , rotation  } = titleArgs(this, offset, position, align);\n        renderText(ctx, title.text, 0, 0, font, {\n            color: title.color,\n            maxWidth,\n            rotation,\n            textAlign: titleAlign(align, position, reverse),\n            textBaseline: 'middle',\n            translation: [\n                titleX,\n                titleY\n            ]\n        });\n    }\n    draw(chartArea) {\n        if (!this._isVisible()) {\n            return;\n        }\n        this.drawBackground();\n        this.drawGrid(chartArea);\n        this.drawBorder();\n        this.drawTitle();\n        this.drawLabels(chartArea);\n    }\n _layers() {\n        const opts = this.options;\n        const tz = opts.ticks && opts.ticks.z || 0;\n        const gz = valueOrDefault(opts.grid && opts.grid.z, -1);\n        const bz = valueOrDefault(opts.border && opts.border.z, 0);\n        if (!this._isVisible() || this.draw !== Scale.prototype.draw) {\n            return [\n                {\n                    z: tz,\n                    draw: (chartArea)=>{\n                        this.draw(chartArea);\n                    }\n                }\n            ];\n        }\n        return [\n            {\n                z: gz,\n                draw: (chartArea)=>{\n                    this.drawBackground();\n                    this.drawGrid(chartArea);\n                    this.drawTitle();\n                }\n            },\n            {\n                z: bz,\n                draw: ()=>{\n                    this.drawBorder();\n                }\n            },\n            {\n                z: tz,\n                draw: (chartArea)=>{\n                    this.drawLabels(chartArea);\n                }\n            }\n        ];\n    }\n getMatchingVisibleMetas(type) {\n        const metas = this.chart.getSortedVisibleDatasetMetas();\n        const axisID = this.axis + 'AxisID';\n        const result = [];\n        let i, ilen;\n        for(i = 0, ilen = metas.length; i < ilen; ++i){\n            const meta = metas[i];\n            if (meta[axisID] === this.id && (!type || meta.type === type)) {\n                result.push(meta);\n            }\n        }\n        return result;\n    }\n _resolveTickFontOptions(index) {\n        const opts = this.options.ticks.setContext(this.getContext(index));\n        return toFont(opts.font);\n    }\n _maxDigits() {\n        const fontSize = this._resolveTickFontOptions(0).lineHeight;\n        return (this.isHorizontal() ? this.width : this.height) / fontSize;\n    }\n}\n\nclass TypedRegistry {\n    constructor(type, scope, override){\n        this.type = type;\n        this.scope = scope;\n        this.override = override;\n        this.items = Object.create(null);\n    }\n    isForType(type) {\n        return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);\n    }\n register(item) {\n        const proto = Object.getPrototypeOf(item);\n        let parentScope;\n        if (isIChartComponent(proto)) {\n            parentScope = this.register(proto);\n        }\n        const items = this.items;\n        const id = item.id;\n        const scope = this.scope + '.' + id;\n        if (!id) {\n            throw new Error('class does not have id: ' + item);\n        }\n        if (id in items) {\n            return scope;\n        }\n        items[id] = item;\n        registerDefaults(item, scope, parentScope);\n        if (this.override) {\n            defaults.override(item.id, item.overrides);\n        }\n        return scope;\n    }\n get(id) {\n        return this.items[id];\n    }\n unregister(item) {\n        const items = this.items;\n        const id = item.id;\n        const scope = this.scope;\n        if (id in items) {\n            delete items[id];\n        }\n        if (scope && id in defaults[scope]) {\n            delete defaults[scope][id];\n            if (this.override) {\n                delete overrides[id];\n            }\n        }\n    }\n}\nfunction registerDefaults(item, scope, parentScope) {\n    const itemDefaults = merge(Object.create(null), [\n        parentScope ? defaults.get(parentScope) : {},\n        defaults.get(scope),\n        item.defaults\n    ]);\n    defaults.set(scope, itemDefaults);\n    if (item.defaultRoutes) {\n        routeDefaults(scope, item.defaultRoutes);\n    }\n    if (item.descriptors) {\n        defaults.describe(scope, item.descriptors);\n    }\n}\nfunction routeDefaults(scope, routes) {\n    Object.keys(routes).forEach((property)=>{\n        const propertyParts = property.split('.');\n        const sourceName = propertyParts.pop();\n        const sourceScope = [\n            scope\n        ].concat(propertyParts).join('.');\n        const parts = routes[property].split('.');\n        const targetName = parts.pop();\n        const targetScope = parts.join('.');\n        defaults.route(sourceScope, sourceName, targetScope, targetName);\n    });\n}\nfunction isIChartComponent(proto) {\n    return 'id' in proto && 'defaults' in proto;\n}\n\nclass Registry {\n    constructor(){\n        this.controllers = new TypedRegistry(DatasetController, 'datasets', true);\n        this.elements = new TypedRegistry(Element, 'elements');\n        this.plugins = new TypedRegistry(Object, 'plugins');\n        this.scales = new TypedRegistry(Scale, 'scales');\n        this._typedRegistries = [\n            this.controllers,\n            this.scales,\n            this.elements\n        ];\n    }\n add(...args) {\n        this._each('register', args);\n    }\n    remove(...args) {\n        this._each('unregister', args);\n    }\n addControllers(...args) {\n        this._each('register', args, this.controllers);\n    }\n addElements(...args) {\n        this._each('register', args, this.elements);\n    }\n addPlugins(...args) {\n        this._each('register', args, this.plugins);\n    }\n addScales(...args) {\n        this._each('register', args, this.scales);\n    }\n getController(id) {\n        return this._get(id, this.controllers, 'controller');\n    }\n getElement(id) {\n        return this._get(id, this.elements, 'element');\n    }\n getPlugin(id) {\n        return this._get(id, this.plugins, 'plugin');\n    }\n getScale(id) {\n        return this._get(id, this.scales, 'scale');\n    }\n removeControllers(...args) {\n        this._each('unregister', args, this.controllers);\n    }\n removeElements(...args) {\n        this._each('unregister', args, this.elements);\n    }\n removePlugins(...args) {\n        this._each('unregister', args, this.plugins);\n    }\n removeScales(...args) {\n        this._each('unregister', args, this.scales);\n    }\n _each(method, args, typedRegistry) {\n        [\n            ...args\n        ].forEach((arg)=>{\n            const reg = typedRegistry || this._getRegistryForType(arg);\n            if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) {\n                this._exec(method, reg, arg);\n            } else {\n                each(arg, (item)=>{\n                    const itemReg = typedRegistry || this._getRegistryForType(item);\n                    this._exec(method, itemReg, item);\n                });\n            }\n        });\n    }\n _exec(method, registry, component) {\n        const camelMethod = _capitalize(method);\n        callback(component['before' + camelMethod], [], component);\n        registry[method](component);\n        callback(component['after' + camelMethod], [], component);\n    }\n _getRegistryForType(type) {\n        for(let i = 0; i < this._typedRegistries.length; i++){\n            const reg = this._typedRegistries[i];\n            if (reg.isForType(type)) {\n                return reg;\n            }\n        }\n        return this.plugins;\n    }\n _get(id, typedRegistry, type) {\n        const item = typedRegistry.get(id);\n        if (item === undefined) {\n            throw new Error('\"' + id + '\" is not a registered ' + type + '.');\n        }\n        return item;\n    }\n}\nvar registry = /* #__PURE__ */ new Registry();\n\nclass PluginService {\n    constructor(){\n        this._init = [];\n    }\n notify(chart, hook, args, filter) {\n        if (hook === 'beforeInit') {\n            this._init = this._createDescriptors(chart, true);\n            this._notify(this._init, chart, 'install');\n        }\n        const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);\n        const result = this._notify(descriptors, chart, hook, args);\n        if (hook === 'afterDestroy') {\n            this._notify(descriptors, chart, 'stop');\n            this._notify(this._init, chart, 'uninstall');\n        }\n        return result;\n    }\n _notify(descriptors, chart, hook, args) {\n        args = args || {};\n        for (const descriptor of descriptors){\n            const plugin = descriptor.plugin;\n            const method = plugin[hook];\n            const params = [\n                chart,\n                args,\n                descriptor.options\n            ];\n            if (callback(method, params, plugin) === false && args.cancelable) {\n                return false;\n            }\n        }\n        return true;\n    }\n    invalidate() {\n        if (!isNullOrUndef(this._cache)) {\n            this._oldCache = this._cache;\n            this._cache = undefined;\n        }\n    }\n _descriptors(chart) {\n        if (this._cache) {\n            return this._cache;\n        }\n        const descriptors = this._cache = this._createDescriptors(chart);\n        this._notifyStateChanges(chart);\n        return descriptors;\n    }\n    _createDescriptors(chart, all) {\n        const config = chart && chart.config;\n        const options = valueOrDefault(config.options && config.options.plugins, {});\n        const plugins = allPlugins(config);\n        return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);\n    }\n _notifyStateChanges(chart) {\n        const previousDescriptors = this._oldCache || [];\n        const descriptors = this._cache;\n        const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.plugin.id === y.plugin.id));\n        this._notify(diff(previousDescriptors, descriptors), chart, 'stop');\n        this._notify(diff(descriptors, previousDescriptors), chart, 'start');\n    }\n}\n function allPlugins(config) {\n    const localIds = {};\n    const plugins = [];\n    const keys = Object.keys(registry.plugins.items);\n    for(let i = 0; i < keys.length; i++){\n        plugins.push(registry.getPlugin(keys[i]));\n    }\n    const local = config.plugins || [];\n    for(let i = 0; i < local.length; i++){\n        const plugin = local[i];\n        if (plugins.indexOf(plugin) === -1) {\n            plugins.push(plugin);\n            localIds[plugin.id] = true;\n        }\n    }\n    return {\n        plugins,\n        localIds\n    };\n}\nfunction getOpts(options, all) {\n    if (!all && options === false) {\n        return null;\n    }\n    if (options === true) {\n        return {};\n    }\n    return options;\n}\nfunction createDescriptors(chart, { plugins , localIds  }, options, all) {\n    const result = [];\n    const context = chart.getContext();\n    for (const plugin of plugins){\n        const id = plugin.id;\n        const opts = getOpts(options[id], all);\n        if (opts === null) {\n            continue;\n        }\n        result.push({\n            plugin,\n            options: pluginOpts(chart.config, {\n                plugin,\n                local: localIds[id]\n            }, opts, context)\n        });\n    }\n    return result;\n}\nfunction pluginOpts(config, { plugin , local  }, opts, context) {\n    const keys = config.pluginScopeKeys(plugin);\n    const scopes = config.getOptionScopes(opts, keys);\n    if (local && plugin.defaults) {\n        scopes.push(plugin.defaults);\n    }\n    return config.createResolver(scopes, context, [\n        ''\n    ], {\n        scriptable: false,\n        indexable: false,\n        allKeys: true\n    });\n}\n\nfunction getIndexAxis(type, options) {\n    const datasetDefaults = defaults.datasets[type] || {};\n    const datasetOptions = (options.datasets || {})[type] || {};\n    return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';\n}\nfunction getAxisFromDefaultScaleID(id, indexAxis) {\n    let axis = id;\n    if (id === '_index_') {\n        axis = indexAxis;\n    } else if (id === '_value_') {\n        axis = indexAxis === 'x' ? 'y' : 'x';\n    }\n    return axis;\n}\nfunction getDefaultScaleIDFromAxis(axis, indexAxis) {\n    return axis === indexAxis ? '_index_' : '_value_';\n}\nfunction idMatchesAxis(id) {\n    if (id === 'x' || id === 'y' || id === 'r') {\n        return id;\n    }\n}\nfunction axisFromPosition(position) {\n    if (position === 'top' || position === 'bottom') {\n        return 'x';\n    }\n    if (position === 'left' || position === 'right') {\n        return 'y';\n    }\n}\nfunction determineAxis(id, ...scaleOptions) {\n    if (idMatchesAxis(id)) {\n        return id;\n    }\n    for (const opts of scaleOptions){\n        const axis = opts.axis || axisFromPosition(opts.position) || id.length > 1 && idMatchesAxis(id[0].toLowerCase());\n        if (axis) {\n            return axis;\n        }\n    }\n    throw new Error(`Cannot determine type of '${id}' axis. Please provide 'axis' or 'position' option.`);\n}\nfunction getAxisFromDataset(id, axis, dataset) {\n    if (dataset[axis + 'AxisID'] === id) {\n        return {\n            axis\n        };\n    }\n}\nfunction retrieveAxisFromDatasets(id, config) {\n    if (config.data && config.data.datasets) {\n        const boundDs = config.data.datasets.filter((d)=>d.xAxisID === id || d.yAxisID === id);\n        if (boundDs.length) {\n            return getAxisFromDataset(id, 'x', boundDs[0]) || getAxisFromDataset(id, 'y', boundDs[0]);\n        }\n    }\n    return {};\n}\nfunction mergeScaleConfig(config, options) {\n    const chartDefaults = overrides[config.type] || {\n        scales: {}\n    };\n    const configScales = options.scales || {};\n    const chartIndexAxis = getIndexAxis(config.type, options);\n    const scales = Object.create(null);\n    Object.keys(configScales).forEach((id)=>{\n        const scaleConf = configScales[id];\n        if (!isObject(scaleConf)) {\n            return console.error(`Invalid scale configuration for scale: ${id}`);\n        }\n        if (scaleConf._proxy) {\n            return console.warn(`Ignoring resolver passed as options for scale: ${id}`);\n        }\n        const axis = determineAxis(id, scaleConf, retrieveAxisFromDatasets(id, config), defaults.scales[scaleConf.type]);\n        const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);\n        const defaultScaleOptions = chartDefaults.scales || {};\n        scales[id] = mergeIf(Object.create(null), [\n            {\n                axis\n            },\n            scaleConf,\n            defaultScaleOptions[axis],\n            defaultScaleOptions[defaultId]\n        ]);\n    });\n    config.data.datasets.forEach((dataset)=>{\n        const type = dataset.type || config.type;\n        const indexAxis = dataset.indexAxis || getIndexAxis(type, options);\n        const datasetDefaults = overrides[type] || {};\n        const defaultScaleOptions = datasetDefaults.scales || {};\n        Object.keys(defaultScaleOptions).forEach((defaultID)=>{\n            const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);\n            const id = dataset[axis + 'AxisID'] || axis;\n            scales[id] = scales[id] || Object.create(null);\n            mergeIf(scales[id], [\n                {\n                    axis\n                },\n                configScales[id],\n                defaultScaleOptions[defaultID]\n            ]);\n        });\n    });\n    Object.keys(scales).forEach((key)=>{\n        const scale = scales[key];\n        mergeIf(scale, [\n            defaults.scales[scale.type],\n            defaults.scale\n        ]);\n    });\n    return scales;\n}\nfunction initOptions(config) {\n    const options = config.options || (config.options = {});\n    options.plugins = valueOrDefault(options.plugins, {});\n    options.scales = mergeScaleConfig(config, options);\n}\nfunction initData(data) {\n    data = data || {};\n    data.datasets = data.datasets || [];\n    data.labels = data.labels || [];\n    return data;\n}\nfunction initConfig(config) {\n    config = config || {};\n    config.data = initData(config.data);\n    initOptions(config);\n    return config;\n}\nconst keyCache = new Map();\nconst keysCached = new Set();\nfunction cachedKeys(cacheKey, generate) {\n    let keys = keyCache.get(cacheKey);\n    if (!keys) {\n        keys = generate();\n        keyCache.set(cacheKey, keys);\n        keysCached.add(keys);\n    }\n    return keys;\n}\nconst addIfFound = (set, obj, key)=>{\n    const opts = resolveObjectKey(obj, key);\n    if (opts !== undefined) {\n        set.add(opts);\n    }\n};\nclass Config {\n    constructor(config){\n        this._config = initConfig(config);\n        this._scopeCache = new Map();\n        this._resolverCache = new Map();\n    }\n    get platform() {\n        return this._config.platform;\n    }\n    get type() {\n        return this._config.type;\n    }\n    set type(type) {\n        this._config.type = type;\n    }\n    get data() {\n        return this._config.data;\n    }\n    set data(data) {\n        this._config.data = initData(data);\n    }\n    get options() {\n        return this._config.options;\n    }\n    set options(options) {\n        this._config.options = options;\n    }\n    get plugins() {\n        return this._config.plugins;\n    }\n    update() {\n        const config = this._config;\n        this.clearCache();\n        initOptions(config);\n    }\n    clearCache() {\n        this._scopeCache.clear();\n        this._resolverCache.clear();\n    }\n datasetScopeKeys(datasetType) {\n        return cachedKeys(datasetType, ()=>[\n                [\n                    `datasets.${datasetType}`,\n                    ''\n                ]\n            ]);\n    }\n datasetAnimationScopeKeys(datasetType, transition) {\n        return cachedKeys(`${datasetType}.transition.${transition}`, ()=>[\n                [\n                    `datasets.${datasetType}.transitions.${transition}`,\n                    `transitions.${transition}`\n                ],\n                [\n                    `datasets.${datasetType}`,\n                    ''\n                ]\n            ]);\n    }\n datasetElementScopeKeys(datasetType, elementType) {\n        return cachedKeys(`${datasetType}-${elementType}`, ()=>[\n                [\n                    `datasets.${datasetType}.elements.${elementType}`,\n                    `datasets.${datasetType}`,\n                    `elements.${elementType}`,\n                    ''\n                ]\n            ]);\n    }\n pluginScopeKeys(plugin) {\n        const id = plugin.id;\n        const type = this.type;\n        return cachedKeys(`${type}-plugin-${id}`, ()=>[\n                [\n                    `plugins.${id}`,\n                    ...plugin.additionalOptionScopes || []\n                ]\n            ]);\n    }\n _cachedScopes(mainScope, resetCache) {\n        const _scopeCache = this._scopeCache;\n        let cache = _scopeCache.get(mainScope);\n        if (!cache || resetCache) {\n            cache = new Map();\n            _scopeCache.set(mainScope, cache);\n        }\n        return cache;\n    }\n getOptionScopes(mainScope, keyLists, resetCache) {\n        const { options , type  } = this;\n        const cache = this._cachedScopes(mainScope, resetCache);\n        const cached = cache.get(keyLists);\n        if (cached) {\n            return cached;\n        }\n        const scopes = new Set();\n        keyLists.forEach((keys)=>{\n            if (mainScope) {\n                scopes.add(mainScope);\n                keys.forEach((key)=>addIfFound(scopes, mainScope, key));\n            }\n            keys.forEach((key)=>addIfFound(scopes, options, key));\n            keys.forEach((key)=>addIfFound(scopes, overrides[type] || {}, key));\n            keys.forEach((key)=>addIfFound(scopes, defaults, key));\n            keys.forEach((key)=>addIfFound(scopes, descriptors, key));\n        });\n        const array = Array.from(scopes);\n        if (array.length === 0) {\n            array.push(Object.create(null));\n        }\n        if (keysCached.has(keyLists)) {\n            cache.set(keyLists, array);\n        }\n        return array;\n    }\n chartOptionScopes() {\n        const { options , type  } = this;\n        return [\n            options,\n            overrides[type] || {},\n            defaults.datasets[type] || {},\n            {\n                type\n            },\n            defaults,\n            descriptors\n        ];\n    }\n resolveNamedOptions(scopes, names, context, prefixes = [\n        ''\n    ]) {\n        const result = {\n            $shared: true\n        };\n        const { resolver , subPrefixes  } = getResolver(this._resolverCache, scopes, prefixes);\n        let options = resolver;\n        if (needContext(resolver, names)) {\n            result.$shared = false;\n            context = isFunction(context) ? context() : context;\n            const subResolver = this.createResolver(scopes, context, subPrefixes);\n            options = _attachContext(resolver, context, subResolver);\n        }\n        for (const prop of names){\n            result[prop] = options[prop];\n        }\n        return result;\n    }\n createResolver(scopes, context, prefixes = [\n        ''\n    ], descriptorDefaults) {\n        const { resolver  } = getResolver(this._resolverCache, scopes, prefixes);\n        return isObject(context) ? _attachContext(resolver, context, undefined, descriptorDefaults) : resolver;\n    }\n}\nfunction getResolver(resolverCache, scopes, prefixes) {\n    let cache = resolverCache.get(scopes);\n    if (!cache) {\n        cache = new Map();\n        resolverCache.set(scopes, cache);\n    }\n    const cacheKey = prefixes.join();\n    let cached = cache.get(cacheKey);\n    if (!cached) {\n        const resolver = _createResolver(scopes, prefixes);\n        cached = {\n            resolver,\n            subPrefixes: prefixes.filter((p)=>!p.toLowerCase().includes('hover'))\n        };\n        cache.set(cacheKey, cached);\n    }\n    return cached;\n}\nconst hasFunction = (value)=>isObject(value) && Object.getOwnPropertyNames(value).some((key)=>isFunction(value[key]));\nfunction needContext(proxy, names) {\n    const { isScriptable , isIndexable  } = _descriptors(proxy);\n    for (const prop of names){\n        const scriptable = isScriptable(prop);\n        const indexable = isIndexable(prop);\n        const value = (indexable || scriptable) && proxy[prop];\n        if (scriptable && (isFunction(value) || hasFunction(value)) || indexable && isArray(value)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nvar version = \"4.4.2\";\n\nconst KNOWN_POSITIONS = [\n    'top',\n    'bottom',\n    'left',\n    'right',\n    'chartArea'\n];\nfunction positionIsHorizontal(position, axis) {\n    return position === 'top' || position === 'bottom' || KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x';\n}\nfunction compare2Level(l1, l2) {\n    return function(a, b) {\n        return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1];\n    };\n}\nfunction onAnimationsComplete(context) {\n    const chart = context.chart;\n    const animationOptions = chart.options.animation;\n    chart.notifyPlugins('afterRender');\n    callback(animationOptions && animationOptions.onComplete, [\n        context\n    ], chart);\n}\nfunction onAnimationProgress(context) {\n    const chart = context.chart;\n    const animationOptions = chart.options.animation;\n    callback(animationOptions && animationOptions.onProgress, [\n        context\n    ], chart);\n}\n function getCanvas(item) {\n    if (_isDomSupported() && typeof item === 'string') {\n        item = document.getElementById(item);\n    } else if (item && item.length) {\n        item = item[0];\n    }\n    if (item && item.canvas) {\n        item = item.canvas;\n    }\n    return item;\n}\nconst instances = {};\nconst getChart = (key)=>{\n    const canvas = getCanvas(key);\n    return Object.values(instances).filter((c)=>c.canvas === canvas).pop();\n};\nfunction moveNumericKeys(obj, start, move) {\n    const keys = Object.keys(obj);\n    for (const key of keys){\n        const intKey = +key;\n        if (intKey >= start) {\n            const value = obj[key];\n            delete obj[key];\n            if (move > 0 || intKey > start) {\n                obj[intKey + move] = value;\n            }\n        }\n    }\n}\n function determineLastEvent(e, lastEvent, inChartArea, isClick) {\n    if (!inChartArea || e.type === 'mouseout') {\n        return null;\n    }\n    if (isClick) {\n        return lastEvent;\n    }\n    return e;\n}\nfunction getSizeForArea(scale, chartArea, field) {\n    return scale.options.clip ? scale[field] : chartArea[field];\n}\nfunction getDatasetArea(meta, chartArea) {\n    const { xScale , yScale  } = meta;\n    if (xScale && yScale) {\n        return {\n            left: getSizeForArea(xScale, chartArea, 'left'),\n            right: getSizeForArea(xScale, chartArea, 'right'),\n            top: getSizeForArea(yScale, chartArea, 'top'),\n            bottom: getSizeForArea(yScale, chartArea, 'bottom')\n        };\n    }\n    return chartArea;\n}\nclass Chart {\n    static defaults = defaults;\n    static instances = instances;\n    static overrides = overrides;\n    static registry = registry;\n    static version = version;\n    static getChart = getChart;\n    static register(...items) {\n        registry.add(...items);\n        invalidatePlugins();\n    }\n    static unregister(...items) {\n        registry.remove(...items);\n        invalidatePlugins();\n    }\n    constructor(item, userConfig){\n        const config = this.config = new Config(userConfig);\n        const initialCanvas = getCanvas(item);\n        const existingChart = getChart(initialCanvas);\n        if (existingChart) {\n            throw new Error('Canvas is already in use. Chart with ID \\'' + existingChart.id + '\\'' + ' must be destroyed before the canvas with ID \\'' + existingChart.canvas.id + '\\' can be reused.');\n        }\n        const options = config.createResolver(config.chartOptionScopes(), this.getContext());\n        this.platform = new (config.platform || _detectPlatform(initialCanvas))();\n        this.platform.updateConfig(config);\n        const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);\n        const canvas = context && context.canvas;\n        const height = canvas && canvas.height;\n        const width = canvas && canvas.width;\n        this.id = uid();\n        this.ctx = context;\n        this.canvas = canvas;\n        this.width = width;\n        this.height = height;\n        this._options = options;\n        this._aspectRatio = this.aspectRatio;\n        this._layers = [];\n        this._metasets = [];\n        this._stacks = undefined;\n        this.boxes = [];\n        this.currentDevicePixelRatio = undefined;\n        this.chartArea = undefined;\n        this._active = [];\n        this._lastEvent = undefined;\n        this._listeners = {};\n         this._responsiveListeners = undefined;\n        this._sortedMetasets = [];\n        this.scales = {};\n        this._plugins = new PluginService();\n        this.$proxies = {};\n        this._hiddenIndices = {};\n        this.attached = false;\n        this._animationsDisabled = undefined;\n        this.$context = undefined;\n        this._doResize = debounce((mode)=>this.update(mode), options.resizeDelay || 0);\n        this._dataChanges = [];\n        instances[this.id] = this;\n        if (!context || !canvas) {\n            console.error(\"Failed to create chart: can't acquire context from the given item\");\n            return;\n        }\n        animator.listen(this, 'complete', onAnimationsComplete);\n        animator.listen(this, 'progress', onAnimationProgress);\n        this._initialize();\n        if (this.attached) {\n            this.update();\n        }\n    }\n    get aspectRatio() {\n        const { options: { aspectRatio , maintainAspectRatio  } , width , height , _aspectRatio  } = this;\n        if (!isNullOrUndef(aspectRatio)) {\n            return aspectRatio;\n        }\n        if (maintainAspectRatio && _aspectRatio) {\n            return _aspectRatio;\n        }\n        return height ? width / height : null;\n    }\n    get data() {\n        return this.config.data;\n    }\n    set data(data) {\n        this.config.data = data;\n    }\n    get options() {\n        return this._options;\n    }\n    set options(options) {\n        this.config.options = options;\n    }\n    get registry() {\n        return registry;\n    }\n _initialize() {\n        this.notifyPlugins('beforeInit');\n        if (this.options.responsive) {\n            this.resize();\n        } else {\n            retinaScale(this, this.options.devicePixelRatio);\n        }\n        this.bindEvents();\n        this.notifyPlugins('afterInit');\n        return this;\n    }\n    clear() {\n        clearCanvas(this.canvas, this.ctx);\n        return this;\n    }\n    stop() {\n        animator.stop(this);\n        return this;\n    }\n resize(width, height) {\n        if (!animator.running(this)) {\n            this._resize(width, height);\n        } else {\n            this._resizeBeforeDraw = {\n                width,\n                height\n            };\n        }\n    }\n    _resize(width, height) {\n        const options = this.options;\n        const canvas = this.canvas;\n        const aspectRatio = options.maintainAspectRatio && this.aspectRatio;\n        const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);\n        const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();\n        const mode = this.width ? 'resize' : 'attach';\n        this.width = newSize.width;\n        this.height = newSize.height;\n        this._aspectRatio = this.aspectRatio;\n        if (!retinaScale(this, newRatio, true)) {\n            return;\n        }\n        this.notifyPlugins('resize', {\n            size: newSize\n        });\n        callback(options.onResize, [\n            this,\n            newSize\n        ], this);\n        if (this.attached) {\n            if (this._doResize(mode)) {\n                this.render();\n            }\n        }\n    }\n    ensureScalesHaveIDs() {\n        const options = this.options;\n        const scalesOptions = options.scales || {};\n        each(scalesOptions, (axisOptions, axisID)=>{\n            axisOptions.id = axisID;\n        });\n    }\n buildOrUpdateScales() {\n        const options = this.options;\n        const scaleOpts = options.scales;\n        const scales = this.scales;\n        const updated = Object.keys(scales).reduce((obj, id)=>{\n            obj[id] = false;\n            return obj;\n        }, {});\n        let items = [];\n        if (scaleOpts) {\n            items = items.concat(Object.keys(scaleOpts).map((id)=>{\n                const scaleOptions = scaleOpts[id];\n                const axis = determineAxis(id, scaleOptions);\n                const isRadial = axis === 'r';\n                const isHorizontal = axis === 'x';\n                return {\n                    options: scaleOptions,\n                    dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left',\n                    dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear'\n                };\n            }));\n        }\n        each(items, (item)=>{\n            const scaleOptions = item.options;\n            const id = scaleOptions.id;\n            const axis = determineAxis(id, scaleOptions);\n            const scaleType = valueOrDefault(scaleOptions.type, item.dtype);\n            if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {\n                scaleOptions.position = item.dposition;\n            }\n            updated[id] = true;\n            let scale = null;\n            if (id in scales && scales[id].type === scaleType) {\n                scale = scales[id];\n            } else {\n                const scaleClass = registry.getScale(scaleType);\n                scale = new scaleClass({\n                    id,\n                    type: scaleType,\n                    ctx: this.ctx,\n                    chart: this\n                });\n                scales[scale.id] = scale;\n            }\n            scale.init(scaleOptions, options);\n        });\n        each(updated, (hasUpdated, id)=>{\n            if (!hasUpdated) {\n                delete scales[id];\n            }\n        });\n        each(scales, (scale)=>{\n            layouts.configure(this, scale, scale.options);\n            layouts.addBox(this, scale);\n        });\n    }\n _updateMetasets() {\n        const metasets = this._metasets;\n        const numData = this.data.datasets.length;\n        const numMeta = metasets.length;\n        metasets.sort((a, b)=>a.index - b.index);\n        if (numMeta > numData) {\n            for(let i = numData; i < numMeta; ++i){\n                this._destroyDatasetMeta(i);\n            }\n            metasets.splice(numData, numMeta - numData);\n        }\n        this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));\n    }\n _removeUnreferencedMetasets() {\n        const { _metasets: metasets , data: { datasets  }  } = this;\n        if (metasets.length > datasets.length) {\n            delete this._stacks;\n        }\n        metasets.forEach((meta, index)=>{\n            if (datasets.filter((x)=>x === meta._dataset).length === 0) {\n                this._destroyDatasetMeta(index);\n            }\n        });\n    }\n    buildOrUpdateControllers() {\n        const newControllers = [];\n        const datasets = this.data.datasets;\n        let i, ilen;\n        this._removeUnreferencedMetasets();\n        for(i = 0, ilen = datasets.length; i < ilen; i++){\n            const dataset = datasets[i];\n            let meta = this.getDatasetMeta(i);\n            const type = dataset.type || this.config.type;\n            if (meta.type && meta.type !== type) {\n                this._destroyDatasetMeta(i);\n                meta = this.getDatasetMeta(i);\n            }\n            meta.type = type;\n            meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);\n            meta.order = dataset.order || 0;\n            meta.index = i;\n            meta.label = '' + dataset.label;\n            meta.visible = this.isDatasetVisible(i);\n            if (meta.controller) {\n                meta.controller.updateIndex(i);\n                meta.controller.linkScales();\n            } else {\n                const ControllerClass = registry.getController(type);\n                const { datasetElementType , dataElementType  } = defaults.datasets[type];\n                Object.assign(ControllerClass, {\n                    dataElementType: registry.getElement(dataElementType),\n                    datasetElementType: datasetElementType && registry.getElement(datasetElementType)\n                });\n                meta.controller = new ControllerClass(this, i);\n                newControllers.push(meta.controller);\n            }\n        }\n        this._updateMetasets();\n        return newControllers;\n    }\n _resetElements() {\n        each(this.data.datasets, (dataset, datasetIndex)=>{\n            this.getDatasetMeta(datasetIndex).controller.reset();\n        }, this);\n    }\n reset() {\n        this._resetElements();\n        this.notifyPlugins('reset');\n    }\n    update(mode) {\n        const config = this.config;\n        config.update();\n        const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());\n        const animsDisabled = this._animationsDisabled = !options.animation;\n        this._updateScales();\n        this._checkEventBindings();\n        this._updateHiddenIndices();\n        this._plugins.invalidate();\n        if (this.notifyPlugins('beforeUpdate', {\n            mode,\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        const newControllers = this.buildOrUpdateControllers();\n        this.notifyPlugins('beforeElementsUpdate');\n        let minPadding = 0;\n        for(let i = 0, ilen = this.data.datasets.length; i < ilen; i++){\n            const { controller  } = this.getDatasetMeta(i);\n            const reset = !animsDisabled && newControllers.indexOf(controller) === -1;\n            controller.buildOrUpdateElements(reset);\n            minPadding = Math.max(+controller.getMaxOverflow(), minPadding);\n        }\n        minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;\n        this._updateLayout(minPadding);\n        if (!animsDisabled) {\n            each(newControllers, (controller)=>{\n                controller.reset();\n            });\n        }\n        this._updateDatasets(mode);\n        this.notifyPlugins('afterUpdate', {\n            mode\n        });\n        this._layers.sort(compare2Level('z', '_idx'));\n        const { _active , _lastEvent  } = this;\n        if (_lastEvent) {\n            this._eventHandler(_lastEvent, true);\n        } else if (_active.length) {\n            this._updateHoverStyles(_active, _active, true);\n        }\n        this.render();\n    }\n _updateScales() {\n        each(this.scales, (scale)=>{\n            layouts.removeBox(this, scale);\n        });\n        this.ensureScalesHaveIDs();\n        this.buildOrUpdateScales();\n    }\n _checkEventBindings() {\n        const options = this.options;\n        const existingEvents = new Set(Object.keys(this._listeners));\n        const newEvents = new Set(options.events);\n        if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {\n            this.unbindEvents();\n            this.bindEvents();\n        }\n    }\n _updateHiddenIndices() {\n        const { _hiddenIndices  } = this;\n        const changes = this._getUniformDataChanges() || [];\n        for (const { method , start , count  } of changes){\n            const move = method === '_removeElements' ? -count : count;\n            moveNumericKeys(_hiddenIndices, start, move);\n        }\n    }\n _getUniformDataChanges() {\n        const _dataChanges = this._dataChanges;\n        if (!_dataChanges || !_dataChanges.length) {\n            return;\n        }\n        this._dataChanges = [];\n        const datasetCount = this.data.datasets.length;\n        const makeSet = (idx)=>new Set(_dataChanges.filter((c)=>c[0] === idx).map((c, i)=>i + ',' + c.splice(1).join(',')));\n        const changeSet = makeSet(0);\n        for(let i = 1; i < datasetCount; i++){\n            if (!setsEqual(changeSet, makeSet(i))) {\n                return;\n            }\n        }\n        return Array.from(changeSet).map((c)=>c.split(',')).map((a)=>({\n                method: a[1],\n                start: +a[2],\n                count: +a[3]\n            }));\n    }\n _updateLayout(minPadding) {\n        if (this.notifyPlugins('beforeLayout', {\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        layouts.update(this, this.width, this.height, minPadding);\n        const area = this.chartArea;\n        const noArea = area.width <= 0 || area.height <= 0;\n        this._layers = [];\n        each(this.boxes, (box)=>{\n            if (noArea && box.position === 'chartArea') {\n                return;\n            }\n            if (box.configure) {\n                box.configure();\n            }\n            this._layers.push(...box._layers());\n        }, this);\n        this._layers.forEach((item, index)=>{\n            item._idx = index;\n        });\n        this.notifyPlugins('afterLayout');\n    }\n _updateDatasets(mode) {\n        if (this.notifyPlugins('beforeDatasetsUpdate', {\n            mode,\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n            this.getDatasetMeta(i).controller.configure();\n        }\n        for(let i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n            this._updateDataset(i, isFunction(mode) ? mode({\n                datasetIndex: i\n            }) : mode);\n        }\n        this.notifyPlugins('afterDatasetsUpdate', {\n            mode\n        });\n    }\n _updateDataset(index, mode) {\n        const meta = this.getDatasetMeta(index);\n        const args = {\n            meta,\n            index,\n            mode,\n            cancelable: true\n        };\n        if (this.notifyPlugins('beforeDatasetUpdate', args) === false) {\n            return;\n        }\n        meta.controller._update(mode);\n        args.cancelable = false;\n        this.notifyPlugins('afterDatasetUpdate', args);\n    }\n    render() {\n        if (this.notifyPlugins('beforeRender', {\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        if (animator.has(this)) {\n            if (this.attached && !animator.running(this)) {\n                animator.start(this);\n            }\n        } else {\n            this.draw();\n            onAnimationsComplete({\n                chart: this\n            });\n        }\n    }\n    draw() {\n        let i;\n        if (this._resizeBeforeDraw) {\n            const { width , height  } = this._resizeBeforeDraw;\n            this._resize(width, height);\n            this._resizeBeforeDraw = null;\n        }\n        this.clear();\n        if (this.width <= 0 || this.height <= 0) {\n            return;\n        }\n        if (this.notifyPlugins('beforeDraw', {\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        const layers = this._layers;\n        for(i = 0; i < layers.length && layers[i].z <= 0; ++i){\n            layers[i].draw(this.chartArea);\n        }\n        this._drawDatasets();\n        for(; i < layers.length; ++i){\n            layers[i].draw(this.chartArea);\n        }\n        this.notifyPlugins('afterDraw');\n    }\n _getSortedDatasetMetas(filterVisible) {\n        const metasets = this._sortedMetasets;\n        const result = [];\n        let i, ilen;\n        for(i = 0, ilen = metasets.length; i < ilen; ++i){\n            const meta = metasets[i];\n            if (!filterVisible || meta.visible) {\n                result.push(meta);\n            }\n        }\n        return result;\n    }\n getSortedVisibleDatasetMetas() {\n        return this._getSortedDatasetMetas(true);\n    }\n _drawDatasets() {\n        if (this.notifyPlugins('beforeDatasetsDraw', {\n            cancelable: true\n        }) === false) {\n            return;\n        }\n        const metasets = this.getSortedVisibleDatasetMetas();\n        for(let i = metasets.length - 1; i >= 0; --i){\n            this._drawDataset(metasets[i]);\n        }\n        this.notifyPlugins('afterDatasetsDraw');\n    }\n _drawDataset(meta) {\n        const ctx = this.ctx;\n        const clip = meta._clip;\n        const useClip = !clip.disabled;\n        const area = getDatasetArea(meta, this.chartArea);\n        const args = {\n            meta,\n            index: meta.index,\n            cancelable: true\n        };\n        if (this.notifyPlugins('beforeDatasetDraw', args) === false) {\n            return;\n        }\n        if (useClip) {\n            clipArea(ctx, {\n                left: clip.left === false ? 0 : area.left - clip.left,\n                right: clip.right === false ? this.width : area.right + clip.right,\n                top: clip.top === false ? 0 : area.top - clip.top,\n                bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom\n            });\n        }\n        meta.controller.draw();\n        if (useClip) {\n            unclipArea(ctx);\n        }\n        args.cancelable = false;\n        this.notifyPlugins('afterDatasetDraw', args);\n    }\n isPointInArea(point) {\n        return _isPointInArea(point, this.chartArea, this._minPadding);\n    }\n    getElementsAtEventForMode(e, mode, options, useFinalPosition) {\n        const method = Interaction.modes[mode];\n        if (typeof method === 'function') {\n            return method(this, e, options, useFinalPosition);\n        }\n        return [];\n    }\n    getDatasetMeta(datasetIndex) {\n        const dataset = this.data.datasets[datasetIndex];\n        const metasets = this._metasets;\n        let meta = metasets.filter((x)=>x && x._dataset === dataset).pop();\n        if (!meta) {\n            meta = {\n                type: null,\n                data: [],\n                dataset: null,\n                controller: null,\n                hidden: null,\n                xAxisID: null,\n                yAxisID: null,\n                order: dataset && dataset.order || 0,\n                index: datasetIndex,\n                _dataset: dataset,\n                _parsed: [],\n                _sorted: false\n            };\n            metasets.push(meta);\n        }\n        return meta;\n    }\n    getContext() {\n        return this.$context || (this.$context = createContext(null, {\n            chart: this,\n            type: 'chart'\n        }));\n    }\n    getVisibleDatasetCount() {\n        return this.getSortedVisibleDatasetMetas().length;\n    }\n    isDatasetVisible(datasetIndex) {\n        const dataset = this.data.datasets[datasetIndex];\n        if (!dataset) {\n            return false;\n        }\n        const meta = this.getDatasetMeta(datasetIndex);\n        return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden;\n    }\n    setDatasetVisibility(datasetIndex, visible) {\n        const meta = this.getDatasetMeta(datasetIndex);\n        meta.hidden = !visible;\n    }\n    toggleDataVisibility(index) {\n        this._hiddenIndices[index] = !this._hiddenIndices[index];\n    }\n    getDataVisibility(index) {\n        return !this._hiddenIndices[index];\n    }\n _updateVisibility(datasetIndex, dataIndex, visible) {\n        const mode = visible ? 'show' : 'hide';\n        const meta = this.getDatasetMeta(datasetIndex);\n        const anims = meta.controller._resolveAnimations(undefined, mode);\n        if (defined(dataIndex)) {\n            meta.data[dataIndex].hidden = !visible;\n            this.update();\n        } else {\n            this.setDatasetVisibility(datasetIndex, visible);\n            anims.update(meta, {\n                visible\n            });\n            this.update((ctx)=>ctx.datasetIndex === datasetIndex ? mode : undefined);\n        }\n    }\n    hide(datasetIndex, dataIndex) {\n        this._updateVisibility(datasetIndex, dataIndex, false);\n    }\n    show(datasetIndex, dataIndex) {\n        this._updateVisibility(datasetIndex, dataIndex, true);\n    }\n _destroyDatasetMeta(datasetIndex) {\n        const meta = this._metasets[datasetIndex];\n        if (meta && meta.controller) {\n            meta.controller._destroy();\n        }\n        delete this._metasets[datasetIndex];\n    }\n    _stop() {\n        let i, ilen;\n        this.stop();\n        animator.remove(this);\n        for(i = 0, ilen = this.data.datasets.length; i < ilen; ++i){\n            this._destroyDatasetMeta(i);\n        }\n    }\n    destroy() {\n        this.notifyPlugins('beforeDestroy');\n        const { canvas , ctx  } = this;\n        this._stop();\n        this.config.clearCache();\n        if (canvas) {\n            this.unbindEvents();\n            clearCanvas(canvas, ctx);\n            this.platform.releaseContext(ctx);\n            this.canvas = null;\n            this.ctx = null;\n        }\n        delete instances[this.id];\n        this.notifyPlugins('afterDestroy');\n    }\n    toBase64Image(...args) {\n        return this.canvas.toDataURL(...args);\n    }\n bindEvents() {\n        this.bindUserEvents();\n        if (this.options.responsive) {\n            this.bindResponsiveEvents();\n        } else {\n            this.attached = true;\n        }\n    }\n bindUserEvents() {\n        const listeners = this._listeners;\n        const platform = this.platform;\n        const _add = (type, listener)=>{\n            platform.addEventListener(this, type, listener);\n            listeners[type] = listener;\n        };\n        const listener = (e, x, y)=>{\n            e.offsetX = x;\n            e.offsetY = y;\n            this._eventHandler(e);\n        };\n        each(this.options.events, (type)=>_add(type, listener));\n    }\n bindResponsiveEvents() {\n        if (!this._responsiveListeners) {\n            this._responsiveListeners = {};\n        }\n        const listeners = this._responsiveListeners;\n        const platform = this.platform;\n        const _add = (type, listener)=>{\n            platform.addEventListener(this, type, listener);\n            listeners[type] = listener;\n        };\n        const _remove = (type, listener)=>{\n            if (listeners[type]) {\n                platform.removeEventListener(this, type, listener);\n                delete listeners[type];\n            }\n        };\n        const listener = (width, height)=>{\n            if (this.canvas) {\n                this.resize(width, height);\n            }\n        };\n        let detached;\n        const attached = ()=>{\n            _remove('attach', attached);\n            this.attached = true;\n            this.resize();\n            _add('resize', listener);\n            _add('detach', detached);\n        };\n        detached = ()=>{\n            this.attached = false;\n            _remove('resize', listener);\n            this._stop();\n            this._resize(0, 0);\n            _add('attach', attached);\n        };\n        if (platform.isAttached(this.canvas)) {\n            attached();\n        } else {\n            detached();\n        }\n    }\n unbindEvents() {\n        each(this._listeners, (listener, type)=>{\n            this.platform.removeEventListener(this, type, listener);\n        });\n        this._listeners = {};\n        each(this._responsiveListeners, (listener, type)=>{\n            this.platform.removeEventListener(this, type, listener);\n        });\n        this._responsiveListeners = undefined;\n    }\n    updateHoverStyle(items, mode, enabled) {\n        const prefix = enabled ? 'set' : 'remove';\n        let meta, item, i, ilen;\n        if (mode === 'dataset') {\n            meta = this.getDatasetMeta(items[0].datasetIndex);\n            meta.controller['_' + prefix + 'DatasetHoverStyle']();\n        }\n        for(i = 0, ilen = items.length; i < ilen; ++i){\n            item = items[i];\n            const controller = item && this.getDatasetMeta(item.datasetIndex).controller;\n            if (controller) {\n                controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index);\n            }\n        }\n    }\n getActiveElements() {\n        return this._active || [];\n    }\n setActiveElements(activeElements) {\n        const lastActive = this._active || [];\n        const active = activeElements.map(({ datasetIndex , index  })=>{\n            const meta = this.getDatasetMeta(datasetIndex);\n            if (!meta) {\n                throw new Error('No dataset found at index ' + datasetIndex);\n            }\n            return {\n                datasetIndex,\n                element: meta.data[index],\n                index\n            };\n        });\n        const changed = !_elementsEqual(active, lastActive);\n        if (changed) {\n            this._active = active;\n            this._lastEvent = null;\n            this._updateHoverStyles(active, lastActive);\n        }\n    }\n notifyPlugins(hook, args, filter) {\n        return this._plugins.notify(this, hook, args, filter);\n    }\n isPluginEnabled(pluginId) {\n        return this._plugins._cache.filter((p)=>p.plugin.id === pluginId).length === 1;\n    }\n _updateHoverStyles(active, lastActive, replay) {\n        const hoverOptions = this.options.hover;\n        const diff = (a, b)=>a.filter((x)=>!b.some((y)=>x.datasetIndex === y.datasetIndex && x.index === y.index));\n        const deactivated = diff(lastActive, active);\n        const activated = replay ? active : diff(active, lastActive);\n        if (deactivated.length) {\n            this.updateHoverStyle(deactivated, hoverOptions.mode, false);\n        }\n        if (activated.length && hoverOptions.mode) {\n            this.updateHoverStyle(activated, hoverOptions.mode, true);\n        }\n    }\n _eventHandler(e, replay) {\n        const args = {\n            event: e,\n            replay,\n            cancelable: true,\n            inChartArea: this.isPointInArea(e)\n        };\n        const eventFilter = (plugin)=>(plugin.options.events || this.options.events).includes(e.native.type);\n        if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) {\n            return;\n        }\n        const changed = this._handleEvent(e, replay, args.inChartArea);\n        args.cancelable = false;\n        this.notifyPlugins('afterEvent', args, eventFilter);\n        if (changed || args.changed) {\n            this.render();\n        }\n        return this;\n    }\n _handleEvent(e, replay, inChartArea) {\n        const { _active: lastActive = [] , options  } = this;\n        const useFinalPosition = replay;\n        const active = this._getActiveElements(e, lastActive, inChartArea, useFinalPosition);\n        const isClick = _isClickEvent(e);\n        const lastEvent = determineLastEvent(e, this._lastEvent, inChartArea, isClick);\n        if (inChartArea) {\n            this._lastEvent = null;\n            callback(options.onHover, [\n                e,\n                active,\n                this\n            ], this);\n            if (isClick) {\n                callback(options.onClick, [\n                    e,\n                    active,\n                    this\n                ], this);\n            }\n        }\n        const changed = !_elementsEqual(active, lastActive);\n        if (changed || replay) {\n            this._active = active;\n            this._updateHoverStyles(active, lastActive, replay);\n        }\n        this._lastEvent = lastEvent;\n        return changed;\n    }\n _getActiveElements(e, lastActive, inChartArea, useFinalPosition) {\n        if (e.type === 'mouseout') {\n            return [];\n        }\n        if (!inChartArea) {\n            return lastActive;\n        }\n        const hoverOptions = this.options.hover;\n        return this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);\n    }\n}\nfunction invalidatePlugins() {\n    return each(Chart.instances, (chart)=>chart._plugins.invalidate());\n}\n\nfunction clipArc(ctx, element, endAngle) {\n    const { startAngle , pixelMargin , x , y , outerRadius , innerRadius  } = element;\n    let angleMargin = pixelMargin / outerRadius;\n    // Draw an inner border by clipping the arc and drawing a double-width border\n    // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders\n    ctx.beginPath();\n    ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);\n    if (innerRadius > pixelMargin) {\n        angleMargin = pixelMargin / innerRadius;\n        ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);\n    } else {\n        ctx.arc(x, y, pixelMargin, endAngle + HALF_PI, startAngle - HALF_PI);\n    }\n    ctx.closePath();\n    ctx.clip();\n}\nfunction toRadiusCorners(value) {\n    return _readValueToProps(value, [\n        'outerStart',\n        'outerEnd',\n        'innerStart',\n        'innerEnd'\n    ]);\n}\n/**\n * Parse border radius from the provided options\n */ function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) {\n    const o = toRadiusCorners(arc.options.borderRadius);\n    const halfThickness = (outerRadius - innerRadius) / 2;\n    const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2);\n    // Outer limits are complicated. We want to compute the available angular distance at\n    // a radius of outerRadius - borderRadius because for small angular distances, this term limits.\n    // We compute at r = outerRadius - borderRadius because this circle defines the center of the border corners.\n    //\n    // If the borderRadius is large, that value can become negative.\n    // This causes the outer borders to lose their radius entirely, which is rather unexpected. To solve that, if borderRadius > outerRadius\n    // we know that the thickness term will dominate and compute the limits at that point\n    const computeOuterLimit = (val)=>{\n        const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2;\n        return _limitValue(val, 0, Math.min(halfThickness, outerArcLimit));\n    };\n    return {\n        outerStart: computeOuterLimit(o.outerStart),\n        outerEnd: computeOuterLimit(o.outerEnd),\n        innerStart: _limitValue(o.innerStart, 0, innerLimit),\n        innerEnd: _limitValue(o.innerEnd, 0, innerLimit)\n    };\n}\n/**\n * Convert (r, 𝜃) to (x, y)\n */ function rThetaToXY(r, theta, x, y) {\n    return {\n        x: x + r * Math.cos(theta),\n        y: y + r * Math.sin(theta)\n    };\n}\n/**\n * Path the arc, respecting border radius by separating into left and right halves.\n *\n *   Start      End\n *\n *    1--->a--->2    Outer\n *   /           \\\n *   8           3\n *   |           |\n *   |           |\n *   7           4\n *   \\           /\n *    6<---b<---5    Inner\n */ function pathArc(ctx, element, offset, spacing, end, circular) {\n    const { x , y , startAngle: start , pixelMargin , innerRadius: innerR  } = element;\n    const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0);\n    const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0;\n    let spacingOffset = 0;\n    const alpha = end - start;\n    if (spacing) {\n        // When spacing is present, it is the same for all items\n        // So we adjust the start and end angle of the arc such that\n        // the distance is the same as it would be without the spacing\n        const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;\n        const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;\n        const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;\n        const adjustedAngle = avNogSpacingRadius !== 0 ? alpha * avNogSpacingRadius / (avNogSpacingRadius + spacing) : alpha;\n        spacingOffset = (alpha - adjustedAngle) / 2;\n    }\n    const beta = Math.max(0.001, alpha * outerRadius - offset / PI) / outerRadius;\n    const angleOffset = (alpha - beta) / 2;\n    const startAngle = start + angleOffset + spacingOffset;\n    const endAngle = end - angleOffset - spacingOffset;\n    const { outerStart , outerEnd , innerStart , innerEnd  } = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle);\n    const outerStartAdjustedRadius = outerRadius - outerStart;\n    const outerEndAdjustedRadius = outerRadius - outerEnd;\n    const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius;\n    const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius;\n    const innerStartAdjustedRadius = innerRadius + innerStart;\n    const innerEndAdjustedRadius = innerRadius + innerEnd;\n    const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius;\n    const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius;\n    ctx.beginPath();\n    if (circular) {\n        // The first arc segments from point 1 to point a to point 2\n        const outerMidAdjustedAngle = (outerStartAdjustedAngle + outerEndAdjustedAngle) / 2;\n        ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerMidAdjustedAngle);\n        ctx.arc(x, y, outerRadius, outerMidAdjustedAngle, outerEndAdjustedAngle);\n        // The corner segment from point 2 to point 3\n        if (outerEnd > 0) {\n            const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y);\n            ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + HALF_PI);\n        }\n        // The line from point 3 to point 4\n        const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y);\n        ctx.lineTo(p4.x, p4.y);\n        // The corner segment from point 4 to point 5\n        if (innerEnd > 0) {\n            const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y);\n            ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + HALF_PI, innerEndAdjustedAngle + Math.PI);\n        }\n        // The inner arc from point 5 to point b to point 6\n        const innerMidAdjustedAngle = (endAngle - innerEnd / innerRadius + (startAngle + innerStart / innerRadius)) / 2;\n        ctx.arc(x, y, innerRadius, endAngle - innerEnd / innerRadius, innerMidAdjustedAngle, true);\n        ctx.arc(x, y, innerRadius, innerMidAdjustedAngle, startAngle + innerStart / innerRadius, true);\n        // The corner segment from point 6 to point 7\n        if (innerStart > 0) {\n            const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y);\n            ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - HALF_PI);\n        }\n        // The line from point 7 to point 8\n        const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y);\n        ctx.lineTo(p8.x, p8.y);\n        // The corner segment from point 8 to point 1\n        if (outerStart > 0) {\n            const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y);\n            ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - HALF_PI, outerStartAdjustedAngle);\n        }\n    } else {\n        ctx.moveTo(x, y);\n        const outerStartX = Math.cos(outerStartAdjustedAngle) * outerRadius + x;\n        const outerStartY = Math.sin(outerStartAdjustedAngle) * outerRadius + y;\n        ctx.lineTo(outerStartX, outerStartY);\n        const outerEndX = Math.cos(outerEndAdjustedAngle) * outerRadius + x;\n        const outerEndY = Math.sin(outerEndAdjustedAngle) * outerRadius + y;\n        ctx.lineTo(outerEndX, outerEndY);\n    }\n    ctx.closePath();\n}\nfunction drawArc(ctx, element, offset, spacing, circular) {\n    const { fullCircles , startAngle , circumference  } = element;\n    let endAngle = element.endAngle;\n    if (fullCircles) {\n        pathArc(ctx, element, offset, spacing, endAngle, circular);\n        for(let i = 0; i < fullCircles; ++i){\n            ctx.fill();\n        }\n        if (!isNaN(circumference)) {\n            endAngle = startAngle + (circumference % TAU || TAU);\n        }\n    }\n    pathArc(ctx, element, offset, spacing, endAngle, circular);\n    ctx.fill();\n    return endAngle;\n}\nfunction drawBorder(ctx, element, offset, spacing, circular) {\n    const { fullCircles , startAngle , circumference , options  } = element;\n    const { borderWidth , borderJoinStyle , borderDash , borderDashOffset  } = options;\n    const inner = options.borderAlign === 'inner';\n    if (!borderWidth) {\n        return;\n    }\n    ctx.setLineDash(borderDash || []);\n    ctx.lineDashOffset = borderDashOffset;\n    if (inner) {\n        ctx.lineWidth = borderWidth * 2;\n        ctx.lineJoin = borderJoinStyle || 'round';\n    } else {\n        ctx.lineWidth = borderWidth;\n        ctx.lineJoin = borderJoinStyle || 'bevel';\n    }\n    let endAngle = element.endAngle;\n    if (fullCircles) {\n        pathArc(ctx, element, offset, spacing, endAngle, circular);\n        for(let i = 0; i < fullCircles; ++i){\n            ctx.stroke();\n        }\n        if (!isNaN(circumference)) {\n            endAngle = startAngle + (circumference % TAU || TAU);\n        }\n    }\n    if (inner) {\n        clipArc(ctx, element, endAngle);\n    }\n    if (!fullCircles) {\n        pathArc(ctx, element, offset, spacing, endAngle, circular);\n        ctx.stroke();\n    }\n}\nclass ArcElement extends Element {\n    static id = 'arc';\n    static defaults = {\n        borderAlign: 'center',\n        borderColor: '#fff',\n        borderDash: [],\n        borderDashOffset: 0,\n        borderJoinStyle: undefined,\n        borderRadius: 0,\n        borderWidth: 2,\n        offset: 0,\n        spacing: 0,\n        angle: undefined,\n        circular: true\n    };\n    static defaultRoutes = {\n        backgroundColor: 'backgroundColor'\n    };\n    static descriptors = {\n        _scriptable: true,\n        _indexable: (name)=>name !== 'borderDash'\n    };\n    circumference;\n    endAngle;\n    fullCircles;\n    innerRadius;\n    outerRadius;\n    pixelMargin;\n    startAngle;\n    constructor(cfg){\n        super();\n        this.options = undefined;\n        this.circumference = undefined;\n        this.startAngle = undefined;\n        this.endAngle = undefined;\n        this.innerRadius = undefined;\n        this.outerRadius = undefined;\n        this.pixelMargin = 0;\n        this.fullCircles = 0;\n        if (cfg) {\n            Object.assign(this, cfg);\n        }\n    }\n    inRange(chartX, chartY, useFinalPosition) {\n        const point = this.getProps([\n            'x',\n            'y'\n        ], useFinalPosition);\n        const { angle , distance  } = getAngleFromPoint(point, {\n            x: chartX,\n            y: chartY\n        });\n        const { startAngle , endAngle , innerRadius , outerRadius , circumference  } = this.getProps([\n            'startAngle',\n            'endAngle',\n            'innerRadius',\n            'outerRadius',\n            'circumference'\n        ], useFinalPosition);\n        const rAdjust = (this.options.spacing + this.options.borderWidth) / 2;\n        const _circumference = valueOrDefault(circumference, endAngle - startAngle);\n        const betweenAngles = _circumference >= TAU || _angleBetween(angle, startAngle, endAngle);\n        const withinRadius = _isBetween(distance, innerRadius + rAdjust, outerRadius + rAdjust);\n        return betweenAngles && withinRadius;\n    }\n    getCenterPoint(useFinalPosition) {\n        const { x , y , startAngle , endAngle , innerRadius , outerRadius  } = this.getProps([\n            'x',\n            'y',\n            'startAngle',\n            'endAngle',\n            'innerRadius',\n            'outerRadius'\n        ], useFinalPosition);\n        const { offset , spacing  } = this.options;\n        const halfAngle = (startAngle + endAngle) / 2;\n        const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2;\n        return {\n            x: x + Math.cos(halfAngle) * halfRadius,\n            y: y + Math.sin(halfAngle) * halfRadius\n        };\n    }\n    tooltipPosition(useFinalPosition) {\n        return this.getCenterPoint(useFinalPosition);\n    }\n    draw(ctx) {\n        const { options , circumference  } = this;\n        const offset = (options.offset || 0) / 4;\n        const spacing = (options.spacing || 0) / 2;\n        const circular = options.circular;\n        this.pixelMargin = options.borderAlign === 'inner' ? 0.33 : 0;\n        this.fullCircles = circumference > TAU ? Math.floor(circumference / TAU) : 0;\n        if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {\n            return;\n        }\n        ctx.save();\n        const halfAngle = (this.startAngle + this.endAngle) / 2;\n        ctx.translate(Math.cos(halfAngle) * offset, Math.sin(halfAngle) * offset);\n        const fix = 1 - Math.sin(Math.min(PI, circumference || 0));\n        const radiusOffset = offset * fix;\n        ctx.fillStyle = options.backgroundColor;\n        ctx.strokeStyle = options.borderColor;\n        drawArc(ctx, this, radiusOffset, spacing, circular);\n        drawBorder(ctx, this, radiusOffset, spacing, circular);\n        ctx.restore();\n    }\n}\n\nfunction setStyle(ctx, options, style = options) {\n    ctx.lineCap = valueOrDefault(style.borderCapStyle, options.borderCapStyle);\n    ctx.setLineDash(valueOrDefault(style.borderDash, options.borderDash));\n    ctx.lineDashOffset = valueOrDefault(style.borderDashOffset, options.borderDashOffset);\n    ctx.lineJoin = valueOrDefault(style.borderJoinStyle, options.borderJoinStyle);\n    ctx.lineWidth = valueOrDefault(style.borderWidth, options.borderWidth);\n    ctx.strokeStyle = valueOrDefault(style.borderColor, options.borderColor);\n}\nfunction lineTo(ctx, previous, target) {\n    ctx.lineTo(target.x, target.y);\n}\n function getLineMethod(options) {\n    if (options.stepped) {\n        return _steppedLineTo;\n    }\n    if (options.tension || options.cubicInterpolationMode === 'monotone') {\n        return _bezierCurveTo;\n    }\n    return lineTo;\n}\nfunction pathVars(points, segment, params = {}) {\n    const count = points.length;\n    const { start: paramsStart = 0 , end: paramsEnd = count - 1  } = params;\n    const { start: segmentStart , end: segmentEnd  } = segment;\n    const start = Math.max(paramsStart, segmentStart);\n    const end = Math.min(paramsEnd, segmentEnd);\n    const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd;\n    return {\n        count,\n        start,\n        loop: segment.loop,\n        ilen: end < start && !outside ? count + end - start : end - start\n    };\n}\n function pathSegment(ctx, line, segment, params) {\n    const { points , options  } = line;\n    const { count , start , loop , ilen  } = pathVars(points, segment, params);\n    const lineMethod = getLineMethod(options);\n    let { move =true , reverse  } = params || {};\n    let i, point, prev;\n    for(i = 0; i <= ilen; ++i){\n        point = points[(start + (reverse ? ilen - i : i)) % count];\n        if (point.skip) {\n            continue;\n        } else if (move) {\n            ctx.moveTo(point.x, point.y);\n            move = false;\n        } else {\n            lineMethod(ctx, prev, point, reverse, options.stepped);\n        }\n        prev = point;\n    }\n    if (loop) {\n        point = points[(start + (reverse ? ilen : 0)) % count];\n        lineMethod(ctx, prev, point, reverse, options.stepped);\n    }\n    return !!loop;\n}\n function fastPathSegment(ctx, line, segment, params) {\n    const points = line.points;\n    const { count , start , ilen  } = pathVars(points, segment, params);\n    const { move =true , reverse  } = params || {};\n    let avgX = 0;\n    let countX = 0;\n    let i, point, prevX, minY, maxY, lastY;\n    const pointIndex = (index)=>(start + (reverse ? ilen - index : index)) % count;\n    const drawX = ()=>{\n        if (minY !== maxY) {\n            ctx.lineTo(avgX, maxY);\n            ctx.lineTo(avgX, minY);\n            ctx.lineTo(avgX, lastY);\n        }\n    };\n    if (move) {\n        point = points[pointIndex(0)];\n        ctx.moveTo(point.x, point.y);\n    }\n    for(i = 0; i <= ilen; ++i){\n        point = points[pointIndex(i)];\n        if (point.skip) {\n            continue;\n        }\n        const x = point.x;\n        const y = point.y;\n        const truncX = x | 0;\n        if (truncX === prevX) {\n            if (y < minY) {\n                minY = y;\n            } else if (y > maxY) {\n                maxY = y;\n            }\n            avgX = (countX * avgX + x) / ++countX;\n        } else {\n            drawX();\n            ctx.lineTo(x, y);\n            prevX = truncX;\n            countX = 0;\n            minY = maxY = y;\n        }\n        lastY = y;\n    }\n    drawX();\n}\n function _getSegmentMethod(line) {\n    const opts = line.options;\n    const borderDash = opts.borderDash && opts.borderDash.length;\n    const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash;\n    return useFastPath ? fastPathSegment : pathSegment;\n}\n function _getInterpolationMethod(options) {\n    if (options.stepped) {\n        return _steppedInterpolation;\n    }\n    if (options.tension || options.cubicInterpolationMode === 'monotone') {\n        return _bezierInterpolation;\n    }\n    return _pointInLine;\n}\nfunction strokePathWithCache(ctx, line, start, count) {\n    let path = line._path;\n    if (!path) {\n        path = line._path = new Path2D();\n        if (line.path(path, start, count)) {\n            path.closePath();\n        }\n    }\n    setStyle(ctx, line.options);\n    ctx.stroke(path);\n}\nfunction strokePathDirect(ctx, line, start, count) {\n    const { segments , options  } = line;\n    const segmentMethod = _getSegmentMethod(line);\n    for (const segment of segments){\n        setStyle(ctx, options, segment.style);\n        ctx.beginPath();\n        if (segmentMethod(ctx, line, segment, {\n            start,\n            end: start + count - 1\n        })) {\n            ctx.closePath();\n        }\n        ctx.stroke();\n    }\n}\nconst usePath2D = typeof Path2D === 'function';\nfunction draw(ctx, line, start, count) {\n    if (usePath2D && !line.options.segment) {\n        strokePathWithCache(ctx, line, start, count);\n    } else {\n        strokePathDirect(ctx, line, start, count);\n    }\n}\nclass LineElement extends Element {\n    static id = 'line';\n static defaults = {\n        borderCapStyle: 'butt',\n        borderDash: [],\n        borderDashOffset: 0,\n        borderJoinStyle: 'miter',\n        borderWidth: 3,\n        capBezierPoints: true,\n        cubicInterpolationMode: 'default',\n        fill: false,\n        spanGaps: false,\n        stepped: false,\n        tension: 0\n    };\n static defaultRoutes = {\n        backgroundColor: 'backgroundColor',\n        borderColor: 'borderColor'\n    };\n    static descriptors = {\n        _scriptable: true,\n        _indexable: (name)=>name !== 'borderDash' && name !== 'fill'\n    };\n    constructor(cfg){\n        super();\n        this.animated = true;\n        this.options = undefined;\n        this._chart = undefined;\n        this._loop = undefined;\n        this._fullLoop = undefined;\n        this._path = undefined;\n        this._points = undefined;\n        this._segments = undefined;\n        this._decimated = false;\n        this._pointsUpdated = false;\n        this._datasetIndex = undefined;\n        if (cfg) {\n            Object.assign(this, cfg);\n        }\n    }\n    updateControlPoints(chartArea, indexAxis) {\n        const options = this.options;\n        if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) {\n            const loop = options.spanGaps ? this._loop : this._fullLoop;\n            _updateBezierControlPoints(this._points, options, chartArea, loop, indexAxis);\n            this._pointsUpdated = true;\n        }\n    }\n    set points(points) {\n        this._points = points;\n        delete this._segments;\n        delete this._path;\n        this._pointsUpdated = false;\n    }\n    get points() {\n        return this._points;\n    }\n    get segments() {\n        return this._segments || (this._segments = _computeSegments(this, this.options.segment));\n    }\n first() {\n        const segments = this.segments;\n        const points = this.points;\n        return segments.length && points[segments[0].start];\n    }\n last() {\n        const segments = this.segments;\n        const points = this.points;\n        const count = segments.length;\n        return count && points[segments[count - 1].end];\n    }\n interpolate(point, property) {\n        const options = this.options;\n        const value = point[property];\n        const points = this.points;\n        const segments = _boundSegments(this, {\n            property,\n            start: value,\n            end: value\n        });\n        if (!segments.length) {\n            return;\n        }\n        const result = [];\n        const _interpolate = _getInterpolationMethod(options);\n        let i, ilen;\n        for(i = 0, ilen = segments.length; i < ilen; ++i){\n            const { start , end  } = segments[i];\n            const p1 = points[start];\n            const p2 = points[end];\n            if (p1 === p2) {\n                result.push(p1);\n                continue;\n            }\n            const t = Math.abs((value - p1[property]) / (p2[property] - p1[property]));\n            const interpolated = _interpolate(p1, p2, t, options.stepped);\n            interpolated[property] = point[property];\n            result.push(interpolated);\n        }\n        return result.length === 1 ? result[0] : result;\n    }\n pathSegment(ctx, segment, params) {\n        const segmentMethod = _getSegmentMethod(this);\n        return segmentMethod(ctx, this, segment, params);\n    }\n path(ctx, start, count) {\n        const segments = this.segments;\n        const segmentMethod = _getSegmentMethod(this);\n        let loop = this._loop;\n        start = start || 0;\n        count = count || this.points.length - start;\n        for (const segment of segments){\n            loop &= segmentMethod(ctx, this, segment, {\n                start,\n                end: start + count - 1\n            });\n        }\n        return !!loop;\n    }\n draw(ctx, chartArea, start, count) {\n        const options = this.options || {};\n        const points = this.points || [];\n        if (points.length && options.borderWidth) {\n            ctx.save();\n            draw(ctx, this, start, count);\n            ctx.restore();\n        }\n        if (this.animated) {\n            this._pointsUpdated = false;\n            this._path = undefined;\n        }\n    }\n}\n\nfunction inRange$1(el, pos, axis, useFinalPosition) {\n    const options = el.options;\n    const { [axis]: value  } = el.getProps([\n        axis\n    ], useFinalPosition);\n    return Math.abs(pos - value) < options.radius + options.hitRadius;\n}\nclass PointElement extends Element {\n    static id = 'point';\n    parsed;\n    skip;\n    stop;\n    /**\n   * @type {any}\n   */ static defaults = {\n        borderWidth: 1,\n        hitRadius: 1,\n        hoverBorderWidth: 1,\n        hoverRadius: 4,\n        pointStyle: 'circle',\n        radius: 3,\n        rotation: 0\n    };\n    /**\n   * @type {any}\n   */ static defaultRoutes = {\n        backgroundColor: 'backgroundColor',\n        borderColor: 'borderColor'\n    };\n    constructor(cfg){\n        super();\n        this.options = undefined;\n        this.parsed = undefined;\n        this.skip = undefined;\n        this.stop = undefined;\n        if (cfg) {\n            Object.assign(this, cfg);\n        }\n    }\n    inRange(mouseX, mouseY, useFinalPosition) {\n        const options = this.options;\n        const { x , y  } = this.getProps([\n            'x',\n            'y'\n        ], useFinalPosition);\n        return Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2) < Math.pow(options.hitRadius + options.radius, 2);\n    }\n    inXRange(mouseX, useFinalPosition) {\n        return inRange$1(this, mouseX, 'x', useFinalPosition);\n    }\n    inYRange(mouseY, useFinalPosition) {\n        return inRange$1(this, mouseY, 'y', useFinalPosition);\n    }\n    getCenterPoint(useFinalPosition) {\n        const { x , y  } = this.getProps([\n            'x',\n            'y'\n        ], useFinalPosition);\n        return {\n            x,\n            y\n        };\n    }\n    size(options) {\n        options = options || this.options || {};\n        let radius = options.radius || 0;\n        radius = Math.max(radius, radius && options.hoverRadius || 0);\n        const borderWidth = radius && options.borderWidth || 0;\n        return (radius + borderWidth) * 2;\n    }\n    draw(ctx, area) {\n        const options = this.options;\n        if (this.skip || options.radius < 0.1 || !_isPointInArea(this, area, this.size(options) / 2)) {\n            return;\n        }\n        ctx.strokeStyle = options.borderColor;\n        ctx.lineWidth = options.borderWidth;\n        ctx.fillStyle = options.backgroundColor;\n        drawPoint(ctx, options, this.x, this.y);\n    }\n    getRange() {\n        const options = this.options || {};\n        // @ts-expect-error Fallbacks should never be hit in practice\n        return options.radius + options.hitRadius;\n    }\n}\n\nfunction getBarBounds(bar, useFinalPosition) {\n    const { x , y , base , width , height  } =  bar.getProps([\n        'x',\n        'y',\n        'base',\n        'width',\n        'height'\n    ], useFinalPosition);\n    let left, right, top, bottom, half;\n    if (bar.horizontal) {\n        half = height / 2;\n        left = Math.min(x, base);\n        right = Math.max(x, base);\n        top = y - half;\n        bottom = y + half;\n    } else {\n        half = width / 2;\n        left = x - half;\n        right = x + half;\n        top = Math.min(y, base);\n        bottom = Math.max(y, base);\n    }\n    return {\n        left,\n        top,\n        right,\n        bottom\n    };\n}\nfunction skipOrLimit(skip, value, min, max) {\n    return skip ? 0 : _limitValue(value, min, max);\n}\nfunction parseBorderWidth(bar, maxW, maxH) {\n    const value = bar.options.borderWidth;\n    const skip = bar.borderSkipped;\n    const o = toTRBL(value);\n    return {\n        t: skipOrLimit(skip.top, o.top, 0, maxH),\n        r: skipOrLimit(skip.right, o.right, 0, maxW),\n        b: skipOrLimit(skip.bottom, o.bottom, 0, maxH),\n        l: skipOrLimit(skip.left, o.left, 0, maxW)\n    };\n}\nfunction parseBorderRadius(bar, maxW, maxH) {\n    const { enableBorderRadius  } = bar.getProps([\n        'enableBorderRadius'\n    ]);\n    const value = bar.options.borderRadius;\n    const o = toTRBLCorners(value);\n    const maxR = Math.min(maxW, maxH);\n    const skip = bar.borderSkipped;\n    const enableBorder = enableBorderRadius || isObject(value);\n    return {\n        topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR),\n        topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR),\n        bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR),\n        bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR)\n    };\n}\nfunction boundingRects(bar) {\n    const bounds = getBarBounds(bar);\n    const width = bounds.right - bounds.left;\n    const height = bounds.bottom - bounds.top;\n    const border = parseBorderWidth(bar, width / 2, height / 2);\n    const radius = parseBorderRadius(bar, width / 2, height / 2);\n    return {\n        outer: {\n            x: bounds.left,\n            y: bounds.top,\n            w: width,\n            h: height,\n            radius\n        },\n        inner: {\n            x: bounds.left + border.l,\n            y: bounds.top + border.t,\n            w: width - border.l - border.r,\n            h: height - border.t - border.b,\n            radius: {\n                topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),\n                topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),\n                bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),\n                bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r))\n            }\n        }\n    };\n}\nfunction inRange(bar, x, y, useFinalPosition) {\n    const skipX = x === null;\n    const skipY = y === null;\n    const skipBoth = skipX && skipY;\n    const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);\n    return bounds && (skipX || _isBetween(x, bounds.left, bounds.right)) && (skipY || _isBetween(y, bounds.top, bounds.bottom));\n}\nfunction hasRadius(radius) {\n    return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;\n}\n function addNormalRectPath(ctx, rect) {\n    ctx.rect(rect.x, rect.y, rect.w, rect.h);\n}\nfunction inflateRect(rect, amount, refRect = {}) {\n    const x = rect.x !== refRect.x ? -amount : 0;\n    const y = rect.y !== refRect.y ? -amount : 0;\n    const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x;\n    const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y;\n    return {\n        x: rect.x + x,\n        y: rect.y + y,\n        w: rect.w + w,\n        h: rect.h + h,\n        radius: rect.radius\n    };\n}\nclass BarElement extends Element {\n    static id = 'bar';\n static defaults = {\n        borderSkipped: 'start',\n        borderWidth: 0,\n        borderRadius: 0,\n        inflateAmount: 'auto',\n        pointStyle: undefined\n    };\n static defaultRoutes = {\n        backgroundColor: 'backgroundColor',\n        borderColor: 'borderColor'\n    };\n    constructor(cfg){\n        super();\n        this.options = undefined;\n        this.horizontal = undefined;\n        this.base = undefined;\n        this.width = undefined;\n        this.height = undefined;\n        this.inflateAmount = undefined;\n        if (cfg) {\n            Object.assign(this, cfg);\n        }\n    }\n    draw(ctx) {\n        const { inflateAmount , options: { borderColor , backgroundColor  }  } = this;\n        const { inner , outer  } = boundingRects(this);\n        const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;\n        ctx.save();\n        if (outer.w !== inner.w || outer.h !== inner.h) {\n            ctx.beginPath();\n            addRectPath(ctx, inflateRect(outer, inflateAmount, inner));\n            ctx.clip();\n            addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));\n            ctx.fillStyle = borderColor;\n            ctx.fill('evenodd');\n        }\n        ctx.beginPath();\n        addRectPath(ctx, inflateRect(inner, inflateAmount));\n        ctx.fillStyle = backgroundColor;\n        ctx.fill();\n        ctx.restore();\n    }\n    inRange(mouseX, mouseY, useFinalPosition) {\n        return inRange(this, mouseX, mouseY, useFinalPosition);\n    }\n    inXRange(mouseX, useFinalPosition) {\n        return inRange(this, mouseX, null, useFinalPosition);\n    }\n    inYRange(mouseY, useFinalPosition) {\n        return inRange(this, null, mouseY, useFinalPosition);\n    }\n    getCenterPoint(useFinalPosition) {\n        const { x , y , base , horizontal  } =  this.getProps([\n            'x',\n            'y',\n            'base',\n            'horizontal'\n        ], useFinalPosition);\n        return {\n            x: horizontal ? (x + base) / 2 : x,\n            y: horizontal ? y : (y + base) / 2\n        };\n    }\n    getRange(axis) {\n        return axis === 'x' ? this.width / 2 : this.height / 2;\n    }\n}\n\nvar elements = /*#__PURE__*/Object.freeze({\n__proto__: null,\nArcElement: ArcElement,\nBarElement: BarElement,\nLineElement: LineElement,\nPointElement: PointElement\n});\n\nconst BORDER_COLORS = [\n    'rgb(54, 162, 235)',\n    'rgb(255, 99, 132)',\n    'rgb(255, 159, 64)',\n    'rgb(255, 205, 86)',\n    'rgb(75, 192, 192)',\n    'rgb(153, 102, 255)',\n    'rgb(201, 203, 207)' // grey\n];\n// Border colors with 50% transparency\nconst BACKGROUND_COLORS = /* #__PURE__ */ BORDER_COLORS.map((color)=>color.replace('rgb(', 'rgba(').replace(')', ', 0.5)'));\nfunction getBorderColor(i) {\n    return BORDER_COLORS[i % BORDER_COLORS.length];\n}\nfunction getBackgroundColor(i) {\n    return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length];\n}\nfunction colorizeDefaultDataset(dataset, i) {\n    dataset.borderColor = getBorderColor(i);\n    dataset.backgroundColor = getBackgroundColor(i);\n    return ++i;\n}\nfunction colorizeDoughnutDataset(dataset, i) {\n    dataset.backgroundColor = dataset.data.map(()=>getBorderColor(i++));\n    return i;\n}\nfunction colorizePolarAreaDataset(dataset, i) {\n    dataset.backgroundColor = dataset.data.map(()=>getBackgroundColor(i++));\n    return i;\n}\nfunction getColorizer(chart) {\n    let i = 0;\n    return (dataset, datasetIndex)=>{\n        const controller = chart.getDatasetMeta(datasetIndex).controller;\n        if (controller instanceof DoughnutController) {\n            i = colorizeDoughnutDataset(dataset, i);\n        } else if (controller instanceof PolarAreaController) {\n            i = colorizePolarAreaDataset(dataset, i);\n        } else if (controller) {\n            i = colorizeDefaultDataset(dataset, i);\n        }\n    };\n}\nfunction containsColorsDefinitions(descriptors) {\n    let k;\n    for(k in descriptors){\n        if (descriptors[k].borderColor || descriptors[k].backgroundColor) {\n            return true;\n        }\n    }\n    return false;\n}\nfunction containsColorsDefinition(descriptor) {\n    return descriptor && (descriptor.borderColor || descriptor.backgroundColor);\n}\nvar plugin_colors = {\n    id: 'colors',\n    defaults: {\n        enabled: true,\n        forceOverride: false\n    },\n    beforeLayout (chart, _args, options) {\n        if (!options.enabled) {\n            return;\n        }\n        const { data: { datasets  } , options: chartOptions  } = chart.config;\n        const { elements  } = chartOptions;\n        if (!options.forceOverride && (containsColorsDefinitions(datasets) || containsColorsDefinition(chartOptions) || elements && containsColorsDefinitions(elements))) {\n            return;\n        }\n        const colorizer = getColorizer(chart);\n        datasets.forEach(colorizer);\n    }\n};\n\nfunction lttbDecimation(data, start, count, availableWidth, options) {\n const samples = options.samples || availableWidth;\n    if (samples >= count) {\n        return data.slice(start, start + count);\n    }\n    const decimated = [];\n    const bucketWidth = (count - 2) / (samples - 2);\n    let sampledIndex = 0;\n    const endIndex = start + count - 1;\n    let a = start;\n    let i, maxAreaPoint, maxArea, area, nextA;\n    decimated[sampledIndex++] = data[a];\n    for(i = 0; i < samples - 2; i++){\n        let avgX = 0;\n        let avgY = 0;\n        let j;\n        const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start;\n        const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start;\n        const avgRangeLength = avgRangeEnd - avgRangeStart;\n        for(j = avgRangeStart; j < avgRangeEnd; j++){\n            avgX += data[j].x;\n            avgY += data[j].y;\n        }\n        avgX /= avgRangeLength;\n        avgY /= avgRangeLength;\n        const rangeOffs = Math.floor(i * bucketWidth) + 1 + start;\n        const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start;\n        const { x: pointAx , y: pointAy  } = data[a];\n        maxArea = area = -1;\n        for(j = rangeOffs; j < rangeTo; j++){\n            area = 0.5 * Math.abs((pointAx - avgX) * (data[j].y - pointAy) - (pointAx - data[j].x) * (avgY - pointAy));\n            if (area > maxArea) {\n                maxArea = area;\n                maxAreaPoint = data[j];\n                nextA = j;\n            }\n        }\n        decimated[sampledIndex++] = maxAreaPoint;\n        a = nextA;\n    }\n    decimated[sampledIndex++] = data[endIndex];\n    return decimated;\n}\nfunction minMaxDecimation(data, start, count, availableWidth) {\n    let avgX = 0;\n    let countX = 0;\n    let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY;\n    const decimated = [];\n    const endIndex = start + count - 1;\n    const xMin = data[start].x;\n    const xMax = data[endIndex].x;\n    const dx = xMax - xMin;\n    for(i = start; i < start + count; ++i){\n        point = data[i];\n        x = (point.x - xMin) / dx * availableWidth;\n        y = point.y;\n        const truncX = x | 0;\n        if (truncX === prevX) {\n            if (y < minY) {\n                minY = y;\n                minIndex = i;\n            } else if (y > maxY) {\n                maxY = y;\n                maxIndex = i;\n            }\n            avgX = (countX * avgX + point.x) / ++countX;\n        } else {\n            const lastIndex = i - 1;\n            if (!isNullOrUndef(minIndex) && !isNullOrUndef(maxIndex)) {\n                const intermediateIndex1 = Math.min(minIndex, maxIndex);\n                const intermediateIndex2 = Math.max(minIndex, maxIndex);\n                if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) {\n                    decimated.push({\n                        ...data[intermediateIndex1],\n                        x: avgX\n                    });\n                }\n                if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) {\n                    decimated.push({\n                        ...data[intermediateIndex2],\n                        x: avgX\n                    });\n                }\n            }\n            if (i > 0 && lastIndex !== startIndex) {\n                decimated.push(data[lastIndex]);\n            }\n            decimated.push(point);\n            prevX = truncX;\n            countX = 0;\n            minY = maxY = y;\n            minIndex = maxIndex = startIndex = i;\n        }\n    }\n    return decimated;\n}\nfunction cleanDecimatedDataset(dataset) {\n    if (dataset._decimated) {\n        const data = dataset._data;\n        delete dataset._decimated;\n        delete dataset._data;\n        Object.defineProperty(dataset, 'data', {\n            configurable: true,\n            enumerable: true,\n            writable: true,\n            value: data\n        });\n    }\n}\nfunction cleanDecimatedData(chart) {\n    chart.data.datasets.forEach((dataset)=>{\n        cleanDecimatedDataset(dataset);\n    });\n}\nfunction getStartAndCountOfVisiblePointsSimplified(meta, points) {\n    const pointCount = points.length;\n    let start = 0;\n    let count;\n    const { iScale  } = meta;\n    const { min , max , minDefined , maxDefined  } = iScale.getUserBounds();\n    if (minDefined) {\n        start = _limitValue(_lookupByKey(points, iScale.axis, min).lo, 0, pointCount - 1);\n    }\n    if (maxDefined) {\n        count = _limitValue(_lookupByKey(points, iScale.axis, max).hi + 1, start, pointCount) - start;\n    } else {\n        count = pointCount - start;\n    }\n    return {\n        start,\n        count\n    };\n}\nvar plugin_decimation = {\n    id: 'decimation',\n    defaults: {\n        algorithm: 'min-max',\n        enabled: false\n    },\n    beforeElementsUpdate: (chart, args, options)=>{\n        if (!options.enabled) {\n            cleanDecimatedData(chart);\n            return;\n        }\n        const availableWidth = chart.width;\n        chart.data.datasets.forEach((dataset, datasetIndex)=>{\n            const { _data , indexAxis  } = dataset;\n            const meta = chart.getDatasetMeta(datasetIndex);\n            const data = _data || dataset.data;\n            if (resolve([\n                indexAxis,\n                chart.options.indexAxis\n            ]) === 'y') {\n                return;\n            }\n            if (!meta.controller.supportsDecimation) {\n                return;\n            }\n            const xAxis = chart.scales[meta.xAxisID];\n            if (xAxis.type !== 'linear' && xAxis.type !== 'time') {\n                return;\n            }\n            if (chart.options.parsing) {\n                return;\n            }\n            let { start , count  } = getStartAndCountOfVisiblePointsSimplified(meta, data);\n            const threshold = options.threshold || 4 * availableWidth;\n            if (count <= threshold) {\n                cleanDecimatedDataset(dataset);\n                return;\n            }\n            if (isNullOrUndef(_data)) {\n                dataset._data = data;\n                delete dataset.data;\n                Object.defineProperty(dataset, 'data', {\n                    configurable: true,\n                    enumerable: true,\n                    get: function() {\n                        return this._decimated;\n                    },\n                    set: function(d) {\n                        this._data = d;\n                    }\n                });\n            }\n            let decimated;\n            switch(options.algorithm){\n                case 'lttb':\n                    decimated = lttbDecimation(data, start, count, availableWidth, options);\n                    break;\n                case 'min-max':\n                    decimated = minMaxDecimation(data, start, count, availableWidth);\n                    break;\n                default:\n                    throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`);\n            }\n            dataset._decimated = decimated;\n        });\n    },\n    destroy (chart) {\n        cleanDecimatedData(chart);\n    }\n};\n\nfunction _segments(line, target, property) {\n    const segments = line.segments;\n    const points = line.points;\n    const tpoints = target.points;\n    const parts = [];\n    for (const segment of segments){\n        let { start , end  } = segment;\n        end = _findSegmentEnd(start, end, points);\n        const bounds = _getBounds(property, points[start], points[end], segment.loop);\n        if (!target.segments) {\n            parts.push({\n                source: segment,\n                target: bounds,\n                start: points[start],\n                end: points[end]\n            });\n            continue;\n        }\n        const targetSegments = _boundSegments(target, bounds);\n        for (const tgt of targetSegments){\n            const subBounds = _getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop);\n            const fillSources = _boundSegment(segment, points, subBounds);\n            for (const fillSource of fillSources){\n                parts.push({\n                    source: fillSource,\n                    target: tgt,\n                    start: {\n                        [property]: _getEdge(bounds, subBounds, 'start', Math.max)\n                    },\n                    end: {\n                        [property]: _getEdge(bounds, subBounds, 'end', Math.min)\n                    }\n                });\n            }\n        }\n    }\n    return parts;\n}\nfunction _getBounds(property, first, last, loop) {\n    if (loop) {\n        return;\n    }\n    let start = first[property];\n    let end = last[property];\n    if (property === 'angle') {\n        start = _normalizeAngle(start);\n        end = _normalizeAngle(end);\n    }\n    return {\n        property,\n        start,\n        end\n    };\n}\nfunction _pointsFromSegments(boundary, line) {\n    const { x =null , y =null  } = boundary || {};\n    const linePoints = line.points;\n    const points = [];\n    line.segments.forEach(({ start , end  })=>{\n        end = _findSegmentEnd(start, end, linePoints);\n        const first = linePoints[start];\n        const last = linePoints[end];\n        if (y !== null) {\n            points.push({\n                x: first.x,\n                y\n            });\n            points.push({\n                x: last.x,\n                y\n            });\n        } else if (x !== null) {\n            points.push({\n                x,\n                y: first.y\n            });\n            points.push({\n                x,\n                y: last.y\n            });\n        }\n    });\n    return points;\n}\nfunction _findSegmentEnd(start, end, points) {\n    for(; end > start; end--){\n        const point = points[end];\n        if (!isNaN(point.x) && !isNaN(point.y)) {\n            break;\n        }\n    }\n    return end;\n}\nfunction _getEdge(a, b, prop, fn) {\n    if (a && b) {\n        return fn(a[prop], b[prop]);\n    }\n    return a ? a[prop] : b ? b[prop] : 0;\n}\n\nfunction _createBoundaryLine(boundary, line) {\n    let points = [];\n    let _loop = false;\n    if (isArray(boundary)) {\n        _loop = true;\n        points = boundary;\n    } else {\n        points = _pointsFromSegments(boundary, line);\n    }\n    return points.length ? new LineElement({\n        points,\n        options: {\n            tension: 0\n        },\n        _loop,\n        _fullLoop: _loop\n    }) : null;\n}\nfunction _shouldApplyFill(source) {\n    return source && source.fill !== false;\n}\n\nfunction _resolveTarget(sources, index, propagate) {\n    const source = sources[index];\n    let fill = source.fill;\n    const visited = [\n        index\n    ];\n    let target;\n    if (!propagate) {\n        return fill;\n    }\n    while(fill !== false && visited.indexOf(fill) === -1){\n        if (!isNumberFinite(fill)) {\n            return fill;\n        }\n        target = sources[fill];\n        if (!target) {\n            return false;\n        }\n        if (target.visible) {\n            return fill;\n        }\n        visited.push(fill);\n        fill = target.fill;\n    }\n    return false;\n}\n function _decodeFill(line, index, count) {\n     const fill = parseFillOption(line);\n    if (isObject(fill)) {\n        return isNaN(fill.value) ? false : fill;\n    }\n    let target = parseFloat(fill);\n    if (isNumberFinite(target) && Math.floor(target) === target) {\n        return decodeTargetIndex(fill[0], index, target, count);\n    }\n    return [\n        'origin',\n        'start',\n        'end',\n        'stack',\n        'shape'\n    ].indexOf(fill) >= 0 && fill;\n}\nfunction decodeTargetIndex(firstCh, index, target, count) {\n    if (firstCh === '-' || firstCh === '+') {\n        target = index + target;\n    }\n    if (target === index || target < 0 || target >= count) {\n        return false;\n    }\n    return target;\n}\n function _getTargetPixel(fill, scale) {\n    let pixel = null;\n    if (fill === 'start') {\n        pixel = scale.bottom;\n    } else if (fill === 'end') {\n        pixel = scale.top;\n    } else if (isObject(fill)) {\n        pixel = scale.getPixelForValue(fill.value);\n    } else if (scale.getBasePixel) {\n        pixel = scale.getBasePixel();\n    }\n    return pixel;\n}\n function _getTargetValue(fill, scale, startValue) {\n    let value;\n    if (fill === 'start') {\n        value = startValue;\n    } else if (fill === 'end') {\n        value = scale.options.reverse ? scale.min : scale.max;\n    } else if (isObject(fill)) {\n        value = fill.value;\n    } else {\n        value = scale.getBaseValue();\n    }\n    return value;\n}\n function parseFillOption(line) {\n    const options = line.options;\n    const fillOption = options.fill;\n    let fill = valueOrDefault(fillOption && fillOption.target, fillOption);\n    if (fill === undefined) {\n        fill = !!options.backgroundColor;\n    }\n    if (fill === false || fill === null) {\n        return false;\n    }\n    if (fill === true) {\n        return 'origin';\n    }\n    return fill;\n}\n\nfunction _buildStackLine(source) {\n    const { scale , index , line  } = source;\n    const points = [];\n    const segments = line.segments;\n    const sourcePoints = line.points;\n    const linesBelow = getLinesBelow(scale, index);\n    linesBelow.push(_createBoundaryLine({\n        x: null,\n        y: scale.bottom\n    }, line));\n    for(let i = 0; i < segments.length; i++){\n        const segment = segments[i];\n        for(let j = segment.start; j <= segment.end; j++){\n            addPointsBelow(points, sourcePoints[j], linesBelow);\n        }\n    }\n    return new LineElement({\n        points,\n        options: {}\n    });\n}\n function getLinesBelow(scale, index) {\n    const below = [];\n    const metas = scale.getMatchingVisibleMetas('line');\n    for(let i = 0; i < metas.length; i++){\n        const meta = metas[i];\n        if (meta.index === index) {\n            break;\n        }\n        if (!meta.hidden) {\n            below.unshift(meta.dataset);\n        }\n    }\n    return below;\n}\n function addPointsBelow(points, sourcePoint, linesBelow) {\n    const postponed = [];\n    for(let j = 0; j < linesBelow.length; j++){\n        const line = linesBelow[j];\n        const { first , last , point  } = findPoint(line, sourcePoint, 'x');\n        if (!point || first && last) {\n            continue;\n        }\n        if (first) {\n            postponed.unshift(point);\n        } else {\n            points.push(point);\n            if (!last) {\n                break;\n            }\n        }\n    }\n    points.push(...postponed);\n}\n function findPoint(line, sourcePoint, property) {\n    const point = line.interpolate(sourcePoint, property);\n    if (!point) {\n        return {};\n    }\n    const pointValue = point[property];\n    const segments = line.segments;\n    const linePoints = line.points;\n    let first = false;\n    let last = false;\n    for(let i = 0; i < segments.length; i++){\n        const segment = segments[i];\n        const firstValue = linePoints[segment.start][property];\n        const lastValue = linePoints[segment.end][property];\n        if (_isBetween(pointValue, firstValue, lastValue)) {\n            first = pointValue === firstValue;\n            last = pointValue === lastValue;\n            break;\n        }\n    }\n    return {\n        first,\n        last,\n        point\n    };\n}\n\nclass simpleArc {\n    constructor(opts){\n        this.x = opts.x;\n        this.y = opts.y;\n        this.radius = opts.radius;\n    }\n    pathSegment(ctx, bounds, opts) {\n        const { x , y , radius  } = this;\n        bounds = bounds || {\n            start: 0,\n            end: TAU\n        };\n        ctx.arc(x, y, radius, bounds.end, bounds.start, true);\n        return !opts.bounds;\n    }\n    interpolate(point) {\n        const { x , y , radius  } = this;\n        const angle = point.angle;\n        return {\n            x: x + Math.cos(angle) * radius,\n            y: y + Math.sin(angle) * radius,\n            angle\n        };\n    }\n}\n\nfunction _getTarget(source) {\n    const { chart , fill , line  } = source;\n    if (isNumberFinite(fill)) {\n        return getLineByIndex(chart, fill);\n    }\n    if (fill === 'stack') {\n        return _buildStackLine(source);\n    }\n    if (fill === 'shape') {\n        return true;\n    }\n    const boundary = computeBoundary(source);\n    if (boundary instanceof simpleArc) {\n        return boundary;\n    }\n    return _createBoundaryLine(boundary, line);\n}\n function getLineByIndex(chart, index) {\n    const meta = chart.getDatasetMeta(index);\n    const visible = meta && chart.isDatasetVisible(index);\n    return visible ? meta.dataset : null;\n}\nfunction computeBoundary(source) {\n    const scale = source.scale || {};\n    if (scale.getPointPositionForValue) {\n        return computeCircularBoundary(source);\n    }\n    return computeLinearBoundary(source);\n}\nfunction computeLinearBoundary(source) {\n    const { scale ={} , fill  } = source;\n    const pixel = _getTargetPixel(fill, scale);\n    if (isNumberFinite(pixel)) {\n        const horizontal = scale.isHorizontal();\n        return {\n            x: horizontal ? pixel : null,\n            y: horizontal ? null : pixel\n        };\n    }\n    return null;\n}\nfunction computeCircularBoundary(source) {\n    const { scale , fill  } = source;\n    const options = scale.options;\n    const length = scale.getLabels().length;\n    const start = options.reverse ? scale.max : scale.min;\n    const value = _getTargetValue(fill, scale, start);\n    const target = [];\n    if (options.grid.circular) {\n        const center = scale.getPointPositionForValue(0, start);\n        return new simpleArc({\n            x: center.x,\n            y: center.y,\n            radius: scale.getDistanceFromCenterForValue(value)\n        });\n    }\n    for(let i = 0; i < length; ++i){\n        target.push(scale.getPointPositionForValue(i, value));\n    }\n    return target;\n}\n\nfunction _drawfill(ctx, source, area) {\n    const target = _getTarget(source);\n    const { line , scale , axis  } = source;\n    const lineOpts = line.options;\n    const fillOption = lineOpts.fill;\n    const color = lineOpts.backgroundColor;\n    const { above =color , below =color  } = fillOption || {};\n    if (target && line.points.length) {\n        clipArea(ctx, area);\n        doFill(ctx, {\n            line,\n            target,\n            above,\n            below,\n            area,\n            scale,\n            axis\n        });\n        unclipArea(ctx);\n    }\n}\nfunction doFill(ctx, cfg) {\n    const { line , target , above , below , area , scale  } = cfg;\n    const property = line._loop ? 'angle' : cfg.axis;\n    ctx.save();\n    if (property === 'x' && below !== above) {\n        clipVertical(ctx, target, area.top);\n        fill(ctx, {\n            line,\n            target,\n            color: above,\n            scale,\n            property\n        });\n        ctx.restore();\n        ctx.save();\n        clipVertical(ctx, target, area.bottom);\n    }\n    fill(ctx, {\n        line,\n        target,\n        color: below,\n        scale,\n        property\n    });\n    ctx.restore();\n}\nfunction clipVertical(ctx, target, clipY) {\n    const { segments , points  } = target;\n    let first = true;\n    let lineLoop = false;\n    ctx.beginPath();\n    for (const segment of segments){\n        const { start , end  } = segment;\n        const firstPoint = points[start];\n        const lastPoint = points[_findSegmentEnd(start, end, points)];\n        if (first) {\n            ctx.moveTo(firstPoint.x, firstPoint.y);\n            first = false;\n        } else {\n            ctx.lineTo(firstPoint.x, clipY);\n            ctx.lineTo(firstPoint.x, firstPoint.y);\n        }\n        lineLoop = !!target.pathSegment(ctx, segment, {\n            move: lineLoop\n        });\n        if (lineLoop) {\n            ctx.closePath();\n        } else {\n            ctx.lineTo(lastPoint.x, clipY);\n        }\n    }\n    ctx.lineTo(target.first().x, clipY);\n    ctx.closePath();\n    ctx.clip();\n}\nfunction fill(ctx, cfg) {\n    const { line , target , property , color , scale  } = cfg;\n    const segments = _segments(line, target, property);\n    for (const { source: src , target: tgt , start , end  } of segments){\n        const { style: { backgroundColor =color  } = {}  } = src;\n        const notShape = target !== true;\n        ctx.save();\n        ctx.fillStyle = backgroundColor;\n        clipBounds(ctx, scale, notShape && _getBounds(property, start, end));\n        ctx.beginPath();\n        const lineLoop = !!line.pathSegment(ctx, src);\n        let loop;\n        if (notShape) {\n            if (lineLoop) {\n                ctx.closePath();\n            } else {\n                interpolatedLineTo(ctx, target, end, property);\n            }\n            const targetLoop = !!target.pathSegment(ctx, tgt, {\n                move: lineLoop,\n                reverse: true\n            });\n            loop = lineLoop && targetLoop;\n            if (!loop) {\n                interpolatedLineTo(ctx, target, start, property);\n            }\n        }\n        ctx.closePath();\n        ctx.fill(loop ? 'evenodd' : 'nonzero');\n        ctx.restore();\n    }\n}\nfunction clipBounds(ctx, scale, bounds) {\n    const { top , bottom  } = scale.chart.chartArea;\n    const { property , start , end  } = bounds || {};\n    if (property === 'x') {\n        ctx.beginPath();\n        ctx.rect(start, top, end - start, bottom - top);\n        ctx.clip();\n    }\n}\nfunction interpolatedLineTo(ctx, target, point, property) {\n    const interpolatedPoint = target.interpolate(point, property);\n    if (interpolatedPoint) {\n        ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y);\n    }\n}\n\nvar index = {\n    id: 'filler',\n    afterDatasetsUpdate (chart, _args, options) {\n        const count = (chart.data.datasets || []).length;\n        const sources = [];\n        let meta, i, line, source;\n        for(i = 0; i < count; ++i){\n            meta = chart.getDatasetMeta(i);\n            line = meta.dataset;\n            source = null;\n            if (line && line.options && line instanceof LineElement) {\n                source = {\n                    visible: chart.isDatasetVisible(i),\n                    index: i,\n                    fill: _decodeFill(line, i, count),\n                    chart,\n                    axis: meta.controller.options.indexAxis,\n                    scale: meta.vScale,\n                    line\n                };\n            }\n            meta.$filler = source;\n            sources.push(source);\n        }\n        for(i = 0; i < count; ++i){\n            source = sources[i];\n            if (!source || source.fill === false) {\n                continue;\n            }\n            source.fill = _resolveTarget(sources, i, options.propagate);\n        }\n    },\n    beforeDraw (chart, _args, options) {\n        const draw = options.drawTime === 'beforeDraw';\n        const metasets = chart.getSortedVisibleDatasetMetas();\n        const area = chart.chartArea;\n        for(let i = metasets.length - 1; i >= 0; --i){\n            const source = metasets[i].$filler;\n            if (!source) {\n                continue;\n            }\n            source.line.updateControlPoints(area, source.axis);\n            if (draw && source.fill) {\n                _drawfill(chart.ctx, source, area);\n            }\n        }\n    },\n    beforeDatasetsDraw (chart, _args, options) {\n        if (options.drawTime !== 'beforeDatasetsDraw') {\n            return;\n        }\n        const metasets = chart.getSortedVisibleDatasetMetas();\n        for(let i = metasets.length - 1; i >= 0; --i){\n            const source = metasets[i].$filler;\n            if (_shouldApplyFill(source)) {\n                _drawfill(chart.ctx, source, chart.chartArea);\n            }\n        }\n    },\n    beforeDatasetDraw (chart, args, options) {\n        const source = args.meta.$filler;\n        if (!_shouldApplyFill(source) || options.drawTime !== 'beforeDatasetDraw') {\n            return;\n        }\n        _drawfill(chart.ctx, source, chart.chartArea);\n    },\n    defaults: {\n        propagate: true,\n        drawTime: 'beforeDatasetDraw'\n    }\n};\n\nconst getBoxSize = (labelOpts, fontSize)=>{\n    let { boxHeight =fontSize , boxWidth =fontSize  } = labelOpts;\n    if (labelOpts.usePointStyle) {\n        boxHeight = Math.min(boxHeight, fontSize);\n        boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);\n    }\n    return {\n        boxWidth,\n        boxHeight,\n        itemHeight: Math.max(fontSize, boxHeight)\n    };\n};\nconst itemsEqual = (a, b)=>a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index;\nclass Legend extends Element {\n constructor(config){\n        super();\n        this._added = false;\n        this.legendHitBoxes = [];\n this._hoveredItem = null;\n        this.doughnutMode = false;\n        this.chart = config.chart;\n        this.options = config.options;\n        this.ctx = config.ctx;\n        this.legendItems = undefined;\n        this.columnSizes = undefined;\n        this.lineWidths = undefined;\n        this.maxHeight = undefined;\n        this.maxWidth = undefined;\n        this.top = undefined;\n        this.bottom = undefined;\n        this.left = undefined;\n        this.right = undefined;\n        this.height = undefined;\n        this.width = undefined;\n        this._margins = undefined;\n        this.position = undefined;\n        this.weight = undefined;\n        this.fullSize = undefined;\n    }\n    update(maxWidth, maxHeight, margins) {\n        this.maxWidth = maxWidth;\n        this.maxHeight = maxHeight;\n        this._margins = margins;\n        this.setDimensions();\n        this.buildLabels();\n        this.fit();\n    }\n    setDimensions() {\n        if (this.isHorizontal()) {\n            this.width = this.maxWidth;\n            this.left = this._margins.left;\n            this.right = this.width;\n        } else {\n            this.height = this.maxHeight;\n            this.top = this._margins.top;\n            this.bottom = this.height;\n        }\n    }\n    buildLabels() {\n        const labelOpts = this.options.labels || {};\n        let legendItems = callback(labelOpts.generateLabels, [\n            this.chart\n        ], this) || [];\n        if (labelOpts.filter) {\n            legendItems = legendItems.filter((item)=>labelOpts.filter(item, this.chart.data));\n        }\n        if (labelOpts.sort) {\n            legendItems = legendItems.sort((a, b)=>labelOpts.sort(a, b, this.chart.data));\n        }\n        if (this.options.reverse) {\n            legendItems.reverse();\n        }\n        this.legendItems = legendItems;\n    }\n    fit() {\n        const { options , ctx  } = this;\n        if (!options.display) {\n            this.width = this.height = 0;\n            return;\n        }\n        const labelOpts = options.labels;\n        const labelFont = toFont(labelOpts.font);\n        const fontSize = labelFont.size;\n        const titleHeight = this._computeTitleHeight();\n        const { boxWidth , itemHeight  } = getBoxSize(labelOpts, fontSize);\n        let width, height;\n        ctx.font = labelFont.string;\n        if (this.isHorizontal()) {\n            width = this.maxWidth;\n            height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;\n        } else {\n            height = this.maxHeight;\n            width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10;\n        }\n        this.width = Math.min(width, options.maxWidth || this.maxWidth);\n        this.height = Math.min(height, options.maxHeight || this.maxHeight);\n    }\n _fitRows(titleHeight, fontSize, boxWidth, itemHeight) {\n        const { ctx , maxWidth , options: { labels: { padding  }  }  } = this;\n        const hitboxes = this.legendHitBoxes = [];\n        const lineWidths = this.lineWidths = [\n            0\n        ];\n        const lineHeight = itemHeight + padding;\n        let totalHeight = titleHeight;\n        ctx.textAlign = 'left';\n        ctx.textBaseline = 'middle';\n        let row = -1;\n        let top = -lineHeight;\n        this.legendItems.forEach((legendItem, i)=>{\n            const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width;\n            if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {\n                totalHeight += lineHeight;\n                lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;\n                top += lineHeight;\n                row++;\n            }\n            hitboxes[i] = {\n                left: 0,\n                top,\n                row,\n                width: itemWidth,\n                height: itemHeight\n            };\n            lineWidths[lineWidths.length - 1] += itemWidth + padding;\n        });\n        return totalHeight;\n    }\n    _fitCols(titleHeight, labelFont, boxWidth, _itemHeight) {\n        const { ctx , maxHeight , options: { labels: { padding  }  }  } = this;\n        const hitboxes = this.legendHitBoxes = [];\n        const columnSizes = this.columnSizes = [];\n        const heightLimit = maxHeight - titleHeight;\n        let totalWidth = padding;\n        let currentColWidth = 0;\n        let currentColHeight = 0;\n        let left = 0;\n        let col = 0;\n        this.legendItems.forEach((legendItem, i)=>{\n            const { itemWidth , itemHeight  } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight);\n            if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {\n                totalWidth += currentColWidth + padding;\n                columnSizes.push({\n                    width: currentColWidth,\n                    height: currentColHeight\n                });\n                left += currentColWidth + padding;\n                col++;\n                currentColWidth = currentColHeight = 0;\n            }\n            hitboxes[i] = {\n                left,\n                top: currentColHeight,\n                col,\n                width: itemWidth,\n                height: itemHeight\n            };\n            currentColWidth = Math.max(currentColWidth, itemWidth);\n            currentColHeight += itemHeight + padding;\n        });\n        totalWidth += currentColWidth;\n        columnSizes.push({\n            width: currentColWidth,\n            height: currentColHeight\n        });\n        return totalWidth;\n    }\n    adjustHitBoxes() {\n        if (!this.options.display) {\n            return;\n        }\n        const titleHeight = this._computeTitleHeight();\n        const { legendHitBoxes: hitboxes , options: { align , labels: { padding  } , rtl  }  } = this;\n        const rtlHelper = getRtlAdapter(rtl, this.left, this.width);\n        if (this.isHorizontal()) {\n            let row = 0;\n            let left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);\n            for (const hitbox of hitboxes){\n                if (row !== hitbox.row) {\n                    row = hitbox.row;\n                    left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);\n                }\n                hitbox.top += this.top + titleHeight + padding;\n                hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);\n                left += hitbox.width + padding;\n            }\n        } else {\n            let col = 0;\n            let top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);\n            for (const hitbox of hitboxes){\n                if (hitbox.col !== col) {\n                    col = hitbox.col;\n                    top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);\n                }\n                hitbox.top = top;\n                hitbox.left += this.left + padding;\n                hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);\n                top += hitbox.height + padding;\n            }\n        }\n    }\n    isHorizontal() {\n        return this.options.position === 'top' || this.options.position === 'bottom';\n    }\n    draw() {\n        if (this.options.display) {\n            const ctx = this.ctx;\n            clipArea(ctx, this);\n            this._draw();\n            unclipArea(ctx);\n        }\n    }\n _draw() {\n        const { options: opts , columnSizes , lineWidths , ctx  } = this;\n        const { align , labels: labelOpts  } = opts;\n        const defaultColor = defaults.color;\n        const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);\n        const labelFont = toFont(labelOpts.font);\n        const { padding  } = labelOpts;\n        const fontSize = labelFont.size;\n        const halfFontSize = fontSize / 2;\n        let cursor;\n        this.drawTitle();\n        ctx.textAlign = rtlHelper.textAlign('left');\n        ctx.textBaseline = 'middle';\n        ctx.lineWidth = 0.5;\n        ctx.font = labelFont.string;\n        const { boxWidth , boxHeight , itemHeight  } = getBoxSize(labelOpts, fontSize);\n        const drawLegendBox = function(x, y, legendItem) {\n            if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {\n                return;\n            }\n            ctx.save();\n            const lineWidth = valueOrDefault(legendItem.lineWidth, 1);\n            ctx.fillStyle = valueOrDefault(legendItem.fillStyle, defaultColor);\n            ctx.lineCap = valueOrDefault(legendItem.lineCap, 'butt');\n            ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, 0);\n            ctx.lineJoin = valueOrDefault(legendItem.lineJoin, 'miter');\n            ctx.lineWidth = lineWidth;\n            ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, defaultColor);\n            ctx.setLineDash(valueOrDefault(legendItem.lineDash, []));\n            if (labelOpts.usePointStyle) {\n                const drawOptions = {\n                    radius: boxHeight * Math.SQRT2 / 2,\n                    pointStyle: legendItem.pointStyle,\n                    rotation: legendItem.rotation,\n                    borderWidth: lineWidth\n                };\n                const centerX = rtlHelper.xPlus(x, boxWidth / 2);\n                const centerY = y + halfFontSize;\n                drawPointLegend(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth);\n            } else {\n                const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);\n                const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);\n                const borderRadius = toTRBLCorners(legendItem.borderRadius);\n                ctx.beginPath();\n                if (Object.values(borderRadius).some((v)=>v !== 0)) {\n                    addRoundedRectPath(ctx, {\n                        x: xBoxLeft,\n                        y: yBoxTop,\n                        w: boxWidth,\n                        h: boxHeight,\n                        radius: borderRadius\n                    });\n                } else {\n                    ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);\n                }\n                ctx.fill();\n                if (lineWidth !== 0) {\n                    ctx.stroke();\n                }\n            }\n            ctx.restore();\n        };\n        const fillText = function(x, y, legendItem) {\n            renderText(ctx, legendItem.text, x, y + itemHeight / 2, labelFont, {\n                strikethrough: legendItem.hidden,\n                textAlign: rtlHelper.textAlign(legendItem.textAlign)\n            });\n        };\n        const isHorizontal = this.isHorizontal();\n        const titleHeight = this._computeTitleHeight();\n        if (isHorizontal) {\n            cursor = {\n                x: _alignStartEnd(align, this.left + padding, this.right - lineWidths[0]),\n                y: this.top + padding + titleHeight,\n                line: 0\n            };\n        } else {\n            cursor = {\n                x: this.left + padding,\n                y: _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),\n                line: 0\n            };\n        }\n        overrideTextDirection(this.ctx, opts.textDirection);\n        const lineHeight = itemHeight + padding;\n        this.legendItems.forEach((legendItem, i)=>{\n            ctx.strokeStyle = legendItem.fontColor;\n            ctx.fillStyle = legendItem.fontColor;\n            const textWidth = ctx.measureText(legendItem.text).width;\n            const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));\n            const width = boxWidth + halfFontSize + textWidth;\n            let x = cursor.x;\n            let y = cursor.y;\n            rtlHelper.setWidth(this.width);\n            if (isHorizontal) {\n                if (i > 0 && x + width + padding > this.right) {\n                    y = cursor.y += lineHeight;\n                    cursor.line++;\n                    x = cursor.x = _alignStartEnd(align, this.left + padding, this.right - lineWidths[cursor.line]);\n                }\n            } else if (i > 0 && y + lineHeight > this.bottom) {\n                x = cursor.x = x + columnSizes[cursor.line].width + padding;\n                cursor.line++;\n                y = cursor.y = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);\n            }\n            const realX = rtlHelper.x(x);\n            drawLegendBox(realX, y, legendItem);\n            x = _textX(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);\n            fillText(rtlHelper.x(x), y, legendItem);\n            if (isHorizontal) {\n                cursor.x += width + padding;\n            } else if (typeof legendItem.text !== 'string') {\n                const fontLineHeight = labelFont.lineHeight;\n                cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight) + padding;\n            } else {\n                cursor.y += lineHeight;\n            }\n        });\n        restoreTextDirection(this.ctx, opts.textDirection);\n    }\n drawTitle() {\n        const opts = this.options;\n        const titleOpts = opts.title;\n        const titleFont = toFont(titleOpts.font);\n        const titlePadding = toPadding(titleOpts.padding);\n        if (!titleOpts.display) {\n            return;\n        }\n        const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);\n        const ctx = this.ctx;\n        const position = titleOpts.position;\n        const halfFontSize = titleFont.size / 2;\n        const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;\n        let y;\n        let left = this.left;\n        let maxWidth = this.width;\n        if (this.isHorizontal()) {\n            maxWidth = Math.max(...this.lineWidths);\n            y = this.top + topPaddingPlusHalfFontSize;\n            left = _alignStartEnd(opts.align, left, this.right - maxWidth);\n        } else {\n            const maxHeight = this.columnSizes.reduce((acc, size)=>Math.max(acc, size.height), 0);\n            y = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());\n        }\n        const x = _alignStartEnd(position, left, left + maxWidth);\n        ctx.textAlign = rtlHelper.textAlign(_toLeftRightCenter(position));\n        ctx.textBaseline = 'middle';\n        ctx.strokeStyle = titleOpts.color;\n        ctx.fillStyle = titleOpts.color;\n        ctx.font = titleFont.string;\n        renderText(ctx, titleOpts.text, x, y, titleFont);\n    }\n _computeTitleHeight() {\n        const titleOpts = this.options.title;\n        const titleFont = toFont(titleOpts.font);\n        const titlePadding = toPadding(titleOpts.padding);\n        return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;\n    }\n _getLegendItemAt(x, y) {\n        let i, hitBox, lh;\n        if (_isBetween(x, this.left, this.right) && _isBetween(y, this.top, this.bottom)) {\n            lh = this.legendHitBoxes;\n            for(i = 0; i < lh.length; ++i){\n                hitBox = lh[i];\n                if (_isBetween(x, hitBox.left, hitBox.left + hitBox.width) && _isBetween(y, hitBox.top, hitBox.top + hitBox.height)) {\n                    return this.legendItems[i];\n                }\n            }\n        }\n        return null;\n    }\n handleEvent(e) {\n        const opts = this.options;\n        if (!isListened(e.type, opts)) {\n            return;\n        }\n        const hoveredItem = this._getLegendItemAt(e.x, e.y);\n        if (e.type === 'mousemove' || e.type === 'mouseout') {\n            const previous = this._hoveredItem;\n            const sameItem = itemsEqual(previous, hoveredItem);\n            if (previous && !sameItem) {\n                callback(opts.onLeave, [\n                    e,\n                    previous,\n                    this\n                ], this);\n            }\n            this._hoveredItem = hoveredItem;\n            if (hoveredItem && !sameItem) {\n                callback(opts.onHover, [\n                    e,\n                    hoveredItem,\n                    this\n                ], this);\n            }\n        } else if (hoveredItem) {\n            callback(opts.onClick, [\n                e,\n                hoveredItem,\n                this\n            ], this);\n        }\n    }\n}\nfunction calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) {\n    const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx);\n    const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight);\n    return {\n        itemWidth,\n        itemHeight\n    };\n}\nfunction calculateItemWidth(legendItem, boxWidth, labelFont, ctx) {\n    let legendItemText = legendItem.text;\n    if (legendItemText && typeof legendItemText !== 'string') {\n        legendItemText = legendItemText.reduce((a, b)=>a.length > b.length ? a : b);\n    }\n    return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width;\n}\nfunction calculateItemHeight(_itemHeight, legendItem, fontLineHeight) {\n    let itemHeight = _itemHeight;\n    if (typeof legendItem.text !== 'string') {\n        itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight);\n    }\n    return itemHeight;\n}\nfunction calculateLegendItemHeight(legendItem, fontLineHeight) {\n    const labelHeight = legendItem.text ? legendItem.text.length : 0;\n    return fontLineHeight * labelHeight;\n}\nfunction isListened(type, opts) {\n    if ((type === 'mousemove' || type === 'mouseout') && (opts.onHover || opts.onLeave)) {\n        return true;\n    }\n    if (opts.onClick && (type === 'click' || type === 'mouseup')) {\n        return true;\n    }\n    return false;\n}\nvar plugin_legend = {\n    id: 'legend',\n _element: Legend,\n    start (chart, _args, options) {\n        const legend = chart.legend = new Legend({\n            ctx: chart.ctx,\n            options,\n            chart\n        });\n        layouts.configure(chart, legend, options);\n        layouts.addBox(chart, legend);\n    },\n    stop (chart) {\n        layouts.removeBox(chart, chart.legend);\n        delete chart.legend;\n    },\n    beforeUpdate (chart, _args, options) {\n        const legend = chart.legend;\n        layouts.configure(chart, legend, options);\n        legend.options = options;\n    },\n    afterUpdate (chart) {\n        const legend = chart.legend;\n        legend.buildLabels();\n        legend.adjustHitBoxes();\n    },\n    afterEvent (chart, args) {\n        if (!args.replay) {\n            chart.legend.handleEvent(args.event);\n        }\n    },\n    defaults: {\n        display: true,\n        position: 'top',\n        align: 'center',\n        fullSize: true,\n        reverse: false,\n        weight: 1000,\n        onClick (e, legendItem, legend) {\n            const index = legendItem.datasetIndex;\n            const ci = legend.chart;\n            if (ci.isDatasetVisible(index)) {\n                ci.hide(index);\n                legendItem.hidden = true;\n            } else {\n                ci.show(index);\n                legendItem.hidden = false;\n            }\n        },\n        onHover: null,\n        onLeave: null,\n        labels: {\n            color: (ctx)=>ctx.chart.options.color,\n            boxWidth: 40,\n            padding: 10,\n            generateLabels (chart) {\n                const datasets = chart.data.datasets;\n                const { labels: { usePointStyle , pointStyle , textAlign , color , useBorderRadius , borderRadius  }  } = chart.legend.options;\n                return chart._getSortedDatasetMetas().map((meta)=>{\n                    const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);\n                    const borderWidth = toPadding(style.borderWidth);\n                    return {\n                        text: datasets[meta.index].label,\n                        fillStyle: style.backgroundColor,\n                        fontColor: color,\n                        hidden: !meta.visible,\n                        lineCap: style.borderCapStyle,\n                        lineDash: style.borderDash,\n                        lineDashOffset: style.borderDashOffset,\n                        lineJoin: style.borderJoinStyle,\n                        lineWidth: (borderWidth.width + borderWidth.height) / 4,\n                        strokeStyle: style.borderColor,\n                        pointStyle: pointStyle || style.pointStyle,\n                        rotation: style.rotation,\n                        textAlign: textAlign || style.textAlign,\n                        borderRadius: useBorderRadius && (borderRadius || style.borderRadius),\n                        datasetIndex: meta.index\n                    };\n                }, this);\n            }\n        },\n        title: {\n            color: (ctx)=>ctx.chart.options.color,\n            display: false,\n            position: 'center',\n            text: ''\n        }\n    },\n    descriptors: {\n        _scriptable: (name)=>!name.startsWith('on'),\n        labels: {\n            _scriptable: (name)=>![\n                    'generateLabels',\n                    'filter',\n                    'sort'\n                ].includes(name)\n        }\n    }\n};\n\nclass Title extends Element {\n constructor(config){\n        super();\n        this.chart = config.chart;\n        this.options = config.options;\n        this.ctx = config.ctx;\n        this._padding = undefined;\n        this.top = undefined;\n        this.bottom = undefined;\n        this.left = undefined;\n        this.right = undefined;\n        this.width = undefined;\n        this.height = undefined;\n        this.position = undefined;\n        this.weight = undefined;\n        this.fullSize = undefined;\n    }\n    update(maxWidth, maxHeight) {\n        const opts = this.options;\n        this.left = 0;\n        this.top = 0;\n        if (!opts.display) {\n            this.width = this.height = this.right = this.bottom = 0;\n            return;\n        }\n        this.width = this.right = maxWidth;\n        this.height = this.bottom = maxHeight;\n        const lineCount = isArray(opts.text) ? opts.text.length : 1;\n        this._padding = toPadding(opts.padding);\n        const textSize = lineCount * toFont(opts.font).lineHeight + this._padding.height;\n        if (this.isHorizontal()) {\n            this.height = textSize;\n        } else {\n            this.width = textSize;\n        }\n    }\n    isHorizontal() {\n        const pos = this.options.position;\n        return pos === 'top' || pos === 'bottom';\n    }\n    _drawArgs(offset) {\n        const { top , left , bottom , right , options  } = this;\n        const align = options.align;\n        let rotation = 0;\n        let maxWidth, titleX, titleY;\n        if (this.isHorizontal()) {\n            titleX = _alignStartEnd(align, left, right);\n            titleY = top + offset;\n            maxWidth = right - left;\n        } else {\n            if (options.position === 'left') {\n                titleX = left + offset;\n                titleY = _alignStartEnd(align, bottom, top);\n                rotation = PI * -0.5;\n            } else {\n                titleX = right - offset;\n                titleY = _alignStartEnd(align, top, bottom);\n                rotation = PI * 0.5;\n            }\n            maxWidth = bottom - top;\n        }\n        return {\n            titleX,\n            titleY,\n            maxWidth,\n            rotation\n        };\n    }\n    draw() {\n        const ctx = this.ctx;\n        const opts = this.options;\n        if (!opts.display) {\n            return;\n        }\n        const fontOpts = toFont(opts.font);\n        const lineHeight = fontOpts.lineHeight;\n        const offset = lineHeight / 2 + this._padding.top;\n        const { titleX , titleY , maxWidth , rotation  } = this._drawArgs(offset);\n        renderText(ctx, opts.text, 0, 0, fontOpts, {\n            color: opts.color,\n            maxWidth,\n            rotation,\n            textAlign: _toLeftRightCenter(opts.align),\n            textBaseline: 'middle',\n            translation: [\n                titleX,\n                titleY\n            ]\n        });\n    }\n}\nfunction createTitle(chart, titleOpts) {\n    const title = new Title({\n        ctx: chart.ctx,\n        options: titleOpts,\n        chart\n    });\n    layouts.configure(chart, title, titleOpts);\n    layouts.addBox(chart, title);\n    chart.titleBlock = title;\n}\nvar plugin_title = {\n    id: 'title',\n _element: Title,\n    start (chart, _args, options) {\n        createTitle(chart, options);\n    },\n    stop (chart) {\n        const titleBlock = chart.titleBlock;\n        layouts.removeBox(chart, titleBlock);\n        delete chart.titleBlock;\n    },\n    beforeUpdate (chart, _args, options) {\n        const title = chart.titleBlock;\n        layouts.configure(chart, title, options);\n        title.options = options;\n    },\n    defaults: {\n        align: 'center',\n        display: false,\n        font: {\n            weight: 'bold'\n        },\n        fullSize: true,\n        padding: 10,\n        position: 'top',\n        text: '',\n        weight: 2000\n    },\n    defaultRoutes: {\n        color: 'color'\n    },\n    descriptors: {\n        _scriptable: true,\n        _indexable: false\n    }\n};\n\nconst map = new WeakMap();\nvar plugin_subtitle = {\n    id: 'subtitle',\n    start (chart, _args, options) {\n        const title = new Title({\n            ctx: chart.ctx,\n            options,\n            chart\n        });\n        layouts.configure(chart, title, options);\n        layouts.addBox(chart, title);\n        map.set(chart, title);\n    },\n    stop (chart) {\n        layouts.removeBox(chart, map.get(chart));\n        map.delete(chart);\n    },\n    beforeUpdate (chart, _args, options) {\n        const title = map.get(chart);\n        layouts.configure(chart, title, options);\n        title.options = options;\n    },\n    defaults: {\n        align: 'center',\n        display: false,\n        font: {\n            weight: 'normal'\n        },\n        fullSize: true,\n        padding: 0,\n        position: 'top',\n        text: '',\n        weight: 1500\n    },\n    defaultRoutes: {\n        color: 'color'\n    },\n    descriptors: {\n        _scriptable: true,\n        _indexable: false\n    }\n};\n\nconst positioners = {\n average (items) {\n        if (!items.length) {\n            return false;\n        }\n        let i, len;\n        let xSet = new Set();\n        let y = 0;\n        let count = 0;\n        for(i = 0, len = items.length; i < len; ++i){\n            const el = items[i].element;\n            if (el && el.hasValue()) {\n                const pos = el.tooltipPosition();\n                xSet.add(pos.x);\n                y += pos.y;\n                ++count;\n            }\n        }\n        const xAverage = [\n            ...xSet\n        ].reduce((a, b)=>a + b) / xSet.size;\n        return {\n            x: xAverage,\n            y: y / count\n        };\n    },\n nearest (items, eventPosition) {\n        if (!items.length) {\n            return false;\n        }\n        let x = eventPosition.x;\n        let y = eventPosition.y;\n        let minDistance = Number.POSITIVE_INFINITY;\n        let i, len, nearestElement;\n        for(i = 0, len = items.length; i < len; ++i){\n            const el = items[i].element;\n            if (el && el.hasValue()) {\n                const center = el.getCenterPoint();\n                const d = distanceBetweenPoints(eventPosition, center);\n                if (d < minDistance) {\n                    minDistance = d;\n                    nearestElement = el;\n                }\n            }\n        }\n        if (nearestElement) {\n            const tp = nearestElement.tooltipPosition();\n            x = tp.x;\n            y = tp.y;\n        }\n        return {\n            x,\n            y\n        };\n    }\n};\nfunction pushOrConcat(base, toPush) {\n    if (toPush) {\n        if (isArray(toPush)) {\n            Array.prototype.push.apply(base, toPush);\n        } else {\n            base.push(toPush);\n        }\n    }\n    return base;\n}\n function splitNewlines(str) {\n    if ((typeof str === 'string' || str instanceof String) && str.indexOf('\\n') > -1) {\n        return str.split('\\n');\n    }\n    return str;\n}\n function createTooltipItem(chart, item) {\n    const { element , datasetIndex , index  } = item;\n    const controller = chart.getDatasetMeta(datasetIndex).controller;\n    const { label , value  } = controller.getLabelAndValue(index);\n    return {\n        chart,\n        label,\n        parsed: controller.getParsed(index),\n        raw: chart.data.datasets[datasetIndex].data[index],\n        formattedValue: value,\n        dataset: controller.getDataset(),\n        dataIndex: index,\n        datasetIndex,\n        element\n    };\n}\n function getTooltipSize(tooltip, options) {\n    const ctx = tooltip.chart.ctx;\n    const { body , footer , title  } = tooltip;\n    const { boxWidth , boxHeight  } = options;\n    const bodyFont = toFont(options.bodyFont);\n    const titleFont = toFont(options.titleFont);\n    const footerFont = toFont(options.footerFont);\n    const titleLineCount = title.length;\n    const footerLineCount = footer.length;\n    const bodyLineItemCount = body.length;\n    const padding = toPadding(options.padding);\n    let height = padding.height;\n    let width = 0;\n    let combinedBodyLength = body.reduce((count, bodyItem)=>count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);\n    combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;\n    if (titleLineCount) {\n        height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom;\n    }\n    if (combinedBodyLength) {\n        const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;\n        height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing;\n    }\n    if (footerLineCount) {\n        height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing;\n    }\n    let widthPadding = 0;\n    const maxLineWidth = function(line) {\n        width = Math.max(width, ctx.measureText(line).width + widthPadding);\n    };\n    ctx.save();\n    ctx.font = titleFont.string;\n    each(tooltip.title, maxLineWidth);\n    ctx.font = bodyFont.string;\n    each(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);\n    widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0;\n    each(body, (bodyItem)=>{\n        each(bodyItem.before, maxLineWidth);\n        each(bodyItem.lines, maxLineWidth);\n        each(bodyItem.after, maxLineWidth);\n    });\n    widthPadding = 0;\n    ctx.font = footerFont.string;\n    each(tooltip.footer, maxLineWidth);\n    ctx.restore();\n    width += padding.width;\n    return {\n        width,\n        height\n    };\n}\nfunction determineYAlign(chart, size) {\n    const { y , height  } = size;\n    if (y < height / 2) {\n        return 'top';\n    } else if (y > chart.height - height / 2) {\n        return 'bottom';\n    }\n    return 'center';\n}\nfunction doesNotFitWithAlign(xAlign, chart, options, size) {\n    const { x , width  } = size;\n    const caret = options.caretSize + options.caretPadding;\n    if (xAlign === 'left' && x + width + caret > chart.width) {\n        return true;\n    }\n    if (xAlign === 'right' && x - width - caret < 0) {\n        return true;\n    }\n}\nfunction determineXAlign(chart, options, size, yAlign) {\n    const { x , width  } = size;\n    const { width: chartWidth , chartArea: { left , right  }  } = chart;\n    let xAlign = 'center';\n    if (yAlign === 'center') {\n        xAlign = x <= (left + right) / 2 ? 'left' : 'right';\n    } else if (x <= width / 2) {\n        xAlign = 'left';\n    } else if (x >= chartWidth - width / 2) {\n        xAlign = 'right';\n    }\n    if (doesNotFitWithAlign(xAlign, chart, options, size)) {\n        xAlign = 'center';\n    }\n    return xAlign;\n}\n function determineAlignment(chart, options, size) {\n    const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size);\n    return {\n        xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign),\n        yAlign\n    };\n}\nfunction alignX(size, xAlign) {\n    let { x , width  } = size;\n    if (xAlign === 'right') {\n        x -= width;\n    } else if (xAlign === 'center') {\n        x -= width / 2;\n    }\n    return x;\n}\nfunction alignY(size, yAlign, paddingAndSize) {\n    let { y , height  } = size;\n    if (yAlign === 'top') {\n        y += paddingAndSize;\n    } else if (yAlign === 'bottom') {\n        y -= height + paddingAndSize;\n    } else {\n        y -= height / 2;\n    }\n    return y;\n}\n function getBackgroundPoint(options, size, alignment, chart) {\n    const { caretSize , caretPadding , cornerRadius  } = options;\n    const { xAlign , yAlign  } = alignment;\n    const paddingAndSize = caretSize + caretPadding;\n    const { topLeft , topRight , bottomLeft , bottomRight  } = toTRBLCorners(cornerRadius);\n    let x = alignX(size, xAlign);\n    const y = alignY(size, yAlign, paddingAndSize);\n    if (yAlign === 'center') {\n        if (xAlign === 'left') {\n            x += paddingAndSize;\n        } else if (xAlign === 'right') {\n            x -= paddingAndSize;\n        }\n    } else if (xAlign === 'left') {\n        x -= Math.max(topLeft, bottomLeft) + caretSize;\n    } else if (xAlign === 'right') {\n        x += Math.max(topRight, bottomRight) + caretSize;\n    }\n    return {\n        x: _limitValue(x, 0, chart.width - size.width),\n        y: _limitValue(y, 0, chart.height - size.height)\n    };\n}\nfunction getAlignedX(tooltip, align, options) {\n    const padding = toPadding(options.padding);\n    return align === 'center' ? tooltip.x + tooltip.width / 2 : align === 'right' ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left;\n}\n function getBeforeAfterBodyLines(callback) {\n    return pushOrConcat([], splitNewlines(callback));\n}\nfunction createTooltipContext(parent, tooltip, tooltipItems) {\n    return createContext(parent, {\n        tooltip,\n        tooltipItems,\n        type: 'tooltip'\n    });\n}\nfunction overrideCallbacks(callbacks, context) {\n    const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;\n    return override ? callbacks.override(override) : callbacks;\n}\nconst defaultCallbacks = {\n    beforeTitle: noop,\n    title (tooltipItems) {\n        if (tooltipItems.length > 0) {\n            const item = tooltipItems[0];\n            const labels = item.chart.data.labels;\n            const labelCount = labels ? labels.length : 0;\n            if (this && this.options && this.options.mode === 'dataset') {\n                return item.dataset.label || '';\n            } else if (item.label) {\n                return item.label;\n            } else if (labelCount > 0 && item.dataIndex < labelCount) {\n                return labels[item.dataIndex];\n            }\n        }\n        return '';\n    },\n    afterTitle: noop,\n    beforeBody: noop,\n    beforeLabel: noop,\n    label (tooltipItem) {\n        if (this && this.options && this.options.mode === 'dataset') {\n            return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue;\n        }\n        let label = tooltipItem.dataset.label || '';\n        if (label) {\n            label += ': ';\n        }\n        const value = tooltipItem.formattedValue;\n        if (!isNullOrUndef(value)) {\n            label += value;\n        }\n        return label;\n    },\n    labelColor (tooltipItem) {\n        const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);\n        const options = meta.controller.getStyle(tooltipItem.dataIndex);\n        return {\n            borderColor: options.borderColor,\n            backgroundColor: options.backgroundColor,\n            borderWidth: options.borderWidth,\n            borderDash: options.borderDash,\n            borderDashOffset: options.borderDashOffset,\n            borderRadius: 0\n        };\n    },\n    labelTextColor () {\n        return this.options.bodyColor;\n    },\n    labelPointStyle (tooltipItem) {\n        const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);\n        const options = meta.controller.getStyle(tooltipItem.dataIndex);\n        return {\n            pointStyle: options.pointStyle,\n            rotation: options.rotation\n        };\n    },\n    afterLabel: noop,\n    afterBody: noop,\n    beforeFooter: noop,\n    footer: noop,\n    afterFooter: noop\n};\n function invokeCallbackWithFallback(callbacks, name, ctx, arg) {\n    const result = callbacks[name].call(ctx, arg);\n    if (typeof result === 'undefined') {\n        return defaultCallbacks[name].call(ctx, arg);\n    }\n    return result;\n}\nclass Tooltip extends Element {\n static positioners = positioners;\n    constructor(config){\n        super();\n        this.opacity = 0;\n        this._active = [];\n        this._eventPosition = undefined;\n        this._size = undefined;\n        this._cachedAnimations = undefined;\n        this._tooltipItems = [];\n        this.$animations = undefined;\n        this.$context = undefined;\n        this.chart = config.chart;\n        this.options = config.options;\n        this.dataPoints = undefined;\n        this.title = undefined;\n        this.beforeBody = undefined;\n        this.body = undefined;\n        this.afterBody = undefined;\n        this.footer = undefined;\n        this.xAlign = undefined;\n        this.yAlign = undefined;\n        this.x = undefined;\n        this.y = undefined;\n        this.height = undefined;\n        this.width = undefined;\n        this.caretX = undefined;\n        this.caretY = undefined;\n        this.labelColors = undefined;\n        this.labelPointStyles = undefined;\n        this.labelTextColors = undefined;\n    }\n    initialize(options) {\n        this.options = options;\n        this._cachedAnimations = undefined;\n        this.$context = undefined;\n    }\n _resolveAnimations() {\n        const cached = this._cachedAnimations;\n        if (cached) {\n            return cached;\n        }\n        const chart = this.chart;\n        const options = this.options.setContext(this.getContext());\n        const opts = options.enabled && chart.options.animation && options.animations;\n        const animations = new Animations(this.chart, opts);\n        if (opts._cacheable) {\n            this._cachedAnimations = Object.freeze(animations);\n        }\n        return animations;\n    }\n getContext() {\n        return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems));\n    }\n    getTitle(context, options) {\n        const { callbacks  } = options;\n        const beforeTitle = invokeCallbackWithFallback(callbacks, 'beforeTitle', this, context);\n        const title = invokeCallbackWithFallback(callbacks, 'title', this, context);\n        const afterTitle = invokeCallbackWithFallback(callbacks, 'afterTitle', this, context);\n        let lines = [];\n        lines = pushOrConcat(lines, splitNewlines(beforeTitle));\n        lines = pushOrConcat(lines, splitNewlines(title));\n        lines = pushOrConcat(lines, splitNewlines(afterTitle));\n        return lines;\n    }\n    getBeforeBody(tooltipItems, options) {\n        return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'beforeBody', this, tooltipItems));\n    }\n    getBody(tooltipItems, options) {\n        const { callbacks  } = options;\n        const bodyItems = [];\n        each(tooltipItems, (context)=>{\n            const bodyItem = {\n                before: [],\n                lines: [],\n                after: []\n            };\n            const scoped = overrideCallbacks(callbacks, context);\n            pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, 'beforeLabel', this, context)));\n            pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, 'label', this, context));\n            pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, 'afterLabel', this, context)));\n            bodyItems.push(bodyItem);\n        });\n        return bodyItems;\n    }\n    getAfterBody(tooltipItems, options) {\n        return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, 'afterBody', this, tooltipItems));\n    }\n    getFooter(tooltipItems, options) {\n        const { callbacks  } = options;\n        const beforeFooter = invokeCallbackWithFallback(callbacks, 'beforeFooter', this, tooltipItems);\n        const footer = invokeCallbackWithFallback(callbacks, 'footer', this, tooltipItems);\n        const afterFooter = invokeCallbackWithFallback(callbacks, 'afterFooter', this, tooltipItems);\n        let lines = [];\n        lines = pushOrConcat(lines, splitNewlines(beforeFooter));\n        lines = pushOrConcat(lines, splitNewlines(footer));\n        lines = pushOrConcat(lines, splitNewlines(afterFooter));\n        return lines;\n    }\n _createItems(options) {\n        const active = this._active;\n        const data = this.chart.data;\n        const labelColors = [];\n        const labelPointStyles = [];\n        const labelTextColors = [];\n        let tooltipItems = [];\n        let i, len;\n        for(i = 0, len = active.length; i < len; ++i){\n            tooltipItems.push(createTooltipItem(this.chart, active[i]));\n        }\n        if (options.filter) {\n            tooltipItems = tooltipItems.filter((element, index, array)=>options.filter(element, index, array, data));\n        }\n        if (options.itemSort) {\n            tooltipItems = tooltipItems.sort((a, b)=>options.itemSort(a, b, data));\n        }\n        each(tooltipItems, (context)=>{\n            const scoped = overrideCallbacks(options.callbacks, context);\n            labelColors.push(invokeCallbackWithFallback(scoped, 'labelColor', this, context));\n            labelPointStyles.push(invokeCallbackWithFallback(scoped, 'labelPointStyle', this, context));\n            labelTextColors.push(invokeCallbackWithFallback(scoped, 'labelTextColor', this, context));\n        });\n        this.labelColors = labelColors;\n        this.labelPointStyles = labelPointStyles;\n        this.labelTextColors = labelTextColors;\n        this.dataPoints = tooltipItems;\n        return tooltipItems;\n    }\n    update(changed, replay) {\n        const options = this.options.setContext(this.getContext());\n        const active = this._active;\n        let properties;\n        let tooltipItems = [];\n        if (!active.length) {\n            if (this.opacity !== 0) {\n                properties = {\n                    opacity: 0\n                };\n            }\n        } else {\n            const position = positioners[options.position].call(this, active, this._eventPosition);\n            tooltipItems = this._createItems(options);\n            this.title = this.getTitle(tooltipItems, options);\n            this.beforeBody = this.getBeforeBody(tooltipItems, options);\n            this.body = this.getBody(tooltipItems, options);\n            this.afterBody = this.getAfterBody(tooltipItems, options);\n            this.footer = this.getFooter(tooltipItems, options);\n            const size = this._size = getTooltipSize(this, options);\n            const positionAndSize = Object.assign({}, position, size);\n            const alignment = determineAlignment(this.chart, options, positionAndSize);\n            const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart);\n            this.xAlign = alignment.xAlign;\n            this.yAlign = alignment.yAlign;\n            properties = {\n                opacity: 1,\n                x: backgroundPoint.x,\n                y: backgroundPoint.y,\n                width: size.width,\n                height: size.height,\n                caretX: position.x,\n                caretY: position.y\n            };\n        }\n        this._tooltipItems = tooltipItems;\n        this.$context = undefined;\n        if (properties) {\n            this._resolveAnimations().update(this, properties);\n        }\n        if (changed && options.external) {\n            options.external.call(this, {\n                chart: this.chart,\n                tooltip: this,\n                replay\n            });\n        }\n    }\n    drawCaret(tooltipPoint, ctx, size, options) {\n        const caretPosition = this.getCaretPosition(tooltipPoint, size, options);\n        ctx.lineTo(caretPosition.x1, caretPosition.y1);\n        ctx.lineTo(caretPosition.x2, caretPosition.y2);\n        ctx.lineTo(caretPosition.x3, caretPosition.y3);\n    }\n    getCaretPosition(tooltipPoint, size, options) {\n        const { xAlign , yAlign  } = this;\n        const { caretSize , cornerRadius  } = options;\n        const { topLeft , topRight , bottomLeft , bottomRight  } = toTRBLCorners(cornerRadius);\n        const { x: ptX , y: ptY  } = tooltipPoint;\n        const { width , height  } = size;\n        let x1, x2, x3, y1, y2, y3;\n        if (yAlign === 'center') {\n            y2 = ptY + height / 2;\n            if (xAlign === 'left') {\n                x1 = ptX;\n                x2 = x1 - caretSize;\n                y1 = y2 + caretSize;\n                y3 = y2 - caretSize;\n            } else {\n                x1 = ptX + width;\n                x2 = x1 + caretSize;\n                y1 = y2 - caretSize;\n                y3 = y2 + caretSize;\n            }\n            x3 = x1;\n        } else {\n            if (xAlign === 'left') {\n                x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize;\n            } else if (xAlign === 'right') {\n                x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;\n            } else {\n                x2 = this.caretX;\n            }\n            if (yAlign === 'top') {\n                y1 = ptY;\n                y2 = y1 - caretSize;\n                x1 = x2 - caretSize;\n                x3 = x2 + caretSize;\n            } else {\n                y1 = ptY + height;\n                y2 = y1 + caretSize;\n                x1 = x2 + caretSize;\n                x3 = x2 - caretSize;\n            }\n            y3 = y1;\n        }\n        return {\n            x1,\n            x2,\n            x3,\n            y1,\n            y2,\n            y3\n        };\n    }\n    drawTitle(pt, ctx, options) {\n        const title = this.title;\n        const length = title.length;\n        let titleFont, titleSpacing, i;\n        if (length) {\n            const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);\n            pt.x = getAlignedX(this, options.titleAlign, options);\n            ctx.textAlign = rtlHelper.textAlign(options.titleAlign);\n            ctx.textBaseline = 'middle';\n            titleFont = toFont(options.titleFont);\n            titleSpacing = options.titleSpacing;\n            ctx.fillStyle = options.titleColor;\n            ctx.font = titleFont.string;\n            for(i = 0; i < length; ++i){\n                ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);\n                pt.y += titleFont.lineHeight + titleSpacing;\n                if (i + 1 === length) {\n                    pt.y += options.titleMarginBottom - titleSpacing;\n                }\n            }\n        }\n    }\n _drawColorBox(ctx, pt, i, rtlHelper, options) {\n        const labelColor = this.labelColors[i];\n        const labelPointStyle = this.labelPointStyles[i];\n        const { boxHeight , boxWidth  } = options;\n        const bodyFont = toFont(options.bodyFont);\n        const colorX = getAlignedX(this, 'left', options);\n        const rtlColorX = rtlHelper.x(colorX);\n        const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;\n        const colorY = pt.y + yOffSet;\n        if (options.usePointStyle) {\n            const drawOptions = {\n                radius: Math.min(boxWidth, boxHeight) / 2,\n                pointStyle: labelPointStyle.pointStyle,\n                rotation: labelPointStyle.rotation,\n                borderWidth: 1\n            };\n            const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;\n            const centerY = colorY + boxHeight / 2;\n            ctx.strokeStyle = options.multiKeyBackground;\n            ctx.fillStyle = options.multiKeyBackground;\n            drawPoint(ctx, drawOptions, centerX, centerY);\n            ctx.strokeStyle = labelColor.borderColor;\n            ctx.fillStyle = labelColor.backgroundColor;\n            drawPoint(ctx, drawOptions, centerX, centerY);\n        } else {\n            ctx.lineWidth = isObject(labelColor.borderWidth) ? Math.max(...Object.values(labelColor.borderWidth)) : labelColor.borderWidth || 1;\n            ctx.strokeStyle = labelColor.borderColor;\n            ctx.setLineDash(labelColor.borderDash || []);\n            ctx.lineDashOffset = labelColor.borderDashOffset || 0;\n            const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth);\n            const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2);\n            const borderRadius = toTRBLCorners(labelColor.borderRadius);\n            if (Object.values(borderRadius).some((v)=>v !== 0)) {\n                ctx.beginPath();\n                ctx.fillStyle = options.multiKeyBackground;\n                addRoundedRectPath(ctx, {\n                    x: outerX,\n                    y: colorY,\n                    w: boxWidth,\n                    h: boxHeight,\n                    radius: borderRadius\n                });\n                ctx.fill();\n                ctx.stroke();\n                ctx.fillStyle = labelColor.backgroundColor;\n                ctx.beginPath();\n                addRoundedRectPath(ctx, {\n                    x: innerX,\n                    y: colorY + 1,\n                    w: boxWidth - 2,\n                    h: boxHeight - 2,\n                    radius: borderRadius\n                });\n                ctx.fill();\n            } else {\n                ctx.fillStyle = options.multiKeyBackground;\n                ctx.fillRect(outerX, colorY, boxWidth, boxHeight);\n                ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);\n                ctx.fillStyle = labelColor.backgroundColor;\n                ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);\n            }\n        }\n        ctx.fillStyle = this.labelTextColors[i];\n    }\n    drawBody(pt, ctx, options) {\n        const { body  } = this;\n        const { bodySpacing , bodyAlign , displayColors , boxHeight , boxWidth , boxPadding  } = options;\n        const bodyFont = toFont(options.bodyFont);\n        let bodyLineHeight = bodyFont.lineHeight;\n        let xLinePadding = 0;\n        const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);\n        const fillLineOfText = function(line) {\n            ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);\n            pt.y += bodyLineHeight + bodySpacing;\n        };\n        const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);\n        let bodyItem, textColor, lines, i, j, ilen, jlen;\n        ctx.textAlign = bodyAlign;\n        ctx.textBaseline = 'middle';\n        ctx.font = bodyFont.string;\n        pt.x = getAlignedX(this, bodyAlignForCalculation, options);\n        ctx.fillStyle = options.bodyColor;\n        each(this.beforeBody, fillLineOfText);\n        xLinePadding = displayColors && bodyAlignForCalculation !== 'right' ? bodyAlign === 'center' ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0;\n        for(i = 0, ilen = body.length; i < ilen; ++i){\n            bodyItem = body[i];\n            textColor = this.labelTextColors[i];\n            ctx.fillStyle = textColor;\n            each(bodyItem.before, fillLineOfText);\n            lines = bodyItem.lines;\n            if (displayColors && lines.length) {\n                this._drawColorBox(ctx, pt, i, rtlHelper, options);\n                bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);\n            }\n            for(j = 0, jlen = lines.length; j < jlen; ++j){\n                fillLineOfText(lines[j]);\n                bodyLineHeight = bodyFont.lineHeight;\n            }\n            each(bodyItem.after, fillLineOfText);\n        }\n        xLinePadding = 0;\n        bodyLineHeight = bodyFont.lineHeight;\n        each(this.afterBody, fillLineOfText);\n        pt.y -= bodySpacing;\n    }\n    drawFooter(pt, ctx, options) {\n        const footer = this.footer;\n        const length = footer.length;\n        let footerFont, i;\n        if (length) {\n            const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);\n            pt.x = getAlignedX(this, options.footerAlign, options);\n            pt.y += options.footerMarginTop;\n            ctx.textAlign = rtlHelper.textAlign(options.footerAlign);\n            ctx.textBaseline = 'middle';\n            footerFont = toFont(options.footerFont);\n            ctx.fillStyle = options.footerColor;\n            ctx.font = footerFont.string;\n            for(i = 0; i < length; ++i){\n                ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);\n                pt.y += footerFont.lineHeight + options.footerSpacing;\n            }\n        }\n    }\n    drawBackground(pt, ctx, tooltipSize, options) {\n        const { xAlign , yAlign  } = this;\n        const { x , y  } = pt;\n        const { width , height  } = tooltipSize;\n        const { topLeft , topRight , bottomLeft , bottomRight  } = toTRBLCorners(options.cornerRadius);\n        ctx.fillStyle = options.backgroundColor;\n        ctx.strokeStyle = options.borderColor;\n        ctx.lineWidth = options.borderWidth;\n        ctx.beginPath();\n        ctx.moveTo(x + topLeft, y);\n        if (yAlign === 'top') {\n            this.drawCaret(pt, ctx, tooltipSize, options);\n        }\n        ctx.lineTo(x + width - topRight, y);\n        ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);\n        if (yAlign === 'center' && xAlign === 'right') {\n            this.drawCaret(pt, ctx, tooltipSize, options);\n        }\n        ctx.lineTo(x + width, y + height - bottomRight);\n        ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);\n        if (yAlign === 'bottom') {\n            this.drawCaret(pt, ctx, tooltipSize, options);\n        }\n        ctx.lineTo(x + bottomLeft, y + height);\n        ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);\n        if (yAlign === 'center' && xAlign === 'left') {\n            this.drawCaret(pt, ctx, tooltipSize, options);\n        }\n        ctx.lineTo(x, y + topLeft);\n        ctx.quadraticCurveTo(x, y, x + topLeft, y);\n        ctx.closePath();\n        ctx.fill();\n        if (options.borderWidth > 0) {\n            ctx.stroke();\n        }\n    }\n _updateAnimationTarget(options) {\n        const chart = this.chart;\n        const anims = this.$animations;\n        const animX = anims && anims.x;\n        const animY = anims && anims.y;\n        if (animX || animY) {\n            const position = positioners[options.position].call(this, this._active, this._eventPosition);\n            if (!position) {\n                return;\n            }\n            const size = this._size = getTooltipSize(this, options);\n            const positionAndSize = Object.assign({}, position, this._size);\n            const alignment = determineAlignment(chart, options, positionAndSize);\n            const point = getBackgroundPoint(options, positionAndSize, alignment, chart);\n            if (animX._to !== point.x || animY._to !== point.y) {\n                this.xAlign = alignment.xAlign;\n                this.yAlign = alignment.yAlign;\n                this.width = size.width;\n                this.height = size.height;\n                this.caretX = position.x;\n                this.caretY = position.y;\n                this._resolveAnimations().update(this, point);\n            }\n        }\n    }\n _willRender() {\n        return !!this.opacity;\n    }\n    draw(ctx) {\n        const options = this.options.setContext(this.getContext());\n        let opacity = this.opacity;\n        if (!opacity) {\n            return;\n        }\n        this._updateAnimationTarget(options);\n        const tooltipSize = {\n            width: this.width,\n            height: this.height\n        };\n        const pt = {\n            x: this.x,\n            y: this.y\n        };\n        opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;\n        const padding = toPadding(options.padding);\n        const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;\n        if (options.enabled && hasTooltipContent) {\n            ctx.save();\n            ctx.globalAlpha = opacity;\n            this.drawBackground(pt, ctx, tooltipSize, options);\n            overrideTextDirection(ctx, options.textDirection);\n            pt.y += padding.top;\n            this.drawTitle(pt, ctx, options);\n            this.drawBody(pt, ctx, options);\n            this.drawFooter(pt, ctx, options);\n            restoreTextDirection(ctx, options.textDirection);\n            ctx.restore();\n        }\n    }\n getActiveElements() {\n        return this._active || [];\n    }\n setActiveElements(activeElements, eventPosition) {\n        const lastActive = this._active;\n        const active = activeElements.map(({ datasetIndex , index  })=>{\n            const meta = this.chart.getDatasetMeta(datasetIndex);\n            if (!meta) {\n                throw new Error('Cannot find a dataset at index ' + datasetIndex);\n            }\n            return {\n                datasetIndex,\n                element: meta.data[index],\n                index\n            };\n        });\n        const changed = !_elementsEqual(lastActive, active);\n        const positionChanged = this._positionChanged(active, eventPosition);\n        if (changed || positionChanged) {\n            this._active = active;\n            this._eventPosition = eventPosition;\n            this._ignoreReplayEvents = true;\n            this.update(true);\n        }\n    }\n handleEvent(e, replay, inChartArea = true) {\n        if (replay && this._ignoreReplayEvents) {\n            return false;\n        }\n        this._ignoreReplayEvents = false;\n        const options = this.options;\n        const lastActive = this._active || [];\n        const active = this._getActiveElements(e, lastActive, replay, inChartArea);\n        const positionChanged = this._positionChanged(active, e);\n        const changed = replay || !_elementsEqual(active, lastActive) || positionChanged;\n        if (changed) {\n            this._active = active;\n            if (options.enabled || options.external) {\n                this._eventPosition = {\n                    x: e.x,\n                    y: e.y\n                };\n                this.update(true, replay);\n            }\n        }\n        return changed;\n    }\n _getActiveElements(e, lastActive, replay, inChartArea) {\n        const options = this.options;\n        if (e.type === 'mouseout') {\n            return [];\n        }\n        if (!inChartArea) {\n            return lastActive.filter((i)=>this.chart.data.datasets[i.datasetIndex] && this.chart.getDatasetMeta(i.datasetIndex).controller.getParsed(i.index) !== undefined);\n        }\n        const active = this.chart.getElementsAtEventForMode(e, options.mode, options, replay);\n        if (options.reverse) {\n            active.reverse();\n        }\n        return active;\n    }\n _positionChanged(active, e) {\n        const { caretX , caretY , options  } = this;\n        const position = positioners[options.position].call(this, active, e);\n        return position !== false && (caretX !== position.x || caretY !== position.y);\n    }\n}\nvar plugin_tooltip = {\n    id: 'tooltip',\n    _element: Tooltip,\n    positioners,\n    afterInit (chart, _args, options) {\n        if (options) {\n            chart.tooltip = new Tooltip({\n                chart,\n                options\n            });\n        }\n    },\n    beforeUpdate (chart, _args, options) {\n        if (chart.tooltip) {\n            chart.tooltip.initialize(options);\n        }\n    },\n    reset (chart, _args, options) {\n        if (chart.tooltip) {\n            chart.tooltip.initialize(options);\n        }\n    },\n    afterDraw (chart) {\n        const tooltip = chart.tooltip;\n        if (tooltip && tooltip._willRender()) {\n            const args = {\n                tooltip\n            };\n            if (chart.notifyPlugins('beforeTooltipDraw', {\n                ...args,\n                cancelable: true\n            }) === false) {\n                return;\n            }\n            tooltip.draw(chart.ctx);\n            chart.notifyPlugins('afterTooltipDraw', args);\n        }\n    },\n    afterEvent (chart, args) {\n        if (chart.tooltip) {\n            const useFinalPosition = args.replay;\n            if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) {\n                args.changed = true;\n            }\n        }\n    },\n    defaults: {\n        enabled: true,\n        external: null,\n        position: 'average',\n        backgroundColor: 'rgba(0,0,0,0.8)',\n        titleColor: '#fff',\n        titleFont: {\n            weight: 'bold'\n        },\n        titleSpacing: 2,\n        titleMarginBottom: 6,\n        titleAlign: 'left',\n        bodyColor: '#fff',\n        bodySpacing: 2,\n        bodyFont: {},\n        bodyAlign: 'left',\n        footerColor: '#fff',\n        footerSpacing: 2,\n        footerMarginTop: 6,\n        footerFont: {\n            weight: 'bold'\n        },\n        footerAlign: 'left',\n        padding: 6,\n        caretPadding: 2,\n        caretSize: 5,\n        cornerRadius: 6,\n        boxHeight: (ctx, opts)=>opts.bodyFont.size,\n        boxWidth: (ctx, opts)=>opts.bodyFont.size,\n        multiKeyBackground: '#fff',\n        displayColors: true,\n        boxPadding: 0,\n        borderColor: 'rgba(0,0,0,0)',\n        borderWidth: 0,\n        animation: {\n            duration: 400,\n            easing: 'easeOutQuart'\n        },\n        animations: {\n            numbers: {\n                type: 'number',\n                properties: [\n                    'x',\n                    'y',\n                    'width',\n                    'height',\n                    'caretX',\n                    'caretY'\n                ]\n            },\n            opacity: {\n                easing: 'linear',\n                duration: 200\n            }\n        },\n        callbacks: defaultCallbacks\n    },\n    defaultRoutes: {\n        bodyFont: 'font',\n        footerFont: 'font',\n        titleFont: 'font'\n    },\n    descriptors: {\n        _scriptable: (name)=>name !== 'filter' && name !== 'itemSort' && name !== 'external',\n        _indexable: false,\n        callbacks: {\n            _scriptable: false,\n            _indexable: false\n        },\n        animation: {\n            _fallback: false\n        },\n        animations: {\n            _fallback: 'animation'\n        }\n    },\n    additionalOptionScopes: [\n        'interaction'\n    ]\n};\n\nvar plugins = /*#__PURE__*/Object.freeze({\n__proto__: null,\nColors: plugin_colors,\nDecimation: plugin_decimation,\nFiller: index,\nLegend: plugin_legend,\nSubTitle: plugin_subtitle,\nTitle: plugin_title,\nTooltip: plugin_tooltip\n});\n\nconst addIfString = (labels, raw, index, addedLabels)=>{\n    if (typeof raw === 'string') {\n        index = labels.push(raw) - 1;\n        addedLabels.unshift({\n            index,\n            label: raw\n        });\n    } else if (isNaN(raw)) {\n        index = null;\n    }\n    return index;\n};\nfunction findOrAddLabel(labels, raw, index, addedLabels) {\n    const first = labels.indexOf(raw);\n    if (first === -1) {\n        return addIfString(labels, raw, index, addedLabels);\n    }\n    const last = labels.lastIndexOf(raw);\n    return first !== last ? index : first;\n}\nconst validIndex = (index, max)=>index === null ? null : _limitValue(Math.round(index), 0, max);\nfunction _getLabelForValue(value) {\n    const labels = this.getLabels();\n    if (value >= 0 && value < labels.length) {\n        return labels[value];\n    }\n    return value;\n}\nclass CategoryScale extends Scale {\n    static id = 'category';\n static defaults = {\n        ticks: {\n            callback: _getLabelForValue\n        }\n    };\n    constructor(cfg){\n        super(cfg);\n         this._startValue = undefined;\n        this._valueRange = 0;\n        this._addedLabels = [];\n    }\n    init(scaleOptions) {\n        const added = this._addedLabels;\n        if (added.length) {\n            const labels = this.getLabels();\n            for (const { index , label  } of added){\n                if (labels[index] === label) {\n                    labels.splice(index, 1);\n                }\n            }\n            this._addedLabels = [];\n        }\n        super.init(scaleOptions);\n    }\n    parse(raw, index) {\n        if (isNullOrUndef(raw)) {\n            return null;\n        }\n        const labels = this.getLabels();\n        index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, valueOrDefault(index, raw), this._addedLabels);\n        return validIndex(index, labels.length - 1);\n    }\n    determineDataLimits() {\n        const { minDefined , maxDefined  } = this.getUserBounds();\n        let { min , max  } = this.getMinMax(true);\n        if (this.options.bounds === 'ticks') {\n            if (!minDefined) {\n                min = 0;\n            }\n            if (!maxDefined) {\n                max = this.getLabels().length - 1;\n            }\n        }\n        this.min = min;\n        this.max = max;\n    }\n    buildTicks() {\n        const min = this.min;\n        const max = this.max;\n        const offset = this.options.offset;\n        const ticks = [];\n        let labels = this.getLabels();\n        labels = min === 0 && max === labels.length - 1 ? labels : labels.slice(min, max + 1);\n        this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);\n        this._startValue = this.min - (offset ? 0.5 : 0);\n        for(let value = min; value <= max; value++){\n            ticks.push({\n                value\n            });\n        }\n        return ticks;\n    }\n    getLabelForValue(value) {\n        return _getLabelForValue.call(this, value);\n    }\n configure() {\n        super.configure();\n        if (!this.isHorizontal()) {\n            this._reversePixels = !this._reversePixels;\n        }\n    }\n    getPixelForValue(value) {\n        if (typeof value !== 'number') {\n            value = this.parse(value);\n        }\n        return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);\n    }\n    getPixelForTick(index) {\n        const ticks = this.ticks;\n        if (index < 0 || index > ticks.length - 1) {\n            return null;\n        }\n        return this.getPixelForValue(ticks[index].value);\n    }\n    getValueForPixel(pixel) {\n        return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);\n    }\n    getBasePixel() {\n        return this.bottom;\n    }\n}\n\nfunction generateTicks$1(generationOptions, dataRange) {\n    const ticks = [];\n    const MIN_SPACING = 1e-14;\n    const { bounds , step , min , max , precision , count , maxTicks , maxDigits , includeBounds  } = generationOptions;\n    const unit = step || 1;\n    const maxSpaces = maxTicks - 1;\n    const { min: rmin , max: rmax  } = dataRange;\n    const minDefined = !isNullOrUndef(min);\n    const maxDefined = !isNullOrUndef(max);\n    const countDefined = !isNullOrUndef(count);\n    const minSpacing = (rmax - rmin) / (maxDigits + 1);\n    let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit;\n    let factor, niceMin, niceMax, numSpaces;\n    if (spacing < MIN_SPACING && !minDefined && !maxDefined) {\n        return [\n            {\n                value: rmin\n            },\n            {\n                value: rmax\n            }\n        ];\n    }\n    numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);\n    if (numSpaces > maxSpaces) {\n        spacing = niceNum(numSpaces * spacing / maxSpaces / unit) * unit;\n    }\n    if (!isNullOrUndef(precision)) {\n        factor = Math.pow(10, precision);\n        spacing = Math.ceil(spacing * factor) / factor;\n    }\n    if (bounds === 'ticks') {\n        niceMin = Math.floor(rmin / spacing) * spacing;\n        niceMax = Math.ceil(rmax / spacing) * spacing;\n    } else {\n        niceMin = rmin;\n        niceMax = rmax;\n    }\n    if (minDefined && maxDefined && step && almostWhole((max - min) / step, spacing / 1000)) {\n        numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks));\n        spacing = (max - min) / numSpaces;\n        niceMin = min;\n        niceMax = max;\n    } else if (countDefined) {\n        niceMin = minDefined ? min : niceMin;\n        niceMax = maxDefined ? max : niceMax;\n        numSpaces = count - 1;\n        spacing = (niceMax - niceMin) / numSpaces;\n    } else {\n        numSpaces = (niceMax - niceMin) / spacing;\n        if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {\n            numSpaces = Math.round(numSpaces);\n        } else {\n            numSpaces = Math.ceil(numSpaces);\n        }\n    }\n    const decimalPlaces = Math.max(_decimalPlaces(spacing), _decimalPlaces(niceMin));\n    factor = Math.pow(10, isNullOrUndef(precision) ? decimalPlaces : precision);\n    niceMin = Math.round(niceMin * factor) / factor;\n    niceMax = Math.round(niceMax * factor) / factor;\n    let j = 0;\n    if (minDefined) {\n        if (includeBounds && niceMin !== min) {\n            ticks.push({\n                value: min\n            });\n            if (niceMin < min) {\n                j++;\n            }\n            if (almostEquals(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) {\n                j++;\n            }\n        } else if (niceMin < min) {\n            j++;\n        }\n    }\n    for(; j < numSpaces; ++j){\n        const tickValue = Math.round((niceMin + j * spacing) * factor) / factor;\n        if (maxDefined && tickValue > max) {\n            break;\n        }\n        ticks.push({\n            value: tickValue\n        });\n    }\n    if (maxDefined && includeBounds && niceMax !== max) {\n        if (ticks.length && almostEquals(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) {\n            ticks[ticks.length - 1].value = max;\n        } else {\n            ticks.push({\n                value: max\n            });\n        }\n    } else if (!maxDefined || niceMax === max) {\n        ticks.push({\n            value: niceMax\n        });\n    }\n    return ticks;\n}\nfunction relativeLabelSize(value, minSpacing, { horizontal , minRotation  }) {\n    const rad = toRadians(minRotation);\n    const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001;\n    const length = 0.75 * minSpacing * ('' + value).length;\n    return Math.min(minSpacing / ratio, length);\n}\nclass LinearScaleBase extends Scale {\n    constructor(cfg){\n        super(cfg);\n         this.start = undefined;\n         this.end = undefined;\n         this._startValue = undefined;\n         this._endValue = undefined;\n        this._valueRange = 0;\n    }\n    parse(raw, index) {\n        if (isNullOrUndef(raw)) {\n            return null;\n        }\n        if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) {\n            return null;\n        }\n        return +raw;\n    }\n    handleTickRangeOptions() {\n        const { beginAtZero  } = this.options;\n        const { minDefined , maxDefined  } = this.getUserBounds();\n        let { min , max  } = this;\n        const setMin = (v)=>min = minDefined ? min : v;\n        const setMax = (v)=>max = maxDefined ? max : v;\n        if (beginAtZero) {\n            const minSign = sign(min);\n            const maxSign = sign(max);\n            if (minSign < 0 && maxSign < 0) {\n                setMax(0);\n            } else if (minSign > 0 && maxSign > 0) {\n                setMin(0);\n            }\n        }\n        if (min === max) {\n            let offset = max === 0 ? 1 : Math.abs(max * 0.05);\n            setMax(max + offset);\n            if (!beginAtZero) {\n                setMin(min - offset);\n            }\n        }\n        this.min = min;\n        this.max = max;\n    }\n    getTickLimit() {\n        const tickOpts = this.options.ticks;\n        let { maxTicksLimit , stepSize  } = tickOpts;\n        let maxTicks;\n        if (stepSize) {\n            maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;\n            if (maxTicks > 1000) {\n                console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);\n                maxTicks = 1000;\n            }\n        } else {\n            maxTicks = this.computeTickLimit();\n            maxTicksLimit = maxTicksLimit || 11;\n        }\n        if (maxTicksLimit) {\n            maxTicks = Math.min(maxTicksLimit, maxTicks);\n        }\n        return maxTicks;\n    }\n computeTickLimit() {\n        return Number.POSITIVE_INFINITY;\n    }\n    buildTicks() {\n        const opts = this.options;\n        const tickOpts = opts.ticks;\n        let maxTicks = this.getTickLimit();\n        maxTicks = Math.max(2, maxTicks);\n        const numericGeneratorOptions = {\n            maxTicks,\n            bounds: opts.bounds,\n            min: opts.min,\n            max: opts.max,\n            precision: tickOpts.precision,\n            step: tickOpts.stepSize,\n            count: tickOpts.count,\n            maxDigits: this._maxDigits(),\n            horizontal: this.isHorizontal(),\n            minRotation: tickOpts.minRotation || 0,\n            includeBounds: tickOpts.includeBounds !== false\n        };\n        const dataRange = this._range || this;\n        const ticks = generateTicks$1(numericGeneratorOptions, dataRange);\n        if (opts.bounds === 'ticks') {\n            _setMinAndMaxByKey(ticks, this, 'value');\n        }\n        if (opts.reverse) {\n            ticks.reverse();\n            this.start = this.max;\n            this.end = this.min;\n        } else {\n            this.start = this.min;\n            this.end = this.max;\n        }\n        return ticks;\n    }\n configure() {\n        const ticks = this.ticks;\n        let start = this.min;\n        let end = this.max;\n        super.configure();\n        if (this.options.offset && ticks.length) {\n            const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;\n            start -= offset;\n            end += offset;\n        }\n        this._startValue = start;\n        this._endValue = end;\n        this._valueRange = end - start;\n    }\n    getLabelForValue(value) {\n        return formatNumber(value, this.chart.options.locale, this.options.ticks.format);\n    }\n}\n\nclass LinearScale extends LinearScaleBase {\n    static id = 'linear';\n static defaults = {\n        ticks: {\n            callback: Ticks.formatters.numeric\n        }\n    };\n    determineDataLimits() {\n        const { min , max  } = this.getMinMax(true);\n        this.min = isNumberFinite(min) ? min : 0;\n        this.max = isNumberFinite(max) ? max : 1;\n        this.handleTickRangeOptions();\n    }\n computeTickLimit() {\n        const horizontal = this.isHorizontal();\n        const length = horizontal ? this.width : this.height;\n        const minRotation = toRadians(this.options.ticks.minRotation);\n        const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001;\n        const tickFont = this._resolveTickFontOptions(0);\n        return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));\n    }\n    getPixelForValue(value) {\n        return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);\n    }\n    getValueForPixel(pixel) {\n        return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;\n    }\n}\n\nconst log10Floor = (v)=>Math.floor(log10(v));\nconst changeExponent = (v, m)=>Math.pow(10, log10Floor(v) + m);\nfunction isMajor(tickVal) {\n    const remain = tickVal / Math.pow(10, log10Floor(tickVal));\n    return remain === 1;\n}\nfunction steps(min, max, rangeExp) {\n    const rangeStep = Math.pow(10, rangeExp);\n    const start = Math.floor(min / rangeStep);\n    const end = Math.ceil(max / rangeStep);\n    return end - start;\n}\nfunction startExp(min, max) {\n    const range = max - min;\n    let rangeExp = log10Floor(range);\n    while(steps(min, max, rangeExp) > 10){\n        rangeExp++;\n    }\n    while(steps(min, max, rangeExp) < 10){\n        rangeExp--;\n    }\n    return Math.min(rangeExp, log10Floor(min));\n}\n function generateTicks(generationOptions, { min , max  }) {\n    min = finiteOrDefault(generationOptions.min, min);\n    const ticks = [];\n    const minExp = log10Floor(min);\n    let exp = startExp(min, max);\n    let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;\n    const stepSize = Math.pow(10, exp);\n    const base = minExp > exp ? Math.pow(10, minExp) : 0;\n    const start = Math.round((min - base) * precision) / precision;\n    const offset = Math.floor((min - base) / stepSize / 10) * stepSize * 10;\n    let significand = Math.floor((start - offset) / Math.pow(10, exp));\n    let value = finiteOrDefault(generationOptions.min, Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision);\n    while(value < max){\n        ticks.push({\n            value,\n            major: isMajor(value),\n            significand\n        });\n        if (significand >= 10) {\n            significand = significand < 15 ? 15 : 20;\n        } else {\n            significand++;\n        }\n        if (significand >= 20) {\n            exp++;\n            significand = 2;\n            precision = exp >= 0 ? 1 : precision;\n        }\n        value = Math.round((base + offset + significand * Math.pow(10, exp)) * precision) / precision;\n    }\n    const lastTick = finiteOrDefault(generationOptions.max, value);\n    ticks.push({\n        value: lastTick,\n        major: isMajor(lastTick),\n        significand\n    });\n    return ticks;\n}\nclass LogarithmicScale extends Scale {\n    static id = 'logarithmic';\n static defaults = {\n        ticks: {\n            callback: Ticks.formatters.logarithmic,\n            major: {\n                enabled: true\n            }\n        }\n    };\n    constructor(cfg){\n        super(cfg);\n         this.start = undefined;\n         this.end = undefined;\n         this._startValue = undefined;\n        this._valueRange = 0;\n    }\n    parse(raw, index) {\n        const value = LinearScaleBase.prototype.parse.apply(this, [\n            raw,\n            index\n        ]);\n        if (value === 0) {\n            this._zero = true;\n            return undefined;\n        }\n        return isNumberFinite(value) && value > 0 ? value : null;\n    }\n    determineDataLimits() {\n        const { min , max  } = this.getMinMax(true);\n        this.min = isNumberFinite(min) ? Math.max(0, min) : null;\n        this.max = isNumberFinite(max) ? Math.max(0, max) : null;\n        if (this.options.beginAtZero) {\n            this._zero = true;\n        }\n        if (this._zero && this.min !== this._suggestedMin && !isNumberFinite(this._userMin)) {\n            this.min = min === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0);\n        }\n        this.handleTickRangeOptions();\n    }\n    handleTickRangeOptions() {\n        const { minDefined , maxDefined  } = this.getUserBounds();\n        let min = this.min;\n        let max = this.max;\n        const setMin = (v)=>min = minDefined ? min : v;\n        const setMax = (v)=>max = maxDefined ? max : v;\n        if (min === max) {\n            if (min <= 0) {\n                setMin(1);\n                setMax(10);\n            } else {\n                setMin(changeExponent(min, -1));\n                setMax(changeExponent(max, +1));\n            }\n        }\n        if (min <= 0) {\n            setMin(changeExponent(max, -1));\n        }\n        if (max <= 0) {\n            setMax(changeExponent(min, +1));\n        }\n        this.min = min;\n        this.max = max;\n    }\n    buildTicks() {\n        const opts = this.options;\n        const generationOptions = {\n            min: this._userMin,\n            max: this._userMax\n        };\n        const ticks = generateTicks(generationOptions, this);\n        if (opts.bounds === 'ticks') {\n            _setMinAndMaxByKey(ticks, this, 'value');\n        }\n        if (opts.reverse) {\n            ticks.reverse();\n            this.start = this.max;\n            this.end = this.min;\n        } else {\n            this.start = this.min;\n            this.end = this.max;\n        }\n        return ticks;\n    }\n getLabelForValue(value) {\n        return value === undefined ? '0' : formatNumber(value, this.chart.options.locale, this.options.ticks.format);\n    }\n configure() {\n        const start = this.min;\n        super.configure();\n        this._startValue = log10(start);\n        this._valueRange = log10(this.max) - log10(start);\n    }\n    getPixelForValue(value) {\n        if (value === undefined || value === 0) {\n            value = this.min;\n        }\n        if (value === null || isNaN(value)) {\n            return NaN;\n        }\n        return this.getPixelForDecimal(value === this.min ? 0 : (log10(value) - this._startValue) / this._valueRange);\n    }\n    getValueForPixel(pixel) {\n        const decimal = this.getDecimalForPixel(pixel);\n        return Math.pow(10, this._startValue + decimal * this._valueRange);\n    }\n}\n\nfunction getTickBackdropHeight(opts) {\n    const tickOpts = opts.ticks;\n    if (tickOpts.display && opts.display) {\n        const padding = toPadding(tickOpts.backdropPadding);\n        return valueOrDefault(tickOpts.font && tickOpts.font.size, defaults.font.size) + padding.height;\n    }\n    return 0;\n}\nfunction measureLabelSize(ctx, font, label) {\n    label = isArray(label) ? label : [\n        label\n    ];\n    return {\n        w: _longestText(ctx, font.string, label),\n        h: label.length * font.lineHeight\n    };\n}\nfunction determineLimits(angle, pos, size, min, max) {\n    if (angle === min || angle === max) {\n        return {\n            start: pos - size / 2,\n            end: pos + size / 2\n        };\n    } else if (angle < min || angle > max) {\n        return {\n            start: pos - size,\n            end: pos\n        };\n    }\n    return {\n        start: pos,\n        end: pos + size\n    };\n}\n function fitWithPointLabels(scale) {\n    const orig = {\n        l: scale.left + scale._padding.left,\n        r: scale.right - scale._padding.right,\n        t: scale.top + scale._padding.top,\n        b: scale.bottom - scale._padding.bottom\n    };\n    const limits = Object.assign({}, orig);\n    const labelSizes = [];\n    const padding = [];\n    const valueCount = scale._pointLabels.length;\n    const pointLabelOpts = scale.options.pointLabels;\n    const additionalAngle = pointLabelOpts.centerPointLabels ? PI / valueCount : 0;\n    for(let i = 0; i < valueCount; i++){\n        const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i));\n        padding[i] = opts.padding;\n        const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i], additionalAngle);\n        const plFont = toFont(opts.font);\n        const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]);\n        labelSizes[i] = textSize;\n        const angleRadians = _normalizeAngle(scale.getIndexAngle(i) + additionalAngle);\n        const angle = Math.round(toDegrees(angleRadians));\n        const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);\n        const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);\n        updateLimits(limits, orig, angleRadians, hLimits, vLimits);\n    }\n    scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b);\n    scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);\n}\nfunction updateLimits(limits, orig, angle, hLimits, vLimits) {\n    const sin = Math.abs(Math.sin(angle));\n    const cos = Math.abs(Math.cos(angle));\n    let x = 0;\n    let y = 0;\n    if (hLimits.start < orig.l) {\n        x = (orig.l - hLimits.start) / sin;\n        limits.l = Math.min(limits.l, orig.l - x);\n    } else if (hLimits.end > orig.r) {\n        x = (hLimits.end - orig.r) / sin;\n        limits.r = Math.max(limits.r, orig.r + x);\n    }\n    if (vLimits.start < orig.t) {\n        y = (orig.t - vLimits.start) / cos;\n        limits.t = Math.min(limits.t, orig.t - y);\n    } else if (vLimits.end > orig.b) {\n        y = (vLimits.end - orig.b) / cos;\n        limits.b = Math.max(limits.b, orig.b + y);\n    }\n}\nfunction createPointLabelItem(scale, index, itemOpts) {\n    const outerDistance = scale.drawingArea;\n    const { extra , additionalAngle , padding , size  } = itemOpts;\n    const pointLabelPosition = scale.getPointPosition(index, outerDistance + extra + padding, additionalAngle);\n    const angle = Math.round(toDegrees(_normalizeAngle(pointLabelPosition.angle + HALF_PI)));\n    const y = yForAngle(pointLabelPosition.y, size.h, angle);\n    const textAlign = getTextAlignForAngle(angle);\n    const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);\n    return {\n        visible: true,\n        x: pointLabelPosition.x,\n        y,\n        textAlign,\n        left,\n        top: y,\n        right: left + size.w,\n        bottom: y + size.h\n    };\n}\nfunction isNotOverlapped(item, area) {\n    if (!area) {\n        return true;\n    }\n    const { left , top , right , bottom  } = item;\n    const apexesInArea = _isPointInArea({\n        x: left,\n        y: top\n    }, area) || _isPointInArea({\n        x: left,\n        y: bottom\n    }, area) || _isPointInArea({\n        x: right,\n        y: top\n    }, area) || _isPointInArea({\n        x: right,\n        y: bottom\n    }, area);\n    return !apexesInArea;\n}\nfunction buildPointLabelItems(scale, labelSizes, padding) {\n    const items = [];\n    const valueCount = scale._pointLabels.length;\n    const opts = scale.options;\n    const { centerPointLabels , display  } = opts.pointLabels;\n    const itemOpts = {\n        extra: getTickBackdropHeight(opts) / 2,\n        additionalAngle: centerPointLabels ? PI / valueCount : 0\n    };\n    let area;\n    for(let i = 0; i < valueCount; i++){\n        itemOpts.padding = padding[i];\n        itemOpts.size = labelSizes[i];\n        const item = createPointLabelItem(scale, i, itemOpts);\n        items.push(item);\n        if (display === 'auto') {\n            item.visible = isNotOverlapped(item, area);\n            if (item.visible) {\n                area = item;\n            }\n        }\n    }\n    return items;\n}\nfunction getTextAlignForAngle(angle) {\n    if (angle === 0 || angle === 180) {\n        return 'center';\n    } else if (angle < 180) {\n        return 'left';\n    }\n    return 'right';\n}\nfunction leftForTextAlign(x, w, align) {\n    if (align === 'right') {\n        x -= w;\n    } else if (align === 'center') {\n        x -= w / 2;\n    }\n    return x;\n}\nfunction yForAngle(y, h, angle) {\n    if (angle === 90 || angle === 270) {\n        y -= h / 2;\n    } else if (angle > 270 || angle < 90) {\n        y -= h;\n    }\n    return y;\n}\nfunction drawPointLabelBox(ctx, opts, item) {\n    const { left , top , right , bottom  } = item;\n    const { backdropColor  } = opts;\n    if (!isNullOrUndef(backdropColor)) {\n        const borderRadius = toTRBLCorners(opts.borderRadius);\n        const padding = toPadding(opts.backdropPadding);\n        ctx.fillStyle = backdropColor;\n        const backdropLeft = left - padding.left;\n        const backdropTop = top - padding.top;\n        const backdropWidth = right - left + padding.width;\n        const backdropHeight = bottom - top + padding.height;\n        if (Object.values(borderRadius).some((v)=>v !== 0)) {\n            ctx.beginPath();\n            addRoundedRectPath(ctx, {\n                x: backdropLeft,\n                y: backdropTop,\n                w: backdropWidth,\n                h: backdropHeight,\n                radius: borderRadius\n            });\n            ctx.fill();\n        } else {\n            ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight);\n        }\n    }\n}\nfunction drawPointLabels(scale, labelCount) {\n    const { ctx , options: { pointLabels  }  } = scale;\n    for(let i = labelCount - 1; i >= 0; i--){\n        const item = scale._pointLabelItems[i];\n        if (!item.visible) {\n            continue;\n        }\n        const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i));\n        drawPointLabelBox(ctx, optsAtIndex, item);\n        const plFont = toFont(optsAtIndex.font);\n        const { x , y , textAlign  } = item;\n        renderText(ctx, scale._pointLabels[i], x, y + plFont.lineHeight / 2, plFont, {\n            color: optsAtIndex.color,\n            textAlign: textAlign,\n            textBaseline: 'middle'\n        });\n    }\n}\nfunction pathRadiusLine(scale, radius, circular, labelCount) {\n    const { ctx  } = scale;\n    if (circular) {\n        ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);\n    } else {\n        let pointPosition = scale.getPointPosition(0, radius);\n        ctx.moveTo(pointPosition.x, pointPosition.y);\n        for(let i = 1; i < labelCount; i++){\n            pointPosition = scale.getPointPosition(i, radius);\n            ctx.lineTo(pointPosition.x, pointPosition.y);\n        }\n    }\n}\nfunction drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) {\n    const ctx = scale.ctx;\n    const circular = gridLineOpts.circular;\n    const { color , lineWidth  } = gridLineOpts;\n    if (!circular && !labelCount || !color || !lineWidth || radius < 0) {\n        return;\n    }\n    ctx.save();\n    ctx.strokeStyle = color;\n    ctx.lineWidth = lineWidth;\n    ctx.setLineDash(borderOpts.dash);\n    ctx.lineDashOffset = borderOpts.dashOffset;\n    ctx.beginPath();\n    pathRadiusLine(scale, radius, circular, labelCount);\n    ctx.closePath();\n    ctx.stroke();\n    ctx.restore();\n}\nfunction createPointLabelContext(parent, index, label) {\n    return createContext(parent, {\n        label,\n        index,\n        type: 'pointLabel'\n    });\n}\nclass RadialLinearScale extends LinearScaleBase {\n    static id = 'radialLinear';\n static defaults = {\n        display: true,\n        animate: true,\n        position: 'chartArea',\n        angleLines: {\n            display: true,\n            lineWidth: 1,\n            borderDash: [],\n            borderDashOffset: 0.0\n        },\n        grid: {\n            circular: false\n        },\n        startAngle: 0,\n        ticks: {\n            showLabelBackdrop: true,\n            callback: Ticks.formatters.numeric\n        },\n        pointLabels: {\n            backdropColor: undefined,\n            backdropPadding: 2,\n            display: true,\n            font: {\n                size: 10\n            },\n            callback (label) {\n                return label;\n            },\n            padding: 5,\n            centerPointLabels: false\n        }\n    };\n    static defaultRoutes = {\n        'angleLines.color': 'borderColor',\n        'pointLabels.color': 'color',\n        'ticks.color': 'color'\n    };\n    static descriptors = {\n        angleLines: {\n            _fallback: 'grid'\n        }\n    };\n    constructor(cfg){\n        super(cfg);\n         this.xCenter = undefined;\n         this.yCenter = undefined;\n         this.drawingArea = undefined;\n         this._pointLabels = [];\n        this._pointLabelItems = [];\n    }\n    setDimensions() {\n        const padding = this._padding = toPadding(getTickBackdropHeight(this.options) / 2);\n        const w = this.width = this.maxWidth - padding.width;\n        const h = this.height = this.maxHeight - padding.height;\n        this.xCenter = Math.floor(this.left + w / 2 + padding.left);\n        this.yCenter = Math.floor(this.top + h / 2 + padding.top);\n        this.drawingArea = Math.floor(Math.min(w, h) / 2);\n    }\n    determineDataLimits() {\n        const { min , max  } = this.getMinMax(false);\n        this.min = isNumberFinite(min) && !isNaN(min) ? min : 0;\n        this.max = isNumberFinite(max) && !isNaN(max) ? max : 0;\n        this.handleTickRangeOptions();\n    }\n computeTickLimit() {\n        return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));\n    }\n    generateTickLabels(ticks) {\n        LinearScaleBase.prototype.generateTickLabels.call(this, ticks);\n        this._pointLabels = this.getLabels().map((value, index)=>{\n            const label = callback(this.options.pointLabels.callback, [\n                value,\n                index\n            ], this);\n            return label || label === 0 ? label : '';\n        }).filter((v, i)=>this.chart.getDataVisibility(i));\n    }\n    fit() {\n        const opts = this.options;\n        if (opts.display && opts.pointLabels.display) {\n            fitWithPointLabels(this);\n        } else {\n            this.setCenterPoint(0, 0, 0, 0);\n        }\n    }\n    setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {\n        this.xCenter += Math.floor((leftMovement - rightMovement) / 2);\n        this.yCenter += Math.floor((topMovement - bottomMovement) / 2);\n        this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement));\n    }\n    getIndexAngle(index) {\n        const angleMultiplier = TAU / (this._pointLabels.length || 1);\n        const startAngle = this.options.startAngle || 0;\n        return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));\n    }\n    getDistanceFromCenterForValue(value) {\n        if (isNullOrUndef(value)) {\n            return NaN;\n        }\n        const scalingFactor = this.drawingArea / (this.max - this.min);\n        if (this.options.reverse) {\n            return (this.max - value) * scalingFactor;\n        }\n        return (value - this.min) * scalingFactor;\n    }\n    getValueForDistanceFromCenter(distance) {\n        if (isNullOrUndef(distance)) {\n            return NaN;\n        }\n        const scaledDistance = distance / (this.drawingArea / (this.max - this.min));\n        return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;\n    }\n    getPointLabelContext(index) {\n        const pointLabels = this._pointLabels || [];\n        if (index >= 0 && index < pointLabels.length) {\n            const pointLabel = pointLabels[index];\n            return createPointLabelContext(this.getContext(), index, pointLabel);\n        }\n    }\n    getPointPosition(index, distanceFromCenter, additionalAngle = 0) {\n        const angle = this.getIndexAngle(index) - HALF_PI + additionalAngle;\n        return {\n            x: Math.cos(angle) * distanceFromCenter + this.xCenter,\n            y: Math.sin(angle) * distanceFromCenter + this.yCenter,\n            angle\n        };\n    }\n    getPointPositionForValue(index, value) {\n        return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));\n    }\n    getBasePosition(index) {\n        return this.getPointPositionForValue(index || 0, this.getBaseValue());\n    }\n    getPointLabelPosition(index) {\n        const { left , top , right , bottom  } = this._pointLabelItems[index];\n        return {\n            left,\n            top,\n            right,\n            bottom\n        };\n    }\n drawBackground() {\n        const { backgroundColor , grid: { circular  }  } = this.options;\n        if (backgroundColor) {\n            const ctx = this.ctx;\n            ctx.save();\n            ctx.beginPath();\n            pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length);\n            ctx.closePath();\n            ctx.fillStyle = backgroundColor;\n            ctx.fill();\n            ctx.restore();\n        }\n    }\n drawGrid() {\n        const ctx = this.ctx;\n        const opts = this.options;\n        const { angleLines , grid , border  } = opts;\n        const labelCount = this._pointLabels.length;\n        let i, offset, position;\n        if (opts.pointLabels.display) {\n            drawPointLabels(this, labelCount);\n        }\n        if (grid.display) {\n            this.ticks.forEach((tick, index)=>{\n                if (index !== 0 || index === 0 && this.min < 0) {\n                    offset = this.getDistanceFromCenterForValue(tick.value);\n                    const context = this.getContext(index);\n                    const optsAtIndex = grid.setContext(context);\n                    const optsAtIndexBorder = border.setContext(context);\n                    drawRadiusLine(this, optsAtIndex, offset, labelCount, optsAtIndexBorder);\n                }\n            });\n        }\n        if (angleLines.display) {\n            ctx.save();\n            for(i = labelCount - 1; i >= 0; i--){\n                const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));\n                const { color , lineWidth  } = optsAtIndex;\n                if (!lineWidth || !color) {\n                    continue;\n                }\n                ctx.lineWidth = lineWidth;\n                ctx.strokeStyle = color;\n                ctx.setLineDash(optsAtIndex.borderDash);\n                ctx.lineDashOffset = optsAtIndex.borderDashOffset;\n                offset = this.getDistanceFromCenterForValue(opts.ticks.reverse ? this.min : this.max);\n                position = this.getPointPosition(i, offset);\n                ctx.beginPath();\n                ctx.moveTo(this.xCenter, this.yCenter);\n                ctx.lineTo(position.x, position.y);\n                ctx.stroke();\n            }\n            ctx.restore();\n        }\n    }\n drawBorder() {}\n drawLabels() {\n        const ctx = this.ctx;\n        const opts = this.options;\n        const tickOpts = opts.ticks;\n        if (!tickOpts.display) {\n            return;\n        }\n        const startAngle = this.getIndexAngle(0);\n        let offset, width;\n        ctx.save();\n        ctx.translate(this.xCenter, this.yCenter);\n        ctx.rotate(startAngle);\n        ctx.textAlign = 'center';\n        ctx.textBaseline = 'middle';\n        this.ticks.forEach((tick, index)=>{\n            if (index === 0 && this.min >= 0 && !opts.reverse) {\n                return;\n            }\n            const optsAtIndex = tickOpts.setContext(this.getContext(index));\n            const tickFont = toFont(optsAtIndex.font);\n            offset = this.getDistanceFromCenterForValue(this.ticks[index].value);\n            if (optsAtIndex.showLabelBackdrop) {\n                ctx.font = tickFont.string;\n                width = ctx.measureText(tick.label).width;\n                ctx.fillStyle = optsAtIndex.backdropColor;\n                const padding = toPadding(optsAtIndex.backdropPadding);\n                ctx.fillRect(-width / 2 - padding.left, -offset - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height);\n            }\n            renderText(ctx, tick.label, 0, -offset, tickFont, {\n                color: optsAtIndex.color,\n                strokeColor: optsAtIndex.textStrokeColor,\n                strokeWidth: optsAtIndex.textStrokeWidth\n            });\n        });\n        ctx.restore();\n    }\n drawTitle() {}\n}\n\nconst INTERVALS = {\n    millisecond: {\n        common: true,\n        size: 1,\n        steps: 1000\n    },\n    second: {\n        common: true,\n        size: 1000,\n        steps: 60\n    },\n    minute: {\n        common: true,\n        size: 60000,\n        steps: 60\n    },\n    hour: {\n        common: true,\n        size: 3600000,\n        steps: 24\n    },\n    day: {\n        common: true,\n        size: 86400000,\n        steps: 30\n    },\n    week: {\n        common: false,\n        size: 604800000,\n        steps: 4\n    },\n    month: {\n        common: true,\n        size: 2.628e9,\n        steps: 12\n    },\n    quarter: {\n        common: false,\n        size: 7.884e9,\n        steps: 4\n    },\n    year: {\n        common: true,\n        size: 3.154e10\n    }\n};\n const UNITS =  /* #__PURE__ */ Object.keys(INTERVALS);\n function sorter(a, b) {\n    return a - b;\n}\n function parse(scale, input) {\n    if (isNullOrUndef(input)) {\n        return null;\n    }\n    const adapter = scale._adapter;\n    const { parser , round , isoWeekday  } = scale._parseOpts;\n    let value = input;\n    if (typeof parser === 'function') {\n        value = parser(value);\n    }\n    if (!isNumberFinite(value)) {\n        value = typeof parser === 'string' ? adapter.parse(value,  parser) : adapter.parse(value);\n    }\n    if (value === null) {\n        return null;\n    }\n    if (round) {\n        value = round === 'week' && (isNumber(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, 'isoWeek', isoWeekday) : adapter.startOf(value, round);\n    }\n    return +value;\n}\n function determineUnitForAutoTicks(minUnit, min, max, capacity) {\n    const ilen = UNITS.length;\n    for(let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i){\n        const interval = INTERVALS[UNITS[i]];\n        const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;\n        if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {\n            return UNITS[i];\n        }\n    }\n    return UNITS[ilen - 1];\n}\n function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {\n    for(let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--){\n        const unit = UNITS[i];\n        if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) {\n            return unit;\n        }\n    }\n    return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];\n}\n function determineMajorUnit(unit) {\n    for(let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i){\n        if (INTERVALS[UNITS[i]].common) {\n            return UNITS[i];\n        }\n    }\n}\n function addTick(ticks, time, timestamps) {\n    if (!timestamps) {\n        ticks[time] = true;\n    } else if (timestamps.length) {\n        const { lo , hi  } = _lookup(timestamps, time);\n        const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];\n        ticks[timestamp] = true;\n    }\n}\n function setMajorTicks(scale, ticks, map, majorUnit) {\n    const adapter = scale._adapter;\n    const first = +adapter.startOf(ticks[0].value, majorUnit);\n    const last = ticks[ticks.length - 1].value;\n    let major, index;\n    for(major = first; major <= last; major = +adapter.add(major, 1, majorUnit)){\n        index = map[major];\n        if (index >= 0) {\n            ticks[index].major = true;\n        }\n    }\n    return ticks;\n}\n function ticksFromTimestamps(scale, values, majorUnit) {\n    const ticks = [];\n     const map = {};\n    const ilen = values.length;\n    let i, value;\n    for(i = 0; i < ilen; ++i){\n        value = values[i];\n        map[value] = i;\n        ticks.push({\n            value,\n            major: false\n        });\n    }\n    return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map, majorUnit);\n}\nclass TimeScale extends Scale {\n    static id = 'time';\n static defaults = {\n bounds: 'data',\n        adapters: {},\n        time: {\n            parser: false,\n            unit: false,\n            round: false,\n            isoWeekday: false,\n            minUnit: 'millisecond',\n            displayFormats: {}\n        },\n        ticks: {\n source: 'auto',\n            callback: false,\n            major: {\n                enabled: false\n            }\n        }\n    };\n constructor(props){\n        super(props);\n         this._cache = {\n            data: [],\n            labels: [],\n            all: []\n        };\n         this._unit = 'day';\n         this._majorUnit = undefined;\n        this._offsets = {};\n        this._normalized = false;\n        this._parseOpts = undefined;\n    }\n    init(scaleOpts, opts = {}) {\n        const time = scaleOpts.time || (scaleOpts.time = {});\n         const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date);\n        adapter.init(opts);\n        mergeIf(time.displayFormats, adapter.formats());\n        this._parseOpts = {\n            parser: time.parser,\n            round: time.round,\n            isoWeekday: time.isoWeekday\n        };\n        super.init(scaleOpts);\n        this._normalized = opts.normalized;\n    }\n parse(raw, index) {\n        if (raw === undefined) {\n            return null;\n        }\n        return parse(this, raw);\n    }\n    beforeLayout() {\n        super.beforeLayout();\n        this._cache = {\n            data: [],\n            labels: [],\n            all: []\n        };\n    }\n    determineDataLimits() {\n        const options = this.options;\n        const adapter = this._adapter;\n        const unit = options.time.unit || 'day';\n        let { min , max , minDefined , maxDefined  } = this.getUserBounds();\n function _applyBounds(bounds) {\n            if (!minDefined && !isNaN(bounds.min)) {\n                min = Math.min(min, bounds.min);\n            }\n            if (!maxDefined && !isNaN(bounds.max)) {\n                max = Math.max(max, bounds.max);\n            }\n        }\n        if (!minDefined || !maxDefined) {\n            _applyBounds(this._getLabelBounds());\n            if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {\n                _applyBounds(this.getMinMax(false));\n            }\n        }\n        min = isNumberFinite(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);\n        max = isNumberFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;\n        this.min = Math.min(min, max - 1);\n        this.max = Math.max(min + 1, max);\n    }\n _getLabelBounds() {\n        const arr = this.getLabelTimestamps();\n        let min = Number.POSITIVE_INFINITY;\n        let max = Number.NEGATIVE_INFINITY;\n        if (arr.length) {\n            min = arr[0];\n            max = arr[arr.length - 1];\n        }\n        return {\n            min,\n            max\n        };\n    }\n buildTicks() {\n        const options = this.options;\n        const timeOpts = options.time;\n        const tickOpts = options.ticks;\n        const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate();\n        if (options.bounds === 'ticks' && timestamps.length) {\n            this.min = this._userMin || timestamps[0];\n            this.max = this._userMax || timestamps[timestamps.length - 1];\n        }\n        const min = this.min;\n        const max = this.max;\n        const ticks = _filterBetween(timestamps, min, max);\n        this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));\n        this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined : determineMajorUnit(this._unit);\n        this.initOffsets(timestamps);\n        if (options.reverse) {\n            ticks.reverse();\n        }\n        return ticksFromTimestamps(this, ticks, this._majorUnit);\n    }\n    afterAutoSkip() {\n        if (this.options.offsetAfterAutoskip) {\n            this.initOffsets(this.ticks.map((tick)=>+tick.value));\n        }\n    }\n initOffsets(timestamps = []) {\n        let start = 0;\n        let end = 0;\n        let first, last;\n        if (this.options.offset && timestamps.length) {\n            first = this.getDecimalForValue(timestamps[0]);\n            if (timestamps.length === 1) {\n                start = 1 - first;\n            } else {\n                start = (this.getDecimalForValue(timestamps[1]) - first) / 2;\n            }\n            last = this.getDecimalForValue(timestamps[timestamps.length - 1]);\n            if (timestamps.length === 1) {\n                end = last;\n            } else {\n                end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;\n            }\n        }\n        const limit = timestamps.length < 3 ? 0.5 : 0.25;\n        start = _limitValue(start, 0, limit);\n        end = _limitValue(end, 0, limit);\n        this._offsets = {\n            start,\n            end,\n            factor: 1 / (start + 1 + end)\n        };\n    }\n _generate() {\n        const adapter = this._adapter;\n        const min = this.min;\n        const max = this.max;\n        const options = this.options;\n        const timeOpts = options.time;\n        const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));\n        const stepSize = valueOrDefault(options.ticks.stepSize, 1);\n        const weekday = minor === 'week' ? timeOpts.isoWeekday : false;\n        const hasWeekday = isNumber(weekday) || weekday === true;\n        const ticks = {};\n        let first = min;\n        let time, count;\n        if (hasWeekday) {\n            first = +adapter.startOf(first, 'isoWeek', weekday);\n        }\n        first = +adapter.startOf(first, hasWeekday ? 'day' : minor);\n        if (adapter.diff(max, min, minor) > 100000 * stepSize) {\n            throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);\n        }\n        const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();\n        for(time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++){\n            addTick(ticks, time, timestamps);\n        }\n        if (time === max || options.bounds === 'ticks' || count === 1) {\n            addTick(ticks, time, timestamps);\n        }\n        return Object.keys(ticks).sort(sorter).map((x)=>+x);\n    }\n getLabelForValue(value) {\n        const adapter = this._adapter;\n        const timeOpts = this.options.time;\n        if (timeOpts.tooltipFormat) {\n            return adapter.format(value, timeOpts.tooltipFormat);\n        }\n        return adapter.format(value, timeOpts.displayFormats.datetime);\n    }\n format(value, format) {\n        const options = this.options;\n        const formats = options.time.displayFormats;\n        const unit = this._unit;\n        const fmt = format || formats[unit];\n        return this._adapter.format(value, fmt);\n    }\n _tickFormatFunction(time, index, ticks, format) {\n        const options = this.options;\n        const formatter = options.ticks.callback;\n        if (formatter) {\n            return callback(formatter, [\n                time,\n                index,\n                ticks\n            ], this);\n        }\n        const formats = options.time.displayFormats;\n        const unit = this._unit;\n        const majorUnit = this._majorUnit;\n        const minorFormat = unit && formats[unit];\n        const majorFormat = majorUnit && formats[majorUnit];\n        const tick = ticks[index];\n        const major = majorUnit && majorFormat && tick && tick.major;\n        return this._adapter.format(time, format || (major ? majorFormat : minorFormat));\n    }\n generateTickLabels(ticks) {\n        let i, ilen, tick;\n        for(i = 0, ilen = ticks.length; i < ilen; ++i){\n            tick = ticks[i];\n            tick.label = this._tickFormatFunction(tick.value, i, ticks);\n        }\n    }\n getDecimalForValue(value) {\n        return value === null ? NaN : (value - this.min) / (this.max - this.min);\n    }\n getPixelForValue(value) {\n        const offsets = this._offsets;\n        const pos = this.getDecimalForValue(value);\n        return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);\n    }\n getValueForPixel(pixel) {\n        const offsets = this._offsets;\n        const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;\n        return this.min + pos * (this.max - this.min);\n    }\n _getLabelSize(label) {\n        const ticksOpts = this.options.ticks;\n        const tickLabelWidth = this.ctx.measureText(label).width;\n        const angle = toRadians(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);\n        const cosRotation = Math.cos(angle);\n        const sinRotation = Math.sin(angle);\n        const tickFontSize = this._resolveTickFontOptions(0).size;\n        return {\n            w: tickLabelWidth * cosRotation + tickFontSize * sinRotation,\n            h: tickLabelWidth * sinRotation + tickFontSize * cosRotation\n        };\n    }\n _getLabelCapacity(exampleTime) {\n        const timeOpts = this.options.time;\n        const displayFormats = timeOpts.displayFormats;\n        const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;\n        const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [\n            exampleTime\n        ], this._majorUnit), format);\n        const size = this._getLabelSize(exampleLabel);\n        const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;\n        return capacity > 0 ? capacity : 1;\n    }\n getDataTimestamps() {\n        let timestamps = this._cache.data || [];\n        let i, ilen;\n        if (timestamps.length) {\n            return timestamps;\n        }\n        const metas = this.getMatchingVisibleMetas();\n        if (this._normalized && metas.length) {\n            return this._cache.data = metas[0].controller.getAllParsedValues(this);\n        }\n        for(i = 0, ilen = metas.length; i < ilen; ++i){\n            timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));\n        }\n        return this._cache.data = this.normalize(timestamps);\n    }\n getLabelTimestamps() {\n        const timestamps = this._cache.labels || [];\n        let i, ilen;\n        if (timestamps.length) {\n            return timestamps;\n        }\n        const labels = this.getLabels();\n        for(i = 0, ilen = labels.length; i < ilen; ++i){\n            timestamps.push(parse(this, labels[i]));\n        }\n        return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps);\n    }\n normalize(values) {\n        return _arrayUnique(values.sort(sorter));\n    }\n}\n\nfunction interpolate(table, val, reverse) {\n    let lo = 0;\n    let hi = table.length - 1;\n    let prevSource, nextSource, prevTarget, nextTarget;\n    if (reverse) {\n        if (val >= table[lo].pos && val <= table[hi].pos) {\n            ({ lo , hi  } = _lookupByKey(table, 'pos', val));\n        }\n        ({ pos: prevSource , time: prevTarget  } = table[lo]);\n        ({ pos: nextSource , time: nextTarget  } = table[hi]);\n    } else {\n        if (val >= table[lo].time && val <= table[hi].time) {\n            ({ lo , hi  } = _lookupByKey(table, 'time', val));\n        }\n        ({ time: prevSource , pos: prevTarget  } = table[lo]);\n        ({ time: nextSource , pos: nextTarget  } = table[hi]);\n    }\n    const span = nextSource - prevSource;\n    return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;\n}\nclass TimeSeriesScale extends TimeScale {\n    static id = 'timeseries';\n static defaults = TimeScale.defaults;\n constructor(props){\n        super(props);\n         this._table = [];\n         this._minPos = undefined;\n         this._tableRange = undefined;\n    }\n initOffsets() {\n        const timestamps = this._getTimestampsForTable();\n        const table = this._table = this.buildLookupTable(timestamps);\n        this._minPos = interpolate(table, this.min);\n        this._tableRange = interpolate(table, this.max) - this._minPos;\n        super.initOffsets(timestamps);\n    }\n buildLookupTable(timestamps) {\n        const { min , max  } = this;\n        const items = [];\n        const table = [];\n        let i, ilen, prev, curr, next;\n        for(i = 0, ilen = timestamps.length; i < ilen; ++i){\n            curr = timestamps[i];\n            if (curr >= min && curr <= max) {\n                items.push(curr);\n            }\n        }\n        if (items.length < 2) {\n            return [\n                {\n                    time: min,\n                    pos: 0\n                },\n                {\n                    time: max,\n                    pos: 1\n                }\n            ];\n        }\n        for(i = 0, ilen = items.length; i < ilen; ++i){\n            next = items[i + 1];\n            prev = items[i - 1];\n            curr = items[i];\n            if (Math.round((next + prev) / 2) !== curr) {\n                table.push({\n                    time: curr,\n                    pos: i / (ilen - 1)\n                });\n            }\n        }\n        return table;\n    }\n _generate() {\n        const min = this.min;\n        const max = this.max;\n        let timestamps = super.getDataTimestamps();\n        if (!timestamps.includes(min) || !timestamps.length) {\n            timestamps.splice(0, 0, min);\n        }\n        if (!timestamps.includes(max) || timestamps.length === 1) {\n            timestamps.push(max);\n        }\n        return timestamps.sort((a, b)=>a - b);\n    }\n _getTimestampsForTable() {\n        let timestamps = this._cache.all || [];\n        if (timestamps.length) {\n            return timestamps;\n        }\n        const data = this.getDataTimestamps();\n        const label = this.getLabelTimestamps();\n        if (data.length && label.length) {\n            timestamps = this.normalize(data.concat(label));\n        } else {\n            timestamps = data.length ? data : label;\n        }\n        timestamps = this._cache.all = timestamps;\n        return timestamps;\n    }\n getDecimalForValue(value) {\n        return (interpolate(this._table, value) - this._minPos) / this._tableRange;\n    }\n getValueForPixel(pixel) {\n        const offsets = this._offsets;\n        const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;\n        return interpolate(this._table, decimal * this._tableRange + this._minPos, true);\n    }\n}\n\nvar scales = /*#__PURE__*/Object.freeze({\n__proto__: null,\nCategoryScale: CategoryScale,\nLinearScale: LinearScale,\nLogarithmicScale: LogarithmicScale,\nRadialLinearScale: RadialLinearScale,\nTimeScale: TimeScale,\nTimeSeriesScale: TimeSeriesScale\n});\n\nconst registerables = [\n    controllers,\n    elements,\n    plugins,\n    scales\n];\n\nexport { Animation, Animations, ArcElement, BarController, BarElement, BasePlatform, BasicPlatform, BubbleController, CategoryScale, Chart, plugin_colors as Colors, DatasetController, plugin_decimation as Decimation, DomPlatform, DoughnutController, Element, index as Filler, Interaction, plugin_legend as Legend, LineController, LineElement, LinearScale, LogarithmicScale, PieController, PointElement, PolarAreaController, RadarController, RadialLinearScale, Scale, ScatterController, plugin_subtitle as SubTitle, Ticks, TimeScale, TimeSeriesScale, plugin_title as Title, plugin_tooltip as Tooltip, adapters as _adapters, _detectPlatform, animator, controllers, defaults, elements, layouts, plugins, registerables, registry, scales };\n//# sourceMappingURL=chart.js.map\n","import angular from \"angular\";\r\nimport { Brand, Calculation, Translations } from \"@salaxy/core\";\r\nimport { Chart, registerables } from \"chart.js\";\r\nimport type { ChartType } from \"chart.js\";\r\n/** Register chart registerables (ex. tooltip) */\r\nChart.register(...registerables);\r\n\r\n/**\r\n * Controller for employer and worker charts using chart.js\r\n */\r\nexport class CalcChartController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$element\", \"$timeout\", \"$scope\"];\r\n\r\n  /** Role for which the chart is rendered: employer (default) or worker */\r\n  public role: \"employer\" | \"worker\";\r\n\r\n  /** Calculation that is rendered. */\r\n  public calc: Calculation;\r\n\r\n  /** Y axis scale */\r\n  public scaleYAxis: boolean;\r\n\r\n  /** Chart type: \"pie\" and \"bar\" (default) are currently supported. */\r\n  public chartType: \"pie\" | \"bar\";\r\n\r\n  private chart: Chart;\r\n\r\n  /** Created datasets from Calculation input */\r\n  private datasetData: any = {};\r\n\r\n  private barChartOptions: any = {};\r\n\r\n  private pieChartOptions: any = {};\r\n\r\n  private chartColors: any = {};\r\n\r\n  constructor(\r\n    private $element: JQLite,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $scope: angular.IScope,\r\n  ) {}\r\n\r\n  /** Initializes the controller. */\r\n  public init() {\r\n    this.role = this.role || \"employer\";\r\n    this.chartType = this.chartType || \"bar\";\r\n    this.setChartOptions();\r\n    this.setChartColors();\r\n    this.$timeout(() => {\r\n      this.createChart();\r\n    });\r\n    this.$scope.$watch(() => ( { chartType: this.chartType, result: this.calc?.result } ), (newValue) => {\r\n      if (newValue) {\r\n\r\n        // update chart does not work, but renders columns instead of pie.\r\n        // this.updateChart();\r\n        if (this.chart) {\r\n          this.chart.destroy();\r\n          this.chart = null;\r\n        }\r\n        this.createChart();\r\n      }\r\n    }, true);\r\n  }\r\n\r\n  /** Creates chart based on data and options to canvas or updates chart if it already exists */\r\n  public createChart(): void {\r\n    this.datasetData = this.getDatasetData;\r\n    if (this.scaleYAxis) {\r\n      if (\r\n        this.datasetData.workerChartScale > this.datasetData.employerChartScale\r\n      ) {\r\n        this.setChartYAxisLimit(this.datasetData.workerChartScale);\r\n      } else {\r\n        this.setChartYAxisLimit(this.datasetData.employerChartScale);\r\n      }\r\n    } else {\r\n      if (this.role === \"worker\") {\r\n        this.setChartYAxisLimit(this.datasetData.workerChartScale);\r\n      } else {\r\n        this.setChartYAxisLimit(this.datasetData.employerChartScale);\r\n      }\r\n    }\r\n    const data = this.getChartData();\r\n    const options = this.chartType === \"bar\" ? this.barChartOptions : this.pieChartOptions;\r\n    if (!this.chart) {\r\n      const ctx = (this.$element.find(\"canvas\")[0] as HTMLCanvasElement)?.getContext(\"2d\");\r\n      if (ctx) {\r\n        this.chart = new Chart(ctx, {\r\n          type: this.chartType as ChartType,\r\n          data,\r\n          options,\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates provided current chart\r\n   * \"none\" parameters means no animation for update\r\n   */\r\n  public updateChart(): void {\r\n    if(this.chart) {\r\n      this.datasetData = this.getDatasetData;\r\n      if (this.scaleYAxis) {\r\n        if (\r\n          this.datasetData.workerChartScale > this.datasetData.employerChartScale\r\n        ) {\r\n          this.setChartYAxisLimit(this.datasetData.workerChartScale);\r\n        } else {\r\n          this.setChartYAxisLimit(this.datasetData.employerChartScale);\r\n        }\r\n      } else {\r\n        if (this.role === \"worker\") {\r\n          this.setChartYAxisLimit(this.datasetData.workerChartScale);\r\n        } else {\r\n          this.setChartYAxisLimit(this.datasetData.employerChartScale);\r\n        }\r\n      }\r\n      const data = this.getChartData();\r\n      const options = this.chartType === \"bar\" ? this.barChartOptions : this.pieChartOptions;\r\n      this.chart.data = data;\r\n      this.chart.options = options;\r\n      this.chart.update(\"none\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Calculates and sets a proper Y axis max value for a given value\r\n   * @param value The number of the highest bar in chart\r\n   */\r\n  private setChartYAxisLimit(value: number) {\r\n    const log = Math.round(Math.log10(value));\r\n    const times = Math.ceil(value / Math.pow(10, log - 1));\r\n    const newValue = Math.pow(10, log - 1) * times;\r\n    this.barChartOptions.scales.y = {\r\n      stacked: true,\r\n      min: 0,\r\n      max: newValue,\r\n      ticks: {\r\n        callback: function(val) {\r\n          return Number.isInteger(val) ? val : null;\r\n        }\r\n      }\r\n    };\r\n  }\r\n\r\n  private getChartData(): { labels: string[]; datasets: any[] } {\r\n    switch (this.role) {\r\n      case \"worker\":\r\n        return {\r\n          labels: [\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.salaryPayment\"\r\n            )} ${this.formatCurrency(this.datasetData.salaryPayment)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.tax\"\r\n            )} ${this.formatCurrency(this.datasetData.tax)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.workerSideCosts\"\r\n            )} ${this.formatCurrency(this.datasetData.workerSideCosts)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.totalExpenses\"\r\n            )} ${this.formatCurrency(\r\n              this.datasetData.benefits + this.datasetData.totalExpenses\r\n            )}`,\r\n          ],\r\n          datasets: this.getDatasets(),\r\n        };\r\n      case \"employer\":\r\n        return {\r\n          labels: [\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.totalGrossSalary\"\r\n            )} ${this.formatCurrency(this.datasetData.totalGrossSalary)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.salaryAdditions\"\r\n            )} ${this.formatCurrency(this.datasetData.salaryAdditions)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.allSideCosts\"\r\n            )} ${this.formatCurrency(this.datasetData.allSideCosts)}`,\r\n            `${Translations.get(\r\n              \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.totalExpenses\"\r\n            )} ${this.formatCurrency(this.datasetData.totalExpenses)}`,\r\n          ],\r\n          datasets: this.getDatasets(),\r\n        };\r\n      default:\r\n        return {\r\n          labels: [],\r\n          datasets: [],\r\n        };\r\n    }\r\n  }\r\n\r\n  private formatCurrency(value: number) {\r\n    const formatter = new Intl.NumberFormat(\"fi-FI\", {\r\n      style: \"currency\",\r\n      currency: \"EUR\",\r\n      minimumFractionDigits: 2,\r\n    });\r\n    return formatter.format(value);\r\n  }\r\n  private setChartOptions(): any {\r\n    this.barChartOptions = {\r\n      label: \"\",\r\n      responsive: true,\r\n      maintainAspectRatio: false,\r\n      scales: {\r\n        x: {\r\n          stacked: true,\r\n          min: 0,\r\n          max: 0,\r\n          display: false,\r\n        },\r\n        y: {\r\n          stacked: true,\r\n          min: 0,\r\n          max: 5000,\r\n          ticks: {\r\n            callback: function(val) {\r\n              return Number.isInteger(val) ? val : null;\r\n            }\r\n          }\r\n        },\r\n      },\r\n      plugins: {\r\n        datalabels: {\r\n          display: false,\r\n        },\r\n        legend: {\r\n          display: false,\r\n        },\r\n        tooltip: {\r\n          mode: \"index\",\r\n          callbacks: {\r\n            title() {\r\n              return \"\";\r\n            },\r\n            label(context: any) {\r\n              return context.dataset.label ?? \"\";\r\n            },\r\n          },\r\n          itemSort(a: { datasetIndex: number }, b: { datasetIndex: number }) {\r\n            return b.datasetIndex - a.datasetIndex;\r\n          },\r\n        },\r\n      },\r\n      events: [\"mousemove\", \"click\"],\r\n    };\r\n\r\n    this.pieChartOptions = {\r\n      plugins: {\r\n        legend: {\r\n          display: false,\r\n        },\r\n        tooltip: {\r\n          mode: \"dataset\",\r\n          callbacks: {\r\n            title() {\r\n              return \"\";\r\n            },\r\n            label(context: any) {\r\n              return context.label ?? \"\";\r\n            },\r\n          },\r\n          itemSort(a: { datasetIndex: number }, b: { datasetIndex: number }) {\r\n            return b.datasetIndex - a.datasetIndex;\r\n          },\r\n        },\r\n      },\r\n      events: [\"mousemove\", \"click\"],\r\n    };\r\n  }\r\n\r\n  private getDatasets(): any[] {\r\n    if (this.chartType === \"pie\") {\r\n      switch (this.role) {\r\n        case \"worker\":\r\n          return [\r\n            {\r\n              label: \"\",\r\n              data: [\r\n                this.datasetData.salaryPayment,\r\n                this.datasetData.tax,\r\n                this.datasetData.workerSideCosts,\r\n                this.datasetData.benefits + this.datasetData.totalExpenses,\r\n              ],\r\n              backgroundColor: [\r\n                this.chartColors.info,\r\n                this.chartColors.success,\r\n                this.chartColors.warning,\r\n                this.chartColors.danger,\r\n              ],\r\n            },\r\n          ];\r\n        case \"employer\":\r\n          return [\r\n            {\r\n              label: \"\",\r\n              data: [\r\n                this.datasetData.totalGrossSalary,\r\n                this.datasetData.salaryAdditions,\r\n                this.datasetData.allSideCosts,\r\n                this.datasetData.totalExpenses,\r\n              ],\r\n              backgroundColor: [\r\n                this.chartColors.info,\r\n                this.chartColors.success,\r\n                this.chartColors.warning,\r\n                this.chartColors.danger,\r\n              ],\r\n            },\r\n          ];\r\n        default:\r\n          return [];\r\n      }\r\n    } else {\r\n      switch (this.role) {\r\n        case \"worker\":\r\n          return [\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.salaryPayment\"\r\n                ) + this.formatCurrency(this.datasetData.salaryPayment),\r\n              data: [this.datasetData.salaryPayment],\r\n              backgroundColor: this.chartColors.info,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.tax\"\r\n                ) + this.formatCurrency(this.datasetData.tax),\r\n              data: [this.datasetData.tax],\r\n              backgroundColor: this.chartColors.success,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.workerSideCosts\"\r\n                ) + this.formatCurrency(this.datasetData.workerSideCosts),\r\n              data: [this.datasetData.workerSideCosts],\r\n              backgroundColor: this.chartColors.warning,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartWorker.seriesLabel.totalExpenses\"\r\n                ) +\r\n                this.formatCurrency(\r\n                  this.datasetData.benefits + this.datasetData.totalExpenses\r\n                ),\r\n              data: [\r\n                this.datasetData.benefits + this.datasetData.totalExpenses,\r\n              ],\r\n              backgroundColor: this.chartColors.danger,\r\n            },\r\n          ];\r\n        case \"employer\":\r\n          return [\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.totalGrossSalary\"\r\n                ) + this.formatCurrency(this.datasetData.totalGrossSalary),\r\n              data: [this.datasetData.totalGrossSalary],\r\n              backgroundColor: this.chartColors.info,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.salaryAdditions\"\r\n                ) + this.formatCurrency(this.datasetData.salaryAdditions),\r\n              data: [this.datasetData.salaryAdditions],\r\n              backgroundColor: this.chartColors.success,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.allSideCosts\"\r\n                ) + this.formatCurrency(this.datasetData.allSideCosts),\r\n              data: [this.datasetData.allSideCosts],\r\n              backgroundColor: this.chartColors.warning,\r\n            },\r\n            {\r\n              label:\r\n                Translations.get(\r\n                  \"SALAXY.NG1.CalcChartComponent.createChartEmployer.seriesLabel.totalExpenses\"\r\n                ) + this.formatCurrency(this.datasetData.totalExpenses),\r\n              data: [this.datasetData.totalExpenses],\r\n              backgroundColor: this.chartColors.danger,\r\n            },\r\n          ];\r\n\r\n        default:\r\n          return [];\r\n      }\r\n    }\r\n  }\r\n\r\n  private setChartColors() {\r\n    const getColorSet = (code: string) =>\r\n      Brand.getBrandColor(code as any, \"rgba\");\r\n    this.chartColors = {\r\n      info: getColorSet(\"info\"),\r\n      success: getColorSet(\"success\"),\r\n      warning: getColorSet(\"warning\"),\r\n      danger: getColorSet(\"danger\"),\r\n    };\r\n  }\r\n\r\n  private get getDatasetData(): any {\r\n    const calc: Calculation = this.calc;\r\n    if (!calc || !calc.result) {\r\n      return {};\r\n    }\r\n\r\n    const { result } = calc;\r\n    const data = {\r\n      // Employer numbers\r\n      totalGrossSalary: result.totals.totalBaseSalary,\r\n      salaryAdditions:\r\n        result.totals.totalGrossSalary - result.totals?.totalBaseSalary,\r\n      allSideCosts: result.employerCalc.allSideCosts,\r\n      finalCost: result.employerCalc.finalCost,\r\n\r\n      // Worker numbers\r\n      salaryPayment: result.workerCalc.salaryPayment,\r\n      tax: result.workerCalc.tax,\r\n      workerSideCosts: result.workerCalc.workerSideCosts,\r\n      benefits: result.workerCalc.benefits,\r\n      totalExpenses: result.totals.totalExpenses,\r\n      totalWorkerPayment: result.workerCalc.totalWorkerPayment,\r\n\r\n      // Chart scales\r\n      employerChartScale: 0,\r\n      workerChartScale: 0,\r\n    };\r\n\r\n    // Calculating max y axis limits\r\n    data.employerChartScale =\r\n      data.totalGrossSalary +\r\n      data.salaryAdditions +\r\n      data.allSideCosts +\r\n      data.totalExpenses;\r\n    data.workerChartScale =\r\n      data.salaryPayment +\r\n      data.tax +\r\n      data.workerSideCosts +\r\n      data.benefits +\r\n      data.totalExpenses;\r\n    return data;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculation, CalculationRowType, CalculationRowUnit, Calculations, CalculatorLogic, DateRange,\r\n  HouseholdUsecase, HouseholdUsecasesLogic, UserDefinedRow, WorkerAccount, Workers, CalcWorktime, Dates, Translations,\r\n} from \"@salaxy/core\";\r\n\r\nimport { UiHelpers\r\n} from \"../../services\";\r\n\r\n/**\r\n * Handles the user interaction of Worktime within the Calculator.\r\n * The Worktime contains the logic for fetching holidays and absences\r\n * for that particular period and adding calculation rows for them if necessary.\r\n */\r\nexport class CalcHouseholdUsecaseController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Calculations\",\r\n    \"Workers\",\r\n  ];\r\n\r\n    /** User interface shortcuts for period selection */\r\n    public periodShortcuts: {\r\n      /** Text for current month. */\r\n      monthCurrent: string,\r\n      /** Text for last month. */\r\n      monthLast: string,\r\n      /** Text for other month. */\r\n      monthOther: string,\r\n      // monthMulti: \"Monta kuukautta\",\r\n      /** Text for two weeks. */\r\n      weeks2: string,\r\n      /** Text for half a month */\r\n      monthHalf: string,\r\n      /** Text for other period. */\r\n      other: string,\r\n    };\r\n  /** The calculation that the controller edits. */\r\n  public calc: Calculation;\r\n\r\n  /** Alternative data binding: creates a calculation based on Worker defaults. */\r\n  public worker: WorkerAccount;\r\n\r\n  /**\r\n   * Shows the Save and Reset buttons.\r\n   * Currently, this is only enabled for WorkerAccount data binding, but mayu later be enabled for calc.\r\n   */\r\n  public showSave: boolean;\r\n\r\n  /**\r\n   * If true, indicates that we are editing salary template information for employment relation:\r\n   * Not a concrete calculation.\r\n   */\r\n  public isEmployment: boolean;\r\n\r\n  /** If true, the UI is in read-only mode. */\r\n  public isReadOnly: boolean;\r\n\r\n\r\n  /** If there is a validation error in period start, it is added here. */\r\n  public periodStartDateError = null;\r\n\r\n  /**\r\n   * Worktime data for the period fetched from the server\r\n   */\r\n  public worktime: CalcWorktime;\r\n\r\n\r\n  /** The tree for selecting the calculation usecase (household) */\r\n  private tree = HouseholdUsecasesLogic.getUsecaseTree();\r\n\r\n  private _periodStartDate;\r\n\r\n  private _dateRange: DateRange;\r\n\r\n\r\n  /**\r\n   * Creates a new CalcHouseholdUsecaseController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private calcApi: Calculations,\r\n    private workersApi: Workers,\r\n\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    if (!this.calc && this.worker) {\r\n      this.resetEmployment();\r\n    }\r\n    this.initDateRanges();\r\n\r\n  }\r\n\r\n\r\n  /**\r\n   * The use case that we are editing\r\n   */\r\n  public get usecaseData(): HouseholdUsecase {\r\n    return this.calc.usecase.data as HouseholdUsecase;\r\n  }\r\n\r\n  /** Gets the view template that is used for showing the usecase details part. */\r\n  public getTemplate() {\r\n    let group = \"other\";\r\n    switch (this.usecaseData.uri) {\r\n      case HouseholdUsecasesLogic.knownUseCases.childCare:\r\n      case HouseholdUsecasesLogic.knownUseCases.mll:\r\n        group = \"childCare\";\r\n        break;\r\n      case HouseholdUsecasesLogic.knownUseCases.cleaning:\r\n        group = \"cleaning\";\r\n        break;\r\n      case HouseholdUsecasesLogic.knownUseCases.construction:\r\n        group = \"construction\";\r\n        break;\r\n      case HouseholdUsecasesLogic.knownUseCases.santaClaus:\r\n      case HouseholdUsecasesLogic.knownUseCases.other:\r\n      default:\r\n        group = \"other\";\r\n        break;\r\n    }\r\n    return `salaxy-components/calc/usecases/household-${group}.html`;\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the isHouseholdDeductible within the usecase.\r\n   * Currently, this is part of the usecase specification and will be set to Salary (household properties in V03) from there.\r\n   */\r\n  public get isHouseholdDeductible(): boolean {\r\n    return this.usecaseData.isHouseholdDeductible;\r\n  }\r\n  public set isHouseholdDeductible(value: boolean) {\r\n    this.usecaseData.isHouseholdDeductible = value;\r\n  }\r\n\r\n   /** Gets the current calculation object */\r\n   public get currentCalc(): Calculation {\r\n    return this.calc;\r\n  }\r\n\r\n  /**\r\n   * Returns true if there is no net salary payment to worker at all.\r\n   */\r\n  public get isCurrentZeroPayment(): boolean {\r\n    return CalculatorLogic.isZeroPayment(this.calc);\r\n  }\r\n\r\n  /**\r\n   * Submit the usecase data and recalculate\r\n   */\r\n  public submitHouseholdUsecase() {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isCalculating\");\r\n    HouseholdUsecasesLogic.applyUseCase(this.calc);\r\n    this.calcApi.recalculate(this.calc).then((data) => {\r\n      angular.copy(data, this.calc);\r\n      loader.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Saves the usecase to employment */\r\n  public saveEmployment() {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n    this.isReadOnly = true;\r\n    this.updateWorkerAccount().then(() => {\r\n      this.workersApi.save(this.worker).then(() => {\r\n        loader.dismiss();\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Does recalculation on the usecase and and applies it to worker account.\r\n   * @returns The updated worker account. The changes are also applied to the worker property.\r\n   */\r\n  public updateWorkerAccount(): Promise<WorkerAccount> {\r\n    HouseholdUsecasesLogic.applyUseCase(this.calc);\r\n    return this.calcApi.recalculate(this.calc).then((calcResult) => {\r\n      this.worker.employment.usecase = calcResult.usecase;\r\n      this.worker.employment.usecase.data.copyToCalc = true;\r\n      this.worker.employment.work.salaryDefaults = calcResult.rows;\r\n      this.worker.employment.work.occupationCode = calcResult.info.occupationCode;\r\n      return this.worker;\r\n    });\r\n  }\r\n\r\n  /** Resets the usecase from employment */\r\n  public resetEmployment() {\r\n    this.isEmployment = true;\r\n    this.calc = CalculatorLogic.getBlank();\r\n    this.calc.usecase = {};\r\n    angular.copy(this.worker.employment.work.salaryDefaults, this.calc.rows);\r\n    angular.copy(this.worker.employment.usecase, this.calc.usecase);\r\n    if (this.calc.usecase?.uri) {\r\n      this.isReadOnly = true;\r\n      HouseholdUsecasesLogic.applyUseCase(this.calc);\r\n    } else {\r\n      this.isReadOnly = false;\r\n    }\r\n  }\r\n\r\n  /** Starts the edit mode if the component is in read-only mode.  */\r\n  public startEdit() {\r\n    this.isReadOnly = false;\r\n  }\r\n\r\n  /**\r\n   * The salary row is the first row is the first row in the rows list\r\n   */\r\n  public get salaryRow(): UserDefinedRow {\r\n    return CalculatorLogic.getSalaryRow(this.calc);\r\n  }\r\n\r\n  /** Returns true if the usecase has been selected. */\r\n  public get isUsecaseSelected(): boolean {\r\n    return !!this.calc?.usecase?.uri;\r\n  }\r\n\r\n  /** Gets the label for price input */\r\n  public get priceLabel() {\r\n    switch (this.salaryRow.rowType) {\r\n      case CalculationRowType.Compensation:\r\n        return \"Työkorvaus\";\r\n      case CalculationRowType.Salary:\r\n        return \"Kertakorvaus\";\r\n      case CalculationRowType.HourlySalary:\r\n        return \"Tuntipalkka\";\r\n      case CalculationRowType.MonthlySalary:\r\n        return \"Kuukausipalkka\";\r\n      case CalculationRowType.TotalEmployerPayment:\r\n        return \"Kokonaiskustannus\";\r\n      case CalculationRowType.TotalWorkerPayment:\r\n        return \"Nettopalkka\";\r\n      default:\r\n        return \"Hinta\";\r\n    }\r\n  }\r\n  /**\r\n   * Select and set usecase in UI\r\n   */\r\n  public selectUsecase(usecase) {\r\n    this.calc.rows = [];\r\n    HouseholdUsecasesLogic.setUsecase(this.calc, usecase);\r\n  }\r\n\r\n  /** Resets the price and amount when row type is changed. */\r\n  public changeRowType() {\r\n    this.salaryRow.price = null;\r\n    if (this.salaryRow.rowType === CalculationRowType.HourlySalary) {\r\n      this.salaryRow.count = null;\r\n      this.salaryRow.unit = CalculationRowUnit.Hours;\r\n    } else {\r\n      this.salaryRow.count = 1;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Resets the usecase to empty: Shows the usecase selection again.\r\n   */\r\n  public resetUsecase() {\r\n    this.calc.usecase = {};\r\n  }\r\n\r\n  /** Getter and setter for Calculation daterange in compatible format for new DateRange component. */\r\n  public get dateRange(): DateRange {\r\n    const info = (this.calc || {}).info;\r\n    const framework = (this.calc || {}).framework;\r\n    if (!this._dateRange) {\r\n      this._dateRange = {\r\n        start: info.workStartDate,\r\n        end: info.workEndDate,\r\n        daysCount: framework.numberOfDays,\r\n      };\r\n    }\r\n    return this._dateRange;\r\n  }\r\n  public set dateRange(value: DateRange) {\r\n    this._dateRange = value;\r\n  }\r\n\r\n  /**\r\n   * Called when the date range changes.\r\n   * @param noPeriodStartDateUpdate If true, the _periodStartDate is not updated.\r\n   * Should be true if the change is triggered by that input to avoid UI flickering.\r\n   */\r\n  public dateRangeChange(noPeriodStartDateUpdate = false) {\r\n    const info = (this.currentCalc || {}).info;\r\n    const framework = (this.currentCalc || {}).framework;\r\n    info.workStartDate = this.dateRange.start;\r\n    if (!noPeriodStartDateUpdate) {\r\n      this._periodStartDate = Dates.format(this.dateRange.start, \"D.M.\", null);\r\n    }\r\n    info.workEndDate = this.dateRange.end;\r\n    framework.numberOfDays = this.dateRange.daysCount;\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the period start date, which is bound to editable input in case the period type\r\n   * is not \"other\" (date the range / calendar component)\r\n   */\r\n  public get periodStartDate(): string {\r\n    return this._periodStartDate;\r\n  }\r\n  public set periodStartDate(value: string) {\r\n    this._periodStartDate = value;\r\n    const parts = (value || \"\").split(\".\");\r\n    if (parts.length < 2 || parts.length > 3) {\r\n      this.periodStartDateError = \"Syötä muodossa 'pv.kk.'\";\r\n      return;\r\n    }\r\n    let year = (parts.length === 3) ? Number((parts[2] || \"\").trim()) : null;\r\n    if (!year || year < 2019 || year > 2100) {\r\n      year = Number(this.dateRange.start.substr(0, 4));\r\n    }\r\n    const date = Dates.getDate(year, Number(parts[1]), Number(parts[0]));\r\n    if (date) {\r\n      this.periodStartDateError = null;\r\n      switch (this.periodShortcut) {\r\n        case \"monthCurrent\":\r\n        case \"monthLast\":\r\n        case \"monthOther\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,1,\"month\"),-1,\"day\"));\r\n          break;\r\n        case \"weeks2\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,2,\"week\"),-1,\"day\"));\r\n          break;\r\n        case \"monthHalf\":\r\n          if (Dates.getDay(date) === 15 || Dates.getDay(date) === 16) {\r\n            this.dateRange = Dates.getDateRange(date, Dates.startEnd(date,\"end-month\"));\r\n          } else {\r\n            this.dateRange = Dates.getDateRange(date, Dates.add(date,14, \"day\"));\r\n          }\r\n          break;\r\n        case \"other\":\r\n          this.dateRange = Dates.getDateRange(date, date);\r\n          break;\r\n      }\r\n      this.dateRangeChange(true);\r\n    } else {\r\n      this.periodStartDateError = `${value} ei ole päivämäärä.`;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the user interface shortcut for the period type:\r\n   * Different user interfaces are shown depending on the period shortcut.\r\n   */\r\n  public get periodShortcut(): \"monthCurrent\" | \"monthLast\" | \"monthOther\" | \"weeks2\" | \"monthHalf\" | \"other\" {\r\n    if (!this.dateRange.start || !this.dateRange.end) {\r\n      return null;\r\n    }\r\n    if (this.dateRange.start === Dates.getDate(\"today\", \"today\", 1)\r\n      && this.dateRange.end === Dates.startEnd(\"today\",\"end-month\")) {\r\n\r\n      return \"monthCurrent\";\r\n    }\r\n    if (this.dateRange.start === Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1,\"month\")\r\n      && this.dateRange.end === Dates.startEnd(Dates.add(Dates.startEnd(\"today\", \"start-month\"),-1,\"month\"),\"end-month\")) {\r\n      return \"monthLast\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start, 1, \"month\"), -1, \"day\")) {\r\n      return \"monthOther\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start,2, \"week\"),-1, \"day\")) {\r\n      return \"weeks2\";\r\n    }\r\n\r\n    // if the range is 15 (14) days or\r\n    // starts 15th or 16th and ends month end\r\n    if ((Dates.getDuration(this.dateRange.start, this.dateRange.end).days() === 14)\r\n      || (Dates.getDay(this.dateRange.start) === 15 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))\r\n      || (Dates.getDay(this.dateRange.start) === 16 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))) {\r\n      return \"monthHalf\";\r\n    }\r\n    return \"other\";\r\n  }\r\n  public set periodShortcut(value: \"monthCurrent\" | \"monthLast\" | \"monthOther\" | \"weeks2\" | \"monthHalf\" | \"other\") {\r\n    this.periodStartDateError = null;\r\n    switch (value) {\r\n      case \"monthCurrent\":\r\n        this.dateRange.start = Dates.getDate(\"today\", \"today\", 1);\r\n        this.dateRange.end = Dates.startEnd(\"today\",\"end-month\");\r\n        break;\r\n      case \"monthOther\":\r\n        if (Dates.getDay(\"today\") === 1) {\r\n          // Move to tomorrow so that the selection is monthOther and not monthCurrent.\r\n          this.dateRange.start = Dates.add(\"today\",1,\"day\");\r\n        } else {\r\n          this.dateRange.start = Dates.asDate(\"today\");\r\n        }\r\n        this.dateRange.end = Dates.add(Dates.add(this.dateRange.start,1,\"month\"),-1,\"day\");\r\n        break;\r\n      case \"monthLast\":\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1,\"month\");\r\n        this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        break;\r\n        case \"weeks2\": //TODO Review this\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-2,\"week\"); //shift to start of current week, and then 2 weeks before\r\n        this.dateRange.end = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-1,\"day\"); //shift to last day of previous week.\r\n        break;\r\n      case \"monthHalf\":\r\n        // TODO Check this\r\n        if (Dates.getDay(\"today\") < 16) {\r\n          // 16 - (28,29,30,31)\r\n          this.dateRange.start = Dates.add(Dates.add(Dates.startEnd(\"today\", \"start-month\"),-1,\"month\"),15,\"day\");\r\n          this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        } else {\r\n          // 1 - 15\r\n          this.dateRange.start = Dates.startEnd(\"today\",\"start-month\");\r\n          this.dateRange.end = Dates.add(this.dateRange.start,14,\"day\");\r\n        }\r\n        break;\r\n      case \"other\":\r\n        this.dateRange.start = Dates.add(\"today\",-1,\"day\");\r\n        this.dateRange.end = Dates.asDate(\"today\");\r\n        break;\r\n    }\r\n    this.dateRange = Dates.getDateRange(this.dateRange.start, this.dateRange.end);\r\n    this.dateRangeChange();\r\n  }\r\n  private initDateRanges() {\r\n    const currentMonth = Dates.getMonth(Dates.getToday());\r\n    this.periodShortcuts = {\r\n      monthCurrent: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth}.label`),\r\n      monthLast: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth === 1 ? 12 : (currentMonth - 1)}.label`),\r\n      monthOther: \"Muu kuukausi\",\r\n      // monthMulti: \"Monta kuukautta\",\r\n      weeks2: Translations.get(\"SALAXY.UI_Terms.week2\"),\r\n      monthHalf: Translations.get(\"SALAXY.UI_Terms.monthHalf\"),\r\n      other: Translations.get(\"SALAXY.UI_Terms.otherPeriod\"),\r\n    };\r\n    this._periodStartDate = Dates.format(this.dateRange.start, \"D.M.\", null);\r\n  }\r\n}\r\n","/** Logical section / area of the calculator ui. */\r\nexport class CalculatorSection {\r\n\r\n  /**\r\n   * Creates a new CalculatorSection\r\n   * @param isActive - If true, the section is currently active / selected in te user interface.\r\n   * @param isSelectionDone - If true, user has selected some values for the section\r\n   * @param title - Short text title for the section\r\n   */\r\n  constructor(public isActive: boolean, public isSelectionDone: boolean, public title: string) {\r\n  }\r\n\r\n  /**\r\n   * Shortcut for isSelectionDone or isActive.\r\n   * This is when the overview window should be shown colored\r\n   */\r\n  get isOverviewActive() {\r\n      return this.isSelectionDone || this.isActive;\r\n  }\r\n}\r\n","import { Calculation, CalculationStatus, CalculatorLogic, Numeric, Translations, UnionPaymentType } from \"@salaxy/core\";\r\nimport { CalculatorSection } from \"./CalculatorSection\";\r\n\r\n/** Sections defines areas of the calculator: worker, household-usecase, worktime, salary, expenses and results. */\r\nexport class CalculatorSections {\r\n\r\n  /**\r\n   * Creates a new CalculatorSections helper for a calculation\r\n   * @param calc The Calculation object for which the helper operates\r\n   */\r\n  constructor(public calc: Calculation) {\r\n    if (!calc || Object.keys(calc).length === 0) {\r\n      this.calc = CalculatorLogic.getBlank();\r\n    }\r\n  }\r\n\r\n  /** Stores the UI properties to the calculation until a roundtrip to server. Then the property is set to null */\r\n  public get ui(): any {\r\n    return CalculatorLogic.getUiCache(this.calc);\r\n  }\r\n\r\n  /**\r\n   * Activates a section in the calculator (opens the detail view).\r\n   * @param section - Name of the section\r\n   */\r\n  public setActive(section: string) {\r\n    this.ui.activeSection = section;\r\n  }\r\n\r\n  /**\r\n   * Toggles the section\r\n   */\r\n  public toggleActive(section: string) {\r\n    this.ui.activeSection = this.ui.activeSection === section ? null : section;\r\n  }\r\n\r\n  /**\r\n   * Toggles the section active / non-active.\r\n   */\r\n  public toggle(section: string) {\r\n    if (this.ui.activeSection === section) {\r\n      this.ui.activeSection = null;\r\n    } else {\r\n      this.ui.activeSection = section;\r\n    }\r\n  }\r\n\r\n  /** Gets a section */\r\n  public get(section: string) {\r\n    const isActive = this.ui.activeSection === section;\r\n    switch (section) {\r\n      case \"worker\":\r\n        return new CalculatorSection(\r\n          isActive,\r\n          this.calc.worker && this.calc.worker.avatar.id != null,\r\n          (this.calc.worker && this.calc.worker.avatar.displayName)\r\n            ? this.calc.worker.avatar.displayName\r\n            : Translations.get(\"SALAXY.NG1.CalcComponent.workerSectionDefaultInfo\"),\r\n        );\r\n      case \"household-usecase\":\r\n        return new CalculatorSection(\r\n          isActive,\r\n          this.calc.usecase == null || this.calc.usecase.label != null,\r\n          null, // No longer in use\r\n        );\r\n      case \"worktime\":\r\n        return new CalculatorSection(\r\n          isActive,\r\n          !!(this.calc.info.workStartDate && this.calc.info.workEndDate),\r\n          null, // No longer in use in Calculator2018\r\n        );\r\n      case \"expenses\": {\r\n        const expenses = CalculatorLogic.getTotalForCategory(this.calc, \"expenses\");\r\n        const benefits = CalculatorLogic.getTotalForCategory(this.calc, \"benefits\");\r\n        const deductions = CalculatorLogic.getTotalForCategory(this.calc, \"deductions\");\r\n        const isHouseholdDeductible = this.calc.salary.isHouseholdDeductible;\r\n        const unionPaymentType = (this.calc.framework as any).unionPayment;\r\n        return new CalculatorSection(\r\n          isActive,\r\n          ((expenses + benefits > 0) || (deductions > 0) || isHouseholdDeductible || (unionPaymentType && unionPaymentType !== UnionPaymentType.NotSelected)),\r\n          Numeric.toFixed(expenses + benefits, 2) + \" € - \" + Numeric.toFixed(deductions, 2) + \" €\",\r\n        );\r\n      }\r\n      case \"salary\": {\r\n        const allSalary = CalculatorLogic.getTotalForCategory(this.calc, \"salary\");\r\n        const salaryAdditions = CalculatorLogic.getTotalForCategory(this.calc, \"salaryAdditions\");\r\n        return new CalculatorSection(\r\n          isActive,\r\n          allSalary > 0,\r\n          (\r\n            allSalary === 0\r\n              ? \"0 €\"\r\n              : salaryAdditions > 0\r\n                ? Numeric.toFixed(this.calc.result.totals.totalBaseSalary, 2) + \" + \" + Numeric.toFixed(salaryAdditions, 2) + \" €\"\r\n                : Numeric.toFixed(this.calc.result.totals.totalBaseSalary, 2) + \" €\"\r\n          ),\r\n        );\r\n      }\r\n      case \"result\": {\r\n        const isResultsActive = (this.calc.result && this.calc.result.totals &&\r\n          (this.calc.rows.length > 0 || this.calc.result.totals.total !== 0 || this.calc.workflow.status !== CalculationStatus.Draft)) || false;\r\n        return new CalculatorSection(\r\n          isResultsActive,\r\n          isResultsActive,\r\n          Translations.get(\"SALAXY.NG1.CalcComponent.resultSectionCalculation\"),\r\n        );\r\n      }\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Arrays, AvatarPictureType, BootstrapStyle, calcReportType, Calculation, CalculationRowType,\r\n  Calculations, CalculationStatus, CalculatorLogic, Dates, LegalEntityType, PaymentChannel, TaxCard2019Logic, TaxcardUiInfo, TaxDeductionWorkCategories,\r\n  Translations, UserDefinedRow, Ajax,\r\n  AbsenceCauseCode\r\n} from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, ReportsService, SessionService, UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectControllerBindings } from \"../bases\";\r\nimport { CalculationCrudController } from \"./CalculationCrudController\";\r\nimport { CalculatorSections } from \"./CalculatorSections\";\r\n\r\n\r\n/** Enumerations for calculator actions */\r\nenum CalculatorActions {\r\n  AllowForcePay = \"allowForcePay\",\r\n  Approve = \"approve\",\r\n  Cancel = \"cancel\",\r\n  CopyAsNew = \"copyAsNew\",\r\n  Delete = \"delete\",\r\n  Pay = \"pay\",\r\n  Recalculate = \"recalculate\",\r\n  Reject = \"reject\",\r\n  Save = \"save\",\r\n  SendToPro = \"sendToPro\",\r\n  ShowPaymentDialog = \"showPaymentDialog\",\r\n  SetSalaryDateKind = \"setSalaryDateKind\",\r\n}\r\n\r\nclass Calculator2019ControllerCrudBindings extends ApiCrudObjectControllerBindings {\r\n  /** Options for the behavior of the calculator when in anonymous (demo) mode. */\r\n  public anonOptions = \"<\";\r\n}\r\n\r\n\r\n/**\r\n * Year 2019 Calculator controller that is not dependent on sigleton Calculations service.\r\n * This controller extends ApiCrudObjectController (via CalculationCrudController).\r\n */\r\nexport class Calculator2019Controller extends CalculationCrudController {\r\n\r\n  /** Component bindings */\r\n  public static crudBindings = new Calculator2019ControllerCrudBindings();\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"UiHelpers\", \"UiCrudHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"ReportsService\", \"InvoicesService\", \"AjaxNg1\"];\r\n\r\n  /** Type of the chart to show by default. */\r\n  public chartType = \"bar\";\r\n\r\n  /** Options for the behavior of the calculator when in anonymous (demo) mode. */\r\n  public anonOptions = {\r\n    role: \"company\" as \"company\" | \"household\",\r\n  };\r\n\r\n\r\n  /** Flags to indicate if the request is in progress */\r\n  public loaders: any = {};\r\n\r\n\r\n  constructor(\r\n    private calcApi: Calculations,\r\n    uiHelpers: UiHelpers,\r\n    protected uiCrudHelpers: UiCrudHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    reportsService: ReportsService,\r\n    protected invoicesService: InvoicesService,\r\n    private ajax: Ajax\r\n  ) {\r\n    // Dependency injection\r\n    super(calcApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n  }\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Returns the current. Called currentCalc for backward compatibility with the old views. */\r\n  public get currentCalc(): Calculation {\r\n    return this.current;\r\n  }\r\n\r\n  /**\r\n   * Gets the Sections object for the current calculation.\r\n   * It keeps track of which section is currently shown and what text etc. is shown in that section.\r\n   */\r\n  public get calcSections(): CalculatorSections {\r\n    return new CalculatorSections(this.current);\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the isHouseholdDeductible.\r\n   * This will be moved to a different location in V03, hence the abstraction.\r\n   */\r\n  public get isHouseholdDeductible(): boolean {\r\n    if (!this.current) {\r\n      return false;\r\n    }\r\n    return this.current.salary.isHouseholdDeductible;\r\n  }\r\n  public set isHouseholdDeductible(value: boolean) {\r\n    this.current.salary.isHouseholdDeductible = value;\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the taxDeductionCategory (used to be salary.taxDeductionCategories).\r\n   * This will be moved to a different location in V03, hence the abstraction.\r\n   */\r\n  public get taxDeductionCategory(): TaxDeductionWorkCategories {\r\n    return this.current.salary.taxDeductionCategories;\r\n  }\r\n  public set taxDeductionCategory(value: TaxDeductionWorkCategories) {\r\n    this.current.salary.taxDeductionCategories = value;\r\n  }\r\n\r\n  /**\r\n   * Returns true if the calculator is in \"household\" mode (as opposed to default \"company\" mode).\r\n   */\r\n  public get isHousehold() {\r\n    if (this.sessionService.isInRole(\"pro\") && this.sessionService.isInRole(\"person\")) {\r\n      return true; // All person created calaulations are considered pro for now.\r\n    }\r\n    if (this.sessionService.isInRole(\"worker\")) {\r\n      return false; // Uses calculator for companies in old Worker site (to be replaced by Omapalkka)\r\n    }\r\n    if (this.sessionService.isInRole(\"anon\")) {\r\n      if (this.anonOptions && this.anonOptions.role === \"household\") {\r\n        return true;\r\n      }\r\n      return false;\r\n    }\r\n    return this.sessionService.isInRole(\"household\");\r\n  }\r\n\r\n\r\n  /**\r\n   * If true, the given action (button) is displayed.\r\n   * @param action One of the action values.\r\n   * For now, validation and role based action logic is in UI.\r\n   * Todo: some edge cases, i.e. isForcePayAllAllowed (for pay-button) are still in UI.\r\n   */\r\n  public showAction(action: CalculatorActions): boolean {\r\n\r\n    if (!this.current) {\r\n      return false;\r\n    }\r\n    // In read only mode\r\n    if (this.isReadOnlyForced && action != CalculatorActions.ShowPaymentDialog) {\r\n      return false;\r\n    }\r\n    if (this.isReadOnlyForced && action == CalculatorActions.ShowPaymentDialog) {\r\n      return true;\r\n    }\r\n    if (this.current.workflow.status == CalculationStatus.PayrollDraft) {\r\n      // Not possible to make changes to editable payroll calculation\r\n      return false;\r\n    }\r\n    if (this.current.isReadOnly) {\r\n      switch (action) {\r\n        case CalculatorActions.Cancel:\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted &&\r\n            [\r\n              PaymentChannel.PalkkausManual,\r\n              PaymentChannel.PalkkausPersonal,\r\n              PaymentChannel.PalkkausInvoices,\r\n              PaymentChannel.PalkkausCfaPaytrail,\r\n              PaymentChannel.PalkkausEcfaPaytrail,\r\n              PaymentChannel.PalkkausCfaReference,\r\n              PaymentChannel.PalkkausEcfaReference,\r\n              PaymentChannel.PalkkausCfaFinvoice,\r\n              PaymentChannel.PalkkausEcfaFinvoice,\r\n              PaymentChannel.PalkkausCfaTest,\r\n            ].indexOf(this.current.info.paymentChannel) > -1;\r\n        case CalculatorActions.CopyAsNew:\r\n          return !this.isReadOnlyForced; // Not needed?\r\n        case CalculatorActions.ShowPaymentDialog:\r\n          return true;\r\n        case CalculatorActions.AllowForcePay: // \"Allow forcepay\" action is payment action when calculation is not valid. Logic handled in UI for now.\r\n        case CalculatorActions.Pay:\r\n        case CalculatorActions.Recalculate:\r\n        default:\r\n          return false;\r\n      }\r\n    } else {\r\n      switch (action) {\r\n        case CalculatorActions.AllowForcePay:\r\n\r\n          return this.isForcePayAllAllowed &&\r\n            (this.current.workflow.status != CalculationStatus.WaitingApproval &&\r\n              this.current.workflow.status != CalculationStatus.SharedRejected &&\r\n              this.current.workflow.status != CalculationStatus.SharedWaiting);\r\n        case CalculatorActions.Pay:\r\n          // add here isValid?\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved;\r\n        case CalculatorActions.Save:\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved ||\r\n            this.current.workflow.status == CalculationStatus.History;\r\n        case CalculatorActions.Delete:\r\n          return this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedRejected ||\r\n            this.current.workflow.status == CalculationStatus.History;\r\n        case CalculatorActions.SendToPro:\r\n          return this.current.workflow.status == CalculationStatus.WaitingApproval;\r\n        case CalculatorActions.Recalculate:\r\n          return true;\r\n        case CalculatorActions.Reject:\r\n          return this.current.workflow.status == CalculationStatus.SharedApproved ||\r\n            this.current.workflow.status == CalculationStatus.SharedWaiting;\r\n        case CalculatorActions.Approve:\r\n          return this.current.workflow.status == CalculationStatus.SharedRejected ||\r\n            this.current.workflow.status == CalculationStatus.SharedWaiting;\r\n        case CalculatorActions.SetSalaryDateKind:\r\n          return (this.current.workflow.status == CalculationStatus.Draft ||\r\n            this.current.workflow.status == CalculationStatus.ProDraft ||\r\n            this.current.workflow.status == CalculationStatus.SharedApproved) &&\r\n            (\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausManual ||\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausInvoices ||\r\n              this.current.info.paymentChannel == PaymentChannel.PalkkausCfaTest ||\r\n              this.current.info.paymentChannel == PaymentChannel.Briox ||\r\n              this.current.info.paymentChannel == PaymentChannel.Askelma ||\r\n              this.current.info.paymentChannel == PaymentChannel.Kitsas ||\r\n              this.current.info.paymentChannel == PaymentChannel.PasseliMerit\r\n            );\r\n        default:\r\n          return false;\r\n      }\r\n    }\r\n\r\n  }\r\n\r\n  /**\r\n   * Returns true, if action (button) is disabled\r\n   * TODO: Add rules based on roles and validation? Pay button logic is in UI.\r\n   */\r\n  public isActionDisabled(action: CalculatorActions): boolean {\r\n    if (!this.current) {\r\n      return true;\r\n    }\r\n    // In read only mode\r\n    if (this.isReadOnlyForced) {\r\n      return true;\r\n    }\r\n\r\n    if (this.current.isReadOnly) {\r\n      switch (action) {\r\n        case CalculatorActions.Delete:\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted;\r\n        case CalculatorActions.Save:\r\n          // add here isValid?\r\n          return this.current.workflow.status == CalculationStatus.PaymentStarted;\r\n        default:\r\n          return true;\r\n      }\r\n    }\r\n  }\r\n  /**\r\n   * Gets the first row of the calculation assuring that it exists\r\n   * If there is no current calculation, the calculation is not added.\r\n   */\r\n  public getFirstRow(): UserDefinedRow {\r\n    return CalculatorLogic.getFirstRow(this.current);\r\n  }\r\n\r\n  /**\r\n   * Takes the current calculation, creates a copy of it in draft state\r\n   * and sets that calculation as current.\r\n   * This is done typically, when a calculation was in Paid state.\r\n   */\r\n  public copyAsNew() {\r\n    const copy = this.copyItem(this.current);\r\n    this.calcApi.recalculate(copy).then((calc) => {\r\n      this.setCurrentRef(calc);\r\n      if ((this as any)?.worktimeCtrl) {\r\n        (this as any).worktimeCtrl.reset();\r\n      }\r\n      else if ((this.parentController as any)?.worktimeCtrl) {\r\n        (this.parentController as any).worktimeCtrl.reset();\r\n      }\r\n      this.calcSections.setActive(\"worktime\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Reset worker in the calculations.\r\n   */\r\n  public resetWorker() {\r\n    this.currentCalc.worker = CalculatorLogic.getBlank().worker;\r\n  }\r\n\r\n  /**\r\n   * Gets misc. logic calculations and operations (client side, based on rows etc.)\r\n   * that affect how the user interface is rendered.\r\n   */\r\n  public get calcLogic() {\r\n    if (!this.current) {\r\n      return {};\r\n    }\r\n    const workerCalc = ((this.current.result || {}).workerCalc || {});\r\n    return {\r\n      /** If true, calcualtion contains compensation. This is useful for customizing texts and other UI elements */\r\n      hasCompensation: !!this.current.rows.find((x) => x.rowType === CalculationRowType.Compensation),\r\n      /** Expenses box total. TODO: We should see can we move this to result / server side! */\r\n      expensesTotal: workerCalc.prepaidExpenses + workerCalc.deductions - workerCalc.unemploymentInsurance - workerCalc.pension - workerCalc.tax,\r\n\r\n      /** Sum for child care subsidy. This is shown separately in the UI. */\r\n      childCareSubsidy: (this.current.result && this.current.result.rows) ? Arrays.sum(this.current.result.rows.filter((x) => x.rowType === CalculationRowType.ChildCareSubsidy), (x) => x.total) : null,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Opens the login form for the current user\r\n   * @param redirectUrl - The URL where the user is taken after a successfull login.\r\n   * @param role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   */\r\n  public signIn(redirectUrl: string = null, role: string = null) {\r\n    this.sessionService.signIn(redirectUrl, role);\r\n  }\r\n\r\n  /**\r\n   * Opens the login dialog with signUp / register functionality\r\n   * @param redirectUrl - The URL where the user is taken after a successfull login\r\n   * @param role - Optional role (household, worker or company) for the situations where it is known - mainly for new users\r\n   */\r\n  public register(redirectUrl: string = null, role: string = null) {\r\n    this.sessionService.register(redirectUrl, role);\r\n  }\r\n\r\n  /**\r\n   * Shows a report for the current calculation using a modal dialog.\r\n   * @param reportType - Type of report to show\r\n   */\r\n  public showReportDialog(reportType: calcReportType) {\r\n    this.reportsService.showReportModalForCalc(reportType, this.current);\r\n  }\r\n\r\n  /**\r\n   * Deletes the currently selected calculation\r\n   */\r\n  public deleteCalc() {\r\n    this.uiHelpers.showConfirm(\"SALAXY.NG1.CalcComponent.dialog.deleteCalc\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          if(this.isNew()){\r\n            this.$location.url(\"/\");\r\n          } else {\r\n            const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n            this.deleteNoConfirm(this.current).then(() => {\r\n            this.setCurrentRef(this.api.getBlank());\r\n            loading.dismiss();\r\n            this.$location.url(\"/\");\r\n          });\r\n          }\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Recalculates the current calculation using the API.\r\n   * @returns A Promise with result data (Calculation)\r\n   */\r\n  public recalculate(): Promise<Calculation> {\r\n    // Sets the accounts before recalculate and not after in setCurrent.\r\n    if (this.sessionService.isInRole(\"worker\")) {\r\n      this.current.worker.isSelf = true;\r\n    } else {\r\n      this.current.employer.isSelf = true;\r\n    }\r\n    return this.calcApi.recalculate(this.current).then((calc) => {\r\n      // TODO: Check that the spinner works here. Also remove unnecessary spinners in other places.\r\n      super.setCurrentValue(calc);\r\n      return calc;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the current item as the given object (reference to a new object).\r\n   * This also resets the original item and sets the state as loaded.\r\n   * Override also sets either employer or worker based on the current role.\r\n   * @param item The new current item.\r\n   */\r\n  public setCurrentRef(item: Calculation) {\r\n    if (item) {\r\n      if (this.sessionService.isInRole(\"worker\")) {\r\n        item.worker.isSelf = true;\r\n      } else {\r\n        item.employer.isSelf = true;\r\n      }\r\n    }\r\n    super.setCurrentRef(item);\r\n  }\r\n\r\n  /** Overrides the save method to allow anonymous saving to local storage */\r\n  public save() {\r\n    /** Not sure whether the local storage saving is enabled anywhere? */\r\n    if (!this.sessionService.isAuthenticated) {\r\n      this.current.id = \"anon\";\r\n      return this.recalculate().then(() => {\r\n        this.current.worker.accountId = \"anon\";\r\n        this.current.worker.avatar.id = this.current.worker.accountId;\r\n        this.current.worker.avatar.color = \"lime\";\r\n        this.current.worker.avatar.displayName = \"SALAXY.NG1.CalcComponent.saveNotAuthenticatedDisplayName\";\r\n        this.current.worker.avatar.entityType = LegalEntityType.Person;\r\n        this.current.worker.avatar.pictureType = AvatarPictureType.Icon;\r\n        this.setToLocalStorage(this.current);\r\n        return this.current;\r\n      });\r\n    } else {\r\n      if (this.current.worker.accountId === \"anon\") {\r\n        this.current.worker.accountId = null;\r\n      }\r\n      if (!this.current.worker.accountId) {\r\n        this.deleteFromLocalStorage();\r\n      }\r\n      if (this.current.id === \"anon\") {\r\n        this.current.id = null;\r\n      }\r\n      return super.save();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns validation for current calculation or empty validation object if the calculation has not been recalculated (validated).\r\n   */\r\n  public get validation() {\r\n    return this.currentCalc?.result?.validation || { errors: [], hasAllRequiredFields: true, isValid: true };\r\n  }\r\n\r\n  /** Returns date range text. */\r\n  public getDatesRangeText() {\r\n    if (!this.currentCalc.info.workStartDate || !this.currentCalc.info.workEndDate) {\r\n      return \"SALAXY.NG1.CalcComponent.getDatesRangeText\";\r\n    }\r\n    return Dates.getFormattedRange(this.currentCalc.info.workStartDate, this.currentCalc.info.workEndDate)\r\n      + ` (${this.currentCalc.framework.numberOfDays}\\xa0${Translations.get(\"SALAXY.NG1.CalcComponent.getUsecaseTextNumberOfDays\")})`; // \"\\xa0\" is non-breaking space.\r\n  }\r\n\r\n  /** Returns household usecase text */\r\n  public getUsecaseText() {\r\n    if (!this.currentCalc.usecase && !this.currentCalc.framework.numberOfDays) {\r\n      return \"SALAXY.NG1.CalcComponent.getUsecaseText\";\r\n    }\r\n    if (this.currentCalc.usecase && !this.currentCalc.framework.numberOfDays) {\r\n      return ` ${this.currentCalc.usecase.label}.` + Translations.get(\"SALAXY.NG1.CalcComponent.getUsecaseText2\");\r\n    }\r\n    return Dates.getFormattedRange(this.currentCalc.info.workStartDate, this.currentCalc.info.workEndDate)\r\n      + ` (${this.currentCalc.framework.numberOfDays} ${Translations.get(\"SALAXY.NG1.CalcComponent.getUsecaseTextNumberOfDays\")}, ${this.currentCalc.usecase.label})`;\r\n  }\r\n\r\n  /** Returns true if the payment is possible when the employer pays all.  */\r\n  public get isForcePayAllAllowed(): boolean {\r\n    const obj = this.validation.errors.find((x) =>\r\n      (x.type !== \"warning\"));\r\n    return !obj;\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for adding a new Employment relation.\r\n   * If user goes through the wizard the employment relation is saved and set to the calculation.\r\n   */\r\n  public showNewWorkerDialog() {\r\n    this.uiCrudHelpers.createNewEmployment().then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.updateFromEmployment(result.item.id, true);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog during the check of auto taxcard.\r\n   */\r\n  public showRefreshAutoTaxcardDialog() {\r\n    this.loaders[\"showRefreshAutoTaxcardDialog\"] = true;\r\n    this.uiCrudHelpers.refreshAutoTaxcard(this.current.worker.tax?.taxcardId, this.current.workflow?.salaryDate).then(() => {\r\n      this.recalculate();\r\n      this.loaders[\"showRefreshAutoTaxcardDialog\"] = false;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for modifying an existing Worker:\r\n   * Saves changes and updates the calculation.\r\n   */\r\n  public showWorkerEditDialog() {\r\n    this.uiCrudHelpers.openEditEmploymentDialog(this.current.worker.employmentId, \"updateCalc\")\r\n      .then((result) => {\r\n        if (result.action === \"ok\" || result.action === \"ok-no-rows\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.CalcComponent.dialog.showWorkerEditDialogLoading\");\r\n          this.updateFromEmployment(result.item.id, result.action === \"ok\").then(() => {\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /** UI related data and texts about the taxcard. */\r\n  public get taxUi(): TaxcardUiInfo {\r\n    return TaxCard2019Logic.getCalcTaxcardInfo(this.current);\r\n  }\r\n\r\n  /**\r\n   * Gets the text for pension.\r\n   * @param isOverview If true, returns the shorter text for overview.\r\n   */\r\n  public getPensionText(isOverview = false) {\r\n    if (this.current?.result?.responsibilities?.pensionCalculation) {\r\n      return Translations.get(`SALAXY.ENUM.PensionCalculation.${this.current.result.responsibilities.pensionCalculation}.${isOverview ? \"labelForIncome\" : \"labelWithEnumLabel\"}`);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends the payroll from company to PRO.\r\n   * @param message Message to the accountant\r\n   */\r\n  public sendToPro(message: string) {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.CalcComponent.dialog.sendToProSending\", \"SALAXY.NG1.CalcComponent.dialog.sendToProSendingDescr\");\r\n    this.current.workflow.status = CalculationStatus.ProDraft;\r\n    this.save().then(() => {\r\n\r\n      this.api.saveWorkflowEvent(this.current, {\r\n        type: \"PartnerMessageClosed\",\r\n        ui: BootstrapStyle.Success,\r\n        message: message ? Translations.get(\"SALAXY.NG1.CalcComponent.dialog.sendToProMessage\") + message : \"SALAXY.NG1.CalcComponent.dialog.sendToProMessageChecked\",\r\n      }).then(() => {\r\n        loader.dismiss();\r\n        this.$location.path(\"/service\");\r\n      });\r\n    });\r\n    return;\r\n  }\r\n\r\n  /**\r\n   * Calculates the total amount of days for the given period type.\r\n   * @param periodType Period type to calculate days for.\r\n   * @returns Sum of days for the given period type.\r\n   */\r\n  public calculatePeriodDays(periodType: \"absencesDays\"  | \"leavesDays\" | \"paidAbsencesDays\") {\r\n    switch (periodType) {\r\n      case \"leavesDays\":\r\n        return Arrays.sum(this.currentCalc.worktime?.absencesPeriods?.filter(x => x.causeCode == AbsenceCauseCode.AnnualLeave) ?? [], (x) => x.period.daysCount);\r\n      case \"absencesDays\":\r\n        return Arrays.sum(this.currentCalc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && !x.isPaid) ?? [], (x) => x.period.daysCount);\r\n      case \"paidAbsencesDays\":\r\n        return Arrays.sum(this.currentCalc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && x.isPaid) ?? [], (x) => x.period.daysCount);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Saves a calculation to local storage\r\n   * @param calc - Calculation to store\r\n   */\r\n  private setToLocalStorage(calc: any): void {\r\n    if (window.localStorage) {\r\n      window.localStorage.setItem(\"salaxy-calculation\", JSON.stringify(calc));\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Deletes a calculation in local storage\r\n   */\r\n  private deleteFromLocalStorage(): void {\r\n    if (window.localStorage) {\r\n      window.localStorage.removeItem(\"salaxy-calculation\");\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculations, IncomeTypeMetadata, IncomeTypesLogic, IrRow, IrRowSourceType, Unit, Translations, Ajax\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  InvoicesService,\r\n  ReportsService,\r\n  SessionService,\r\n  UiCrudHelpers,\r\n  UiHelpers,\r\n} from \"../../services\";\r\n\r\nimport { Calculator2019Controller } from \"./Calculator2019Controller\";\r\n\r\n/**\r\n * IR-rows based editor for calculation\r\n */\r\nexport class CalcIrRowsController extends Calculator2019Controller {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"UiHelpers\", \"UiCrudHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"ReportsService\", \"InvoicesService\", \"AjaxNg1\"];\r\n\r\n  /**\r\n   * Translated enums\r\n   */\r\n  public groupingOptions: any = {\r\n    baseSalary: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.baseSalary\"),\r\n    benefits: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.benefits\"),\r\n    deductions: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.deductions\"),\r\n    disabled: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.disabled\"),\r\n    expenses: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.expenses\"),\r\n    otherNoPayment: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.otherNoPayment\"),\r\n    salaryAdditions: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.salaryAdditions\"),\r\n    totals: Translations.get(\"SALAXY.NG1.CalcRowsComponent.irRows.totals\"),\r\n  };\r\n\r\n  /**\r\n   * Active tab of editor\r\n   */\r\n  protected activeTab = 1;\r\n\r\n  private _currentRow: IrRow;\r\n\r\n  /**\r\n   * Creates a new instance of the controller with dependency injection.\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    calcApi: Calculations,\r\n    uiHelpers: UiHelpers,\r\n    uiCrudHelpers: UiCrudHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    reportsService: ReportsService,\r\n    protected invoicesService: InvoicesService,\r\n    ajax: Ajax,\r\n  ) {\r\n    super(calcApi, uiHelpers, uiCrudHelpers, $location, $routeParams, sessionService, reportsService, invoicesService, ajax);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** The current row that is being viewed / edited. */\r\n  public get currentRow(): IrRow {\r\n    if (!this._currentRow || !this.currentCalc.result || !this.currentCalc.result.irRows) {\r\n      return null;\r\n    }\r\n    if (!this.currentCalc.result.irRows.find((x) => x === this._currentRow)) {\r\n      // Recalculation outside this controller has destroyed the current row.\r\n      this._currentRow = null;\r\n    }\r\n    return this._currentRow;\r\n  }\r\n\r\n  /** The metadata that describes currentRow */\r\n  public get currentRowType(): IncomeTypeMetadata {\r\n    return this.getIncomeType(this.currentRow);\r\n  }\r\n\r\n  /** IR-rows that are viewed / edited by the controller */\r\n  public get irRows(): IrRow[] {\r\n    if (!this.currentCalc || !this.currentCalc.result) {\r\n      return [];\r\n    }\r\n    return this.currentCalc.result.irRows;\r\n  }\r\n\r\n  /** Sets the current edited / viewd row */\r\n  public setCurrentIrRow(row: IrRow) {\r\n    this._currentRow = row;\r\n  }\r\n\r\n  /** Deletes a row */\r\n  public deleteIrRow(row: any) {\r\n    this.irRows.splice(this.irRows.indexOf(row), 1);\r\n  }\r\n\r\n  /** Returns true if the row is read-only: Cannot be directly edited. */\r\n  public get isIrRowReadOnly() {\r\n    return this.currentRow == null || this.currentRow.type !== \"manual\";\r\n  }\r\n\r\n  /** Updates the current row type. */\r\n  public updateCurrentRowType() {\r\n    if (this.currentRowType) {\r\n      if (!this.currentRow.message || IncomeTypesLogic.getAll().find((x) => x.label === this.currentRow.message)) {\r\n        this.currentRow.message = this.currentRowType.label;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Gets the income type (the metadata) object for the currently selected row. */\r\n  public getIncomeType(row: any): IncomeTypeMetadata {\r\n    return IncomeTypesLogic.getAll().find((x) => x.code === row.irData.code);\r\n  }\r\n\r\n  /** Adds a new IR row to the collection. */\r\n  public addIrRow() {\r\n    const row: IrRow = {\r\n      type: IrRowSourceType.Manual,\r\n      irData: {\r\n        code: null,\r\n      },\r\n      count: 1,\r\n      unit: Unit.Undefined,\r\n      price: 0,\r\n    };\r\n    this.irRows.push(row);\r\n    this.setCurrentIrRow(row as any);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Ajax,\r\n  Calculation,\r\n  Language,\r\n  Numeric,\r\n  ReportType,\r\n  Translations,\r\n  Reports,\r\n  Objects\r\n} from \"@salaxy/core\";\r\nimport { SessionService, SettingsService, UiHelpers } from \"../../services\";\r\nimport {\r\n  CalculationMapper,\r\n  CalculationReport,\r\n  ESalaryMapper,\r\n  ReportData,\r\n  ReportOptions,\r\n  Templates,\r\n  TotalsReportConfigGenerator\r\n} from \"@salaxy/reports\";\r\nimport { ColumnDefinition } from \"tabulator-tables\";\r\nimport { SxyTableOptions, SxyTableController } from \"../sxy-table/SxyTableController\";\r\n\r\n/**\r\n * Renders a calculation report or a calculation summary report for the given calculation(s).\r\n * Uses Handlebars templates (@salaxy/reports).\r\n */\r\nexport class CalcReportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Templates\",\r\n    \"AjaxNg1\",\r\n    \"$sce\",\r\n    \"SettingsService\",\r\n    \"$timeout\",\r\n    \"SessionService\",\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  /** The calculation(s) for the report. Todo add Calcs*/\r\n  public calc: Calculation | Calculation[];\r\n\r\n  /** The type for the calculation report. */\r\n  public reportType: ReportType;\r\n\r\n  /** Template for the report */\r\n  public templateName: string;\r\n\r\n  /** Boolean indicating if the refresh is in progress. */\r\n  public refreshInprogress: boolean;\r\n\r\n  /**Selected report language */\r\n  public lang: Language;\r\n\r\n  /** If true, adds the preview watermark to the preview. */\r\n  public preview?: boolean;\r\n\r\n  /** Ref to used SxyTable */\r\n  public $sxyTable: SxyTableController;\r\n\r\n  private renderedCalc: Calculation | Calculation[];\r\n\r\n  private renderedOptions: string;\r\n\r\n  private renderedLang: string;\r\n\r\n  private htmlData: any;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private reportData: ReportData<CalculationReport> = {\r\n    headerFooter: {},\r\n    layout: {},\r\n    report: {},\r\n  };\r\n  private isXslLoading: boolean;\r\n  private xslText: string;\r\n\r\n  private sxyTableConfig: { currentCalc: Calculation | Calculation[], reportLang: Language, config: { options: SxyTableOptions, include: ColumnDefinition[], data: any[] } } = {\r\n    currentCalc: null,\r\n    reportLang: Language.Default,\r\n    config: null\r\n  };\r\n\r\n  /**\r\n   * Creates a new CalcReportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private templates: Templates,\r\n    private ajax: Ajax,\r\n    private $sce: angular.ISCEService,\r\n    private settingsService: SettingsService,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private sessionService: SessionService,\r\n    private reportsApi: Reports,\r\n\r\n    private uiHelpers: UiHelpers\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    // no initializations\r\n  }\r\n\r\n  /** Bindable and trusted html. */\r\n  public get html(): any {\r\n    if (!this.calc) {\r\n      this.renderedCalc = null;\r\n      this.renderedOptions = null;\r\n      this.renderedLang = null;\r\n    } else {\r\n      const calc = angular.copy(this.calc);\r\n\r\n      if (!this.renderedCalc ||\r\n        !angular.equals(calc, this.renderedCalc) ||\r\n        this.renderedOptions !== this.reportType + \";\" + this.templateName ||\r\n        this.renderedLang !== this.lang) {\r\n        this.renderedCalc = angular.copy(calc);\r\n        this.renderedOptions = this.reportType + \";\" + this.templateName;\r\n        this.renderedLang = this.lang;\r\n        this.getDefaultLanguage(this.lang).then((lang) => {\r\n          this.lang = lang;\r\n          this.renderedLang = this.lang;\r\n          // Refresh html reports\r\n          if (this.reportType !== ReportType.ESalarySpecification) {\r\n            this.refresh();\r\n          }\r\n          // Refresh eSalary xml\r\n          if (this.reportType === ReportType.ESalarySpecification && !this.isXslLoading) {\r\n            this.isXslLoading = true;\r\n            if (!this.xslText) {\r\n              fetch(`https://cdn.salaxy.com/reports/PayslipCommon20.xsl`)\r\n                .then(response => response.text())\r\n                .then(text => {\r\n                  this.xslText = text;\r\n                  this.refreshESalaryXml();\r\n                });\r\n            } else {\r\n              this.refreshESalaryXml();\r\n            }\r\n          }\r\n          return;\r\n        });\r\n      }\r\n    }\r\n    return this.htmlData;\r\n  }\r\n\r\n  /**\r\n   * Config for SxyTable\r\n   */\r\n  public get tableConfig(): { options: SxyTableOptions, include: ColumnDefinition[], data: any[] } {\r\n    if (!this.calc) {\r\n      this.sxyTableConfig = {\r\n        currentCalc: null,\r\n        reportLang: null,\r\n        config: null\r\n      };\r\n    } else {\r\n      const calcs = angular.copy(this.calc);\r\n      if (!Objects.equal(this.sxyTableConfig.currentCalc, calcs) || this.lang !== this.sxyTableConfig.reportLang) {\r\n        this.sxyTableConfig.currentCalc = calcs;\r\n        this.sxyTableConfig.reportLang = this.lang;\r\n        this.getDefaultLanguage(this.lang).then((lang) => {\r\n          this.lang = lang;\r\n          this.renderedLang = this.lang;\r\n          this.refreshTableConfig();\r\n        });\r\n      }\r\n    }\r\n    return this.sxyTableConfig.config;\r\n  }\r\n\r\n  /**\r\n   * Method used to refresh table config\r\n   */\r\n  public async refreshTableConfig() {\r\n    const renderingLang = this.lang ?? Language.Fi;\r\n    await Translations.loadLanguage(renderingLang);\r\n    this.sxyTableConfig.config = TotalsReportConfigGenerator.getConfig(this.calc, renderingLang);\r\n    await this.$timeout();\r\n    this.$sxyTable.refresh();\r\n  }\r\n\r\n  private async refreshESalaryXml() {\r\n    const calc = await this.resolveCumulativeCalculation(Array.isArray(this.calc) ? this.calc[0] : this.calc);\r\n    const xml = this.templates.getHtml(\"eSalary\", ESalaryMapper.getESalary(calc), this.lang ?? Language.Fi);\r\n    const xsltProcessor = new XSLTProcessor();\r\n    const xslDoc = new window.DOMParser().parseFromString(this.xslText, \"text/xml\");\r\n    const xmlDoc = new window.DOMParser().parseFromString(xml, \"text/xml\");\r\n    xsltProcessor.importStylesheet(xslDoc);\r\n    const resultDocument = xsltProcessor.transformToDocument(xmlDoc);\r\n    this.htmlData = this.$sce.trustAsHtml(resultDocument.documentElement.innerHTML);\r\n    this.isXslLoading = false;\r\n    this.$timeout();\r\n  }\r\n\r\n  private async resolveCumulativeCalculation(calc: Calculation): Promise<Calculation> {\r\n    if (calc.id) {\r\n      calc = angular.copy(calc);\r\n      const cumulativeCalc = await this.reportsApi.getCumulativeCalculation(calc.id);\r\n      (calc as any).cumulative = cumulativeCalc.cumulative;\r\n      return Promise.resolve(calc);\r\n    }\r\n    return Promise.resolve(calc);\r\n  }\r\n\r\n  /**\r\n   * Refresh calculation report data.\r\n   */\r\n  private async refresh() {\r\n    if (this.refreshInprogress) {\r\n      return;\r\n    }\r\n    this.refreshInprogress = true;\r\n    this.settingsService.getReportOptions().then(async (options) => {\r\n      this.reportOptions = options;\r\n      const renderingLang = this.lang ?? Language.Fi;\r\n      await Translations.loadLanguage(renderingLang);\r\n      if (Array.isArray(this.calc)) {\r\n        this.reportData.report = CalculationMapper.getCalculationSummaryReport(this.calc, renderingLang);\r\n        this.reportData.headerFooter = CalculationMapper.getCalculationSummaryReportHeaderFooter(this.calc, this.reportOptions, renderingLang);\r\n      } else {\r\n        this.reportData.report = CalculationMapper.getCalculationReport(this.calc, this.reportType, renderingLang);\r\n        this.reportData.headerFooter = CalculationMapper.getHeaderFooter(this.reportType, this.calc, this.reportOptions, renderingLang);\r\n      }\r\n      const reportOptions = this.getDefaultReportOptions(angular.copy(this.reportOptions));\r\n      this.reportData.layout = CalculationMapper.getReportLayout(false, false, this.preview ? \"default\" : undefined);\r\n      // Special case (simple report), no mapper needed\r\n      if (this.reportType === ReportType.TotalsReport) {\r\n        this.reportData.report = Array.isArray(this.calc) ? this.calc as CalculationReport : [this.calc] as CalculationReport;\r\n        this.reportData.headerFooter = CalculationMapper.getTotalReportHeaderFooter(Array.isArray(this.calc) ? this.calc[0] : this.calc, this.reportOptions, renderingLang);\r\n        this.reportData.layout = CalculationMapper.getReportLayout(true, false, this.preview ? \"default\" : undefined);\r\n      }\r\n      const css = \"\";\r\n      this.reportData.layout.hasCustomCss = false;\r\n      this.reportData.layout.customCss = (css || \"\");\r\n      if (this.preview) {\r\n        this.reportData.layout.isPreview = true;\r\n      }\r\n      this.reportData.layout.margin = {\r\n        top: reportOptions.margin.top,\r\n        right: reportOptions.margin.right,\r\n        bottom: reportOptions.margin.bottom,\r\n        left: reportOptions.margin.left\r\n      };\r\n      const templates = new Templates();\r\n      this.reportData.headerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.headerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.reportData.footerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.footerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.htmlData = this.$sce.trustAsHtml(this.templates.getHtml(this.templateName, this.reportData, renderingLang));\r\n      this.refreshInprogress = false;\r\n      this.$timeout();\r\n    });\r\n\r\n  }\r\n\r\n  private getDefaultReportOptions(optionsInput?: ReportOptions): ReportOptions {\r\n    optionsInput = optionsInput || {};\r\n    optionsInput.margin = optionsInput.margin || {};\r\n    optionsInput.margin.top = Numeric.parseNumber(optionsInput.margin.top) || 30;\r\n    optionsInput.margin.right = Numeric.parseNumber(optionsInput.margin.right) || 10;\r\n    optionsInput.margin.bottom = Numeric.parseNumber(optionsInput.margin.bottom) || 40;\r\n    optionsInput.margin.left = Numeric.parseNumber(optionsInput.margin.left) || 10;\r\n    return optionsInput;\r\n  }\r\n\r\n  private async getDefaultLanguage(lang: Language): Promise<Language> {\r\n    if (!lang) {\r\n      return this.sessionService.getReportLang();\r\n    }\r\n    return Promise.resolve(lang);\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Ajax,\r\n  calcReportType,\r\n  Calculation,\r\n  CalculationStatus,\r\n  Configs,\r\n  Language,\r\n  Reports,\r\n  ReportType,\r\n  Objects,\r\n  Translations,\r\n  Texts,\r\n  Dates\r\n} from \"@salaxy/core\";\r\nimport { IrRowsReportConfigGenerator, RowsReportConfigGenerator, TotalsReportConfigGenerator } from \"@salaxy/reports\";\r\nimport { ColumnDefinition } from \"tabulator-tables\";\r\nimport { SxyTableController, SxyTableOptions } from \"../sxy-table/SxyTableController\";\r\nimport {\r\n  SessionService,\r\n  UiHelpers,\r\n  ExcelHelpers\r\n} from \"../../services\";\r\nimport { CalcReportController } from \"./CalcReportController\";\r\nimport { CalcsIrRowsController } from \"./CalcsIrRowsController\";\r\n\r\n/**\r\n * Displays the reports for the given calculations.\r\n */\r\nexport class CalcReportsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AjaxNg1\",\r\n    \"UiHelpers\",\r\n    \"SessionService\",\r\n    \"$timeout\",\r\n    \"$http\",\r\n    \"Reports\"\r\n  ];\r\n\r\n  /** Report type */\r\n  public reportType: calcReportType;\r\n\r\n  /** Calculations for the reports. */\r\n  public calcs: Calculation[] = [];\r\n  /** Current selected language from UI. */\r\n  public reportLang = Language.Default;\r\n\r\n  /** Ref to used CalcReports */\r\n  public $calcReports: CalcReportController;\r\n\r\n  /** Ref to used SxyTable */\r\n  public $sxyTable: SxyTableController;\r\n\r\n  /** Ref to used CalcsIrRows */\r\n  public $calcsIrRows: CalcsIrRowsController;\r\n\r\n  /**\r\n   * The current view of the report. Partial is the default.\r\n   * Please note that not all reports support \"page1\" or \"full\".\r\n   */\r\n  public view: \"partial\" | \"page1\" | \"full\";\r\n\r\n  /** If true, adds the preview watermark to the preview. */\r\n  public preview?: boolean;\r\n\r\n  private employerLang: Language;\r\n\r\n  private workerLangs: { [key: string]: Language } = {};\r\n\r\n  /** Report templates and the currently selected template */\r\n  private reports = {\r\n    salarySlip: {\r\n      full: \"salarySlipV2\",\r\n      page1: \"salarySlipV2Page1\",\r\n      partial: \"workerCalculationTablesV2\",\r\n    },\r\n    employerReport: {\r\n      full: \"employerReportV2\",\r\n      page1: \"employerReportV2Page1\",\r\n      partial: \"employerCalculationTablesV2\",\r\n    },\r\n    paymentReport: {\r\n      full: \"paymentReportV2\",\r\n      page1: \"paymentReportV2\",\r\n      partial: \"paymentTablesV2\",\r\n    },\r\n    paymentSummaryReport: {\r\n      full: \"paymentSummaryReportV2\",\r\n      page1: \"paymentSummaryReportV2\",\r\n      partial: \"paymentTablesV2\",\r\n    },\r\n    totalsReport: {\r\n      full: \"totalsReport\",\r\n      page1: \"totalsReport\",\r\n      partial: \"totalsTables\",\r\n    },\r\n  };\r\n\r\n  private sxyTableConfig: { currentCalc: Calculation | Calculation[], reportLang: Language, config: { options: SxyTableOptions, include: ColumnDefinition[], data: any[] } } = {\r\n    currentCalc: null,\r\n    reportLang: Language.Default,\r\n    config: null\r\n  };\r\n\r\n  /**\r\n   * Creates a new CalcReportsController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private ajax: Ajax,\r\n    private uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $http: angular.IHttpService,\r\n    private reportsApi: Reports\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.view = this.view || \"partial\";\r\n    this.sessionService.getReportLang().then((lang) => {\r\n      this.reportLang = lang;\r\n    });\r\n  }\r\n\r\n  /** Sets reportLang and refreshes table if $sxyTable exists */\r\n  public async setReportLang(lang: Language) {\r\n    this.reportLang = lang;\r\n    switch (this.reportType) {\r\n      case \"totalsReport\": {\r\n        if (this.$calcReports) {\r\n          await this.$calcReports.refreshTableConfig();\r\n        }\r\n      }\r\n        break;\r\n      case \"rowsReport\": {\r\n        if (this.$sxyTable) {\r\n          await this.refreshTableConfig();\r\n        }\r\n      }\r\n        break;\r\n      case \"irRows\": {\r\n        if (this.$calcsIrRows) {\r\n          await this.$calcsIrRows.refreshTableConfig();\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Get lang for employer reports\r\n   * @returns language for calculation\r\n   */\r\n  public getEmployerLang(): Language {\r\n    if (this.reportLang !== Language.Default) {\r\n      return this.reportLang;\r\n    }\r\n    else {\r\n      if (!this.employerLang) {\r\n        this.employerLang = Language.Default;\r\n        this.sessionService.getReportLang().then(lang => {\r\n          this.employerLang = lang;\r\n          // Trigger AngularJs to redraw\r\n          this.$timeout();\r\n        });\r\n      }\r\n    }\r\n    return this.employerLang;\r\n  }\r\n\r\n  /**\r\n   * Get lang for worker reports\r\n   * @param calc selected calculation\r\n   * @returns language for calculation\r\n   */\r\n  public getWorkerLang(calc: Calculation): Language {\r\n    if (this.reportLang !== Language.Default) {\r\n      return this.reportLang;\r\n    }\r\n    if (!this.workerLangs[calc.worker.accountId]) {\r\n      this.workerLangs[calc.worker.accountId] = Language.Default;\r\n      this.sessionService.getReportLang(calc.worker.accountId).then(lang => {\r\n        this.workerLangs[calc.worker.accountId] = lang;\r\n        // Trigger AngularJs to redraw\r\n        this.$timeout();\r\n      });\r\n    }\r\n\r\n    return this.workerLangs[calc.worker.accountId];\r\n  }\r\n\r\n  /**\r\n   * Return languge text to ui\r\n   */\r\n  public get languageText() {\r\n    switch (this.reportLang) {\r\n      case Language.Fi:\r\n        return \"SALAXY.ENUM.Language.fi.label\";\r\n      case Language.En:\r\n        return \"SALAXY.ENUM.Language.en.label\";\r\n      case Language.Sv:\r\n        return \"SALAXY.ENUM.Language.sv.label\";\r\n      case Language.Default:\r\n        return (this.reportType === \"salarySlip\" || this.reportType === \"employerReport\" || this.reportType === \"paymentReport\") ? \"SALAXY.NG1.CalcReportsComponent.reportLanguageWorker\" : \"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Exports tabulator based reports data as excel file\r\n   */\r\n  public async downloadExcel() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const getExportData = async (data: Calculation[]) => {\r\n      const renderingLang = this.getEmployerLang() ?? Language.Fi;\r\n      await Translations.loadLanguage(renderingLang);\r\n      switch (this.reportType) {\r\n        case \"totalsReport\": {\r\n          return TotalsReportConfigGenerator.getTableData(data, renderingLang);\r\n        }\r\n        case \"rowsReport\": {\r\n          return RowsReportConfigGenerator.getTableData(data, renderingLang);\r\n        }\r\n        case \"irRows\": {\r\n          return IrRowsReportConfigGenerator.getTableData(data, renderingLang);\r\n        }\r\n      }\r\n    };\r\n    const fileNames = {\r\n      \"totalsReport\": \"SALAXY.ENUM.ReportType.totalsReport.label\",\r\n      \"rowsReport\": \"SALAXY.NG1.CalcReportsComponent.rowsReport\",\r\n      \"irRows\": \"SALAXY.NG1.CalcReportsComponent.irRows\"\r\n    };\r\n    const getFileName = (): string => {\r\n      return Texts.escapeFileName(`${Translations.get(fileNames[this.reportType])}_${Dates.format(\"today\", \"YYYY_MM\")}`);\r\n    };\r\n\r\n    ExcelHelpers.export(await getExportData(this.calcs), getFileName());\r\n    loading.dismiss();\r\n  }\r\n\r\n  /**\r\n   * Shows a download dialog for the given calculations.\r\n   * @param inline - If true, the download link opens the pdf into a new web page.\r\n   */\r\n  public showDownloadDialog(inline = false) {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    if (this.reportType == \"paymentSummaryReport\" || this.reportType == \"accountingReport\" || this.reportType == \"totalsReport\" || this.reportType == \"rowsReport\") {\r\n      let url = \"\";\r\n      switch (this.reportType) {\r\n        case ReportType.PaymentSummaryReport:\r\n          // backend cannot resolve reportLang, send employerLang\r\n          url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(this.reportType)}&template=${encodeURIComponent(\"paymentSummaryReportV2\")}&language=${encodeURIComponent(this.getEmployerLang())}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n          this.handlePdfRequest(url, inline, { object: this.calcs }, loading);\r\n          break;\r\n        case ReportType.AccountingReport:\r\n          // backend cannot resolve reportLang, send employerLang\r\n          url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(this.reportType)}&template=${encodeURIComponent(\"accountingReport\")}&language=${encodeURIComponent(this.getEmployerLang())}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n          this.reportsApi.getAccountingDataForCalculations(this.calcs).then(accountingData => {\r\n            this.handlePdfRequest(url, inline, { object: accountingData }, loading);\r\n          });\r\n          break;\r\n        case ReportType.TotalsReport:\r\n          // backend cannot resolve reportLang, send employerLang\r\n          url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(this.reportType)}&template=${encodeURIComponent(\"totalsReport\")}&language=${encodeURIComponent(this.getEmployerLang())}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n          this.handlePdfRequest(url, inline, { object: this.calcs }, loading);\r\n          break;\r\n        case \"rowsReport\":\r\n          alert(\"Tulostus ei ole vielä tuettu tällä raporttityypillä.\");\r\n          loading.dismiss();\r\n          return;\r\n      }\r\n    } else {\r\n      const idsOnly = this.calcs.every((x) => x.workflow.status === CalculationStatus.PaymentSucceeded);\r\n      if (idsOnly) {\r\n        let url = `${Configs.current.apiServer}/v03/api/reports/assure-pdf/${this.reportType}?disposition=inline&`;\r\n        this.calcs.map((x) => x.id).forEach((x) => { url += \"ids=\" + encodeURIComponent(\"\" + x) + \"&\"; });\r\n        url += `language=${encodeURIComponent(this.reportLang)}`; // backend resolves reportLang for worker\r\n        url = url.replace(/[?&]$/, \"\");\r\n        url = url + `&access_token=${this.ajax.getCurrentToken()}`;\r\n        this.handlePdfRequest(url, inline, null, loading);\r\n      } else {\r\n        // backend resolves reportLang for worker\r\n        const url = `${Configs.current.apiServer}/v03/api/reports/assure-pdf/${this.reportType}?language=${encodeURIComponent(this.reportLang)}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n        this.handlePdfRequest(url, inline, this.calcs, loading);\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Reloads the current report */\r\n  public reload() {\r\n    const reportType = this.reportType;\r\n    this.reportType = null;\r\n    this.$timeout(0).then(() => {\r\n      this.reportType = reportType;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Config for SxyTable\r\n   */\r\n  public get rowsReportTableConfig(): { options: SxyTableOptions, include: ColumnDefinition[], data: any[] } {\r\n    if (!this.calcs) {\r\n      this.sxyTableConfig = {\r\n        currentCalc: null,\r\n        reportLang: null,\r\n        config: null\r\n      };\r\n    } else {\r\n      const calcs = angular.copy(this.calcs);\r\n      if (!Objects.equal(this.sxyTableConfig.currentCalc, calcs) || this.reportLang !== this.sxyTableConfig.reportLang) {\r\n        this.sxyTableConfig.currentCalc = calcs;\r\n        this.sxyTableConfig.reportLang = this.reportLang;\r\n        this.getDefaultLanguage(this.reportLang).then((lang) => {\r\n          this.reportLang = lang;\r\n          this.refreshTableConfig();\r\n        });\r\n      }\r\n    }\r\n    return this.sxyTableConfig.config;\r\n  }\r\n\r\n  private async refreshTableConfig() {\r\n    const renderingLang = this.reportLang ?? Language.Fi;\r\n    await Translations.loadLanguage(renderingLang);\r\n    this.sxyTableConfig.config = RowsReportConfigGenerator.getConfig(this.calcs, renderingLang);\r\n    await this.$timeout();\r\n    this.$sxyTable.refresh();\r\n  }\r\n\r\n  private async getDefaultLanguage(lang: Language): Promise<Language> {\r\n    if (!lang) {\r\n      return this.sessionService.getReportLang();\r\n    }\r\n    return Promise.resolve(lang);\r\n  }\r\n\r\n  /**\r\n   * Handles pdf request\r\n   * TODO: Refactor to handleReportServerPdfRequest -> if error, post to fail-over server\r\n   * @param url post url\r\n   * @param inline inline pdf\r\n   * @param payload http post payload. {object: businessObject} or only businessObject\r\n   * @param loading loader reference, used to dissmiss loading after actions\r\n   */\r\n  private async handlePdfRequest(url: string, inline: boolean, payload: any, loading: any): Promise<void> {\r\n    let response: any;\r\n    try {\r\n      if (payload) {\r\n        response = await this.$http.post(url, payload, { responseType: \"blob\" });\r\n      } else {\r\n        response = await this.$http.get(url, { responseType: \"blob\" });\r\n      }\r\n      if (response.data) {\r\n        if (inline) {\r\n          this.uiHelpers.openFile(response.data as any);\r\n        } else {\r\n          this.uiHelpers.downloadFile(response.data as any, decodeURIComponent(response.headers(\"content-disposition\")).match(/filename\\s*=\\s*\"?(?<file>.*?)(?:\\s*;|\"|\\s*$)/)?.groups?.file);\r\n        }\r\n      }\r\n    } catch (error) {\r\n      console.error(error);\r\n    }\r\n    if (loading) {\r\n      loading.dismiss();\r\n    }\r\n\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { calcReportType, Calculation, Calculations } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for displaying calculation\r\n */\r\nexport class CalcReportsDisplayController implements angular.IController {\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Calculations\"\r\n  ];\r\n  /**\r\n   * Creates a new instance of CalcReportsDisplayController\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   */\r\n constructor(\r\n  private uiHelpers: UiHelpers,\r\n  private calculations: Calculations\r\n) {}\r\n\r\n/**\r\n * Display CalcReports\r\n * @param reportType Report type\r\n * @param calculation BusinessObject\r\n */\r\npublic display(reportType: calcReportType, calculation: Calculation): void {\r\n    const calcs: Calculation[] = [calculation];\r\n    const data = {\r\n      reportType,\r\n      calcs,\r\n    };\r\n\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/calc/CalcReports.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"lg\",\r\n      true);\r\n  }\r\n\r\n/**\r\n * Display CalcReports\r\n * @param reportType Report type\r\n * @param calculationId BusinessObject id\r\n */\r\npublic async displayForId(reportType: calcReportType, calculationId: string): Promise<void> {\r\n    const calculation = await this.calculations.getSingle(calculationId);\r\n    const calcs: Calculation[] = [calculation];\r\n    const data = {\r\n      reportType,\r\n      calcs,\r\n    };\r\n\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/calc/CalcReports.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"lg\",\r\n      true);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { CalcRowConfig, CalculationRowCategory, CalculationRowType, CalculatorLogic, InputEnumOption, Objects, Translations, UserDefinedRow } from \"@salaxy/core\";\r\n\r\nimport { RowTypeService, SessionService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * UI logic for changing the row type and potentially the kind for UserDefined row in calculation.\r\n * Note that changing the type may change the message of the row as well:\r\n * In the future, usecase defaults may also be changed.\r\n */\r\nexport class CalcRowTypeController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\", \"UiHelpers\", \"RowTypeService\"];\r\n\r\n  /** Type of the input element. Default is typeahead. */\r\n  public type: \"typehead\" | \"list\" | \"read-only\";\r\n\r\n  /** If set, filters the rows based on categories (plus rowTypes if set) */\r\n  public categories: CalculationRowCategory[];\r\n\r\n  /** If set, shows only these types (plus categories if set) */\r\n  public rowTypes: CalculationRowType[];\r\n\r\n  /** Name and identifier of the typehead input */\r\n  public name: string;\r\n\r\n  /**\r\n   * Placeholder text in the typeahead input.\r\n   * Default is 'SALAXY.UI_Terms.select'.\r\n   */\r\n  public placeholder: string;\r\n\r\n  /**\r\n   * If true, the list will show all the children under each parent that is shown as a direct hit.\r\n   */\r\n  public showChildren: boolean;\r\n\r\n  /**\r\n   * Function that is called after the row type and potentially kind and message have been changed.\r\n   * @example <salaxy-calc-row-type on-row-changed=\"$ctrl.commitNewRow()\"></salaxy-calc-row-type>\r\n   */\r\n  public onRowChanged: (eventData: {\r\n    /** New item which was created. */\r\n    row: UserDefinedRow,\r\n  }) => void;\r\n\r\n  /** The calculation row that this component modifies. */\r\n  public model: UserDefinedRow;\r\n\r\n  /**\r\n   * The default number of items that is returned from the typeahead search list.\r\n   * Default is 50.\r\n   */\r\n  public top: number;\r\n\r\n  private _internalValue: InputEnumOption;\r\n\r\n  private modelRowType;\r\n\r\n  private modelDataKind;\r\n\r\n  private listCache: {\r\n    /** Cache key */\r\n    key: string,\r\n    /** Cache value */\r\n    value: CalcRowConfig[],\r\n  } = null;\r\n\r\n  constructor(private session: SessionService, private uiHelpers: UiHelpers, private rowTypeService: RowTypeService) {\r\n  }\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    this.top = this.top || 50;\r\n    if (!this.type) {\r\n      this.type = \"typehead\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Detects the changes in the model properties \"rowType\" and \"data.kind\"\r\n   * and reflects them to internalValue.\r\n   */\r\n  public $doCheck() {\r\n    let hasChanges = false;\r\n    if (this.model?.rowType !== this.modelRowType) {\r\n      this.modelRowType = this.model?.rowType;\r\n      hasChanges = true;\r\n    }\r\n    if (this.model?.data?.kind !== this.modelDataKind) {\r\n      this.modelDataKind = this.model?.data?.kind;\r\n      hasChanges = true;\r\n    }\r\n    if (hasChanges) {\r\n      // NOTE: There is potential incoherent behavior here: depending on in which order attributes \"categories\"\r\n      //       \"rowTypes\" and \"model\" are set, the filters may behave differently in edge case where model value\r\n      //       is outside these filters. This was not considered significant at the time of writing.\r\n      if (this.modelDataKind) {\r\n        this._internalValue = this.getList().find((x) => x.value === `${this.modelRowType}.${this.modelDataKind}`);\r\n      } else {\r\n        this._internalValue = this.getList().find((x) => x.value === this.modelRowType);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Internal value from view to the controller. This is one of the numerations returned by getList()\r\n   * if model has been set and it matches to oneof those values.\r\n   */\r\n  protected get internalValue(): InputEnumOption {\r\n    return this._internalValue;\r\n  }\r\n  protected set internalValue(val: InputEnumOption) {\r\n    this._internalValue = val;\r\n    if (!this.model) {\r\n      return;\r\n    }\r\n    this.model.data = this.model.data || {};\r\n    if (!val) {\r\n      this.model.rowType = null;\r\n      this.model.data.kind = null;\r\n      this.model.type = null;\r\n    } else if (val.value.indexOf(\".\")) {\r\n      const valueArr = val.value.split(\".\");\r\n      this.model.rowType = valueArr[0] as CalculationRowType;\r\n      this.model.data.kind = valueArr[1] || undefined;\r\n      // TODO: Requires refactoring => type should be directly in value\r\n      if (val.ui) {\r\n        this.model.type = val.ui.type;\r\n        this.model.rowType = val.ui.rowType;\r\n        (this.model as any).config = {\r\n          group: val.ui.group,\r\n        };\r\n      }\r\n    } else {\r\n      this.model.rowType = val.value as CalculationRowType;\r\n      this.model.data.kind = undefined;\r\n      // TODO: Requires refactoring => type should be directly in value\r\n      if (val.ui) {\r\n        this.model.type = val.ui.type;\r\n        this.model.rowType = val.ui.rowType;\r\n        (this.model as any).config = {\r\n          group: val.ui.group,\r\n        };\r\n      }\r\n    }\r\n    this.onRowChanged({ row: this.model });\r\n  }\r\n\r\n  /**\r\n   * Gets the list of row types according to options:\r\n   * This list changes and is cached based on role (household/company), language,\r\n   * rowTypes and categories. Currently the same as search(null), but cached.\r\n   */\r\n  public getList(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"list\",\r\n      () => { return this.search(null, true, true); },\r\n      () => Translations.getLanguage() + this.rowTypes?.join(\"\") + this.categories?.join(\"\"));\r\n  }\r\n\r\n  /**\r\n   * Gets the search as cached item: Can be bound to ng-repeat.\r\n   * @param searchText The search text. If null or empty, returns the full list.\r\n   */\r\n  public getCachedSearch(searchText: string): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"search\",\r\n      () => { return this.search(searchText, true, null); },\r\n      () => searchText + this.categories?.toString());\r\n  }\r\n\r\n  /**\r\n   * Searches the row types.\r\n   * @param searchText The search text. If null or empty, returns the full list.\r\n   * @param ignoreTop If true, ignores the this.top setting to return only top n items of the search\r\n   * @param showChildren Forces the showChildren value to true for this run.\r\n   * By default, children are only shown if they match the search.\r\n   */\r\n  public search(searchText: string, ignoreTop = false, showChildren: boolean = null): InputEnumOption[] {\r\n    if (showChildren == null) {\r\n      showChildren = this.showChildren;\r\n    }\r\n    const toOption = (config: CalcRowConfig) => {\r\n      return {\r\n        text: config.label,\r\n        value: config.name,\r\n        title: config.descr,\r\n        ui: {\r\n          color: config.color,\r\n          iconText: config.iconText,\r\n          addedByChild: null,\r\n          // TODO: Requires refactoring\r\n          group: config.group,\r\n          type: config.type,\r\n          rowType: config.rowType,\r\n        },\r\n      };\r\n    };\r\n    const result: InputEnumOption[] = [];\r\n    searchText = (searchText || \"\").trim().toLowerCase();\r\n    this.getRowTypes().forEach((rowConfig) => {\r\n      let isParentAdded = false;\r\n      let isParentAddedAsSelf = false;\r\n      if (\r\n        !searchText\r\n        || (rowConfig.label + rowConfig.descr + rowConfig.name).toLowerCase().indexOf(searchText) >= 0\r\n      ) {\r\n        result.push(toOption(rowConfig));\r\n        if (!ignoreTop && result.length >= this.top) {\r\n          return result;\r\n        }\r\n        isParentAdded = true;\r\n        isParentAddedAsSelf = true;\r\n      }\r\n      if (rowConfig.kind?.values) {\r\n        rowConfig.kind.values.forEach((kind) => {\r\n          if (\r\n            !(kind.name == \"undefined\" || kind.name == \"unknown\") &&\r\n            (\r\n              (isParentAddedAsSelf && showChildren)\r\n              || (searchText && (kind.label + kind.descr + kind.name).toLowerCase().indexOf(searchText) >= 0)\r\n            )\r\n          ) {\r\n            if (!isParentAdded) {\r\n              const option = toOption(rowConfig);\r\n              option.ui.addedByChild = true;\r\n              result.push(option);\r\n              isParentAdded = true;\r\n            }\r\n            result.push({\r\n              text: kind.label,\r\n              value: rowConfig.name + \".\" + kind.name,\r\n              title: kind.descr,\r\n              // TODO: Requires refactoring\r\n              ui: {\r\n                group: rowConfig.group,\r\n                type: rowConfig.type,\r\n                rowType: rowConfig.rowType,\r\n              }\r\n            });\r\n            if (!ignoreTop && result.length >= this.top) {\r\n              return result;\r\n            }\r\n          }\r\n        });\r\n      }\r\n    });\r\n\r\n    if (result.length === 2 && result[0].ui.addedByChild) {\r\n      // If only one parent with one child (child is exact match) => Merge to one row.\r\n      return [{\r\n        text: result[0].text + \": \" + result[1].text,\r\n        value: result[1].value,\r\n        title: result[1].title,\r\n        ui: result[0].ui,\r\n      }];\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /** Gets a label for the given internal value. */\r\n  public getRowLabel(rowTypeKey: string) {\r\n    if (!rowTypeKey) {\r\n      return null;\r\n    }\r\n    let rowTypeName = null;\r\n    let kindName = null;\r\n    if (rowTypeKey.indexOf(\".\")) {\r\n      const valueArr = rowTypeKey.split(\".\");\r\n      rowTypeName = valueArr[0] as CalculationRowType;\r\n      kindName = valueArr[1];\r\n      if (kindName === \"undefined\") {\r\n        kindName = null; // For undefined, take the main category.\r\n      }\r\n    } else {\r\n      rowTypeName = rowTypeKey as CalculationRowType;\r\n    }\r\n    const rowType = this.getRowTypes().find((type) => type.name === rowTypeName);\r\n    if (!rowType) {\r\n      return null;\r\n    }\r\n    const kind = rowType.kind?.values?.find((x) => x.name === kindName);\r\n    return kind ? kind.label : rowType.label;\r\n  }\r\n\r\n  /**\r\n   * Shows a dilaog that contains information about the row type.\r\n   * @param rowType The row type to show information about.\r\n   */\r\n  public showInfoScreen(rowType: InputEnumOption){\r\n    this.model = this.model || {\r\n      rowIndex: 0,\r\n      data: {\r\n        dimensions: {},\r\n        accounting: {},\r\n      },\r\n    };\r\n    this.internalValue = rowType; // Updates the model.\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/calc/rows/RowTypeEditDialog.html\", this.model, {\r\n      calc: CalculatorLogic.getBlank(),\r\n    }, \"lg\", \"CalcRows2019Controller\", ).then((_result) => {\r\n      // Do something?\r\n    });\r\n\r\n  }\r\n\r\n  /**\r\n   * Gets the list of row types. Method filters based on rowTypes and categories,\r\n   * the texts are language versioned and there is a role filter for \"household\"/\"company\".\r\n   */\r\n  private getRowTypes(): CalcRowConfig[] {\r\n    const key = \"\" + this.categories + this.rowTypes + this.rowTypeService.isReady;\r\n    if (!this.listCache || this.listCache.key !== key) {\r\n      const rowsLogic = this.rowTypeService.logic;\r\n      let value;\r\n      if ((this.categories || []).length + (this.rowTypes || []).length > 0) {\r\n        const rowConfigsByCategory =  Objects.copy(rowsLogic.getRowConfigsByCategory(this.categories));\r\n        // Remove kind from IrIncomeType: prevent listing of income types in category based lists\r\n        const irIncomeType = rowConfigsByCategory.find( (x) => x.name === CalculationRowType.IrIncomeType);\r\n        if (irIncomeType != null) {\r\n          irIncomeType.kind = null;\r\n        }\r\n        value = rowsLogic.getRowConfigsByType(this.rowTypes).concat(rowConfigsByCategory);\r\n      } else {\r\n        value = rowsLogic.getRowConfigs();\r\n      }\r\n\r\n      // Obsolete\r\n      const obsolete = [\r\n        CalculationRowType.PaidSickLeaveSalary,\r\n        CalculationRowType.PaidSickLeaveHourlySalary,\r\n        CalculationRowType.PaidSickLeaveMonthlySalary\r\n      ];\r\n      value = value.filter((x) => !(obsolete.indexOf(x.name) >= 0));\r\n\r\n      // For pro and admin only\r\n      if (!this.session.isInSomeRole(\"pro,admin\")) {\r\n        value = value.filter((x) => x.name != CalculationRowType.Service);\r\n      }\r\n\r\n      this.listCache = { key, value };\r\n    }\r\n    return this.listCache.value;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  AbsenceCauseCode,\r\n  Calculation, Calculations, Calculator, CalculatorLogic, CalcWorktime, DateRange, Dates, HolidayCode, HolidayYear, MonthlyHolidayAccrual, SalaryDateKind, SalaryDateLogic, Translations, WageBasis, WorkerAbsences, Employments, Employment,\r\n  HolidaysLogic, AnnualLeave,Arrays, InputEnumOption, HolidayPayCalculation, CalculationStatus\r\n} from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\nimport { HolidayYearCrudController, WorkerAbsencesCrudController } from \"../worker\";\r\nimport { CalculatorSections } from \"./CalculatorSections\";\r\n\r\n/**\r\n * Handles the user interaction of Worktime within the Calculator.\r\n * The Worktime contains the logic for fetching holidays and absences\r\n * for that particular period and adding calculation rows for them if necessary.\r\n */\r\nexport class CalcWorktimeController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Calculations\",\r\n    \"Calculator\",\r\n    \"SessionService\",\r\n    \"Employments\",\r\n    \"$timeout\"\r\n  ];\r\n\r\n  /** User interface shortcuts for period selection */\r\n  public periodShortcuts: {\r\n    /** Text for current month. */\r\n    monthCurrent: string,\r\n    /** Text for last month. */\r\n    monthLast: string,\r\n    /** Text for other month. */\r\n    monthOther: string,\r\n    // monthMulti: \"Monta kuukautta\",\r\n    /** Text for two weeks. */\r\n    weeks2: string,\r\n    /** Text for half a month */\r\n    monthHalf: string,\r\n    /** Text for other period. */\r\n    other: string,\r\n  };\r\n\r\n  /** The calculation that the controller edits (shows in read-only mode). */\r\n  public calc: Calculation;\r\n\r\n  /**\r\n   * The employment data for the worker.\r\n   */\r\n  public workerEmployment: Employment;\r\n\r\n  /**\r\n   * Worktime data for the period fetched from the server\r\n   */\r\n  public worktime: CalcWorktime;\r\n\r\n  /** If there is a validation error in period start, it is added here. */\r\n  public periodStartDateError = null;\r\n\r\n  /** Demodata for the anonymous demo calculator. */\r\n  public demoData: {\r\n    /** Start date for which the data was generated. */\r\n    startDate: string,\r\n    /** End date for which the data was generated. */\r\n    endDate: string,\r\n    /** The holiday data */\r\n    holidays?: HolidayYear,\r\n    /** Absences data. */\r\n    absences?: WorkerAbsences,\r\n  } = { startDate: null, endDate: null };\r\n\r\n  private _periodStartDate;\r\n  private _dateRange: DateRange;\r\n\r\n  /**\r\n   * Creates a new CalcWorktimeController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private calcApi: Calculations,\r\n    private anonCalcApi: Calculator,\r\n    private sessionService: SessionService,\r\n    private employmentsApi: Employments,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.initDateRanges();\r\n    if (this.currentCalc && this.currentCalc.info.workStartDate && this.currentCalc.info.workEndDate) {\r\n      this.reloadHolidays();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Reset the controller to initial state.\r\n   */\r\n  public reset() {\r\n    this._dateRange = {};\r\n    this._periodStartDate = null;\r\n    this.worktime ??= {};\r\n    angular.copy(this.calc?.worktime ?? {}, this.worktime);\r\n  }\r\n\r\n  /**\r\n   * Loads the employment data for the current worker.\r\n   */\r\n  public async loadEmployment(): Promise<void> {\r\n    if(this.currentCalc.worker.employmentId) {\r\n      const result = await this.employmentsApi.getSingle(this.currentCalc.worker.employmentId);\r\n      this.workerEmployment = result;\r\n      this.$timeout();\r\n\r\n    } else {\r\n      this.workerEmployment = null;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Getter for checking if WorkerHolidays is active.\r\n   */\r\n  public get isWorkerHolidaysActive(): boolean {\r\n    if(this.workerEmployment && this.workerEmployment.holidays) {\r\n      return HolidaysLogic.isWorkerHolidaysActive(this.workerEmployment.holidays);\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets the requested salary date */\r\n  public get requestedSalaryDate(): string {\r\n    return this.calc.workflow.requestedSalaryDate;\r\n  }\r\n  public set requestedSalaryDate(value: string) {\r\n    this.calc.workflow.requestedSalaryDate = value;\r\n    this.calc.workflow.salaryDate = value; // Set the salary date to the requestedSalaryDate until the next recalculation.\r\n  }\r\n\r\n  /**\r\n   * Reloads the holidays from server.\r\n   */\r\n  public reloadHolidays(): void {\r\n    this.worktime ??= {};\r\n    if(this.sessionService.isInRole(\"disableHolidays\")) {\r\n      return;\r\n    }\r\n    angular.copy(this.calc.worktime ?? {}, this.worktime);\r\n    if (this.sessionService.isAuthenticated) {\r\n      if (this.calc?.isReadOnly || this.calc?.workflow?.status === CalculationStatus.PaymentStarted) {\r\n        return;\r\n      }\r\n      this.calcApi.getWorktimeData(this.calc).then((result) => angular.copy(result, this.worktime));\r\n    } else {\r\n      this.checkDemoData();\r\n      this.anonCalcApi.getWorktimeData(this.calc, this.demoData.holidays, this.demoData.absences).then((result) => angular.copy(result, this.worktime));\r\n    }\r\n  }\r\n\r\n  /** Holiday year has been changed and must be saved and reloaded. */\r\n  public holidaysChanged(holidaysCtrl: HolidayYearCrudController) {\r\n    holidaysCtrl.save().then(() => {\r\n      this.reloadHolidays();\r\n    });\r\n  }\r\n\r\n  /** Absences has been changed and must be saved and reloaded. */\r\n  public absencesChanged(absencesCtrl: WorkerAbsencesCrudController) {\r\n    absencesCtrl.save().then(() => {\r\n      this.reloadHolidays();\r\n    });\r\n  }\r\n\r\n  /** Gets the current calculation object */\r\n  public get currentCalc(): Calculation {\r\n    return this.calc;\r\n  }\r\n\r\n  /**\r\n   * Returns true if there is no net salary payment to worker at all.\r\n   */\r\n  public get isCurrentZeroPayment(): boolean {\r\n      return CalculatorLogic.isZeroPayment(this.calc);\r\n  }\r\n\r\n  /** Disable function for the salary date picker. */\r\n  public isDisabledSalaryDate = (date): boolean => {\r\n    const role =  this.sessionService.isInRole(\"pro\") ? \"pro\" :\r\n                this.sessionService.isInRole(\"admin\") ? \"admin\" : null;\r\n    switch(this.calc.workflow.salaryDateKind) {\r\n      case SalaryDateKind.InPast:\r\n        return false;\r\n      case SalaryDateKind.Default:\r\n      default:\r\n        return !SalaryDateLogic.isValidSalaryDate(date, null, null, true, this.calc.info.paymentChannel, CalculatorLogic.isZeroPayment(this.calc), role);\r\n    }\r\n  };\r\n\r\n  /** Getter and setter for Calculation daterange in compatible format for new DateRange component. */\r\n  public get dateRange(): DateRange {\r\n    const info = (this.currentCalc || {}).info;\r\n    const framework = (this.currentCalc || {}).framework;\r\n    if (!this._dateRange) {\r\n      this._dateRange = {\r\n        start: info.workStartDate,\r\n        end: info.workEndDate,\r\n        daysCount: framework.numberOfDays,\r\n      };\r\n    }\r\n    return this._dateRange;\r\n  }\r\n  public set dateRange(value: DateRange) {\r\n    this._dateRange = value;\r\n  }\r\n\r\n  /** Returns true if the holidays uses accrual. */\r\n  public get isHolidayAccrual(): boolean {\r\n    if (!this.worktime?.holidaySpec) {\r\n      return false;\r\n    }\r\n    return  this.worktime.holidaySpec.code == HolidayCode.Permanent14Days ||\r\n    this.worktime.holidaySpec.code == HolidayCode.Permanent35Hours ||\r\n    this.worktime.holidaySpec.code == HolidayCode.TemporaryTimeOff;\r\n  }\r\n\r\n\r\n  /** Returns true if holidays are accrued for this calc. */\r\n  public get accruesHolidays(): boolean {\r\n    if (!this.worktime?.accrualSpec) {\r\n      return false;\r\n    }\r\n    return  this.worktime.accrualSpec.code == HolidayCode.Permanent14Days ||\r\n    this.worktime.accrualSpec.code == HolidayCode.Permanent35Hours ||\r\n    this.worktime.accrualSpec.code == HolidayCode.TemporaryTimeOff;\r\n  }\r\n\r\n\r\n  /**\r\n   * Called when the date range changes.\r\n   * @param noPeriodStartDateUpdate If true, the _periodStartDate is not updated.\r\n   * Should be true if the change is triggered by that input to avoid UI flickering.\r\n   */\r\n  public dateRangeChange(noPeriodStartDateUpdate = false) {\r\n    const info = (this.currentCalc || {}).info;\r\n    const framework = (this.currentCalc || {}).framework;\r\n    info.workStartDate = this.dateRange.start;\r\n    if (!noPeriodStartDateUpdate) {\r\n      this._periodStartDate = Dates.format(this.dateRange.start, \"D.M.\", null);\r\n    }\r\n    info.workEndDate = this.dateRange.end;\r\n    framework.numberOfDays = this.dateRange.daysCount;\r\n    this.reloadHolidays();\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the period start date, which is bound to editable input in case the period type\r\n   * is not \"other\" (date the range / calendar component)\r\n   */\r\n  public get periodStartDate(): string {\r\n    return this._periodStartDate;\r\n  }\r\n  public set periodStartDate(value: string) {\r\n    this._periodStartDate = value;\r\n    const parts = (value || \"\").split(\".\");\r\n    if (parts.length < 2 || parts.length > 3) {\r\n      this.periodStartDateError = \"SALAXY.NG1.CalcWorktimeComponent.periodStartDateErrorFormat\";\r\n      return;\r\n    }\r\n    let year = (parts.length === 3) ? Number((parts[2] || \"\").trim()) : null;\r\n    if (!year || year < 2019 || year > 2100) {\r\n      year = Number(this.dateRange.start.substr(0, 4));\r\n    }\r\n    const date = Dates.getDate(year, Number(parts[1]), Number(parts[0]));\r\n    if (date) {\r\n      this.periodStartDateError = null;\r\n      switch (this.periodShortcut) {\r\n        case \"monthCurrent\":\r\n        case \"monthLast\":\r\n        case \"monthOther\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,1,\"month\"),-1,\"day\"));\r\n          break;\r\n        case \"weeks2\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,2,\"week\"),-1,\"day\"));\r\n          break;\r\n        case \"monthHalf\":\r\n          if (Dates.getDay(date) === 15 || Dates.getDay(date) === 16) {\r\n            this.dateRange = Dates.getDateRange(date, Dates.startEnd(date, \"end-month\"));\r\n          } else {\r\n            this.dateRange = Dates.getDateRange(date, Dates.add(date,14,\"day\"));\r\n          }\r\n          break;\r\n        case \"other\":\r\n          this.dateRange = Dates.getDateRange(date, date);\r\n          break;\r\n      }\r\n      this.dateRangeChange(true);\r\n    } else {\r\n      this.periodStartDateError = value + \"SALAXY.NG1.CalcWorktimeComponent.periodStartDateErrorNotDate\" ;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the user interface shortcut for the period type:\r\n   * Different user interfaces are shown depending on the period shortcut.\r\n   */\r\n  public get periodShortcut(): \"monthCurrent\" | \"monthLast\" | \"monthOther\" | \"weeks2\" | \"monthHalf\" | \"other\" {\r\n    if (!this.dateRange.start || !this.dateRange.end) {\r\n      return null;\r\n    }\r\n    if (this.dateRange.start === Dates.getDate(\"today\", \"today\", 1)\r\n      && this.dateRange.end === Dates.startEnd(\"today\", \"end-month\")) {\r\n\r\n      return \"monthCurrent\";\r\n    }\r\n    if (this.dateRange.start === Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1,\"month\")\r\n      && this.dateRange.end === Dates.startEnd(Dates.add(Dates.startEnd(\"today\", \"start-month\"),-1,\"month\"),\"end-month\")) {\r\n      return \"monthLast\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start, 1, \"month\"), -1, \"day\")) {\r\n      return \"monthOther\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start,2, \"week\"),-1, \"day\")) {\r\n      return \"weeks2\";\r\n    }\r\n\r\n    // if the range is 15 (14) days or\r\n    // starts 15th or 16th and ends month end\r\n    if ((Dates.getDuration(this.dateRange.start, this.dateRange.end).days() === 14)\r\n      || (Dates.getDay(this.dateRange.start) === 15 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))\r\n      || (Dates.getDay(this.dateRange.start) === 16 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))) {\r\n      return \"monthHalf\";\r\n    }\r\n    return \"other\";\r\n  }\r\n\r\n  public set periodShortcut(value: \"monthCurrent\" | \"monthLast\" | \"monthOther\" | \"weeks2\" | \"monthHalf\" | \"other\") {\r\n    this.periodStartDateError = null;\r\n    switch (value) {\r\n      case \"monthCurrent\":\r\n        this.dateRange.start = Dates.startEnd(\"today\",\"start-month\");\r\n        this.dateRange.end = Dates.startEnd(\"today\",\"end-month\");\r\n        break;\r\n      case \"monthOther\":\r\n        if (Dates.getDay(\"today\") === 1) {\r\n          // Move to tomorrow so that the selection is monthOther and not monthCurrent.\r\n          this.dateRange.start = Dates.add(\"today\",1,\"day\");\r\n        } else {\r\n          this.dateRange.start = Dates.asDate(\"today\");\r\n        }\r\n        this.dateRange.end = Dates.add(Dates.add(this.dateRange.start,1,\"month\"),-1,\"day\");\r\n        break;\r\n      case \"monthLast\":\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1,\"month\");\r\n        this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        break;\r\n      case \"weeks2\": //TODO Review this\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-2,\"week\"); //shift to start of current week, and then 2 weeks before\r\n        this.dateRange.end = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-1,\"day\"); //shift to last day of previous week.\r\n        break;\r\n      case \"monthHalf\":\r\n        if (Dates.getDay(\"today\") < 16) {\r\n          // 16 - (28,29,30,31)\r\n          this.dateRange.start = Dates.add(Dates.add(Dates.startEnd(\"today\", \"start-month\"),-1,\"month\"),15,\"day\");\r\n          this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        } else {\r\n          // 1 - 15\r\n          this.dateRange.start = Dates.startEnd(\"today\",\"start-month\");\r\n          this.dateRange.end = Dates.add(this.dateRange.start,14,\"day\");\r\n        }\r\n        break;\r\n      case \"other\":\r\n        this.dateRange.start = Dates.add(\"today\",-1,\"day\");\r\n        this.dateRange.end = Dates.asDate(\"today\");\r\n        break;\r\n    }\r\n    this.dateRange = Dates.getDateRange(this.dateRange.start, this.dateRange.end);\r\n    this.dateRangeChange();\r\n  }\r\n\r\n  /**\r\n   * Submit the data in the Worktime (period) dialog.\r\n   */\r\n  public submitWorktime() {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.CalcWorktimeComponent.submitWorktimeTitle\");\r\n      angular.copy(this.worktime, this.calc.worktime);\r\n      this.calcApi.recalculateWorktime(this.calc).then((result) => {\r\n        angular.copy(result, this.calc);\r\n        angular.copy(this.calc.worktime, this.worktime);\r\n        loader.dismiss();\r\n        new CalculatorSections(this.currentCalc).setActive(\"salary\");\r\n    });\r\n  }\r\n\r\n  /** Returns true if the current worktime data seems to have holidays or absences to add as rows in the salary calculation.  */\r\n  public hasHolidaysOrAbsences() {\r\n\r\n    return this.worktime?.holidaySpec?.code === HolidayCode.HolidayCompensation\r\n      || this.worktime?.holidaySpec?.code === HolidayCode.HolidayCompensationIncluded\r\n      || (this.worktime?.absencesPeriods ?? []).length > 0\r\n      ;\r\n  }\r\n\r\n  /**\r\n   * Returns the logic for the worktime data related lists\r\n   * @returns Logic object for the lists.\r\n   */\r\n  public getLogicForLists(): any {\r\n    const logic = {\r\n      getAbcencesForPeriod: () => {\r\n        return this.worktime.absencesPeriods.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave);\r\n      },\r\n      getAbcensePeriodsTotalDays: (type: \"all\" | \"absencesPaid\" | \"absencesUnpaid\" | \"absencesHolidayAccrual\" | \"absencesNoHolidayAccrual\" = \"all\") => {\r\n        const list = logic.getAbcencesForPeriod();\r\n        switch (type) {\r\n          case \"all\":\r\n            return Arrays.sum(list, (x) => x.period.daysCount);\r\n          case \"absencesPaid\":\r\n            return Arrays.sum(list.filter((x) => x.isPaid), (x) => x.period.daysCount);\r\n          case \"absencesUnpaid\":\r\n            return Arrays.sum(list.filter((x) => !x.isPaid), (x) => x.period.daysCount);\r\n          case \"absencesHolidayAccrual\":\r\n            return Arrays.sum(list.filter((x) => x.isHolidayAccrual), (x) => x.period.daysCount);\r\n          case \"absencesNoHolidayAccrual\":\r\n            return Arrays.sum(list.filter((x) => !x.isHolidayAccrual), (x) => x.period.daysCount);\r\n        }\r\n      },\r\n      getAnnualLeavesForPeriod: () => {\r\n        return this.worktime.absencesPeriods.filter(x => x.causeCode == AbsenceCauseCode.AnnualLeave);\r\n      },\r\n      getAnnualLeaveDescription: (row: AnnualLeave) => {\r\n        if (row.notes) {\r\n          return row.notes;\r\n        }\r\n        return row.period.start < `${Dates.getYear(this.worktime.workDays.start)}-10-1` ? Translations.get(\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.summerHoliday\") : Translations.get(\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.winterHoliday\");\r\n      },\r\n      getAnnualLeavesTotalDays: () => {\r\n        const list = logic.getAnnualLeavesForPeriod();\r\n        return Arrays.sum(list, (x) => x.period.daysCount);\r\n      },\r\n      getAnnualLeavesBonusDays: () => {\r\n        const list = logic.getAnnualLeavesForPeriod();\r\n        return Arrays.sum(list, (x) => x.bonusDaysCount ?? 0);\r\n      },\r\n      getholidayPayCalculationOptions:(): InputEnumOption[] => {\r\n        return this.uiHelpers.cache(this, \"holidayPayCalculationOptions\", () => {\r\n          switch (this.worktime.holidaySpec?.code) {\r\n            case HolidayCode.Permanent14Days:\r\n              if(this.worktime.holidaySpec?.wageBasis === WageBasis.Monthly) {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.normalMonthlyPay.label\"), value: HolidayPayCalculation.NormalMonthlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              } else {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.averageDailyPay.label\"), value: HolidayPayCalculation.AverageDailyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.averageHourlyPay.label\"), value: HolidayPayCalculation.AverageHourlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              }\r\n            case HolidayCode.Permanent35Hours:\r\n              if(this.worktime.holidaySpec?.wageBasis === WageBasis.Monthly) {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.normalMonthlyPay.label\"), value: HolidayPayCalculation.NormalMonthlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.percentageBasedPay.label\"), value: HolidayPayCalculation.PercentageBasedPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              } else {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.percentageBasedPay.label\"), value: HolidayPayCalculation.PercentageBasedPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              }\r\n            case HolidayCode.TemporaryTimeOff:\r\n              if(this.worktime.holidaySpec?.wageBasis === WageBasis.Monthly || this.worktime.holidaySpec?.wageBasis === WageBasis.PerformanceBased || this.worktime.holidaySpec?.wageBasis === WageBasis.Hourly) {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.holidayCompensation.label\"), value: HolidayPayCalculation.HolidayCompensation},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              }\r\n              break;\r\n            default:\r\n              return [];\r\n          }\r\n        });\r\n      }\r\n    };\r\n    return logic;\r\n  }\r\n\r\n  /** Shows the pro-dialog */\r\n  public showPeriodDetails() {\r\n    const detailsModel = {\r\n      worktime: this.worktime,\r\n      logic: this.getLogicForLists()\r\n    };\r\n    this.uiHelpers.showDialog(\"salaxy-components/calc/details/worktime-pro.html\", null, detailsModel, null, \"lg\");\r\n  }\r\n\r\n  /**\r\n   * Gets the status for the current holidays and absences fetching.\r\n   * These are fetched from the server when the period and / or worker changes.\r\n   */\r\n  public getHolidaysStatus(): \"noWorker\" | \"noPeriod\" | \"loading\" | \"ok\" {\r\n    if (!this.currentCalc.worker?.employmentId && this.sessionService.isAuthenticated) {\r\n      return \"noWorker\";\r\n    }\r\n    if (!this.currentCalc.info.workStartDate || !(this.currentCalc.framework.numberOfDays > 0)) {\r\n      return \"noPeriod\";\r\n    }\r\n    return this.worktime?.holidaySpec == null ? \"loading\" : \"ok\";\r\n  }\r\n\r\n  /**\r\n   * Gets the monthly text for calendar month for accruals.\r\n   * @param type Type of the text is either header or description.\r\n   */\r\n  public getAccrualMonthText(type: \"header\" | \"description\", month: MonthlyHolidayAccrual) {\r\n    if (type === \"header\") {\r\n      (month as any) = Dates.getMonth(month.month);\r\n    }\r\n    switch (type) {\r\n      case \"header\":\r\n        return month ? Translations.get(`SALAXY.ENUM.CalendarMonth.month${month}.label`) : \"#err month\";\r\n      case \"description\": {\r\n        switch (this.worktime.accrualSpec.code) {\r\n          case HolidayCode.Permanent14Days:\r\n            return \"SALAXY.NG1.CalcWorktimeComponent.getAccrualMonthText.permanent14Days\";\r\n          case HolidayCode.Permanent35Hours:\r\n            return \"SALAXY.NG1.CalcWorktimeComponent.getAccrualMonthText.permanent35Hours\";\r\n          case HolidayCode.TemporaryTimeOff:\r\n            return \"SALAXY.NG1.CalcWorktimeComponent.getAccrualMonthText.temporaryTimeOff\";\r\n          default:\r\n            return \"SALAXY.NG1.CalcWorktimeComponent.getAccrualMonthText.default\";\r\n        }\r\n      }\r\n    }\r\n    return \"#err \" + type;\r\n  }\r\n\r\n  /**\r\n   * Gets the accrual explanation text. This is currently not in use.\r\n   * TODO: translate\r\n   */\r\n  public getAccrualText(monthlyAccrual: MonthlyHolidayAccrual): string {\r\n    if (this.worktime.accrualSpec.code === HolidayCode.Permanent14Days) {\r\n      if (monthlyAccrual.workDays < 14) {\r\n        return `${monthlyAccrual.workDays} pv < 14 pv => Ei lomakertymää.`;\r\n      } else {\r\n        return `${monthlyAccrual.workDays} pv > 14 pv => Lomakertymä ${monthlyAccrual.daysAccrued} pv.`;\r\n      }\r\n    } else if (this.worktime.accrualSpec.code === HolidayCode.Permanent35Hours) {\r\n      if (monthlyAccrual.workHours == null) {\r\n        return `Ei tietoa tunneista, oletus yli 35h => Lomakertymä ${monthlyAccrual.daysAccrued} pv.`;\r\n      } else if (monthlyAccrual.workHours < 35) {\r\n        return `${monthlyAccrual.workHours} h < 35 h => Ei lomakertymää.`;\r\n      } else {\r\n        return `${monthlyAccrual.workHours} h > 35 h => Lomakertymä ${monthlyAccrual.daysAccrued} pv.`;\r\n      }\r\n    } else if (this.worktime.accrualSpec.code === HolidayCode.TemporaryTimeOff) {\r\n      return `Vapaan ansaintasäännössä lomapäivien kertymä on aina ${monthlyAccrual.daysAccrued} pv / kalenterikuukausi.`;\r\n    } else {\r\n      return \"Ei lomapäivien kertymää.\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens the dialog for editing calculation payments\r\n   */\r\n  public openCalcLeavesDialog(): void {\r\n    const logic = {calc: this.currentCalc, worktime: this.worktime};\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/CalcLeaves.html\", logic, null, \"lg\").then(dialogResult => {\r\n      if (dialogResult.result) {\r\n        this.worktime.absencesPeriods = dialogResult.result.absencesPeriods;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Checks if the period has changed and if so resets the demo data. */\r\n  public checkDemoData(): void {\r\n    if (\r\n      this.currentCalc.info.workStartDate == this.demoData.startDate && this.currentCalc.info.workEndDate == this.demoData.endDate) {\r\n      return;\r\n    }\r\n    let holiday = null;\r\n    let absenceDay = null;\r\n    if (this.currentCalc.info.workStartDate && this.currentCalc.info.workEndDate) {\r\n        const workdays = Dates.getWorkdays(this.currentCalc.info.workStartDate, this.currentCalc.info.workEndDate);\r\n        if (workdays.length > 5) {\r\n          holiday = workdays[Math.round(workdays.length / 2)];\r\n          absenceDay = workdays[Math.round(workdays.length / 2) + 1];\r\n        }\r\n    }\r\n    this.demoData = this.demoData || {} as any;\r\n    this.demoData.startDate = this.currentCalc.info.workStartDate;\r\n    this.demoData.endDate = this.currentCalc.info.workEndDate;\r\n\r\n    if (!holiday) {\r\n      this.demoData.holidays = null;\r\n      this.demoData.absences = null;\r\n      return;\r\n    }\r\n    this.demoData.holidays = {\r\n      year: Dates.getYear(holiday),\r\n      employmentId: null,\r\n      spec: {\r\n        wageBasis: WageBasis.Monthly,\r\n      }\r\n    };\r\n    this.demoData.absences = {\r\n      employmentId: null,\r\n      periods: [\r\n        {\r\n          causeCode: AbsenceCauseCode.Illness,\r\n          notes: \"Poissaolo demodatassa\",\r\n          period: {\r\n            start: absenceDay,\r\n            end: absenceDay,\r\n            daysCount: 1,\r\n            days: absenceDay,\r\n          },\r\n        }\r\n      ]\r\n    };\r\n  }\r\n\r\n  private initDateRanges() {\r\n    const currentMonth = Dates.getMonth(Dates.getToday());\r\n    this.periodShortcuts = {\r\n      monthCurrent: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth}.label`),\r\n      monthLast: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth === 1 ? 12 : (currentMonth - 1)}.label`),\r\n      monthOther: Translations.get(\"SALAXY.NG1.DateRange.otherMonth\"),\r\n      // monthMulti: \"Monta kuukautta\",\r\n      weeks2: Translations.get(\"SALAXY.UI_Terms.week2\"),\r\n      monthHalf: Translations.get(\"SALAXY.UI_Terms.monthHalf\"),\r\n      other: Translations.get(\"SALAXY.UI_Terms.otherPeriod\"),\r\n    };\r\n    this._periodStartDate = Dates.format(this.dateRange.start, \"D.M.\", null);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CostAccountingDimensionDefinition, CostAccountingDimension, CostAccountingDimensionScope, Translations, UserDefinedRow } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for handling row dimension input in the CalcRowsEditor.\r\n */\r\nexport class CalcRowDimensionInputController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /** Currently edited row */\r\n  public row: UserDefinedRow;\r\n  /** Current dimension defition */\r\n  public definition: CostAccountingDimensionDefinition;\r\n  /** Possible upper level (e.g. calculation) dimensions that are inherited */\r\n  private _inherited: CostAccountingDimension[];\r\n  /** Bindable read-only */\r\n  public readOnly?: boolean;\r\n  /**\r\n   * Style of inputs.\r\n   * If null or empty, displays normal input.\r\n   * - \"openeClose\" shows readOnly-like input with toggle button to open the field for editing.\r\n   */\r\n  public inputMode: \"\" | \"openClose\";\r\n\r\n  private _options: Array<{\r\n    /** Option value. */\r\n    value: any,\r\n    /** Option text.  */\r\n    text: string,\r\n    /** Option description. */\r\n    title?: string,\r\n  }>= [];\r\n\r\n  private _newDimensions: CostAccountingDimension[] = [];\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Copy of inherited dimensions */\r\n  public get inherited(): CostAccountingDimension[] {\r\n    return this._inherited;\r\n  }\r\n\r\n  /** Copy of inherited dimensions */\r\n  public set inherited(value: CostAccountingDimension[])  {\r\n    this._inherited = angular.copy(value);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the dimension values are inherited.\r\n   */\r\n  public isInherited(): boolean {\r\n    if(!this.row.accounting.dimensions.some((x) => x.id === this.definition.id && !!x.value)) {\r\n      return !!this.cleanDimensions(this.inherited)?.some((x) => x.id === this.definition.id);\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Determines if cost sharing is enabled based on the current definition.\r\n   * @returns {boolean} True if cost sharing is allowed, otherwise false.\r\n   */\r\n  public isCostSharingEnabled(): boolean {\r\n    return this.definition.allowCostSharing;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the cost sharing values for the current row dimension.\r\n   * This method uses a caching mechanism to store the computed values for performance optimization. It truncates the text values to a maximum of 10 characters, appending \"...\" if the text exceeds this length\r\n   * If the dimension is inherited, it filters and maps the inherited dimensions to the required format. Otherwise, it uses the current row's accounting dimensions.\r\n   */\r\n  public getCostSharingValues(): {text: string, value: number}[] {\r\n    return this.uiHelpers.cache(this, \"costSharingValues\", () => {\r\n      const truncate = (text: string): string => {\r\n        if (text.length <= 10) {\r\n          return text;\r\n        }\r\n        return text.substring(0, 10) + \"...\";\r\n      };\r\n      if(this.isInherited()) {\r\n        return this.cleanDimensions(this.inherited).filter((x) => x.id === this.definition.id).map((x) => ({ text: truncate(this.definition.options.find(option => option.value === x.value).text), value: x.percent }));\r\n      } else {\r\n        return this.row.accounting.dimensions.filter((x) => x.id === this.definition.id).map((x) => ({ text: truncate(this.definition.options.find(option => option.value === x.value).text), value: x.percent }));\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns inherited single value.\r\n   */\r\n  public getInheritedSingleValue(): CostAccountingDimension | undefined {\r\n    return (this.cleanDimensions(this.inherited) ?? []).find((x) => x.id === this.definition.id);\r\n  }\r\n\r\n  /**\r\n   * Sets single value.\r\n   */\r\n  public setSingleValue(value: any) {\r\n    const singleValue = this.row.accounting.dimensions?.find((x) => x.id === this.definition.id);\r\n    if (singleValue) {\r\n      singleValue.value = value;\r\n    } else {\r\n      this.row.accounting.dimensions.push({ id: this.definition.id, value });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns single value.\r\n   */\r\n  public getSingleValue() {\r\n    let singleValue = this.row.accounting.dimensions?.find((x) => x.id === this.definition.id) ?? this._newDimensions.find((x) => x.id === this.definition.id);\r\n    if (!singleValue && !this.readOnly) {\r\n      singleValue = { id: this.definition.id };\r\n      this._newDimensions.push(singleValue);\r\n    }\r\n\r\n    return singleValue;\r\n  }\r\n\r\n  /**\r\n   * Returns true if options exists for the dimension.\r\n   * @returns True, if an option exists for the value.\r\n   */\r\n  public hasOptions(): boolean {\r\n    const opts = this.getOptions();\r\n    return opts.filter(x => x.value).length > 0;\r\n  }\r\n\r\n  /**\r\n   * Returns available options for dimension.\r\n   */\r\n  public getOptions() {\r\n    if (!this._options) {\r\n      this._options = [];\r\n    }\r\n\r\n    let newOptions = [];\r\n\r\n    if (this.definition) {\r\n      newOptions = this.definition.options.filter((x) =>\r\n        x.scope !== CostAccountingDimensionScope.Hidden &&\r\n        (\r\n          // show if scope definition for dimension not given\r\n          ( !x.scope || x.scope === CostAccountingDimensionScope.None) ||\r\n          // or this scope\r\n          (CostAccountingDimensionScope.Row === x.scope)\r\n        )\r\n      )\r\n      .map( (x) => ({ value: x.value, text: x.text }));\r\n      newOptions.unshift({value: \"\", text: Translations.get(\"SALAXY.UI_Terms.notChosen\") });\r\n    }\r\n\r\n    this.modifyOptions(newOptions, this._options);\r\n    return this._options;\r\n  }\r\n\r\n  private cleanDimensions(dimensions: CostAccountingDimension[]) {\r\n    if (!dimensions) {\r\n      return dimensions;\r\n    }\r\n    const cleaned = dimensions.filter(x => x?.value && x?.id);\r\n    return cleaned;\r\n  }\r\n\r\n  private modifyOptions(\r\n    source: any[],\r\n    target: any[]) {\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    target.splice(0, target.length);\r\n    target.push(...source);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  CalcRowConfig,\r\n  CalcRowsLogic,\r\n  Calculation,\r\n  CalculationRowType,\r\n  CalculatorLogic,\r\n  Dates,\r\n  EnumerationsLogic,\r\n  IncomeTypesLogic,\r\n  Numeric,\r\n  RowsUsecaseLogic,\r\n  UserDefinedRow,\r\n  YearlyChangingNumbers,\r\n  Years,\r\n  IncomeTypeMetadata,\r\n  BaseUsecaseLogic,\r\n  InputEnumOption,\r\n  MilageOwnCarUsecaseLogic,\r\n  Translations,\r\n  UserDefinedRowLogic,\r\n  CalculationRowUnit,\r\n  WorktimeImportRow,\r\n  Arrays,\r\n  CostAccountingDimensionDefinition,\r\n  CostAccountingDimensionScope,\r\n  CalculationRowSource\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  EditDialogParameters,\r\n  RowTypeService,\r\n  SessionService,\r\n  UiHelpers,\r\n} from \"../../services\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\nclass CalcRows2019ControllerBindings extends ListControllerBaseBindings {\r\n  /** Sets the title in the table header. */\r\n  public title = \"@\";\r\n\r\n  /** Shows edit buttons. Used in Payroll. */\r\n  public showEditButtons = \"<\";\r\n\r\n  /** Shows gross totals and total payment in table footer */\r\n  public showGrossTotals = \"<\";\r\n\r\n  /**\r\n   * Alternative binding for parent: Give just a stand-alone rows list.\r\n   * Setting the row to an array will set these rows to the parent component\r\n   * or create a new parent component if no parent component is specified.\r\n   */\r\n  public rows = \"<\";\r\n\r\n  /** If set, filters the rows based on categories (plus rowTypes if set) */\r\n  public categories = \"<\";\r\n\r\n  /** If set, filters the rows based on statuses (Worktime rows only) */\r\n  public statuses = \"<\";\r\n\r\n  /**\r\n   * Defines the helper texts and branding color for row type selection list dialog.\r\n   * Null for default \"primary\" (no texts)\r\n   */\r\n  public rowTypeSelectHelp = \"@\";\r\n\r\n  /** If set, shows only these types (plus categories if set) */\r\n  public rowTypes = \"<\";\r\n\r\n  /**\r\n   * If set, shows only these sources in the source drop-down.\r\n   * This is a comma separated list of enum values.\r\n   */\r\n  public rowSources = \"@\";\r\n\r\n  /**\r\n   * Optional CostAccountingDimensionDefinitions\r\n   * If not set, cost accounting dimensions and their options are read from the settings.\r\n   */\r\n  public dimensions = \"<\";\r\n\r\n  /**\r\n   * User interface type of the editor: \"default\" is the one used in calculators.\r\n   * \"worktime-import\" is used in editing worktime import (contains employment relation).\r\n   * \"worktime-import-employment\" is used in editing worktime import (no employment, contains period).\r\n   * \"salary-defaults\" is used behind empoloyment to specify defaults (also in the settings).\r\n   */\r\n  public type = \"@\";\r\n\r\n  /** Hides final cost row. */\r\n  public hideFinalCostRow = \"<\";\r\n\r\n  /**\r\n   * Propertieds and logic for the situation where the dialog is dispalyed as part of row type definition editor.\r\n   */\r\n  public definitionEditor = \"<\";\r\n\r\n  /** Default dimension id to show in rows editor */\r\n  public defaultDimension = \"@\";\r\n\r\n  /** Count of dimension to show in editor */\r\n  public dimensionCount = \"<\";\r\n}\r\n\r\n/**\r\n * Editor for Calculation rows / usecases.\r\n * Can be bound to a Calculation or to Employment relation.\r\n */\r\nexport class CalcRows2019Controller extends ListControllerBase<\r\n  Calculation,\r\n  WorktimeImportRow\r\n> {\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new CalcRows2019ControllerBindings();\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"$timeout\",\r\n    \"SessionService\",\r\n    \"EditDialogParameters\",\r\n    \"$element\",\r\n    \"RowTypeService\",\r\n  ];\r\n\r\n  /** New empty row for databinding when creating a new row. */\r\n  public newRow: UserDefinedRow;\r\n\r\n  /** Currently selected row in 2022 UI. */\r\n  public current: UserDefinedRow;\r\n\r\n  /** Title in the Table header */\r\n  public title: string;\r\n\r\n  /** Shows edit buttons. Used in Payroll. */\r\n  public showEditButtons: boolean;\r\n\r\n  /** Shows gross totals and total payment in table footer */\r\n  public showGrossTotals: boolean;\r\n\r\n  /**\r\n   * Alternative binding for parent: Give just a stand-alone rows list.\r\n   * Setting the row to an array will set these rows to the parent component\r\n   * or create a new parent component if no parent component is specified.\r\n   * The resolving occures in list get, so the order of setting is not an issue.\r\n   */\r\n  public rows: UserDefinedRow[];\r\n\r\n  /**\r\n   * Propertieds and logic for the situation where the dialog is displayed as part of row type definition editor.\r\n   * If undefined, this is a rows editor (typically for a calculation) and not a row type definition editor.\r\n   */\r\n  public definitionEditor?: {\r\n    /** Mode of the definition editor. */\r\n    mode: \"builtIn\" | \"custom\" | \"prices\";\r\n  };\r\n\r\n  /**\r\n   * If set, filters the rows based on categories (plus rowTypes if set).\r\n   * Note that category error (validation errors) is added later and may not be supported by all parts of the UI.\r\n   */\r\n  public categories: (\r\n    | \"salary\"\r\n    | \"salaryCalc\"\r\n    | \"holidays\"\r\n    | \"salaryAdditions\"\r\n    | \"benefits\"\r\n    | \"expenses\"\r\n    | \"deductions\"\r\n    | \"other\"\r\n  )[];\r\n\r\n  /**\r\n   * Defines the helper texts and branding color for row type selection list dialog\r\n   * (showRowTypeSelectionDialog method)\r\n   */\r\n  public rowTypeSelectHelp: \"salaries\" | \"benefits\" | \"expenses\" | \"deductions\";\r\n\r\n  /** If set, shows only these types (plus categories if set) */\r\n  public rowTypes: CalculationRowType[];\r\n\r\n  /** If set, shows only the rows with these statuses. */\r\n  public statuses: string[] | string;\r\n\r\n  /**\r\n   * If set, shows only these sources in the source drop-down.\r\n   * This is a comma separated list of enum values.\r\n   */\r\n  public rowSources: string;\r\n\r\n  /** User interface type of the editor: Default is the one used in calculators. */\r\n  public type: \"worktime-import\" | \"worktime-import-employment\" | \"salary-defaults\" | \"default\";\r\n\r\n  /** If true, the current UI is a modal dialog. */\r\n  public isDialog: boolean;\r\n\r\n  /** Information on the usecase specific data / UI for this row. */\r\n  public usecase: {\r\n    isLoading?: boolean;\r\n    schema?: any;\r\n    isDefined?: boolean;\r\n  } = {};\r\n\r\n  /** Hides final cost row. */\r\n  public hideFinalCostRow = false;\r\n\r\n  /** Default dimension to show in rows editor */\r\n  public defaultDimension: string;\r\n\r\n  /** Count of dimension to show in editor */\r\n  public dimensionCount = 0;\r\n\r\n  public _dimensions: CostAccountingDimensionDefinition[] = undefined;\r\n\r\n  private _vehicleTypeSelection: InputEnumOption[];\r\n  private _vehicleAdditions: InputEnumOption[];\r\n\r\n  private _dailyAllowanceRegions: InputEnumOption[];\r\n\r\n  /**\r\n   * Creates a new CalcRows2019Controller\r\n   * @param uiHelpers - Salaxy UI helpers service.\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    uiHelpers: UiHelpers,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private session: SessionService,\r\n    editDialogParams: EditDialogParameters<any>,\r\n    private $element: JQLite,\r\n    private rowTypeService: RowTypeService,\r\n  ) {\r\n    super(uiHelpers);\r\n    if (editDialogParams.logic?.calc) {\r\n      // EditDialogParameters inject controller data in dialog situation.\r\n      // At the moment this is always a single item, but may later be extended to lists.\r\n      this.parent = editDialogParams.logic.calc;\r\n      if (editDialogParams.logic.definitionEditor) {\r\n        this.definitionEditor = editDialogParams.logic.definitionEditor;\r\n        this.isDialog = false;\r\n      } else {\r\n        this.isDialog = true;\r\n      }\r\n      this.current = editDialogParams.current;\r\n    }\r\n  }\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    this.newRow = this.getBlank();\r\n  }\r\n\r\n  /** Yearlysidecosts for translations, used in template */\r\n  public get yearlySideCosts(): {\r\n    current: YearlyChangingNumbers;\r\n    previous: YearlyChangingNumbers;\r\n  } {\r\n    const currentYear = Dates.getToday();\r\n    const previousYear = Dates.add(currentYear, -1, \"year\");\r\n    return {\r\n      current: this.formatYearlyNumbers(\r\n        Years.getYearlyChangingNumbers(currentYear)\r\n      ),\r\n      previous: this.formatYearlyNumbers(\r\n        Years.getYearlyChangingNumbers(previousYear)\r\n      ),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Marks that the editor is stand-alone, meaning that it does not edit a calculation,\r\n   * but it just edits a set of rows, typically in employment or settings.\r\n   * In this case the editor has creaed a fake calculation (because calculation is currently required for the row editor to work).\r\n   * TODO: Consider separating Calculation rows editor from stand-alone row editor.\r\n   */\r\n  public get isStandAlone(): boolean {\r\n    return !!this.parent?.usecase?.data?.standAloneRows;\r\n  }\r\n\r\n  /** Copies the given text to clipboard. */\r\n  public copyToClipboard(text: string) {\r\n    navigator.clipboard.writeText(text);\r\n  }\r\n\r\n  /** List of rows  */\r\n  public get list(): WorktimeImportRow[] | null {\r\n    if (!this.parent) {\r\n      if (this.rows) {\r\n        this.parent = CalculatorLogic.getBlank();\r\n        this.parent.usecase.data.standAloneRows = true;\r\n        this.parent.isReadOnly = this.mode == \"read-only\";\r\n      } else {\r\n        return null;\r\n      }\r\n    }\r\n    // HACK: This does not belong here: Move to server-side (in v03 release candidate).\r\n    CalculatorLogic.moveSalaryToRows(this.parent);\r\n    if (this.rows && this.parent.rows !== this.rows) {\r\n      // Rows has been set outside.\r\n      this.parent.rows = this.rows;\r\n    }\r\n    return this.parent.rows;\r\n  }\r\n\r\n  /** List filtered by categories and rowTypes. */\r\n  public get filteredList(): WorktimeImportRow[] | null {\r\n    const typesToShow = this.rowTypesToShow.map((x) => x as string);\r\n    const statuses = Arrays.assureArray(this.statuses);\r\n    const rowSources = Arrays.assureArray(this.rowSources);\r\n    if (typesToShow.length === 0 && statuses.length === 0 && rowSources.length === 0) {\r\n      return this.list;\r\n    }\r\n    return this.list.filter((x) =>\r\n      (!typesToShow.length || typesToShow.indexOf(x.rowType) >= 0) &&\r\n      (!statuses.length || statuses.indexOf((x as any).status) >= 0) &&\r\n      // HACK: rowSources property should be completely removed when moving default row display to RowTypeSettings editor\r\n      (!rowSources.length || x.source != CalculationRowSource.PriceEmployment)\r\n    );\r\n  }\r\n\r\n  /** Combines together categories and rowTypes properties as one list of row types. */\r\n  public get rowTypesToShow() {\r\n    const rowsLogic = new CalcRowsLogic(\r\n      this.session.isInRole(\"household\") ? \"household\" : \"company\"\r\n    );\r\n    const types = [...(this.rowTypes || [])];\r\n    if (this.categories) {\r\n      for (const cat of this.categories) {\r\n        types.push(...rowsLogic.getRowTypesByCategory(cat as any));\r\n      }\r\n    }\r\n    return types;\r\n  }\r\n\r\n  /** Creating of a new item. */\r\n  public getBlank(): UserDefinedRow {\r\n    const newRow = UserDefinedRowLogic.getBlank(this.list?.filter((x) => x.rowIndex >= 0).length || 0);\r\n    return newRow;\r\n  }\r\n\r\n  /**\r\n   * Returns a validation message for a row or null if none is required.\r\n   * @param row The row that is validated.\r\n   */\r\n  public getValidation(row: UserDefinedRow): {\r\n    /** Validation message */\r\n    msg: string;\r\n    /** Type of validation message */\r\n    type: \"default\" | \"error\";\r\n  } {\r\n    return RowsUsecaseLogic.getValidation(row);\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl() {\r\n    return \"salaxy-components/calc/rows/CalcRows2019EditDialog.html\";\r\n  }\r\n\r\n  /** checks if the image fileUrl given in the cost line is not a blob (omapalkka image upload adds blob) */\r\n  public showImagePreview(): boolean {\r\n    return (\r\n      this.current?.data?.fileUrl &&\r\n      !this.current?.data?.fileUrl.startsWith(\"blob:\")\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Gets the UX configuration for a row.\r\n   * @param row Row for which the config is fetched.\r\n   * If not set, gets the config for current.\r\n   */\r\n  public getConfig(row: UserDefinedRow = null): CalcRowConfig | undefined {\r\n    return this.rowTypeService.getConfig(row || this.current);\r\n  }\r\n\r\n  /**\r\n   * Gets the placeholder text for an input.\r\n   */\r\n  public getPlaceholderText(row: UserDefinedRow, field: \"amount\" | \"price\") {\r\n    if (!row.rowType) {\r\n      return \"\";\r\n    }\r\n    const config = this.getConfig(row);\r\n    if (field === \"amount\") {\r\n      return config.amount.label;\r\n    } else {\r\n      return config.price.label;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return the total for the row\r\n   */\r\n  public getRowTotal(row: UserDefinedRow) {\r\n    if (row == null) {\r\n      return null;\r\n    }\r\n    if (row.count == null) {\r\n      return row.price;\r\n    } else {\r\n      return row.count * row.price;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns true, if the row is disabled. The row is interpreted as disabled if it has no rowType\r\n   * or it has been set as hidden in the configuration.\r\n   * @param row Row to check\r\n   * @param field Type of the input / field.\r\n   */\r\n  public isDisabled(row: UserDefinedRow, field: \"amount\" | \"price\") {\r\n    if (!row?.rowType) {\r\n      return true;\r\n    }\r\n    const config = this.getConfig(row);\r\n    if (!config?.amount || !config?.price) {\r\n      console.debug(\"Row config not found for row\", row);\r\n      return false;\r\n    }\r\n    switch (field) {\r\n      case \"amount\":\r\n        return config.amount.input === \"hidden\";\r\n      case \"price\":\r\n        return config.price.input === \"hidden\";\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates the compensation row with the calculated price based on the unit type.\r\n   * @param row - The row containing both the main row price and compensation row data.\r\n   */\r\n  public updateCompensationRow(row: UserDefinedRow): void {\r\n    const compRow = row.data.compensationRows[0];\r\n    let price = 0;\r\n    switch (compRow.unit) {\r\n      case \"percent\":\r\n        price = row.price * compRow.count;\r\n        break;\r\n      case \"hours\":\r\n        price = compRow.price;\r\n        break;\r\n    }\r\n    compRow.price = price;\r\n  }\r\n\r\n  /** Row type changes on a row */\r\n  public rowTypeChanged(row: UserDefinedRow) {\r\n    this.rowTypeService.applyDefaultsToNewRow(row, this.parent?.workflow?.salaryDate ?? \"today\");\r\n  }\r\n\r\n  /**\r\n   * Commits the new row in newRow property and adds it to the rows list.\r\n   * Updates usecase and sets the newRow as new blank row.\r\n   */\r\n  public commitNewRow(showEdit = false): UserDefinedRow {\r\n    if (!this.newRow?.rowType) {\r\n      console.error(\"No row type set for the new row.\");\r\n      return null;\r\n    }\r\n    const row = this.newRow;\r\n    // TODO: Why this order? Shouldn't we first do rowTypeChanged and then updateUsecase?\r\n    this.updateUsecase(row);\r\n    this.list.push(row);\r\n    this.rowTypeChanged(row);\r\n    this.$timeout(() => {\r\n      // Reset new row type after timeout to avoid debounce\r\n      this.newRow = this.getBlank();\r\n    }, 300);\r\n    if (showEdit) {\r\n      this.showEdit(row, \"auto\");\r\n    } else {\r\n      this.$timeout(() => {\r\n        let elem: HTMLElement = null;\r\n        if (this.isDisabled(row, \"amount\")) {\r\n          elem = (this.$element[0] as HTMLElement).querySelector(\r\n            \"#iptPrice\" + row.rowIndex\r\n          );\r\n        } else {\r\n          elem = (this.$element[0] as HTMLElement).querySelector(\r\n            \"#iptCount\" + row.rowIndex\r\n          );\r\n        }\r\n        if (elem) {\r\n          elem.focus();\r\n        }\r\n      }, 500);\r\n    }\r\n    return row;\r\n  }\r\n\r\n  /** Shows the selection dialog for the row type. */\r\n  public showRowTypeSelectionDialog() {\r\n    this.uiHelpers\r\n      .openEditDialog(\r\n        \"salaxy-components/modals/calc/row-type-select.html\",\r\n        this.newRow,\r\n        {\r\n          categories: this.categories,\r\n          rowTypes: this.rowTypes,\r\n          rowTypeSelectHelp: this.rowTypeSelectHelp,\r\n        }\r\n      )\r\n      .then((result) => {\r\n        if (result.action === \"ok\" && result.hasChanges) {\r\n          this.showEdit(this.commitNewRow(), \"auto\");\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Updates the usecase property values without going to server. */\r\n  public updateUsecase(row: UserDefinedRow) {\r\n    this.getUsecaseLogic(row);\r\n  }\r\n\r\n  /**\r\n   * Returns the usecase logic instance for current row, also running the first update cycle on the row.\r\n   */\r\n  public getUsecaseLogic(row: UserDefinedRow): BaseUsecaseLogic {\r\n    return RowsUsecaseLogic.getUsecaseLogicForCalc(row, this.parent, true);\r\n  }\r\n\r\n  /**\r\n   * Gets vehicle type selections from usecase\r\n   * @returns InputEnumOption[] of vehicle selections\r\n   */\r\n  public getVehicleTypeSelection(): InputEnumOption[] {\r\n    if (!this._vehicleTypeSelection) {\r\n      this._vehicleTypeSelection = [];\r\n      const vehicleTypes: InputEnumOption[] = (\r\n        RowsUsecaseLogic.getUsecaseLogicForCalc(\r\n          this.current,\r\n          this.parent,\r\n          true\r\n        ) as MilageOwnCarUsecaseLogic\r\n      ).getVehicleTypeSelection();\r\n      this._vehicleTypeSelection.push(...vehicleTypes);\r\n    }\r\n    return this._vehicleTypeSelection;\r\n  }\r\n\r\n  /**\r\n   * Gets vehicle additions from usecase\r\n   * @returns InputEnumOption[] of vehicle additions\r\n   */\r\n  public getVehicleAdditions(): InputEnumOption[] {\r\n    if (!this._vehicleAdditions) {\r\n      this._vehicleAdditions = [];\r\n      const vehicleAdditions: InputEnumOption[] = (\r\n        RowsUsecaseLogic.getUsecaseLogicForCalc(\r\n          this.current,\r\n          this.parent,\r\n          true\r\n        ) as MilageOwnCarUsecaseLogic\r\n      ).getAdditionsSelection();\r\n      this._vehicleAdditions.push(...vehicleAdditions);\r\n    }\r\n    return this._vehicleAdditions;\r\n  }\r\n\r\n  /**\r\n   * Gets the regions for InternationalDailyAllowance as of today\r\n   */\r\n  public get dailyAllowanceRegions(): InputEnumOption[] {\r\n    if (!this._dailyAllowanceRegions) {\r\n      this._dailyAllowanceRegions = [];\r\n      const result = [];\r\n      Object.entries(Years.getYearlyTaxFreeNumbers(\"today\").countries).forEach(\r\n        (x) => {\r\n          result.push({\r\n            text: `${Translations.get(\r\n              `SALAXY.CORE.yearlyTaxfreeYears.countries.${x[0]}`\r\n            )} (${x[1]}€)`,\r\n            value: (x[0] as any) ?? \"\",\r\n          });\r\n        }\r\n      );\r\n      this._dailyAllowanceRegions.push(...result);\r\n    }\r\n    this._dailyAllowanceRegions = this._dailyAllowanceRegions.sort((a, b) =>\r\n      a.text.localeCompare(b.text)\r\n    );\r\n    return this._dailyAllowanceRegions;\r\n  }\r\n\r\n  /**\r\n   * Gets the Incomes Register metadata for a calculation row.\r\n   * @param row Row to check, null for current row.\r\n   * @returns The income type metadata. Empty object for empty row or empty irData.\r\n   */\r\n  public getIrCodeData(row: UserDefinedRow = null) {\r\n    row = row || this.current;\r\n    if (row?.data?.irData) {\r\n      return IncomeTypesLogic.getAll().find(\r\n        (x) => x.code === row.data.irData.code\r\n      );\r\n    }\r\n    return {};\r\n  }\r\n\r\n  /** Return the metadata based on irCode */\r\n  public getIrCodeDataWithCode(irCode: number): IncomeTypeMetadata {\r\n    return IncomeTypesLogic.getAll().find((x) => x.code === irCode);\r\n  }\r\n\r\n  /** Returns true if the filtered list has any rows. */\r\n  public get hasRows(): boolean {\r\n    return (this.filteredList || []).length > 0;\r\n  }\r\n\r\n  /** Gets the total for the current rows. */\r\n  public getTotal() {\r\n    return (this.filteredList || []).reduce(\r\n      (prev, curr) => prev + curr.count * curr.price,\r\n      0\r\n    );\r\n  }\r\n  /**\r\n   * Gets the gross total for the calculation.\r\n   * Current implementation does not support filtering.\r\n   */\r\n  public getGrossTotal() {\r\n    if (!this.parent || !this.parent.result || !this.parent.result.totals) {\r\n      return null;\r\n    }\r\n    return this.parent.result.totals.totalGrossSalary;\r\n  }\r\n\r\n  /**\r\n   * Gets the total payment for the calculation.\r\n   * Current implementation does not support filtering.\r\n   */\r\n  public getFinalCost() {\r\n    if (\r\n      !this.parent ||\r\n      !this.parent.result ||\r\n      !this.parent.result.employerCalc\r\n    ) {\r\n      return null;\r\n    }\r\n    return this.parent.result.employerCalc.finalCost;\r\n  }\r\n  /**\r\n   * Gets the net salary for the calculation.\r\n   * Current implementation does not support filtering.\r\n   */\r\n  public getNetSalary() {\r\n    return this.parent.result.workerCalc.salaryPayment;\r\n  }\r\n\r\n  /**\r\n   * Gets the total payment that is paid to palkkaus.fi.\r\n   * Current implementation does not support filtering.\r\n   */\r\n  public getTotalPayment() {\r\n    return this.parent.result.employerCalc.totalPayment;\r\n  }\r\n\r\n  /**\r\n   * Closes the edit dialog (either modal dialog or inline).\r\n   * @param method The closing method.\r\n   * @param $close In the case of modal dialog, this is the modal dialog close method.\r\n   */\r\n  public closeEditDialog(\r\n    method: \"cancel\" | \"ok-no-save\" | \"delete-no-save\",\r\n    $close: any = null\r\n  ): void {\r\n    if ($close) {\r\n      $close(method);\r\n      return;\r\n    }\r\n    switch (method) {\r\n      case \"delete-no-save\":\r\n        this.delete(this.current);\r\n        this.current = null;\r\n        return;\r\n      case \"ok-no-save\": // Perhaps later have commit functionality.\r\n      case \"cancel\":\r\n      default:\r\n        this.current = null;\r\n        return;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Shows the editor UI that may either be a dialog or an inline edit UI.\r\n   * @param item Item to edit. If rowIndex is null/undefined, the item is considered a new row and the properties\r\n   * extend new item (fetched from getBlank()).\r\n   * @param type Type of the edit UI.\r\n   */\r\n  public showEdit(\r\n    item: UserDefinedRow,\r\n    type: \"dialog\" | \"inline\" | \"auto\" = \"auto\"\r\n  ) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    const isNew = this.isInEdit && item.rowIndex == null;\r\n    if (isNew) {\r\n      item = angular.merge({}, this.getBlank(), item);\r\n      this.rowTypeChanged(item);\r\n      this.updateUsecase(item);\r\n    } else {\r\n      item.data = item.data ?? {};\r\n      item.accounting = item.accounting ?? {};\r\n    }\r\n\r\n    if (type != \"dialog\" && type != \"inline\") {\r\n      const elem = this.$element[0]?.querySelector(\r\n        \".salaxy-calc-rows-editor-details-container\"\r\n      ) as HTMLElement;\r\n      if (\r\n        elem &&\r\n        (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length)\r\n      ) {\r\n        // jQuery isVisible: https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom\r\n        type = \"inline\";\r\n      } else {\r\n        type = \"dialog\";\r\n      }\r\n    }\r\n    if (type == \"dialog\") {\r\n      this.showEditDialog(item, isNew);\r\n      return;\r\n    }\r\n\r\n    // Inline edit UI.\r\n    if (this.current == item) {\r\n      this.current = null;\r\n    } else {\r\n      if (isNew) {\r\n        this.list.push(item);\r\n      }\r\n      this.current = item;\r\n      this.$timeout(() => {\r\n        const elem: HTMLElement = (\r\n          this.$element[0] as HTMLElement\r\n        ).querySelector(\".salaxy-calc-details-dialog .form-control\");\r\n        if (elem) {\r\n          elem.focus();\r\n        }\r\n      }, 300);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog: Extends the base functionality with custom controller (non-supported results removed).\r\n   * @param item Item to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: UserDefinedRow | \"new\", isNew = false) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    if (item === \"new\") {\r\n      isNew = true;\r\n      item = this.getBlank();\r\n    }\r\n\r\n    item.data = item.data ?? {};\r\n    item.accounting = item.accounting ?? {};\r\n    this.uiHelpers\r\n      .openEditDialog(\r\n        this.getEditDialogTemplateUrl(),\r\n        item,\r\n        {\r\n          calc: this.parent,\r\n          readOnly: !this.isInEdit,\r\n        },\r\n        \"\",\r\n        \"CalcRows2019Controller\"\r\n      )\r\n      .then((result) => {\r\n        if (result.action === \"ok-no-save\") {\r\n          if (isNew) {\r\n            this.list.push(result.item);\r\n          }\r\n        } else if (result.action === \"delete-no-save\") {\r\n          if (!isNew) {\r\n            this.delete(item as UserDefinedRow);\r\n          }\r\n        } else {\r\n          // No changes, cancel\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the flag telling whether the component is in edit or read-only mode.\r\n   */\r\n  public get isInEdit(): boolean {\r\n    if (!this.isEditable) {\r\n      return !!this._isInEdit;\r\n    }\r\n    return super.isInEdit;\r\n  }\r\n  public set isInEdit(value: boolean) {\r\n    super.isInEdit = value;\r\n  }\r\n\r\n  /**\r\n   * Changes the view from read-only mode to edit mode.\r\n   */\r\n  public startEdit() {\r\n    if (!this.isEditable) {\r\n      this.isInEdit = true;\r\n      this.onStartEdit({\r\n        parent: this.parent,\r\n      });\r\n    } else {\r\n      super.startEdit();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns placeholder text for row\r\n   * @param row used row\r\n   * @returns row message as string\r\n   */\r\n  public getMessagePlaceholderText(row: UserDefinedRow): string {\r\n    if (row.message) {\r\n      return row.message;\r\n    }\r\n    let label = \"\";\r\n    if (row.rowType === CalculationRowType.IrIncomeType) {\r\n      label = IncomeTypesLogic.getAll().find(\r\n        (x) =>\r\n          (row.data?.kind && x.transactionCode === row.data.kind) ||\r\n          (row.data?.irData?.code > 0 && x.code === row.data.irData.code)\r\n      )?.label;\r\n    } else if (row.rowType == CalculationRowType.AbsencePeriod) {\r\n      label = EnumerationsLogic.getEnumLabel(\r\n        \"AbsenceCauseCode\",\r\n        row.data?.kind\r\n      );\r\n    } else if (\r\n      [\r\n        CalculationRowType.DailyAllowance,\r\n        CalculationRowType.EmploymentTermination,\r\n        CalculationRowType.WorkingTimeCompensation,\r\n        CalculationRowType.Remuneration,\r\n        CalculationRowType.OtherCompensation,\r\n        CalculationRowType.NonProfitOrg,\r\n        CalculationRowType.MealBenefit,\r\n        CalculationRowType.Training,\r\n        CalculationRowType.PaidSickLeave,\r\n        CalculationRowType.TotalWorkerPayment,\r\n      ].includes(row.rowType) &&\r\n      row.data?.kind\r\n    ) {\r\n      label = EnumerationsLogic.getEnumLabel(\r\n        `${row.rowType}Kind`,\r\n        row.data.kind\r\n      );\r\n    }\r\n\r\n    return (\r\n      label || EnumerationsLogic.getEnumLabel(\"CalculationRowType\", row.rowType)\r\n    );\r\n  }\r\n\r\n  /** Initializes and returns the unit for the row. */\r\n  public ensureUnit(row: UserDefinedRow): CalculationRowUnit {\r\n    if (!row.unit) {\r\n      const config = this.getConfig(row);\r\n      row.unit = config.amount.unit;\r\n    }\r\n    return row.unit;\r\n  }\r\n\r\n  /**\r\n   * Select a row in the list or unselect if already selected.\r\n   * @param row Row to select or \"all\" to select all currently vivisble rows.\r\n   * @param value Optional value to force selection true or false regardless of the current state.\r\n   */\r\n  public toggleSelectedRow(row: WorktimeImportRow | \"all\", value?: boolean) {\r\n    if (row == \"all\") {\r\n      this.filteredList.forEach((x) => {\r\n        this.toggleSelectedRow(x, value);\r\n      });\r\n      return;\r\n    }\r\n    if (row.data.isSelected && !value) {\r\n      // Toggle / Force unselect (undefined/false), Force select (true) keeps as is.\r\n      row.data.isSelected = false;\r\n    } else if (value !== false) {\r\n      // Toggle or Force select (undefined/true). Force unselect (false) keeps as is.\r\n      row.data.isSelected = true;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the selected rows in the list (only the filtered / visible rows).\r\n   * @returns The selected rows.\r\n   */\r\n  public getSelectedRows(): WorktimeImportRow[] {\r\n    return this.filteredList.filter((x) => x.data.isSelected);\r\n  }\r\n\r\n  /**\r\n   * Determines the visibility of dimensions based on certain conditions.\r\n   * @returns {boolean} - Returns `true` if dimensions should be visible, otherwise `false`.\r\n   */\r\n  public showDimension(): boolean {\r\n    return this.dimensionsCountToShow() > 0;\r\n  }\r\n\r\n  /**\r\n   * Returns the number of dimensions to show.\r\n   * @returns {number} The number of dimensions to show. If `dimensionCount` is not defined, returns 0.\r\n   */\r\n  public dimensionsCountToShow(): number {\r\n    return this.getDimensionsToShow().length;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the dimensions to show based on the session settings and predefined rules.\r\n   * This method filters the available dimensions to exclude hidden ones and includes\r\n   * those that match specific scope criteria. It prioritizes adding the default dimension\r\n   * and cost center first, followed by the remaining dimensions until the limit defined\r\n   * by `dimensionsCountToShow` is reached.\r\n   * @returns {CostAccountingDimensionDefinition[]} An array of dimensions to be displayed.\r\n   */\r\n  public getDimensionsToShow(): CostAccountingDimensionDefinition[] {\r\n    if (!this._dimensions) {\r\n      const dimensions = (this.session.session?.settings?.costAccounting?.dimensions ?? [])\r\n      .filter( (x) =>\r\n        // no hidden scope\r\n        x.scope !== CostAccountingDimensionScope.Hidden &&\r\n        (\r\n          // show if scope definition for dimension not given\r\n          ( !x.scope || x.scope === CostAccountingDimensionScope.None) ||\r\n          // or this scope\r\n          (CostAccountingDimensionScope.Row === x.scope)\r\n        )\r\n      );\r\n      const defaultDimension = this.defaultDimension || \"costCenter\";\r\n      // take a copy\r\n      const ordered = dimensions.slice(0);\r\n      // sort and mutate\r\n      ordered.sort( (x, y) => x.id == defaultDimension ? -1 : x.id == \"costCenter\" && y.id != defaultDimension ? -1: 0  );\r\n      // set length\r\n      ordered.length = (ordered.length > (this.dimensionCount ?? 0)) ? this.dimensionCount ?? 0: ordered.length;\r\n      return this._dimensions = ordered;\r\n    }\r\n    return this._dimensions;\r\n  }\r\n\r\n  private formatYearlyNumbers(\r\n    yearlyNumbers: YearlyChangingNumbers\r\n  ): YearlyChangingNumbers {\r\n    const keys = Object.keys(yearlyNumbers.sideCosts);\r\n    for (const key of keys) {\r\n      if (yearlyNumbers.sideCosts[key] >= 1) {\r\n        yearlyNumbers.sideCosts[key + \"Formatted\"] = Numeric.formatPrice(\r\n          yearlyNumbers.sideCosts[key]\r\n        );\r\n      }\r\n    }\r\n    return yearlyNumbers;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Calculation, Calculations, CalculationStatus } from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, ReportsService, SessionService, UiHelpers } from \"../../services\";\r\nimport { CalculationCrudController } from \"./CalculationCrudController\";\r\n\r\n/**\r\n * Controller for sharing actions: accept, decline\r\n */\r\nexport class CalcSharingReceiptActionController extends CalculationCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"ReportsService\", \"UiHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"InvoicesService\"];\r\n\r\n  /**\r\n   * Creates a new CalcSharingController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    calculationsApi: Calculations,\r\n    reportsService: ReportsService,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    protected invoicesService: InvoicesService,\r\n  ) {\r\n    super(calculationsApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Approve the the calculation requested by the worker. */\r\n  public approve(): Promise<Calculation> {\r\n    switch (this.current.workflow.status) {\r\n      case CalculationStatus.SharedWaiting:\r\n      case CalculationStatus.SharedRejected:\r\n        this.current.workflow.status = CalculationStatus.SharedApproved;\r\n        return this.save();\r\n      case CalculationStatus.SharedApproved:\r\n      default:\r\n        return Promise.resolve(this.current);\r\n    }\r\n  }\r\n\r\n  /** Reject the the calculation requested by the worker. */\r\n  public reject(): Promise<Calculation> {\r\n    switch (this.current.workflow.status) {\r\n      case CalculationStatus.SharedWaiting:\r\n      case CalculationStatus.SharedApproved:\r\n        this.current.workflow.status = CalculationStatus.SharedRejected;\r\n        return this.save();\r\n      case CalculationStatus.SharedRejected:\r\n      default:\r\n        return Promise.resolve(this.current);\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculation,\r\n  Language,\r\n  Translations,\r\n  Objects\r\n} from \"@salaxy/core\";\r\nimport {IrRowsReportConfigGenerator} from \"@salaxy/reports\";\r\nimport { SessionService } from \"../../services\";\r\nimport { ColumnDefinition } from \"tabulator-tables\";\r\nimport {SxyTableOptions} from \"../sxy-table/SxyTableController\";\r\nimport { SxyTableController } from \"../sxy-table/SxyTableController\";\r\n/**\r\n * Renders ir rows report for given calculations\r\n * Uses Tabulator tables.\r\n */\r\nexport class CalcsIrRowsController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"$timeout\",\r\n    \"SessionService\"\r\n  ];\r\n\r\n  /** The calculations for the report. Todo add Calcs*/\r\n  public calcs: Calculation[];\r\n\r\n  /**Selected report language */\r\n  public lang: Language;\r\n\r\n  /** Ref to used SxyTable */\r\n  public $sxyTable: SxyTableController;\r\n\r\n  private sxyTableConfig: {currentCalc: Calculation | Calculation[], reportLang: Language, config: {options: SxyTableOptions, include: ColumnDefinition[], data: any[]}} = {\r\n    currentCalc: null,\r\n    reportLang: Language.Default,\r\n    config: null\r\n  };\r\n\r\n  private renderedLang: string;\r\n\r\n  /**\r\n   * Creates a new CalcReportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private sessionService: SessionService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Config for SxyTable\r\n   */\r\n  public get tableConfig(): {options: SxyTableOptions, include: ColumnDefinition[], data: any[]}{\r\n    if(!this.calcs) {\r\n      this.sxyTableConfig = {\r\n        currentCalc: null,\r\n        reportLang: null,\r\n        config: null\r\n      };\r\n    } else {\r\n      const calcs = angular.copy(this.calcs);\r\n      if(!Objects.equal(this.sxyTableConfig.currentCalc, calcs) || this.lang !== this.sxyTableConfig.reportLang) {\r\n        this.sxyTableConfig.currentCalc = calcs;\r\n        this.sxyTableConfig.reportLang = this.lang;\r\n        this.getDefaultLanguage(this.lang).then((lang) => {\r\n          this.lang = lang;\r\n          this.renderedLang = this.lang;\r\n          this.refreshTableConfig();\r\n        });\r\n      }\r\n    }\r\n    return this.sxyTableConfig.config;\r\n  }\r\n\r\n  /** Refreshes table config */\r\n  public async refreshTableConfig() {\r\n    const renderingLang = this.lang ?? Language.Fi;\r\n    await Translations.loadLanguage(renderingLang);\r\n    this.sxyTableConfig.config = IrRowsReportConfigGenerator.getConfig(this.calcs, renderingLang);\r\n    await this.$timeout();\r\n    this.$sxyTable.refresh();\r\n  }\r\n\r\n  private async getDefaultLanguage(lang: Language): Promise<Language> {\r\n    if (!lang) {\r\n      return this.sessionService.getReportLang();\r\n    }\r\n    return Promise.resolve(lang);\r\n  }\r\n}","import { Calculation, CalculatorLogic } from \"@salaxy/core\";\r\n\r\n/**\r\n * Defines the panels logic in the Calculator\r\n */\r\nexport class CalculatorPanels {\r\n\r\n    /**\r\n     * Creates a new CalculatorPanels helper for a calculation\r\n     * @param calc - The Calculation object for which the helper operates\r\n     */\r\n    constructor(public calc: Calculation) {\r\n        if (!calc || Object.keys(calc).length === 0) {\r\n            calc = CalculatorLogic.getBlank();\r\n        }\r\n    }\r\n\r\n    /** Stores the UI properties to the calculation until a roundtrip to server. Then the property is set to null */\r\n    public get ui(): any {\r\n      if (!this.calc) {\r\n        return null;\r\n      }\r\n      const calcAsAny = this.calc as any;\r\n      calcAsAny.$ui = calcAsAny.$ui || {};\r\n      calcAsAny.$ui.activePanels = calcAsAny.$ui.activePanels || [];\r\n      return calcAsAny.$ui;\r\n    }\r\n\r\n    /**\r\n     * Toggles the user interface panels active (open/close) in a hierarchical way.\r\n     * The functionality mimics a hierarchical panel/menu structure in HTML / components that are not hierarchical.\r\n     * See the example to better understand the logic.\r\n     * Hierarchy logic is supported to 2 levels only - it is not tested on deeper hierarchy though it may function.\r\n     * @param panels - Identifiers of panel or two panels (panel and its child) that should be toggled.\r\n     * @example\r\n     * Assume we have these two panels open: \"panel1\", \"panel2\"\r\n     *\r\n     * - togglePanel(\"panel1\", \"panel2\") => [\"panel1\"]      // Normal 2nd level toggle opens and closes the last level.\r\n     * - togglePanel(\"panel2\") => [\"panel1\"]                // Alternative explicit last level close\r\n     * - togglePanel(\"panel1\") => []                        // Normal 1st level toggle opens and closes the first level\r\n     * - togglePanel(\"panel3\") => [\"panel3\"]                // Opening another \"path\" of the hierarchy\r\n     * - togglePanel(\"panel3\", \"panel4\") => [\"panel3\", \"panel4\"]\r\n     * - togglePanel(\"panel1\", \"panel4\") => [\"panel1\", \"panel4\"]    // Being a separate \"path\" is determined by last element only\r\n     * - togglePanel(\"last\") => [\"panel1\"]                  // Special keyword for closing the last panel\r\n     * - togglePanel() => []                                // Closes all panels\r\n     */\r\n    public toggleActivePanel(...panels: any[]) {\r\n        if (panels.length === 0 || !panels[0]) {\r\n            // Closing all\r\n            this.ui.activePanels = [];\r\n            return;\r\n        }\r\n        if (panels[0] === \"last\") {\r\n            // Closing last\r\n            if (this.ui.activePanels.length > 0) {\r\n                this.ui.activePanels.splice(this.ui.activePanels.length - 1);\r\n            }\r\n            return;\r\n        }\r\n        const positionOfLastPanel = this.ui.activePanels.indexOf(panels[panels.length - 1]);\r\n        if (positionOfLastPanel === -1) {\r\n            // New hierarchy path\r\n            this.ui.activePanels = panels;\r\n        } else {\r\n            // Remove starting from the match\r\n            this.ui.activePanels.splice(positionOfLastPanel, this.ui.activePanels.length);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Returns true if the panel is active (open).\r\n     * @param panel - identifier of the panel.\r\n     */\r\n    public isPanelActive(panel: string) {\r\n        return (this.ui.activePanels as string[]).indexOf(panel) >= 0;\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Barcodes, Dates, Invoice, InvoicePreview, Numeric, QrCodes, BicHelper, Iban, InvoicesLogic } from \"@salaxy/core\";\r\n\r\n/**\r\n * Shows an invoice as credit transfer: Either as printable display, copy-pasteable barcode or both.\r\n */\r\nexport class CreditTransferController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"$sce\", \"$timeout\"];\r\n\r\n  /** Invoice that is shown as credit transfer: The main data object. */\r\n  public invoice: Invoice;\r\n\r\n  private invoiceQrCode = \"\";\r\n\r\n  /**\r\n   * Display mode is either\r\n   *\r\n   * - \"official\": The official printable credit transfer (Finanssialan keskusliitto)\r\n   * - \"barcode-copy\": The copy-paste input + button (in a div) for copy pasting the the barcode into a web bank\r\n   * - \"default\": Both of the above separted by an explaining text.\r\n   */\r\n  public mode: \"default\" | \"official\" | \"barcode-copy\";\r\n\r\n  private _invoicePreview: InvoicePreview;\r\n\r\n  /**\r\n   * Creates a new CreditTransferController.\r\n   * @ignore\r\n   */\r\n  constructor(private $scope: angular.IScope, private $sce: angular.ISCEService, private $timeout: angular.ITimeoutService) {\r\n    // Dependency injection if necessary.\r\n  }\r\n\r\n  /** Copies the barcode from input to clipboard. */\r\n  public copyBarcode(): void {\r\n    const id = \"barcode\" + this.getId();\r\n    (document.getElementById(id) as HTMLInputElement).select();\r\n    document.execCommand(\"copy\");\r\n  }\r\n\r\n  /** Gets a unique id for the barcode input (from which the copying to clipboard is done). */\r\n  public getId(): number {\r\n    return this.$scope.$id;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the QR code for the specified invoice item.\r\n   * If the QR code is not already cached, it generates the QR code and caches it for future use.\r\n   * @returns The QR code string.\r\n   */\r\n  public getQrCode(): string {\r\n    if(!this.invoiceQrCode) {\r\n      this.invoiceQrCode = \"loading\";\r\n      this.generateQrCodeSvgForInvoice().then((qrCode) => {\r\n        if(!qrCode) {\r\n          this.invoiceQrCode = \"error\";\r\n          this.$timeout();\r\n          return this.invoiceQrCode;\r\n        } else {\r\n          this.invoiceQrCode = qrCode;\r\n          this.$timeout();\r\n          return this.$sce.trustAsHtml(this.invoiceQrCode);\r\n        }\r\n      });\r\n    }\r\n    if(this.invoiceQrCode === \"error\") {\r\n      return this.invoiceQrCode;\r\n    }\r\n    return this.$sce.trustAsHtml(this.invoiceQrCode);\r\n  }\r\n\r\n  /**\r\n   * Sets the Invoice based on an invoice preview (list item based preview) if the invoice is not empty.\r\n   * I.e. if you wish to set to null, you need to set the invoice null separately.\r\n   * Gets the original preview object if set.\r\n   */\r\n  public get invoicePreview(): InvoicePreview {\r\n    return this._invoicePreview;\r\n  }\r\n  public set invoicePreview(value: InvoicePreview) {\r\n    this._invoicePreview = value;\r\n    if (value?.invoice) {\r\n      this.invoice = this.getInvoice(value);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Retrieves the barcode for the invoice recipient's IBAN.\r\n   * If the IBAN does not start with \"fi\" or is not provided, an empty string is returned.\r\n   * The barcode is generated using the Barcodes.createBarcode function.\r\n   * @returns The barcode as a string, wrapped in an HTML trust object.\r\n   */\r\n  public getBarcode(): string {\r\n    if (!this.invoice?.recipient.iban || !this.invoice?.recipient.iban.toLowerCase().trim().startsWith(\"fi\")) {\r\n      return \"\";\r\n    }\r\n    const getDocumentAndSvgNode = () => {\r\n      return {document, svgNode: document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")};\r\n    };\r\n\r\n    const result = Barcodes.createBarcode(\r\n      getDocumentAndSvgNode,\r\n      this.invoice.recipient.iban || \"\",\r\n      this.invoice.header.referenceNumber || \"\",\r\n      Dates.asDate(this.invoice.header.dueDate),\r\n      Numeric.round(this.invoice.header.total * 100, 0),\r\n      {\r\n        width: 1.42,\r\n        height: 35,\r\n        displayValue: true,\r\n        fontSize: 15\r\n      }\r\n    );\r\n    if(!result) {\r\n      return \"\";\r\n    }\r\n    return this.$sce.trustAsHtml(new XMLSerializer().serializeToString(result as any));\r\n  }\r\n\r\n  /** Barcode value */\r\n  public get bcValue(): string {\r\n    if (!this.invoice?.recipient.iban) {\r\n      return \"\";\r\n    }\r\n    return Barcodes.getValue(\r\n      this.invoice.recipient.iban || \"\",\r\n      this.invoice.header.referenceNumber || \"\",\r\n      Dates.asDate(this.invoice.header.dueDate),\r\n      Numeric.round(this.invoice.header.total * 100, 0));\r\n  }\r\n\r\n  /**\r\n   * Generates the QR code for the invoice.\r\n   */\r\n  public async generateQrCodeSvgForInvoice(): Promise<string> {\r\n    if (!this.invoice) {\r\n      return;\r\n    }\r\n    const svg = await QrCodes.getValue(\r\n      this.getBicForIban(this.invoice?.recipient?.iban),\r\n      this.invoice.recipient.fullName,\r\n      this.invoice.recipient.iban,\r\n      this.invoice.header.referenceNumber,\r\n      null,\r\n      this.invoice.header.total,\r\n      this.invoice.header.dueDate\r\n    );\r\n    return svg;\r\n  }\r\n\r\n  /**\r\n   * Returns bic for iban\r\n   * @param iban Iban to get bic for\r\n   */\r\n  public getBicForIban(iban: string): string {\r\n    return BicHelper.getBicForIban(iban);\r\n  }\r\n\r\n  /**\r\n   * Determines whether to show the QR code for the invoice.\r\n   * @returns A boolean indicating whether to show the QR code.\r\n   */\r\n  public showQrCode(): boolean {\r\n    return InvoicesLogic.isEcfa(this.invoice.header.channel);\r\n  }\r\n\r\n  /**\r\n   * Checks if the IBAN of the recipient is an international IBAN.\r\n   * @returns {boolean} True if the IBAN is international, false otherwise.\r\n   */\r\n  public isInternationalIban(): boolean {\r\n    return Iban.isInternationalIban(this.invoice.recipient.iban ?? \"\");\r\n  }\r\n\r\n  /** Maps an invoice preview object to invoice. */\r\n  private getInvoice(preview: InvoicePreview): Invoice {\r\n    if (!preview?.invoice) {\r\n      return null;\r\n    }\r\n    return {\r\n      header: {\r\n        dueDate: preview.invoice.data.dueDate,\r\n        total: preview.invoice.payment,\r\n        referenceNumber: preview.invoice.reference,\r\n      },\r\n      rows: [],\r\n      payer: {\r\n        avatar: preview.invoice.ownerInfo.avatar,\r\n        officialId: preview.invoice.ownerInfo.officialId,\r\n        contact: {\r\n          email: preview.invoice.ownerInfo.email,\r\n          telephone: preview.invoice.ownerInfo.telephone,\r\n        },\r\n      },\r\n      recipient: {\r\n        fullName: preview.invoice.otherPartyInfo.avatar.displayName,\r\n        iban: preview.invoice.otherPartyInfo.ibanNumber,\r\n        officialId: preview.invoice.otherPartyInfo.officialId,\r\n        contact: {\r\n          email: preview.invoice.otherPartyInfo.email,\r\n          telephone: preview.invoice.otherPartyInfo.telephone,\r\n        },\r\n      },\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiListItemValidation, BootstrapStyle, calcReportType, Calculation, CalculationResult, CalculationResultLogic, Calculations,\r\n  CalendarEvents, Dates, Employments, InputEnumOption, MessageFrom, MessageThreadStatus, Objects, ODataResult, PaymentChannel, Payroll03Info, PayrollDetails,\r\n  Payrolls, PayrollStatus, SalaryDateKind, SalaryDateLogic, ThreadedMessageType, Translations, TaxcardUiInfo, TaxCard2019Logic, IApiListItem, PayrollListItem,\r\n  Taxcards,\r\n  EmploymentRelationTaxcard, HolidayCode, Arrays,\r\n  AbsenceCauseCode\r\n} from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, ReportsService, SessionService, UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { PayrollLogic } from \"./PayrollLogic\";\r\nimport { MessageThreadCrudController } from \"../communications\";\r\n\r\n/**\r\n * Payroll (Palkkalista) is a list of employees who receive salary or wages from a particular organization.\r\n * Typical usecase is that a a company has e.g. a monthly salary list that is paid\r\n * at the end of month. For next month, a copy is then made from the latest list and\r\n * the copy is potentially modified with the changes of that particular month.\r\n */\r\nexport class PayrollCrudController extends ApiCrudObjectController<PayrollDetails, PayrollListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Payrolls\", \"UiHelpers\", \"UiCrudHelpers\", \"$location\", \"$routeParams\", \"Calculations\", \"ReportsService\", \"SessionService\", \"InvoicesService\", \"CalendarEvents\", \"Employments\", \"$timeout\", \"Taxcards\"];\r\n\r\n  /** Index of the active tab in the combined edit view. */\r\n  public activeTab = \"properties\";\r\n\r\n  /** Flags to indicate if the request is in progress */\r\n  public loaders: any = {};\r\n\r\n  /**\r\n   * Action buttons that are visible in the user interface.\r\n   * Default is \"copy\", \"cancel\". If read only is forced neither is included.\r\n   * TODO: Current implementation is for read-only view only.\r\n   */\r\n  public actions: (\"none\" | \"copy\" | \"pay\" | \"cancel\")[];\r\n\r\n  /** All employment list items related to all calcs in payroll. */\r\n  private _employments: { [key: string]: IApiListItem } = {};\r\n\r\n  /** TODO: Items to refactor before going to production. */\r\n  /** Cache for changedCalcCount so that it is called only once within on $digest loop. */\r\n  protected changedCalcCountCache;\r\n\r\n  /** User interface related properties. */\r\n  private calcUiProperties: {\r\n    /** Calculation ID */\r\n    id: string,\r\n    /** If true, the calc is in edit mode. */\r\n    isInEdit: boolean,\r\n    /** If true, the calculation is in collapsed mode (not showing the details) */\r\n    isCollapsed: boolean,\r\n  }[] = [];\r\n\r\n  /**\r\n   * Reference to the latest calculation result\r\n   */\r\n  private _calcsResult: CalculationResult;\r\n\r\n  /**\r\n   * Reference to empty calculation array.\r\n   * Prevents infinite $digest iterations, when the reference to empty array does not change.\r\n   */\r\n  private emptyCalcList: Calculation[] = [];\r\n\r\n  /** Available channels */\r\n  private _availableChannels: Array<{ value: string, text: string }> = [];\r\n\r\n  constructor(\r\n    private payrollsApi: Payrolls,\r\n    uiHelpers: UiHelpers,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private calcsApi: Calculations,\r\n    private reportsService: ReportsService,\r\n    private sessionService: SessionService,\r\n    private invoicesService: InvoicesService,\r\n    private calendarEvents: CalendarEvents,\r\n    private employmentsApi: Employments,\r\n    private $timeout: angular.ITimeoutService,\r\n    private taxcardsApi: Taxcards,\r\n  ) {\r\n    // Dependency injection\r\n    super(payrollsApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (this.isReadOnlyForced) {\r\n      this.activeTab = \"reports\";\r\n    }\r\n  }\r\n\r\n  /** Catched the return of reload to update values. */\r\n  public reload(): Promise<PayrollDetails> {\r\n    return super.reload().then((payroll) => {\r\n      if (super.isNew()) {\r\n        this.setPaymentChannel(payroll);\r\n      }\r\n      return payroll;\r\n    });\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/payroll\",\r\n      detailsUrl: this.detailsUrl || \"/payroll/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Payrolls.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n\r\n  /**\r\n   * Returns true, if the given action button should be shown\r\n   * @param action One of the action values: See actions field type for supported values.\r\n   */\r\n  public showAction(action: string): boolean {\r\n    const actions = this.actions?.length ? this.actions :\r\n      this.isReadOnlyForced ? [] : [\"copy\", \"cancel\"];\r\n\r\n    if (action === \"pay\") {\r\n      // Check action and status\r\n      return !!actions.find(x => x == action) &&\r\n      ( !!this.current &&\r\n        ( this.current.info.status === PayrollStatus.Draft ||\r\n          this.current.info.status === PayrollStatus.WaitingApproval\r\n        )\r\n      );\r\n    }\r\n\r\n    return !!actions.find(x => x == action);\r\n  }\r\n\r\n  /** Returns true if any calculations have been added to the Payroll */\r\n  public get hasCalculations() {\r\n    return this.current && this.current.calcs.length > 0;\r\n  }\r\n\r\n  /** Save changes to the payroll as well as to changed calculations */\r\n  public save(): Promise<PayrollDetails> {\r\n    if (this.changedCalcCount > 0) {\r\n      // Just to not show \"Saving calculations...\"\r\n      return this.commitAllCalcs().then(() => {\r\n        return super.save();\r\n      });\r\n    }\r\n    return super.save();\r\n  }\r\n\r\n  /** Recalculate and save worktimes of all calculations. */\r\n  public recalculateWorktimes(): Promise<Calculation[]> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const recalcs: Promise<Calculation>[] = this.calcs.map((apiCalc) => {\r\n    return this.calcsApi.getWorktimeData(apiCalc).then((worktime) => {\r\n      apiCalc.worktime = worktime;\r\n      return this.calcsApi.recalculateWorktime(apiCalc).then((resultCalc) => {\r\n          return angular.copy(resultCalc, apiCalc);\r\n        });\r\n      });\r\n    });\r\n    return Promise.all(recalcs).then((result) => {\r\n      loader.dismiss();\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Calculates the total amount of days for the given period type.\r\n   * @param calc Calculation to calculate days for.\r\n   * @param periodType Period type to calculate days for.\r\n   * @returns Sum of days for the given period type.\r\n   */\r\n  public calculatePeriodDays(calc: Calculation, periodType: \"absencesDays\"  | \"leavesDays\" | \"paidAbsencesDays\" | \"accruedDays\") {\r\n    switch (periodType) {\r\n      case \"leavesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode == AbsenceCauseCode.AnnualLeave) ?? [], (x) => x.period.daysCount);\r\n      case \"absencesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && !x.isPaid) ?? [], (x) => x.period.daysCount);\r\n      case \"paidAbsencesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && x.isPaid) ?? [], (x) => x.period.daysCount);\r\n      case \"accruedDays\":\r\n        if (this.showAccruals(calc)) {\r\n          return Arrays.sum(calc.worktime?.accruals, (x) => x.daysAccrued);\r\n        }\r\n        return 0;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns true if the accruals are accumulated.\r\n   * @param calc Calculation.\r\n   * @returns Returns true if the accruals are accumulated.\r\n   */\r\n  public showAccruals(calc: Calculation) {\r\n    return calc.worktime?.accrualSpec?.code ==  HolidayCode.Permanent14Days || calc.worktime?.accrualSpec?.code ==  HolidayCode.Permanent35Hours || calc.worktime?.accrualSpec?.code ==  HolidayCode.TemporaryTimeOff;\r\n  }\r\n\r\n  /**\r\n   * Creates a copy of a payroll\r\n   * This is a synchronous method that should basically convert a saved item to a new item.\r\n   * @param copySource Item (container item) to copy as new.\r\n   */\r\n  public copyItem(copySource: PayrollDetails): PayrollDetails {\r\n    const oldId = copySource.id;\r\n    const copy = super.copyItem(copySource);\r\n    copy.info.messageThreadId = null;\r\n    if (copy.info.status === PayrollStatus.Template) {\r\n      copy.input.template = oldId;\r\n      copy.info.status = PayrollStatus.Draft;\r\n    }\r\n    // HACK: remove payroll-service flag. This will be replaced with invoicing flags eventually.\r\n    if (copy.usecase &&\r\n      (copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/pro-calc\" ||\r\n        copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/calc\")) {\r\n      copy.usecase = {};\r\n    }\r\n    return copy;\r\n  }\r\n\r\n  /**\r\n   * Reloads the validations and info for the current item.\r\n   * These are constructed based on calculations data and if changed, will update the Payroll in storage.\r\n   */\r\n  public reloadValidation() {\r\n    // TODO: Add indication that validation is being updated.\r\n    // TODO: This would become obsolete when we separate calculations modification to a separate controller.\r\n    if (this.currentId) {\r\n      this.api.getSingle(this.currentId).then((payroll) => {\r\n        this.current.validations = payroll.validations;\r\n        this.current.info = payroll.info;\r\n        this.original.validations = payroll.validations;\r\n        this.original.info = payroll.info;\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Gets a validation object for a calculation */\r\n  public getValidation(calc: Calculation): ApiListItemValidation {\r\n    return this.current.validations.find((x) => x.id === calc.id) || {\r\n      id: calc.id, // Paid Payrolls will not have validations.\r\n      isValid: true,\r\n    };\r\n  }\r\n\r\n  /** UI related data and texts about the taxcard. */\r\n  public getTaxUi(calc: Calculation): TaxcardUiInfo {\r\n    return TaxCard2019Logic.getCalcTaxcardInfo(calc);\r\n  }\r\n\r\n  /** Show add new taxcard dialog */\r\n  public async showAddNewTaxcard(calc: Calculation) {\r\n    const empl = await this.employmentsApi.getSingle(calc.worker.employmentId);\r\n    if (!empl) {\r\n      return;\r\n    }\r\n\r\n    // try to set to auto as first\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    if(empl.info.taxcard==EmploymentRelationTaxcard.Undefined || empl.info.taxcard==EmploymentRelationTaxcard.Auto){\r\n      const taxcard = await this.taxcardsApi.setAuto(calc.worker.paymentData.socialSecurityNumberValid);\r\n      if (taxcard) {\r\n        await this.commitCalc(calc, false, true);\r\n        loading.dismiss();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const result = await this.uiCrudHelpers.createNewTaxcard(calc.worker.paymentData.socialSecurityNumberValid);\r\n    if (result.action === \"ok\") {\r\n      await this.commitCalc(calc, false, true);\r\n      loading.dismiss();\r\n      return;\r\n    }\r\n\r\n    loading.dismiss();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the date is overdue (smaller than today).\r\n   * @param date Date to compare to today.\r\n   */\r\n  public isOverdue(date: string): boolean {\r\n    date = Dates.asDate(date);\r\n    return date < Dates.getToday();\r\n  }\r\n\r\n  /** Gets the list of calculations in this payroll object */\r\n  public get calcs(): Calculation[] {\r\n    return this.current ? this.current.calcs : this.emptyCalcList;\r\n  }\r\n\r\n  /** Returns the constantly updating info component from the open calculations (without round-trip to server) */\r\n  public get info(): Payroll03Info {\r\n    return PayrollLogic.getInfo(this.current, this.calcs);\r\n  }\r\n\r\n  /** Summarized CalculationResult for all calculations in the payroll. */\r\n  public get calcsResult(): CalculationResult {\r\n    const result = CalculationResultLogic.add(this.calcs.map((x) => x.result));\r\n    if (!angular.equals(result, this._calcsResult)) {\r\n      this._calcsResult = result;\r\n    }\r\n    return this._calcsResult;\r\n  }\r\n\r\n  /** Returns true if there is no net salary payment to worker at all. */\r\n  public get isCurrentZeroPayment(): boolean {\r\n    return PayrollLogic.isZeroPayment(this.calcs ?? []);\r\n  }\r\n\r\n  /** Disable function for the salary date picker. */\r\n  public isDisabledSalaryDate = (date): boolean => {\r\n    const role = this.sessionService.isInRole(\"pro\") ? \"pro\" :\r\n      this.sessionService.isInRole(\"admin\") ? \"admin\" : null;\r\n    switch (this.current.input.salaryDateKind) {\r\n      case SalaryDateKind.InPast:\r\n        return false;\r\n      case SalaryDateKind.Default:\r\n      default:\r\n        return !SalaryDateLogic.isValidSalaryDate(date, null, null, true, this.current.input.paymentChannel, PayrollLogic.isZeroPayment(this.calcs ?? []), role);\r\n    }\r\n  };\r\n\r\n  /**\r\n   * Checks if user is in one of the given roles.\r\n   * @param roles A comma separated list of roles, potentially with exlamation mark\r\n   */\r\n  public isInSomeRole(roles: string): boolean {\r\n    return this.sessionService.isInSomeRole(roles);\r\n  }\r\n\r\n  /** Gets the UI properties for a calculation */\r\n  public getUi(calc: Calculation): {\r\n    /** Calculation ID */\r\n    id: string,\r\n    /** If true, the calc is in edit mode. */\r\n    isInEdit: boolean,\r\n    /** If true, the calculation is in collabsed mode (not showing the details) */\r\n    isCollapsed: boolean,\r\n  } {\r\n    if (!calc || !calc.id) {\r\n      return {} as any;\r\n    }\r\n    let ui = this.calcUiProperties.find((x) => x.id === calc.id);\r\n    if (ui == null) {\r\n      ui = {\r\n        id: calc.id,\r\n        isCollapsed: true,\r\n        isInEdit: false,\r\n      };\r\n      this.calcUiProperties.push(ui);\r\n    }\r\n    return ui;\r\n  }\r\n\r\n  /**\r\n   * Set calculation rows editable\r\n   */\r\n  public setRowsEditable(calc: Calculation | \"all\") {\r\n    if (calc === \"all\") {\r\n      this.setUiForAll(\"isInEdit\", true);\r\n      this.setUiForAll(\"isCollapsed\", false);\r\n    } else {\r\n      this.getUi(calc).isCollapsed = false;\r\n      this.getUi(calc).isInEdit = false; // First to false to assure firing of the setter.\r\n      this.getUi(calc).isInEdit = true;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets a UI property for all calculations.\r\n   * @param prop Name of the property to set.\r\n   * @param value New value for the property.\r\n   */\r\n  public setUiForAll(prop: \"isCollapsed\" | \"isInEdit\", value: boolean) {\r\n    this.calcs.forEach((calc) => {\r\n      this.getUi(calc)[prop] = value;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Recalculates and saves calculation to the server.\r\n   * @param calc Calculation to save.\r\n   * @param noReloadValidation If true, the parent should call reloadValidation().\r\n   * @param forceSave If true, changes are saved even when there are no changes.\r\n   */\r\n  public commitCalc(calc: Calculation, noReloadValidation = false, forceSave = false): Promise<{\r\n    /** Calculation (after save, if saved) */\r\n    calc: Calculation,\r\n    /** True, if the calculation was saved. Unchanged calculations are not saved. */\r\n    isSaved: boolean,\r\n  }> {\r\n    this.getUi(calc).isInEdit = false;\r\n    if (forceSave || this.hasCalcChanges(calc)) {\r\n      return this.payrollsApi.calculationSave(calc, this.current.id).then((result) => {\r\n        if (!noReloadValidation) {\r\n          this.reloadValidation();\r\n        }\r\n        return this.setCalc(result);\r\n      });\r\n    }\r\n    return Promise.resolve({ calc, isSaved: false });\r\n  }\r\n\r\n  /** Sets the calculation after round-trip from the server. */\r\n  public setCalc = (newCalc: Calculation) => {\r\n    const oldCalc = this.current.calcs.find((x) => x.id === newCalc.id);\r\n    const originalCalc = this.original.calcs.find((x) => x.id === newCalc.id);\r\n    angular.copy(newCalc, oldCalc);\r\n    angular.copy(newCalc, originalCalc);\r\n    return { calc: newCalc, isSaved: true };\r\n  };\r\n\r\n  /**\r\n   * Reset any modifications to a calculation.\r\n   * @param calc Calculation that was edited.\r\n   */\r\n  public resetCalc(calc: Calculation) {\r\n    this.getUi(calc).isInEdit = false;\r\n    if (this.hasCalcChanges(calc)) {\r\n      const originalCalc = this.original.calcs.find((x) => x.id === calc.id);\r\n      angular.copy(originalCalc, calc);\r\n    }\r\n  }\r\n\r\n  /** Gets the count of changed calculations. */\r\n  public get changedCalcCount() {\r\n    // Cache within one $digest loop.\r\n    this.changedCalcCountCache = this.calcs.filter((x) => this.hasCalcChanges(x)).length;\r\n    return this.changedCalcCountCache;\r\n  }\r\n\r\n  /** Returns true if a calculation has changes to its original. */\r\n  public hasCalcChanges(calc: Calculation): boolean {\r\n    // TODO: Move this check to be run in every $digest loop\r\n    const originalCalc = this.original.calcs.find((x) => x.id === calc.id);\r\n    if (!originalCalc) {\r\n      throw new Error(\"Unexpected: No original calc in hasCalcChanges.\");\r\n    }\r\n    return !angular.equals(originalCalc, calc);\r\n  }\r\n\r\n  /**\r\n   * Commits changes to all calculations that are in edit mode.\r\n   * @returns A promise with the number of saved (changed) calculations.\r\n   */\r\n  public commitAllCalcs(): Promise<number> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.commitAllCalcs.heading\");\r\n    this.setUiForAll(\"isCollapsed\", true);\r\n    this.setUiForAll(\"isInEdit\", false);\r\n    const promises = this.calcs.map((x) => this.commitCalc(x, true));\r\n    return Promise.all(promises).then((result) => {\r\n      loader.dismiss();\r\n      this.reloadValidation();\r\n      return result.filter((x) => x.isSaved).length;\r\n    });\r\n  }\r\n\r\n  /** Resets all calculations to their unsaved state. */\r\n  public resetAllCalcs() {\r\n    this.calcs.forEach((x) => this.resetCalc(x));\r\n  }\r\n\r\n  /**\r\n   * Opens DateRange component in modal dialog.\r\n   * If daterange is changed asks whether all calculations should be changed to a new period.\r\n   * Saves changes to server.\r\n   */\r\n  public showDateRange() {\r\n    this.uiHelpers.showDateRange(this.current.input.period, \"SALAXY.NG1.PayrollComponent.showDateRangeTitle\", \"SALAXY.UI_Terms.save\").then((result) => {\r\n      if (result.result === \"ok\" && result.hasChanges && this.calcs.length > 0) {\r\n        this.uiHelpers.showConfirm(\"SALAXY.NG1.PayrollComponent.showDateRangeDialogTitle\",\r\n          \"SALAXY.NG1.PayrollComponent.showDateRangeDialogDescr\",\r\n          \"SALAXY.UI_Terms.yes\", \"SALAXY.UI_Terms.no\").then((value) => {\r\n            if (value) {\r\n              this.calcs.forEach((calc) => {\r\n                calc.info.workStartDate = this.current.input.period.start;\r\n                calc.info.workEndDate = this.current.input.period.end;\r\n                calc.framework.numberOfDays = this.current.input.period.daysCount;\r\n              });\r\n              this.save();\r\n            } else {\r\n              super.save();\r\n            }\r\n          });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a DateRange edit component for a single calculation.\r\n   * @param calc Calculation to modify.\r\n   */\r\n  public showDateRangeForCalculation(calc: Calculation) {\r\n    this.uiHelpers.showDateRange(calc, \"SALAXY.NG1.PayrollComponent.showDateRangeTitle\", \"SALAXY.UI_Terms.ok\");\r\n  }\r\n\r\n  /**\r\n   * Shows the calculation in a new dialog.\r\n   * @param calc Calculation to modify / view in dialog.\r\n   */\r\n  public showEditCalcDialog(calc: Calculation, dialog: \"default\" | \"ir\" = \"default\"): Promise<Calculation> {\r\n    const template = dialog === \"ir\" ? \"salaxy-components/modals/calc/CalcIr.html\" : \"salaxy-components/modals/calc/Calc.html\";\r\n    return this.uiHelpers.openEditDialog(\r\n      template,\r\n      calc,\r\n      {\r\n        title: Translations.get(\"SALAXY.NG1.PayrollComponent.showEditCalcDialog\"),\r\n      },\r\n      \"lg\",\r\n    ).then((result) => {\r\n      if (result.action === \"ok\") {\r\n        if (result.hasChanges) {\r\n          return this.commitCalc(result.item).then((result) => {\r\n            return result.calc;\r\n          });\r\n        } else {\r\n          return calc;\r\n        }\r\n      } else if (result.action === \"delete\") {\r\n        this.deleteCalc(calc);\r\n        return null;\r\n      } else {\r\n        this.resetCalc(calc);\r\n        return calc;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for editing an existing worker.\r\n   * @param calc - Calculation that should be edited\r\n   */\r\n  public showEditWorkerDialog(calc: Calculation): void {\r\n    if (!calc.worker?.accountId) {\r\n      this.showAddWorkerDialog(calc);\r\n    }\r\n    else {\r\n      this.uiCrudHelpers.openEditEmploymentDialog(calc.worker.employmentId, \"updateCalc\").then((result) => {\r\n        if (result.action === \"ok\" || result.action === \"ok-no-rows\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.showEditWorkerDialogUpdating\");\r\n          this.calcsApi.updateFromEmployment(calc, true, result.action === \"ok\").then((result2) => {\r\n            this.reloadValidation();\r\n            this.setCalc(result2);\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens a list of workers in to a dialog window.\r\n   * Edits the  calculation for the selected worker and current payroll.\r\n   */\r\n  public showAddWorkerDialog(calc: Calculation): void {\r\n    const workerList = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/WorkerSelect.html\",\r\n      workerList,\r\n      {\r\n        title: \"SALAXY.NG1.PayrollComponent.validate.addWorker\",\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && result.item.length == 1) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.showEditWorkerDialogUpdating\");\r\n          calc.worker.employmentId = result.item[0].id;\r\n          this.calcsApi.updateFromEmployment(calc, true, false).then((result2) => {\r\n            this.reloadValidation();\r\n            this.setCalc(result2);\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog during the check of auto taxcard.\r\n   */\r\n  public showRefreshAutoTaxcardDialog(calc: Calculation) {\r\n    this.loaders[\"showRefreshAutoTaxcardDialog\"] = true;\r\n    this.uiCrudHelpers.refreshAutoTaxcard(calc.worker.tax?.taxcardId, calc.workflow?.salaryDate).then(() => {\r\n      this.commitCalc(calc, false, true);\r\n      this.loaders[\"showRefreshAutoTaxcardDialog\"] = false;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a confirm dialog if payroll has any calculations.\r\n   * Returns true if a user clicks OK -button. Otherwise (cancel or close) returns false.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public importEmploymentDataAll(): Promise<boolean> {\r\n    const payroll = this.current as any;\r\n    if (!payroll.info.calcCount || payroll.info.calcCount === 0) {\r\n      return this.uiHelpers.showAlert(\"SALAXY.NG1.PayrollComponent.importEmploymentDataAllAlertTitle\", \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllAlertDescr\").then(() => false);\r\n    } else {\r\n      return this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllConfirmTitle\",\r\n        \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllConfirmDescr\",\r\n        \"SALAXY.UI_Terms.continue\",\r\n        \"SALAXY.UI_Terms.cancel\",\r\n      ).then((result: boolean) => {\r\n        if (result) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.importEmploymentDataAllLoading\");\r\n          const promises = this.calcs.map((x) => this.calcsApi.updateFromEmployment(x, true, true).then((result) => this.setCalc(result)));\r\n          return Promise.all(promises).then(() => {\r\n            loader.dismiss();\r\n            this.reloadValidation();\r\n            return true;\r\n          });\r\n        } else {\r\n          return false;\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Adds default rows (SalaryDefault) from employment information to calculation.\r\n   * Also saves the calculation\r\n   * @param calc The calculation to update.\r\n   */\r\n  public importEmploymentData(calc: Calculation): Promise<{\r\n    /** Calculation (after save, if saved) */\r\n    calc: Calculation,\r\n    /** True, if the calculation was saved. Unchanged calculations are not saved. */\r\n    isSaved: boolean,\r\n  }> {\r\n    return this.uiHelpers.showConfirm(\r\n      \"SALAXY.NG1.PayrollComponent.importEmploymentDataTitle\",\r\n      \"SALAXY.NG1.PayrollComponent.importEmploymentDataDescr\",\r\n      \"SALAXY.UI_Terms.continue\",\r\n      \"SALAXY.UI_Terms.cancel\",\r\n    ).then((result: boolean) => {\r\n      if (result) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.importEmploymentDataLoading\");\r\n        return this.calcsApi.updateFromEmployment(calc, true, true).then((result) => {\r\n          loader.dismiss();\r\n          this.reloadValidation();\r\n          return this.setCalc(result);\r\n        });\r\n      } else {\r\n        return Promise.resolve({ calc, isSaved: false });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Show confirm dialog and export employment data from calculation to Employment relation.\r\n   * If the calculation has unmodified changes, the calculation is saved.\r\n   * @param calc Calculation that should be exported to Employment.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public exportEmploymentData(calc: Calculation): Promise<boolean> {\r\n    return this.uiHelpers.showConfirm(\r\n      \"SALAXY.NG1.PayrollComponent.exportEmploymentDataTitle\",\r\n      \"SALAXY.NG1.PayrollComponent.exportEmploymentDataDescr\",\r\n      \"SALAXY.UI_Terms.continue\",\r\n      \"SALAXY.UI_Terms.cancel\",\r\n    ).then((result: boolean) => {\r\n      if (result) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataLoading\");\r\n        this.exportEmploymentDataNoConfirm(calc).then((resultInner) => {\r\n          if (resultInner.isSaved) {\r\n            this.reloadValidation();\r\n          }\r\n          loader.dismiss();\r\n          return true;\r\n        });\r\n      } else {\r\n        return false;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Show confirm dialog and export employment data from all calculations\r\n   * to their respective Employment relations.\r\n   * If any of calculations have unmodified changes, they are saved.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public exportEmploymentDataAll(): Promise<boolean> {\r\n    const payroll = this.current as any;\r\n    if (!payroll.info.calcCount || payroll.info.calcCount === 0) {\r\n      return this.uiHelpers.showAlert(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllAlertTitle\", \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllAlertDescr\").then(() => false);\r\n    } else {\r\n      return this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllConfirmTitle\",\r\n        \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllConfirmDescr\",\r\n        \"SALAXY.UI_Terms.continue\",\r\n        \"SALAXY.UI_Terms.cancel\",\r\n      ).then((result: boolean) => {\r\n        if (result) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllLoading\");\r\n          const promises = this.calcs.map((x) => this.exportEmploymentDataNoConfirm(x));\r\n          return Promise.all(promises).then((resultInner) => {\r\n            if (resultInner.find((x) => x.isSaved)) {\r\n              this.reloadValidation();\r\n            }\r\n            loader.dismiss();\r\n            return true;\r\n          });\r\n        } else {\r\n          return false;\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Deletes the calculation\r\n   * @param calc Calculation to delete\r\n   * @param unlink If true, will not delete the actual calculation, but instead unlinks it as a separate calculation outside this payroll.\r\n   */\r\n  public deleteCalc(calc: Calculation, unlink = false) {\r\n\r\n    if (unlink) {\r\n      this.uiHelpers.showConfirm(\"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.heading\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.intro\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.confirmButton\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.cancelButton\")\r\n        .then((result: boolean) => {\r\n          if (result) {\r\n            const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.loading\");\r\n            this.payrollsApi.unlinkCalculations(this.current, [calc.id])\r\n              .then((savedPayroll) => {\r\n                this.setCurrentValue(savedPayroll, true);\r\n                loader.dismiss();\r\n              });\r\n          }\r\n        });\r\n    } else {\r\n      this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.heading\",\r\n        this.changedCalcCount > 0 ? \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.introChanges\" : \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.introNoChanges\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.confirmButton\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.cancelButton\")\r\n        .then((result: boolean) => {\r\n          if (result) {\r\n            const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.loading\");\r\n            this.payrollsApi.deleteCalculations(this.current, [calc.id])\r\n              .then((savedPayroll) => {\r\n                this.setCurrentValue(savedPayroll, true);\r\n                loader.dismiss();\r\n              });\r\n          }\r\n        });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the URL for a payroll pdf.\r\n   * If report has not been saved (ID is null), returns null.\r\n   * @returns Url for specified report\r\n   */\r\n  public getPdfUrl() {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    return this.reportsService.getPdfUrlForCalcs(\"salarySlip\", this.current.calcs.filter((x) => x.id).map((x) => x.id), true);\r\n  }\r\n\r\n  /**\r\n   * Shows a report for the payroll calculation using a modal dialog.\r\n   * @param reportType - Type of report to show\r\n   * @param calculation - Calculation for the report\r\n   */\r\n  public showReport(reportType: calcReportType, calculation: Calculation) {\r\n    this.reportsService.showReportModalForCalc(reportType, calculation);\r\n  }\r\n\r\n  /**\r\n   * Opens a list of workers in to a dialog window.\r\n   * Creates a new calculation for the selected worker and current payroll.\r\n   */\r\n  public createNewCalc() {\r\n    const workerList = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/WorkerList.html\",\r\n      workerList,\r\n      {\r\n        title: \"SALAXY.NG1.PayrollComponent.createNewCalcDialog\",\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && workerList.length > 0) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.createNewCalcLoading\");\r\n          this.payrollsApi.addEmployments(this.current, workerList.map((x) => x.id))\r\n            .then((savedPayroll) => {\r\n              this.setCurrentValue(savedPayroll, true);\r\n              loader.dismiss();\r\n            });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Opens the list of calculations into a dialog window for selection and then adds them to payroll\r\n   * @param category Either \"paid\": Read-only, a copy is added ... or \"draft\": Editable, moved with status changed.\r\n   */\r\n  public addExistingCalc(category: \"paid\" | \"draft\" = \"draft\") {\r\n    const title = (category === \"paid\" ? \"SALAXY.NG1.PayrollComponent.addExistingCalcCopy\" : \"SALAXY.NG1.PayrollComponent.addExistingCalcMove\");\r\n    this.uiHelpers.openSelectCalcs(category, title).then((result) => {\r\n      if (result.action === \"ok\" && result.item.length > 0) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.addExistingCalcLoading\");\r\n        this.payrollsApi.addCalculations(this.current, result.item.map((x) => x.id))\r\n          .then((savedPayroll) => {\r\n            this.setCurrentValue(savedPayroll, true);\r\n            loader.dismiss();\r\n          });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Opens a list of payrolls for merging the payroll calculations to the current payroll.\r\n   * @param removeImportedRows If true, the operation removes all the imported rows,\r\n   * meaning all the rows in the target Payroll calcs that have a sourceId.\r\n   */\r\n  public async mergePayroll(removeImportedRows = false): Promise<void> {\r\n    const payrolls = [];\r\n    const result = await this.uiHelpers.openEditDialog(\"salaxy-components/modals/payroll/PayrollList.html\", payrolls, {\r\n      title: \"Valitse tuotava palkkalista\",\r\n      category: \"draft\",\r\n    }, \"lg\");\r\n    if (result.action != \"ok\" || payrolls.length < 1) {\r\n      return;\r\n    }\r\n    const loader = this.uiHelpers.showLoading(\"Yhdistetään palkkalistoja\");\r\n    const source = await this.payrollsApi.getSingle(payrolls[0].id);\r\n    let target = this.current;\r\n    const targetEmployments = target.calcs.map(x => x.worker.employmentId);\r\n    const newEmployments = new Set(source.calcs.map(x => x.worker.employmentId).filter(x => targetEmployments.indexOf(x) < 0));\r\n    if (newEmployments.size) {\r\n      loader.setText(`Lisätään ${newEmployments.size} työntekijää.`);\r\n      target = await this.payrollsApi.addEmployments(target, [...newEmployments]);\r\n      this.setCurrentValue(target, true);\r\n    }\r\n\r\n    const calcsToSave: Calculation[] = [];\r\n    if (removeImportedRows) {\r\n      target.calcs.forEach((calc) => {\r\n        if (calc.rows.find(x => !!x.sourceId)) {\r\n          calc.rows = calc.rows.filter(x => !x.sourceId);\r\n          calcsToSave.push(calc);\r\n        }\r\n      });\r\n    }\r\n\r\n    source.calcs.forEach((srcCalc) => {\r\n      const targetCalc = target.calcs.find((x) => x.worker.employmentId == srcCalc.worker.employmentId);\r\n      if (!targetCalc) {\r\n        throw new Error(\"No calculation: This is unexpected.\");\r\n      }\r\n      targetCalc.rows = targetCalc.rows.filter((x) => x.sourceId != srcCalc.id);\r\n      const newRows = Objects.copy(srcCalc.rows);\r\n      newRows.forEach(row => {\r\n        row.sourceId = srcCalc.id;\r\n      });\r\n      targetCalc.rows.push(...newRows);\r\n      if (calcsToSave.indexOf(targetCalc) < 0) {\r\n        calcsToSave.push(targetCalc);\r\n      }\r\n    });\r\n    const promises = calcsToSave.map((calc) => this.payrollsApi.calculationSave(calc, target.id));\r\n    loader.setText(`Tallennetaan ${promises.length} muokattua laskelmaa.`);\r\n    const calcs = await Promise.all(promises);\r\n    calcs.forEach((calc) => {\r\n      this.setCalc(calc);\r\n    });\r\n    this.reloadValidation();\r\n    loader.dismiss();\r\n  }\r\n\r\n  /** Returns true if the period of a calculation is different than the period of the Payroll. */\r\n  public isDateDifferent(calc: Calculation) {\r\n    return calc.info.workStartDate !== this.current.input.period.start\r\n      || calc.info.workEndDate !== this.current.input.period.end\r\n      || calc.framework.numberOfDays !== this.current.input.period.daysCount;\r\n  }\r\n\r\n  /**\r\n   * If true, the form controls should be read-only (no control at all).\r\n   */\r\n  public get isReadOnly() {\r\n    return super.isReadOnly\r\n      || (\r\n        this.current.info.status === PayrollStatus.PaymentStarted &&\r\n        this.current.input.paymentChannel !== PaymentChannel.Undefined\r\n      )\r\n      || (!this.sessionService.isInRole(\"pro\") && this.current.info.status === PayrollStatus.PaymentStarted);\r\n  }\r\n\r\n  /**\r\n   * Exports employment data from calculation to Employment relation.\r\n   * If the calculation has unmodified changes, the calculation is saved.\r\n   * @param calc Calculation that should be exported to Employment.\r\n   */\r\n  private exportEmploymentDataNoConfirm(calc: Calculation): Promise<{\r\n    /** Calculation (after save, if saved) */\r\n    calc: Calculation,\r\n    /** True, if the calculation was saved. Unchanged calculations are not saved. */\r\n    isSaved: boolean,\r\n  }> {\r\n    if (this.hasCalcChanges(calc)) {\r\n      return this.calcsApi.updateToEmployment(calc).then(() => this.commitCalc(calc, true));\r\n    } else {\r\n      return this.calcsApi.updateToEmployment(calc).then(() => {\r\n        return Promise.resolve({ calc, isSaved: false });\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends a payroll with messaging system and sets\r\n   * @param $msg The MessageThreadCrudController that is used for creating the message thread.\r\n   */\r\n  public sendPayroll($msg: MessageThreadCrudController): Promise<void> {\r\n    if (!$msg.current) {\r\n      $msg.model = \"new\";\r\n    }\r\n    const model = $msg.current;\r\n    model.otherParty = this.sessionService.session.settings.partner.accountId;\r\n    model.status = MessageThreadStatus.Active;\r\n    model.title = model.title || \"Palkkalista \" + this.current.input.title;\r\n    model.ownerWorkflow = {\r\n      salaryDate: this.current.info.salaryDate,\r\n    };\r\n    model.messages.push({\r\n      contentId: this.currentId,\r\n      fromParty: this.sessionService.isInRole(\"pro\") ? MessageFrom.OtherParty : MessageFrom.Owner,\r\n      type: ThreadedMessageType.Payroll\r\n    });\r\n    return $msg.save().then((msg) => {\r\n      if (this.current.info.status != PayrollStatus.WaitingApproval) {\r\n        this.current.info.messageThreadId = msg.id;\r\n        this.current.info.status = PayrollStatus.WaitingApproval;\r\n        return this.save().then(() => {\r\n          return;\r\n        });\r\n      } else {\r\n        this.current.info.messageThreadId = msg.id; // This is done by messageThread logic on server => ne need to save.\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the message title for the action.\r\n   * TODO: This could be replaced by enums.\r\n   */\r\n  public getTitle(action: string) {\r\n    return this.messageActions.find((x) => x.value == action).title + \": \" + this.current.input.title;\r\n  }\r\n\r\n  /**\r\n   * Available actions for the message.\r\n   * TODO: This could be replaced by enums or it may come from Service model.\r\n   */\r\n  public messageActions: InputEnumOption[] = [\r\n    {\r\n      text: \"Maksa\",\r\n      value: \"pay\",\r\n      title: \"Maksa palkkalista\",\r\n    },/* {\r\n      text: \"Tarkista (hyväksy/hylkää)\",\r\n      value: \"approve\",\r\n      title: \"Tarkista palkkalista\",\r\n    },*/\r\n    {\r\n      text: \"Tiedoksi\",\r\n      value: \"info\",\r\n      title: \"Tiedoksi palkkalista\",\r\n    }, {\r\n      text: \"Vastaa kysymykseen\",\r\n      value: \"question\",\r\n      title: \"Kysymyksiä palkkalistasta\",\r\n    }\r\n  ];\r\n\r\n  /**\r\n   * Deletes a linked message: Both the message thread and msg id in this payroll.\r\n   * @param $msg The MessageThreadCrudController that contains the current message.\r\n   */\r\n  public deleteMessage($msg: MessageThreadCrudController) {\r\n    this.uiHelpers.showConfirm(\"Haluatko poistaa viestiketjun?\", \"Haluatko varmasti poistaa viestiketjun?\")\r\n      .then((result) => {\r\n        if (result) {\r\n          if ($msg.current) {\r\n            $msg.deleteNoConfirm($msg.current).then(() => {\r\n              this.current.info.messageThreadId = null;\r\n              this.save();\r\n            });\r\n          } else {\r\n            this.current.info.messageThreadId = null;\r\n            this.save();\r\n          }\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Shows the paymentd dialog / the invoices UI. */\r\n  public showPaymentDialog() {\r\n    this.invoicesService.showPaymentDialog(this.current);\r\n  }\r\n\r\n  private setPaymentChannel(payroll: PayrollDetails) {\r\n    if (payroll && payroll.input) {\r\n      payroll.input.paymentChannel = this.invoicesService.defaultChannel;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends the payroll from company to PRO.\r\n   * @param message Message to the accountant\r\n   */\r\n  public sendToPro(message: string): void {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.sendToProSending\", \"SALAXY.NG1.PayrollComponent.sendToProSendingDescr\");\r\n    this.current.info.status = PayrollStatus.Draft;\r\n    this.save().then(() => {\r\n\r\n      this.api.saveWorkflowEvent(this.current, {\r\n        type: \"PartnerMessageClosed\",\r\n        ui: BootstrapStyle.Success,\r\n        message: message ? Translations.get(\"SALAXY.NG1.PayrollComponent.sendToProMessage\") + message : Translations.get(\"SALAXY.NG1.PayrollComponent.sendToProMessageChecked\"),\r\n      }).then(() => {\r\n        loader.dismiss();\r\n        this.$location.path(\"/\");\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Cancels the payment or invoice processing for the current payroll.\r\n   */\r\n  public cancel(): Promise<PayrollDetails> {\r\n    const eprWarningMessage = this.invoicesService.getEprWarningForCancellation(this.current.info.salaryDate, this.current.info.status == PayrollStatus.PaymentSucceeded);\r\n    const eprText = eprWarningMessage ? \"\\n\" + eprWarningMessage : \"\";\r\n    return this.uiHelpers.showConfirm(Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogTitle\") + \"?\", Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogDescr\") + `${eprText}`, \"SALAXY.NG1.CalcResultsComponent.cancelDialogYes\", \"SALAXY.NG1.CalcResultsComponent.cancelDialogNo\").then((result) => {\r\n      if (result) {\r\n        const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n        return this.payrollsApi.cancel(this.currentId).then((item: PayrollDetails) => {\r\n          this.setCurrentValue(item);\r\n          loading.dismiss();\r\n          return this.current;\r\n        });\r\n      } else {\r\n        return this.current;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Fetches and returns all employment list items related to all calcs in payroll. */\r\n  public get employments(): { [key: string]: IApiListItem } {\r\n    if (this.calcs) {\r\n      const calcsEmploymentIds = this.calcs.map((x) => x.worker.employmentId).filter((x) => !!x);\r\n      if (calcsEmploymentIds.length > 0) {\r\n        const fetchedEmploymenIds = Object.keys(this._employments);\r\n        const missingIds = calcsEmploymentIds.filter((x) => fetchedEmploymenIds.indexOf(x) < 0);\r\n        if (missingIds.length > 0) {\r\n          Object.assign(this._employments, Object.fromEntries(missingIds.map((id) => [id, undefined])));\r\n          const chunkSize = 15; // maximum possible without maxNodeCount error\r\n          const calls: Promise<ODataResult<any>>[] = [];\r\n          for (let i = 0; i < missingIds.length; i += chunkSize) {\r\n            const callIds = missingIds.slice(i, i + chunkSize);\r\n            calls.push(this.employmentsApi.getOData({ $filter: callIds.map((id) => `id eq '${id}'`).join(\" or \") }));\r\n          }\r\n          Promise.all(calls).then((results) => {\r\n            results.forEach((result) => {\r\n              result.items.forEach((item) => {\r\n                this._employments[item.id] = item;\r\n              });\r\n            });\r\n            this.$timeout();\r\n          });\r\n        }\r\n      }\r\n    }\r\n\r\n    return this._employments;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ContactType, EmploymentLogic, Dates, Taxcards, EmploymentRelationTaxcard, MessageThreadStatus, MessageFrom, ThreadedMessageType, Arrays, Numeric, PayrollDetails, Payrolls4, PayrollListItem, CalculationListItem, Calculation, Calculations, PayrollStatus, SalaryDateKind, SalaryDateLogic, Translations, Employment, Employments, InvoicesLogic, ApiListItemValidation, CalculationStatus, InputEnumOption, HolidayCode, AbsenceCauseCode } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, UiCrudHelpers, InvoicesService, UserSettingsService, SessionService } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { MessageThreadCrudController} from \"../communications/MessageThreadCrudController\";\r\n\r\n/**\r\n * Payroll header change info.\r\n */\r\nclass HeaderChangeInfo {\r\n\r\n  /** The payment channel has been changed. */\r\n  public isPaymentChannelChanged: boolean;\r\n  /** The period has been changed. */\r\n  public isPeriodChanged: boolean;\r\n  /** Salary date or salary date kind has been changed */\r\n  public isSalaryDateChanged: boolean;\r\n}\r\n\r\n/**\r\n * EXPERIMENTAL v4 version of the Payrolls CRUD Controller.\r\n * NOTE: This is just a quick hack version => Not for production  before complete review!!\r\n */\r\nexport class Payroll4CrudController extends ApiCrudObjectController<PayrollDetails, PayrollListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Payrolls4\", \"UiHelpers\", \"$location\", \"$routeParams\", \"Calculations\", \"Employments\", \"InvoicesService\", \"$timeout\", \"UserSettingsService\", \"SessionService\", \"Taxcards\", \"UiCrudHelpers\"];\r\n\r\n  /** Current calculation ID if one is selected. */\r\n  public calcId: string | undefined;\r\n\r\n  /** Current calculation if on is selected and loaded. */\r\n  public calc: Calculation | undefined;\r\n\r\n  /** Original calculation */\r\n  public originalCalc: Calculation | undefined;\r\n\r\n  /** Current calc list item*/\r\n  public calcListItem: CalculationListItem | undefined;\r\n\r\n  /** Active tab for single calculation. */\r\n  public calcTab = \"rows\";\r\n\r\n  /** Flags to indicate if the request is in progress */\r\n  public loaders: any = {};\r\n\r\n  /** Flag for showing the header dialog */\r\n  public showHeader = false;\r\n\r\n  /** Calculations for the reports. */\r\n  public reportCalcs: CalculationListItem[] = [];\r\n\r\n  /** Currently selected view in the Calculation Details offcanvas. */\r\n  public calcView = \"rows\";\r\n\r\n  /** Currently selected view in the Payroll Details offcanvas. */\r\n  public headerView = \"calculations\";\r\n\r\n  /**\r\n   * Action buttons that are visible in the user interface.\r\n   * Default is \"copy\", \"cancel\". If read only is forced neither is included.\r\n   * TODO: Current implementation is for read-only view only.\r\n   */\r\n  public actions: (\"none\" | \"copy\" | \"pay\" | \"cancel\")[];\r\n\r\n  constructor(\r\n    private payrollsApi: Payrolls4,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private calcsApi: Calculations,\r\n    private employmentsApi: Employments,\r\n    private invoicesService: InvoicesService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private userSettingsService: UserSettingsService,\r\n    private sessionService: SessionService,\r\n    private taxcardsApi: Taxcards,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n  ) {\r\n    // Dependency injection\r\n    super(payrollsApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (this.isReadOnlyForced) {\r\n      this.headerView = \"reports\";\r\n    }\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/payroll\",\r\n      detailsUrl: this.detailsUrl || \"/payroll/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Payrolls.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n   /**\r\n    * Returns true, if the given action button should be shown\r\n    * @param action One of the action values: See actions field type for supported values.\r\n    */\r\n    public showAction(action: string): boolean {\r\n      const actions = this.actions?.length ? this.actions :\r\n      this.isReadOnlyForced ? [] : [\"copy\", \"cancel\"];\r\n\r\n      if (action === \"pay\") {\r\n        // Check action and status\r\n        return !!actions.find(x => x == action) &&\r\n        ( !!this.current &&\r\n          ( this.current.info.status === PayrollStatus.Draft ||\r\n            this.current.info.status === PayrollStatus.WaitingApproval\r\n          )\r\n        );\r\n      }\r\n\r\n      return !!actions.find(x => x == action);\r\n    }\r\n\r\n  /**\r\n   * If true, the form controls should be read-only (no control at all).\r\n   */\r\n  public get isReadOnly() {\r\n    return super.isReadOnly || this.current?.info?.status === PayrollStatus.PaymentStarted;\r\n  }\r\n\r\n  /** Returns true if the period of a calculation is different than the period of the Payroll. */\r\n  public isDateDifferent(calc: CalculationListItem): boolean {\r\n    if (!calc?.data) {\r\n      return false;\r\n    }\r\n    return Dates.asDate(calc.data.workStartDate) !== Dates.asDate(this.current.input.period.start)\r\n      || Dates.asDate(calc.data.workEndDate) !== Dates.asDate(this.current.input.period.end);\r\n  }\r\n\r\n  /** Save changes to the payroll as well as to changed calculations */\r\n  public save(options: { applyEmploymentDefaultRows: boolean } = null): Promise<PayrollDetails> {\r\n    this.loaders[this.current?.id || \"new\"] = true;\r\n    if (this.isNew() && this.current?.input?.calculations?.length > 0) {\r\n      // Create new payroll\r\n      const calcIds = this.current.input.calculations.slice();\r\n      this.current.input.calculations = [];\r\n      return this.calcsApi.getSingle(calcIds[0]).then((calc) => {\r\n        return this.payrollsApi.getCalcsOData(calc.info.payrollId, null).then((odataResult) => {\r\n          return super.save(options).then(() => {\r\n            const calcs = this.orderCalcs(calcIds,odataResult.items);\r\n            const data: any = {};\r\n            data.listItemType = \"CalculationListItem\";\r\n            const columns = undefined;\r\n            const paramsTemplate = undefined;\r\n            const action = (items /*, data */) => {\r\n              const itemIds = items.map((x) => x.id);\r\n              return this.payrollsApi.addCalculations(this.current.id, itemIds).then((result) => {\r\n                const results = items.map(() => ({ message: \"\", result: [] }));\r\n                if (results.length > 0) {\r\n                  results[0].result = result;\r\n                }\r\n                return results;\r\n              });\r\n            };\r\n            return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.UI_Terms.wait\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then(() => {\r\n              return this.$timeout(() => this.reload().then(() => {\r\n                this.$location.path(\"/payroll/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n                return this.current;\r\n              }), 5000); // HACK: wait for index\r\n            });\r\n          });\r\n        });\r\n      });\r\n    }\r\n    else {\r\n      const wasNew = this.isNew();\r\n      const headerChangeInfo = this.getHeaderChangeInfo();\r\n      return super.save(options).then((result) => {\r\n        if (wasNew) {\r\n          delete this.loaders[\"new\"];\r\n          delete this.loaders[this.current.id];\r\n          return result;\r\n        }\r\n        else {\r\n          if (headerChangeInfo.isPaymentChannelChanged || headerChangeInfo.isSalaryDateChanged || headerChangeInfo.isPeriodChanged) {\r\n            const shouldChangePeriod = () => {\r\n              if (headerChangeInfo.isPeriodChanged) {\r\n                return this.uiHelpers.showConfirm(\"SALAXY.NG1.PayrollComponent.showDateRangeDialogTitle\",\r\n                  \"SALAXY.NG1.PayrollComponent.showDateRangeDialogDescr\",\r\n                  \"SALAXY.UI_Terms.yes\", \"SALAXY.UI_Terms.no\");\r\n              }\r\n              else {\r\n                return Promise.resolve(false);\r\n              }\r\n            };\r\n            return shouldChangePeriod().then((doChangePeriod) => {\r\n              if (!doChangePeriod && !headerChangeInfo.isPaymentChannelChanged && !headerChangeInfo.isSalaryDateChanged) {\r\n                delete this.loaders[\"new\"];\r\n                delete this.loaders[this.current.id];\r\n                return result;\r\n              }\r\n              else {\r\n                const calcs = this.calcs.slice(0);\r\n                const data: any = {};\r\n                data.listItemType = \"CalculationListItem\";\r\n                const columns = undefined;\r\n                const paramsTemplate = undefined;\r\n                const action = (items /*, data */) => {\r\n                  const itemIds = items.map((x) => x.id);\r\n                  return this.calcsApi.getMulti(itemIds).then((apiCalcs) => {\r\n                    for (const apiCalc of apiCalcs) {\r\n                      if (doChangePeriod) {\r\n                        apiCalc.info.workStartDate = this.current.input.period.start;\r\n                        apiCalc.info.workEndDate = this.current.input.period.end;\r\n                        apiCalc.framework.numberOfDays = this.current.input.period.daysCount;\r\n                      }\r\n                    }\r\n                    return this.payrollsApi.saveCalculations(this.current.id, apiCalcs).then((calcsResult) => {\r\n                      const results = items.map(() => ({ message: \"\", result: [] }));\r\n                      if (results.length > 0) {\r\n                        results[0].result = calcsResult;\r\n                      }\r\n                      return results;\r\n                    });\r\n                  });\r\n                };\r\n                return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.commitAllCalcs.heading\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n                  if (dialogResult.done) {\r\n                    dialogResult.results.forEach((result) => {\r\n                      for (const item of result.result) {\r\n                        const listItem = this.calcs.find((c) => c.id === item.id);\r\n                        if (listItem) {\r\n                          angular.copy(item, listItem);\r\n                        }\r\n                        else {\r\n                          this.calcs.push(item);\r\n                        }\r\n                      }\r\n                    });\r\n                    this.setPageItems();\r\n                  }\r\n                  delete this.loaders[\"new\"];\r\n                  delete this.loaders[this.current.id];\r\n                  return this.reload();\r\n                });\r\n              }\r\n            });\r\n          }\r\n          else {\r\n            delete this.loaders[\"new\"];\r\n            delete this.loaders[this.current.id];\r\n            return result;\r\n          }\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Recalculate and save worktimes of all calculations. */\r\n  public saveWorktimes(): Promise<void> {\r\n    this.loaders[\"worktime\" + this.current?.id] = true;\r\n    const calcs = this.calcs.slice(0);\r\n    const data: any = {};\r\n    data.listItemType = \"CalculationListItem\";\r\n    const columns = undefined;\r\n    const paramsTemplate = undefined;\r\n    const action = (items) => {\r\n      const itemIds = items.map((x) => x.id);\r\n      return this.payrollsApi.saveCalculations(this.current.id, itemIds, true ).then((result) => {\r\n        const results = items.map(() => ({ message: \"\", result: [] }));\r\n        if (results.length > 0) {\r\n          results[0].result = result;\r\n        }\r\n        return results;\r\n      });\r\n    };\r\n    return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.commitAllCalcs.heading\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n      if (dialogResult.done) {\r\n        dialogResult.results.forEach((result) => {\r\n          for (const item of result.result) {\r\n            const listItem = this.calcs.find((c) => c.id === item.id);\r\n            if (listItem) {\r\n              angular.copy(item, listItem);\r\n            }\r\n          }\r\n        });\r\n        const currentPage = this.page;\r\n        // start reload calculations\r\n        currentPage.calcs = [];\r\n        currentPage.originalCalcs = [];\r\n        // and payroll\r\n        return this.reload();\r\n      }\r\n    }).then( () => {\r\n      delete this.loaders[\"worktime\" + this.current?.id];\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Calculates the total amount of days for the given period type.\r\n   * @param calc Calculation to calculate days for.\r\n   * @param periodType Period type to calculate days for.\r\n   * @returns Sum of days for the given period type.\r\n   */\r\n  public calculatePeriodDays(calc: Calculation, periodType: \"absencesDays\"  | \"leavesDays\" | \"paidAbsencesDays\" | \"accruedDays\") {\r\n    switch (periodType) {\r\n      case \"leavesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode == AbsenceCauseCode.AnnualLeave) ?? [], (x) => x.period.daysCount);\r\n      case \"absencesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && !x.isPaid) ?? [], (x) => x.period.daysCount);\r\n      case \"paidAbsencesDays\":\r\n        return Arrays.sum(calc.worktime?.absencesPeriods?.filter(x => x.causeCode != AbsenceCauseCode.AnnualLeave && x.isPaid) ?? [], (x) => x.period.daysCount);\r\n      case \"accruedDays\":\r\n        if (this.showAccruals(calc)) {\r\n          return Arrays.sum(calc.worktime?.accruals, (x) => x.daysAccrued);\r\n        }\r\n        return 0;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns true if the accruals are accumulated.\r\n   * @param calc Calculation.\r\n   * @returns Returns true if the accruals are accumulated.\r\n   */\r\n  public showAccruals(calc: Calculation) {\r\n    return calc.worktime?.accrualSpec?.code ==  HolidayCode.Permanent14Days || calc.worktime?.accrualSpec?.code ==  HolidayCode.Permanent35Hours || calc.worktime?.accrualSpec?.code ==  HolidayCode.TemporaryTimeOff;\r\n  }\r\n\r\n  /**\r\n   * Creates a copy of a payroll\r\n   * This is a synchronous method that should basically convert a saved item to a new item.\r\n   * @param copySource Item (container item) to copy as new.\r\n   */\r\n  public copyItem(copySource: PayrollDetails): PayrollDetails {\r\n    const oldId = copySource.id;\r\n    const copy = super.copyItem(copySource);\r\n    copy.input.salaryDate = null;\r\n    copy.info.salaryDate = null;\r\n    copy.info.messageThreadId = null;\r\n    copy.info.originalPaymentId = undefined;\r\n    copy.info.paymentId = undefined;\r\n    if (copy.info.status === PayrollStatus.Template) {\r\n      copy.input.template = oldId;\r\n    }\r\n    copy.info.status = PayrollStatus.Draft;\r\n    // HACK: remove payroll-service flag. This will be replaced with invoicing flags eventually.\r\n    if (copy.usecase &&\r\n      (copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/pro-calc\" ||\r\n        copy.usecase.uri === \"palkkaus.fi/usecases/payroll-service/calc\")) {\r\n      copy.usecase = {};\r\n    }\r\n    return copy;\r\n  }\r\n\r\n  /** Close the header dialog */\r\n  public closeHeader() {\r\n    delete this.showHeader;\r\n    if (this.isNew()) {\r\n      this.$location.path(this.getDefaults().listUrl);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets the current calculation ID\r\n   * @param calcId The ID of the calculation to set.\r\n   * Set as undefined to hide the current calculation.\r\n   */\r\n  public setCalc(calcId: string | undefined) {\r\n    this.calcId = calcId;\r\n    this.calcListItem = this.calcs.find((c) => c.id === calcId);\r\n    this.calc = undefined;\r\n    this.originalCalc = undefined;\r\n    if (calcId) {\r\n      const loadedCalc = this.page.calcs.find((c) => c.id === calcId);\r\n      if (loadedCalc && !!loadedCalc.rows) {\r\n        this.calc = loadedCalc;\r\n        this.originalCalc = this.page.originalCalcs.find((c) => c.id === calcId);\r\n      }\r\n      else\r\n      {\r\n        this.calcsApi.getSingle(calcId).then((result) => {\r\n          // find from current page\r\n          const preCalc = this.page.calcs.find((c) => c.id === calcId);\r\n          if (preCalc) {\r\n            const calc = result;\r\n            angular.copy(calc, preCalc);\r\n            const originalCalc = this.page.originalCalcs.find((c) => c.id === calcId);\r\n            angular.copy(calc, originalCalc);\r\n            this.calc = preCalc;\r\n            this.originalCalc = originalCalc;\r\n          }\r\n          else\r\n          {\r\n            // find from all pages\r\n            const page = this._pages.pages.find((p) => p.items.find((c) => c.id === calcId));\r\n            if (page) {\r\n              const calc = result;\r\n              page.calcs.push(calc);\r\n              const originalCalc = angular.copy(calc);\r\n              page.originalCalcs.push(originalCalc);\r\n              this.calc = calc;\r\n              this.originalCalc = originalCalc;\r\n              this._pages.currentIdx = page.current -1;\r\n            }\r\n          }\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  private _canvasInfo = {\r\n    calc: false,\r\n    header: false\r\n  };\r\n  /**\r\n   * Returns true if the canvas should be shown.\r\n   */\r\n  public shouldShowCanvas(canvas: \"calc\" | \"header\" ,  truly: any): boolean {\r\n    const showCanvas = !!truly;\r\n    const launcher = document.querySelector(\"iframe#launcher\") as HTMLElement;\r\n    if (launcher) {\r\n      this._canvasInfo[canvas] = showCanvas;\r\n      const hideHelp = this._canvasInfo[\"calc\"] || this._canvasInfo[\"header\"];\r\n      if (hideHelp) {\r\n        launcher.style.display = \"none\";\r\n      }\r\n      else {\r\n        launcher.style.display = \"\";\r\n      }\r\n    }\r\n    return showCanvas;\r\n  }\r\n\r\n  /**\r\n   * Advances to next calc.\r\n   */\r\n  public goToCalc(previous = false) {\r\n    let idx = this.calcs.indexOf(this.calcListItem);\r\n    if (idx == -1) {\r\n      return;\r\n    }\r\n\r\n\r\n    const saveIfChanged = () => {\r\n      if (this.hasEmploymentChange) {\r\n        return this.saveEmployment((this as any).$employment.current, false);\r\n      }\r\n      else if (this.hasCalcChange) {\r\n        return this.saveCalc(this.calc);\r\n      }\r\n      else\r\n      {\r\n        return Promise.resolve(this.current);\r\n      }\r\n    };\r\n\r\n    return saveIfChanged().then(() => {\r\n      if (previous) {\r\n        idx -= 1;\r\n        return idx > -1 ? this.setCalc(this.calcs[idx].id) : this.setCalc(this.calcs[this.calcs.length - 1].id);\r\n      }\r\n      else {\r\n        idx += 1;\r\n        return idx < this.calcs.length ? this.setCalc(this.calcs[idx].id) : this.setCalc(this.calcs[0].id);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Checks if the current calcs has changes.\r\n   */\r\n  public get hasCalcChange(): boolean {\r\n    if (this.calc?.isReadOnly) {\r\n      return false;\r\n    }\r\n    return !angular.equals(this.calc, this.originalCalc);\r\n  }\r\n\r\n  /**\r\n   * Checks if the current employment has changes.\r\n   */\r\n  public get hasEmploymentChange(): boolean {\r\n    if (this.calc?.isReadOnly) {\r\n      return false;\r\n    }\r\n    const employment = (this as any).$employment;\r\n\r\n    if (employment?.current && employment?.original) {\r\n      // HACK fixes\r\n      // remove $$hashKey added by angular\r\n      const current = angular.fromJson(angular.toJson(employment.current));\r\n      // add defaults to original as in current\r\n      const original = angular.copy(employment.original);\r\n      EmploymentLogic.getContact(original, ContactType.EmployerOverride);\r\n      return !angular.equals(current, original);\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Toggles the current calculation ID\r\n   * @param calcId The ID of the calculation to set.\r\n   */\r\n  public toggleCalc(calcId: string | undefined) {\r\n    if (this.calcId === calcId) {\r\n      this.setCalc(undefined);\r\n    } else {\r\n      this.setCalc(calcId);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Saves the calculation and reloads the payroll.\r\n   */\r\n  public saveCalc(calcToSave: Calculation): Promise<PayrollDetails> {\r\n    const calcId = calcToSave.id;\r\n\r\n    this.loaders[calcId] = true;\r\n    return this.payrollsApi.saveCalculations(this.current.id, [calcToSave]).then((items) => {\r\n      for (const item of items) {\r\n        const listItem = this.calcs.find((c) => c.id === item.id);\r\n        if (listItem) {\r\n          angular.copy(item, listItem);\r\n        }\r\n      }\r\n      delete this.loaders[calcId];\r\n      return this.calcsApi.getSingle(calcId).then((calc) => {\r\n        if (this.calcId == calcId) {\r\n          if (this.calc) {\r\n            angular.copy(calc,this.calc);\r\n            angular.copy(calc, this.originalCalc);\r\n          }\r\n          else\r\n          {\r\n            this.calc = calc;\r\n            this.originalCalc = angular.copy(calc);\r\n          }\r\n        }\r\n        else\r\n        {\r\n          // start reload calculations\r\n          const currentPage = this.page;\r\n          currentPage.calcs = currentPage.calcs.filter((x) => x.id != calcId);\r\n          currentPage.originalCalcs = currentPage.originalCalcs.filter((x) => x.id != calcId);\r\n        }\r\n        return this.reload();\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Saves the employment and updates the calcs rows optionally */\r\n  public saveEmployment(employment: Employment, updateRows = false): Promise<PayrollDetails> {\r\n    this.loaders[this.calc.id + \"-employment-\" + updateRows] = true;\r\n    return this.employmentsApi.save(employment).then(() => {\r\n      return this.calcsApi.updateFromEmployment(this.calc, false, updateRows).then((calc) => {\r\n        if (this.calc) {\r\n          angular.copy(calc,this.calc);\r\n          angular.copy(calc, this.originalCalc);\r\n        }\r\n        else\r\n        {\r\n          this.calc = calc;\r\n          this.originalCalc = angular.copy(calc);\r\n        }\r\n        return this.saveCalc(this.calc).then(() => {\r\n          delete this.loaders[this.calc.id + \"-employment-\" + updateRows];\r\n          return this.current;\r\n        });\r\n      });\r\n    });\r\n  }\r\n\r\n  private _calcs: CalculationListItem[] | undefined;\r\n\r\n  /**\r\n   * Gets the list items of the calculations of the current payroll.\r\n   * HACK: This is temporary dev version => Need to consider different apprroaches for the final version.\r\n   */\r\n  public get calcs(): CalculationListItem[] | undefined {\r\n    if (!this.current?.id) {\r\n      return undefined;\r\n    }\r\n    if (!this._calcs) {\r\n      this._calcs = [];\r\n      this._pages = { currentIdx: 0, pages: [] };\r\n      this.payrollsApi.getCalcsOData(this.current.id, {}).then((result) => {\r\n        this._calcs = this.orderCalcs(this.current.input.calculations, result.items);\r\n        this.setPageItems();\r\n      });\r\n    }\r\n    return this._calcs;\r\n  }\r\n\r\n  private _pages: { currentIdx: number, pages: Array<{ current: number, total: number,  items: CalculationListItem[], calcs: Calculation[], originalCalcs: Calculation[], calcRange: string, totalCalcCount}>};\r\n\r\n  /** Returns current calc page. */\r\n  public get page(): { current: number, total: number, items: CalculationListItem[], calcs: Calculation[], originalCalcs: Calculation[], calcRange: string, totalCalcCount: number} | undefined {\r\n    if (this._pages) {\r\n      for(let i = 0; i < this._pages.pages.length; i++) {\r\n        if (i !== this._pages.currentIdx && this._pages.pages[i].calcs.length > 0) {\r\n          this._pages.pages[i].calcs = [];\r\n          this._pages.pages[i].originalCalcs = [];\r\n        }\r\n      }\r\n    }\r\n    return this._pages?.pages[this._pages.currentIdx] ?? {current: 1, total: 1, items: [], calcs: [], originalCalcs: [], calcRange: \"\", totalCalcCount: 0};\r\n  }\r\n\r\n  /** Set page items. */\r\n  public setPageItems() {\r\n    if (this._pages) {\r\n      this._pages.currentIdx = 0;\r\n      this._pages.pages.splice(0, this._pages.pages.length);\r\n      const pageSize = 10;\r\n      const totalCalcCount = this._calcs.length;\r\n      const pageTotal = Math.ceil(this._calcs.length / pageSize);\r\n      for (let i = 0; i < this._calcs.length; i += pageSize) {\r\n        const items = this._calcs.slice(i, i + pageSize);\r\n        const calcRange = (i + 1) + \" - \" + (i + items.length);\r\n        this._pages.pages.push({ current:  Math.ceil((i + 1) / pageSize), total: pageTotal, items, calcs: [], originalCalcs: [], calcRange, totalCalcCount});\r\n      }\r\n    }\r\n  }\r\n\r\n   /** Returns current calc page. */\r\n   public getPageCalc(item: CalculationListItem): Calculation | undefined {\r\n    if (this._pages) {\r\n      const currentPage = this.page;\r\n      currentPage.calcs ??= [];\r\n      currentPage.originalCalcs ??= [];\r\n      const calc = currentPage.calcs.find((x) => x.id == item.id);\r\n      if (calc) {\r\n        if (calc.rows) {\r\n          // ready\r\n          return calc;\r\n        }\r\n        else\r\n        {\r\n          // precalc\r\n          return undefined;\r\n        }\r\n      }\r\n      else\r\n      {\r\n        const preCalc = { id: item.id };\r\n        const preOriginalCalc = angular.copy(preCalc);\r\n        currentPage.calcs.push( preCalc );\r\n        currentPage.originalCalcs.push( preOriginalCalc);\r\n        this.calcsApi.getSingle(item.id).then((calc) => {\r\n          angular.copy(calc, preCalc);\r\n          angular.copy(calc, preOriginalCalc);\r\n        });\r\n      }\r\n    }\r\n    else {\r\n      return undefined;\r\n    }\r\n  }\r\n\r\n /**\r\n  * Saves the calculation and reloads the payroll.\r\n  */\r\n  public savePageCalcs(): Promise<PayrollDetails> {\r\n    const currentPage =  this.page;\r\n    this.loaders[\"pageCalcs\" + currentPage.current] = true;\r\n    // no precalcs, no readonly\r\n    const calcs = this.page.calcs.filter((x) => !!x.rows && x.isReadOnly !== true);\r\n    const changedCalcs = calcs.filter((x) => !angular.equals(x, currentPage.originalCalcs.find((c) => c.id === x.id)));\r\n    return this.payrollsApi.saveCalculations(this.current.id, changedCalcs).then((items) => {\r\n      for (const item of items) {\r\n        const listItem = this.calcs.find((c) => c.id === item.id);\r\n        if (listItem) {\r\n          angular.copy(item, listItem);\r\n        }\r\n      }\r\n      delete this.loaders[\"pageCalcs\" + currentPage.current];\r\n      // start reload calculations\r\n      currentPage.calcs = currentPage.calcs.filter((x) => !changedCalcs.find((c) => c.id === x.id));\r\n      currentPage.originalCalcs = currentPage.originalCalcs.filter((x) => !changedCalcs.find((c) => c.id === x.id));\r\n      // and payroll\r\n      return this.reload();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Checks if the current page calcs have changes.\r\n   * Returns the number of changed calcs.\r\n   */\r\n  public get numOfChangedPageCalcs(): number {\r\n    const currentPage =  this.page;\r\n    // no precalcs, no readonly\r\n    const calcs = this.page.calcs.filter((x) => !!x.rows && x.isReadOnly !== true);\r\n\r\n    return calcs.filter((x) => !angular.equals(x, currentPage.originalCalcs.find((c) => c.id === x.id))).length;\r\n  }\r\n\r\n  /** Gets calculation validity from the calc table entry */\r\n  public getCalcValidity(row: CalculationListItem): ApiListItemValidation {\r\n    return  this.current?.validations?.find((x) => x.id === row.id);\r\n  }\r\n\r\n  /**\r\n   * Advances to next page.\r\n   */\r\n  public goToPage(previous = false) {\r\n    if (!this._pages) {\r\n      return;\r\n    }\r\n\r\n    const saveIfChanged = () => {\r\n      if (this.numOfChangedPageCalcs > 0) {\r\n        return this.savePageCalcs();\r\n      }\r\n      else\r\n      {\r\n        return Promise.resolve(this.current);\r\n      }\r\n    };\r\n\r\n    return saveIfChanged().then(() => {\r\n      let idx = this._pages.currentIdx;\r\n      if (previous) {\r\n        idx -= 1;\r\n        this._pages.currentIdx = idx > -1 ?  idx : this._pages.pages.length - 1;\r\n      }\r\n      else {\r\n        idx += 1;\r\n        this._pages.currentIdx = idx < this._pages.pages.length ? idx : 0;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Opens a list of workers in to a dialog window.\r\n   * Creates a new calculation for the selected worker and current payroll.\r\n   */\r\n  public addEmployments() {\r\n    const workerList = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/WorkerList.html\",\r\n      workerList,\r\n      {\r\n        title: \"SALAXY.NG1.PayrollComponent.createNewCalcDialog\",\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && workerList.length > 0) {\r\n          const data: any = {};\r\n          data.listItemType = \"EmploymentListItem\";\r\n          const columns = undefined;\r\n          const paramsTemplate = undefined;\r\n          const action = (items, /*data*/) => {\r\n            const itemIds = items.map((x) => x.id);\r\n            return this.payrollsApi.addEmployments(this.current.id, itemIds).then((result) => {\r\n              const results = items.map(() => ({ message: \"\", result: [] }));\r\n              if (results.length > 0) {\r\n                results[0].result = result;\r\n              }\r\n              return results;\r\n            });\r\n          };\r\n          return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.createNewCalcLoading\"), workerList, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n            if (dialogResult.done) {\r\n              dialogResult.results.forEach((result) => {\r\n                for (const item of result.result) {\r\n                  const listItem = this.calcs.find((c) => c.id === item.id);\r\n                  if (listItem) {\r\n                    angular.copy(item, listItem);\r\n                  }\r\n                  else {\r\n                    this.calcs.push(item);\r\n                  }\r\n                }\r\n              });\r\n              this.setPageItems();\r\n            }\r\n            return this.reload();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Opens the list of calculations into a dialog window for selection and then adds them to payroll\r\n   * @param category Either \"paid\": Read-only, a copy is added ... or \"draft\": Editable, moved with status changed.\r\n   * @param isMerge If true, the operation merges the calculations to the current payroll.\r\n   * @param removeImportedRows If true, the merge operation removes all the imported rows from the calculation.\r\n   * @param applyEmploymentDefaultRows If true, the merge operation applies the employment default rows to the new calculations.\r\n   */\r\n  public addCalcs(category: \"paid\" | \"shared\" | \"draft\" = \"draft\", isMerge = false, removeImportedRows = false, applyEmploymentDefaultRows = false) {\r\n    const title = (category === \"paid\" ?  \"SALAXY.NG1.PayrollComponent.addExistingCalcCopy\" : category == \"shared\" ? \"SALAXY.NG1.PayrollComponent.addExistingCalcMoveShared\" :  \"SALAXY.NG1.PayrollComponent.addExistingCalcMove\");\r\n    this.uiHelpers.openSelectCalcs(category, title).then((result) => {\r\n      if (result.action === \"ok\" && result.item.length > 0) {\r\n\r\n        const calcs = result.item;\r\n        const data: any = {};\r\n        data.listItemType = \"CalculationListItem\";\r\n        const columns = undefined;\r\n        const paramsTemplate = undefined;\r\n        const action = (items, /*data*/) => {\r\n          const itemIds = items.map((x) => x.id);\r\n          return (!isMerge ? this.payrollsApi.addCalculations(this.current.id, itemIds):\r\n          this.payrollsApi.mergeCalculations(this.current.id, itemIds, removeImportedRows, applyEmploymentDefaultRows)  ).then((result) => {\r\n            const results = items.map(() => ({ message: \"\", result: [] }));\r\n            if (results.length > 0) {\r\n              results[0].result = result;\r\n            }\r\n            return results;\r\n          });\r\n        };\r\n        return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.addExistingCalcLoading\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n          if (dialogResult.done) {\r\n            dialogResult.results.forEach((result) => {\r\n              for (const item of result.result) {\r\n                const listItem = this.calcs.find((c) => c.id === item.id);\r\n                if (listItem) {\r\n                  angular.copy(item, listItem);\r\n                }\r\n                else {\r\n                  this.calcs.push(item);\r\n                }\r\n              }\r\n            });\r\n            this.setPageItems();\r\n          }\r\n          return this.reload();\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes the calculation\r\n   * @param unlink If true, will not delete the actual calculation, but instead unlinks it as a separate calculation outside this payroll.\r\n   */\r\n  public deleteCalc(unlink = false) {\r\n    const calcId = this.calcId;\r\n    if (unlink) {\r\n      this.uiHelpers.showConfirm(\"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.heading\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.intro\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.confirmButton\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.cancelButton\")\r\n        .then((result: boolean) => {\r\n          if (result) {\r\n            const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.payrollCalcs.unlinkCalcDialog.loading\");\r\n            this.payrollsApi.unlinkCalculation(this.current.id, calcId).then((savedPayroll) => {\r\n              this.setCurrentValue(savedPayroll, true);\r\n              if (this.current.input.calculations.indexOf(calcId) == -1) {\r\n                // remove list item\r\n                const listItem = this.calcs.find((c) => c.id === calcId);\r\n                if (listItem) {\r\n                  this.calcs.splice(this.calcs.indexOf(listItem), 1);\r\n                  this.setPageItems();\r\n                }\r\n                this.setCalc(undefined);\r\n              }\r\n              loader.dismiss();\r\n            });\r\n          }\r\n          else {\r\n            // cancel\r\n            return;\r\n          }\r\n        });\r\n    } else {\r\n      this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.heading\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.introNoChanges\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.confirmButton\",\r\n        \"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.cancelButton\")\r\n        .then((result: boolean) => {\r\n          if (result) {\r\n            const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.payrollCalcs.deleteCalcDialog.loading\");\r\n            this.payrollsApi.deleteCalculation(this.current.id, calcId)\r\n              .then((savedPayroll) => {\r\n                this.setCurrentValue(savedPayroll, true);\r\n                if (this.current.input.calculations.indexOf(calcId) == -1) {\r\n                  // remove list item\r\n                  const listItem = this.calcs.find((c) => c.id === calcId);\r\n                  if (listItem) {\r\n                    this.calcs.splice(this.calcs.indexOf(listItem), 1);\r\n                    this.setPageItems();\r\n                  }\r\n                  this.setCalc(undefined);\r\n                }\r\n                loader.dismiss();\r\n              });\r\n          }\r\n          else {\r\n            return;\r\n          }\r\n        });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens a list of payrolls for merging the payroll calculations to the current payroll.\r\n   * @param removeImportedRows If true, the operation removes all the imported rows from the calculation.\r\n   * @param applyEmploymentDefaultRows If true, the operation applies the employment default rows to the new calculations.\r\n   */\r\n  public mergePayroll(removeImportedRows = false, applyEmploymentDefaultRows = false): Promise<PayrollDetails> {\r\n    const payrollItems = [];\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/modals/payroll/PayrollDetailsList.html\", payrollItems, {\r\n      title: Translations.get(\"SALAXY.NG1.PayrollComponent.mergePayroll.title\"),\r\n      category: \"draft\",\r\n    }, \"lg\").then((result) => {\r\n\r\n      if (result.action != \"ok\" || payrollItems.length < 1) {\r\n        return this.current;\r\n      }\r\n\r\n      // get all calcs\r\n      const calcs = [];\r\n      let calcPromises = undefined;\r\n      for (const payrollItem of payrollItems) {\r\n        if (payrollItem.id == this.current.id) {\r\n          continue;\r\n        }\r\n        const calcPromise = this.payrollsApi.getSingle(payrollItem.id)\r\n          .then((payroll) => this.payrollsApi.getCalcsOData(payrollItem.id, null)\r\n          .then((result) => calcs.push(...this.orderCalcs(payroll.input.calculations, result.items))));\r\n        calcPromises = !calcPromises ? calcPromise : calcPromises.then(calcPromise);\r\n      }\r\n\r\n      return calcPromises.then(() => {\r\n        const data: any = {};\r\n        data.listItemType = \"CalculationListItem\";\r\n        const columns = undefined;\r\n        const paramsTemplate = undefined;\r\n        const action = (items, data) => {\r\n          const itemIds = items.map((x) => x.id);\r\n          if (removeImportedRows == true) {\r\n            const firstRound = data.dialogList.filter((x) => x.processed).length == itemIds.length;\r\n            if (!firstRound) {\r\n              removeImportedRows = false;\r\n            }\r\n          }\r\n          return this.payrollsApi.mergeCalculations(this.current.id, itemIds, removeImportedRows, applyEmploymentDefaultRows).then((result) => {\r\n            const results = items.map(() => ({ message: \"\", result: [] }));\r\n            if (results.length > 0) {\r\n              results[0].result = result;\r\n            }\r\n            return results;\r\n          });\r\n        };\r\n        return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.mergePayroll.batchProcessTitle\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n          if (dialogResult.done) {\r\n            dialogResult.results.forEach((result) => {\r\n              for (const item of result.result) {\r\n                const listItem = this.calcs.find((c) => c.id === item.id);\r\n                if (listItem) {\r\n                  angular.copy(item, listItem);\r\n                }\r\n                else {\r\n                  this.calcs.push(item);\r\n                }\r\n              }\r\n            });\r\n            this.setPageItems();\r\n          }\r\n          return this.reload();\r\n        });\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a confirm dialog if payroll has any calculations.\r\n   * Returns true if a user clicks OK -button. Otherwise (cancel or close) returns false.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public importEmploymentDataAll(): Promise<boolean> {\r\n    const payroll = this.current;\r\n    if (!payroll.info.calcCount || payroll.info.calcCount === 0) {\r\n      return this.uiHelpers.showAlert(\"SALAXY.NG1.PayrollComponent.importEmploymentDataAllAlertTitle\", \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllAlertDescr\").then(() => false);\r\n    } else {\r\n      return this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllConfirmTitle\",\r\n        \"SALAXY.NG1.PayrollComponent.importEmploymentDataAllConfirmDescr\",\r\n        \"SALAXY.UI_Terms.continue\",\r\n        \"SALAXY.UI_Terms.cancel\",\r\n      ).then((result: boolean) => {\r\n        if (result) {\r\n          const calcs = this.calcs.slice(0);\r\n          const data: any = {};\r\n          data.listItemType = \"CalculationListItem\";\r\n          const columns = undefined;\r\n          const paramsTemplate = undefined;\r\n          const action = (item /*, data */) => {\r\n            return this.calcsApi.getSingle(item.id).then((calc) => {\r\n              return this.calcsApi.updateFromEmployment(calc, true, true).then(() => {\r\n                return [{ message: \"\", result: [] }];\r\n              });\r\n            });\r\n          };\r\n          return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.importEmploymentDataAllLoading\"), calcs, action, paramsTemplate, data, columns, null, true, true).then(() => {\r\n            return this.reload().then(() => {\r\n              this._calcs = null;\r\n              return true;\r\n            });\r\n          });\r\n        } else {\r\n          return false;\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Show confirm dialog and export employment data from all calculations\r\n   * to their respective Employment relations.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public exportEmploymentDataAll(): Promise<boolean> {\r\n    const payroll = this.current;\r\n    if (!payroll.info.calcCount || payroll.info.calcCount === 0) {\r\n      return this.uiHelpers.showAlert(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllAlertTitle\", \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllAlertDescr\").then(() => false);\r\n    } else {\r\n      return this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllConfirmTitle\",\r\n        \"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllConfirmDescr\",\r\n        \"SALAXY.UI_Terms.continue\",\r\n        \"SALAXY.UI_Terms.cancel\",\r\n      ).then((result: boolean) => {\r\n        if (result) {\r\n          const calcs = this.calcs.slice(0);\r\n          const data: any = {};\r\n          data.listItemType = \"CalculationListItem\";\r\n          const columns = undefined;\r\n          const paramsTemplate = undefined;\r\n          const action = (item /*, data */) => {\r\n            return this.calcsApi.getSingle(item.id).then((calc) => {\r\n              return this.calcsApi.updateToEmployment(calc).then(() => {\r\n                return [{ message: \"\", result: [] }];\r\n              });\r\n            });\r\n          };\r\n          return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataAllLoading\"), calcs, action, paramsTemplate, data, columns, null, true, true).then(() => {\r\n            return true;\r\n          });\r\n        } else {\r\n          return false;\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Show confirm dialog and export employment data from calculation to Employment relation.\r\n   * If the calculation has unmodified changes, the calculation is saved.\r\n   * @returns True if the user confirmed the operation.\r\n   */\r\n  public exportEmploymentData(): Promise<boolean> {\r\n    return this.uiHelpers.showConfirm(\r\n      \"SALAXY.NG1.PayrollComponent.exportEmploymentDataTitle\",\r\n      \"SALAXY.NG1.PayrollComponent.exportEmploymentDataDescr\",\r\n      \"SALAXY.UI_Terms.continue\",\r\n      \"SALAXY.UI_Terms.cancel\",\r\n    ).then((ok) => {\r\n      if (ok) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayrollComponent.exportEmploymentDataLoading\");\r\n        return this.saveCalc(this.calc).then(() => {\r\n          return this.calcsApi.updateToEmployment(this.calc).then(() => {\r\n            loader.dismiss();\r\n            return true;\r\n          });\r\n        });\r\n      }\r\n      else {\r\n        return false;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Free reports */\r\n  public clearReports() {\r\n    this.reportCalcs = null;\r\n    this.reportCalcs = [];\r\n  }\r\n\r\n  /** Refreshses the reports for the payroll. */\r\n  public refreshReports(): Promise<Calculation[]> {\r\n    const payroll = this.current;\r\n    if (payroll.info.calcCount && payroll.info.calcCount > 0) {\r\n      const calcs = this.calcs.slice(0);\r\n      const data: any = {};\r\n      data.listItemType = \"CalculationListItem\";\r\n      const columns = undefined;\r\n      const paramsTemplate = undefined;\r\n      const action = (items /*, data */) => {\r\n        const itemIds = items.map((x) => x.id);\r\n        return this.calcsApi.getMulti(itemIds).then((result) => {\r\n          const results = items.map(() => ({ message: \"\", result: [] }));\r\n          if (results.length > 0) {\r\n            results[0].result = result;\r\n          }\r\n          return results;\r\n        });\r\n      };\r\n      return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.UI_Terms.wait\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n        if (dialogResult.done) {\r\n          this.reportCalcs.splice(0, this.reportCalcs.length);\r\n          dialogResult.results.forEach((result) => {\r\n            this.reportCalcs.push(...result.result);\r\n          });\r\n        }\r\n        return this.reportCalcs;\r\n      });\r\n    }\r\n    else {\r\n      this.reportCalcs.splice(0, this.reportCalcs.length);\r\n      return Promise.resolve(this.reportCalcs);\r\n    }\r\n  }\r\n\r\n  /** Disable function for the salary date picker. */\r\n  public isDisabledSalaryDate = (date): boolean => {\r\n    switch (this.current.input.salaryDateKind) {\r\n      case SalaryDateKind.InPast:\r\n        return false;\r\n      case SalaryDateKind.Default:\r\n      default:\r\n        return !SalaryDateLogic.isValidSalaryDate(date, null, null, true, this.current.input.paymentChannel);\r\n    }\r\n  };\r\n\r\n  /** Shows the paymentd dialog / the invoices UI. */\r\n  public showPaymentDialog() {\r\n    this.invoicesService.showPaymentDialog(this.current);\r\n  }\r\n\r\n  /**\r\n   * Cancels the payment or invoice processing for the current payroll.\r\n   */\r\n  public cancelInvoices(): Promise<PayrollDetails> {\r\n    const eprWarningMessage = this.invoicesService.getEprWarningForCancellation(this.current.info.salaryDate, this.current.info.status == PayrollStatus.PaymentSucceeded);\r\n    const eprText = eprWarningMessage ? \"\\n\" + eprWarningMessage : \"\";\r\n    return this.uiHelpers.showConfirm(Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogTitle\") + \"?\", Translations.get(\"SALAXY.NG1.CalcResultsComponent.cancelDialogDescr\") + `${eprText}`, \"SALAXY.NG1.CalcResultsComponent.cancelDialogYes\", \"SALAXY.NG1.CalcResultsComponent.cancelDialogNo\").then((ok) => {\r\n      if (ok) {\r\n        if (InvoicesLogic.isCfa(this.current.input.paymentChannel)) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          return this.payrollsApi.cancelInvoices(this.current.id, [], false).then(() => {\r\n            return this.reload().then(() => {\r\n              loading.dismiss();\r\n              this._calcs = null;\r\n              return this.current;\r\n            });\r\n          });\r\n        }\r\n        else\r\n        {\r\n          const calcs = angular.copy(this.calcs);\r\n          const data: any = {};\r\n          data.listItemType = \"CalculationListItem\";\r\n          const columns = undefined;\r\n          const paramsTemplate = undefined;\r\n          const action = (items, data) => {\r\n            const itemIds = items.map((x) => x.id);\r\n            const remainingAfterThis =  data.dialogList.filter((x) => !x.processed).length;\r\n            const excludePeriodic = remainingAfterThis == 0 ? false:  true;\r\n            return this.payrollsApi.cancelInvoices(this.current.id, itemIds, excludePeriodic).then(() => {\r\n              const results = items.map(() => ( {message: \"\", result: []}));\r\n              return results;\r\n            });\r\n          };\r\n          return this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.UI_Terms.wait\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then(() => {\r\n            return this.reload().then(() => {\r\n              this._calcs = null;\r\n              return this.current;\r\n            });\r\n          });\r\n        }\r\n      }\r\n      else {\r\n        return this.current;\r\n      }\r\n    });\r\n  }\r\n\r\n /**\r\n  * Gets the user-specific setting (service), stored in the local storage.\r\n  */\r\n  public get userSettings() {\r\n    return this.userSettingsService;\r\n  }\r\n\r\n\r\n  private _info = {\r\n    calcCount: {\r\n      actual: 0,\r\n      original: 0,\r\n      exception: false,\r\n    },\r\n    totalGrossSalary: {\r\n      actual: 0,\r\n      original: 0,\r\n      exception: false,\r\n    },\r\n    totalPayment: {\r\n      actual: 0,\r\n      original: 0,\r\n      exception: false,\r\n    },\r\n  };\r\n\r\n  /** Get calculated header info. */\r\n  public get info() {\r\n    const allCalcs = this.calcs ?? [];\r\n    const infoCalcs = allCalcs.filter((x) => {\r\n      switch(this.current?.info.status) {\r\n        case PayrollStatus.PaymentSucceeded:\r\n          return x.status === CalculationStatus.PaymentSucceeded;\r\n        case PayrollStatus.PaymentStarted:\r\n          return x.status === CalculationStatus.PaymentStarted || x.status === CalculationStatus.PaymentSucceeded;\r\n        default:\r\n          return true;\r\n      }\r\n    });\r\n\r\n    this._info.calcCount.original = this.current?.info.calcCount ?? 0;\r\n    this._info.calcCount.actual = infoCalcs.length;\r\n    this._info.calcCount.exception = this._info.calcCount.actual !== this._info.calcCount.original;\r\n\r\n    this._info.totalGrossSalary.original = Numeric.round(this.current?.info.totalGrossSalary ?? 0);\r\n    this._info.totalGrossSalary.actual = Numeric.round(Arrays.sum(infoCalcs, (x) => x.grossSalary ?? 0));\r\n    this._info.totalGrossSalary.exception = this._info.totalGrossSalary.actual !== this._info.totalGrossSalary.original;\r\n\r\n    this._info.totalPayment.original = Numeric.round(this.current?.info.totalPayment ?? 0);\r\n    this._info.totalPayment.actual = Numeric.round(Arrays.sum(infoCalcs, (x) => x.payment ?? 0));\r\n    this._info.totalPayment.exception = this._info.totalPayment.actual !== this._info.totalPayment.original;\r\n\r\n    return this._info;\r\n  }\r\n\r\n  /** Returns exception style. */\r\n  public getExceptionStyle(hasException: boolean) {\r\n    if (hasException) {\r\n     return { \"text-decoration\": \"line-through\" };\r\n    }\r\n    return {};\r\n  }\r\n\r\n  /** Returns true, if a warning should be indicated in a row. */\r\n  public rowStatusWarning(row: CalculationListItem): boolean {\r\n    switch(this.current?.info.status) {\r\n      case PayrollStatus.PaymentSucceeded:\r\n        return !(row.status === CalculationStatus.PaymentSucceeded);\r\n      case PayrollStatus.PaymentStarted:\r\n        return !(row.status === CalculationStatus.PaymentStarted || row.status === CalculationStatus.PaymentSucceeded);\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  /** Copy current calc */\r\n  public copyCalc() {\r\n    const copy = angular.copy(this.calc);\r\n    copy.id = null;\r\n    copy.info.payrollId = null;\r\n    copy.workflow.status = CalculationStatus.Draft;\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return this.calcsApi.save(copy).then(() => {\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Returns true if the curren payroll has cfa payment channel. */\r\n  public get isCfa(): boolean {\r\n    return InvoicesLogic.isCfa(this.current?.input?.paymentChannel);\r\n  }\r\n\r\n  /** Pay current calc */\r\n  public payCalc() {\r\n    if (!this.isCfa) {\r\n      this.invoicesService.showPaymentDialog(this.calc);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends a payroll with messaging system and sets\r\n   * @param $msg The MessageThreadCrudController that is used for creating the message thread.\r\n   */\r\n  public sendPayrollMessage($msg: MessageThreadCrudController): Promise<void> {\r\n    if (!$msg.current) {\r\n      $msg.model = \"new\";\r\n    }\r\n    const model = $msg.current;\r\n    model.otherParty = this.sessionService.session.settings.partner.accountId;\r\n    model.status = MessageThreadStatus.Active;\r\n    model.title = model.title || \"Palkkalista \" + this.current.input.title;\r\n    model.ownerWorkflow = {\r\n      salaryDate: this.current.info.salaryDate,\r\n    };\r\n    model.messages.push({\r\n      contentId: this.currentId,\r\n      fromParty: this.sessionService.isInRole(\"pro\") ? MessageFrom.OtherParty : MessageFrom.Owner,\r\n      type: ThreadedMessageType.Payroll\r\n    });\r\n    return $msg.save().then((msg) => {\r\n      if (this.current.info.status != PayrollStatus.WaitingApproval) {\r\n        this.current.info.messageThreadId = msg.id;\r\n        this.current.info.status = PayrollStatus.WaitingApproval;\r\n        return this.save().then(() => {\r\n          return;\r\n        });\r\n      } else {\r\n        this.current.info.messageThreadId = msg.id; // This is done by messageThread logic on server => ne need to save.\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the message title for the action.\r\n   */\r\n  public getMessageTitle(action: string) {\r\n    return this.messageActions.find((x) => x.value == action).title + \": \" + this.current.input.title;\r\n  }\r\n\r\n  /**\r\n   * Available actions for the message.\r\n   * TODO: This could be replaced by enums or it may come from Service model.\r\n   */\r\n  public messageActions: InputEnumOption[] = [\r\n    {\r\n      text: \"Maksa\",\r\n      value: \"pay\",\r\n      title: \"Maksa palkkalista\",\r\n    },/* {\r\n      text: \"Tarkista (hyväksy/hylkää)\",\r\n      value: \"approve\",\r\n      title: \"Tarkista palkkalista\",\r\n    },*/\r\n    {\r\n      text: \"Tiedoksi\",\r\n      value: \"info\",\r\n      title: \"Tiedoksi palkkalista\",\r\n    }, {\r\n      text: \"Vastaa kysymykseen\",\r\n      value: \"question\",\r\n      title: \"Kysymyksiä palkkalistasta\",\r\n    }\r\n  ];\r\n\r\n  /**\r\n   * Deletes a linked message: Both the message thread and msg id in this payroll.\r\n   * @param $msg The MessageThreadCrudController that contains the current message.\r\n   */\r\n  public deleteMessage($msg: MessageThreadCrudController) {\r\n    this.uiHelpers.showConfirm(\"Haluatko poistaa viestiketjun?\", \"Haluatko varmasti poistaa viestiketjun?\")\r\n      .then((result) => {\r\n        if (result) {\r\n          if ($msg.current) {\r\n            $msg.deleteNoConfirm($msg.current).then(() => {\r\n              this.current.info.messageThreadId = null;\r\n              this.save();\r\n            });\r\n          } else {\r\n            this.current.info.messageThreadId = null;\r\n            this.save();\r\n          }\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Show add new taxcard dialog */\r\n  public async showAddNewTaxcard($event: angular.IAngularEvent,item: CalculationListItem) {\r\n    $event.stopPropagation();\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n\r\n    const calc = this.getPageCalc(item) ?? await this.calcsApi.getSingle(item.id);\r\n\r\n    if (!calc || calc.isReadOnly) {\r\n      loading.dismiss();\r\n      return;\r\n    }\r\n    const empl = await this.employmentsApi.getSingle(calc.worker.employmentId);\r\n    if (!empl) {\r\n      loading.dismiss();\r\n      return;\r\n    }\r\n\r\n    if(empl.info.taxcard==EmploymentRelationTaxcard.Undefined || empl.info.taxcard==EmploymentRelationTaxcard.Auto){\r\n      const taxcard = await this.taxcardsApi.setAuto(calc.worker.paymentData.socialSecurityNumberValid);\r\n      if (taxcard) {\r\n        await this.saveCalc(calc);\r\n        loading.dismiss();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const result = await this.uiCrudHelpers.createNewTaxcard(calc.worker.paymentData.socialSecurityNumberValid);\r\n    if (result.action === \"ok\") {\r\n      await this.saveCalc(calc);\r\n      loading.dismiss();\r\n      return;\r\n    }\r\n\r\n    loading.dismiss();\r\n  }\r\n\r\n  private getHeaderChangeInfo(): HeaderChangeInfo {\r\n    return {\r\n      isPaymentChannelChanged: this.current.input.paymentChannel !== this.original.input.paymentChannel,\r\n      isPeriodChanged: (this.current.input.period.daysCount !== this.original.input.period.daysCount ||\r\n        this.current.input.period.start !== this.original.input.period.start ||\r\n        this.current.input.period.end !== this.original.input.period.end),\r\n      isSalaryDateChanged: this.current.input.salaryDate !== this.original.input.salaryDate || this.current.input.salaryDateKind !== this.original.input.salaryDateKind,\r\n    };\r\n  }\r\n\r\n  private orderCalcs(ids: string[], items: CalculationListItem[]): CalculationListItem[] {\r\n    if (!items) {\r\n      return items;\r\n    }\r\n    items.sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));\r\n    return items;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Avatar,\r\n  Calculation,\r\n  InvoicesLogic,\r\n  PaymentChannel,\r\n  PayrollDetails,\r\n  Translations,\r\n} from \"@salaxy/core\";\r\n\r\nimport { InvoicesService } from \"../../services\";\r\n\r\n/**\r\n * Contains functionality for executing payments for payrolls or calculations.\r\n */\r\nexport class PaymentController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"InvoicesService\"];\r\n\r\n  /**\r\n   * The current business item that is being paid: Either Calculation or PayrollDetails.\r\n   * Currently only supports direct reference. May later support 'url' etc. like CRUD controllers.\r\n   */\r\n  public model: Calculation | PayrollDetails;\r\n\r\n  /** Button text set from the element */\r\n  public label: string;\r\n\r\n  /** Mode is either \"pay-button\" (default), \"channel-select\" \"button-and-channel\" or \"button-and-channel-horizontal\" */\r\n  public mode: \"pay-button\" | \"channel-select\" | \"button-and-channel\" | \"button-and-channel-horizontal\";\r\n\r\n /**\r\n  * Function that is called when the payment channel has been chagned\r\n  * Function has the following locals:\r\n  * paymentChannel: the selected payment channel.\r\n  * businessObject: the current business object which has been changed.\r\n  */\r\n  public onPaymentChannelChange: (params: {\r\n    /** Selected payment channel */\r\n    paymentChannel: PaymentChannel,\r\n    /** The current business object which has been changed.  */\r\n    businessObject: Calculation | PayrollDetails,\r\n  }) => void;\r\n\r\n  constructor(private invoicesService: InvoicesService) {\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    // Init here\r\n  }\r\n\r\n  /**\r\n   * Text for the payment button\r\n   * This is typically customized in custom payment scenarios.\r\n   */\r\n  public getPaymentButtonText(): string {\r\n    return this.label ? Translations.get(this.label) : Translations.get(\"SALAXY.UI_Terms.pay\");\r\n  }\r\n\r\n  /**\r\n   * Shows the payment process first page in a dialog (the invoice create process).\r\n   */\r\n  public goToInvoices() {\r\n    this.invoicesService.showPaymentDialog(this.businessObject);\r\n  }\r\n\r\n  /** Returns current business object */\r\n  public get businessObject(): Calculation | PayrollDetails {\r\n    return this.model;\r\n  }\r\n\r\n  /**\r\n   * Returns true if there is a selected channel for the business object.\r\n   */\r\n  public get isChannelDefined() {\r\n    return this.getCurrentChannel() != PaymentChannel.Undefined;\r\n  }\r\n\r\n  /** Gets the current channel avatar. */\r\n  public get currentChannel(): Avatar {\r\n    return InvoicesLogic.getChannelAvatar(this.getCurrentChannel());\r\n  }\r\n\r\n  /** Sets the payment channel and starts recalculation. */\r\n  public setPaymentChannel(newChannel: PaymentChannel) {\r\n    if (InvoicesLogic.isCalculation(this.businessObject)) {\r\n      this.businessObject.info.paymentChannel = newChannel;\r\n    } else if (InvoicesLogic.isPayroll(this.businessObject)) {\r\n      this.businessObject.input.paymentChannel = newChannel;\r\n    } else {\r\n      throw new Error(\"Unknwon business object type.\");\r\n    }\r\n    this.onPaymentChannelChange({ paymentChannel: newChannel, businessObject: this.businessObject });\r\n  }\r\n\r\n  /** Gets the enabled channels. */\r\n  public get allChannels(): Avatar[] {\r\n    return this.invoicesService.channels;\r\n  }\r\n\r\n  /**\r\n   * Determines whether the payment channel selection should be shown.\r\n   */\r\n  public showPaymentChannelSelection(): boolean {\r\n    return this.allChannels.length > 1 || (this.allChannels.length == 1 && this.currentChannel.id != this.allChannels[0].id);\r\n  }\r\n\r\n  private getCurrentChannel(): PaymentChannel {\r\n    let channel = null;\r\n    if (InvoicesLogic.isCalculation(this.businessObject)) {\r\n      channel = this.businessObject.info.paymentChannel;\r\n    } else if (InvoicesLogic.isPayroll(this.businessObject)) {\r\n      channel = this.businessObject.input.paymentChannel;\r\n    }\r\n    return channel ?? PaymentChannel.Undefined;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, AccountingData, Calculations, DateRange, Calculation, CalculationCorrection, CalculationResultLogic, Reports, VersionInfo, ApiListItem, ApiValidationErrorType, Translations, InputEnumOption, Language, kevaEmploymentRegCodes} from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, InvoicesService, ReportsService, SessionService, UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport { CalculationCrudController } from \"./CalculationCrudController\";\r\n\r\n/**\r\n * CalculationEditorController used to handle EPR actions\r\n * This controller extends ApiCrudObjectController (via CalculationCrudController).\r\n */\r\nexport class CalculationEditorController extends CalculationCrudController {\r\n\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = {\r\n\r\n  };\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"UiHelpers\", \"UiCrudHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"ReportsService\", \"InvoicesService\", \"Reports\", \"AjaxNg1\"];\r\n\r\n\r\n   /** Flags to indicate if the request is in progress */\r\n   public loaders:any = {};\r\n\r\n   /** Indicates if the details sidebar is open */\r\n   public isRightSidebarOpen: boolean;\r\n\r\n  /** Data reader for the accounting diffa data. */\r\n  public accountingDiffDataReader = {\r\n    /** Function to read data into given array */\r\n    read: (target: string, ruleSet: string, arr: AccountingData[]): Promise<void> => {\r\n      if (this.accountingDiffData) {\r\n        arr.push(this.accountingDiffData);\r\n        return Promise.resolve();\r\n      } else {\r\n        return Promise.resolve();\r\n      }\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: null,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.accountingDiffData,\r\n    /* Indicates if row is expandable */\r\n    showExpand: true,\r\n    /* Indicates if rows exists*/\r\n    hasRows: () => !this.accountingDiffData?.ledgerAccounts\r\n  };\r\n\r\n  /** Status for diff data . */\r\n  private accountingDiffDataStatus: \"initial\" | \"loading\" | string = \"initial\";\r\n\r\n  private _accountingDiffData: AccountingData;\r\n\r\n  private _diffCalc: Calculation = {};\r\n\r\n  private latestCurrent: Calculation;\r\n\r\n  private latestBase: Calculation;\r\n\r\n  private pendingAccountingDiffData = false;\r\n\r\n  private _documentFlow: { item: ApiListItem, children: any[]};\r\n\r\n  private _state: string;\r\n\r\n  private baseCalc: Calculation;\r\n  private versionId: string;\r\n\r\n  constructor(\r\n    calcApi: Calculations,\r\n    uiHelpers: UiHelpers,\r\n    protected uiCrudHelpers: UiCrudHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    reportsService: ReportsService,\r\n    protected invoicesService: InvoicesService,\r\n    private reportsApi: Reports,\r\n    private ajax: Ajax,\r\n  ) {\r\n    // Dependency injection\r\n    super(calcApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n    calcApi.getSingle = (id: string) =>  {\r\n      return this.ajax.getJSON(`/v03-rc/api/calculations/correction/${id}`).then((data: CalculationCorrection) => {\r\n        return data.calculation;\r\n      });\r\n    };\r\n  }\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Calculation total result diff between original and current calculation. */\r\n  public get diffCalc() {\r\n    this.onCalculationChange();\r\n    return this._diffCalc;\r\n  }\r\n\r\n  /** Accounting data diff between original and current calculation. */\r\n  public get accountingDiffData() {\r\n    this.onCalculationChange();\r\n    return this._accountingDiffData;\r\n  }\r\n\r\n   /** Document flow for the current calculation */\r\n   public get documentFlow() {\r\n    if (!this._documentFlow && this.current?.id) {\r\n      this._documentFlow = { item: null, children: null};\r\n      this.ajax.getJSON(`/v03-rc/api/calculations/correction/${this.current.id}/document-flow`).then((data) => {\r\n        angular.copy(data, this._documentFlow);\r\n      });\r\n    }\r\n    return this._documentFlow;\r\n  }\r\n\r\n  /**\r\n   * Returns validation for calculation\r\n   */\r\n  public get validation() {\r\n    // Currently apiValidation isValid is false even if all the items are warnings\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!this.current.result.validation.isValid) {\r\n      (this.current.result.validation as any).isValid = this.current.result.validation.errors.every(x => x.type === ApiValidationErrorType.Warning);\r\n    }\r\n\r\n    return this.current.result.validation;\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process depending on the bindingMode:\r\n   */\r\n   public reload(): Promise<Calculation> {\r\n    return super.reload().then((calculation) => {\r\n      calculation.isReadOnly = false;\r\n      return calculation;\r\n    });\r\n  }\r\n  /** Load accounting data and calculate diff. */\r\n  public loadAccountingDiffData(targetId: string = null) {\r\n    if (targetId == null) {\r\n      if (this.accountingDiffDataStatus === \"initial\") {\r\n        targetId = \"default\";\r\n      }\r\n      else if (this.accountingDiffDataStatus === \"loading\") {\r\n        return;\r\n      }\r\n      else {\r\n        targetId = this.accountingDiffDataStatus;\r\n      }\r\n    }\r\n    if (this.accountingDiffDataStatus !== \"loading\") {\r\n      this.pendingAccountingDiffData = false;\r\n      // Start downloading for the new id\r\n      this.accountingDiffDataStatus = \"loading\";\r\n\r\n      const promises = [this.base,this.current].map((x) =>  this.reportsApi.getAccountingDataForCalculations([x], targetId, null));\r\n      Promise.all(promises).then( (accountingReports) => {\r\n        if (accountingReports && accountingReports.length == 2) {\r\n          this._accountingDiffData = this.diffAccountingData(accountingReports[0], accountingReports[1]);\r\n        }\r\n        this.accountingDiffDataStatus = targetId;\r\n\r\n        if(this.pendingAccountingDiffData){\r\n          this.loadAccountingDiffData();\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n\r\n  /**\r\n   * Change base calculations\r\n   */\r\n   public changeBase() {\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/calc/SelectVersion.html\",\r\n      null,\r\n      {\r\n        versions: this.versions,\r\n        versionId: this.versionId,\r\n      }).then((result) => {\r\n        if (result && result != \"cancel\") {\r\n          const version = result as VersionInfo;\r\n          this.api.getVersion(this.currentId, version?.versionId).then((data) => {\r\n            data.isReadOnly = false;\r\n            this.baseCalc = data;\r\n            this.versionId = version?.versionId;\r\n            this.onCalculationChange();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n\r\n  // TODO: refresh -method should be called after every field update in the ui. Including rows.\r\n\r\n  /**\r\n   * Refreshes the calculation using the server side logic.\r\n   * @param refresh Option for refresh.\r\n   */\r\n   public refresh(refresh = \"default\"){\r\n\r\n    let confirmationDescription = \"\";\r\n\r\n    if(refresh == \"default\"){\r\n      this.loaders[refresh] = true;\r\n        const payload = {\r\n          id : this.current.id,\r\n          calculation: this.current,\r\n          state: this._state,\r\n        };\r\n        this.ajax.postJSON(`/v03-rc/api/calculations/correction/refresh/${refresh}`, payload).then((data) => {\r\n          this._state = data.state;\r\n          data.calculation.isReadOnly = false;\r\n          angular.copy(data.calculation, this.current);\r\n          this.loaders[refresh] = false;\r\n        });\r\n    } else {\r\n      switch (refresh) {\r\n        case \"worker\":\r\n          confirmationDescription = \"Haluatko päivittää työntekijän tiedot laskelmalle?\";\r\n          break;\r\n        case \"employer\":\r\n          confirmationDescription = \"Haluatko päivittää työnantajan tiedot laskelmalle?\";\r\n          break;\r\n        case \"employment\":\r\n          confirmationDescription = \"Haluatko päivittää työsuhteen tiedot laskelmalle?\";\r\n          break;\r\n        case \"taxcard\":\r\n          confirmationDescription = \"Haluatko päivittää verokortin tiedot laskelmalle?\";\r\n          break;\r\n        case \"insurances\":\r\n          confirmationDescription = \"Haluatko päivittää vero-, eläke- ja vakuutustiedot laskelmalle?\";\r\n          break;\r\n        case \"cfa\":\r\n          confirmationDescription = \"Haluatko päivittää asiakasvaraerät laskelmalle?\";\r\n          break;\r\n        default:\r\n          confirmationDescription = \"\";\r\n      }\r\n      this.uiHelpers.showConfirm(\"Haluatko jatkaa?\", confirmationDescription, \"Päivitä\", \"Peruuta\").then((result) =>\r\n    {\r\n      if (result) {\r\n        this.loaders[refresh] = true;\r\n        const payload = {\r\n          id : this.current.id,\r\n          calculation: this.current,\r\n          state: this._state,\r\n        };\r\n        this.ajax.postJSON(`/v03-rc/api/calculations/correction/refresh/${refresh}`, payload).then((data) => {\r\n          this._state = data.state;\r\n          data.calculation.isReadOnly = false;\r\n          angular.copy(data.calculation, this.current);\r\n          this.loaders[refresh] = false;\r\n        });\r\n        }\r\n        else\r\n        {\r\n          return;\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Saves the edited readonly calculation.\r\n   */\r\n   public saveEdited(){\r\n    const payload = {\r\n      id : this.current.id,\r\n      calculation: this.current,\r\n      state: this._state,\r\n      snapshot: {\r\n        categories: []\r\n      }\r\n    };\r\n    this.ajax.getJSON(\"/v03-rc/api/calculations/correction/snapshot/categories\").then((categories) =>\r\n    {\r\n      this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/EditorConfirm.html\", { categories : [\"\"]}, { categories}).then((result) =>\r\n      {\r\n        if (result.action == EditDialogKnownActions.Ok) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n            payload.snapshot = result.item;\r\n            this.ajax.postJSON(`/v03-rc/api/calculations/correction`, payload).then((data) =>\r\n            {\r\n              loading.dismiss();\r\n              this._state = data.state;\r\n              data.calculation.isReadOnly = false;\r\n              angular.copy(data.calculation, this.current);\r\n            });\r\n          }\r\n          else\r\n          {\r\n            return;\r\n          }\r\n        });\r\n    });\r\n  }\r\n\r\n  private _dateRange: DateRange;\r\n\r\n  /** Getter and setter for Calculation daterange in compatible format for new DateRange component. */\r\n  public get dateRange(): DateRange {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!this._dateRange) {\r\n      this._dateRange = {\r\n        start: this.current.info.workStartDate,\r\n        end: this.current.info.workEndDate,\r\n        daysCount: this.current.framework.numberOfDays,\r\n      };\r\n    }\r\n    return this._dateRange;\r\n  }\r\n  public set dateRange(value: DateRange) {\r\n    this._dateRange = value;\r\n  }\r\n\r\n  /**\r\n   * Called when the date range changes.\r\n   */\r\n  public dateRangeChange() {\r\n    if (!this.dateRange || !this.current) {\r\n      return;\r\n    }\r\n    this.current.info.workStartDate = this.dateRange.start;\r\n    this.current.info.workEndDate = this.dateRange.end;\r\n    this.current.framework.numberOfDays = this.dateRange.daysCount;\r\n  }\r\n\r\n  private get base() {\r\n    if (!this.baseCalc && this.versions.length > 0) {\r\n      this.versionId = this.versions[this.versions.length - 1].versionId;\r\n      this.baseCalc = angular.copy(this.original);\r\n    }\r\n    return this.baseCalc ?? this.original;\r\n  }\r\n\r\n  /**\r\n   * Returns valid employment reg codes for the selected pensions company.\r\n   * @returns Options for the employment reg codes.\r\n   */\r\n  public getEmploymentRegCodeOptions(): Array<InputEnumOption> {\r\n    return this.uiHelpers.cache(this, \"employmentRegCodes\",\r\n    () => kevaEmploymentRegCodes.filter((x) => x.pensionCompany === this.current.result.responsibilities.pensionCompany).map((regCode) =>\r\n      ({ value: regCode.code, text: Translations.getLanguage() === Language.Sv ? regCode.labelSv : regCode.labelFi })),\r\n    () => this.current.result.responsibilities.pensionCompany);\r\n  }\r\n\r\n  private diffAccountingData(originalAccountingData: AccountingData, modifiedAccountingData: AccountingData): AccountingData {\r\n    // Leave only top level.\r\n    originalAccountingData.ledgerAccounts.forEach((x) => x.entries = []);\r\n    originalAccountingData.summary = {};\r\n    modifiedAccountingData.ledgerAccounts.forEach((x) => x.entries = []);\r\n    modifiedAccountingData.summary = {};\r\n    const result = modifiedAccountingData;\r\n\r\n    originalAccountingData.ledgerAccounts.forEach( (orig) => {\r\n      const modified =  result.ledgerAccounts.find((x) => x.accountNumber === orig.accountNumber && x.accountGrouping == orig.accountGrouping );\r\n      if (modified) {\r\n        (modified as any).saldo = modified.saldo - orig.saldo;\r\n      } else {\r\n        const removedAccount = angular.copy(orig);\r\n        (removedAccount as any).saldo = 0.0 - orig.saldo;\r\n        result.ledgerAccounts.push(removedAccount);\r\n      }\r\n    });\r\n    result.ledgerAccounts.forEach((x) => x.entries =\r\n    [\r\n      {\r\n        id: null,\r\n        entryDate: null,\r\n        description: \"Ero\",\r\n        isDebit: x.saldo >= 0,\r\n        amount: x.saldo >= 0 ? x.saldo : -1.0 * x.saldo,\r\n        vatPercent: null,\r\n        accountNumber: x.accountNumber,\r\n        accountName: x.accountName,\r\n        accountGrouping: x.accountGrouping,\r\n        dimension: {},\r\n      }\r\n    ]);\r\n    return result;\r\n  }\r\n\r\n  private onCalculationChange(){\r\n    if (this.base && this.current && ( !angular.equals(this.current, this.latestCurrent) || !angular.equals(this.base, this.latestBase))) {\r\n      this.latestCurrent = angular.copy(this.current);\r\n      this.latestBase = angular.copy(this.base);\r\n      const diff = angular.copy(this.base);\r\n      diff.result = CalculationResultLogic.diff(this.base.result, this.current.result);\r\n      angular.copy(diff, this._diffCalc);\r\n      this.pendingAccountingDiffData = true;\r\n      this.loadAccountingDiffData();\r\n    }\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Arrays, CostAccountingDimensionDefinition, CostAccountingDimension, CostAccountingDimensionScope, Translations } from \"@salaxy/core\";\r\n\r\nimport { SessionService} from \"../../services\";\r\n\r\n/**\r\n * Handles the user interaction for entering cost accounting data.\r\n */\r\nexport class CostAccountingController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** Scope for the cost accounting: calculation or row. */\r\n  public scope: CostAccountingDimensionScope;\r\n\r\n  /** Dimension values to edit.*/\r\n  public current: CostAccountingDimension[];\r\n\r\n  /** Possible upper level (e.g. calculation) dimensions that are inherited */\r\n  private _inherited: CostAccountingDimension[];\r\n\r\n  /** Bindable read-only */\r\n  public readOnly?: boolean;\r\n\r\n  /** CostAccountingDimensionDefinition including label, type and options */\r\n  public dimensions: CostAccountingDimensionDefinition[];\r\n\r\n  /**\r\n   * Style of inputs.\r\n   * If null or empty, displays normal input.\r\n   * - \"openeClose\" shows readOnly-like input with toggle button to open the field for editing.\r\n   */\r\n  public inputMode: \"\" | \"openClose\";\r\n\r\n  private _definitions:  CostAccountingDimensionDefinition[] = [];\r\n  private _options: { [key: string] : Array<{\r\n    /** Option value. */\r\n    value: any,\r\n    /** Option text.  */\r\n    text: string,\r\n    /** Option description. */\r\n    title?: string,\r\n  }> } = {};\r\n\r\n  private _values:  { [key: string] : Array<CostAccountingDimension> } = {};\r\n\r\n  private _inheritedValues:  { [key: string] : Array<CostAccountingDimension> } = {};\r\n  private _obsoleteValues: Array<CostAccountingDimension> = [];\r\n  private _newDimensions: CostAccountingDimension[] = [];\r\n\r\n  /**\r\n   * Creates a new CalcCostAccountingController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    protected  sessionService: SessionService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n   // empty\r\n  }\r\n\r\n  /** Copy of inherited dimensions */\r\n  public get inherited(): CostAccountingDimension[] {\r\n    return this._inherited;\r\n  }\r\n\r\n  /** Copy of inherited dimensions */\r\n  public set inherited(value: CostAccountingDimension[])  {\r\n    this._inherited = angular.copy(value);\r\n  }\r\n\r\n  /** Returns applicable dimensions*/\r\n  public get definitions(): CostAccountingDimensionDefinition[] {\r\n    const d = (this.dimensions ?? this.sessionService.session?.settings?.costAccounting?.dimensions ?? [])\r\n    .filter( (x) =>\r\n      // no hidden scope\r\n      x.scope !== CostAccountingDimensionScope.Hidden &&\r\n      (\r\n        // show if scope definition for dimension not given\r\n        ( !x.scope || x.scope === CostAccountingDimensionScope.None) ||\r\n        // or if scope definition for use given\r\n        (!this.scope || this.scope === CostAccountingDimensionScope.None) ||\r\n        // or this scope\r\n        (this.scope === x.scope)\r\n      )\r\n    );\r\n    this.modifyOptions(d, this._definitions);\r\n    return this._definitions;\r\n  }\r\n\r\n  /**\r\n   * Returns true, if the dimension exists.\r\n   * @param id Id of the dimension.\r\n   * @returns True, if the dimension with given id exists.\r\n   */\r\n  public getDefinition(id: string) {\r\n    return this.definitions.find( (x) => x.id == id);\r\n  }\r\n\r\n   /**\r\n    * Returns total percentage for the dimension\r\n    * @param id Name of the dimension.\r\n    */\r\n  public getSum(id: string ): number {\r\n      return Arrays.sum((this.current ?? []).filter((x) => x.id == id), (x: any) => x.percent ?? 0);\r\n  }\r\n\r\n   /**\r\n    * Returns available options.\r\n    * @param id Id of the dimension.\r\n    */\r\n  public getOptions(id: string) {\r\n    if (!this._options[id]) {\r\n      this._options[id] = [];\r\n    }\r\n\r\n    let newOptions = [];\r\n    const dimensionForOptions = this.definitions.find((x) => x.id === id);\r\n    if (dimensionForOptions) {\r\n      newOptions = dimensionForOptions.options.filter((x) =>\r\n        x.scope !== CostAccountingDimensionScope.Hidden &&\r\n        (\r\n          // show if scope definition for dimension not given\r\n          ( !x.scope || x.scope === CostAccountingDimensionScope.None) ||\r\n          // or if scope definition for use given\r\n          (!this.scope || this.scope === CostAccountingDimensionScope.None) ||\r\n          // or this scope\r\n          (this.scope === x.scope)\r\n        )\r\n      )\r\n      .map( (x) => ({ value: x.value, text: x.text }));\r\n      newOptions.unshift({value: \"\", text: Translations.get(\"SALAXY.UI_Terms.notChosen\") });\r\n    }\r\n\r\n    this.modifyOptions(newOptions, this._options[id]);\r\n    return this._options[id];\r\n  }\r\n\r\n  /**\r\n   * Returns true if options exists for the dimension.\r\n   * @param id Id of the dimension.\r\n   * @param value Value of the dimension.\r\n   * @returns True, if an option exists for the value.\r\n   */\r\n  public hasOptions(id: string, value: string): boolean {\r\n    const opts = this.getOptions(id);\r\n    if (!value) {\r\n      return opts.filter(x => x.value).length > 0;\r\n    }\r\n    return !!opts.find((x) => x.value == value);\r\n  }\r\n\r\n   /**\r\n    * Returns single value.\r\n    * @param id Id of the dimension.\r\n    */\r\n   public getSingleValue(id: string) {\r\n    let singleValue = this.current?.find((x) => x.id === id) ?? this._newDimensions.find((x) => x.id === id);\r\n    if (!singleValue && !this.readOnly) {\r\n      singleValue = { id };\r\n      this._newDimensions.push(singleValue);\r\n    }\r\n    return singleValue;\r\n  }\r\n\r\n  /**\r\n   * Sets single value.\r\n   * @param id Id of the dimension.\r\n   * @param value Value of the dimension.\r\n   */\r\n    public setSingleValue(id: string, value: string) {\r\n      const singleValue = this.current?.find((x) => x.id === id);\r\n      if (singleValue) {\r\n        singleValue.value = value;\r\n      }\r\n      else {\r\n        this.current.push({ id, value });\r\n      }\r\n    }\r\n\r\n  /**\r\n   * Returns current values.\r\n   * @param id Id of the dimension.\r\n   */\r\n  public getValues(id: string) {\r\n    if (!this._values[id]) {\r\n      this._values[id] = [];\r\n    }\r\n\r\n    const values = (this.current ?? []).filter((x) => x.id === id);\r\n    this.modifyOptions(values, this._values[id]);\r\n\r\n    return this._values[id];\r\n  }\r\n\r\n  /**\r\n   * Sets values.\r\n   * @param values Values of the dimension.\r\n   */\r\n  public setValues(values: CostAccountingDimension[]) {\r\n    this.current.push( ... angular.copy(values));\r\n  }\r\n\r\n  /**\r\n   * Deletes value from the dimensions\r\n   * @param value Value to delete\r\n   */\r\n  public deleteValue(value: CostAccountingDimension) {\r\n    const index = this.current.indexOf(value);\r\n    if (index >= 0) {\r\n      this.current.splice(index,1);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns true if the dimension values are inherited.\r\n   * @param id Id of the dimension.\r\n   */\r\n  public isInherited(id: string) {\r\n    if ( !this.current?.some((x) => x.id === id && !!x.value)) {\r\n      return !!this.cleanDimensions(this.inherited)?.some((x) => x.id === id);\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Returns inherited single value.\r\n   * @param id Id of the dimension.\r\n   */\r\n  public getInheritedSingleValue(id: string) {\r\n    const singleValue = (this.cleanDimensions(this.inherited) ?? []).find((x) => x.id === id);\r\n    return singleValue;\r\n  }\r\n\r\n  /**\r\n   * Returns inherited values.\r\n   * @param id Id of the dimension.\r\n   */\r\n   public getInheritedValues(id: string) {\r\n\r\n    if (!this._inheritedValues[id]) {\r\n      this._inheritedValues[id] = [];\r\n    }\r\n\r\n    const values = (this.cleanDimensions(this.inherited) ?? []).filter((x) => x.id === id);\r\n    this.modifyOptions(values, this._inheritedValues[id]);\r\n\r\n    return this._inheritedValues[id];\r\n  }\r\n\r\n  /**\r\n   * Returns total percentage for the dimension for inherited values\r\n   * @param id Name of the dimension.\r\n   */\r\n   public getInheritedSum(id: string ): number {\r\n      return Arrays.sum((this.cleanDimensions(this.inherited)  ?? []).filter((x) => x.id == id), (x: any) => x.percent ?? 0);\r\n  }\r\n\r\n  /**\r\n   * Returns current obsolete values.\r\n   */\r\n    public get obsoleteValues() {\r\n      if (this.current){\r\n        const obsolete = this.current.filter((x) => !this._definitions.find((d) => d.id === x.id)).sort((a,b) => (a.id ?? \"\").localeCompare(b.id ?? \"\") );\r\n        this.modifyOptions(obsolete, this._obsoleteValues);\r\n      }\r\n      return this._obsoleteValues;\r\n    }\r\n\r\n  /**\r\n   * Returns true if the values contains obsolete dimensions.\r\n   * @returns True if the values contains obsolete dimensions.\r\n   */\r\n  public get hasObsoleteValues(): boolean {\r\n    return this.obsoleteValues.length > 0;\r\n  }\r\n\r\n  private modifyOptions(\r\n    source: any[],\r\n    target: any[]) {\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    target.splice(0, target.length);\r\n    target.push(...source);\r\n  }\r\n\r\n  private cleanDimensions(dimensions: CostAccountingDimension[]) {\r\n    if (!dimensions) {\r\n      return dimensions;\r\n    }\r\n    const cleaned = dimensions.filter(x => x.value && x.id);\r\n    return cleaned;\r\n  }\r\n}\r\n","import { Arrays, Calculation, CostAccountingDimensionScope } from \"@salaxy/core\";\r\n\r\nimport { SessionService} from \"../../services\";\r\n\r\nimport { CostAccountingController } from \"./CostAccountingController\";\r\n\r\n/**\r\n * Handles the user interaction for entering cost accounting data for the calculation.\r\n */\r\nexport class CalcCostAccountingController extends CostAccountingController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** The calculation*/\r\n  public calc: Calculation;\r\n\r\n  /**\r\n   * Creates a new CalcCostAccountingController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    sessionService: SessionService\r\n  ) {\r\n    super(sessionService);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n   this.scope = CostAccountingDimensionScope.Calculation;\r\n   super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current calculation is read only.\r\n   */\r\n   public get isReadOnly(): boolean {\r\n    if (this.readOnly === true || this.readOnly === false) {\r\n      return this.readOnly;\r\n    }\r\n    return this.calc.isReadOnly;\r\n  }\r\n\r\n  // TO BE REMOVED\r\n\r\n  /** Returns the cost accounting model type */\r\n  public get isLegacy(): boolean {\r\n    //backward compat.\r\n    if (this.calc.usecase?.uri === \"/UsecaseDefinition/FI53POYS0025543933/costcenter-percentages\") {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Returns total cost center percentage */\r\n  public getLegacySum(): number {\r\n    if (this.isLegacy) {\r\n      return Arrays.sum(this.calc.usecase?.data?.dimensions?.costCenter ?? [], (x: any) => x.percent ?? 0);\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /** Returns current costCenter. */\r\n  public get costCenter() {\r\n    if (this.isLegacy) {\r\n      if (!this.calc.usecase) {\r\n        this.calc.usecase = {};\r\n      }\r\n      if (!this.calc.usecase.data) {\r\n        this.calc.usecase.data = {};\r\n      }\r\n      if (!this.calc.usecase.data.dimensions) {\r\n        this.calc.usecase.data.dimensions = {};\r\n      }\r\n      if (!this.calc.usecase.data.dimensions.costCenter) {\r\n        this.calc.usecase.data.dimensions.costCenter = [];\r\n      }\r\n    }\r\n    return this.calc.usecase?.data?.dimensions?.costCenter;\r\n  }\r\n}\r\n","import { Arrays, Calculation, CostAccountingDimensionScope, UserDefinedRow } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"../../services\";\r\nimport { CostAccountingController } from \"./CostAccountingController\";\r\n\r\n/**\r\n * Handles the user interaction for entering cost accounting data for the calculation row.\r\n */\r\nexport class CalcRowCostAccountingController extends CostAccountingController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** The calculation for row */\r\n  public calc: Calculation;\r\n\r\n  /** Current row */\r\n  public row: UserDefinedRow;\r\n\r\n  /**\r\n   * Creates a new CalcCostAccountingController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    sessionService: SessionService,\r\n\r\n  ) {\r\n    super(sessionService);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.scope = CostAccountingDimensionScope.Row;\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current calculation is read only.\r\n   */\r\n   public get isReadOnly(): boolean {\r\n    if (this.readOnly === true || this.readOnly === false) {\r\n      return this.readOnly;\r\n    }\r\n    return this.calc.isReadOnly;\r\n  }\r\n\r\n  /** Returns the cost accounting model type */\r\n  public get isLegacy(): boolean {\r\n    //backward compat.\r\n    if (this.calc.usecase?.uri === \"/UsecaseDefinition/FI53POYS0025543933/costcenter-percentages\") {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Returns total cost center percentage */\r\n  public getLegacySum(): number {\r\n    if (this.isLegacy) {\r\n      return Arrays.sum(this.row?.data?.dimensions?.costCenter ?? [], (x: any) => x.percent ?? 0);\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /** Returns current costCenter. */\r\n  public get costCenter() {\r\n    if (this.isLegacy) {\r\n      if (!this.row.data) {\r\n        this.row.data = {};\r\n      }\r\n      if (!this.row.data.dimensions) {\r\n        this.row.data.dimensions = {};\r\n      }\r\n      if (!this.row.data.dimensions.costCenter) {\r\n        this.row.data.dimensions.costCenter = [];\r\n      }\r\n    }\r\n\r\n    return this.row.data?.dimensions?.costCenter;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Calculation, CalculationStatus } from \"@salaxy/core\";\r\nimport { WizardController } from \"../bases/WizardController\";\r\nimport { WizardStep, WizardService, InvoicesService, EditDialogParameters } from \"../../services\";\r\n\r\n/**\r\n * Wizard for creating personal payment.\r\n */\r\nexport class PalkkausPersonalPaymentOverviewController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n   public static $inject = [\"$scope\", \"InvoicesService\", \"EditDialogParameters\", \"WizardService\"];\r\n\r\n   /** Used calculation */\r\n  public model: Calculation;\r\n\r\n  /**\r\n   * Creates a new WizardController with dependency injection.\r\n   * @ignore\r\n   */\r\n   constructor(\r\n    $scope: angular.IScope,\r\n    private invoices: InvoicesService,\r\n    private editDialogParameters: EditDialogParameters<Calculation>,\r\n    wizardService: WizardService\r\n  ) {\r\n    super($scope, wizardService);\r\n  }\r\n\r\n  /**\r\n   * Initialization of the controller\r\n   */\r\n   public $onInit() {\r\n    super.$onInit();\r\n    this.wizardService.setSteps(this.getWizardSteps());\r\n    if (!this.editDialogParameters) {\r\n      throw new Error(\"No editDialogParameters coming in.\");\r\n    }\r\n    this.model = this.editDialogParameters.current as Calculation;\r\n    if (this.model?.workflow?.status === CalculationStatus.PaymentSucceeded && !this.editDialogParameters?.logic?.isInspectingPaidInvoices) {\r\n      this.step = 4;\r\n    }\r\n  }\r\n\r\n  /** Worker wizard configuration */\r\n  public getWizardSteps(): WizardStep[] {\r\n    if (this.editDialogParameters?.logic?.isInspectingPaidInvoices) {\r\n      return [\r\n        {\r\n          title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step1.heading\",\r\n          view: \"salaxy-components/modals/calc/personal-payment/TotalWorkerPayment.html\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step2.heading\",\r\n          view: \"salaxy-components/modals/calc/personal-payment/Tax.html\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.heading\",\r\n          view: \"salaxy-components/modals/calc/personal-payment/SideCosts.html\",\r\n        },\r\n      ];\r\n    }\r\n    return [\r\n      {\r\n        title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step1.heading\",\r\n        view: \"salaxy-components/modals/calc/personal-payment/TotalWorkerPayment.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step2.heading\",\r\n        view: \"salaxy-components/modals/calc/personal-payment/Tax.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.heading\",\r\n        view: \"salaxy-components/modals/calc/personal-payment/SideCosts.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.heading\",\r\n        view: \"salaxy-components/modals/calc/personal-payment/Approval.html\",\r\n      },\r\n    ];\r\n  }\r\n\r\n  /** Returns true if user can go forward in  the wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n          return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible.\r\n   * Override adds the taxcard if personalId is there and resets it if personalId has changed.\r\n   */\r\n   public goNext() {\r\n    super.goNext();\r\n  }\r\n\r\n  /**\r\n   * Checks if user can navigate to previuous step\r\n   */\r\n  public get canGoPrevious(): boolean {\r\n    if (this.model?.workflow?.status === CalculationStatus.PaymentSucceeded && !this.editDialogParameters?.logic?.isInspectingPaidInvoices) {\r\n      return false;\r\n    }\r\n\r\n    if (this.step > 1 && !this.steps[this.step - 2].disabled) {\r\n        return true;\r\n    }\r\n    return false;\r\n}\r\n\r\n  /**\r\n   * Return EPR payment warning to template\r\n   */\r\n  public get eprPaymentWarning() {\r\n    return this.invoices.getEprWarningForPayment(this.model?.workflow?.salaryDate);\r\n  }\r\n\r\n  /**\r\n   * Return EPR cancel warning to template\r\n   */\r\n   public get eprCancelWarning() {\r\n    return this.invoices.getEprWarningForCancellation(this.model?.workflow?.salaryDate, this.model?.workflow?.status === CalculationStatus.PaymentSucceeded ? true : false);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculation,\r\n  InvoicesLogic,\r\n  PayrollDetails,\r\n  SalaryDateKind,\r\n  Brand\r\n} from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Contains functionality for switching between salary date kinds for payrolls or calculations.\r\n */\r\nexport class SalaryDateKindController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /**\r\n   * The current business item that is being paid: Either Calculation or PayrollDetails.\r\n   */\r\n  public model: Calculation | PayrollDetails;\r\n\r\n /**\r\n  * Function that is called when the salary date kind has been chagned\r\n  * Function has the following locals:\r\n  * paymentChannel: the selected payment channel.\r\n  * businessObject: the current business object which has been changed.\r\n  */\r\n  public onSalaryDateKindChange: (params: {\r\n    /** Selected payment channel */\r\n    salaryDateKind: SalaryDateKind,\r\n    /** The current business object which has been changed.  */\r\n    businessObject: Calculation | PayrollDetails,\r\n  }) => void;\r\n\r\n  public salaryDateKinds = SalaryDateKindController.getSalaryDateKinds();\r\n\r\n  constructor(private uiHelpers: UiHelpers) {\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    // Init here\r\n  }\r\n\r\n  /** Gets the current salary date kind object. */\r\n  public get currentSalaryDateKind() {\r\n    let currentValue: SalaryDateKind = undefined;\r\n    if (InvoicesLogic.isCalculation(this.model)) {\r\n      currentValue = this.model.workflow.salaryDateKind;\r\n    } else if (InvoicesLogic.isPayroll(this.model)) {\r\n      currentValue = this.model.input.salaryDateKind;\r\n    }\r\n    return this.salaryDateKinds.find((x) => x.value == currentValue) ?? this.salaryDateKinds[0];\r\n  }\r\n\r\n\r\n  /** Sets the salary date kind and starts recalculation. */\r\n  public setSalaryDateKind(newSalaryDateKind: SalaryDateKind) {\r\n    if (InvoicesLogic.isCalculation(this.model)) {\r\n      this.showCalculationSalaryDateKindSelection(newSalaryDateKind, this.model);\r\n    } else if (InvoicesLogic.isPayroll(this.model)) {\r\n      this.showPayrollSalaryDateKindSelection(newSalaryDateKind, this.model);\r\n    } else {\r\n      throw new Error(\"Unknwon business object type.\");\r\n    }\r\n  }\r\n\r\n\r\n\r\n  /** Shows the salary date kind dialog */\r\n  private showCalculationSalaryDateKindSelection(newSalaryDateKind: SalaryDateKind, calculation: Calculation) {\r\n    const original = calculation.workflow.salaryDateKind;\r\n    const isCfa = InvoicesLogic.isCfa(calculation.info.paymentChannel);\r\n    const logic = {\r\n        value: newSalaryDateKind,\r\n        text: `SALAXY.ENUM.SalaryDateKind.${newSalaryDateKind}.label`,\r\n        title: `SALAXY.ENUM.SalaryDateKind.${newSalaryDateKind}.description${isCfa ? \"Cfa\" : \"NonCfa\"}`\r\n    };\r\n\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/SalaryDateKind.html\", calculation.workflow.salaryDateKind, logic).then( (result) => {\r\n      if (result.action ==  EditDialogKnownActions.Ok) {\r\n        if (original != newSalaryDateKind) {\r\n          calculation.workflow.salaryDateKind = newSalaryDateKind;\r\n          this.onSalaryDateKindChange({ salaryDateKind: newSalaryDateKind, businessObject: calculation });\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Shows the salary date kind dialog */\r\n  private showPayrollSalaryDateKindSelection(newSalaryDateKind: SalaryDateKind, payroll: PayrollDetails) {\r\n\r\n    const original = payroll.input.salaryDateKind;\r\n    const isCfa = InvoicesLogic.isCfa(payroll.input.paymentChannel);\r\n    const logic = {\r\n        value: newSalaryDateKind,\r\n        text: `SALAXY.ENUM.SalaryDateKind.${newSalaryDateKind}.label`,\r\n        title: `SALAXY.ENUM.SalaryDateKind.${newSalaryDateKind}.description${isCfa ? \"Cfa\" : \"NonCfa\"}`\r\n    };\r\n\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/SalaryDateKind.html\", payroll.input.salaryDateKind, logic).then( (result) => {\r\n      if (result.action ==  EditDialogKnownActions.Ok) {\r\n        if (original != newSalaryDateKind) {\r\n          payroll.input.salaryDateKind = newSalaryDateKind;\r\n          this.onSalaryDateKindChange({ salaryDateKind: newSalaryDateKind, businessObject: payroll });\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  private static getSalaryDateKinds() {\r\n    return [\r\n      {\r\n        value : SalaryDateKind.Default,\r\n        text: \"SALAXY.ENUM.SalaryDateKind.default.label\",\r\n        avatar: {\r\n          color: Brand.getBrandColor(\"primary\", \"rgba\"),\r\n          icon: \"fa-clock-o\",\r\n        }\r\n      },\r\n      {\r\n        value : SalaryDateKind.InPast,\r\n        text: \"SALAXY.ENUM.SalaryDateKind.inPast.label\",\r\n        avatar: {\r\n          color: Brand.getBrandColor(\"danger\", \"rgba\"),\r\n          icon: \"fa-history\",\r\n        }\r\n      },\r\n    ];\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {Calculation,CalcWorktime, HolidayYears, HolidayYear, Dates, AbsencePeriod, Arrays, HolidayBonusPaymentMethod, AbsenceCauseCode} from \"@salaxy/core\";\r\nimport {UiHelpers} from \"../../services\";\r\n\r\n/**\r\n * Displays leaves for current calculation period.\r\n */\r\nexport class CalcLeavesController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"HolidayYears\", \"UiHelpers\"];\r\n\r\n  public annualLeavestoBePaid: AbsencePeriod[] = [];\r\n  public annualLeavesWaitingForPayment: AbsencePeriod[] = [];\r\n  public absencesToUse: AbsencePeriod[] = [];\r\n  public absencesToReject: AbsencePeriod[] = [];\r\n\r\n  /** Current calculation. */\r\n  public calc: Calculation;\r\n\r\n   /** Current worktime. */\r\n   public worktime: CalcWorktime;\r\n\r\n   /** All holiday years for employment */\r\n   public employmentHolidayYears: HolidayYear[] = [];\r\n\r\n   /** Current holiday year for employment */\r\n   public currentEmploymentHolidayYear: HolidayYear;\r\n\r\n  /**\r\n   * Creates a new CalcReportsController\r\n   * @ignore\r\n   */\r\n  constructor(private fullApi: HolidayYears, private uiHelpers: UiHelpers) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.absencesToUse.push(...this.worktime.absencesPeriods?.filter((x) => x.causeCode !== AbsenceCauseCode.AnnualLeave) || []);\r\n    // generate ids for absences\r\n    this.absencesToUse.forEach((x) => x.id = x.id || \"$\"+this.newGuid());\r\n    this.absencesToReject.push(...angular.copy(this.absencesToUse));\r\n    // there is no need to load absences, because absences can only be used or not used. No picking from other periods should be possible.\r\n    // probably there is no need to edit absences either\r\n\r\n    this.getHolidayYearsForEmployment(this.calc.worker.employmentId).then(() => {\r\n      this.annualLeavestoBePaid = this.worktime.absencesPeriods?.filter((x) => x.causeCode == AbsenceCauseCode.AnnualLeave) || [];\r\n      this.annualLeavesWaitingForPayment = this.currentEmploymentHolidayYear.leaves.planned.map( x => ({\r\n        causeCode: AbsenceCauseCode.AnnualLeave,\r\n        id: x.id,\r\n        period: angular.copy(x.period),\r\n        notes: x.notes\r\n      }));\r\n    });\r\n  }\r\n\r\n  /** Returns final absences periods */\r\n  public getAbsencesPeriods() {\r\n    const result = angular.copy(([] as AbsencePeriod[]).concat(...this.annualLeavestoBePaid).concat(...this.absencesToUse));\r\n    // remove absence ids\r\n    result.forEach((x) => {\r\n      if (x.id?.startsWith(\"$\")) {\r\n        delete x.id;\r\n      }\r\n    });\r\n    return result;\r\n  }\r\n\r\n  /** Loads holiday years for employment and sets current holiday year */\r\n  public getHolidayYearsForEmployment(employmentId: string): Promise<HolidayYear[]> {\r\n    return this.fullApi.getForEmployment(employmentId).then((result) => {\r\n      this.employmentHolidayYears = result;\r\n      const periodStart = Dates.asDate(this.calc.info.workStartDate || Dates.getToday());\r\n      const year = periodStart > Dates.getDate(Dates.getYear(periodStart), 3, 31) ? Dates.getYear(periodStart) : Dates.getYear(periodStart) - 1;\r\n\r\n      this.currentEmploymentHolidayYear = this.employmentHolidayYears.find((holidayYear) => holidayYear.year === year);\r\n      return result;\r\n    });\r\n  }\r\n\r\n /**\r\n  * Moves an item between different payment lists.\r\n  * @param item - The item to be moved.\r\n  * @param target - The target payment list.\r\n  */\r\n  public moveItem(item: any, target:\"annualLeavestoBePaid\" | \"annualLeavesWaitingForPayment\") {\r\n    if(target ===\"annualLeavesWaitingForPayment\") {\r\n      const index = this.annualLeavestoBePaid.indexOf(item);\r\n      if (index > -1) {\r\n        this.annualLeavestoBePaid.splice(index, 1);\r\n      }\r\n    }\r\n    if(target ===\"annualLeavestoBePaid\") {\r\n      this.annualLeavestoBePaid.push(item);\r\n    }\r\n  }\r\n\r\n /**\r\n  * Moves an item between different payment lists.\r\n  * @param item - The item to be moved.\r\n  * @param target - The target payment list.\r\n  */\r\n   public moveAbsenceItem(item: any, target:\"absencesToUse\" | \"absencesToReject\") {\r\n    if(target ===\"absencesToReject\") {\r\n      const index = this.absencesToUse.indexOf(item);\r\n      if (index > -1) {\r\n        this.absencesToUse.splice(index, 1);\r\n      }\r\n    }\r\n    if(target ===\"absencesToUse\") {\r\n      this.absencesToUse.push(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Determines if a given leave should be disabled based on its type and whether it's in the list of leaves to be paid.\r\n   * @param {AnnualLeave} leave - The leave object to check.\r\n   */\r\n  public isSelectedToBePaid(leave: AbsencePeriod) {\r\n    return this.annualLeavestoBePaid?.some((item) => item.id === leave.id);\r\n  }\r\n\r\n  /**\r\n   * Determines if a given absence should be disabled based on it's in the list of absences to use.\r\n   * @param {AbsencePeriod} absence - The leave object to check.\r\n   */\r\n    public isAbsenceSelectedToUse(absence: AbsencePeriod) {\r\n      return this.absencesToUse?.some((item) => item.id === absence.id);\r\n    }\r\n\r\n  /**\r\n   * Determines the style for a given leave based on whether it should be disabled or not.\r\n   * @param {AnnualLeave} leave - The leave object to check.\r\n   */\r\n  public getDisabledStyle(leave: AbsencePeriod) {\r\n    if (this.isSelectedToBePaid(leave)) {\r\n      return {\r\n        \"background-color\": \"lightgrey\",\r\n        \"opacity\": \"0.5\"\r\n      };\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Determines the style for a given absence based on whether it should be disabled or not.\r\n   * @param {AnnualLeave} absence - The absences object to check.\r\n   */\r\n    public getAbsenceDisabledStyle(absence: AbsencePeriod) {\r\n      if (this.isAbsenceSelectedToUse(absence)) {\r\n        return {\r\n          \"background-color\": \"lightgrey\",\r\n          \"opacity\": \"0.5\"\r\n        };\r\n      }\r\n    }\r\n\r\n  /** Returns daysCount sum of annualLeavestoBePaid/bonusPeriodstoBePaid depending on type parameter*/\r\n  public getAccrualRemaningsToBePaid(type: \"holidayPay\" | \"holidayBonus\") {\r\n    return type === \"holidayPay\" ? Arrays.sum(this.annualLeavestoBePaid, (x) => x.period.daysCount) || 0 : Arrays.sum(this.annualLeavestoBePaid, (x) => x.bonusDaysCount) || 0;\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog.\r\n   * @param item AnnualLeave to edit.\r\n   */\r\n  public showEditDialog(item: AbsencePeriod) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n\r\n    const logic =  {\r\n      /** Updates the workdays count */\r\n      updatePeriodDays: (current: AbsencePeriod) => {\r\n        if (current.period.start > current.period.end) {\r\n          current.period.end = current.period.start;\r\n        }\r\n        if (current.period.start && current.period.end) {\r\n          if (current.period.days) {\r\n            current.period.days = Dates.getVacationDays(current.period.start, current.period.end);\r\n            current.period.daysCount = current.period.days.length;\r\n            if (this.worktime.holidaySpec.bonusMethod !== HolidayBonusPaymentMethod.None) {\r\n              current.bonusDaysCount = current.period.days.length;\r\n            }\r\n          } else {\r\n            current.period.daysCount = Dates.getVacationDays(current.period.start, current.period.end).length;\r\n            if (this.worktime.holidaySpec.bonusMethod !== HolidayBonusPaymentMethod.None) {\r\n              current.bonusDaysCount = current.period.daysCount;\r\n            }\r\n          }\r\n        }\r\n      },\r\n\r\n      /** Sets the days array in period to enable days selection UI. */\r\n      setDaysSelection: (period: AbsencePeriod) => {\r\n        period.period.days = Dates.getVacationDays(period.period.start, period.period.end);\r\n        period.period.daysCount = period.period.days.length;\r\n        if (this.worktime.holidaySpec.bonusMethod !== HolidayBonusPaymentMethod.None) {\r\n          period.bonusDaysCount = period.period.days.length;\r\n        }\r\n      },\r\n\r\n    };\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/worker/holidays/HolidayYearHolidaysEditDialog.html\", item, logic).then((result) => {\r\n       if (result.action === \"delete\" || result.action === \"delete-no-save\") {\r\n        this.annualLeavestoBePaid.splice(this.annualLeavestoBePaid.indexOf(item), 1);\r\n      } else {\r\n        // No changes, cancel\r\n      }\r\n      });\r\n  }\r\n\r\n  private newGuid(): string {\r\n    let dt = new Date().getTime();\r\n    const uuid = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\r\n      /* eslint-disable-next-line no-bitwise */\r\n      const r = (dt + Math.random() * 16) % 16 | 0;\r\n      dt = Math.floor(dt / 16);\r\n      /* eslint-disable-next-line no-bitwise */\r\n      return (c === \"x\" ? r : (r & 0x3 | 0x8)).toString(16);\r\n    });\r\n    return uuid;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Controller rendering a contact info box in the page area.\r\n */\r\nexport class ContactInfoController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n\r\n  /** If true, short version of the content is shown */\r\n  public showShortContent: boolean;\r\n\r\n  /** If true, contact info is hidden */\r\n   public hideContactInfo: boolean;\r\n\r\n  /**\r\n   * Creates a new ContactInfoController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    //\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    // initialization\r\n  };\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Arrays, Calculation, CalculationListItem, CalculationRowType, Calculations, CalculatorLogic, Message, MessageFrom, MessageListItem, MessageThread, MessageThreads, MessageThreadStatus, Numeric, ODataResult, PayrollListItem, Payrolls, ThreadedMessageType, Translations } from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, SessionService, UiHelpers, UploadService } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * User interface logic for a set of messages and/or attachments\r\n * that are grouped together as messages thread.\r\n */\r\nexport class MessageThreadCrudController extends ApiCrudObjectController<MessageThread, MessageListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"MessageThreads\", \"UiHelpers\", \"UploadService\", \"$location\", \"$routeParams\", \"$anchorScroll\", \"$timeout\", \"SessionService\", \"Calculations\", \"Payrolls\"];\r\n\r\n  /** New message that is edited / to be added to the thread. */\r\n  public newMessage: Message = {\r\n    type: ThreadedMessageType.Text,\r\n  };\r\n\r\n  /** If true, the message is currently in edit mode. */\r\n  public isInEdit: boolean;\r\n\r\n  /** Role of the current user. Owner is default. */\r\n  public role: MessageFrom;\r\n\r\n  /** Once message thread loaded, create a calculation based on the rows. */\r\n  public createCalc: boolean;\r\n\r\n  /** Calculation that is created / updated based on the message thread rows. */\r\n  public calc: Calculation;\r\n\r\n  /** Approval page url. */\r\n  public approvalUrl: string;\r\n\r\n  /**\r\n   * If set, the controller will mark a message thread as open once it has been loaded.\r\n   * If the value is true, the message is marked as read immediately.\r\n   * If the value is number, the controller waits the given amount of seconds before marking the item as read.\r\n   */\r\n  private _markAsRead: number | true;\r\n\r\n  private _otherParty: string;\r\n\r\n  private _otherPartyOptions: { [key: string]: string };\r\n\r\n  private markAsReadTimeout: any;\r\n\r\n  constructor(\r\n    private messageApi: MessageThreads,\r\n    uiHelpers: UiHelpers,\r\n    protected uploadService: UploadService,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private $anchorScroll: angular.IAnchorScrollService,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private sessionService: SessionService,\r\n\r\n    private calculations: Calculations,\r\n    private payrolls: Payrolls,\r\n  ) {\r\n    // Dependency injection\r\n    super(messageApi, uiHelpers, $location, $routeParams);\r\n  }\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    this.role = this.role || MessageFrom.Owner;\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Cleaning the timeout.\r\n   */\r\n  public $onDestroy = () => {\r\n    if (angular.isDefined(this.markAsReadTimeout)) {\r\n      this.$timeout.cancel(this.markAsReadTimeout);\r\n    }\r\n  };\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/messages\",\r\n      detailsUrl: this.detailsUrl || \"/messages/details/\",\r\n      approvalUrl: this.approvalUrl || \"/messages/approval/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/MessageThreads.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * If true, this is a new unsaved object.\r\n   * Adds \"new-for-calc\" and \"new-for-payroll\" actions as new item.\r\n   */\r\n   public isNew(): boolean {\r\n    if (this.parentController) {\r\n      return this.parentController.isNew();\r\n    }\r\n    return this.action === \"new-for-calc\" || this.action === \"new-for-payroll\" || super.isNew();\r\n  }\r\n\r\n  /**\r\n   * Overrides the isReadOnly with workflow cases\r\n   */\r\n  public get isReadOnly(): boolean {\r\n    return super.isReadOnly ||\r\n      (this.role === \"owner\" && this.current?.workflowData?.events.some((x) => x.type === \"PartnerMessageClosed\"));\r\n  }\r\n\r\n  /**\r\n   * If set, the controller will mark a message thread as open once it has been loaded.\r\n   * If the value is true, the message is marked as read immediately.\r\n   * If the value is number, the controller waits the given amount of seconds before marking the item as read.\r\n   */\r\n  public get markAsRead(): number | true {\r\n    if (this.parentController) {\r\n      return (this.parentController as MessageThreadCrudController).markAsRead;\r\n    }\r\n    return this._markAsRead;\r\n  }\r\n  public set markAsRead(value: number | true) {\r\n    if (this.parentController) {\r\n      (this.parentController as MessageThreadCrudController).markAsRead = value;\r\n    }\r\n    this._markAsRead = value;\r\n  }\r\n\r\n  /**\r\n   * Salaxy ID (IBAN format) for the other party (besides the message thread owner).\r\n   * Supports special values: \"partner\" for payment partner.\r\n   */\r\n  public get otherParty(): string {\r\n    return this._otherParty;\r\n  }\r\n  public set otherParty(value: string) {\r\n    if (value === \"partner\") {\r\n      this._otherParty = this.sessionService.session.settings.partner.accountId;\r\n    } else {\r\n      this._otherParty = value;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * If set, shows a drop-down for these options using the enum component.\r\n   * Keys may have special values: \"partner\": payment partner.\r\n   */\r\n  public get otherPartyOptions(): { [key: string]: string } {\r\n    return this._otherPartyOptions;\r\n  }\r\n  public set otherPartyOptions(value: { [key: string]: string }) {\r\n    if (!value || Object.keys(value).length === 0) {\r\n      this._otherPartyOptions = null;\r\n      return;\r\n    }\r\n    this._otherPartyOptions = Object.assign({}, ...Object.keys(value).map((key) => {\r\n      if (key === \"partner\") {\r\n        const partner = this.sessionService.session.settings.partner;\r\n        return { [partner.accountId]: value[key] || partner.serviceModel.site.webAppName || partner.info.avatar.displayName };\r\n      }\r\n      return { [key]: value[key] };\r\n    }));\r\n  }\r\n\r\n  /**\r\n   * Returns true if the other-party is 'partner' or partner's ID.\r\n   */\r\n  public get isOtherPartyPartner(): boolean {\r\n    return this.otherParty === \"partner\" ||  this.otherParty === this.sessionService.session?.settings?.partner?.accountId;\r\n  }\r\n\r\n  /**\r\n   * Adds a text message (from the textarea / this.newMessage) to the current thread.\r\n   */\r\n  public sendMessage(): Promise<MessageThread> {\r\n    this.newMessage.content = (this.newMessage.content || \"\").trim();\r\n    this.newMessage.fromParty = this.role;\r\n    switch (this.newMessage.type) {\r\n      case ThreadedMessageType.Text:\r\n        if (!this.newMessage.content) {\r\n          return;\r\n        }\r\n        break;\r\n\r\n    }\r\n    return this.setStatus(this.messageApi.addMessage(this.currentId, this.newMessage))\r\n      .then((thread) => {\r\n        this.newMessage = {\r\n          type: ThreadedMessageType.Text,\r\n        };\r\n        this.setCurrent(thread);\r\n        return thread;\r\n      });\r\n  }\r\n\r\n  /** Sets the type of the message to be added / edited */\r\n  public setType(type: ThreadedMessageType) {\r\n    type = type || ThreadedMessageType.Text;\r\n    this.newMessage = {\r\n      type: type,\r\n    };\r\n    switch (type) {\r\n      case \"absence\" as any:\r\n        this.newMessage.contentData = {\r\n          periods: [],\r\n        };\r\n        this.newMessage.content = \"Absence content\";\r\n        break;\r\n      case \"annualLeave\" as any:\r\n        this.newMessage.contentData = {\r\n          leaves: [],\r\n        };\r\n        this.newMessage.content = \"Annual leave content\";\r\n        break;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends an email notification to the thread owner.\r\n   */\r\n  public sendNotification(): Promise<MessageThread> {\r\n    const endUserService = this.sessionService.session.settings.partner.serviceModel.site.webAppName || this.sessionService.session.settings.partner.info.avatar.displayName;\r\n    const subject = `${Translations.get(\"SALAXY.NG1.MessageThreadComponent.sendNotificationSubject\")} ${endUserService}`;\r\n    const body = `${Translations.get(\"SALAXY.NG1.MessageThreadComponent.sendNotificationBody\")}`;\r\n\r\n    return this.setStatus(this.messageApi.sendNotification(this.currentId, subject, body))\r\n      .then((thread) => {\r\n        this.setCurrent(thread);\r\n        return thread;\r\n      });\r\n  }\r\n\r\n  /** Overrides the save to assure that the other party is defined (can be set in component properties).  */\r\n  public save() {\r\n    if (!this.current.otherParty) {\r\n      if (!this.otherParty) {\r\n        this.uiHelpers.showAlert(\"SALAXY.NG1.MessageThreadComponent.saveNoToField\");\r\n        return;\r\n      }\r\n      this.current.otherParty = this.otherParty;\r\n    }\r\n    return super.save();\r\n  }\r\n\r\n  /** Selects a calculation as current calculation. */\r\n  public selectCalc(): void {\r\n    this.uiHelpers.openSelectCalcs(\"draft\", \"Valitse palkkalaskelma\").then((dialogResult) => {\r\n      if (dialogResult.action == EditDialogKnownActions.Ok && dialogResult.item.length > 0) {\r\n        this.calculations.getSingle(dialogResult.item[0].id).then((calc) => {\r\n          this.calc = calc;\r\n          this.updateCalc();\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Updates the calculation based on rows in the message. */\r\n  public updateCalc(): void {\r\n    this.calc = this.calc || CalculatorLogic.getBlank();\r\n    const totalMinutes = Arrays.sum(this.current.messages, (x) => x.contentData?.totalTime || 0);\r\n    this.calc.employer.isSelf = true;\r\n    this.calc.worker.accountId = this.calc.worker.accountId || this.current.otherParty;\r\n    this.calc.rows = this.calc.rows.filter((x) => x.sourceId != this.current.id);\r\n    // HACK: Get the price from employment\r\n    const price = 10;\r\n    this.calc.rows.splice(0, 0, {\r\n      rowType: CalculationRowType.HourlySalary,\r\n      count: Numeric.round(totalMinutes / 60),\r\n      price,\r\n      sourceId: this.current.id,\r\n    });\r\n    // TODO: Lauantai ja sunnuntai\r\n    this.recalculate();\r\n  }\r\n\r\n  /** Recalculates the calculation based on the rows in the message. */\r\n  public recalculate(): Promise<Calculation> {\r\n    return this.calculations.recalculate(this.calc).then((result) => {\r\n      this.calc = result;\r\n      return this.calc;\r\n    });\r\n  }\r\n\r\n  /** Saves the current calculation. */\r\n  public saveCalc(): Promise<Calculation> {\r\n    return this.calculations.save(this.calc).then((result) => {\r\n      this.calc = result;\r\n      return this.calc;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process depending on the bindingMode.\r\n   * Overrides a different load process for \"new-for-calc\" and \"new-for-payroll\".\r\n   * Overrides the reload to send the browser to the bottom\r\n   */\r\n   public reload(): Promise<MessageThread> {\r\n    if (this.action === \"new-for-calc\" || this.action === \"new-for-payroll\") {\r\n      if (this.parentController) {\r\n        return this.parentController.reload().then((item) => {\r\n          this._currentId = null;\r\n          return item;\r\n        });\r\n      } else {\r\n\r\n        const prepareMessage = (): Promise<MessageThread> => {\r\n          const newMessage = this.api.getBlank();\r\n          newMessage.status = MessageThreadStatus.Active;\r\n          if (this.currentId === \"new\") {\r\n            this._currentId = null;\r\n          }\r\n          if (this.action === \"new-for-calc\" && this.currentId && this.currentId != \"new\") {\r\n\r\n            return this.getCalculationListItem(this.currentId).then( (calculationListItem) => {\r\n              newMessage.title = \"Palkka \" + calculationListItem?.otherPartyInfo?.avatar?.displayName;\r\n              newMessage.ownerWorkflow = {\r\n                salaryDate: calculationListItem?.salaryDate\r\n              };\r\n              newMessage.messages.push(\r\n                {\r\n                  contentId: this.currentId,\r\n                  fromParty: this.role || MessageFrom.Owner,\r\n                  type: ThreadedMessageType.Calculation\r\n                });\r\n                return newMessage;\r\n              });\r\n          }\r\n          else if (this.action === \"new-for-payroll\" && this.currentId && this.currentId != \"new\")\r\n          {\r\n            return this.getPayrollListItem(this.currentId).then( (payrollListItem) => {\r\n              newMessage.status = MessageThreadStatus.Active;\r\n              newMessage.title = \"Palkkalista \" + payrollListItem?.shortText;\r\n              newMessage.ownerWorkflow = {\r\n                salaryDate: payrollListItem?.salaryDate\r\n              };\r\n              newMessage.messages.push(\r\n                {\r\n                  contentId: this.currentId,\r\n                  fromParty: this.role || MessageFrom.Owner,\r\n                  type: ThreadedMessageType.Payroll\r\n                });\r\n                return newMessage;\r\n              });\r\n          } else {\r\n            return Promise.resolve(newMessage);\r\n          }\r\n        };\r\n        return prepareMessage().then( (newMessage) => {\r\n          this._currentId = null;\r\n          return this.setStatus(Promise.resolve(newMessage))\r\n            .then((item) => {\r\n              this.setCurrentRef(item);\r\n              return item;\r\n            });\r\n        });\r\n      }\r\n    } else {\r\n      return super.reload().then((value) => {\r\n\r\n        // HACK?\r\n        if (this.createCalc) {\r\n          this.updateCalc();\r\n        }\r\n        if (!this.isNew()) {\r\n          this.$timeout(() => {\r\n            this.$anchorScroll(\"messageContainerBottom\");\r\n          });\r\n          if (this.status === \"loaded\" && this.markAsRead && !this.getReadTime()) {\r\n            const relevantMessages = this.current.messages\r\n              .filter((x) => x.fromParty === (this.role === \"otherParty\" ? \"owner\" : \"otherParty\"));\r\n            if (relevantMessages.length > 0) {\r\n              if (this.markAsRead === true) {\r\n                this.markAllAsRead();\r\n              } else {\r\n                this.markAsReadTimeout = this.$timeout(() => {\r\n                  if (!this.isInEdit) {\r\n                    this.markAllAsRead();\r\n                  }\r\n                }, this.markAsRead * 1000);\r\n              }\r\n            }\r\n          }\r\n        }\r\n        return value;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Marks all messages as read by a given party.\r\n   * The command is immediately sent to the server and the current message is updated incrementally (just the read/unread info).\r\n   * @param readBy The party for which the messages are marked as read.\r\n   * If not specified, uses the current role or the controller.\r\n   * @returns The entire thread with the messages marked as read.\r\n   */\r\n  public markAllAsRead(readBy?: MessageFrom): Promise<MessageThread> {\r\n    readBy = readBy || this.role || MessageFrom.Owner;\r\n    return this.messageApi.markAsRead(this.currentId, readBy)\r\n      .then((result) => {\r\n        this.current.messages.forEach((msg: Message) => {\r\n          if (readBy === \"otherParty\") {\r\n            msg.readByOtherParty = msg.readByOtherParty || new Date().toISOString();\r\n          } else {\r\n            msg.readByOwner = msg.readByOwner || new Date().toISOString();\r\n          }\r\n        });\r\n        return result;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Marks a message / attachment as read/unread also changing all messages before that message.\r\n   * The role of the read/unread is determined by the message: It is the opposite of fromParty (owner (default)/otherParty).\r\n   * The changes are made only to the current message, not Saved to the server.\r\n   * @param message The message that is marked as read/unread (with the messages before that).\r\n   * @param readByValue Possibility to force whether the flag is set to read or unread.\r\n   * If null, the flag is set to the opposite of the current.\r\n   */\r\n  public markItemAsRead(message: Message, readByValue: boolean = null) {\r\n    const flagFor: \"owner\" | \"otherParty\" = message.fromParty === \"otherParty\" ? \"owner\" : \"otherParty\";\r\n    if (readByValue == null) {\r\n      readByValue = flagFor === \"owner\" ? !message.readByOwner : !message.readByOtherParty;\r\n    }\r\n    if (readByValue) {\r\n      for (const item of this.current.messages) {\r\n        if (flagFor === \"owner\") {\r\n          item.readByOwner = item.readByOwner || new Date().toISOString();\r\n        } else {\r\n          item.readByOtherParty = item.readByOtherParty || new Date().toISOString();\r\n        }\r\n        if (item === message) {\r\n          return;\r\n        }\r\n      }\r\n    } else {\r\n      const startFrom = this.current.messages.indexOf(message);\r\n      for (let i = startFrom; i < this.current.messages.length; i++) {\r\n        if (flagFor === \"owner\") {\r\n          this.current.messages[i].readByOwner = null;\r\n        } else {\r\n          this.current.messages[i].readByOtherParty = null;\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the time when a message was read.\r\n   * The time is dependent of the fromParty of the message: There are separate times for owner and other party.\r\n   * If time is null, the message has not been read.\r\n   * @param message Message for which the readTime is fetched.\r\n   * If not set, uses the last message for the current party.\r\n   * @returns If fromParty is \"otherParty\", then readByOwner is returned, otherwise readByOtherParty is returned.\r\n   * The value should be ISO date (string) or null if the item has not been read yet.\r\n   */\r\n  public getReadTime(message: Message = null) {\r\n    if (!message) {\r\n      const relevantMessages = this.current.messages\r\n        .filter((x) => x.fromParty === (this.role === \"otherParty\" ? \"owner\" : \"otherParty\"));\r\n      if (relevantMessages.length === 0) {\r\n        return null;\r\n      }\r\n      message = relevantMessages[relevantMessages.length - 1];\r\n    }\r\n    if (message.fromParty === \"otherParty\") {\r\n      return message.readByOwner || null;\r\n    } else {\r\n      return message.readByOtherParty || null;\r\n    }\r\n  }\r\n\r\n  /** temp upload progress */\r\n  public uploadProgress = 0;\r\n\r\n  /**\r\n   * Uploads the files to the server\r\n   * @param files The files collection from the upload component\r\n   * @example\r\n   * <button ngf-select=\"$ctrl.uploadFiles($files)\" multiple accept=\"image/*\">Select Files</button>\r\n   */\r\n  public uploadFiles(files: any[]) {\r\n    if (files && files.length) {\r\n      const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.MessageThreadComponent.uploadFilesSaving\");\r\n      this.uploadService.upload<MessageThread>(\r\n        this.messageApi.getUploadUrl(this.currentId), {\r\n          files,\r\n          from: this.role || \"owner\",\r\n        }, (progress, error) => {\r\n          this.uploadProgress = progress;\r\n        }).then((response) => {\r\n          this.newMessage.content = \"\";\r\n          this.setCurrent(response);\r\n          loader.dismiss();\r\n          return response;\r\n        }).catch((response) => {\r\n            loader.dismiss();\r\n            this.uiHelpers.showAlert(\"SALAXY.UI_Terms.error\", \"SALAXY.NG1.MessageThreadComponent.uploadFilesError\");\r\n            throw new Error(response);\r\n        });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the file display related information.\r\n   * @param message Message that contains the file.\r\n   */\r\n  public getFileInfo(message: Message) {\r\n    // TODO: Move to a helper\r\n    const result = {\r\n      isImage: false,\r\n      previewUrl: null,\r\n      downloadUrl: null,\r\n      icon: null,\r\n    };\r\n    if (message.type !== \"blobFile\") {\r\n      return result;\r\n    }\r\n    result.isImage = true;\r\n    result.icon = this.uploadService.getFileIcon(message.content);\r\n    if (message.contentId) {\r\n      if (message.preview === message.contentId) {\r\n        result.previewUrl = this.uploadService.getPreviewUrl(message.preview);\r\n      }\r\n      result.downloadUrl = this.uploadService.getFileUrl(message.contentId);\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Opens the list of calculations into a dialog window for selection and then adds them to payroll\r\n   * @param category Either \"paid\": Read-only, a copy is added ... or \"draft\": Editable, moved with status changed.\r\n   */\r\n  public addExistingCalc(category: \"paid\" | \"draft\" = \"draft\") {\r\n    const calculations = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/CalcList.html\",\r\n      calculations,\r\n      {\r\n        title: (category === \"paid\" ? \"SALAXY.NG1.MessageThreadComponent.addExistingCalcCopy\" : \"SALAXY.NG1.MessageThreadComponent.addExistingCalcMove\"),\r\n        category,\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && calculations.length > 0) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.MessageThreadComponent.addExistingCalcLoading\");\r\n          const messages = calculations.map((x) => {\r\n            const msg: Message = {\r\n              contentId: x.id,\r\n              fromParty: this.role || MessageFrom.Owner,\r\n              type: ThreadedMessageType.Calculation,\r\n            };\r\n            return msg;\r\n          });\r\n          this.current.messages.push(...messages);\r\n          this.save().then(() => {\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Opens the list of payrolls into a dialog window for selection and then adds them to payroll\r\n   * @param category Either \"paid\": Read-only, a copy is added ... or \"draft\": Editable, moved with status changed.\r\n   */\r\n   public addExistingPayroll(category: \"paid\" | \"draft\" = \"draft\") {\r\n    const payrolls = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/payroll/PayrollList.html\",\r\n      payrolls,\r\n      {\r\n        title: (category === \"paid\" ? \"Maksetut\" : \"Luonnokset\"),\r\n        category,\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && payrolls.length > 0) {\r\n          const loader = this.uiHelpers.showLoading(\"Lisätään palkkalistoja\");\r\n          const messages = payrolls.map((x) => {\r\n            const msg: Message = {\r\n              contentId: x.id,\r\n              fromParty: this.role || MessageFrom.Owner,\r\n              type: ThreadedMessageType.Payroll,\r\n            };\r\n            return msg;\r\n          });\r\n          this.current.messages.push(...messages);\r\n          this.save().then(() => {\r\n            loader.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n\r\n  /** Deletes a message from the message list (must be saved still) */\r\n  public deleteMessage(item: Message) {\r\n    this.current.messages.splice(this.current.messages.findIndex((x) => x === item), 1);\r\n  }\r\n\r\n  private getCalculationListItem(id: string): Promise<CalculationListItem> {\r\n    return this.calculations.getOData({ $filter: `id eq '${id}'`}).then( (data: ODataResult<CalculationListItem>) => {\r\n      if (data.items.length == 1) {\r\n        return data.items[0];\r\n      } else {\r\n        return null;\r\n      }\r\n    });\r\n  }\r\n  private getPayrollListItem(id: string): Promise<PayrollListItem> {\r\n    return this.payrolls.getOData({ $filter: `id eq '${id}'`}).then( (data: ODataResult<PayrollListItem>) => {\r\n      if (data.items.length == 1) {\r\n        return data.items[0];\r\n      } else {\r\n        return null;\r\n      }\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Ajax, Configs, OAuthMessage } from \"@salaxy/core\";\r\nimport { SessionService } from \"../../services\";\r\n\r\n/**\r\n * Controller for Omapalkka integration.\r\n */\r\nexport class OmapalkkaController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\", \"SessionService\", \"$sce\"];\r\n\r\n  private _url = null;\r\n  private _urlInProgress = false;\r\n\r\n  /**\r\n   * Creates a new ContactInfoController\r\n   * @ignore\r\n   */\r\n  constructor(private ajax: Ajax, private sessionService: SessionService, private $sce: angular.ISCEService) {\r\n    //\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    // initialization\r\n  };\r\n\r\n  /** Gets the URL to the Omapalkka server with Google Firebase token. */\r\n  public get url() {\r\n    if (this.sessionService.isAuthenticated) {\r\n      if (!this._url) {\r\n        if (!this._urlInProgress) {\r\n          this._urlInProgress = true;\r\n          this.ajax.getJSON(`${Configs.current.getOmapalkkaApiServer()}/api/security/token`).then( (msg: OAuthMessage) => {\r\n            const embeddedUrl = `${Configs.current.getOmapalkkaServer()}/embedded.html#fb-token=${msg?.access_token}`;\r\n            // const embeddedUrl = `http://localhost:3000/embedded.html#fb-token=${msg?.access_token}`;\r\n            this._url = this.$sce.trustAsResourceUrl(embeddedUrl);\r\n          });\r\n        }\r\n      }\r\n    }\r\n    return this._url;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculation,\r\n  Language,\r\n  PensionCalculation,\r\n  PensionCompany,\r\n  Translations,\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  SessionService,\r\n  SettingsService,\r\n  UiHelpers,\r\n  EditDialogKnownActions\r\n} from \"../../services\";\r\n\r\n\r\n/**\r\n * Provides methods for profiled Welcome messages to the end user.\r\n */\r\nexport class VarmaBannerController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"SessionService\",\r\n    \"SettingsService\",\r\n    \"UiHelpers\",\r\n    \"$sce\"\r\n  ];\r\n\r\n\r\n  /** Current calculation */\r\n  public calc: Calculation;\r\n\r\n  /** Pension Company*/\r\n  public pensionCompany: PensionCompany;\r\n\r\n  /** Varma banner/popup flags */\r\n  private _varmaPensionBanners = {\r\n    isReady: false,\r\n    showGetTyel: false,\r\n    showMoveTyel: false,\r\n    showGetYel: false,\r\n  };\r\n\r\n  /** Varma pop up dismissed flags */\r\n  private _dismissed = {\r\n    showGetTyel: false,\r\n    showMoveTyel: false,\r\n    showGetYel: [],\r\n    inStorage: false\r\n  };\r\n\r\n  /**\r\n   * Creates a new VarmaBannerController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private sessionService: SessionService,\r\n    private settingsService: SettingsService,\r\n    private uiHelpers: UiHelpers,\r\n    private $sce: angular.ISCEService,\r\n  ) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    // initialization\r\n  }\r\n\r\n\r\n  /**\r\n   * Show the popup\r\n   */\r\n  public showVarmaPopup() {\r\n    let dialogData: any = {};\r\n\r\n    if (this.varmaPensionBanners.showGetTyel) {\r\n      dialogData = {\r\n        dismiss: () => this.dismiss(\"tyel\"),\r\n        varmaShopLink: this.getVarmaShopLink(),\r\n        title: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.tyel.title\"),\r\n        message: this.$sce.trustAsHtml(Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.tyel.html\")),\r\n        btnText: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.tyel.btnText\")\r\n      };\r\n    } else if (this.varmaPensionBanners.showMoveTyel) {\r\n      dialogData = {\r\n        dismiss: () => this.dismiss(\"moveTyel\"),\r\n        varmaShopLink:  this.getVarmaShopLink(),\r\n        title: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.moveTyel.title\"),\r\n        message: this.$sce.trustAsHtml(Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.moveTyel.html\",  {pensionCompany:  Translations.get(\"SALAXY.ENUM.PensionCompany.\" + this.settingsService.current?.calc.pensionContracts[0].company+ \".label\") })),\r\n        btnText: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.moveTyel.btnText\")\r\n      };\r\n    } else if (this.varmaPensionBanners.showGetYel) {\r\n      dialogData = {\r\n        dismiss: () => this.dismiss(\"yel\"),\r\n        varmaShopLink:  this.getVarmaShopLink(),\r\n        title: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.yel.title\"),\r\n        message: this.$sce.trustAsHtml(Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.yel.html\")),\r\n        btnText: Translations.get(\"SALAXY.NG1.VarmaBannerComponent.pensionPopup.yel.btnText\")\r\n      };\r\n    }\r\n    if (dialogData.dismiss) {\r\n      this.uiHelpers.openEditDialog(\r\n        \"salaxy-components/modals/communications/VarmaPopup.html\",\r\n        dialogData,\r\n        null,\r\n        \"lg\").then((result)=> {\r\n          if(result.action == EditDialogKnownActions.Cancel){\r\n            dialogData.dismiss();\r\n          }\r\n        });\r\n    }\r\n  }\r\n\r\n\r\n  /** Gets the flags that indicate which popup to show. */\r\n  public get varmaPensionBanners(): {\r\n    /** if true, banner is ready to be shown */\r\n    isReady: boolean,\r\n    /** If true, shows popup that offers to get employee pension contract from Varma */\r\n    showGetTyel: boolean,\r\n    /** If true, shows popup that offrs to move employee pension contract from other company to Varma */\r\n    showMoveTyel: boolean,\r\n    /** If true, shows popup that offers to get entrepreneur pension contract from Varma */\r\n    showGetYel: boolean,\r\n  } {\r\n    this._varmaPensionBanners.isReady = !!this.calc && !!this.settingsService.current;\r\n    this._varmaPensionBanners.showGetTyel = this._varmaPensionBanners.isReady && this.isTyelCalculation && !this.dismissed.showGetTyel && (this.settingsService.current?.calc.pensionContracts.length == 0 || this.settingsService.current?.calc.pensionContracts.every((x) => !x.company));\r\n    this._varmaPensionBanners.showMoveTyel = this._varmaPensionBanners.isReady && this.isTyelCalculation && !this.dismissed.showMoveTyel && !this._varmaPensionBanners.showGetTyel && this.settingsService.current?.calc.pensionContracts.every((x) => x.company != PensionCompany.Varma) && this.settingsService.current?.calc.pensionContracts.every((x) => x.company != PensionCompany.None);\r\n    this._varmaPensionBanners.showGetYel = this._varmaPensionBanners.isReady && this.isYelCalculation && this.calc.worker?.employmentId && (this.dismissed.showGetYel.indexOf(this.calc.worker?.employmentId) < 0);\r\n    return this._varmaPensionBanners;\r\n  }\r\n\r\n   /** Get link to Varma pension contract shop with language parameter */\r\n   public getVarmaShopLink(): string {\r\n    if (!this.settingsService.current) {\r\n      return \"https://vaha.asiointi.varma.fi/vakuutushakemus/?PartnerID=Palkkaus&utm_source=partner&utm_medium=palkkaus\";\r\n    }\r\n    const userLang : Language = this.sessionService.session.currentAccount?.language ?? Language.Fi;\r\n\r\n    switch (userLang) {\r\n      case Language.Default:\r\n      case Language.Fi:\r\n        return \"https://vaha.asiointi.varma.fi/vakuutushakemus/?PartnerID=Palkkaus&utm_source=partner&utm_medium=palkkaus\";\r\n      case Language.Sv:\r\n        return \"https://vaha.asiointi.varma.fi/vakuutushakemus/?PartnerID=Palkkaus&langcode=sv&utm_source=partner&utm_medium=palkkaus\";\r\n      case Language.En:\r\n        return \"https://vaha.asiointi.varma.fi/vakuutushakemus/?PartnerID=Palkkaus&langcode=en&utm_source=partner&utm_medium=palkkaus\";\r\n    }\r\n  }\r\n\r\n  /** Adds dismissed to local storage to prevent the display of the popups again */\r\n  private dismiss(pension: \"tyel\" | \"moveTyel\" | \"yel\") {\r\n    switch (pension) {\r\n      case \"yel\":\r\n        if (this._dismissed.showGetYel.indexOf(this.calc.worker.employmentId) < 0) {\r\n          this._dismissed.showGetYel.push(this.calc.worker.employmentId);\r\n        }\r\n        break;\r\n      case \"tyel\":\r\n        {\r\n          this._dismissed.showGetTyel = true;\r\n        }\r\n        break;\r\n      case \"moveTyel\":\r\n        {\r\n          this._dismissed.showMoveTyel = true;\r\n        }\r\n        break;\r\n    }\r\n    this._dismissed.inStorage = true;\r\n    if (window.localStorage) {\r\n      window.localStorage.setItem(\"salaxy-varma-banner-dismissed\", JSON.stringify(this._dismissed));\r\n    }\r\n  }\r\n\r\n  /** Checks if the banner as been dismissed earlier */\r\n  private get dismissed() {\r\n    if (!this._dismissed.inStorage) {\r\n\r\n      if (window.localStorage) {\r\n        const json = window.localStorage.getItem(\"salaxy-varma-banner-dismissed\");\r\n        if (json) {\r\n          this._dismissed = JSON.parse(json);\r\n          this._dismissed.inStorage = true;\r\n        }\r\n      }\r\n\r\n    }\r\n    return this._dismissed;\r\n  }\r\n\r\n\r\n  /** Logic for determing the pension is for employee */\r\n  private get isTyelCalculation() {\r\n    if (!this.calc) {\r\n      return false;\r\n    }\r\n    return this.calc.result?.responsibilities?.pensionCalculation == PensionCalculation.Employee;\r\n  }\r\n\r\n  /** Logic for determing the pension is for entrepreneur */\r\n  private get isYelCalculation() {\r\n    if (!this.calc) {\r\n      return false;\r\n    }\r\n    return this.calc.result?.responsibilities?.pensionCalculation == PensionCalculation.Entrepreneur;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiListItem, Avatar, Calculation, Dates,\r\n  EmploymentLogic,\r\n  EmploymentRelationTaxcard,\r\n  Iban,\r\n  InsuranceContract,\r\n  Overview, PensionContract, TaxCard2019Logic,\r\n  Taxcards, Texts,\r\n  WelcomeDataWorker,\r\n  WorkerListItem,\r\n  Workers\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  ReportsService,\r\n  SettingsService,\r\n  SessionService,\r\n  UiCrudHelpers,\r\n  UiHelpers,\r\n} from \"../../services\";\r\n\r\n/**\r\n * Provides methods for profiled Welcome messages to the end user.\r\n */\r\nexport class WelcomeController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"SessionService\",\r\n    \"Workers\",\r\n    \"SettingsService\",\r\n    \"$location\",\r\n    \"UiCrudHelpers\",\r\n    \"$rootScope\",\r\n    \"Taxcards\",\r\n    \"Overview\",\r\n    \"UiHelpers\",\r\n    \"ReportsService\",\r\n  ];\r\n\r\n  /**\r\n   * If set to true, the settings are handled by proxy:\r\n   * we do not ask the user to change the settings in\r\n   * the Welcome screen (mainly Pension or Insurance).\r\n   */\r\n  public settingsByProxy;\r\n\r\n  /** Worker home page UI properties */\r\n  public workerUI: {\r\n    isReady?: boolean,\r\n    /** If true, worker has added taxcard. */\r\n    taxCardAdded?: boolean,\r\n  } = {};\r\n\r\n  /** Welcome page (timeline) data forr the Worker role */\r\n  public workerDataNew: WelcomeDataWorker;\r\n\r\n  public workerList: WorkerListItem[] = [];\r\n\r\n\r\n  /** Start date for filtering list of calculations with status \"PaymentStarted\". Displayed on front page */\r\n  public paymentStartedWarningStartDate = Dates.getToday();\r\n  /** End date for filtering list of calculations with status \"PaymentStarted\". Displayed on front page */\r\n  public paymentStartedWarningEndDate =  Dates.add(this.paymentStartedWarningStartDate, -6, \"month\");\r\n\r\n  private workerListStatus: \"initial\" | \"loading\" | \"loaded\" = \"initial\";\r\n\r\n  private initialOwner: string;\r\n\r\n\r\n  /**\r\n   * Creates a new WelcomeController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private session: SessionService,\r\n    private workers: Workers,\r\n    private settingsService: SettingsService,\r\n    private $location: angular.ILocationService,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    private $rootScope: angular.IRootScopeService,\r\n    private taxcards: Taxcards,\r\n    private overview: Overview,\r\n    private uiHelpers: UiHelpers,\r\n    private reportsService: ReportsService,\r\n  ) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    this.loadWelcomeData();\r\n    this.session.subscribe(this.$rootScope, () => {\r\n      this.loadWelcomeData();\r\n    });\r\n  };\r\n\r\n\r\n  /**\r\n   * Gets a preview URL for the image.\r\n   * Currently only for a taxcard, but may later support other items.\r\n   */\r\n  // eslint-disable-next-line\r\n  public getPreviewUrl(item: ApiListItem) {\r\n    // Previews disabled for every item 10.6.2021 /MJ\r\n    return null;\r\n  }\r\n\r\n  /**\r\n   * Returns the url where to download the tax card\r\n   * @param taxCard Taxcard or if null, the current is used.\r\n   */\r\n  public getTaxcardDownloadUrl(taxCard): string {\r\n    return this.taxcards.getDownloadUrl(taxCard);\r\n  }\r\n\r\n  /**\r\n   * Moves the browser to create-new calculation screen\r\n   * @param employmentId Identifier for the Employment relation for which to create the calculation.\r\n   */\r\n  public createNewCalculationFor(employmentId: string) {\r\n    this.$location.path(\"/calc/details/\" + employmentId + \"/new-for-employment\");\r\n  }\r\n\r\n  /** Gets the current pension product or empty object */\r\n  public getPension(): PensionContract {\r\n    return this.settingsService.current?.calc.pensionContracts.find( (x) =>\r\n     Dates.isSameOrAfter(\"today\", x.startDate ?? \"1900-01-01\") &&\r\n     Dates.isBefore(\"today\", Dates.add(x.endDate ?? \"2100-01-01\", 1,\"day\"))) || {};\r\n  }\r\n\r\n  /** Gets the current insurance product or empty object */\r\n  public getInsurance(): InsuranceContract {\r\n    return this.settingsService.current?.calc.insuranceContracts.find( (x) =>\r\n     Dates.isSameOrAfter(\"today\", x.startDate ?? \"1900-01-01\") &&\r\n     Dates.isBefore(\"today\", Dates.add(x.endDate ?? \"2100-01-01\", 1,\"day\"))) || {};\r\n  }\r\n\r\n  /**\r\n   * Loads the welcome data from the server.\r\n   */\r\n  public loadWelcomeData() {\r\n    if (this.session.isSessionChecked && this.session.isAuthenticated) {\r\n      const owner = this.session.session.currentAccount.owner;\r\n      if (this.initialOwner != owner){\r\n        this.initialOwner = owner;\r\n        this.workerDataNew = undefined;\r\n        this.workerUI = {};\r\n        this.settingsByProxy = false;\r\n        this.workerList = [];\r\n        this.workerListStatus = \"initial\";\r\n\r\n        if (this.session.isInRole(\"person\")) {\r\n          this.loadWorkerData();\r\n        } else if (this.session.isInRole(\"company\")) {\r\n          this.loadCompanyData();\r\n        }\r\n      }\r\n    }\r\n    else {\r\n      this.initialOwner = null;\r\n      this.workerDataNew = undefined;\r\n      this.workerUI = {};\r\n      this.settingsByProxy = false;\r\n      this.workerList = [];\r\n      this.workerListStatus = \"initial\";\r\n    }\r\n  }\r\n\r\n  /** Loads the Worker role data and UI. */\r\n  public loadWorkerData() {\r\n    this.overview.getWelcomeDataWorker().then((result) => {\r\n      this.workerDataNew = result;\r\n      this.workerUI = {\r\n        isReady: true,\r\n        taxCardAdded: !!result.activeTaxcard,\r\n      };\r\n    });\r\n  }\r\n\r\n  /** Loads worker list initially */\r\n  public loadWorkers(): Promise<WorkerListItem[]> {\r\n    if (this.workerListStatus === \"loaded\") {\r\n      return Promise.resolve(this.workerList);\r\n    } else {\r\n      this.workerListStatus = \"loading\";\r\n      // Only fetch first 50 workers (first page). Selection should not be shown if more than 49 workers / next page.\r\n      return this.workers.getOData({}).then((data) => {\r\n        this.workerList = data.items;\r\n        this.workerListStatus = \"loaded\";\r\n        return this.workerList;\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Loads the welcome data from the server for Company role */\r\n  public loadCompanyData() {\r\n    // TODO\r\n  }\r\n\r\n  /**\r\n   * Gets the URL for a calculation pdf.\r\n   * If report has not been saved (ID is null), returns null.\r\n   * @param calc - Calculation. This method requires that the calculation has been saved.\r\n   * @param inline - if false, downloads the pdf file\r\n   * @returns Url for specified report\r\n   */\r\n  public getPdfUrl(calc: Calculation, inline = false) {\r\n    if (!calc) {\r\n      return null;\r\n    }\r\n\r\n    return this.reportsService.getPdfUrlForCalc(\"salarySlip\", calc.id, inline);\r\n  }\r\n\r\n  /**\r\n   * Gets the chart data for taxcard, labels, colors and other settings.\r\n   * Uses chartCache to avoid $digest loop.\r\n   */\r\n   public get taxcardChartData() {\r\n    if (!this.workerDataNew || !this.workerDataNew.activeTaxcard) {\r\n      return null;\r\n    }\r\n   if (!this.workerDataNew.activeTaxcard.card.incomeLimit){\r\n      return {config: this.uiHelpers.cache(this, \"pieChartV2\",\r\n      () => TaxCard2019Logic.getPieChartDataV2(this.workerDataNew.activeTaxcard),\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(this.workerDataNew.activeTaxcard)), limits:TaxCard2019Logic.getIncomeLimitInfo(this.workerDataNew.activeTaxcard)};\r\n    }\r\n    return {config: this.uiHelpers.cache(this, \"lineChartV2\",\r\n    () => TaxCard2019Logic.getMainChartV2(this.workerDataNew.activeTaxcard),\r\n    () => TaxCard2019Logic.getIncomeLimitInfo(this.workerDataNew.activeTaxcard)), limits:TaxCard2019Logic.getIncomeLimitInfo(this.workerDataNew.activeTaxcard)};\r\n  }\r\n\r\n  /**\r\n   * Gets the chart data for taxcard, labels, colors and other settings.\r\n   * Uses chartCache to avoid $digest loop.\r\n   */\r\n  public get taxcardMobileChartData() {\r\n    if (!this.workerDataNew || !this.workerDataNew.activeTaxcard) {\r\n      return null;\r\n    }\r\n    return this.uiHelpers.cache(this, \"lineChartMobileV2\",\r\n      () => {\r\n       const data = TaxCard2019Logic.getMainChartV2(this.workerDataNew.activeTaxcard);\r\n       data.options.plugins.legend.display = false;\r\n       // TODO ? data.options.scales.yAxes.display = false;\r\n       return data;\r\n      },\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(this.workerDataNew.activeTaxcard));\r\n  }\r\n\r\n  /** Calls the Worker wizard and if a Worker is added, starts a calculation for that worker. */\r\n  public launchEmploymentWizard() {\r\n    this.uiCrudHelpers.createNewEmployment().then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.createNewCalculationFor(result.item.id);\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Gets the flags that indicate which tutorials to show. */\r\n  public get tutorials(): {\r\n    /** If true, shows info box that the site is runnin in anonymous mode. */\r\n    showAnon: boolean,\r\n    /** If true, should direct the user to create the first Worker */\r\n    showAddWorker: boolean,\r\n    /** If true, should direct user to create a new calculation.  */\r\n    showAddCalculation: boolean,\r\n    /** If true, should ask the user for digital signature. */\r\n    showSign: boolean,\r\n    /** If true, should ask the user to fill in the Pension contract information. */\r\n    showPension: boolean,\r\n    /** If true, should ask the user to fill in the Accident Insurance contract information. */\r\n    showInsurance: boolean,\r\n    /** If true, should promote Payroll feature. */\r\n    showTryPayroll: boolean,\r\n    /** If true, should promote new features. */\r\n    showNewFeatures: boolean\r\n  } {\r\n    const result = {\r\n      showAnon: false,\r\n      showAddWorker: false,\r\n      showAddCalculation: true,\r\n      showSign: false,\r\n      showPension: false,\r\n      showInsurance: false,\r\n      showTryPayroll: false,\r\n      showNewFeatures: false\r\n    };\r\n    if (!this.session.isSessionChecked) {\r\n      return result;\r\n    }\r\n    if (!this.session.isAuthenticated) {\r\n      result.showAnon = true;\r\n      return result;\r\n    }\r\n    if (!this.settingsByProxy) {\r\n      if (!this.session.checkAccountVerification()) {\r\n        result.showSign = true;\r\n      }\r\n      result.showPension = this.settingsService.current?.calc.pensionContracts.length == 0 || this.settingsService.current?.calc.pensionContracts.every( (x) => !x.company);\r\n      result.showInsurance = this.settingsService.current?.calc.pensionContracts.length == 0 || this.settingsService.current?.calc.insuranceContracts.every( (x) => !x.company);\r\n    }\r\n    switch (this.workerListStatus) {\r\n      case \"loaded\":\r\n        if (this.workerList.length === 0) {\r\n          result.showAddWorker = true;\r\n          return result;\r\n        }\r\n        if (this.workerList.length > 45) {\r\n          result.showAddCalculation = false;\r\n          return result;\r\n        }\r\n        break;\r\n      case \"loading\":\r\n        return result;\r\n      case \"initial\":\r\n        this.loadWorkers();\r\n        return result;\r\n    }\r\n    result.showAddCalculation = true;\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Returns system alert html.\r\n   */\r\n  public get systemAlertHtml(): string {\r\n    if (!this.session) {\r\n      return null;\r\n    }\r\n\r\n    const userSession = this.session.getSession();\r\n    if (!userSession) {\r\n      return null;\r\n    }\r\n\r\n    const html = userSession.systemAlertHtml;\r\n    if (!html) {\r\n      return null;\r\n    }\r\n    return html;\r\n  }\r\n\r\n  /**\r\n   * Returns true if system alert exists.\r\n   */\r\n  public get hasSystemAlert(): boolean {\r\n    return !!this.systemAlertHtml;\r\n  }\r\n\r\n  /**\r\n   * Filters preloaded workers.\r\n   * Avatar values are formatted and ID is employment ID insteead of worker ID.\r\n   */\r\n  public filterWorkers = (searchString: string): Avatar[] => {\r\n    if (!searchString) {\r\n      const allResult = this.workerList\r\n        .slice(0, 30).map(this.getAvatar);\r\n      return allResult;\r\n    }\r\n    searchString = (searchString || \"\").trim().toLowerCase();\r\n    const result = this.workerList\r\n      .filter((w) =>\r\n        (w.otherPartyInfo.avatar.displayName || \"\").toLowerCase().indexOf(searchString) >= 0 ||\r\n        (w.otherPartyInfo.avatar.sortableName || \"\").toLowerCase().indexOf(searchString) >= 0 ||\r\n        (w.otherPartyInfo.telephone || \"\").toLowerCase().indexOf(searchString) >= 0 ||\r\n        (w.otherPartyInfo.email || \"\").toLowerCase().indexOf(searchString) >= 0 ||\r\n        (w.id || \"\").toLowerCase().indexOf(searchString) === 0 ||\r\n        (w.otherPartyInfo.officialId || \"\").toLowerCase().indexOf(searchString) === 0)\r\n      .map(this.getAvatar);\r\n    return result.length > 0 ? result.slice(0, 30) : [];\r\n  };\r\n\r\n  /** Gets the display name for the selected worker. */\r\n  public getWorkerName = (avatarId: string): string => {\r\n    for (const worker of this.workerList) {\r\n      if (avatarId === worker.otherId) {\r\n        return Texts.escapeHtml(this.getAvatar(worker).displayName);\r\n      }\r\n    }\r\n    return null;\r\n  };\r\n\r\n  /**\r\n   * Searches all workers and checks if manual/auto taxcard is enabled\r\n   */\r\n  public showAutoTaxcardInfobox(): boolean {\r\n    if(this.workerList.length) {\r\n      return !this.workerList.some(x => x.data.taxcard === EmploymentRelationTaxcard.Auto || x.data.taxcard === EmploymentRelationTaxcard.Manual);\r\n    }\r\n  }\r\n\r\n\r\n  private getAvatar = (worker: WorkerListItem): Avatar => {\r\n    const result: Avatar = Object.assign({}, worker.otherPartyInfo.avatar);\r\n    (result as any).displayId =\r\n      ((worker.id || \"\").startsWith(\"FI\") ? Iban.formatIban(worker.id) + \" / \" : \"\")\r\n      + (worker.otherPartyInfo.officialId ? worker.otherPartyInfo.officialId : \"-\")\r\n      ;\r\n    result.displayName = Texts.escapeHtml(result.displayName);\r\n    result.description = Texts.escapeHtml(EmploymentLogic.getDescription(worker.otherPartyInfo, worker?.data.type, worker?.data.pensionCalculation));\r\n    result.id = worker.id;\r\n    return result;\r\n  };\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { FormGroupLabelType } from \"./FormGroupLabelType\";\r\n\r\n/**\r\n * Base controller for form control groups (label, input, validation errors etc.).\r\n */\r\nexport class InputBase<T> implements angular.IController {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public static crudBindings = {\r\n\r\n    /** Name of the input - also used as id. */\r\n    name: \"@\",\r\n\r\n    /** Label for the control */\r\n    label: \"@\",\r\n\r\n    /**\r\n     * @deprecated Use \"require\" instead:\r\n     * This attribute overlaps with required/ng-required directive, which produces unexpected results.\r\n     */\r\n    required: \"@\",\r\n\r\n    /** If true the field is required (form validation) */\r\n    require: \"<\",\r\n\r\n    /**\r\n     * Expression for read-only display of the input control\r\n     * This is visualized in a different way than readonly: The input is not shown and display is more compact.\r\n     */\r\n    readOnly: \"<\",\r\n\r\n    /** Expression for ng-readonly of the input */\r\n    readonly: \"<\",\r\n\r\n    /** Expression for ng-disabled of the input */\r\n    disabled: \"<\",\r\n\r\n    /**\r\n     * Positioning of the label of form-control.\r\n     * Supported values are \"horizontal\" (default), \"no-label\", \"plain\" and \"basic\".\r\n     * See FormGourpLabelType for details.\r\n     */\r\n    labelType: \"@\",\r\n\r\n    /**\r\n     * Label columns expressed as Bootstrap grid columns. Supports multiple classes (e.g. \"col-xs-4 col-sm-2\").\r\n     * Default is 'col-sm-4' for label-type: 'horizontal' and 'col-sm-12' for label-type: 'no-label'.\r\n     * Other label-types do not have column classes at the moment.\r\n     */\r\n    labelCols: \"@\",\r\n\r\n    /** Placeholder text */\r\n    placeholder: \"@\",\r\n\r\n    /**\r\n     * TooltipHtml adds an info button after the input which opens a uib-popover-html.\r\n     */\r\n    tooltipHtml: \"@\",\r\n\r\n    /** Options for ui.bootstrap.popover */\r\n    tooltipPlacement: \"@\",\r\n\r\n    /**\r\n     * Disables the default validation error message.\r\n     * Use this if you want to create custom error messages in the UI.\r\n     */\r\n    disableValidationErrors: \"<\",\r\n\r\n    /**\r\n     * Style of the input.\r\n     * Supports empty or 'openClose'\r\n     */\r\n     inputMode: \"@\",\r\n  };\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Label for the control. If not set, it is derived from name. */\r\n  public label: string;\r\n\r\n  /**\r\n   * Positioning of the label of form-control.\r\n   * Supported values are \"horizontal\" (default), \"no-label\" | \"plain\" | \"basic\" | \"empty-label\" | \"inline\".\r\n   * See FormGourpLabelType for details.\r\n   */\r\n  public labelType: FormGroupLabelType;\r\n\r\n  /** The model that is bound to the input */\r\n  public model: angular.INgModelController;\r\n\r\n  /** Form controller, if available */\r\n  public form: angular.IFormController;\r\n\r\n  /** The value of the input */\r\n  public value: T;\r\n\r\n  /** Form control name */\r\n  public name: string;\r\n\r\n  /** List of validation error texts (typically language version keys that should be translated). */\r\n  public validationErrors: string[] = [];\r\n\r\n  /** Placeholder text */\r\n  public placeholder: string;\r\n\r\n  /**\r\n   * @deprecated Use \"require\" instead:\r\n   * This attribute overlaps with required/ng-required directive, which produces unexpected results.\r\n   */\r\n  public required: string;\r\n\r\n  /**\r\n   * If true, displays the control as read-only div instead of the input control.\r\n   * This \"read-only\" attribute is visualized in a different way than standard html \"readonly\" (ng-readonly):\r\n   * The input is not shown and display is more compact.\r\n   * Also note, that you may change the same read-only for the form using readonly / ng-readonly attribute.\r\n   * @example\r\n   * ```html\r\n   * <form name=\"foo\" ng-readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <form name=\"foo\" readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <salaxy-input name=\"input1\" read-only=\"true\"></salaxy-input>\r\n   * ```\r\n   */\r\n  public readOnly: boolean;\r\n\r\n  /** If true, disabled is set on the input with ng-disabled */\r\n  public disabled: boolean;\r\n\r\n  /** Placement of tooltip button */\r\n  public tooltipPlacement: string;\r\n\r\n  /** Defines HTML for tooltip button */\r\n  public tooltipHtml: string;\r\n\r\n  /**\r\n   * Style of the input.\r\n   * If null or empty, displays normal input.\r\n   * - \"openeClose\" shows readOnly-like input with toggle button to open the field for editing.\r\n   * Recommended to use when only one or few fields of the form are expected to be edited.\r\n   */\r\n  public inputMode: \"\" | \"openClose\";\r\n\r\n  private _onInitValue = this.onInitValue;\r\n\r\n  private requirePendingUpdate: boolean | undefined;\r\n\r\n\r\n  /**\r\n   * Creates a new InputController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    /* */\r\n  }\r\n\r\n  /**\r\n   * Set the values and defaults on init.\r\n   * When overridding at derived classes, do your own stuff first and then call this method\r\n   * because this method calls validate() at the end.\r\n   */\r\n  public $onInit() {\r\n    if(this.tooltipHtml && !this.tooltipPlacement){\r\n      this.tooltipPlacement = \"top\";\r\n    }\r\n    if (!this.name) {\r\n      throw new Error(`Property 'name' is required for Salaxy form controls (label: ${this.label}).`);\r\n    }\r\n    if (this.name && this.label == null) {\r\n      this.label = this.name;\r\n    }\r\n    if (this.requirePendingUpdate) {\r\n      this.require = true;\r\n      this.requirePendingUpdate = undefined;\r\n    }\r\n    this.model.$render = () => {\r\n      this.value = this.model.$viewValue;\r\n      if (this._onInitValue) {\r\n        this._onInitValue();\r\n        this._onInitValue = null;\r\n      }\r\n    };\r\n    this.validate();\r\n  }\r\n\r\n  /** Gets or sets the presence of the required validator in the underlying model. */\r\n  public get require(): boolean {\r\n    return !!this.model?.$validators.required;\r\n  }\r\n  public set require(value: boolean) {\r\n    if (!this.model) {\r\n      this.requirePendingUpdate = value;\r\n      return;\r\n    }\r\n    const hasRequiredValidator = !!this.model.$validators.required;\r\n    if (value && !hasRequiredValidator) {\r\n      this.model.$validators.required = (modelValue, viewValue) => {\r\n        return !this.model.$isEmpty(viewValue);\r\n      };\r\n    } else if (!value && hasRequiredValidator) {\r\n      delete this.model.$validators.required;\r\n    }\r\n  }\r\n\r\n  /** Gets the readonly value either from the controller or from the form */\r\n  protected getReadOnly(): boolean {\r\n    // This readOnly can be true, false or undefined\r\n    const readOnlyValue = (this.readOnly + \"\").trim().toLowerCase();\r\n    if (readOnlyValue === \"true\" || readOnlyValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (readOnlyValue === \"false\" || readOnlyValue === \"0\") {\r\n      return false;\r\n    }\r\n    const readOnlyFormValue = !!this?.form?.$$element[0]?.attributes?.readonly;\r\n    if (readOnlyFormValue) {\r\n      return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  /** Gets the disabled value either from the controller or from the form */\r\n  protected getDisabled(): boolean {\r\n    if (this.disabled) {\r\n      return true;\r\n    }\r\n    if (this.form && this.form.$$element && this.form.$$element[0]) {\r\n      return !!this.form.$$element[0].attributes.disabled;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Returns the placeholder text: We will probably add stuff about validation here if not explicitly set. */\r\n  protected getPlaceholder() {\r\n    return this.placeholder;\r\n  }\r\n\r\n  /** Gets the tooltip HTML with necessary escape. */\r\n  protected getToolTipHtml() {\r\n    // TODO: Add escaping if necessary.\r\n    return this.tooltipHtml;\r\n  }\r\n\r\n  /** On change of the value, do preventive operations and set value to model. */\r\n  protected onChange() {\r\n    this.model.$setViewValue(this.value);\r\n    this.validate();\r\n  }\r\n\r\n  /** Do validations. Automatically called on onInit() and onChange() */\r\n  protected validate() {\r\n    const validationErrors = [];\r\n    for (const validationErrorKey in this.model.$error) {\r\n      if (Objects.has(this.model.$error, validationErrorKey) && validationErrorKey !== \"parse\") {\r\n        validationErrors.push(\"SALAXY.VALIDATION.ValidationErrors.\" + validationErrorKey);\r\n      }\r\n    }\r\n    this.modifyValidationErrors(validationErrors, this.validationErrors);\r\n    if (this.validationErrors.length > 0) {\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n\r\n  /** Called after initial value assignment. Called only once.  */\r\n  protected onInitValue() {\r\n    // empty\r\n  }\r\n\r\n  private modifyValidationErrors(source: string[], target: string[]) {\r\n    // check if source values differ from target\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    // remove values\r\n    target.splice(0, target.length);\r\n    // add values\r\n    target.push(...source);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, PaymentChannel, SalaryDateLogic } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"../../services\";\r\n\r\n/**\r\n * Controller for datepicker control.\r\n */\r\nexport class DatepickerController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** Form controller, if available */\r\n  public form: angular.IFormController;\r\n  /** Label for the control */\r\n  public label: string;\r\n\r\n  /** The model that is bound to the input */\r\n  public model: any;\r\n\r\n  /** The value of the ui.bootstrap.datepicker */\r\n  public dtValue: Date;\r\n\r\n  /**\r\n   * Preset algorithms for enabled/disabled dates.\r\n   * Currently supported: \"salary\" for next possible salary date and \"next-weekday\" for next weekday / banking day.\r\n   * If set as \"disable-function\", you should set the disable-function too.\r\n   */\r\n  public dateDisabled: \"salary\" | \"next-weekday\" | \"disable-function\" | null;\r\n\r\n  /** Disable function for date. If set, date-disabled is ignored. */\r\n  public disableFunction:  ((date: any) => boolean)  | null;\r\n\r\n  /** Payment channel. This affects which dates are disabled in the salary date selection. */\r\n  public paymentChannel: PaymentChannel;\r\n\r\n  /** Boolean indicating if the net salary payment to the worker is zero. */\r\n  public zeroPayment: boolean;\r\n\r\n  /** Form control name */\r\n  public name: string;\r\n\r\n  /** Validation error text */\r\n  public validationError: string;\r\n\r\n  /** Options for ui.bootstrap.datepicker */\r\n  public datepickerOptions: any;\r\n\r\n  /** Defines HTML for tooltip button */\r\n  public tooltipHtml: string;\r\n\r\n  /** Placement of tooltip */\r\n  public tooltipPlacement: string;\r\n\r\n  /**\r\n   * If true, displays the control as read-only div instead of the input control.\r\n   * This \"read-only\" attribute is visualized in a different way than standard html \"readonly\" (ng-readonly):\r\n   * The input is not shown and display is more compact.\r\n   * Also note, that you may change the same read-only for the form using readonly / ng-readonly attribute.\r\n   * @example\r\n   * ```html\r\n   * <form name=\"foo\" ng-readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <form name=\"foo\" readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <salaxy-input name=\"input1\" read-only=\"true\"></salaxy-input>\r\n   */\r\n  public readOnly: boolean;\r\n\r\n  /**\r\n   * @deprecated Use \"require\" instead:\r\n   * This attribute overlaps with required/ng-required directive, which produces unexpected results.\r\n   */\r\n  public required: string;\r\n\r\n  private requirePendingUpdate: boolean | undefined;\r\n  private _minDate: string;\r\n  private _maxDate: string;\r\n\r\n  constructor(private sessionService: SessionService) {\r\n  }\r\n\r\n  /** Gets or sets the value as ISO formatted date string. */\r\n  public get value() {\r\n    return Dates.asDate(this.dtValue);\r\n  }\r\n  public set value(val) {\r\n    this.dtValue = Dates.asJSDate(val);\r\n    this.onChange();\r\n  }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    if (this.name && !this.label) {\r\n      this.label = this.name;\r\n    }\r\n    if(!this.tooltipPlacement){\r\n      this.tooltipPlacement = \"top\";\r\n    }\r\n    this.model.$render = () => {\r\n      this.dtValue = Dates.asJSDate(this.model.$viewValue);\r\n    };\r\n    this.refreshOptions();\r\n    this.validate();\r\n\r\n  }\r\n\r\n  /**\r\n   * Minimum available date.\r\n   * Bindable and ISO string version of the datepicker-options.minDate.\r\n   * Currently not supported together with dateDisabled filters.\r\n   */\r\n  public get minDate(): string {\r\n    return this._minDate;\r\n  }\r\n  public set minDate(value: string) {\r\n    this._minDate = Dates.asDate(value);\r\n    this.datepickerOptions = this.datepickerOptions || {};\r\n    this.datepickerOptions.minDate = Dates.asJSDate(this._minDate);\r\n  }\r\n\r\n  /**\r\n   * Maximum available date.\r\n   * Bindable and ISO string version of the datepicker-options.maxDate.\r\n   * Currently not supported together with dateDisabled filters.\r\n   */\r\n  public get maxDate(): string {\r\n    return this._maxDate;\r\n  }\r\n  public set maxDate(value: string) {\r\n    this._maxDate = Dates.asDate(value);\r\n    this.datepickerOptions = this.datepickerOptions || {};\r\n    this.datepickerOptions.maxDate = Dates.asJSDate(this._maxDate);\r\n  }\r\n\r\n  /** Gets or sets the presence of the required validator in the underlying model. */\r\n  public get require(): boolean {\r\n    return !!this.model?.$validators.required;\r\n  }\r\n  public set require(value: boolean) {\r\n    if (!this.model) {\r\n      this.requirePendingUpdate = value;\r\n      return;\r\n    }\r\n    const hasRequiredValidator = !!this.model.$validators.required;\r\n    if (value && !hasRequiredValidator) {\r\n      this.model.$validators.required = (modelValue, viewValue) => {\r\n        return !this.model.$isEmpty(viewValue);\r\n      };\r\n    } else if (!value && hasRequiredValidator) {\r\n      delete this.model.$validators.required;\r\n    }\r\n  }\r\n\r\n  /** On change of the value, do preventive operations and set value to model. */\r\n  public onChange() {\r\n    this.model.$setViewValue(this.value);\r\n    this.validate();\r\n  }\r\n\r\n  /** Do validations. Automatically called on onInit() and onChange() */\r\n  public validate() {\r\n    if (Dates.isValidDateTime(this.value)) {\r\n      this.validationError = \"\";\r\n      return true;\r\n    }\r\n    this.validationError = \"SALAXY.NG1.DatepickerComponent.validationErrorDefault\";\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Refresh picker options\r\n   */\r\n  protected refreshOptions() {\r\n    if (!this.datepickerOptions) {\r\n      this.datepickerOptions = {};\r\n    }\r\n    if (this.dateDisabled) {\r\n      const role =  this.sessionService.isInRole(\"pro\") ? \"pro\" :\r\n                this.sessionService.isInRole(\"admin\") ? \"admin\" : null;\r\n      switch (this.dateDisabled) {\r\n        case \"next-weekday\":\r\n          this.datepickerOptions.minDate = Dates.asJSDate(Dates.asDate(\"today\"));\r\n          this.datepickerOptions.dateDisabled = (data: any) => {\r\n            const date = data.date;\r\n            const mode = data.mode;\r\n            return (mode === \"day\" || !mode) && (Dates.asDate(date) < Dates.addWorkdays(\"today\", 1) || !Dates.isWorkday(date));\r\n          };\r\n          break;\r\n        case \"salary\":\r\n        default:\r\n          this.datepickerOptions.minDate = Dates.asJSDate(Dates.add(Dates.asDate(\"today\"), -1, \"year\"));\r\n          if (this.disableFunction) {\r\n            this.datepickerOptions.dateDisabled = (data: any) => {\r\n              const date = data.date;\r\n              const mode = data.mode;\r\n              return (mode === \"day\" || !mode) && this.disableFunction(date);\r\n            };\r\n          }\r\n          else\r\n          {\r\n            this.datepickerOptions.dateDisabled = (data: any) => {\r\n              const date = data.date;\r\n              const mode = data.mode;\r\n              return (mode === \"day\" || !mode) && (!SalaryDateLogic.isValidSalaryDate(date, null, null, true, this.paymentChannel, this.zeroPayment, role));\r\n            };\r\n          }\r\n          break;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Gets the readonly value either from the controller or from the form */\r\n  protected getReadOnly(): boolean {\r\n    // This readOnly can be true, false or undefined\r\n    const readOnlyValue = (this.readOnly + \"\").trim().toLowerCase();\r\n    if (readOnlyValue === \"true\" || readOnlyValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (readOnlyValue === \"false\" || readOnlyValue === \"0\") {\r\n      return false;\r\n    }\r\n    const readOnlyFormValue = !!this?.form?.$$element[0]?.attributes?.readonly;\r\n    if (readOnlyFormValue) {\r\n      return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n}\r\n","import { DatepickerController } from \"./DatepickerController\";\r\nimport { SessionService } from \"../../services\";\r\n\r\n/**\r\n * Controller for datepicker popup control.\r\n */\r\nexport class DatepickerPopupController extends DatepickerController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"SessionService\"];\r\n\r\n    /** Options for ui.bootstrap.datepicker */\r\n    public popupPlacement = \"bottom\";\r\n\r\n    /** Date format in text input. Default is d.M.yyyy */\r\n    public format: string;\r\n\r\n    /**\r\n     * If set to true, sets datepicker-append-to-body to false.\r\n     * By default we set it to true in Salaxy framework,\r\n     * but you may want to set it back to false in e.g. Modal dialogs.\r\n     */\r\n    public appendInline: boolean;\r\n\r\n    /** Popup control state. */\r\n    public popup = {\r\n        opened: false,\r\n    };\r\n\r\n    constructor(sessionService: SessionService) {\r\n      super(sessionService);\r\n    }\r\n\r\n\r\n\r\n    /** Open popup. */\r\n    public open() {\r\n      this.refreshOptions();\r\n      this.popup.opened = true;\r\n    }\r\n\r\n     /** Gets the tooltip HTML with necessary escape. */\r\n  protected getToolTipHtml() {\r\n    // TODO: Add escaping if necessary.\r\n    return this.tooltipHtml;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { DateRange, Dates, Objects, Translations } from \"@salaxy/core\";\r\n\r\n/**\r\n * Provides a user interface for picking up a date range\r\n * and optionally specifying also the number of working days within that range.\r\n */\r\nexport class DateRangeController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Label for the control */\r\n  public label: string;\r\n\r\n  /** Label for the scondary input. Translation is attempted. Default is SALAXY.NG1.DateRange.labelDaysCount.  */\r\n  public labelDaysCount: string;\r\n\r\n  /** The model that is bound to the input */\r\n  public model: angular.INgModelController;\r\n\r\n  /**\r\n   * The selection mode is either:\r\n   *\r\n   * - \"range\" for (default) calendar control with start and end.\r\n   * - \"multiple\" for selecting multiple individual dates from a calendar control\r\n   * - \"calc\" for period selection that is optimized for salary calculation (months, 2 weeks, 1/2 months etc.)\r\n   */\r\n  public mode: \"range\" | \"multiple\" | \"calc\";\r\n\r\n  /**\r\n   * Minimum available date.\r\n   * Bindable and ISO string version of the datepicker-options.minDate.\r\n   */\r\n  public minDate: string;\r\n\r\n  /** Form controller, if available */\r\n  public form: angular.IFormController;\r\n\r\n  /**\r\n   * Maximum available date.\r\n   * Bindable and ISO string version of the datepicker-options.maxDate.\r\n   */\r\n  public maxDate: string;\r\n\r\n  /** If there is a validation error in period start, it is added here. */\r\n  public periodStartDateError = null;\r\n\r\n  /**\r\n   * If true, displays the control as read-only div instead of the input control.\r\n   * This \"read-only\" attribute is visualized in a different way than standard html \"readonly\" (ng-readonly):\r\n   * The input is not shown and display is more compact.\r\n   * Also note, that you may change the same read-only for the form using readonly / ng-readonly attribute.\r\n   * @example\r\n   * ```html\r\n   * <form name=\"foo\" ng-readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <form name=\"foo\" readonly=\"true\">\r\n   * <!-- .... or plain HTML ... -->\r\n   * <salaxy-input name=\"input1\" read-only=\"true\"></salaxy-input>\r\n   */\r\n  public readOnly: boolean;\r\n\r\n  /**\r\n   * Fires an event when the model is changing: Any of the values specific to the model are changing: start, end or daysCount.\r\n   * This should typically used instead of ng-change because ng-change will only fire if the object reference changes.\r\n   * On-change fires when dates or day count changes and this is typically what you are looking for.\r\n   * @example <salaxy-date-range ng-model=\"$ctrl.dateRange\" on-change=\"$ctrl.dateRangeChange(value)\"></salaxy-date-range>\r\n   */\r\n  public onChange: (eventData: {\r\n    /** The changed date range. */\r\n    value: DateRange,\r\n  }) => void;\r\n\r\n  /**\r\n   * Gets or sets the internal value of the complex object.\r\n   */\r\n  public get value(): {\r\n    /** Dately value for start date. */\r\n    start?: string,\r\n     /** Dately value for end date. */\r\n    end?: string,\r\n    /** Boolean indicating whether the end date has been explictly set: end date has been selected and is not the same as the start date. */\r\n    isEndExplicit?: boolean,\r\n    /** Number of days in the range. */\r\n    daysCount?: number,\r\n    /** Array of selected days in the range. */\r\n    days?: string[],\r\n    /** Latest selected date. */\r\n    latest?: string,\r\n    /** Formatted presentation of  range. */\r\n    formattedRange?: string,\r\n  } {\r\n    return this._value;\r\n  }\r\n  public set value(val) {\r\n    this._value = val;\r\n    this.setModelValue();\r\n  }\r\n\r\n  /** User interface shortcuts for period selection */\r\n  public periodShortcuts: {\r\n    /** Text for current month. */\r\n    monthCurrent: string,\r\n    /** Text for last month. */\r\n    monthLast: string,\r\n    /** Text for other month. */\r\n    monthOther: string,\r\n    // monthMulti: \"Monta kuukautta\",\r\n    /** Text for two weeks. */\r\n    weeks2: string,\r\n    /** Text for half a month */\r\n    monthHalf: string,\r\n    /** Text for other period. */\r\n    other: string,\r\n  };\r\n\r\n  /** Form control name */\r\n  public name: string;\r\n\r\n  /** If true, the input value is required */\r\n  public require: boolean;\r\n\r\n  /**\r\n   * Options for ui.bootstrap.datepicker\r\n   * Note that if you use customClass, you need to handle the formatting of the selected range.\r\n   * See getDayClass().\r\n   * Also note that this value is not watched, it is read only once when the options are first needed-\r\n   */\r\n  public datepickerOptions: any;\r\n\r\n  private internalOptions: any;\r\n\r\n  /** When only first selection is done in Range, we set the minimum value here. */\r\n  private tempMinDateForRangeSelection: Date;\r\n\r\n  private _value;\r\n\r\n  private _periodStartDate;\r\n\r\n  constructor() { /**/ }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    const currentMonth = Dates.getMonth(Dates.getToday());\r\n    this.periodShortcuts = {\r\n      monthCurrent: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth}.label`),\r\n      monthLast: Translations.get(`SALAXY.ENUM.CalendarMonth.month${currentMonth === 1 ? 12 : (currentMonth - 1)}.label`),\r\n      monthOther: Translations.get(\"SALAXY.NG1.DateRange.otherMonth\"),\r\n      // monthMulti: \"Monta kuukautta\",\r\n      weeks2: Translations.get(\"SALAXY.UI_Terms.week2\"),\r\n      monthHalf: Translations.get(\"SALAXY.UI_Terms.monthHalf\"),\r\n      other: Translations.get(\"SALAXY.UI_Terms.otherPeriod\"),\r\n    };\r\n    this.model.$render = () => {\r\n      const modelValue = this.model.$viewValue;\r\n      if (modelValue) {\r\n        if (modelValue.start) {\r\n          modelValue.latest = modelValue.start;\r\n          modelValue.formattedRange = Dates.getFormattedRange(modelValue.start, modelValue.end);\r\n        }\r\n        if (modelValue.end) {\r\n          modelValue.latest = modelValue.end;\r\n          modelValue.isEndExplicit = true;\r\n        }\r\n        this._value = modelValue; // Update the internal model without firing any events.\r\n        this._periodStartDate = Dates.format(modelValue.start, \"D.M.\", null);\r\n      }\r\n    };\r\n  }\r\n\r\n  /** HACK: Temporary shortcut peiod setting. Needs go-through / refactoring. */\r\n  public get dateRange(): DateRange {\r\n    return this.value;\r\n  }\r\n  public set dateRange(value: DateRange) {\r\n    (value as any).isEndExplicit = true;\r\n    (value as any).latest = value.end;\r\n    this.value = value;\r\n  }\r\n\r\n  /**\r\n   * This is the latest selection in the Datepicker component.\r\n   * When in mode=range: First it sets the value start, then end and then again start (and sets end to null).\r\n   * When in mode=multiple: Sets the values on or off in the array.\r\n   */\r\n  public get latestDateSelection() {\r\n    return (this.value || {}).latest;\r\n  }\r\n  public set latestDateSelection(newvalue) {\r\n    const value = this.value || {};\r\n    newvalue = Dates.asDate(newvalue);\r\n    value.latest = newvalue;\r\n    if (!newvalue) {\r\n      // Indicates failure in parsing. Datepicker component should not return null.\r\n      return;\r\n    }\r\n    if (this.mode === \"multiple\") {\r\n      if (value.days && value.days.indexOf(value.latest) > -1) {\r\n        value.days = value.days.filter((x) => x !== value.latest).sort();\r\n      } else {\r\n        if (!value.days) {\r\n          value.days = [];\r\n        }\r\n        value.days.push(value.latest);\r\n        value.days = value.days.sort();\r\n      }\r\n      value.daysCount = value.days.length;\r\n    } else {\r\n      // mode=range - Used to be the only supported functionality.\r\n      if (value.start && !value.isEndExplicit) {\r\n        value.end = value.latest;\r\n        value.isEndExplicit = true;\r\n        this.tempMinDateForRangeSelection = null;\r\n      } else {\r\n        value.start = newvalue;\r\n        value.end = newvalue;\r\n        value.isEndExplicit = false;\r\n        this.tempMinDateForRangeSelection = Dates.asJSDate(newvalue);\r\n      }\r\n      value.daysCount = Dates.getWorkdays(value.start, value.end).length;\r\n      value.formattedRange = Dates.getFormattedRange(value.start, value.end);\r\n    }\r\n    this.setModelValue();\r\n  }\r\n\r\n  /** Gets or sets the period start date */\r\n  public get periodStartDate(): string {\r\n\r\n    return this._periodStartDate;\r\n  }\r\n  public set periodStartDate(value: string) {\r\n\r\n    this._periodStartDate = value;\r\n    const parts = (value || \"\").split(\".\");\r\n    if (parts.length < 2 || parts.length > 3) {\r\n      this.periodStartDateError = Translations.get(\"SALAXY.NG1.DateRange.periodStartDateError\");\r\n      return;\r\n    }\r\n    let year = (parts.length === 3) ? Number((parts[2] || \"\").trim()) : null;\r\n    if (!year || year < 2019 || year > 2100) {\r\n      year = Number(this.dateRange.start.substr(0, 4));\r\n    }\r\n    const date = Dates.getDate(year, Number(parts[1]), Number(parts[0]));\r\n    if (date) {\r\n      this.periodStartDateError = null;\r\n      switch (this.periodShortcut) {\r\n        case \"monthCurrent\":\r\n        case \"monthLast\":\r\n        case \"monthOther\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,1,\"month\"),-1, \"day\"));\r\n          break;\r\n        case \"weeks2\":\r\n          this.dateRange = Dates.getDateRange(date, Dates.add(Dates.add(date,2,\"week\"),-1, \"day\"));\r\n          break;\r\n        case \"monthHalf\":\r\n          if (Dates.getDay(date) === 15 || Dates.getDay(date) === 16 ) {\r\n            this.dateRange = Dates.getDateRange(date, Dates.startEnd(date,\"end-month\"));\r\n          } else {\r\n            this.dateRange = Dates.getDateRange(date, Dates.add(date,14, \"day\"));\r\n          }\r\n          break;\r\n        case \"other\":\r\n          this.dateRange = Dates.getDateRange(date, date);\r\n          break;\r\n    }\r\n      this.dateRangeChange(true);\r\n    } else {\r\n      this.periodStartDateError = `${value}` + Translations.get(\"SALAXY.NG1.DateRange.periodStartDateError2\");\r\n    }\r\n  }\r\n\r\n  /** Gets the user interface shortcut for the period. */\r\n  public get periodShortcut(): string {\r\n    if (!this.dateRange || !this.dateRange.start || !this.dateRange.end) {\r\n      return null;\r\n    }\r\n    if (this.dateRange.start === Dates.getDate(\"today\", \"today\", 1)\r\n      && this.dateRange.end === Dates.startEnd(\"today\",\"end-month\")) {\r\n\r\n        return \"monthCurrent\";\r\n    }\r\n    if (this.dateRange.start === Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1, \"month\")\r\n      && this.dateRange.end === Dates.startEnd(Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1, \"month\"),\"end-month\")) {\r\n      return \"monthLast\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start,1, \"month\"),-1, \"day\")) {\r\n      return \"monthOther\";\r\n    }\r\n    if (this.dateRange.end === Dates.add(Dates.add(this.dateRange.start,2, \"week\"),-1, \"day\")) {\r\n      return \"weeks2\";\r\n\r\n    }\r\n\r\n    // if the range is 15 (14) days or\r\n    // starts 15th or 16th and ends month end\r\n    if ((Dates.getDuration(this.dateRange.start, this.dateRange.end ).days() === 14)\r\n      || (Dates.getDay(this.dateRange.start) === 15 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))\r\n      || (Dates.getDay(this.dateRange.start) === 16 && this.dateRange.end === Dates.startEnd(this.dateRange.start,\"end-month\"))) {\r\n        return \"monthHalf\";\r\n    }\r\n\r\n    // TODO: Potentially add other options.\r\n    return \"other\";\r\n  }\r\n  public set periodShortcut(value: string) {\r\n    this.periodStartDateError = null;\r\n    switch (value) {\r\n      case \"monthCurrent\":\r\n        this.dateRange.start = Dates.startEnd(\"today\",\"start-month\");\r\n        this.dateRange.end = Dates.startEnd(\"today\",\"end-month\");\r\n        break;\r\n      case \"monthOther\":\r\n        if (Dates.getDay(\"today\") === 1) {\r\n          // Move to tomorrow so that the selection is monthOther and not monthCurrent.\r\n          this.dateRange.start = Dates.add(\"today\",1,\"day\");\r\n        } else {\r\n          this.dateRange.start = Dates.asDate(\"today\");\r\n        }\r\n        this.dateRange.end = Dates.add(Dates.add(this.dateRange.start,1,\"month\"),-1,\"day\");\r\n        break;\r\n      case \"monthLast\":\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-month\"),-1, \"month\");\r\n        this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        break;\r\n      case \"weeks2\":\r\n        this.dateRange.start = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-2,\"week\"); //shift to start of current week, and then 2 weeks before\r\n        this.dateRange.end = Dates.add(Dates.startEnd(\"today\",\"start-week\"),-1,\"day\"); //shift to last day of previous week.\r\n        break;\r\n      case \"monthHalf\":\r\n\r\n        // TODO Check this\r\n        if (Dates.getDay(\"today\") < 16) {\r\n          // 16 - (28,29,30,31)\r\n          this.dateRange.start = Dates.add(Dates.add(Dates.startEnd(\"today\", \"start-month\"),-1,\"month\"),15,\"day\");\r\n          this.dateRange.end = Dates.startEnd(this.dateRange.start,\"end-month\");\r\n        } else {\r\n          // 1 - 15\r\n          this.dateRange.start = Dates.startEnd(\"today\",\"start-month\");\r\n          this.dateRange.end = Dates.add(this.dateRange.start,14,\"day\");\r\n        }\r\n        break;\r\n      case \"other\":\r\n        this.dateRange.start = Dates.add(\"today\",-1,\"day\");\r\n        this.dateRange.end = Dates.asDate(\"today\");\r\n        break;\r\n    }\r\n    this.dateRange = Dates.getDateRange(this.dateRange.start, this.dateRange.end);\r\n    this.dateRangeChange();\r\n  }\r\n\r\n  /**\r\n   * Called when the date range changes.\r\n   * @param noPeriodStartDateUpdate If true, the _periodStartDate is not updated.\r\n   * Should be true if the change is triggered by that input to avoid UI flickering.\r\n   */\r\n  public dateRangeChange(noPeriodStartDateUpdate = false) {\r\n    if (!noPeriodStartDateUpdate) {\r\n      this._periodStartDate = Dates.format(this.dateRange.start, \"D.M.\", null);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets the ng-model value from this.value;\r\n   * Called by daysCount input directly and the datepicker through latestDateSelection.\r\n   * Also called by value setter, but that probably not really used by any code at the moment.\r\n   */\r\n  public setModelValue() {\r\n    const modelValue = this.model.$viewValue as DateRange;\r\n    modelValue.start = this.value.start;\r\n    modelValue.end = this.value.end;\r\n    modelValue.daysCount = this.value.daysCount;\r\n    this.model.$setViewValue(modelValue);\r\n    this.onChange({ value: modelValue });\r\n  }\r\n\r\n  /**\r\n   * Gets the options for datepicker.\r\n   * Uses datepickerOptions, but adds customClass for range formatting.\r\n   * Also converts minDate and maxDate to Date() object if necessary.\r\n   */\r\n  protected getOptions() {\r\n    if (!this.internalOptions) {\r\n      this.internalOptions = Objects.copy(this.datepickerOptions || {});\r\n    }\r\n    if (!this.internalOptions.customClass) {\r\n      this.internalOptions.customClass = this.getDayClass;\r\n    }\r\n    if (this.internalOptions.showWeeks == null) {\r\n      // Switch default to false (if not explicitly specified to true)\r\n      this.internalOptions.showWeeks = false;\r\n    }\r\n    if (this.tempMinDateForRangeSelection) {\r\n      this.internalOptions.minDateText = \"range selection\";\r\n      this.internalOptions.minDate = this.tempMinDateForRangeSelection;\r\n    } else if (this.minDate !== this.internalOptions.minDateText) {\r\n      this.internalOptions.minDateText = this.minDate;\r\n      this.internalOptions.minDate = Dates.asJSDate(this.minDate);\r\n    }\r\n    if (this.maxDate !== this.internalOptions.maxDateText) {\r\n      this.internalOptions.maxDateText = this.maxDate;\r\n      this.internalOptions.maxDate = Dates.asJSDate(this.maxDate);\r\n    }\r\n    return this.internalOptions;\r\n  }\r\n\r\n  /** Gets the readonly value either from the controller or from the form */\r\n  protected getReadOnly(): boolean {\r\n    // This readOnly can be true, false or undefined\r\n    const readOnlyValue = (this.readOnly + \"\").trim().toLowerCase();\r\n    if (readOnlyValue === \"true\" || readOnlyValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (readOnlyValue === \"false\" || readOnlyValue === \"0\") {\r\n      return false;\r\n    }\r\n    const readOnlyFormValue = !!this?.form?.$$element[0]?.attributes?.readonly;\r\n    if (readOnlyFormValue) {\r\n      return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  private getDayClass = (data) => {\r\n    const date = data.date;\r\n    const mode = data.mode;\r\n    if (!this.value) {\r\n      return \"\";\r\n    }\r\n    if (mode === \"day\" && this.value.start && this.value.end) {\r\n      const dayToCheck = Dates.asDate(new Date(date).setHours(0, 0, 0, 0));\r\n      if (this.mode === \"multiple\") {\r\n        if (this.value.days.indexOf(dayToCheck) > -1) {\r\n          return \"selected\";\r\n        }\r\n      } else {\r\n        if (dayToCheck === this.value.start) {\r\n          return \"selected start\";\r\n        }\r\n        if (dayToCheck === this.value.end) {\r\n          return \"selected end\";\r\n        }\r\n        if (dayToCheck > this.value.start && dayToCheck < this.value.end) {\r\n          return \"selected\";\r\n        }\r\n      }\r\n    }\r\n    return \"\";\r\n  };\r\n}\r\n","import angular from \"angular\";\r\nimport { FormGroupLabelType } from \"./FormGroupLabelType\";\r\n\r\n/**\r\n * Helper for rendering the HTML for FormGroup:\r\n * This component renders only the label - input html.\r\n * It does not do any of the real form-control logic like ng-model, validations etc.\r\n * The \"input\" part of the form group may be a non form control - e.g. just a text.\r\n * Also the label may be hidden.\r\n */\r\nexport class FormGroupController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Label for the control */\r\n  public label: string;\r\n\r\n  /** Form control name */\r\n  public name: string;\r\n\r\n  /** If true, shows the asterix in the label. */\r\n  public require: boolean;\r\n\r\n  /**\r\n   * @deprecated Use \"require\" instead:\r\n   * This attribute overlaps with required/ng-required directive, which produces unexpected results.\r\n   */\r\n  public required: string;\r\n\r\n  /**\r\n   * Positioning of the label of form-control.\r\n   * Supported values are \"horizontal\" (default), \"no-label\", \"plain\", \"basic\", \"inline\" and \"empty-label\".\r\n   * See FormGourpLabelType for details.\r\n   */\r\n  public labelType: FormGroupLabelType;\r\n\r\n  /**\r\n   * Label columns expressed as Bootstrap grid columns.\r\n   * Default is 'col-sm-4' for label-type: 'horizontal' and 'col-sm-12' for label-type: 'no-label'.\r\n   * Other label-types do not have column classes at the moment.\r\n   */\r\n  public labelCols: string;\r\n\r\n  constructor() { /* Dependency injeciton */ }\r\n\r\n  /**\r\n   * Checks the existence of name property.\r\n   */\r\n  public $onInit() {\r\n    if (!this.name) {\r\n      throw new Error(`Property 'name' is required for Salaxy form controls (label: ${this.label}).`);\r\n    }\r\n    if (this.name && this.label == null) {\r\n      this.label = this.name;\r\n    }\r\n    if (this.required) {\r\n      const legacyRequiredValue = this.required?.toLowerCase().trim();\r\n      this.require = legacyRequiredValue === \"true\" || legacyRequiredValue === \"1\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the class (or classes space separated) for label or value element.\r\n   */\r\n  public getLabelCols(forElement: \"label\" | \"value\" | \"no-label\" ): string {\r\n    switch (forElement) {\r\n      case \"label\":\r\n        return this.labelCols || \"col-sm-4\";\r\n      case \"value\": {\r\n        let classes = \"\";\r\n        if (this.labelCols && this.labelCols.length >= 8) {\r\n          const regex = /col-(xs|sm|md|lg)-([1-9][1-2]?)/gm;\r\n          let m = regex.exec(this.labelCols);\r\n          while (m !== null) {\r\n              if (m.index === regex.lastIndex) {\r\n                  regex.lastIndex++;\r\n              }\r\n              const colsCount = parseInt(m[2], 10);\r\n              if (colsCount > 0 && colsCount < 13) {\r\n                classes += `col-${ m[1] }-${ 12 - colsCount} `;\r\n              }\r\n              m = regex.exec(this.labelCols);\r\n          }\r\n        }\r\n        return classes.trim() || \"col-sm-8\";\r\n      }\r\n      case \"no-label\":\r\n        return this.labelCols || \"col-sm-12\";\r\n    }\r\n  }\r\n\r\n  /** Gets the label type with \"horizontal\" as default / unknown value. */\r\n  protected getLabelType() {\r\n    switch (this.labelType) {\r\n      case \"no-label\":\r\n      case \"plain\":\r\n      case \"basic\":\r\n      case \"empty-label\":\r\n      case \"inline\":\r\n        return this.labelType;\r\n      default:\r\n        return \"horizontal\";\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Base controller for form control groups (label, input, validation errors etc.).\r\n */\r\nexport class InputController extends InputBase<string> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Minimum length, 0 is the default */\r\n  public minlength: number;\r\n\r\n  /** Maximum length, 1024 is the default */\r\n  public maxlength: number;\r\n\r\n  /** The rows property of the textarea. Default is 3. Not used input, only textarea. */\r\n  public rows: number;\r\n\r\n  /** Regular expression pattern for validation */\r\n  public pattern: string;\r\n\r\n  /** If true, sets the readonly attribute of the input with ng-readonly. */\r\n  public readonly: boolean;\r\n\r\n  /** The model that is bound to the input */\r\n  public model: angular.INgModelController;\r\n  /**\r\n   * Creates a new InputController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    super();\r\n  }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    if (!this.maxlength) {\r\n      this.maxlength = 100000;\r\n    }\r\n    if (this.minlength) {\r\n      this.require = true;\r\n    }\r\n    if (this.required) {\r\n      this.require = true;\r\n    }\r\n    super.$onInit();\r\n  }\r\n\r\n  /** On change of the value, do preventive operations and set value to model. */\r\n  public onChange() {\r\n    if (this.value && this.maxlength && this.value.length > this.maxlength) {\r\n      this.value = this.value.substring(0, this.maxlength);\r\n    }\r\n    super.onChange();\r\n  }\r\n\r\n    /** Empties typeahead input value and opens selection */\r\n    public reset(input: any) {\r\n      this.model.$setViewValue(undefined);\r\n      this.model.$render();\r\n      setTimeout(() => {\r\n        if (input && input[0]) {\r\n          input[0].focus();\r\n        }\r\n      }, 100);\r\n    }\r\n}","import { InputController } from \"./InputController\";\r\nimport { AccountingTargetListItem, ODataQueryOptions, AccountingTargets } from \"@salaxy/core\";\r\n/**\r\n * Controller behind form controls that select an accounting target.\r\n */\r\n\r\nexport class InputAccountingTargetController extends InputController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AccountingTargets\"];\r\n  public _accountingTargetDisplayItem: AccountingTargetListItem;\r\n  /**\r\n   * Creates a new InputAccountingTargetController\r\n   * @ignore\r\n   */\r\n  constructor(private accountingTargets: AccountingTargets) {\r\n    super();\r\n  }\r\n\r\n  /**\r\n   * Query all available accountingTargets from index\r\n   */\r\n  public queryAccountingTargets(search: string): Promise<AccountingTargetListItem[]> {\r\n    search = search ?? \"\";\r\n    const queryOptions: ODataQueryOptions = {\r\n      $search: search,\r\n      $top: 50\r\n    };\r\n    return this.accountingTargets.getOData(queryOptions).then((result) => {\r\n      return result.items;\r\n    });\r\n  }\r\n\r\n\r\n\r\n  /**\r\n   * Get selected accounting target displayName\r\n   * @param accountingTargetId selected accounting target id\r\n   * @param refresher helper for refreshing view after\r\n   * @returns accountingTargetDisplayName from otherPartyInfo.avatar.displayName\r\n   */\r\n  public queryAccountingTargetDisplayName(accountingTargetId: string, refresher: any[]): string {\r\n    if (!accountingTargetId) {\r\n      return \"\";\r\n    }\r\n    if (this._accountingTargetDisplayItem && this._accountingTargetDisplayItem.id === accountingTargetId) {\r\n      return this._accountingTargetDisplayItem.otherPartyInfo.avatar.displayName;\r\n    }\r\n\r\n    this._accountingTargetDisplayItem = {\r\n      id: accountingTargetId,\r\n      otherPartyInfo: {\r\n        avatar: {\r\n          displayName: accountingTargetId\r\n        }\r\n      }\r\n    };\r\n\r\n    const queryOptions: ODataQueryOptions = {\r\n      $filter: `id eq '${accountingTargetId}_AccountingTargetDto'`,\r\n      $top: 50\r\n    };\r\n    this.accountingTargets.getOData(queryOptions).then((result) => {\r\n      this._accountingTargetDisplayItem = (result.items.find((item) => item.id === accountingTargetId)) ?? this._accountingTargetDisplayItem;\r\n      refresher[0] = new Date().getTime();\r\n    });\r\n    return this._accountingTargetDisplayItem.otherPartyInfo.avatar.displayName;\r\n  }\r\n\r\n}\r\n","import { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Controller behind boolean form controls (checkbox, radio, switch)\r\n */\r\n\r\nexport class InputBooleanController extends InputBase<boolean> {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [];\r\n\r\n    /** Type of the input element. Default is checkbox. */\r\n    public type: \"checkbox\" | \"radio\" | \"select\" | \"switch-xl\" | \"switch\";\r\n\r\n    /**\r\n     * Text to show as a label for input with value FALSE\r\n     * Supported by types radio and dropdown\r\n     */\r\n     public labelFalse: string;\r\n\r\n     /**\r\n      * Text to show as a label for input with value TRUE\r\n      * Supported by types radio, checkbox and dropdown\r\n      */\r\n     public labelTrue: string;\r\n\r\n    /**\r\n     * TODO: Is this needed when there's support for 'empty-label' ?\r\n     * BS class for offsetting the input (no-label)\r\n     */\r\n\r\n    public offsetCols: string;\r\n\r\n    /** If true, the radio buttons are aligned horizontally side-by-side */\r\n    public horizontal: boolean;\r\n\r\n     /**\r\n      * Creates a new InputController\r\n      * @ignore\r\n      */\r\n      constructor() {\r\n        super();\r\n      }\r\n\r\n      /** Toggles boolean value. */\r\n      public toggle() {\r\n        this.value = !this.value;\r\n        this.onChange();\r\n      }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Arrays, EnumerationsLogic, InputEnumOption, Objects, Translations } from \"@salaxy/core\";\r\n\r\nimport { InputController } from \"./InputController\";\r\n\r\n/**\r\n * Controller behind form controls that select an occupation type.\r\n */\r\nexport class InputEnumController extends InputController {\r\n\r\n  /**\r\n   * Binds to an enumeration defined by the Salaxy API.\r\n   * Set the name of the enumeration.\r\n   */\r\n  public enum: string;\r\n\r\n  /** Type of the input element. Options are typeahead, select (default) and radio. Todo: remove 'uib-dropdown' */\r\n  public type: \"typeahead\" | \"select\" | \"radio\" | \"multi-select\" | \"dropdown\" | \"uib-dropdown\";\r\n\r\n  /** Options of the select control as a key-value object. */\r\n  protected _options: any;\r\n\r\n  /**\r\n   * Array or comma separated string to filter the option values to just the given ones.\r\n   * Also sets the order to this order, so works for ordering a given set of values.\r\n   * Note that hiddenOptions is applied first, so if you want e.g. \"undefined\" to appear if selected,\r\n   * you may add it here and it behaves as expected (undefined is still hidden if a value is selevted).\r\n   */\r\n  public filter: string[];\r\n\r\n  /** If set to true, does not cache enums. */\r\n  public disableCache;\r\n\r\n  /**\r\n   * These values are visible only if they are selected in the data.\r\n   * Default is [\"undefined\"], set to empty array to show all in every state.\r\n   * I.e. after something else is selected, hidden value cannot be selected back.\r\n   * Use for not-selected values (\"Please choose...\") when you do not want selection reversed\r\n   * or legacy data that is not selectable, but may still exist on the server.\r\n   */\r\n  public hiddenOptions: string[];\r\n\r\n  /**\r\n   * These values are not considered as valid in the UI.\r\n   * Default is [\"unknown\"] and only used when input is \"required\" and input type is \"select\"\r\n   * Use in situations where an unknown/other/none value is set in API but should not be available as an option.\r\n   */\r\n  public invalidEnums: string[];\r\n\r\n  /**\r\n   * Label format for the option. The default format is to show only the text of the option.\r\n   * Options are:\r\n   * \"text\" or empty: only the text of the option is displayed.\r\n   * \"text-value\": in addition to the text, the value is also displayed in the label.\r\n   * \"value\": only the value is displayed.\r\n   * \"title\": Title (description of enumeration) if available. Defaults to text.\r\n   */\r\n  public labelFormat:  \"text\" | \"value\" | \"text-value\" | \"title\";\r\n\r\n  /**\r\n   * If set, last selected option is stored in LocalStorage and set as default/selected value in element.\r\n   * Currently supported only in type 'select' and 'uib-dropbdown'.\r\n   */\r\n  public remember: string;\r\n  private enumCache: InputEnumOption[] = [];\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (!this.type) {\r\n      this.type = \"select\";\r\n    }\r\n    if (!this.hiddenOptions) {\r\n      this.hiddenOptions = [\"undefined\"];\r\n    }\r\n    if (!this.invalidEnums) {\r\n      this.invalidEnums = [\"unknown\"];\r\n    }\r\n    if(this.remember && window.localStorage.getItem(this.remember+\".\"+this.name)){\r\n      this.value = this.getStoredValue();\r\n      super.onChange();\r\n    }\r\n  }\r\n\r\n  /** Options list */\r\n  public get options(): any[] {\r\n    return this._options;\r\n  }\r\n  public set options(value: any[]) {\r\n    this._options = value;\r\n  }\r\n\r\n  /**\r\n   * Gets the label for an enumeration.\r\n   * @param value Type of the enum.\r\n   */\r\n  public getEnumerationLabel(value: string): string {\r\n    const option = this.getEnumerations().find((x) => x.value === value);\r\n    if (option) {\r\n      return this.formatLabel(option);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Returns true if the placeholder should be added to the options. */\r\n  public get showPlaceholder(): boolean {\r\n    if (!this.value || this.value === \"undefined\" || this.value === \"unknown\") {\r\n      if (!this.getEnumerations().find((x) => x.value === this.value)) {\r\n        return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Formats the label for display and typeahed searches. */\r\n  public formatLabel(option: InputEnumOption) {\r\n    switch(this.labelFormat) {\r\n      case \"value\":\r\n        return option.value;\r\n      case \"text-value\":\r\n        {\r\n          let text = option.text ? Translations.get(option.text) : option.text;\r\n          text = text ? text : option.value;\r\n          return `${text}${option.value ? \" (\" + option.value +\")\" : \"\"}`;\r\n        }\r\n      case \"title\":\r\n        return Translations.get(option.title) ?? Translations.get(option.text);\r\n      case \"text\":\r\n      default:\r\n        return Translations.get(option.text);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns items for current enumeration.\r\n   */\r\n  protected getEnumerations(): InputEnumOption[] {\r\n    if (this.enumCache.length > 0 && !this.disableCache) {\r\n      return this.enumCache;\r\n    }\r\n    let allValues: InputEnumOption[] = [];\r\n    const selectedValue = this.value;\r\n    if (this.options) {\r\n      if (Array.isArray(this.options)) {\r\n        allValues = this.options.map((item: any) => {\r\n          if (item == null) {\r\n            return { value: null, text: \"[null]\" };\r\n          }\r\n          if (Objects.has(item, \"value\") || Objects.has(item, \"text\")) {\r\n            return {\r\n              value: item.value,\r\n              text: item.text,\r\n              title: (item.title && item.title !== item.value) ? item.title : null,\r\n              ui: item.ui ? item.ui : null\r\n            };\r\n          }\r\n          return { value: item, text: item };\r\n        });\r\n      } else {\r\n        allValues = Object.keys(this.options)\r\n          .map((key) => ({ value: key, text: this.options[key], title: null }));\r\n      }\r\n    } else if (this.enum) {\r\n      const enums = EnumerationsLogic.getEnumMetadata(this.enum);\r\n      if (enums) {\r\n        allValues = enums.values\r\n          .map((e) => ({ value: e.name, text: e.label, title: e.descr && e.descr !== e.name ? e.descr : null }));\r\n      } else {\r\n        allValues = [{\r\n          value: \"\",\r\n          text: `ERROR: ${this.enum} not found.`,\r\n          title: null,\r\n        }];\r\n      }\r\n    }\r\n    if (this.hiddenOptions) {\r\n      allValues = allValues.filter((option) => {\r\n        const matchingHiddenValue = Arrays.assureArray(this.hiddenOptions).find((hiddenValue) => hiddenValue === option.value);\r\n        // Hidden is shown only if it is currently selected in data.\r\n        return matchingHiddenValue == null || matchingHiddenValue === selectedValue;\r\n      });\r\n    }\r\n    const filterArr = Arrays.assureArray(this.filter);\r\n    if (filterArr.length > 0) {\r\n      allValues = filterArr.map((x) => allValues.find((y) => y.value === x)).filter((x) => x != null);\r\n    }\r\n    this.modifyOptions(allValues, this.enumCache);\r\n    return this.enumCache;\r\n  }\r\n\r\n  private modifyOptions(\r\n    source: ({\r\n      /** Enum value. */\r\n      value: any,\r\n      /** Label for the value. */\r\n      text: string,\r\n      /** Description for the value. */\r\n      title?: string,\r\n    })[],\r\n    target: ({\r\n      /** Enum value. */\r\n      value: any,\r\n      /** Label for the value. */\r\n      text: string,\r\n      /** Description for the value. */\r\n      title?: string,\r\n    })[]) {\r\n    // check if source values differ from target\r\n    const ok = angular.equals(source, target);\r\n\r\n    if (ok) {\r\n      return;\r\n    }\r\n    // remove values\r\n    target.splice(0, target.length);\r\n\r\n    // add values\r\n    target.push(...source);\r\n  }\r\n\r\n  /** Store selection to LocalStorage */\r\n  public setStoredValue(inputName: any, value: any){\r\n    if(this.remember && window.localStorage){\r\n      const storageKey = this.remember +\".\" + inputName;\r\n      window.localStorage.setItem(storageKey, value);\r\n    }\r\n  }\r\n\r\n  /** Get stored value from LocalStorage*/\r\n  public getStoredValue(){\r\n    if(this.remember && window.localStorage){\r\n      const storageKey = this.remember +\".\" + this.name;\r\n      return window.localStorage.getItem(storageKey);\r\n    }\r\n    return null;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { SessionUserCredential } from \"@salaxy/core\";\r\n\r\nimport { WorkflowService } from \"../../services\";\r\nimport { InputEnumController } from \"./InputEnumController\";\r\n\r\n/**\r\n * Controller for selecting a credential.\r\n */\r\n\r\nexport class InputCredentialController extends InputEnumController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WorkflowService\"];\r\n\r\n  private credentials: SessionUserCredential[] = [];\r\n\r\n  /**\r\n   * Creates a new InputOccupationTypeController\r\n   * @ignore\r\n   */\r\n  constructor(private $scope, private workflowService: WorkflowService) {\r\n    super();\r\n  }\r\n\r\n  /** Options list */\r\n  public get options(): any[] {\r\n    const newCredentials = this.workflowService.credentials || [];\r\n    if (!angular.equals(this.credentials, newCredentials)) {\r\n      this._options = newCredentials.map( (x) => {\r\n        return {\r\n          value: x.id,\r\n          text: x.avatar.displayName,\r\n        };\r\n      });\r\n    }\r\n    return this._options;\r\n  }\r\n  public set options(value: any[]) {\r\n    // empty on purpose\r\n    // this._options = value;\r\n  }\r\n}\r\n","import { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Controller for Duration edit input\r\n */\r\n\r\nexport class InputDurationController extends InputBase<string> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  public innerValue: {\r\n    /** If true, the duration is negative, meaning \"before\" the reference time. */\r\n    isNegative: boolean,\r\n    /** Integer number of days. */\r\n    days: number,\r\n    /** Rest of the duration is just kept if it exists. It cannot be edited at the moment. */\r\n    rest: string,\r\n  };\r\n\r\n  /**\r\n   * Creates a new InputController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    super();\r\n  }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    if (this.name && !this.label) {\r\n      this.label = this.name;\r\n    }\r\n    this.model.$render = () => {\r\n      this.value = this.model.$viewValue;\r\n      this.setInnerValue(this.model.$viewValue);\r\n    };\r\n    this.validate();\r\n  }\r\n\r\n  /** Called when the view changes the model. */\r\n  public onChange() {\r\n    this.value = this.getInnerValue();\r\n    super.onChange();\r\n  }\r\n\r\n  /** Gets the inner value as string */\r\n  public getInnerValue(): string {\r\n    if (!this.innerValue) {\r\n      return null;\r\n    }\r\n    let result = \"\";\r\n    if (this.innerValue.days != null && !isNaN(this.innerValue.days)) {\r\n      result += this.innerValue.days;\r\n    }\r\n    if (this.innerValue.rest) {\r\n      if (result != \"\") {\r\n        result += \".\";\r\n      }\r\n      result += this.innerValue.rest;\r\n    }\r\n    if (result == \"\") {\r\n      return null;\r\n    }\r\n    if (this.innerValue.isNegative) {\r\n      result = \"-\" + result;\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /** Parses an input string and sets the inner value based on it. */\r\n  public setInnerValue(value: string) {\r\n    value = value?.trim();\r\n    if (!value) {\r\n      this.innerValue = null;\r\n      return;\r\n    }\r\n    this.innerValue = this.innerValue || {} as any;\r\n    if (value[0] == \"-\") {\r\n      this.innerValue.isNegative = true;\r\n      value = value.substring(1);\r\n    } else {\r\n      this.innerValue.isNegative = false;\r\n    }\r\n    const point = value.indexOf(\".\");\r\n    if (point >= 0) {\r\n      this.innerValue.days = parseInt(value.substr(0, point)) || 0;\r\n      this.innerValue.rest = value.substr(point + 1).trim();\r\n    } else {\r\n      if (value.indexOf(\":\") >= 0) {\r\n        this.innerValue.days = parseInt(value) || 0;\r\n        this.innerValue.rest = null;\r\n      } else {\r\n        this.innerValue.days = null;\r\n        this.innerValue.rest = value.trim();\r\n      }\r\n    }\r\n  }\r\n}\r\n","import { IncomeTypesLogic, Translations } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"../../services\";\r\nimport { InputController } from \"./InputController\";\r\n\r\n/**\r\n * Controller behind form controls that selects Income type code for transaction in Income Registry (Tulorekisteri).\r\n */\r\n\r\nexport class InputIncomeTypeController extends InputController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** Type of the input element. Default is typeahead. */\r\n  public type: \"typehead\" | \"list\";\r\n\r\n  /**\r\n   * List of income type codes to exclude from the selection list.\r\n   */\r\n  public hiddenCodes: number[];\r\n\r\n  /**\r\n   * Creates a new InputIncomeTypeController\r\n   * @ignore\r\n   */\r\n  constructor(private sessionService: SessionService) {\r\n    super();\r\n  }\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (!this.type) {\r\n      this.type = \"typehead\";\r\n    }\r\n  }\r\n\r\n  /** Gets the list of all income types. */\r\n  public getIncomeTypes(searchString: string) {\r\n    // Refresh incometype translations\r\n    IncomeTypesLogic.getAll();\r\n    let result = IncomeTypesLogic.search(searchString);\r\n    if (this.hiddenCodes) {\r\n      result = result.filter( (x) => !this.hiddenCodes.find( (c) => c === x.code) );\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Returns the label for given income type.\r\n   * @param code - Income type code.\r\n   */\r\n  public getRowLabel(code: string): string {\r\n    if (!code) {\r\n      return null;\r\n    }\r\n    const type = IncomeTypesLogic.getAll().find((x) => x.code === Number(code));\r\n    return type ? (type.code + \" - \" + type.label) : \"SALAXY.NG1.InputIncomeType.getRowLabelNotFound\" + code;\r\n  }\r\n\r\n  /** Returns the placeholder text - this control has a default text. */\r\n  public getPlaceholder() {\r\n    // TODO: Translate\r\n    return super.getPlaceholder() || Translations.get(\"SALAXY.NG1.InputIncomeType.getPlaceholder\");\r\n  }\r\n\r\n  /** Called by the view, when a value is selected. */\r\n  protected selectionClicked(value: number) {\r\n    this.value = value as any;\r\n    this.onChange();\r\n  }\r\n}\r\n","import {  CalcRowsLogic, CalculationRowUnit, Numeric } from \"@salaxy/core\";\r\n\r\nimport { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Controller behind form controls that select an occupation type.\r\n */\r\nexport class InputNumberController extends InputBase<number> {\r\n\r\n    /**\r\n     * Unit for the number.\r\n     * If set, shows a visual clue of the unit.\r\n     * For 'percent' editor value is multiplied by 100.\r\n     */\r\n    public unit: CalculationRowUnit;\r\n\r\n    /**\r\n     * Expression for the allowed Units for the number.\r\n     * If set, shows a selection of control for the unit.\r\n     */\r\n     public units: CalculationRowUnit[];\r\n\r\n    /** Type of the input element. Options are default and slider */\r\n    public type: \"default\" | \"slider\";\r\n\r\n    /** Step for slider */\r\n    public sliderStep: number;\r\n\r\n    /**\r\n     * If true, the input edits negative value: The value is multiplied by -1.\r\n     * E.g. \"3\" days ago => -3.\r\n     */\r\n    public negative: boolean;\r\n\r\n    /**\r\n     * Function that is called when the unit has been changed.\r\n     * Function has the following locals:  unit: the selected unit.\r\n     */\r\n    public onUnitChange: (params: {\r\n      /** Selected unit */\r\n      unit: CalculationRowUnit,\r\n    }) => void;\r\n\r\n    /** Sets the default values in init. */\r\n    public $onInit() {\r\n      super.$onInit();\r\n    }\r\n\r\n    /**\r\n     * Gets or sets the string value that is used in the view.\r\n     * For percent, this is multiplied by 100.\r\n     */\r\n    public get viewValue(): string {\r\n      let valueNum = Numeric.parseNumber(this.value); // Historically, the value may be string e.g. \"3\" instead of 3.\r\n      if (valueNum != null && this.unit === CalculationRowUnit.Percent) {\r\n        valueNum = valueNum * 100;\r\n      }\r\n      if (this.negative && valueNum) {\r\n        valueNum = valueNum * -1;\r\n      }\r\n      return valueNum == null ? null : Numeric.toString(valueNum).replace(\".\", \",\");\r\n    }\r\n    public set viewValue(value: string) {\r\n      let valueNum = Numeric.parseNumber(value);\r\n      if (valueNum != null && this.unit === CalculationRowUnit.Percent) {\r\n        valueNum = valueNum / 100;\r\n      }\r\n      if (this.negative && valueNum) {\r\n        valueNum = valueNum * -1;\r\n      }\r\n      this.value = valueNum;\r\n      this.onChange();\r\n    }\r\n\r\n    /**\r\n     * Gets an indicator string (1-2 characters) for the unit.\r\n     */\r\n    public getUnitIndicator(unit: CalculationRowUnit) {\r\n      return CalcRowsLogic.getUnitIndicator(unit ?? this.unit);\r\n    }\r\n\r\n    /**\r\n     * Changes the unit and calls the onUnitChange function.\r\n     * @param unit New unit.\r\n     */\r\n    public changeUnit(unit: CalculationRowUnit) {\r\n      this.unit = unit;\r\n      if (this.onUnitChange) {\r\n        this.onUnitChange({ unit });\r\n      }\r\n    }\r\n}\r\n","import { Occupation, Occupations, Translations } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"../../services\";\r\nimport { InputController } from \"./InputController\";\r\n\r\n/**\r\n * Controller behind form controls that select an occupation type.\r\n */\r\n\r\nexport class InputOccupationTypeController extends InputController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /**\r\n   * One or a list of occupation IDs or a known keyword to define which occupations are shown\r\n   * Supported keywords: 'household' and 'company'\r\n   */\r\n  public defaultList: string;\r\n\r\n  /**\r\n   * These values are not considered as valid in the UI.\r\n   * Default is [\"other\"] and only used when input is \"required\".\r\n   * Use in situations where an unknown/other/none value is set in API but should not be available as an option or considered as a valid option.\r\n   */\r\n  public invalidEnums: string[];\r\n  /**\r\n   * Creates a new InputOccupationTypeController\r\n   * @ignore\r\n   */\r\n  constructor(private sessionService: SessionService) {\r\n    super();\r\n  }\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    if (!this.invalidEnums) {\r\n      this.invalidEnums = [\"other\"];\r\n    }\r\n  }\r\n  /** Gets the list of all occupations. */\r\n  public getOccupations(searchString: string): Occupation[] {\r\n    if (!searchString || searchString.length < 2) {\r\n      const defaultList = this.defaultList || this.sessionService.isInSomeRole(\"household,worker\") ? \"household\" : \"company\";\r\n      return Occupations.getByIds(defaultList);\r\n    }\r\n    return Occupations.search(searchString);\r\n  }\r\n\r\n  /**\r\n   * Returns the label for given occupation id.\r\n   * @param occupationId - Id of the occupation.\r\n   */\r\n  public getOccupationLabel(occupationId: string): string {\r\n    for (const occupation of Occupations.getAll(null)) {\r\n      if (occupationId === occupation.id) {\r\n        return occupation.label;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Returns the placeholder text - this control has a default text. */\r\n  public getPlaceholder() {\r\n    // TODO: Translate\r\n    return super.getPlaceholder() || Translations.get(\"SALAXY.NG1.InputOccupationType.getPlaceholder\");\r\n  }\r\n}\r\n","// =============================================================================\n// Weekday\n// =============================================================================\nexport var ALL_WEEKDAYS = [\n    'MO',\n    'TU',\n    'WE',\n    'TH',\n    'FR',\n    'SA',\n    'SU',\n];\nvar Weekday = /** @class */ (function () {\n    function Weekday(weekday, n) {\n        if (n === 0)\n            throw new Error(\"Can't create weekday with n == 0\");\n        this.weekday = weekday;\n        this.n = n;\n    }\n    Weekday.fromStr = function (str) {\n        return new Weekday(ALL_WEEKDAYS.indexOf(str));\n    };\n    // __call__ - Cannot call the object directly, do it through\n    // e.g. RRule.TH.nth(-1) instead,\n    Weekday.prototype.nth = function (n) {\n        return this.n === n ? this : new Weekday(this.weekday, n);\n    };\n    // __eq__\n    Weekday.prototype.equals = function (other) {\n        return this.weekday === other.weekday && this.n === other.n;\n    };\n    // __repr__\n    Weekday.prototype.toString = function () {\n        var s = ALL_WEEKDAYS[this.weekday];\n        if (this.n)\n            s = (this.n > 0 ? '+' : '') + String(this.n) + s;\n        return s;\n    };\n    Weekday.prototype.getJsWeekday = function () {\n        return this.weekday === 6 ? 0 : this.weekday + 1;\n    };\n    return Weekday;\n}());\nexport { Weekday };\n//# sourceMappingURL=weekday.js.map","// =============================================================================\n// Helper functions\n// =============================================================================\nimport { ALL_WEEKDAYS } from './weekday';\nexport var isPresent = function (value) {\n    return value !== null && value !== undefined;\n};\nexport var isNumber = function (value) {\n    return typeof value === 'number';\n};\nexport var isWeekdayStr = function (value) {\n    return typeof value === 'string' && ALL_WEEKDAYS.includes(value);\n};\nexport var isArray = Array.isArray;\n/**\n * Simplified version of python's range()\n */\nexport var range = function (start, end) {\n    if (end === void 0) { end = start; }\n    if (arguments.length === 1) {\n        end = start;\n        start = 0;\n    }\n    var rang = [];\n    for (var i = start; i < end; i++)\n        rang.push(i);\n    return rang;\n};\nexport var clone = function (array) {\n    return [].concat(array);\n};\nexport var repeat = function (value, times) {\n    var i = 0;\n    var array = [];\n    if (isArray(value)) {\n        for (; i < times; i++)\n            array[i] = [].concat(value);\n    }\n    else {\n        for (; i < times; i++)\n            array[i] = value;\n    }\n    return array;\n};\nexport var toArray = function (item) {\n    if (isArray(item)) {\n        return item;\n    }\n    return [item];\n};\nexport function padStart(item, targetLength, padString) {\n    if (padString === void 0) { padString = ' '; }\n    var str = String(item);\n    targetLength = targetLength >> 0;\n    if (str.length > targetLength) {\n        return String(str);\n    }\n    targetLength = targetLength - str.length;\n    if (targetLength > padString.length) {\n        padString += repeat(padString, targetLength / padString.length);\n    }\n    return padString.slice(0, targetLength) + String(str);\n}\n/**\n * Python like split\n */\nexport var split = function (str, sep, num) {\n    var splits = str.split(sep);\n    return num\n        ? splits.slice(0, num).concat([splits.slice(num).join(sep)])\n        : splits;\n};\n/**\n * closure/goog/math/math.js:modulo\n * Copyright 2006 The Closure Library Authors.\n * The % operator in JavaScript returns the remainder of a / b, but differs from\n * some other languages in that the result will have the same sign as the\n * dividend. For example, -1 % 8 == -1, whereas in some other languages\n * (such as Python) the result would be 7. This function emulates the more\n * correct modulo behavior, which is useful for certain applications such as\n * calculating an offset index in a circular list.\n *\n * @param {number} a The dividend.\n * @param {number} b The divisor.\n * @return {number} a % b where the result is between 0 and b (either 0 <= x < b\n * or b < x <= 0, depending on the sign of b).\n */\nexport var pymod = function (a, b) {\n    var r = a % b;\n    // If r and b differ in sign, add b to wrap the result to the correct sign.\n    return r * b < 0 ? r + b : r;\n};\n/**\n * @see: <http://docs.python.org/library/functions.html#divmod>\n */\nexport var divmod = function (a, b) {\n    return { div: Math.floor(a / b), mod: pymod(a, b) };\n};\nexport var empty = function (obj) {\n    return !isPresent(obj) || obj.length === 0;\n};\n/**\n * Python-like boolean\n *\n * @return {Boolean} value of an object/primitive, taking into account\n * the fact that in Python an empty list's/tuple's\n * boolean value is False, whereas in JS it's true\n */\nexport var notEmpty = function (obj) {\n    return !empty(obj);\n};\n/**\n * Return true if a value is in an array\n */\nexport var includes = function (arr, val) {\n    return notEmpty(arr) && arr.indexOf(val) !== -1;\n};\n//# sourceMappingURL=helpers.js.map","import { padStart } from './helpers';\nexport var datetime = function (y, m, d, h, i, s) {\n    if (h === void 0) { h = 0; }\n    if (i === void 0) { i = 0; }\n    if (s === void 0) { s = 0; }\n    return new Date(Date.UTC(y, m - 1, d, h, i, s));\n};\n/**\n * General date-related utilities.\n * Also handles several incompatibilities between JavaScript and Python\n *\n */\nexport var MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n/**\n * Number of milliseconds of one day\n */\nexport var ONE_DAY = 1000 * 60 * 60 * 24;\n/**\n * @see: <http://docs.python.org/library/datetime.html#datetime.MAXYEAR>\n */\nexport var MAXYEAR = 9999;\n/**\n * Python uses 1-Jan-1 as the base for calculating ordinals but we don't\n * want to confuse the JS engine with milliseconds > Number.MAX_NUMBER,\n * therefore we use 1-Jan-1970 instead\n */\nexport var ORDINAL_BASE = datetime(1970, 1, 1);\n/**\n * Python: MO-SU: 0 - 6\n * JS: SU-SAT 0 - 6\n */\nexport var PY_WEEKDAYS = [6, 0, 1, 2, 3, 4, 5];\n/**\n * py_date.timetuple()[7]\n */\nexport var getYearDay = function (date) {\n    var dateNoTime = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());\n    return (Math.ceil((dateNoTime.valueOf() - new Date(date.getUTCFullYear(), 0, 1).valueOf()) /\n        ONE_DAY) + 1);\n};\nexport var isLeapYear = function (year) {\n    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n};\nexport var isDate = function (value) {\n    return value instanceof Date;\n};\nexport var isValidDate = function (value) {\n    return isDate(value) && !isNaN(value.getTime());\n};\n/**\n * @return {Number} the date's timezone offset in ms\n */\nexport var tzOffset = function (date) {\n    return date.getTimezoneOffset() * 60 * 1000;\n};\n/**\n * @see: <http://www.mcfedries.com/JavaScript/DaysBetween.asp>\n */\nexport var daysBetween = function (date1, date2) {\n    // The number of milliseconds in one day\n    // Convert both dates to milliseconds\n    var date1ms = date1.getTime();\n    var date2ms = date2.getTime();\n    // Calculate the difference in milliseconds\n    var differencems = date1ms - date2ms;\n    // Convert back to days and return\n    return Math.round(differencems / ONE_DAY);\n};\n/**\n * @see: <http://docs.python.org/library/datetime.html#datetime.date.toordinal>\n */\nexport var toOrdinal = function (date) {\n    return daysBetween(date, ORDINAL_BASE);\n};\n/**\n * @see - <http://docs.python.org/library/datetime.html#datetime.date.fromordinal>\n */\nexport var fromOrdinal = function (ordinal) {\n    return new Date(ORDINAL_BASE.getTime() + ordinal * ONE_DAY);\n};\nexport var getMonthDays = function (date) {\n    var month = date.getUTCMonth();\n    return month === 1 && isLeapYear(date.getUTCFullYear())\n        ? 29\n        : MONTH_DAYS[month];\n};\n/**\n * @return {Number} python-like weekday\n */\nexport var getWeekday = function (date) {\n    return PY_WEEKDAYS[date.getUTCDay()];\n};\n/**\n * @see: <http://docs.python.org/library/calendar.html#calendar.monthrange>\n */\nexport var monthRange = function (year, month) {\n    var date = datetime(year, month + 1, 1);\n    return [getWeekday(date), getMonthDays(date)];\n};\n/**\n * @see: <http://docs.python.org/library/datetime.html#datetime.datetime.combine>\n */\nexport var combine = function (date, time) {\n    time = time || date;\n    return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()));\n};\nexport var clone = function (date) {\n    var dolly = new Date(date.getTime());\n    return dolly;\n};\nexport var cloneDates = function (dates) {\n    var clones = [];\n    for (var i = 0; i < dates.length; i++) {\n        clones.push(clone(dates[i]));\n    }\n    return clones;\n};\n/**\n * Sorts an array of Date or Time objects\n */\nexport var sort = function (dates) {\n    dates.sort(function (a, b) {\n        return a.getTime() - b.getTime();\n    });\n};\nexport var timeToUntilString = function (time, utc) {\n    if (utc === void 0) { utc = true; }\n    var date = new Date(time);\n    return [\n        padStart(date.getUTCFullYear().toString(), 4, '0'),\n        padStart(date.getUTCMonth() + 1, 2, '0'),\n        padStart(date.getUTCDate(), 2, '0'),\n        'T',\n        padStart(date.getUTCHours(), 2, '0'),\n        padStart(date.getUTCMinutes(), 2, '0'),\n        padStart(date.getUTCSeconds(), 2, '0'),\n        utc ? 'Z' : '',\n    ].join('');\n};\nexport var untilStringToDate = function (until) {\n    var re = /^(\\d{4})(\\d{2})(\\d{2})(T(\\d{2})(\\d{2})(\\d{2})Z?)?$/;\n    var bits = re.exec(until);\n    if (!bits)\n        throw new Error(\"Invalid UNTIL value: \".concat(until));\n    return new Date(Date.UTC(parseInt(bits[1], 10), parseInt(bits[2], 10) - 1, parseInt(bits[3], 10), parseInt(bits[5], 10) || 0, parseInt(bits[6], 10) || 0, parseInt(bits[7], 10) || 0));\n};\nvar dateTZtoISO8601 = function (date, timeZone) {\n    // date format for sv-SE is almost ISO8601\n    var dateStr = date.toLocaleString('sv-SE', { timeZone: timeZone });\n    // '2023-02-07 10:41:36'\n    return dateStr.replace(' ', 'T') + 'Z';\n};\nexport var dateInTimeZone = function (date, timeZone) {\n    var localTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n    // Date constructor can only reliably parse dates in ISO8601 format\n    var dateInLocalTZ = new Date(dateTZtoISO8601(date, localTimeZone));\n    var dateInTargetTZ = new Date(dateTZtoISO8601(date, timeZone !== null && timeZone !== void 0 ? timeZone : 'UTC'));\n    var tzOffset = dateInTargetTZ.getTime() - dateInLocalTZ.getTime();\n    return new Date(date.getTime() - tzOffset);\n};\n//# sourceMappingURL=dateutil.js.map","/**\n * This class helps us to emulate python's generators, sorta.\n */\nvar IterResult = /** @class */ (function () {\n    function IterResult(method, args) {\n        this.minDate = null;\n        this.maxDate = null;\n        this._result = [];\n        this.total = 0;\n        this.method = method;\n        this.args = args;\n        if (method === 'between') {\n            this.maxDate = args.inc\n                ? args.before\n                : new Date(args.before.getTime() - 1);\n            this.minDate = args.inc ? args.after : new Date(args.after.getTime() + 1);\n        }\n        else if (method === 'before') {\n            this.maxDate = args.inc ? args.dt : new Date(args.dt.getTime() - 1);\n        }\n        else if (method === 'after') {\n            this.minDate = args.inc ? args.dt : new Date(args.dt.getTime() + 1);\n        }\n    }\n    /**\n     * Possibly adds a date into the result.\n     *\n     * @param {Date} date - the date isn't necessarly added to the result\n     * list (if it is too late/too early)\n     * @return {Boolean} true if it makes sense to continue the iteration\n     * false if we're done.\n     */\n    IterResult.prototype.accept = function (date) {\n        ++this.total;\n        var tooEarly = this.minDate && date < this.minDate;\n        var tooLate = this.maxDate && date > this.maxDate;\n        if (this.method === 'between') {\n            if (tooEarly)\n                return true;\n            if (tooLate)\n                return false;\n        }\n        else if (this.method === 'before') {\n            if (tooLate)\n                return false;\n        }\n        else if (this.method === 'after') {\n            if (tooEarly)\n                return true;\n            this.add(date);\n            return false;\n        }\n        return this.add(date);\n    };\n    /**\n     *\n     * @param {Date} date that is part of the result.\n     * @return {Boolean} whether we are interested in more values.\n     */\n    IterResult.prototype.add = function (date) {\n        this._result.push(date);\n        return true;\n    };\n    /**\n     * 'before' and 'after' return only one date, whereas 'all'\n     * and 'between' an array.\n     *\n     * @return {Date,Array?}\n     */\n    IterResult.prototype.getValue = function () {\n        var res = this._result;\n        switch (this.method) {\n            case 'all':\n            case 'between':\n                return res;\n            case 'before':\n            case 'after':\n            default:\n                return (res.length ? res[res.length - 1] : null);\n        }\n    };\n    IterResult.prototype.clone = function () {\n        return new IterResult(this.method, this.args);\n    };\n    return IterResult;\n}());\nexport default IterResult;\n//# sourceMappingURL=iterresult.js.map","/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol */\n\nvar extendStatics = function(d, b) {\n  extendStatics = Object.setPrototypeOf ||\n      ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n      function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n  return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n  if (typeof b !== \"function\" && b !== null)\n      throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n  extendStatics(d, b);\n  function __() { this.constructor = d; }\n  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n  __assign = Object.assign || function __assign(t) {\n      for (var s, i = 1, n = arguments.length; i < n; i++) {\n          s = arguments[i];\n          for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n      }\n      return t;\n  }\n  return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n  var t = {};\n  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n      t[p] = s[p];\n  if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n      for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n          if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n              t[p[i]] = s[p[i]];\n      }\n  return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n  if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n  return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n  return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n  function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n  var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n  var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n  var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n  var _, done = false;\n  for (var i = decorators.length - 1; i >= 0; i--) {\n      var context = {};\n      for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n      for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n      context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n      var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n      if (kind === \"accessor\") {\n          if (result === void 0) continue;\n          if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n          if (_ = accept(result.get)) descriptor.get = _;\n          if (_ = accept(result.set)) descriptor.set = _;\n          if (_ = accept(result.init)) initializers.unshift(_);\n      }\n      else if (_ = accept(result)) {\n          if (kind === \"field\") initializers.unshift(_);\n          else descriptor[key] = _;\n      }\n  }\n  if (target) Object.defineProperty(target, contextIn.name, descriptor);\n  done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n  var useValue = arguments.length > 2;\n  for (var i = 0; i < initializers.length; i++) {\n      value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n  }\n  return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n  return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n  if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n  return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n  if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n  return new (P || (P = Promise))(function (resolve, reject) {\n      function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n      function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n      function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n      step((generator = generator.apply(thisArg, _arguments || [])).next());\n  });\n}\n\nexport function __generator(thisArg, body) {\n  var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n  return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n  function verb(n) { return function (v) { return step([n, v]); }; }\n  function step(op) {\n      if (f) throw new TypeError(\"Generator is already executing.\");\n      while (g && (g = 0, op[0] && (_ = 0)), _) try {\n          if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n          if (y = 0, t) op = [op[0] & 2, t.value];\n          switch (op[0]) {\n              case 0: case 1: t = op; break;\n              case 4: _.label++; return { value: op[1], done: false };\n              case 5: _.label++; y = op[1]; op = [0]; continue;\n              case 7: op = _.ops.pop(); _.trys.pop(); continue;\n              default:\n                  if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                  if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                  if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                  if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                  if (t[2]) _.ops.pop();\n                  _.trys.pop(); continue;\n          }\n          op = body.call(thisArg, _);\n      } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n      if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n  }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n  if (k2 === undefined) k2 = k;\n  var desc = Object.getOwnPropertyDescriptor(m, k);\n  if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n      desc = { enumerable: true, get: function() { return m[k]; } };\n  }\n  Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n  if (k2 === undefined) k2 = k;\n  o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n  for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n  var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n  if (m) return m.call(o);\n  if (o && typeof o.length === \"number\") return {\n      next: function () {\n          if (o && i >= o.length) o = void 0;\n          return { value: o && o[i++], done: !o };\n      }\n  };\n  throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n  var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n  if (!m) return o;\n  var i = m.call(o), r, ar = [], e;\n  try {\n      while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n  }\n  catch (error) { e = { error: error }; }\n  finally {\n      try {\n          if (r && !r.done && (m = i[\"return\"])) m.call(i);\n      }\n      finally { if (e) throw e.error; }\n  }\n  return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n  for (var ar = [], i = 0; i < arguments.length; i++)\n      ar = ar.concat(__read(arguments[i]));\n  return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n  for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n  for (var r = Array(s), k = 0, i = 0; i < il; i++)\n      for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n          r[k] = a[j];\n  return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n      if (ar || !(i in from)) {\n          if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n          ar[i] = from[i];\n      }\n  }\n  return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n  return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n  if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n  var g = generator.apply(thisArg, _arguments || []), i, q = [];\n  return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\n  function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\n  function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n  function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n  function fulfill(value) { resume(\"next\", value); }\n  function reject(value) { resume(\"throw\", value); }\n  function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n  var i, p;\n  return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n  function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n  if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n  var m = o[Symbol.asyncIterator], i;\n  return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n  if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n  return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n  Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n  o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n  if (mod && mod.__esModule) return mod;\n  var result = {};\n  if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n  __setModuleDefault(result, mod);\n  return result;\n}\n\nexport function __importDefault(mod) {\n  return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n  if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n  if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n  return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n  if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n  if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n  if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n  return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n  if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n  return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n  if (value !== null && value !== void 0) {\n    if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n    var dispose;\n    if (async) {\n        if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n        dispose = value[Symbol.asyncDispose];\n    }\n    if (dispose === void 0) {\n        if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n        dispose = value[Symbol.dispose];\n    }\n    if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n    env.stack.push({ value: value, dispose: dispose, async: async });\n  }\n  else if (async) {\n    env.stack.push({ async: true });\n  }\n  return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n  var e = new Error(message);\n  return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n  function fail(e) {\n    env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n    env.hasError = true;\n  }\n  function next() {\n    while (env.stack.length) {\n      var rec = env.stack.pop();\n      try {\n        var result = rec.dispose && rec.dispose.call(rec.value);\n        if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n      }\n      catch (e) {\n          fail(e);\n      }\n    }\n    if (env.hasError) throw env.error;\n  }\n  return next();\n}\n\nexport default {\n  __extends,\n  __assign,\n  __rest,\n  __decorate,\n  __param,\n  __metadata,\n  __awaiter,\n  __generator,\n  __createBinding,\n  __exportStar,\n  __values,\n  __read,\n  __spread,\n  __spreadArrays,\n  __spreadArray,\n  __await,\n  __asyncGenerator,\n  __asyncDelegator,\n  __asyncValues,\n  __makeTemplateObject,\n  __importStar,\n  __importDefault,\n  __classPrivateFieldGet,\n  __classPrivateFieldSet,\n  __classPrivateFieldIn,\n  __addDisposableResource,\n  __disposeResources,\n};\n","import { __extends } from \"tslib\";\nimport IterResult from './iterresult';\n/**\n * IterResult subclass that calls a callback function on each add,\n * and stops iterating when the callback returns false.\n */\nvar CallbackIterResult = /** @class */ (function (_super) {\n    __extends(CallbackIterResult, _super);\n    function CallbackIterResult(method, args, iterator) {\n        var _this = _super.call(this, method, args) || this;\n        _this.iterator = iterator;\n        return _this;\n    }\n    CallbackIterResult.prototype.add = function (date) {\n        if (this.iterator(date, this._result.length)) {\n            this._result.push(date);\n            return true;\n        }\n        return false;\n    };\n    return CallbackIterResult;\n}(IterResult));\nexport default CallbackIterResult;\n//# sourceMappingURL=callbackiterresult.js.map","// =============================================================================\n// i18n\n// =============================================================================\nvar ENGLISH = {\n    dayNames: [\n        'Sunday',\n        'Monday',\n        'Tuesday',\n        'Wednesday',\n        'Thursday',\n        'Friday',\n        'Saturday',\n    ],\n    monthNames: [\n        'January',\n        'February',\n        'March',\n        'April',\n        'May',\n        'June',\n        'July',\n        'August',\n        'September',\n        'October',\n        'November',\n        'December',\n    ],\n    tokens: {\n        SKIP: /^[ \\r\\n\\t]+|^\\.$/,\n        number: /^[1-9][0-9]*/,\n        numberAsText: /^(one|two|three)/i,\n        every: /^every/i,\n        'day(s)': /^days?/i,\n        'weekday(s)': /^weekdays?/i,\n        'week(s)': /^weeks?/i,\n        'hour(s)': /^hours?/i,\n        'minute(s)': /^minutes?/i,\n        'month(s)': /^months?/i,\n        'year(s)': /^years?/i,\n        on: /^(on|in)/i,\n        at: /^(at)/i,\n        the: /^the/i,\n        first: /^first/i,\n        second: /^second/i,\n        third: /^third/i,\n        nth: /^([1-9][0-9]*)(\\.|th|nd|rd|st)/i,\n        last: /^last/i,\n        for: /^for/i,\n        'time(s)': /^times?/i,\n        until: /^(un)?til/i,\n        monday: /^mo(n(day)?)?/i,\n        tuesday: /^tu(e(s(day)?)?)?/i,\n        wednesday: /^we(d(n(esday)?)?)?/i,\n        thursday: /^th(u(r(sday)?)?)?/i,\n        friday: /^fr(i(day)?)?/i,\n        saturday: /^sa(t(urday)?)?/i,\n        sunday: /^su(n(day)?)?/i,\n        january: /^jan(uary)?/i,\n        february: /^feb(ruary)?/i,\n        march: /^mar(ch)?/i,\n        april: /^apr(il)?/i,\n        may: /^may/i,\n        june: /^june?/i,\n        july: /^july?/i,\n        august: /^aug(ust)?/i,\n        september: /^sep(t(ember)?)?/i,\n        october: /^oct(ober)?/i,\n        november: /^nov(ember)?/i,\n        december: /^dec(ember)?/i,\n        comma: /^(,\\s*|(and|or)\\s*)+/i,\n    },\n};\nexport default ENGLISH;\n//# sourceMappingURL=i18n.js.map","import ENGLISH from './i18n';\nimport { RRule } from '../rrule';\nimport { isArray, isNumber, isPresent } from '../helpers';\n// =============================================================================\n// Helper functions\n// =============================================================================\n/**\n * Return true if a value is in an array\n */\nvar contains = function (arr, val) {\n    return arr.indexOf(val) !== -1;\n};\nvar defaultGetText = function (id) { return id.toString(); };\nvar defaultDateFormatter = function (year, month, day) { return \"\".concat(month, \" \").concat(day, \", \").concat(year); };\n/**\n *\n * @param {RRule} rrule\n * Optional:\n * @param {Function} gettext function\n * @param {Object} language definition\n * @constructor\n */\nvar ToText = /** @class */ (function () {\n    function ToText(rrule, gettext, language, dateFormatter) {\n        if (gettext === void 0) { gettext = defaultGetText; }\n        if (language === void 0) { language = ENGLISH; }\n        if (dateFormatter === void 0) { dateFormatter = defaultDateFormatter; }\n        this.text = [];\n        this.language = language || ENGLISH;\n        this.gettext = gettext;\n        this.dateFormatter = dateFormatter;\n        this.rrule = rrule;\n        this.options = rrule.options;\n        this.origOptions = rrule.origOptions;\n        if (this.origOptions.bymonthday) {\n            var bymonthday = [].concat(this.options.bymonthday);\n            var bynmonthday = [].concat(this.options.bynmonthday);\n            bymonthday.sort(function (a, b) { return a - b; });\n            bynmonthday.sort(function (a, b) { return b - a; });\n            // 1, 2, 3, .., -5, -4, -3, ..\n            this.bymonthday = bymonthday.concat(bynmonthday);\n            if (!this.bymonthday.length)\n                this.bymonthday = null;\n        }\n        if (isPresent(this.origOptions.byweekday)) {\n            var byweekday = !isArray(this.origOptions.byweekday)\n                ? [this.origOptions.byweekday]\n                : this.origOptions.byweekday;\n            var days = String(byweekday);\n            this.byweekday = {\n                allWeeks: byweekday.filter(function (weekday) {\n                    return !weekday.n;\n                }),\n                someWeeks: byweekday.filter(function (weekday) {\n                    return Boolean(weekday.n);\n                }),\n                isWeekdays: days.indexOf('MO') !== -1 &&\n                    days.indexOf('TU') !== -1 &&\n                    days.indexOf('WE') !== -1 &&\n                    days.indexOf('TH') !== -1 &&\n                    days.indexOf('FR') !== -1 &&\n                    days.indexOf('SA') === -1 &&\n                    days.indexOf('SU') === -1,\n                isEveryDay: days.indexOf('MO') !== -1 &&\n                    days.indexOf('TU') !== -1 &&\n                    days.indexOf('WE') !== -1 &&\n                    days.indexOf('TH') !== -1 &&\n                    days.indexOf('FR') !== -1 &&\n                    days.indexOf('SA') !== -1 &&\n                    days.indexOf('SU') !== -1,\n            };\n            var sortWeekDays = function (a, b) {\n                return a.weekday - b.weekday;\n            };\n            this.byweekday.allWeeks.sort(sortWeekDays);\n            this.byweekday.someWeeks.sort(sortWeekDays);\n            if (!this.byweekday.allWeeks.length)\n                this.byweekday.allWeeks = null;\n            if (!this.byweekday.someWeeks.length)\n                this.byweekday.someWeeks = null;\n        }\n        else {\n            this.byweekday = null;\n        }\n    }\n    /**\n     * Test whether the rrule can be fully converted to text.\n     *\n     * @param {RRule} rrule\n     * @return {Boolean}\n     */\n    ToText.isFullyConvertible = function (rrule) {\n        var canConvert = true;\n        if (!(rrule.options.freq in ToText.IMPLEMENTED))\n            return false;\n        if (rrule.origOptions.until && rrule.origOptions.count)\n            return false;\n        for (var key in rrule.origOptions) {\n            if (contains(['dtstart', 'tzid', 'wkst', 'freq'], key))\n                return true;\n            if (!contains(ToText.IMPLEMENTED[rrule.options.freq], key))\n                return false;\n        }\n        return canConvert;\n    };\n    ToText.prototype.isFullyConvertible = function () {\n        return ToText.isFullyConvertible(this.rrule);\n    };\n    /**\n     * Perform the conversion. Only some of the frequencies are supported.\n     * If some of the rrule's options aren't supported, they'll\n     * be omitted from the output an \"(~ approximate)\" will be appended.\n     *\n     * @return {*}\n     */\n    ToText.prototype.toString = function () {\n        var gettext = this.gettext;\n        if (!(this.options.freq in ToText.IMPLEMENTED)) {\n            return gettext('RRule error: Unable to fully convert this rrule to text');\n        }\n        this.text = [gettext('every')];\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n        // @ts-ignore\n        this[RRule.FREQUENCIES[this.options.freq]]();\n        if (this.options.until) {\n            this.add(gettext('until'));\n            var until = this.options.until;\n            this.add(this.dateFormatter(until.getUTCFullYear(), this.language.monthNames[until.getUTCMonth()], until.getUTCDate()));\n        }\n        else if (this.options.count) {\n            this.add(gettext('for'))\n                .add(this.options.count.toString())\n                .add(this.plural(this.options.count) ? gettext('times') : gettext('time'));\n        }\n        if (!this.isFullyConvertible())\n            this.add(gettext('(~ approximate)'));\n        return this.text.join('');\n    };\n    ToText.prototype.HOURLY = function () {\n        var gettext = this.gettext;\n        if (this.options.interval !== 1)\n            this.add(this.options.interval.toString());\n        this.add(this.plural(this.options.interval) ? gettext('hours') : gettext('hour'));\n    };\n    ToText.prototype.MINUTELY = function () {\n        var gettext = this.gettext;\n        if (this.options.interval !== 1)\n            this.add(this.options.interval.toString());\n        this.add(this.plural(this.options.interval)\n            ? gettext('minutes')\n            : gettext('minute'));\n    };\n    ToText.prototype.DAILY = function () {\n        var gettext = this.gettext;\n        if (this.options.interval !== 1)\n            this.add(this.options.interval.toString());\n        if (this.byweekday && this.byweekday.isWeekdays) {\n            this.add(this.plural(this.options.interval)\n                ? gettext('weekdays')\n                : gettext('weekday'));\n        }\n        else {\n            this.add(this.plural(this.options.interval) ? gettext('days') : gettext('day'));\n        }\n        if (this.origOptions.bymonth) {\n            this.add(gettext('in'));\n            this._bymonth();\n        }\n        if (this.bymonthday) {\n            this._bymonthday();\n        }\n        else if (this.byweekday) {\n            this._byweekday();\n        }\n        else if (this.origOptions.byhour) {\n            this._byhour();\n        }\n    };\n    ToText.prototype.WEEKLY = function () {\n        var gettext = this.gettext;\n        if (this.options.interval !== 1) {\n            this.add(this.options.interval.toString()).add(this.plural(this.options.interval) ? gettext('weeks') : gettext('week'));\n        }\n        if (this.byweekday && this.byweekday.isWeekdays) {\n            if (this.options.interval === 1) {\n                this.add(this.plural(this.options.interval)\n                    ? gettext('weekdays')\n                    : gettext('weekday'));\n            }\n            else {\n                this.add(gettext('on')).add(gettext('weekdays'));\n            }\n        }\n        else if (this.byweekday && this.byweekday.isEveryDay) {\n            this.add(this.plural(this.options.interval) ? gettext('days') : gettext('day'));\n        }\n        else {\n            if (this.options.interval === 1)\n                this.add(gettext('week'));\n            if (this.origOptions.bymonth) {\n                this.add(gettext('in'));\n                this._bymonth();\n            }\n            if (this.bymonthday) {\n                this._bymonthday();\n            }\n            else if (this.byweekday) {\n                this._byweekday();\n            }\n            if (this.origOptions.byhour) {\n                this._byhour();\n            }\n        }\n    };\n    ToText.prototype.MONTHLY = function () {\n        var gettext = this.gettext;\n        if (this.origOptions.bymonth) {\n            if (this.options.interval !== 1) {\n                this.add(this.options.interval.toString()).add(gettext('months'));\n                if (this.plural(this.options.interval))\n                    this.add(gettext('in'));\n            }\n            else {\n                // this.add(gettext('MONTH'))\n            }\n            this._bymonth();\n        }\n        else {\n            if (this.options.interval !== 1) {\n                this.add(this.options.interval.toString());\n            }\n            this.add(this.plural(this.options.interval)\n                ? gettext('months')\n                : gettext('month'));\n        }\n        if (this.bymonthday) {\n            this._bymonthday();\n        }\n        else if (this.byweekday && this.byweekday.isWeekdays) {\n            this.add(gettext('on')).add(gettext('weekdays'));\n        }\n        else if (this.byweekday) {\n            this._byweekday();\n        }\n    };\n    ToText.prototype.YEARLY = function () {\n        var gettext = this.gettext;\n        if (this.origOptions.bymonth) {\n            if (this.options.interval !== 1) {\n                this.add(this.options.interval.toString());\n                this.add(gettext('years'));\n            }\n            else {\n                // this.add(gettext('YEAR'))\n            }\n            this._bymonth();\n        }\n        else {\n            if (this.options.interval !== 1) {\n                this.add(this.options.interval.toString());\n            }\n            this.add(this.plural(this.options.interval) ? gettext('years') : gettext('year'));\n        }\n        if (this.bymonthday) {\n            this._bymonthday();\n        }\n        else if (this.byweekday) {\n            this._byweekday();\n        }\n        if (this.options.byyearday) {\n            this.add(gettext('on the'))\n                .add(this.list(this.options.byyearday, this.nth, gettext('and')))\n                .add(gettext('day'));\n        }\n        if (this.options.byweekno) {\n            this.add(gettext('in'))\n                .add(this.plural(this.options.byweekno.length)\n                ? gettext('weeks')\n                : gettext('week'))\n                .add(this.list(this.options.byweekno, undefined, gettext('and')));\n        }\n    };\n    ToText.prototype._bymonthday = function () {\n        var gettext = this.gettext;\n        if (this.byweekday && this.byweekday.allWeeks) {\n            this.add(gettext('on'))\n                .add(this.list(this.byweekday.allWeeks, this.weekdaytext, gettext('or')))\n                .add(gettext('the'))\n                .add(this.list(this.bymonthday, this.nth, gettext('or')));\n        }\n        else {\n            this.add(gettext('on the')).add(this.list(this.bymonthday, this.nth, gettext('and')));\n        }\n        // this.add(gettext('DAY'))\n    };\n    ToText.prototype._byweekday = function () {\n        var gettext = this.gettext;\n        if (this.byweekday.allWeeks && !this.byweekday.isWeekdays) {\n            this.add(gettext('on')).add(this.list(this.byweekday.allWeeks, this.weekdaytext));\n        }\n        if (this.byweekday.someWeeks) {\n            if (this.byweekday.allWeeks)\n                this.add(gettext('and'));\n            this.add(gettext('on the')).add(this.list(this.byweekday.someWeeks, this.weekdaytext, gettext('and')));\n        }\n    };\n    ToText.prototype._byhour = function () {\n        var gettext = this.gettext;\n        this.add(gettext('at')).add(this.list(this.origOptions.byhour, undefined, gettext('and')));\n    };\n    ToText.prototype._bymonth = function () {\n        this.add(this.list(this.options.bymonth, this.monthtext, this.gettext('and')));\n    };\n    ToText.prototype.nth = function (n) {\n        n = parseInt(n.toString(), 10);\n        var nth;\n        var gettext = this.gettext;\n        if (n === -1)\n            return gettext('last');\n        var npos = Math.abs(n);\n        switch (npos) {\n            case 1:\n            case 21:\n            case 31:\n                nth = npos + gettext('st');\n                break;\n            case 2:\n            case 22:\n                nth = npos + gettext('nd');\n                break;\n            case 3:\n            case 23:\n                nth = npos + gettext('rd');\n                break;\n            default:\n                nth = npos + gettext('th');\n        }\n        return n < 0 ? nth + ' ' + gettext('last') : nth;\n    };\n    ToText.prototype.monthtext = function (m) {\n        return this.language.monthNames[m - 1];\n    };\n    ToText.prototype.weekdaytext = function (wday) {\n        var weekday = isNumber(wday) ? (wday + 1) % 7 : wday.getJsWeekday();\n        return ((wday.n ? this.nth(wday.n) + ' ' : '') +\n            this.language.dayNames[weekday]);\n    };\n    ToText.prototype.plural = function (n) {\n        return n % 100 !== 1;\n    };\n    ToText.prototype.add = function (s) {\n        this.text.push(' ');\n        this.text.push(s);\n        return this;\n    };\n    ToText.prototype.list = function (arr, callback, finalDelim, delim) {\n        var _this = this;\n        if (delim === void 0) { delim = ','; }\n        if (!isArray(arr)) {\n            arr = [arr];\n        }\n        var delimJoin = function (array, delimiter, finalDelimiter) {\n            var list = '';\n            for (var i = 0; i < array.length; i++) {\n                if (i !== 0) {\n                    if (i === array.length - 1) {\n                        list += ' ' + finalDelimiter + ' ';\n                    }\n                    else {\n                        list += delimiter + ' ';\n                    }\n                }\n                list += array[i];\n            }\n            return list;\n        };\n        callback =\n            callback ||\n                function (o) {\n                    return o.toString();\n                };\n        var realCallback = function (arg) {\n            return callback && callback.call(_this, arg);\n        };\n        if (finalDelim) {\n            return delimJoin(arr.map(realCallback), delim, finalDelim);\n        }\n        else {\n            return arr.map(realCallback).join(delim + ' ');\n        }\n    };\n    return ToText;\n}());\nexport default ToText;\n//# sourceMappingURL=totext.js.map","import ENGLISH from './i18n';\nimport { RRule } from '../rrule';\n// =============================================================================\n// Parser\n// =============================================================================\nvar Parser = /** @class */ (function () {\n    function Parser(rules) {\n        this.done = true;\n        this.rules = rules;\n    }\n    Parser.prototype.start = function (text) {\n        this.text = text;\n        this.done = false;\n        return this.nextSymbol();\n    };\n    Parser.prototype.isDone = function () {\n        return this.done && this.symbol === null;\n    };\n    Parser.prototype.nextSymbol = function () {\n        var best;\n        var bestSymbol;\n        this.symbol = null;\n        this.value = null;\n        do {\n            if (this.done)\n                return false;\n            var rule = void 0;\n            best = null;\n            for (var name_1 in this.rules) {\n                rule = this.rules[name_1];\n                var match = rule.exec(this.text);\n                if (match) {\n                    if (best === null || match[0].length > best[0].length) {\n                        best = match;\n                        bestSymbol = name_1;\n                    }\n                }\n            }\n            if (best != null) {\n                this.text = this.text.substr(best[0].length);\n                if (this.text === '')\n                    this.done = true;\n            }\n            if (best == null) {\n                this.done = true;\n                this.symbol = null;\n                this.value = null;\n                return;\n            }\n        } while (bestSymbol === 'SKIP');\n        this.symbol = bestSymbol;\n        this.value = best;\n        return true;\n    };\n    Parser.prototype.accept = function (name) {\n        if (this.symbol === name) {\n            if (this.value) {\n                var v = this.value;\n                this.nextSymbol();\n                return v;\n            }\n            this.nextSymbol();\n            return true;\n        }\n        return false;\n    };\n    Parser.prototype.acceptNumber = function () {\n        return this.accept('number');\n    };\n    Parser.prototype.expect = function (name) {\n        if (this.accept(name))\n            return true;\n        throw new Error('expected ' + name + ' but found ' + this.symbol);\n    };\n    return Parser;\n}());\nexport default function parseText(text, language) {\n    if (language === void 0) { language = ENGLISH; }\n    var options = {};\n    var ttr = new Parser(language.tokens);\n    if (!ttr.start(text))\n        return null;\n    S();\n    return options;\n    function S() {\n        // every [n]\n        ttr.expect('every');\n        var n = ttr.acceptNumber();\n        if (n)\n            options.interval = parseInt(n[0], 10);\n        if (ttr.isDone())\n            throw new Error('Unexpected end');\n        switch (ttr.symbol) {\n            case 'day(s)':\n                options.freq = RRule.DAILY;\n                if (ttr.nextSymbol()) {\n                    AT();\n                    F();\n                }\n                break;\n            // FIXME Note: every 2 weekdays != every two weeks on weekdays.\n            // DAILY on weekdays is not a valid rule\n            case 'weekday(s)':\n                options.freq = RRule.WEEKLY;\n                options.byweekday = [RRule.MO, RRule.TU, RRule.WE, RRule.TH, RRule.FR];\n                ttr.nextSymbol();\n                AT();\n                F();\n                break;\n            case 'week(s)':\n                options.freq = RRule.WEEKLY;\n                if (ttr.nextSymbol()) {\n                    ON();\n                    AT();\n                    F();\n                }\n                break;\n            case 'hour(s)':\n                options.freq = RRule.HOURLY;\n                if (ttr.nextSymbol()) {\n                    ON();\n                    F();\n                }\n                break;\n            case 'minute(s)':\n                options.freq = RRule.MINUTELY;\n                if (ttr.nextSymbol()) {\n                    ON();\n                    F();\n                }\n                break;\n            case 'month(s)':\n                options.freq = RRule.MONTHLY;\n                if (ttr.nextSymbol()) {\n                    ON();\n                    F();\n                }\n                break;\n            case 'year(s)':\n                options.freq = RRule.YEARLY;\n                if (ttr.nextSymbol()) {\n                    ON();\n                    F();\n                }\n                break;\n            case 'monday':\n            case 'tuesday':\n            case 'wednesday':\n            case 'thursday':\n            case 'friday':\n            case 'saturday':\n            case 'sunday':\n                options.freq = RRule.WEEKLY;\n                var key = ttr.symbol\n                    .substr(0, 2)\n                    .toUpperCase();\n                options.byweekday = [RRule[key]];\n                if (!ttr.nextSymbol())\n                    return;\n                // TODO check for duplicates\n                while (ttr.accept('comma')) {\n                    if (ttr.isDone())\n                        throw new Error('Unexpected end');\n                    var wkd = decodeWKD();\n                    if (!wkd) {\n                        throw new Error('Unexpected symbol ' + ttr.symbol + ', expected weekday');\n                    }\n                    options.byweekday.push(RRule[wkd]);\n                    ttr.nextSymbol();\n                }\n                AT();\n                MDAYs();\n                F();\n                break;\n            case 'january':\n            case 'february':\n            case 'march':\n            case 'april':\n            case 'may':\n            case 'june':\n            case 'july':\n            case 'august':\n            case 'september':\n            case 'october':\n            case 'november':\n            case 'december':\n                options.freq = RRule.YEARLY;\n                options.bymonth = [decodeM()];\n                if (!ttr.nextSymbol())\n                    return;\n                // TODO check for duplicates\n                while (ttr.accept('comma')) {\n                    if (ttr.isDone())\n                        throw new Error('Unexpected end');\n                    var m = decodeM();\n                    if (!m) {\n                        throw new Error('Unexpected symbol ' + ttr.symbol + ', expected month');\n                    }\n                    options.bymonth.push(m);\n                    ttr.nextSymbol();\n                }\n                ON();\n                F();\n                break;\n            default:\n                throw new Error('Unknown symbol');\n        }\n    }\n    function ON() {\n        var on = ttr.accept('on');\n        var the = ttr.accept('the');\n        if (!(on || the))\n            return;\n        do {\n            var nth = decodeNTH();\n            var wkd = decodeWKD();\n            var m = decodeM();\n            // nth <weekday> | <weekday>\n            if (nth) {\n                // ttr.nextSymbol()\n                if (wkd) {\n                    ttr.nextSymbol();\n                    if (!options.byweekday)\n                        options.byweekday = [];\n                    options.byweekday.push(RRule[wkd].nth(nth));\n                }\n                else {\n                    if (!options.bymonthday)\n                        options.bymonthday = [];\n                    options.bymonthday.push(nth);\n                    ttr.accept('day(s)');\n                }\n                // <weekday>\n            }\n            else if (wkd) {\n                ttr.nextSymbol();\n                if (!options.byweekday)\n                    options.byweekday = [];\n                options.byweekday.push(RRule[wkd]);\n            }\n            else if (ttr.symbol === 'weekday(s)') {\n                ttr.nextSymbol();\n                if (!options.byweekday) {\n                    options.byweekday = [RRule.MO, RRule.TU, RRule.WE, RRule.TH, RRule.FR];\n                }\n            }\n            else if (ttr.symbol === 'week(s)') {\n                ttr.nextSymbol();\n                var n = ttr.acceptNumber();\n                if (!n) {\n                    throw new Error('Unexpected symbol ' + ttr.symbol + ', expected week number');\n                }\n                options.byweekno = [parseInt(n[0], 10)];\n                while (ttr.accept('comma')) {\n                    n = ttr.acceptNumber();\n                    if (!n) {\n                        throw new Error('Unexpected symbol ' + ttr.symbol + '; expected monthday');\n                    }\n                    options.byweekno.push(parseInt(n[0], 10));\n                }\n            }\n            else if (m) {\n                ttr.nextSymbol();\n                if (!options.bymonth)\n                    options.bymonth = [];\n                options.bymonth.push(m);\n            }\n            else {\n                return;\n            }\n        } while (ttr.accept('comma') || ttr.accept('the') || ttr.accept('on'));\n    }\n    function AT() {\n        var at = ttr.accept('at');\n        if (!at)\n            return;\n        do {\n            var n = ttr.acceptNumber();\n            if (!n) {\n                throw new Error('Unexpected symbol ' + ttr.symbol + ', expected hour');\n            }\n            options.byhour = [parseInt(n[0], 10)];\n            while (ttr.accept('comma')) {\n                n = ttr.acceptNumber();\n                if (!n) {\n                    throw new Error('Unexpected symbol ' + ttr.symbol + '; expected hour');\n                }\n                options.byhour.push(parseInt(n[0], 10));\n            }\n        } while (ttr.accept('comma') || ttr.accept('at'));\n    }\n    function decodeM() {\n        switch (ttr.symbol) {\n            case 'january':\n                return 1;\n            case 'february':\n                return 2;\n            case 'march':\n                return 3;\n            case 'april':\n                return 4;\n            case 'may':\n                return 5;\n            case 'june':\n                return 6;\n            case 'july':\n                return 7;\n            case 'august':\n                return 8;\n            case 'september':\n                return 9;\n            case 'october':\n                return 10;\n            case 'november':\n                return 11;\n            case 'december':\n                return 12;\n            default:\n                return false;\n        }\n    }\n    function decodeWKD() {\n        switch (ttr.symbol) {\n            case 'monday':\n            case 'tuesday':\n            case 'wednesday':\n            case 'thursday':\n            case 'friday':\n            case 'saturday':\n            case 'sunday':\n                return ttr.symbol.substr(0, 2).toUpperCase();\n            default:\n                return false;\n        }\n    }\n    function decodeNTH() {\n        switch (ttr.symbol) {\n            case 'last':\n                ttr.nextSymbol();\n                return -1;\n            case 'first':\n                ttr.nextSymbol();\n                return 1;\n            case 'second':\n                ttr.nextSymbol();\n                return ttr.accept('last') ? -2 : 2;\n            case 'third':\n                ttr.nextSymbol();\n                return ttr.accept('last') ? -3 : 3;\n            case 'nth':\n                var v = parseInt(ttr.value[1], 10);\n                if (v < -366 || v > 366)\n                    throw new Error('Nth out of range: ' + v);\n                ttr.nextSymbol();\n                return ttr.accept('last') ? -v : v;\n            default:\n                return false;\n        }\n    }\n    function MDAYs() {\n        ttr.accept('on');\n        ttr.accept('the');\n        var nth = decodeNTH();\n        if (!nth)\n            return;\n        options.bymonthday = [nth];\n        ttr.nextSymbol();\n        while (ttr.accept('comma')) {\n            nth = decodeNTH();\n            if (!nth) {\n                throw new Error('Unexpected symbol ' + ttr.symbol + '; expected monthday');\n            }\n            options.bymonthday.push(nth);\n            ttr.nextSymbol();\n        }\n    }\n    function F() {\n        if (ttr.symbol === 'until') {\n            var date = Date.parse(ttr.text);\n            if (!date)\n                throw new Error('Cannot parse until date:' + ttr.text);\n            options.until = new Date(date);\n        }\n        else if (ttr.accept('for')) {\n            options.count = parseInt(ttr.value[0], 10);\n            ttr.expect('number');\n            // ttr.expect('times')\n        }\n    }\n}\n//# sourceMappingURL=parsetext.js.map","export var Frequency;\n(function (Frequency) {\n    Frequency[Frequency[\"YEARLY\"] = 0] = \"YEARLY\";\n    Frequency[Frequency[\"MONTHLY\"] = 1] = \"MONTHLY\";\n    Frequency[Frequency[\"WEEKLY\"] = 2] = \"WEEKLY\";\n    Frequency[Frequency[\"DAILY\"] = 3] = \"DAILY\";\n    Frequency[Frequency[\"HOURLY\"] = 4] = \"HOURLY\";\n    Frequency[Frequency[\"MINUTELY\"] = 5] = \"MINUTELY\";\n    Frequency[Frequency[\"SECONDLY\"] = 6] = \"SECONDLY\";\n})(Frequency || (Frequency = {}));\nexport function freqIsDailyOrGreater(freq) {\n    return freq < Frequency.HOURLY;\n}\n//# sourceMappingURL=types.js.map","import ToText from './totext';\nimport parseText from './parsetext';\nimport { RRule } from '../rrule';\nimport { Frequency } from '../types';\nimport ENGLISH from './i18n';\n/* !\n * rrule.js - Library for working with recurrence rules for calendar dates.\n * https://github.com/jakubroztocil/rrule\n *\n * Copyright 2010, Jakub Roztocil and Lars Schoning\n * Licenced under the BSD licence.\n * https://github.com/jakubroztocil/rrule/blob/master/LICENCE\n *\n */\n/**\n *\n * Implementation of RRule.fromText() and RRule::toText().\n *\n *\n * On the client side, this file needs to be included\n * when those functions are used.\n *\n */\n// =============================================================================\n// fromText\n// =============================================================================\n/**\n * Will be able to convert some of the below described rules from\n * text format to a rule object.\n *\n *\n * RULES\n *\n * Every ([n])\n * day(s)\n * | [weekday], ..., (and) [weekday]\n * | weekday(s)\n * | week(s)\n * | month(s)\n * | [month], ..., (and) [month]\n * | year(s)\n *\n *\n * Plus 0, 1, or multiple of these:\n *\n * on [weekday], ..., (or) [weekday] the [monthday], [monthday], ... (or) [monthday]\n *\n * on [weekday], ..., (and) [weekday]\n *\n * on the [monthday], [monthday], ... (and) [monthday] (day of the month)\n *\n * on the [nth-weekday], ..., (and) [nth-weekday] (of the month/year)\n *\n *\n * Plus 0 or 1 of these:\n *\n * for [n] time(s)\n *\n * until [date]\n *\n * Plus (.)\n *\n *\n * Definitely no supported for parsing:\n *\n * (for year):\n * in week(s) [n], ..., (and) [n]\n *\n * on the [yearday], ..., (and) [n] day of the year\n * on day [yearday], ..., (and) [n]\n *\n *\n * NON-TERMINALS\n *\n * [n]: 1, 2 ..., one, two, three ..\n * [month]: January, February, March, April, May, ... December\n * [weekday]: Monday, ... Sunday\n * [nth-weekday]: first [weekday], 2nd [weekday], ... last [weekday], ...\n * [monthday]: first, 1., 2., 1st, 2nd, second, ... 31st, last day, 2nd last day, ..\n * [date]:\n * - [month] (0-31(,) ([year])),\n * - (the) 0-31.(1-12.([year])),\n * - (the) 0-31/(1-12/([year])),\n * - [weekday]\n *\n * [year]: 0000, 0001, ... 01, 02, ..\n *\n * Definitely not supported for parsing:\n *\n * [yearday]: first, 1., 2., 1st, 2nd, second, ... 366th, last day, 2nd last day, ..\n *\n * @param {String} text\n * @return {Object, Boolean} the rule, or null.\n */\nvar fromText = function (text, language) {\n    if (language === void 0) { language = ENGLISH; }\n    return new RRule(parseText(text, language) || undefined);\n};\nvar common = [\n    'count',\n    'until',\n    'interval',\n    'byweekday',\n    'bymonthday',\n    'bymonth',\n];\nToText.IMPLEMENTED = [];\nToText.IMPLEMENTED[Frequency.HOURLY] = common;\nToText.IMPLEMENTED[Frequency.MINUTELY] = common;\nToText.IMPLEMENTED[Frequency.DAILY] = ['byhour'].concat(common);\nToText.IMPLEMENTED[Frequency.WEEKLY] = common;\nToText.IMPLEMENTED[Frequency.MONTHLY] = common;\nToText.IMPLEMENTED[Frequency.YEARLY] = ['byweekno', 'byyearday'].concat(common);\n// =============================================================================\n// Export\n// =============================================================================\nvar toText = function (rrule, gettext, language, dateFormatter) {\n    return new ToText(rrule, gettext, language, dateFormatter).toString();\n};\nvar isFullyConvertible = ToText.isFullyConvertible;\nexport { fromText, parseText, isFullyConvertible, toText };\n//# sourceMappingURL=index.js.map","import { __extends } from \"tslib\";\nimport { Frequency } from './types';\nimport { pymod, divmod, empty, includes } from './helpers';\nimport { getWeekday, MAXYEAR, monthRange } from './dateutil';\nvar Time = /** @class */ (function () {\n    function Time(hour, minute, second, millisecond) {\n        this.hour = hour;\n        this.minute = minute;\n        this.second = second;\n        this.millisecond = millisecond || 0;\n    }\n    Time.prototype.getHours = function () {\n        return this.hour;\n    };\n    Time.prototype.getMinutes = function () {\n        return this.minute;\n    };\n    Time.prototype.getSeconds = function () {\n        return this.second;\n    };\n    Time.prototype.getMilliseconds = function () {\n        return this.millisecond;\n    };\n    Time.prototype.getTime = function () {\n        return ((this.hour * 60 * 60 + this.minute * 60 + this.second) * 1000 +\n            this.millisecond);\n    };\n    return Time;\n}());\nexport { Time };\nvar DateTime = /** @class */ (function (_super) {\n    __extends(DateTime, _super);\n    function DateTime(year, month, day, hour, minute, second, millisecond) {\n        var _this = _super.call(this, hour, minute, second, millisecond) || this;\n        _this.year = year;\n        _this.month = month;\n        _this.day = day;\n        return _this;\n    }\n    DateTime.fromDate = function (date) {\n        return new this(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.valueOf() % 1000);\n    };\n    DateTime.prototype.getWeekday = function () {\n        return getWeekday(new Date(this.getTime()));\n    };\n    DateTime.prototype.getTime = function () {\n        return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond)).getTime();\n    };\n    DateTime.prototype.getDay = function () {\n        return this.day;\n    };\n    DateTime.prototype.getMonth = function () {\n        return this.month;\n    };\n    DateTime.prototype.getYear = function () {\n        return this.year;\n    };\n    DateTime.prototype.addYears = function (years) {\n        this.year += years;\n    };\n    DateTime.prototype.addMonths = function (months) {\n        this.month += months;\n        if (this.month > 12) {\n            var yearDiv = Math.floor(this.month / 12);\n            var monthMod = pymod(this.month, 12);\n            this.month = monthMod;\n            this.year += yearDiv;\n            if (this.month === 0) {\n                this.month = 12;\n                --this.year;\n            }\n        }\n    };\n    DateTime.prototype.addWeekly = function (days, wkst) {\n        if (wkst > this.getWeekday()) {\n            this.day += -(this.getWeekday() + 1 + (6 - wkst)) + days * 7;\n        }\n        else {\n            this.day += -(this.getWeekday() - wkst) + days * 7;\n        }\n        this.fixDay();\n    };\n    DateTime.prototype.addDaily = function (days) {\n        this.day += days;\n        this.fixDay();\n    };\n    DateTime.prototype.addHours = function (hours, filtered, byhour) {\n        if (filtered) {\n            // Jump to one iteration before next day\n            this.hour += Math.floor((23 - this.hour) / hours) * hours;\n        }\n        for (;;) {\n            this.hour += hours;\n            var _a = divmod(this.hour, 24), dayDiv = _a.div, hourMod = _a.mod;\n            if (dayDiv) {\n                this.hour = hourMod;\n                this.addDaily(dayDiv);\n            }\n            if (empty(byhour) || includes(byhour, this.hour))\n                break;\n        }\n    };\n    DateTime.prototype.addMinutes = function (minutes, filtered, byhour, byminute) {\n        if (filtered) {\n            // Jump to one iteration before next day\n            this.minute +=\n                Math.floor((1439 - (this.hour * 60 + this.minute)) / minutes) * minutes;\n        }\n        for (;;) {\n            this.minute += minutes;\n            var _a = divmod(this.minute, 60), hourDiv = _a.div, minuteMod = _a.mod;\n            if (hourDiv) {\n                this.minute = minuteMod;\n                this.addHours(hourDiv, false, byhour);\n            }\n            if ((empty(byhour) || includes(byhour, this.hour)) &&\n                (empty(byminute) || includes(byminute, this.minute))) {\n                break;\n            }\n        }\n    };\n    DateTime.prototype.addSeconds = function (seconds, filtered, byhour, byminute, bysecond) {\n        if (filtered) {\n            // Jump to one iteration before next day\n            this.second +=\n                Math.floor((86399 - (this.hour * 3600 + this.minute * 60 + this.second)) /\n                    seconds) * seconds;\n        }\n        for (;;) {\n            this.second += seconds;\n            var _a = divmod(this.second, 60), minuteDiv = _a.div, secondMod = _a.mod;\n            if (minuteDiv) {\n                this.second = secondMod;\n                this.addMinutes(minuteDiv, false, byhour, byminute);\n            }\n            if ((empty(byhour) || includes(byhour, this.hour)) &&\n                (empty(byminute) || includes(byminute, this.minute)) &&\n                (empty(bysecond) || includes(bysecond, this.second))) {\n                break;\n            }\n        }\n    };\n    DateTime.prototype.fixDay = function () {\n        if (this.day <= 28) {\n            return;\n        }\n        var daysinmonth = monthRange(this.year, this.month - 1)[1];\n        if (this.day <= daysinmonth) {\n            return;\n        }\n        while (this.day > daysinmonth) {\n            this.day -= daysinmonth;\n            ++this.month;\n            if (this.month === 13) {\n                this.month = 1;\n                ++this.year;\n                if (this.year > MAXYEAR) {\n                    return;\n                }\n            }\n            daysinmonth = monthRange(this.year, this.month - 1)[1];\n        }\n    };\n    DateTime.prototype.add = function (options, filtered) {\n        var freq = options.freq, interval = options.interval, wkst = options.wkst, byhour = options.byhour, byminute = options.byminute, bysecond = options.bysecond;\n        switch (freq) {\n            case Frequency.YEARLY:\n                return this.addYears(interval);\n            case Frequency.MONTHLY:\n                return this.addMonths(interval);\n            case Frequency.WEEKLY:\n                return this.addWeekly(interval, wkst);\n            case Frequency.DAILY:\n                return this.addDaily(interval);\n            case Frequency.HOURLY:\n                return this.addHours(interval, filtered, byhour);\n            case Frequency.MINUTELY:\n                return this.addMinutes(interval, filtered, byhour, byminute);\n            case Frequency.SECONDLY:\n                return this.addSeconds(interval, filtered, byhour, byminute, bysecond);\n        }\n    };\n    return DateTime;\n}(Time));\nexport { DateTime };\n//# sourceMappingURL=datetime.js.map","import { __assign } from \"tslib\";\nimport { freqIsDailyOrGreater } from './types';\nimport { includes, notEmpty, isPresent, isNumber, isArray, isWeekdayStr, } from './helpers';\nimport { RRule, defaultKeys, DEFAULT_OPTIONS } from './rrule';\nimport { getWeekday, isDate, isValidDate } from './dateutil';\nimport { Weekday } from './weekday';\nimport { Time } from './datetime';\nexport function initializeOptions(options) {\n    var invalid = [];\n    var keys = Object.keys(options);\n    // Shallow copy for options and origOptions and check for invalid\n    for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {\n        var key = keys_1[_i];\n        if (!includes(defaultKeys, key))\n            invalid.push(key);\n        if (isDate(options[key]) && !isValidDate(options[key])) {\n            invalid.push(key);\n        }\n    }\n    if (invalid.length) {\n        throw new Error('Invalid options: ' + invalid.join(', '));\n    }\n    return __assign({}, options);\n}\nexport function parseOptions(options) {\n    var opts = __assign(__assign({}, DEFAULT_OPTIONS), initializeOptions(options));\n    if (isPresent(opts.byeaster))\n        opts.freq = RRule.YEARLY;\n    if (!(isPresent(opts.freq) && RRule.FREQUENCIES[opts.freq])) {\n        throw new Error(\"Invalid frequency: \".concat(opts.freq, \" \").concat(options.freq));\n    }\n    if (!opts.dtstart)\n        opts.dtstart = new Date(new Date().setMilliseconds(0));\n    if (!isPresent(opts.wkst)) {\n        opts.wkst = RRule.MO.weekday;\n    }\n    else if (isNumber(opts.wkst)) {\n        // cool, just keep it like that\n    }\n    else {\n        opts.wkst = opts.wkst.weekday;\n    }\n    if (isPresent(opts.bysetpos)) {\n        if (isNumber(opts.bysetpos))\n            opts.bysetpos = [opts.bysetpos];\n        for (var i = 0; i < opts.bysetpos.length; i++) {\n            var v = opts.bysetpos[i];\n            if (v === 0 || !(v >= -366 && v <= 366)) {\n                throw new Error('bysetpos must be between 1 and 366,' + ' or between -366 and -1');\n            }\n        }\n    }\n    if (!(Boolean(opts.byweekno) ||\n        notEmpty(opts.byweekno) ||\n        notEmpty(opts.byyearday) ||\n        Boolean(opts.bymonthday) ||\n        notEmpty(opts.bymonthday) ||\n        isPresent(opts.byweekday) ||\n        isPresent(opts.byeaster))) {\n        switch (opts.freq) {\n            case RRule.YEARLY:\n                if (!opts.bymonth)\n                    opts.bymonth = opts.dtstart.getUTCMonth() + 1;\n                opts.bymonthday = opts.dtstart.getUTCDate();\n                break;\n            case RRule.MONTHLY:\n                opts.bymonthday = opts.dtstart.getUTCDate();\n                break;\n            case RRule.WEEKLY:\n                opts.byweekday = [getWeekday(opts.dtstart)];\n                break;\n        }\n    }\n    // bymonth\n    if (isPresent(opts.bymonth) && !isArray(opts.bymonth)) {\n        opts.bymonth = [opts.bymonth];\n    }\n    // byyearday\n    if (isPresent(opts.byyearday) &&\n        !isArray(opts.byyearday) &&\n        isNumber(opts.byyearday)) {\n        opts.byyearday = [opts.byyearday];\n    }\n    // bymonthday\n    if (!isPresent(opts.bymonthday)) {\n        opts.bymonthday = [];\n        opts.bynmonthday = [];\n    }\n    else if (isArray(opts.bymonthday)) {\n        var bymonthday = [];\n        var bynmonthday = [];\n        for (var i = 0; i < opts.bymonthday.length; i++) {\n            var v = opts.bymonthday[i];\n            if (v > 0) {\n                bymonthday.push(v);\n            }\n            else if (v < 0) {\n                bynmonthday.push(v);\n            }\n        }\n        opts.bymonthday = bymonthday;\n        opts.bynmonthday = bynmonthday;\n    }\n    else if (opts.bymonthday < 0) {\n        opts.bynmonthday = [opts.bymonthday];\n        opts.bymonthday = [];\n    }\n    else {\n        opts.bynmonthday = [];\n        opts.bymonthday = [opts.bymonthday];\n    }\n    // byweekno\n    if (isPresent(opts.byweekno) && !isArray(opts.byweekno)) {\n        opts.byweekno = [opts.byweekno];\n    }\n    // byweekday / bynweekday\n    if (!isPresent(opts.byweekday)) {\n        opts.bynweekday = null;\n    }\n    else if (isNumber(opts.byweekday)) {\n        opts.byweekday = [opts.byweekday];\n        opts.bynweekday = null;\n    }\n    else if (isWeekdayStr(opts.byweekday)) {\n        opts.byweekday = [Weekday.fromStr(opts.byweekday).weekday];\n        opts.bynweekday = null;\n    }\n    else if (opts.byweekday instanceof Weekday) {\n        if (!opts.byweekday.n || opts.freq > RRule.MONTHLY) {\n            opts.byweekday = [opts.byweekday.weekday];\n            opts.bynweekday = null;\n        }\n        else {\n            opts.bynweekday = [[opts.byweekday.weekday, opts.byweekday.n]];\n            opts.byweekday = null;\n        }\n    }\n    else {\n        var byweekday = [];\n        var bynweekday = [];\n        for (var i = 0; i < opts.byweekday.length; i++) {\n            var wday = opts.byweekday[i];\n            if (isNumber(wday)) {\n                byweekday.push(wday);\n                continue;\n            }\n            else if (isWeekdayStr(wday)) {\n                byweekday.push(Weekday.fromStr(wday).weekday);\n                continue;\n            }\n            if (!wday.n || opts.freq > RRule.MONTHLY) {\n                byweekday.push(wday.weekday);\n            }\n            else {\n                bynweekday.push([wday.weekday, wday.n]);\n            }\n        }\n        opts.byweekday = notEmpty(byweekday) ? byweekday : null;\n        opts.bynweekday = notEmpty(bynweekday) ? bynweekday : null;\n    }\n    // byhour\n    if (!isPresent(opts.byhour)) {\n        opts.byhour = opts.freq < RRule.HOURLY ? [opts.dtstart.getUTCHours()] : null;\n    }\n    else if (isNumber(opts.byhour)) {\n        opts.byhour = [opts.byhour];\n    }\n    // byminute\n    if (!isPresent(opts.byminute)) {\n        opts.byminute =\n            opts.freq < RRule.MINUTELY ? [opts.dtstart.getUTCMinutes()] : null;\n    }\n    else if (isNumber(opts.byminute)) {\n        opts.byminute = [opts.byminute];\n    }\n    // bysecond\n    if (!isPresent(opts.bysecond)) {\n        opts.bysecond =\n            opts.freq < RRule.SECONDLY ? [opts.dtstart.getUTCSeconds()] : null;\n    }\n    else if (isNumber(opts.bysecond)) {\n        opts.bysecond = [opts.bysecond];\n    }\n    return { parsedOptions: opts };\n}\nexport function buildTimeset(opts) {\n    var millisecondModulo = opts.dtstart.getTime() % 1000;\n    if (!freqIsDailyOrGreater(opts.freq)) {\n        return [];\n    }\n    var timeset = [];\n    opts.byhour.forEach(function (hour) {\n        opts.byminute.forEach(function (minute) {\n            opts.bysecond.forEach(function (second) {\n                timeset.push(new Time(hour, minute, second, millisecondModulo));\n            });\n        });\n    });\n    return timeset;\n}\n//# sourceMappingURL=parseoptions.js.map","import { __assign } from \"tslib\";\nimport { Frequency } from './types';\nimport { Weekday } from './weekday';\nimport { untilStringToDate } from './dateutil';\nimport { Days } from './rrule';\nexport function parseString(rfcString) {\n    var options = rfcString\n        .split('\\n')\n        .map(parseLine)\n        .filter(function (x) { return x !== null; });\n    return __assign(__assign({}, options[0]), options[1]);\n}\nexport function parseDtstart(line) {\n    var options = {};\n    var dtstartWithZone = /DTSTART(?:;TZID=([^:=]+?))?(?::|=)([^;\\s]+)/i.exec(line);\n    if (!dtstartWithZone) {\n        return options;\n    }\n    var tzid = dtstartWithZone[1], dtstart = dtstartWithZone[2];\n    if (tzid) {\n        options.tzid = tzid;\n    }\n    options.dtstart = untilStringToDate(dtstart);\n    return options;\n}\nfunction parseLine(rfcString) {\n    rfcString = rfcString.replace(/^\\s+|\\s+$/, '');\n    if (!rfcString.length)\n        return null;\n    var header = /^([A-Z]+?)[:;]/.exec(rfcString.toUpperCase());\n    if (!header) {\n        return parseRrule(rfcString);\n    }\n    var key = header[1];\n    switch (key.toUpperCase()) {\n        case 'RRULE':\n        case 'EXRULE':\n            return parseRrule(rfcString);\n        case 'DTSTART':\n            return parseDtstart(rfcString);\n        default:\n            throw new Error(\"Unsupported RFC prop \".concat(key, \" in \").concat(rfcString));\n    }\n}\nfunction parseRrule(line) {\n    var strippedLine = line.replace(/^RRULE:/i, '');\n    var options = parseDtstart(strippedLine);\n    var attrs = line.replace(/^(?:RRULE|EXRULE):/i, '').split(';');\n    attrs.forEach(function (attr) {\n        var _a = attr.split('='), key = _a[0], value = _a[1];\n        switch (key.toUpperCase()) {\n            case 'FREQ':\n                options.freq = Frequency[value.toUpperCase()];\n                break;\n            case 'WKST':\n                options.wkst = Days[value.toUpperCase()];\n                break;\n            case 'COUNT':\n            case 'INTERVAL':\n            case 'BYSETPOS':\n            case 'BYMONTH':\n            case 'BYMONTHDAY':\n            case 'BYYEARDAY':\n            case 'BYWEEKNO':\n            case 'BYHOUR':\n            case 'BYMINUTE':\n            case 'BYSECOND':\n                var num = parseNumber(value);\n                var optionKey = key.toLowerCase();\n                // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n                // @ts-ignore\n                options[optionKey] = num;\n                break;\n            case 'BYWEEKDAY':\n            case 'BYDAY':\n                options.byweekday = parseWeekday(value);\n                break;\n            case 'DTSTART':\n            case 'TZID':\n                // for backwards compatibility\n                var dtstart = parseDtstart(line);\n                options.tzid = dtstart.tzid;\n                options.dtstart = dtstart.dtstart;\n                break;\n            case 'UNTIL':\n                options.until = untilStringToDate(value);\n                break;\n            case 'BYEASTER':\n                options.byeaster = Number(value);\n                break;\n            default:\n                throw new Error(\"Unknown RRULE property '\" + key + \"'\");\n        }\n    });\n    return options;\n}\nfunction parseNumber(value) {\n    if (value.indexOf(',') !== -1) {\n        var values = value.split(',');\n        return values.map(parseIndividualNumber);\n    }\n    return parseIndividualNumber(value);\n}\nfunction parseIndividualNumber(value) {\n    if (/^[+-]?\\d+$/.test(value)) {\n        return Number(value);\n    }\n    return value;\n}\nfunction parseWeekday(value) {\n    var days = value.split(',');\n    return days.map(function (day) {\n        if (day.length === 2) {\n            // MO, TU, ...\n            return Days[day]; // wday instanceof Weekday\n        }\n        // -1MO, +3FR, 1SO, 13TU ...\n        var parts = day.match(/^([+-]?\\d{1,2})([A-Z]{2})$/);\n        if (!parts || parts.length < 3) {\n            throw new SyntaxError(\"Invalid weekday string: \".concat(day));\n        }\n        var n = Number(parts[1]);\n        var wdaypart = parts[2];\n        var wday = Days[wdaypart].weekday;\n        return new Weekday(wday, n);\n    });\n}\n//# sourceMappingURL=parsestring.js.map","import { dateInTimeZone, timeToUntilString } from './dateutil';\nvar DateWithZone = /** @class */ (function () {\n    function DateWithZone(date, tzid) {\n        if (isNaN(date.getTime())) {\n            throw new RangeError('Invalid date passed to DateWithZone');\n        }\n        this.date = date;\n        this.tzid = tzid;\n    }\n    Object.defineProperty(DateWithZone.prototype, \"isUTC\", {\n        get: function () {\n            return !this.tzid || this.tzid.toUpperCase() === 'UTC';\n        },\n        enumerable: false,\n        configurable: true\n    });\n    DateWithZone.prototype.toString = function () {\n        var datestr = timeToUntilString(this.date.getTime(), this.isUTC);\n        if (!this.isUTC) {\n            return \";TZID=\".concat(this.tzid, \":\").concat(datestr);\n        }\n        return \":\".concat(datestr);\n    };\n    DateWithZone.prototype.getTime = function () {\n        return this.date.getTime();\n    };\n    DateWithZone.prototype.rezonedDate = function () {\n        if (this.isUTC) {\n            return this.date;\n        }\n        return dateInTimeZone(this.date, this.tzid);\n    };\n    return DateWithZone;\n}());\nexport { DateWithZone };\n//# sourceMappingURL=datewithzone.js.map","import { RRule, DEFAULT_OPTIONS } from './rrule';\nimport { includes, isPresent, isArray, isNumber, toArray } from './helpers';\nimport { Weekday } from './weekday';\nimport { timeToUntilString } from './dateutil';\nimport { DateWithZone } from './datewithzone';\nexport function optionsToString(options) {\n    var rrule = [];\n    var dtstart = '';\n    var keys = Object.keys(options);\n    var defaultKeys = Object.keys(DEFAULT_OPTIONS);\n    for (var i = 0; i < keys.length; i++) {\n        if (keys[i] === 'tzid')\n            continue;\n        if (!includes(defaultKeys, keys[i]))\n            continue;\n        var key = keys[i].toUpperCase();\n        var value = options[keys[i]];\n        var outValue = '';\n        if (!isPresent(value) || (isArray(value) && !value.length))\n            continue;\n        switch (key) {\n            case 'FREQ':\n                outValue = RRule.FREQUENCIES[options.freq];\n                break;\n            case 'WKST':\n                if (isNumber(value)) {\n                    outValue = new Weekday(value).toString();\n                }\n                else {\n                    outValue = value.toString();\n                }\n                break;\n            case 'BYWEEKDAY':\n                /*\n                  NOTE: BYWEEKDAY is a special case.\n                  RRule() deconstructs the rule.options.byweekday array\n                  into an array of Weekday arguments.\n                  On the other hand, rule.origOptions is an array of Weekdays.\n                  We need to handle both cases here.\n                  It might be worth change RRule to keep the Weekdays.\n        \n                  Also, BYWEEKDAY (used by RRule) vs. BYDAY (RFC)\n        \n                  */\n                key = 'BYDAY';\n                outValue = toArray(value)\n                    .map(function (wday) {\n                    if (wday instanceof Weekday) {\n                        return wday;\n                    }\n                    if (isArray(wday)) {\n                        return new Weekday(wday[0], wday[1]);\n                    }\n                    return new Weekday(wday);\n                })\n                    .toString();\n                break;\n            case 'DTSTART':\n                dtstart = buildDtstart(value, options.tzid);\n                break;\n            case 'UNTIL':\n                outValue = timeToUntilString(value, !options.tzid);\n                break;\n            default:\n                if (isArray(value)) {\n                    var strValues = [];\n                    for (var j = 0; j < value.length; j++) {\n                        strValues[j] = String(value[j]);\n                    }\n                    outValue = strValues.toString();\n                }\n                else {\n                    outValue = String(value);\n                }\n        }\n        if (outValue) {\n            rrule.push([key, outValue]);\n        }\n    }\n    var rules = rrule\n        .map(function (_a) {\n        var key = _a[0], value = _a[1];\n        return \"\".concat(key, \"=\").concat(value.toString());\n    })\n        .join(';');\n    var ruleString = '';\n    if (rules !== '') {\n        ruleString = \"RRULE:\".concat(rules);\n    }\n    return [dtstart, ruleString].filter(function (x) { return !!x; }).join('\\n');\n}\nfunction buildDtstart(dtstart, tzid) {\n    if (!dtstart) {\n        return '';\n    }\n    return 'DTSTART' + new DateWithZone(new Date(dtstart), tzid).toString();\n}\n//# sourceMappingURL=optionstostring.js.map","import IterResult from './iterresult';\nimport { clone, cloneDates } from './dateutil';\nimport { isArray } from './helpers';\nfunction argsMatch(left, right) {\n    if (Array.isArray(left)) {\n        if (!Array.isArray(right))\n            return false;\n        if (left.length !== right.length)\n            return false;\n        return left.every(function (date, i) { return date.getTime() === right[i].getTime(); });\n    }\n    if (left instanceof Date) {\n        return right instanceof Date && left.getTime() === right.getTime();\n    }\n    return left === right;\n}\nvar Cache = /** @class */ (function () {\n    function Cache() {\n        this.all = false;\n        this.before = [];\n        this.after = [];\n        this.between = [];\n    }\n    /**\n     * @param {String} what - all/before/after/between\n     * @param {Array,Date} value - an array of dates, one date, or null\n     * @param {Object?} args - _iter arguments\n     */\n    Cache.prototype._cacheAdd = function (what, value, args) {\n        if (value) {\n            value = value instanceof Date ? clone(value) : cloneDates(value);\n        }\n        if (what === 'all') {\n            this.all = value;\n        }\n        else {\n            args._value = value;\n            this[what].push(args);\n        }\n    };\n    /**\n     * @return false - not in the cache\n     * @return null  - cached, but zero occurrences (before/after)\n     * @return Date  - cached (before/after)\n     * @return []    - cached, but zero occurrences (all/between)\n     * @return [Date1, DateN] - cached (all/between)\n     */\n    Cache.prototype._cacheGet = function (what, args) {\n        var cached = false;\n        var argsKeys = args ? Object.keys(args) : [];\n        var findCacheDiff = function (item) {\n            for (var i = 0; i < argsKeys.length; i++) {\n                var key = argsKeys[i];\n                if (!argsMatch(args[key], item[key])) {\n                    return true;\n                }\n            }\n            return false;\n        };\n        var cachedObject = this[what];\n        if (what === 'all') {\n            cached = this.all;\n        }\n        else if (isArray(cachedObject)) {\n            // Let's see whether we've already called the\n            // 'what' method with the same 'args'\n            for (var i = 0; i < cachedObject.length; i++) {\n                var item = cachedObject[i];\n                if (argsKeys.length && findCacheDiff(item))\n                    continue;\n                cached = item._value;\n                break;\n            }\n        }\n        if (!cached && this.all) {\n            // Not in the cache, but we already know all the occurrences,\n            // so we can find the correct dates from the cached ones.\n            var iterResult = new IterResult(what, args);\n            for (var i = 0; i < this.all.length; i++) {\n                if (!iterResult.accept(this.all[i]))\n                    break;\n            }\n            cached = iterResult.getValue();\n            this._cacheAdd(what, cached, args);\n        }\n        return isArray(cached)\n            ? cloneDates(cached)\n            : cached instanceof Date\n                ? clone(cached)\n                : cached;\n    };\n    return Cache;\n}());\nexport { Cache };\n//# sourceMappingURL=cache.js.map","import { __spreadArray } from \"tslib\";\nimport { range, repeat } from './helpers';\n// =============================================================================\n// Date masks\n// =============================================================================\n// Every mask is 7 days longer to handle cross-year weekly periods.\nvar M365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], repeat(1, 31), true), repeat(2, 28), true), repeat(3, 31), true), repeat(4, 30), true), repeat(5, 31), true), repeat(6, 30), true), repeat(7, 31), true), repeat(8, 31), true), repeat(9, 30), true), repeat(10, 31), true), repeat(11, 30), true), repeat(12, 31), true), repeat(1, 7), true);\nvar M366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], repeat(1, 31), true), repeat(2, 29), true), repeat(3, 31), true), repeat(4, 30), true), repeat(5, 31), true), repeat(6, 30), true), repeat(7, 31), true), repeat(8, 31), true), repeat(9, 30), true), repeat(10, 31), true), repeat(11, 30), true), repeat(12, 31), true), repeat(1, 7), true);\nvar M28 = range(1, 29);\nvar M29 = range(1, 30);\nvar M30 = range(1, 31);\nvar M31 = range(1, 32);\nvar MDAY366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], M31, true), M29, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31.slice(0, 7), true);\nvar MDAY365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], M31, true), M28, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31.slice(0, 7), true);\nvar NM28 = range(-28, 0);\nvar NM29 = range(-29, 0);\nvar NM30 = range(-30, 0);\nvar NM31 = range(-31, 0);\nvar NMDAY366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], NM31, true), NM29, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31.slice(0, 7), true);\nvar NMDAY365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], NM31, true), NM28, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31.slice(0, 7), true);\nvar M366RANGE = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366];\nvar M365RANGE = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];\nvar WDAYMASK = (function () {\n    var wdaymask = [];\n    for (var i = 0; i < 55; i++)\n        wdaymask = wdaymask.concat(range(7));\n    return wdaymask;\n})();\nexport { WDAYMASK, M365MASK, M365RANGE, M366MASK, M366RANGE, MDAY365MASK, MDAY366MASK, NMDAY365MASK, NMDAY366MASK, };\n//# sourceMappingURL=masks.js.map","import { __assign } from \"tslib\";\nimport { datetime, getWeekday, isLeapYear, toOrdinal } from '../dateutil';\nimport { empty, repeat, pymod, includes } from '../helpers';\nimport { M365MASK, MDAY365MASK, NMDAY365MASK, WDAYMASK, M365RANGE, M366MASK, MDAY366MASK, NMDAY366MASK, M366RANGE, } from '../masks';\nexport function rebuildYear(year, options) {\n    var firstyday = datetime(year, 1, 1);\n    var yearlen = isLeapYear(year) ? 366 : 365;\n    var nextyearlen = isLeapYear(year + 1) ? 366 : 365;\n    var yearordinal = toOrdinal(firstyday);\n    var yearweekday = getWeekday(firstyday);\n    var result = __assign(__assign({ yearlen: yearlen, nextyearlen: nextyearlen, yearordinal: yearordinal, yearweekday: yearweekday }, baseYearMasks(year)), { wnomask: null });\n    if (empty(options.byweekno)) {\n        return result;\n    }\n    result.wnomask = repeat(0, yearlen + 7);\n    var firstwkst;\n    var wyearlen;\n    var no1wkst = (firstwkst = pymod(7 - yearweekday + options.wkst, 7));\n    if (no1wkst >= 4) {\n        no1wkst = 0;\n        // Number of days in the year, plus the days we got\n        // from last year.\n        wyearlen = result.yearlen + pymod(yearweekday - options.wkst, 7);\n    }\n    else {\n        // Number of days in the year, minus the days we\n        // left in last year.\n        wyearlen = yearlen - no1wkst;\n    }\n    var div = Math.floor(wyearlen / 7);\n    var mod = pymod(wyearlen, 7);\n    var numweeks = Math.floor(div + mod / 4);\n    for (var j = 0; j < options.byweekno.length; j++) {\n        var n = options.byweekno[j];\n        if (n < 0) {\n            n += numweeks + 1;\n        }\n        if (!(n > 0 && n <= numweeks)) {\n            continue;\n        }\n        var i = void 0;\n        if (n > 1) {\n            i = no1wkst + (n - 1) * 7;\n            if (no1wkst !== firstwkst) {\n                i -= 7 - firstwkst;\n            }\n        }\n        else {\n            i = no1wkst;\n        }\n        for (var k = 0; k < 7; k++) {\n            result.wnomask[i] = 1;\n            i++;\n            if (result.wdaymask[i] === options.wkst)\n                break;\n        }\n    }\n    if (includes(options.byweekno, 1)) {\n        // Check week number 1 of next year as well\n        // orig-TODO : Check -numweeks for next year.\n        var i = no1wkst + numweeks * 7;\n        if (no1wkst !== firstwkst)\n            i -= 7 - firstwkst;\n        if (i < yearlen) {\n            // If week starts in next year, we\n            // don't care about it.\n            for (var j = 0; j < 7; j++) {\n                result.wnomask[i] = 1;\n                i += 1;\n                if (result.wdaymask[i] === options.wkst)\n                    break;\n            }\n        }\n    }\n    if (no1wkst) {\n        // Check last week number of last year as\n        // well. If no1wkst is 0, either the year\n        // started on week start, or week number 1\n        // got days from last year, so there are no\n        // days from last year's last week number in\n        // this year.\n        var lnumweeks = void 0;\n        if (!includes(options.byweekno, -1)) {\n            var lyearweekday = getWeekday(datetime(year - 1, 1, 1));\n            var lno1wkst = pymod(7 - lyearweekday.valueOf() + options.wkst, 7);\n            var lyearlen = isLeapYear(year - 1) ? 366 : 365;\n            var weekst = void 0;\n            if (lno1wkst >= 4) {\n                lno1wkst = 0;\n                weekst = lyearlen + pymod(lyearweekday - options.wkst, 7);\n            }\n            else {\n                weekst = yearlen - no1wkst;\n            }\n            lnumweeks = Math.floor(52 + pymod(weekst, 7) / 4);\n        }\n        else {\n            lnumweeks = -1;\n        }\n        if (includes(options.byweekno, lnumweeks)) {\n            for (var i = 0; i < no1wkst; i++)\n                result.wnomask[i] = 1;\n        }\n    }\n    return result;\n}\nfunction baseYearMasks(year) {\n    var yearlen = isLeapYear(year) ? 366 : 365;\n    var firstyday = datetime(year, 1, 1);\n    var wday = getWeekday(firstyday);\n    if (yearlen === 365) {\n        return {\n            mmask: M365MASK,\n            mdaymask: MDAY365MASK,\n            nmdaymask: NMDAY365MASK,\n            wdaymask: WDAYMASK.slice(wday),\n            mrange: M365RANGE,\n        };\n    }\n    return {\n        mmask: M366MASK,\n        mdaymask: MDAY366MASK,\n        nmdaymask: NMDAY366MASK,\n        wdaymask: WDAYMASK.slice(wday),\n        mrange: M366RANGE,\n    };\n}\n//# sourceMappingURL=yearinfo.js.map","import { RRule } from '../rrule';\nimport { empty, repeat, pymod } from '../helpers';\nexport function rebuildMonth(year, month, yearlen, mrange, wdaymask, options) {\n    var result = {\n        lastyear: year,\n        lastmonth: month,\n        nwdaymask: [],\n    };\n    var ranges = [];\n    if (options.freq === RRule.YEARLY) {\n        if (empty(options.bymonth)) {\n            ranges = [[0, yearlen]];\n        }\n        else {\n            for (var j = 0; j < options.bymonth.length; j++) {\n                month = options.bymonth[j];\n                ranges.push(mrange.slice(month - 1, month + 1));\n            }\n        }\n    }\n    else if (options.freq === RRule.MONTHLY) {\n        ranges = [mrange.slice(month - 1, month + 1)];\n    }\n    if (empty(ranges)) {\n        return result;\n    }\n    // Weekly frequency won't get here, so we may not\n    // care about cross-year weekly periods.\n    result.nwdaymask = repeat(0, yearlen);\n    for (var j = 0; j < ranges.length; j++) {\n        var rang = ranges[j];\n        var first = rang[0];\n        var last = rang[1] - 1;\n        for (var k = 0; k < options.bynweekday.length; k++) {\n            var i = void 0;\n            var _a = options.bynweekday[k], wday = _a[0], n = _a[1];\n            if (n < 0) {\n                i = last + (n + 1) * 7;\n                i -= pymod(wdaymask[i] - wday, 7);\n            }\n            else {\n                i = first + (n - 1) * 7;\n                i += pymod(7 - wdaymask[i] + wday, 7);\n            }\n            if (first <= i && i <= last)\n                result.nwdaymask[i] = 1;\n        }\n    }\n    return result;\n}\n//# sourceMappingURL=monthinfo.js.map","export function easter(y, offset) {\n    if (offset === void 0) { offset = 0; }\n    var a = y % 19;\n    var b = Math.floor(y / 100);\n    var c = y % 100;\n    var d = Math.floor(b / 4);\n    var e = b % 4;\n    var f = Math.floor((b + 8) / 25);\n    var g = Math.floor((b - f + 1) / 3);\n    var h = Math.floor(19 * a + b - d - g + 15) % 30;\n    var i = Math.floor(c / 4);\n    var k = c % 4;\n    var l = Math.floor(32 + 2 * e + 2 * i - h - k) % 7;\n    var m = Math.floor((a + 11 * h + 22 * l) / 451);\n    var month = Math.floor((h + l - 7 * m + 114) / 31);\n    var day = ((h + l - 7 * m + 114) % 31) + 1;\n    var date = Date.UTC(y, month - 1, day + offset);\n    var yearStart = Date.UTC(y, 0, 1);\n    return [Math.ceil((date - yearStart) / (1000 * 60 * 60 * 24))];\n}\n//# sourceMappingURL=easter.js.map","import { notEmpty, repeat, range, isPresent } from '../helpers';\nimport { Frequency } from '../types';\nimport { rebuildYear } from './yearinfo';\nimport { rebuildMonth } from './monthinfo';\nimport { easter } from './easter';\nimport { Time } from '../datetime';\nimport { datetime, sort, toOrdinal } from '../dateutil';\n// =============================================================================\n// Iterinfo\n// =============================================================================\nvar Iterinfo = /** @class */ (function () {\n    // eslint-disable-next-line no-empty-function\n    function Iterinfo(options) {\n        this.options = options;\n    }\n    Iterinfo.prototype.rebuild = function (year, month) {\n        var options = this.options;\n        if (year !== this.lastyear) {\n            this.yearinfo = rebuildYear(year, options);\n        }\n        if (notEmpty(options.bynweekday) &&\n            (month !== this.lastmonth || year !== this.lastyear)) {\n            var _a = this.yearinfo, yearlen = _a.yearlen, mrange = _a.mrange, wdaymask = _a.wdaymask;\n            this.monthinfo = rebuildMonth(year, month, yearlen, mrange, wdaymask, options);\n        }\n        if (isPresent(options.byeaster)) {\n            this.eastermask = easter(year, options.byeaster);\n        }\n    };\n    Object.defineProperty(Iterinfo.prototype, \"lastyear\", {\n        get: function () {\n            return this.monthinfo ? this.monthinfo.lastyear : null;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"lastmonth\", {\n        get: function () {\n            return this.monthinfo ? this.monthinfo.lastmonth : null;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"yearlen\", {\n        get: function () {\n            return this.yearinfo.yearlen;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"yearordinal\", {\n        get: function () {\n            return this.yearinfo.yearordinal;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"mrange\", {\n        get: function () {\n            return this.yearinfo.mrange;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"wdaymask\", {\n        get: function () {\n            return this.yearinfo.wdaymask;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"mmask\", {\n        get: function () {\n            return this.yearinfo.mmask;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"wnomask\", {\n        get: function () {\n            return this.yearinfo.wnomask;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"nwdaymask\", {\n        get: function () {\n            return this.monthinfo ? this.monthinfo.nwdaymask : [];\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"nextyearlen\", {\n        get: function () {\n            return this.yearinfo.nextyearlen;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"mdaymask\", {\n        get: function () {\n            return this.yearinfo.mdaymask;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Object.defineProperty(Iterinfo.prototype, \"nmdaymask\", {\n        get: function () {\n            return this.yearinfo.nmdaymask;\n        },\n        enumerable: false,\n        configurable: true\n    });\n    Iterinfo.prototype.ydayset = function () {\n        return [range(this.yearlen), 0, this.yearlen];\n    };\n    Iterinfo.prototype.mdayset = function (_, month) {\n        var start = this.mrange[month - 1];\n        var end = this.mrange[month];\n        var set = repeat(null, this.yearlen);\n        for (var i = start; i < end; i++)\n            set[i] = i;\n        return [set, start, end];\n    };\n    Iterinfo.prototype.wdayset = function (year, month, day) {\n        // We need to handle cross-year weeks here.\n        var set = repeat(null, this.yearlen + 7);\n        var i = toOrdinal(datetime(year, month, day)) - this.yearordinal;\n        var start = i;\n        for (var j = 0; j < 7; j++) {\n            set[i] = i;\n            ++i;\n            if (this.wdaymask[i] === this.options.wkst)\n                break;\n        }\n        return [set, start, i];\n    };\n    Iterinfo.prototype.ddayset = function (year, month, day) {\n        var set = repeat(null, this.yearlen);\n        var i = toOrdinal(datetime(year, month, day)) - this.yearordinal;\n        set[i] = i;\n        return [set, i, i + 1];\n    };\n    Iterinfo.prototype.htimeset = function (hour, _, second, millisecond) {\n        var _this = this;\n        var set = [];\n        this.options.byminute.forEach(function (minute) {\n            set = set.concat(_this.mtimeset(hour, minute, second, millisecond));\n        });\n        sort(set);\n        return set;\n    };\n    Iterinfo.prototype.mtimeset = function (hour, minute, _, millisecond) {\n        var set = this.options.bysecond.map(function (second) { return new Time(hour, minute, second, millisecond); });\n        sort(set);\n        return set;\n    };\n    Iterinfo.prototype.stimeset = function (hour, minute, second, millisecond) {\n        return [new Time(hour, minute, second, millisecond)];\n    };\n    Iterinfo.prototype.getdayset = function (freq) {\n        switch (freq) {\n            case Frequency.YEARLY:\n                return this.ydayset.bind(this);\n            case Frequency.MONTHLY:\n                return this.mdayset.bind(this);\n            case Frequency.WEEKLY:\n                return this.wdayset.bind(this);\n            case Frequency.DAILY:\n                return this.ddayset.bind(this);\n            default:\n                return this.ddayset.bind(this);\n        }\n    };\n    Iterinfo.prototype.gettimeset = function (freq) {\n        switch (freq) {\n            case Frequency.HOURLY:\n                return this.htimeset.bind(this);\n            case Frequency.MINUTELY:\n                return this.mtimeset.bind(this);\n            case Frequency.SECONDLY:\n                return this.stimeset.bind(this);\n        }\n    };\n    return Iterinfo;\n}());\nexport default Iterinfo;\n//# sourceMappingURL=index.js.map","import { combine, fromOrdinal, sort } from '../dateutil';\nimport { pymod, isPresent, includes } from '../helpers';\nexport function buildPoslist(bysetpos, timeset, start, end, ii, dayset) {\n    var poslist = [];\n    for (var j = 0; j < bysetpos.length; j++) {\n        var daypos = void 0;\n        var timepos = void 0;\n        var pos = bysetpos[j];\n        if (pos < 0) {\n            daypos = Math.floor(pos / timeset.length);\n            timepos = pymod(pos, timeset.length);\n        }\n        else {\n            daypos = Math.floor((pos - 1) / timeset.length);\n            timepos = pymod(pos - 1, timeset.length);\n        }\n        var tmp = [];\n        for (var k = start; k < end; k++) {\n            var val = dayset[k];\n            if (!isPresent(val))\n                continue;\n            tmp.push(val);\n        }\n        var i = void 0;\n        if (daypos < 0) {\n            i = tmp.slice(daypos)[0];\n        }\n        else {\n            i = tmp[daypos];\n        }\n        var time = timeset[timepos];\n        var date = fromOrdinal(ii.yearordinal + i);\n        var res = combine(date, time);\n        // XXX: can this ever be in the array?\n        // - compare the actual date instead?\n        if (!includes(poslist, res))\n            poslist.push(res);\n    }\n    sort(poslist);\n    return poslist;\n}\n//# sourceMappingURL=poslist.js.map","import { freqIsDailyOrGreater } from '../types';\nimport { combine, fromOrdinal, MAXYEAR } from '../dateutil';\nimport Iterinfo from '../iterinfo/index';\nimport { RRule } from '../rrule';\nimport { buildTimeset } from '../parseoptions';\nimport { notEmpty, includes, isPresent } from '../helpers';\nimport { DateWithZone } from '../datewithzone';\nimport { buildPoslist } from './poslist';\nimport { DateTime } from '../datetime';\nexport function iter(iterResult, options) {\n    var dtstart = options.dtstart, freq = options.freq, interval = options.interval, until = options.until, bysetpos = options.bysetpos;\n    var count = options.count;\n    if (count === 0 || interval === 0) {\n        return emitResult(iterResult);\n    }\n    var counterDate = DateTime.fromDate(dtstart);\n    var ii = new Iterinfo(options);\n    ii.rebuild(counterDate.year, counterDate.month);\n    var timeset = makeTimeset(ii, counterDate, options);\n    for (;;) {\n        var _a = ii.getdayset(freq)(counterDate.year, counterDate.month, counterDate.day), dayset = _a[0], start = _a[1], end = _a[2];\n        var filtered = removeFilteredDays(dayset, start, end, ii, options);\n        if (notEmpty(bysetpos)) {\n            var poslist = buildPoslist(bysetpos, timeset, start, end, ii, dayset);\n            for (var j = 0; j < poslist.length; j++) {\n                var res = poslist[j];\n                if (until && res > until) {\n                    return emitResult(iterResult);\n                }\n                if (res >= dtstart) {\n                    var rezonedDate = rezoneIfNeeded(res, options);\n                    if (!iterResult.accept(rezonedDate)) {\n                        return emitResult(iterResult);\n                    }\n                    if (count) {\n                        --count;\n                        if (!count) {\n                            return emitResult(iterResult);\n                        }\n                    }\n                }\n            }\n        }\n        else {\n            for (var j = start; j < end; j++) {\n                var currentDay = dayset[j];\n                if (!isPresent(currentDay)) {\n                    continue;\n                }\n                var date = fromOrdinal(ii.yearordinal + currentDay);\n                for (var k = 0; k < timeset.length; k++) {\n                    var time = timeset[k];\n                    var res = combine(date, time);\n                    if (until && res > until) {\n                        return emitResult(iterResult);\n                    }\n                    if (res >= dtstart) {\n                        var rezonedDate = rezoneIfNeeded(res, options);\n                        if (!iterResult.accept(rezonedDate)) {\n                            return emitResult(iterResult);\n                        }\n                        if (count) {\n                            --count;\n                            if (!count) {\n                                return emitResult(iterResult);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        if (options.interval === 0) {\n            return emitResult(iterResult);\n        }\n        // Handle frequency and interval\n        counterDate.add(options, filtered);\n        if (counterDate.year > MAXYEAR) {\n            return emitResult(iterResult);\n        }\n        if (!freqIsDailyOrGreater(freq)) {\n            timeset = ii.gettimeset(freq)(counterDate.hour, counterDate.minute, counterDate.second, 0);\n        }\n        ii.rebuild(counterDate.year, counterDate.month);\n    }\n}\nfunction isFiltered(ii, currentDay, options) {\n    var bymonth = options.bymonth, byweekno = options.byweekno, byweekday = options.byweekday, byeaster = options.byeaster, bymonthday = options.bymonthday, bynmonthday = options.bynmonthday, byyearday = options.byyearday;\n    return ((notEmpty(bymonth) && !includes(bymonth, ii.mmask[currentDay])) ||\n        (notEmpty(byweekno) && !ii.wnomask[currentDay]) ||\n        (notEmpty(byweekday) && !includes(byweekday, ii.wdaymask[currentDay])) ||\n        (notEmpty(ii.nwdaymask) && !ii.nwdaymask[currentDay]) ||\n        (byeaster !== null && !includes(ii.eastermask, currentDay)) ||\n        ((notEmpty(bymonthday) || notEmpty(bynmonthday)) &&\n            !includes(bymonthday, ii.mdaymask[currentDay]) &&\n            !includes(bynmonthday, ii.nmdaymask[currentDay])) ||\n        (notEmpty(byyearday) &&\n            ((currentDay < ii.yearlen &&\n                !includes(byyearday, currentDay + 1) &&\n                !includes(byyearday, -ii.yearlen + currentDay)) ||\n                (currentDay >= ii.yearlen &&\n                    !includes(byyearday, currentDay + 1 - ii.yearlen) &&\n                    !includes(byyearday, -ii.nextyearlen + currentDay - ii.yearlen)))));\n}\nfunction rezoneIfNeeded(date, options) {\n    return new DateWithZone(date, options.tzid).rezonedDate();\n}\nfunction emitResult(iterResult) {\n    return iterResult.getValue();\n}\nfunction removeFilteredDays(dayset, start, end, ii, options) {\n    var filtered = false;\n    for (var dayCounter = start; dayCounter < end; dayCounter++) {\n        var currentDay = dayset[dayCounter];\n        filtered = isFiltered(ii, currentDay, options);\n        if (filtered)\n            dayset[currentDay] = null;\n    }\n    return filtered;\n}\nfunction makeTimeset(ii, counterDate, options) {\n    var freq = options.freq, byhour = options.byhour, byminute = options.byminute, bysecond = options.bysecond;\n    if (freqIsDailyOrGreater(freq)) {\n        return buildTimeset(options);\n    }\n    if ((freq >= RRule.HOURLY &&\n        notEmpty(byhour) &&\n        !includes(byhour, counterDate.hour)) ||\n        (freq >= RRule.MINUTELY &&\n            notEmpty(byminute) &&\n            !includes(byminute, counterDate.minute)) ||\n        (freq >= RRule.SECONDLY &&\n            notEmpty(bysecond) &&\n            !includes(bysecond, counterDate.second))) {\n        return [];\n    }\n    return ii.gettimeset(freq)(counterDate.hour, counterDate.minute, counterDate.second, counterDate.millisecond);\n}\n//# sourceMappingURL=index.js.map","import { isValidDate } from './dateutil';\nimport IterResult from './iterresult';\nimport CallbackIterResult from './callbackiterresult';\nimport { fromText, parseText, toText, isFullyConvertible } from './nlp/index';\nimport { Frequency, } from './types';\nimport { parseOptions, initializeOptions } from './parseoptions';\nimport { parseString } from './parsestring';\nimport { optionsToString } from './optionstostring';\nimport { Cache } from './cache';\nimport { Weekday } from './weekday';\nimport { iter } from './iter/index';\n// =============================================================================\n// RRule\n// =============================================================================\nexport var Days = {\n    MO: new Weekday(0),\n    TU: new Weekday(1),\n    WE: new Weekday(2),\n    TH: new Weekday(3),\n    FR: new Weekday(4),\n    SA: new Weekday(5),\n    SU: new Weekday(6),\n};\nexport var DEFAULT_OPTIONS = {\n    freq: Frequency.YEARLY,\n    dtstart: null,\n    interval: 1,\n    wkst: Days.MO,\n    count: null,\n    until: null,\n    tzid: null,\n    bysetpos: null,\n    bymonth: null,\n    bymonthday: null,\n    bynmonthday: null,\n    byyearday: null,\n    byweekno: null,\n    byweekday: null,\n    bynweekday: null,\n    byhour: null,\n    byminute: null,\n    bysecond: null,\n    byeaster: null,\n};\nexport var defaultKeys = Object.keys(DEFAULT_OPTIONS);\n/**\n *\n * @param {Options?} options - see <http://labix.org/python-dateutil/#head-cf004ee9a75592797e076752b2a889c10f445418>\n * - The only required option is `freq`, one of RRule.YEARLY, RRule.MONTHLY, ...\n * @constructor\n */\nvar RRule = /** @class */ (function () {\n    function RRule(options, noCache) {\n        if (options === void 0) { options = {}; }\n        if (noCache === void 0) { noCache = false; }\n        // RFC string\n        this._cache = noCache ? null : new Cache();\n        // used by toString()\n        this.origOptions = initializeOptions(options);\n        var parsedOptions = parseOptions(options).parsedOptions;\n        this.options = parsedOptions;\n    }\n    RRule.parseText = function (text, language) {\n        return parseText(text, language);\n    };\n    RRule.fromText = function (text, language) {\n        return fromText(text, language);\n    };\n    RRule.fromString = function (str) {\n        return new RRule(RRule.parseString(str) || undefined);\n    };\n    RRule.prototype._iter = function (iterResult) {\n        return iter(iterResult, this.options);\n    };\n    RRule.prototype._cacheGet = function (what, args) {\n        if (!this._cache)\n            return false;\n        return this._cache._cacheGet(what, args);\n    };\n    RRule.prototype._cacheAdd = function (what, value, args) {\n        if (!this._cache)\n            return;\n        return this._cache._cacheAdd(what, value, args);\n    };\n    /**\n     * @param {Function} iterator - optional function that will be called\n     * on each date that is added. It can return false\n     * to stop the iteration.\n     * @return Array containing all recurrences.\n     */\n    RRule.prototype.all = function (iterator) {\n        if (iterator) {\n            return this._iter(new CallbackIterResult('all', {}, iterator));\n        }\n        var result = this._cacheGet('all');\n        if (result === false) {\n            result = this._iter(new IterResult('all', {}));\n            this._cacheAdd('all', result);\n        }\n        return result;\n    };\n    /**\n     * Returns all the occurrences of the rrule between after and before.\n     * The inc keyword defines what happens if after and/or before are\n     * themselves occurrences. With inc == True, they will be included in the\n     * list, if they are found in the recurrence set.\n     *\n     * @return Array\n     */\n    RRule.prototype.between = function (after, before, inc, iterator) {\n        if (inc === void 0) { inc = false; }\n        if (!isValidDate(after) || !isValidDate(before)) {\n            throw new Error('Invalid date passed in to RRule.between');\n        }\n        var args = {\n            before: before,\n            after: after,\n            inc: inc,\n        };\n        if (iterator) {\n            return this._iter(new CallbackIterResult('between', args, iterator));\n        }\n        var result = this._cacheGet('between', args);\n        if (result === false) {\n            result = this._iter(new IterResult('between', args));\n            this._cacheAdd('between', result, args);\n        }\n        return result;\n    };\n    /**\n     * Returns the last recurrence before the given datetime instance.\n     * The inc keyword defines what happens if dt is an occurrence.\n     * With inc == True, if dt itself is an occurrence, it will be returned.\n     *\n     * @return Date or null\n     */\n    RRule.prototype.before = function (dt, inc) {\n        if (inc === void 0) { inc = false; }\n        if (!isValidDate(dt)) {\n            throw new Error('Invalid date passed in to RRule.before');\n        }\n        var args = { dt: dt, inc: inc };\n        var result = this._cacheGet('before', args);\n        if (result === false) {\n            result = this._iter(new IterResult('before', args));\n            this._cacheAdd('before', result, args);\n        }\n        return result;\n    };\n    /**\n     * Returns the first recurrence after the given datetime instance.\n     * The inc keyword defines what happens if dt is an occurrence.\n     * With inc == True, if dt itself is an occurrence, it will be returned.\n     *\n     * @return Date or null\n     */\n    RRule.prototype.after = function (dt, inc) {\n        if (inc === void 0) { inc = false; }\n        if (!isValidDate(dt)) {\n            throw new Error('Invalid date passed in to RRule.after');\n        }\n        var args = { dt: dt, inc: inc };\n        var result = this._cacheGet('after', args);\n        if (result === false) {\n            result = this._iter(new IterResult('after', args));\n            this._cacheAdd('after', result, args);\n        }\n        return result;\n    };\n    /**\n     * Returns the number of recurrences in this set. It will have go trough\n     * the whole recurrence, if this hasn't been done before.\n     */\n    RRule.prototype.count = function () {\n        return this.all().length;\n    };\n    /**\n     * Converts the rrule into its string representation\n     *\n     * @see <http://www.ietf.org/rfc/rfc2445.txt>\n     * @return String\n     */\n    RRule.prototype.toString = function () {\n        return optionsToString(this.origOptions);\n    };\n    /**\n     * Will convert all rules described in nlp:ToText\n     * to text.\n     */\n    RRule.prototype.toText = function (gettext, language, dateFormatter) {\n        return toText(this, gettext, language, dateFormatter);\n    };\n    RRule.prototype.isFullyConvertibleToText = function () {\n        return isFullyConvertible(this);\n    };\n    /**\n     * @return a RRule instance with the same freq and options\n     * as this one (cache is not cloned)\n     */\n    RRule.prototype.clone = function () {\n        return new RRule(this.origOptions);\n    };\n    // RRule class 'constants'\n    RRule.FREQUENCIES = [\n        'YEARLY',\n        'MONTHLY',\n        'WEEKLY',\n        'DAILY',\n        'HOURLY',\n        'MINUTELY',\n        'SECONDLY',\n    ];\n    RRule.YEARLY = Frequency.YEARLY;\n    RRule.MONTHLY = Frequency.MONTHLY;\n    RRule.WEEKLY = Frequency.WEEKLY;\n    RRule.DAILY = Frequency.DAILY;\n    RRule.HOURLY = Frequency.HOURLY;\n    RRule.MINUTELY = Frequency.MINUTELY;\n    RRule.SECONDLY = Frequency.SECONDLY;\n    RRule.MO = Days.MO;\n    RRule.TU = Days.TU;\n    RRule.WE = Days.WE;\n    RRule.TH = Days.TH;\n    RRule.FR = Days.FR;\n    RRule.SA = Days.SA;\n    RRule.SU = Days.SU;\n    RRule.parseString = parseString;\n    RRule.optionsToString = optionsToString;\n    return RRule;\n}());\nexport { RRule };\n//# sourceMappingURL=rrule.js.map","import { DateWithZone } from './datewithzone';\nimport { iter } from './iter';\nimport { sort } from './dateutil';\nexport function iterSet(iterResult, _rrule, _exrule, _rdate, _exdate, tzid) {\n    var _exdateHash = {};\n    var _accept = iterResult.accept;\n    function evalExdate(after, before) {\n        _exrule.forEach(function (rrule) {\n            rrule.between(after, before, true).forEach(function (date) {\n                _exdateHash[Number(date)] = true;\n            });\n        });\n    }\n    _exdate.forEach(function (date) {\n        var zonedDate = new DateWithZone(date, tzid).rezonedDate();\n        _exdateHash[Number(zonedDate)] = true;\n    });\n    iterResult.accept = function (date) {\n        var dt = Number(date);\n        if (isNaN(dt))\n            return _accept.call(this, date);\n        if (!_exdateHash[dt]) {\n            evalExdate(new Date(dt - 1), new Date(dt + 1));\n            if (!_exdateHash[dt]) {\n                _exdateHash[dt] = true;\n                return _accept.call(this, date);\n            }\n        }\n        return true;\n    };\n    if (iterResult.method === 'between') {\n        evalExdate(iterResult.args.after, iterResult.args.before);\n        iterResult.accept = function (date) {\n            var dt = Number(date);\n            if (!_exdateHash[dt]) {\n                _exdateHash[dt] = true;\n                return _accept.call(this, date);\n            }\n            return true;\n        };\n    }\n    for (var i = 0; i < _rdate.length; i++) {\n        var zonedDate = new DateWithZone(_rdate[i], tzid).rezonedDate();\n        if (!iterResult.accept(new Date(zonedDate.getTime())))\n            break;\n    }\n    _rrule.forEach(function (rrule) {\n        iter(iterResult, rrule.options);\n    });\n    var res = iterResult._result;\n    sort(res);\n    switch (iterResult.method) {\n        case 'all':\n        case 'between':\n            return res;\n        case 'before':\n            return ((res.length && res[res.length - 1]) || null);\n        case 'after':\n        default:\n            return ((res.length && res[0]) || null);\n    }\n}\n//# sourceMappingURL=iterset.js.map","import { __assign } from \"tslib\";\nimport { RRule } from './rrule';\nimport { RRuleSet } from './rruleset';\nimport { untilStringToDate } from './dateutil';\nimport { includes, split } from './helpers';\nimport { parseString, parseDtstart } from './parsestring';\n/**\n * RRuleStr\n * To parse a set of rrule strings\n */\nvar DEFAULT_OPTIONS = {\n    dtstart: null,\n    cache: false,\n    unfold: false,\n    forceset: false,\n    compatible: false,\n    tzid: null,\n};\nexport function parseInput(s, options) {\n    var rrulevals = [];\n    var rdatevals = [];\n    var exrulevals = [];\n    var exdatevals = [];\n    var parsedDtstart = parseDtstart(s);\n    var dtstart = parsedDtstart.dtstart;\n    var tzid = parsedDtstart.tzid;\n    var lines = splitIntoLines(s, options.unfold);\n    lines.forEach(function (line) {\n        var _a;\n        if (!line)\n            return;\n        var _b = breakDownLine(line), name = _b.name, parms = _b.parms, value = _b.value;\n        switch (name.toUpperCase()) {\n            case 'RRULE':\n                if (parms.length) {\n                    throw new Error(\"unsupported RRULE parm: \".concat(parms.join(',')));\n                }\n                rrulevals.push(parseString(line));\n                break;\n            case 'RDATE':\n                var _c = (_a = /RDATE(?:;TZID=([^:=]+))?/i.exec(line)) !== null && _a !== void 0 ? _a : [], rdateTzid = _c[1];\n                if (rdateTzid && !tzid) {\n                    tzid = rdateTzid;\n                }\n                rdatevals = rdatevals.concat(parseRDate(value, parms));\n                break;\n            case 'EXRULE':\n                if (parms.length) {\n                    throw new Error(\"unsupported EXRULE parm: \".concat(parms.join(',')));\n                }\n                exrulevals.push(parseString(value));\n                break;\n            case 'EXDATE':\n                exdatevals = exdatevals.concat(parseRDate(value, parms));\n                break;\n            case 'DTSTART':\n                break;\n            default:\n                throw new Error('unsupported property: ' + name);\n        }\n    });\n    return {\n        dtstart: dtstart,\n        tzid: tzid,\n        rrulevals: rrulevals,\n        rdatevals: rdatevals,\n        exrulevals: exrulevals,\n        exdatevals: exdatevals,\n    };\n}\nfunction buildRule(s, options) {\n    var _a = parseInput(s, options), rrulevals = _a.rrulevals, rdatevals = _a.rdatevals, exrulevals = _a.exrulevals, exdatevals = _a.exdatevals, dtstart = _a.dtstart, tzid = _a.tzid;\n    var noCache = options.cache === false;\n    if (options.compatible) {\n        options.forceset = true;\n        options.unfold = true;\n    }\n    if (options.forceset ||\n        rrulevals.length > 1 ||\n        rdatevals.length ||\n        exrulevals.length ||\n        exdatevals.length) {\n        var rset_1 = new RRuleSet(noCache);\n        rset_1.dtstart(dtstart);\n        rset_1.tzid(tzid || undefined);\n        rrulevals.forEach(function (val) {\n            rset_1.rrule(new RRule(groomRruleOptions(val, dtstart, tzid), noCache));\n        });\n        rdatevals.forEach(function (date) {\n            rset_1.rdate(date);\n        });\n        exrulevals.forEach(function (val) {\n            rset_1.exrule(new RRule(groomRruleOptions(val, dtstart, tzid), noCache));\n        });\n        exdatevals.forEach(function (date) {\n            rset_1.exdate(date);\n        });\n        if (options.compatible && options.dtstart)\n            rset_1.rdate(dtstart);\n        return rset_1;\n    }\n    var val = rrulevals[0] || {};\n    return new RRule(groomRruleOptions(val, val.dtstart || options.dtstart || dtstart, val.tzid || options.tzid || tzid), noCache);\n}\nexport function rrulestr(s, options) {\n    if (options === void 0) { options = {}; }\n    return buildRule(s, initializeOptions(options));\n}\nfunction groomRruleOptions(val, dtstart, tzid) {\n    return __assign(__assign({}, val), { dtstart: dtstart, tzid: tzid });\n}\nfunction initializeOptions(options) {\n    var invalid = [];\n    var keys = Object.keys(options);\n    var defaultKeys = Object.keys(DEFAULT_OPTIONS);\n    keys.forEach(function (key) {\n        if (!includes(defaultKeys, key))\n            invalid.push(key);\n    });\n    if (invalid.length) {\n        throw new Error('Invalid options: ' + invalid.join(', '));\n    }\n    return __assign(__assign({}, DEFAULT_OPTIONS), options);\n}\nfunction extractName(line) {\n    if (line.indexOf(':') === -1) {\n        return {\n            name: 'RRULE',\n            value: line,\n        };\n    }\n    var _a = split(line, ':', 1), name = _a[0], value = _a[1];\n    return {\n        name: name,\n        value: value,\n    };\n}\nfunction breakDownLine(line) {\n    var _a = extractName(line), name = _a.name, value = _a.value;\n    var parms = name.split(';');\n    if (!parms)\n        throw new Error('empty property name');\n    return {\n        name: parms[0].toUpperCase(),\n        parms: parms.slice(1),\n        value: value,\n    };\n}\nfunction splitIntoLines(s, unfold) {\n    if (unfold === void 0) { unfold = false; }\n    s = s && s.trim();\n    if (!s)\n        throw new Error('Invalid empty string');\n    // More info about 'unfold' option\n    // Go head to http://www.ietf.org/rfc/rfc2445.txt\n    if (!unfold) {\n        return s.split(/\\s/);\n    }\n    var lines = s.split('\\n');\n    var i = 0;\n    while (i < lines.length) {\n        // TODO\n        var line = (lines[i] = lines[i].replace(/\\s+$/g, ''));\n        if (!line) {\n            lines.splice(i, 1);\n        }\n        else if (i > 0 && line[0] === ' ') {\n            lines[i - 1] += line.slice(1);\n            lines.splice(i, 1);\n        }\n        else {\n            i += 1;\n        }\n    }\n    return lines;\n}\nfunction validateDateParm(parms) {\n    parms.forEach(function (parm) {\n        if (!/(VALUE=DATE(-TIME)?)|(TZID=)/.test(parm)) {\n            throw new Error('unsupported RDATE/EXDATE parm: ' + parm);\n        }\n    });\n}\nfunction parseRDate(rdateval, parms) {\n    validateDateParm(parms);\n    return rdateval.split(',').map(function (datestr) { return untilStringToDate(datestr); });\n}\n//# sourceMappingURL=rrulestr.js.map","import { __extends } from \"tslib\";\nimport { RRule } from './rrule';\nimport { sort, timeToUntilString } from './dateutil';\nimport { includes } from './helpers';\nimport { iterSet } from './iterset';\nimport { rrulestr } from './rrulestr';\nimport { optionsToString } from './optionstostring';\nfunction createGetterSetter(fieldName) {\n    var _this = this;\n    return function (field) {\n        if (field !== undefined) {\n            _this[\"_\".concat(fieldName)] = field;\n        }\n        if (_this[\"_\".concat(fieldName)] !== undefined) {\n            return _this[\"_\".concat(fieldName)];\n        }\n        for (var i = 0; i < _this._rrule.length; i++) {\n            var field_1 = _this._rrule[i].origOptions[fieldName];\n            if (field_1) {\n                return field_1;\n            }\n        }\n    };\n}\nvar RRuleSet = /** @class */ (function (_super) {\n    __extends(RRuleSet, _super);\n    /**\n     *\n     * @param {Boolean?} noCache\n     * The same stratagy as RRule on cache, default to false\n     * @constructor\n     */\n    function RRuleSet(noCache) {\n        if (noCache === void 0) { noCache = false; }\n        var _this = _super.call(this, {}, noCache) || this;\n        _this.dtstart = createGetterSetter.apply(_this, ['dtstart']);\n        _this.tzid = createGetterSetter.apply(_this, ['tzid']);\n        _this._rrule = [];\n        _this._rdate = [];\n        _this._exrule = [];\n        _this._exdate = [];\n        return _this;\n    }\n    RRuleSet.prototype._iter = function (iterResult) {\n        return iterSet(iterResult, this._rrule, this._exrule, this._rdate, this._exdate, this.tzid());\n    };\n    /**\n     * Adds an RRule to the set\n     *\n     * @param {RRule}\n     */\n    RRuleSet.prototype.rrule = function (rrule) {\n        _addRule(rrule, this._rrule);\n    };\n    /**\n     * Adds an EXRULE to the set\n     *\n     * @param {RRule}\n     */\n    RRuleSet.prototype.exrule = function (rrule) {\n        _addRule(rrule, this._exrule);\n    };\n    /**\n     * Adds an RDate to the set\n     *\n     * @param {Date}\n     */\n    RRuleSet.prototype.rdate = function (date) {\n        _addDate(date, this._rdate);\n    };\n    /**\n     * Adds an EXDATE to the set\n     *\n     * @param {Date}\n     */\n    RRuleSet.prototype.exdate = function (date) {\n        _addDate(date, this._exdate);\n    };\n    /**\n     * Get list of included rrules in this recurrence set.\n     *\n     * @return List of rrules\n     */\n    RRuleSet.prototype.rrules = function () {\n        return this._rrule.map(function (e) { return rrulestr(e.toString()); });\n    };\n    /**\n     * Get list of excluded rrules in this recurrence set.\n     *\n     * @return List of exrules\n     */\n    RRuleSet.prototype.exrules = function () {\n        return this._exrule.map(function (e) { return rrulestr(e.toString()); });\n    };\n    /**\n     * Get list of included datetimes in this recurrence set.\n     *\n     * @return List of rdates\n     */\n    RRuleSet.prototype.rdates = function () {\n        return this._rdate.map(function (e) { return new Date(e.getTime()); });\n    };\n    /**\n     * Get list of included datetimes in this recurrence set.\n     *\n     * @return List of exdates\n     */\n    RRuleSet.prototype.exdates = function () {\n        return this._exdate.map(function (e) { return new Date(e.getTime()); });\n    };\n    RRuleSet.prototype.valueOf = function () {\n        var result = [];\n        if (!this._rrule.length && this._dtstart) {\n            result = result.concat(optionsToString({ dtstart: this._dtstart }));\n        }\n        this._rrule.forEach(function (rrule) {\n            result = result.concat(rrule.toString().split('\\n'));\n        });\n        this._exrule.forEach(function (exrule) {\n            result = result.concat(exrule\n                .toString()\n                .split('\\n')\n                .map(function (line) { return line.replace(/^RRULE:/, 'EXRULE:'); })\n                .filter(function (line) { return !/^DTSTART/.test(line); }));\n        });\n        if (this._rdate.length) {\n            result.push(rdatesToString('RDATE', this._rdate, this.tzid()));\n        }\n        if (this._exdate.length) {\n            result.push(rdatesToString('EXDATE', this._exdate, this.tzid()));\n        }\n        return result;\n    };\n    /**\n     * to generate recurrence field such as:\n     * DTSTART:19970902T010000Z\n     * RRULE:FREQ=YEARLY;COUNT=2;BYDAY=TU\n     * RRULE:FREQ=YEARLY;COUNT=1;BYDAY=TH\n     */\n    RRuleSet.prototype.toString = function () {\n        return this.valueOf().join('\\n');\n    };\n    /**\n     * Create a new RRuleSet Object completely base on current instance\n     */\n    RRuleSet.prototype.clone = function () {\n        var rrs = new RRuleSet(!!this._cache);\n        this._rrule.forEach(function (rule) { return rrs.rrule(rule.clone()); });\n        this._exrule.forEach(function (rule) { return rrs.exrule(rule.clone()); });\n        this._rdate.forEach(function (date) { return rrs.rdate(new Date(date.getTime())); });\n        this._exdate.forEach(function (date) { return rrs.exdate(new Date(date.getTime())); });\n        return rrs;\n    };\n    return RRuleSet;\n}(RRule));\nexport { RRuleSet };\nfunction _addRule(rrule, collection) {\n    if (!(rrule instanceof RRule)) {\n        throw new TypeError(String(rrule) + ' is not RRule instance');\n    }\n    if (!includes(collection.map(String), String(rrule))) {\n        collection.push(rrule);\n    }\n}\nfunction _addDate(date, collection) {\n    if (!(date instanceof Date)) {\n        throw new TypeError(String(date) + ' is not Date instance');\n    }\n    if (!includes(collection.map(Number), Number(date))) {\n        collection.push(date);\n        sort(collection);\n    }\n}\nfunction rdatesToString(param, rdates, tzid) {\n    var isUTC = !tzid || tzid.toUpperCase() === 'UTC';\n    var header = isUTC ? \"\".concat(param, \":\") : \"\".concat(param, \";TZID=\").concat(tzid, \":\");\n    var dateString = rdates\n        .map(function (rdate) { return timeToUntilString(rdate.valueOf(), isUTC); })\n        .join(',');\n    return \"\".concat(header).concat(dateString);\n}\n//# sourceMappingURL=rruleset.js.map","import { rrulestr } from \"rrule\";\r\n\r\nimport { RRuleFinnish } from \"../../helpers\";\r\nimport { InputBase } from \"./_InputBase\";\r\n\r\n\r\n\r\n/**\r\n * Controller for Recurrence Rule (RRule) edit input\r\n */\r\n\r\nexport class InputRruleController extends InputBase<string> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /**\r\n   * Creates a new InputController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    super();\r\n  }\r\n\r\n  /**\r\n   * Gets the recurrence rule as human readable text.\r\n   * @param rrule The iCalendar Recurrence rule that should be interpreted.\r\n   */\r\n   public getRRuleText(rrule: string) {\r\n    const rule = rrulestr(rrule, {\r\n      // dtstart: Dates.asDate,\r\n    });\r\n    return rule.toText((id) => {\r\n      return RRuleFinnish.texts[id.toString()] || id.toString();\r\n    }, RRuleFinnish, (year: number, month: string, day: number) => {\r\n      return `${day}. ${month}ta ${year}`;\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiValidation, ApiValidationError, ApiValidationErrorType, Translations } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for viewing and modifying the current account data\r\n * including the products that are enabled for the current account and their properties.\r\n */\r\nexport class ValidationSummaryController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /** The server-side API-validation object that is displayed by this controller. */\r\n  public apiValidation: ApiValidation;\r\n\r\n  /** HTML that should be shown when the bound validation data is null */\r\n  public loadingHtml: \"SALAXY.NG1.ValidationSummaryComponent.loadingHtml\";\r\n\r\n  /** Layout of the validation html. Use \"minimal\" for easy customizing */\r\n  public layout: \"default\" | \"minimal\"  = \"default\";\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    // constructor code.\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => { /* init code here */\r\n  if(this.layout != \"minimal\"){\r\n    this.layout = \"default\";\r\n    }\r\n  };\r\n\r\n  /** If false, there is no validation object bound to the component. */\r\n  public get hasValidation(): boolean {\r\n    return !!this.apiValidation;\r\n  }\r\n\r\n  /** If true, the validation has no errors. */\r\n  public get isValid(): boolean {\r\n    return this.getValidation().isValid;\r\n  }\r\n\r\n  /** If false, has empty required fields. These are shown separately from other errors. */\r\n  public get hasAllRequiredFields(): boolean {\r\n    return this.apiValidation?.hasAllRequiredFields ?? false;\r\n  }\r\n\r\n  /** If true, there is no errors, but there are some warnings.  */\r\n  public get hasWarningsOnly(): boolean {\r\n    return this.apiValidation?.isValid && !!this.apiValidation?.errors?.find((x) => x.type == ApiValidationErrorType.Warning);\r\n  }\r\n\r\n  /** If true, has other errors than missing required fiels. */\r\n  public get hasValidationOrGeneralErrors(): boolean {\r\n    return this.getErrors(\"!required\").length > 0;\r\n  }\r\n\r\n  /**\r\n   * Gets the errors, optionally filtered by a type.\r\n   * @param type Type of the error: \"general\", \"required\", \"invalid\" or null.\r\n   * If null, all errors are returned.\r\n   * Also supports negation: \"!general\", \"!required\" or \"!invalid\".\r\n   */\r\n  public getErrors(type?: ApiValidationErrorType | string): ApiValidationError[] {\r\n    const errors = this.getValidation().errors || [];\r\n    if (type) {\r\n      if (type.toString().startsWith(\"!\")) {\r\n        type = type.substr(1);\r\n        return errors.filter((x) => x.type !== type) || [];\r\n      } else {\r\n        return errors.filter((x) => x.type === type) || [];\r\n      }\r\n    }\r\n    return errors || [];\r\n  }\r\n\r\n  /**\r\n   * Returns the label for the validation result.\r\n   * The label is translated using the key: `SALAXY.VALIDATION.[error.code].label`\r\n   * If the translation does not exist the `error.msg` is returned.\r\n   * @param error - Error in validation.\r\n   */\r\n  public getLabel(error: ApiValidationError): string {\r\n    const labelKey = \"SALAXY.VALIDATION.\" + error.code + \".label\";\r\n    return Translations.getWithDefault(labelKey) || error.msg || \"❗ERROR\";\r\n  }\r\n\r\n  /**\r\n   * Returns the description for the validation result.\r\n   * The label is translated using the key: `SALAXY.VALIDATION.[error.code].description`\r\n   * If the translation does not exist the `null` is returned.\r\n   * @param error - Error in validation.\r\n   */\r\n  public getDescription(error: ApiValidationError): string {\r\n    const descriptionKey = \"SALAXY.VALIDATION.\" + error.code + \".description\";\r\n    return Translations.getWithDefault(descriptionKey) || error.description;\r\n  }\r\n\r\n  /**\r\n   * Returns true if the translation for the key `SALAXY.VALIDATION.[error.code].description` exists.\r\n   * @param error - Error in validation.\r\n   */\r\n  public hasDescription(error: ApiValidationError): boolean {\r\n    return !!this.getDescription(error);\r\n  }\r\n\r\n  /** Shows details of the errors. */\r\n  public showDetails() {\r\n    this.uiHelpers.showDialog(\r\n      `salaxy-components/form-controls/ValidationSummaryDetails.html`,\r\n      null, // controller\r\n      {\r\n        controller: () => this,\r\n      },\r\n      null, // window template URL\r\n    );\r\n  }\r\n\r\n  private getValidation(): ApiValidation {\r\n    return this.apiValidation || {\r\n      errors: [],\r\n      hasAllRequiredFields: true,\r\n      isValid: false,\r\n    };\r\n  }\r\n\r\n}\r\n","import { DateTimes } from \"@salaxy/core\";\r\nimport { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Controller behind form controls that select time\r\n */\r\nexport class InputTimeController extends InputBase<string | number> {\r\n    /** Type of the input element. Options are minutes and isoTime */\r\n    public type: \"minutes\" | \"time\" = \"time\";\r\n\r\n    public _viewValue: Date;\r\n    public debug: any;\r\n\r\n    /** Sets the default values in init. */\r\n    public $onInit() {\r\n      super.$onInit();\r\n    }\r\n\r\n    /**\r\n     * Gets or sets the string value that is used in the view.\r\n     */\r\n    public get viewValue(): Date {\r\n      if (this.value) {\r\n        if (this.type === \"time\") {\r\n          if (this._viewValue?.getTime() !== DateTimes.fromTime(this.value as string).getTime()) {\r\n            this._viewValue = DateTimes.fromTime(this.value as string);\r\n          }\r\n        }\r\n\r\n        else if (this.type === \"minutes\") {\r\n          if (this._viewValue?.getTime() !== DateTimes.fromMinutes(this.value as number).getTime()) {\r\n            this._viewValue = DateTimes.fromMinutes(this.value as number);\r\n          }\r\n        }\r\n\r\n        return this._viewValue;\r\n      }\r\n      return null;\r\n    }\r\n    public set viewValue(value: Date) {\r\n      if (this.type === \"time\") {\r\n        this.value = DateTimes.asTime(value);\r\n      }\r\n\r\n      else if (this.type === \"minutes\") {\r\n        this.value = DateTimes.asMinutes(value);\r\n      }\r\n\r\n      this.onChange();\r\n    }\r\n}\r\n","import { InputBase } from \"./_InputBase\";\r\n\r\n/**\r\n * Controller behind form control which edits/displays holiday pay calculation multipliers.\r\n */\r\n\r\nexport class InputHolidayMultipliersController extends InputBase<any> {\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Delete one multiplier */\r\n  public delete(key: string) {\r\n    delete this.value[key];\r\n    this.onChange();\r\n  }\r\n\r\n  /** Add one multiplier */\r\n  public createNew() {\r\n    let newKey = 1;\r\n    if (!this.value) {\r\n      this.value = {};\r\n    }\r\n    for(const key in this.value) {\r\n      const keyValue = Number.parseInt(key);\r\n      if ( keyValue >= newKey) {\r\n        newKey = keyValue + 1;\r\n      }\r\n    }\r\n    this.value[newKey] = 0;\r\n    this.onChange();\r\n  }\r\n\r\n  /** On key changed event. */\r\n  public onKeyChanged(key: string, newKey: string) {\r\n    if (key !== newKey) {\r\n      const value = this.value[key];\r\n      delete this.value[key];\r\n      this.value[newKey] = value;\r\n    }\r\n    this.onChange();\r\n  }\r\n}\r\n","import {CalculationRowType, IncomeTypesLogic, EnumerationsLogic} from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\nimport { InputController } from \"./InputController\";\r\n\r\n/**\r\n * Controller behind form control which edits/displays row types for holiday accrual or holiday pay calculation.\r\n */\r\n\r\nexport class InputHolidayRowTypeController extends InputController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n\r\n  constructor(private uiHelpers: UiHelpers) {\r\n    super();\r\n  }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Returns true if this is an exclusive row type.  */\r\n  public get isExclusive(): boolean {\r\n    return (this.value ?? \"\").startsWith(\"!\");\r\n  }\r\n\r\n  /** Returns text for the row type */\r\n  public get text(): string {\r\n    // Possible types\r\n    /*\r\n    incomeType.[code]\r\n    incomeType.[code]-[unit]\r\n\r\n    rowType.[rowType]\r\n    rowType.[rowType].[kind]\r\n\r\n    rowType.[rowType]-[unit]\r\n    rowType.[rowType].[kind]-[unit]\r\n\r\n    type.[type]\r\n\r\n    */\r\n\r\n    if (!this.value) {\r\n      return \"\";\r\n    }\r\n\r\n    const types = this.parseRowType(this.value);\r\n    switch(types.baseType) {\r\n      case \"rowType\":\r\n        return \"Rivityyppi: \" + this.getCalculationRowTypeLabel(types.type as CalculationRowType, types.kind) + (types.unit ? ` (${EnumerationsLogic.getEnumLabel(\"CalculationRowUnit\", types.unit, null, null)})` : \"\");\r\n      case \"incomeType\":\r\n        {\r\n          const incomeType = IncomeTypesLogic.getAll(null).find( (x) => (x.code + \"\") == types.type);\r\n          return  \"Tulolaji: \" + `${incomeType?.code} - ` + incomeType?.label + (types.unit ? ` (${EnumerationsLogic.getEnumLabel(\"CalculationRowUnit\", types.unit, null, null)})` : \"\");\r\n        }\r\n      case \"type\":\r\n        return \"Palkkalaji: \" + types.type ;\r\n    }\r\n  }\r\n\r\n  /** Edit entry. */\r\n  public edit() {\r\n    const logic = {\r\n      readOnly: this.getReadOnly(),\r\n      _userDefinedRow:{\r\n        item: null,\r\n        row: {\r\n          data: {\r\n            get kind() {\r\n              return logic._userDefinedRow.item.kind;\r\n            },\r\n            set kind(value) {\r\n              logic._userDefinedRow.item.kind = value;\r\n            },\r\n          },\r\n          get rowType() {\r\n            return logic._userDefinedRow.item.type;\r\n          },\r\n          set rowType(value) {\r\n            logic._userDefinedRow.item.type = value;\r\n          }\r\n        }\r\n      },\r\n      asUserDefinedRow: (item ) => {\r\n        logic._userDefinedRow.item = item;\r\n        return logic._userDefinedRow.row;\r\n      }\r\n    };\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/form-controls/HolidayRowTypeEdit.html\",\r\n      this.parseRowType(this.value),\r\n      logic\r\n      ).then((result) => {\r\n        if (result.action === \"ok\") {\r\n          this.value = this.composeRowType(result.item);\r\n          this.onChange();\r\n        }\r\n      });\r\n  }\r\n\r\n  private getCalculationRowTypeLabel(rowType: CalculationRowType, kind: string): string {\r\n    let label = \"\";\r\n    if (rowType === CalculationRowType.IrIncomeType) {\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => (kind && x.transactionCode === kind))?.label;\r\n    }\r\n    else if (kind) {\r\n      label =  EnumerationsLogic.getEnumLabel(`${rowType}Kind`, kind, null, null);\r\n    }\r\n    return label || EnumerationsLogic.getEnumLabel(\"CalculationRowType\", rowType, null, null);\r\n\r\n  }\r\n\r\n  private parseRowType(rowType: string): {baseType?: string, type?: string, kind?: string, unit?: string, isExclusive?: boolean} {\r\n    // Possible types\r\n    /*\r\n    incomeType.[code]\r\n    incomeType.[code]-[unit]\r\n\r\n    rowType.[rowType]\r\n    rowType.[rowType].[kind]\r\n\r\n    rowType.[rowType]-[unit]\r\n    rowType.[rowType].[kind]-[unit]\r\n\r\n    type.[type]\r\n\r\n    */\r\n    if (!rowType) {\r\n      return { isExclusive: false};\r\n    }\r\n\r\n    let isExclusive = false;\r\n    let unit = \"\";\r\n    let kind = \"\";\r\n    let type = \"\";\r\n    if (rowType.startsWith(\"!\")) {\r\n      isExclusive = true;\r\n      rowType = rowType.substring(1);\r\n    }\r\n\r\n    const baseType = rowType.split(\".\")[0];\r\n    if (baseType != \"type\") {\r\n      if (rowType.lastIndexOf(\"-\") > 0) {\r\n        unit = rowType.substring(rowType.lastIndexOf(\"-\") + 1);\r\n        rowType = rowType.substring(0, rowType.lastIndexOf(\"-\"));\r\n      }\r\n      const nameParts = rowType.split(\".\");\r\n      type = nameParts[1];\r\n      kind = nameParts[2];\r\n    }\r\n    else\r\n    {\r\n      type = rowType.substring(rowType.indexOf(\".\") + 1);\r\n    }\r\n\r\n    return {baseType, type, kind, unit, isExclusive};\r\n  }\r\n\r\n  private composeRowType(types: {baseType?: string, type?: string, kind?: string, unit?: string, isExclusive?: boolean}): string {\r\n    if (!types?.baseType || !types?.type) {\r\n      return \"\";\r\n    }\r\n    let rowType = `${types.baseType}.${types.type}`;\r\n    if (types.kind) {\r\n      rowType += `.${types.kind}`;\r\n    }\r\n    if (types.unit && types.unit !== \"undefined\") {\r\n      rowType += `-${types.unit}`;\r\n    }\r\n    if (types.isExclusive) {\r\n      rowType = \"!\" + rowType;\r\n    }\r\n    return rowType;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Configs } from \"@salaxy/core\";\r\n/**\r\n * Controller for action button\r\n */\r\nexport class ActionButtonController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Text for the button */\r\n  public label: string;\r\n\r\n  /** Additional Bootstrap or custom style classes. I.e. btn-danger, btn-sm, my-btn. Defaults to btn-primary. */\r\n  public buttonClass: string;\r\n\r\n  /**\r\n   * Action to be executed.\r\n   * newCalc: starts a new blank calculation.\r\n   * newCalcForEmployment: starts a new calculation for the given employment ID.\r\n   * newPayroll: starts a new blank payroll.\r\n   * newWorker: opens workerWizard for creating a new worker.\r\n   * newMessage: starts a new message thread with partner.\r\n   * payment: opens the payment dialog for the current calculation.\r\n   * newTaxcard: Links to taxcards page. Currently supported only when role is Worker.\r\n   */\r\n  public action: \"newCalc\" | \"newCalcForEmployment\" | \"newPayroll\" | \"newWorker\" | \"newMessage\" | \"payment\" | \"newTaxcard\";\r\n\r\n  /** Disabled but visible */\r\n  public disabled?: boolean;\r\n\r\n  /** Optional options for button. */\r\n  public options?: {\r\n    /**\r\n     * id: id of current item such as Employment or Calculation. Currently used only in newCalcForEmployment action.\r\n     */\r\n    id: string,\r\n  };\r\n\r\n  /**\r\n   * Creates a new InputController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    //\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    this.buttonClass = this.buttonClass || \"btn-primary\";\r\n  };\r\n\r\n  /**\r\n   * Returns environment based on config.\r\n   * TODO: Replace this with ConfigsLogic\r\n   */\r\n  public getEnv(): \"local\" | \"test\" | \"demo\" | \"prod\" | \"rc\" {\r\n    const config = Configs.current;\r\n    if (!config.isTestData) {\r\n      return \"prod\";\r\n    }\r\n    if (config.apiServer?.indexOf(\"localhost\") > -1  ) {\r\n      return \"local\";\r\n    }\r\n    if (config.integrationsServer?.indexOf(\"test\") > -1  ) {\r\n      return \"test\";\r\n    }\r\n    if (config.apiServer?.indexOf(\"rc\") > -1  ) {\r\n      return \"rc\";\r\n    }\r\n    return \"demo\";\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Controller rendering an Alert box in the page area.\r\n */\r\nexport class AlertController implements angular.IController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"$transclude\"];\r\n\r\n    /** Type of the alert is the Bootstrap style: Note that also \"primary\" and \"default\" are supported. */\r\n    public type: \"default\" | \"primary\" | \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\n    /**\r\n     * Alert main content as simple text.\r\n     * You can alternatively provide html as main element.\r\n     * NOTE: If necessary we could provide a html property to bind from JavaScript and to allow HTML in the binded content.\r\n     */\r\n    public text: string;\r\n\r\n    /**\r\n     * Possibility to speicfy a font-awesome icon.\r\n     * Setting \"none\", will show no icon.\r\n     * If not set, it is determined by type.\r\n     */\r\n    public icon: \"none\" | string;\r\n\r\n    /** If true (and hasMoreInfo is true), the more info html is shown. */\r\n    public showMoreInfo: boolean;\r\n\r\n    /** If true, the aside part is shown immidiately. Also hides \"read more\"- button. */\r\n    public forceMoreInfo = false;\r\n\r\n    /**\r\n     * Creates a new AlertController\r\n     * @ignore\r\n     */\r\n    constructor(private $transclude: angular.ITranscludeFunction) {\r\n     }\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit = () => {\r\n        // initialization\r\n    };\r\n\r\n    /** Returns true if details part (aside element) is filled / \"More info\" button should be shown. */\r\n    public get hasMoreInfo() {\r\n        return this.$transclude.isSlotFilled(\"aside\");\r\n    }\r\n\r\n    /** Returns the icon based on the type. */\r\n    public getIcon() {\r\n        if (!this.icon) {\r\n            switch (this.type) {\r\n                case \"danger\":\r\n                    return \"fa-exclamation\";\r\n                case \"success\":\r\n                    return \"fa-check\";\r\n                case \"warning\":\r\n                    return \"fa-exclamation-triangle\";\r\n                default:\r\n                    return \"fa-info\";\r\n            }\r\n        }\r\n        if (this.icon === \"none\") {\r\n            return null;\r\n        }\r\n        return this.icon;\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {AvatarPictureType} from \"@salaxy/core\";\r\n\r\n/**\r\n * Controller rendering a Salaxy account Avatar (image for the person / company).\r\n */\r\nexport class AvatarController implements angular.IController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [];\r\n\r\n    /** The Avatar object which the controller is rendering */\r\n    public avatar: any;\r\n\r\n    /**\r\n     * Creates a new AvatarController\r\n     * @ignore\r\n     */\r\n    constructor() {\r\n        //\r\n     }\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit = () => {\r\n        // initialization\r\n     };\r\n\r\n    /** Returns true if the avatar is an image url (as opposed to icon rendering) */\r\n    public get isImage(): boolean {\r\n        return this.avatar != null\r\n            && ( this.avatar.pictureType === AvatarPictureType.Uploaded || this.avatar.pictureType === AvatarPictureType.Gravatar)\r\n            && this.avatar.url != null\r\n            && this.avatar.url.substr(0, 4).toLowerCase() === \"http\"\r\n            ;\r\n    }\r\n\r\n    /** Returns true if the avatar should be rendered as a person icon */\r\n    public get isPersonIcon(): boolean {\r\n        return this.avatar != null && !this.isImage && this.avatar.entityType !== \"company\";\r\n    }\r\n\r\n    /** Returns true if the avatar should be rendered as a company icon */\r\n    public get isCompanyIcon(): boolean {\r\n        return this.avatar == null || (!this.isImage && this.avatar.entityType === \"company\");\r\n    }\r\n\r\n    /** Returns the avatar color or 'gray' if nothing is defined. */\r\n    public get color(): string {\r\n        if (this.avatar) {\r\n            return this.avatar.color;\r\n        }\r\n        return \"gray\";\r\n    }\r\n\r\n    /** Returns the initials for rendering the avatar */\r\n    public get initials(): string {\r\n        if (this.avatar) {\r\n            return this.avatar.initials || \"-\";\r\n        }\r\n        return \"?\";\r\n    }\r\n}\r\n","import angular from \"angular\";\r\nimport { SxyTableController, SxyTableOptions } from \"../sxy-table\";\r\nimport { ColumnDefinition } from \"tabulator-tables\";\r\nimport { Arrays, CellRenderingLogic, EnumerationsLogic, AccountInIndex, OpenAPIV3, Translations, JsonSchemaUtils } from \"@salaxy/core\";\r\nimport { JsonSchemaService } from \"../../services\";\r\n\r\n/**\r\n * Used for running batch processes to the server.\r\n * At the time of writing, the controller isonly used in Modal dialogs, but may�be used for something else later.\r\n */\r\nexport class BatchProcessController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$uibModalInstance\", \"data\", \"$sce\", \"$timeout\", \"JsonSchemaService\"];\r\n\r\n  /** Counter and status for the processing of the items */\r\n  public processCounter: {\r\n    /** If true, the processing is in progress (started and not yet done). */\r\n    isProcessing: boolean,\r\n    /** If true, the processing is done. Note that this may also mean that the processing has been canceled by the user. */\r\n    isDone: boolean,\r\n    /** Total count of items that should be processed. */\r\n    totalCount: number,\r\n    /** Count of items that have been processed. Note that also errors are counted as processed. */\r\n    processedCount: number,\r\n    /** Errors that occured. */\r\n    errorsCount: number,\r\n    /** If true, the process has been canceled by the user. If also isDone is true, the canceling has completed. */\r\n    canceling: boolean,\r\n  };\r\n\r\n  /** Options for the modal dialog */\r\n  public dialogHeader: string;\r\n\r\n  /** Columns that are shown in the grid. Leave empty use default columns */\r\n  public columns: string | (string | ColumnDefinition)[];\r\n\r\n  /** List of items that should be processed. */\r\n  public list: any[];\r\n\r\n  /** Usecase specific data for the dialog. */\r\n  public data: any;\r\n\r\n  /**\r\n   * Method that is called by the process.\r\n   * ItemOrArray is the item/array that is processed, Data is the controller data that may be edited in the form.\r\n   * The promise may return a message that is shown after text \"OK\".\r\n   * Promise rejection is cached.\r\n   */\r\n  public method: (itemOrArray: any | any[], data: any) => Promise<({message: string, result: any[]}[])>;\r\n\r\n  /**\r\n   * Optional chunk size for the batch process. This is used if the method supports arrays.\r\n   */\r\n  public chunkSize: number;\r\n\r\n  /** Start process right after opening the invoice. */\r\n  public autoStart: boolean;\r\n\r\n  /** Close dialog after process. */\r\n  public autoClose: boolean;\r\n\r\n  /** Options that are bound to the grid.  */\r\n  public tableOptions: SxyTableOptions;\r\n\r\n  /** Inner template that is included for usecase specific form and other UI. */\r\n  public batchTemplateUrl: string;\r\n\r\n  /** Binding for start button, which launches the processing. */\r\n  public isProcessStarted = false;\r\n\r\n  /** The table controller after it has been initialized. */\r\n  public $table: SxyTableController;\r\n\r\n  /** References a schema document directly: the schema document is not fetched from the UI */\r\n  public openApiDoc: any;\r\n\r\n  /**\r\n   * URL for the Open API document that contains the definition for the type.\r\n   * The url can be an absolute url, relative url or an url with salaxy-secure/ -prefix.\r\n   * The salaxy-secure/ -prefix will be replaced in runtime with the salaxy api server url of the curren environment.\r\n   */\r\n  public openApi = \"salaxy-secure/schemas/v02.json\";\r\n\r\n  /** The schema model */\r\n  public schemaModel: OpenAPIV3.SchemaObject;\r\n\r\n  /** If true, the schema loading is ready. */\r\n  public isReady: boolean;\r\n\r\n  /**\r\n   * Constructor for dependency instance.\r\n   * @param $uibModalInstance Modal instance supports functions such as close(result), dismiss(reason) and promises result, opened, closed and rendered.\r\n   * @param data Rest of the data injected from the caller.\r\n   */\r\n  constructor(protected $uibModalInstance: any, data: any, $sce: angular.ISCEService, private $timeout: angular.ITimeoutService, private jsonSchemaService: JsonSchemaService) {\r\n    this.data = data;\r\n    this.dialogHeader = this.data.dialogHeader || Translations.get(\"SALAXY.NG1.BatchProcessComponent.title\");\r\n    this.list = this.data.dialogList || [];\r\n    this.columns = this.getColumns(this.data.gridColumns);\r\n    this.method = this.data.batchMethod;\r\n    this.chunkSize = this.data.chunkSize ?? 0;\r\n    this.autoStart = this.data.autoStart ?? false;\r\n    this.autoClose = this.data.autoClose ?? false;\r\n    this.tableOptions = this.getGridOptions();\r\n    this.batchTemplateUrl = $sce.trustAsResourceUrl(data.batchTemplateUrl);\r\n  }\r\n\r\n  /** Initialization */\r\n  public $onInit = () => {\r\n    this.resetProcessed();\r\n    if (this.autoStart === true) {\r\n      this.startProcess();\r\n    }\r\n    if (this.data.listItemType) {\r\n      if (this.openApiDoc) {\r\n        this.jsonSchemaService.addSchemaDocument(this.openApi, this.openApiDoc);\r\n        this.schemaModel = this.jsonSchemaService.findSchema(this.openApi, this.data.listItemType);\r\n        this.isReady = true;\r\n      } else {\r\n        this.jsonSchemaService.assureSchemaDocument(this.openApi).then((openApiDoc) => {\r\n          this.openApiDoc = openApiDoc;\r\n          this.schemaModel = this.jsonSchemaService.findSchema(this.openApi, this.data.listItemType);\r\n          this.isReady = true;\r\n        });\r\n      }\r\n    } else {\r\n      this.isReady = true;\r\n    }\r\n  };\r\n\r\n  /** Starts the processing */\r\n  public startProcess() {\r\n    // Prevent double clicks\r\n    if (this.isProcessStarted) {\r\n      return;\r\n    }\r\n    this.isProcessStarted = true;\r\n    this.resetProcessed();\r\n    this.processNextItems();\r\n  }\r\n\r\n  /** Processes next items in the queue */\r\n  public processNextItems() {\r\n    this.$timeout(() => {\r\n      this.processNextItemsInternal();\r\n      // TODO: Consider adding this method to the SxyTableController in addition of refresh(). which redraws the table.\r\n      try {\r\n        this.$table.tabulator.replaceData(this.list);\r\n      } catch (e) {\r\n        // Ignore, the table is not initialized yet.\r\n      }\r\n    });\r\n  }\r\n\r\n  private processNextItemsInternal() {\r\n    const counter = this.processCounter;\r\n    counter.isProcessing = true;\r\n    if (counter.canceling) {\r\n      counter.isProcessing = false;\r\n      counter.isDone = true;\r\n      return;\r\n    }\r\n    const remainingItems = this.list.filter((x) => !x.processed);\r\n    if (remainingItems.length === 0) {\r\n      counter.isProcessing = false;\r\n      counter.isDone = true;\r\n      this.data.done = true;\r\n      if (this.autoClose) {\r\n        this.close();\r\n      }\r\n    } else {\r\n      const itemsToProcess = remainingItems.slice(0, this.chunkSize > 0 ? this.chunkSize : 1);\r\n      for (const itemToProcess of itemsToProcess) {\r\n        itemToProcess.processed = Translations.get(\"SALAXY.NG1.BatchProcessComponent.processing\");\r\n      }\r\n      this.method(this.chunkSize > 0 ? itemsToProcess : itemsToProcess[0], this.data)\r\n        .then((results) => {\r\n          let i = 0;\r\n          for (const itemToProcess of itemsToProcess) {\r\n            itemToProcess.processed = \"OK \" + (results[i].message);\r\n            itemToProcess.processedResult = { message: results[i].message, result: results[i].result };\r\n            i++;\r\n          }\r\n          counter.processedCount += itemsToProcess.length;\r\n          this.processNextItems();\r\n        })\r\n        .catch((reason) => {\r\n          let label = \"Server error\";\r\n          let msg = \"Unknown error\";\r\n          if (reason) {\r\n            msg = reason.statusText || msg;\r\n            if (reason.data) {\r\n              label = reason.data.error || label;\r\n              msg = reason.data.messageHtml || msg;\r\n            }\r\n          }\r\n          for (const itemToProcess of itemsToProcess) {\r\n            itemToProcess.processed = \"ERR \" + label + \". \" + msg;\r\n            itemToProcess.processedResult = null;\r\n          }\r\n          console.error(label, reason);\r\n          counter.processedCount += itemsToProcess.length;\r\n          counter.errorsCount += itemsToProcess.length;\r\n          this.processNextItems();\r\n        });\r\n    }\r\n  }\r\n\r\n  /** Closes the dialog. */\r\n  public close() {\r\n    this.resetProcessed();\r\n    this.$uibModalInstance.close();\r\n  }\r\n\r\n  /** Resets the processed status column(s) */\r\n  public resetProcessed() {\r\n    for (const item of this.list) {\r\n      if (item.processed) {\r\n        item.processed = null;\r\n      }\r\n    }\r\n    this.processCounter = {\r\n      isProcessing: false,\r\n      isDone: false,\r\n      totalCount: this.list.length,\r\n      processedCount: 0,\r\n      errorsCount: 0,\r\n      canceling: false,\r\n    };\r\n  }\r\n\r\n  /** Cancels the process: Waits for the next response, but does not start a new one. */\r\n  public cancelProcess() {\r\n    this.processCounter.canceling = true;\r\n  }\r\n\r\n  private getColumns(columns: string | (string | ColumnDefinition)[]): string | (string | ColumnDefinition)[] {\r\n    const defaultCols: ColumnDefinition[] = [\r\n      ...this.getAvatarCols(\"owner\", Translations.get(\"SALAXY.NG1.BatchProcessComponent.employer\"), { width: 300 }),\r\n      ...this.getAvatarCols(\"other\", Translations.get(\"SALAXY.NG1.BatchProcessComponent.worker\"), { width: 400 }),\r\n      {\r\n        field: \"status\",\r\n        title: Translations.get(\"SALAXY.NG1.BatchProcessComponent.status\"),\r\n        formatter: (cell: any) => {\r\n          const status = cell.getData().status;\r\n          const statusEnum = JsonSchemaUtils.getProperty(this.schemaModel, \"status\")?.schema?.format;\r\n          if (!status) {\r\n            return `<div>-</div>`;\r\n          }\r\n          if (!statusEnum) {\r\n            return `<div>${status}</div>`;\r\n          }\r\n          return Translations.get(`SALAXY.ENUM.${statusEnum}.${status}.label`);\r\n        }\r\n      },\r\n    ];\r\n    if (typeof columns === \"string\") {\r\n      columns = Arrays.assureArray(columns);\r\n    }\r\n    if (!columns?.length) {\r\n      columns = defaultCols;\r\n    }\r\n    if (!columns.find((x) => x == \"processed\" || (x as ColumnDefinition).field === \"processed\")) {\r\n      columns.splice(0, 0,{\r\n        width: 400,\r\n        field: \"processed\",\r\n        title: Translations.get(\"SALAXY.NG1.BatchProcessComponent.processed\"),\r\n        // TODO: cellTemplate: \"salaxy-aspa-components/grid-col/processed.html\",\r\n        // eslint-disable-next-line\r\n        // cellTooltip: (row, col) => row.entity.processed,\r\n      });\r\n    }\r\n    return columns;\r\n  }\r\n\r\n  /**\r\n   * Gets a column definition for avatar column: Renders an avatar with sortable name and second info line.\r\n   * @param party The party to render: either \"owner\" (ownerInfo) or \"other\" (otherPartyInfo).\r\n   * @param title The title of the column.\r\n   * @param props Other properties that should be set on the column.\r\n   */\r\n  public getAvatarCols(party: \"owner\" | \"other\", title: string, props?: any): any[] {\r\n    const infoProp = party === \"other\" ? \"otherPartyInfo\" : \"ownerInfo\";\r\n    const result: any[] = [\r\n      {\r\n        field: `${infoProp}.avatar.sortableName`, title,\r\n        headerFilter: true,\r\n        formatter: (cell: any) => {\r\n          const info: AccountInIndex = cell.getData()[infoProp];\r\n          return `\r\n              <div class=\"tabulator-avatar\">${CellRenderingLogic.getAvatar(info?.avatar)}${info?.avatar?.sortableName || \"-\"}</div>\r\n          `;\r\n        },\r\n        ...props,\r\n      },\r\n    ];\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Gets a column definition for enumerations column\r\n   * @param field The field name / path in the data model.\r\n   * @param title The title of the column.\r\n   * @param enumType The type name of the enumeration.\r\n   * @param props Other properties that should be set on the column.\r\n   */\r\n  public getEnumColumn(field: string, title: string, enumType: string, props?: any): any {\r\n    return {\r\n      field, title,\r\n      formatter: (cell: any) => EnumerationsLogic.getEnumLabel(enumType, cell.getValue()),\r\n      headerFilter: \"list\",\r\n      headerFilterFunc: \"=\",\r\n      headerFilterParams: {\r\n        values: EnumerationsLogic.getEnumMetadata(enumType)?.values.map(v => ({ label: v.label, value: v.name })),\r\n      },\r\n      ...props,\r\n    };\r\n  }\r\n\r\n  /** Gets the options for the UI grid */\r\n  private getGridOptions(): SxyTableOptions {\r\n    const options: SxyTableOptions = {\r\n      height: \"50vh\",\r\n      layout: \"fitColumns\"\r\n    };\r\n    return options;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, Translations, CalendarDay, CalendarMonth, CalendarSeries, CalendarUiEvent, HolidaysLogic, Configs } from \"@salaxy/core\";\r\nimport { UiHelpers, ExcelHelpers } from \"../../services\";\r\nimport { ListControllerBase } from \"../bases\";\r\n\r\n/**\r\n * Renders a calendar control for visualisation of holidays.\r\n */\r\nexport class CalendarController implements angular.IController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"UiHelpers\", \"$http\"];\r\n\r\n    /**\r\n     * Start date for the calendar as ISO date yyyy-MM-dd. Renders from the beginning of this month.\r\n     */\r\n    public start: string;\r\n\r\n    /**\r\n     * End date of the calendar as ISO date yyyy-MM-dd. Renders until the end of this month.\r\n     */\r\n    public end: string;\r\n\r\n    /**\r\n     * Calendar data where single series can be represented as an array of events (CalendarUiEvent or date ISO string).\r\n     * Several series should be represented as CalendarSeries that contain events.\r\n     * Note that a DateRange also passes as CalendarUiEvent because it has start and end dates.\r\n     */\r\n    public data: CalendarSeries[] | (CalendarUiEvent | string)[] | any;\r\n\r\n    /**\r\n     * Function that is called when user selects an item in the calendar.\r\n     * Function can have the following locals: type: \"event\" | \"day\", date: string, day: Full calendar day with all the day info,\r\n     * calEvent: The calendar event if type is \"event\", series: Series that the event belongs to or the series that is clicked (not always available).\r\n     * @example <salaxy-calendar on-list-select=\"$ctrl.myCustomSelectFunc(type, date, calEvent)\"></salaxy-calendar>\r\n     */\r\n    public onListSelect: (params: {\r\n      /** Selection type. */\r\n      type: \"event\" | \"day\" | \"series\",\r\n      /** Seleted date as ISO string. */\r\n      date: string,\r\n      /** Full calendar day with all the day info. */\r\n      day: CalendarDay,\r\n      /** Calendar event that was clicked: Only if selection type is \"event.\" */\r\n      calEvent?: CalendarUiEvent,\r\n      /**\r\n       * Series that the event belongs to or the series that is clicked.\r\n       * Note that some clicks of type \"day\" might not have the series info, in current UI the header above series when calendar supports multiple series.\r\n       */\r\n      series?: CalendarSeries,\r\n    }) => void;\r\n\r\n    /** Language versioned weekdays short texts (e.g. \"ma\", \"ti\",...) */\r\n    public weekdays: string[];\r\n\r\n    /** Get the header days for the whole calendar. */\r\n    public weekdaysForMonth: {\r\n      /** Weekday index number (align-weekdays) or day of month (align-left). */\r\n      ix: number,\r\n      /** Week day number in week (align-weekdays). */\r\n      weekday?: number,\r\n      /** Text for the week day (align-weekdays) or day of month (align-left). */\r\n      text: string,\r\n    }[] = [];\r\n\r\n    /** A mapper that is used in converting custom data to Calendar series array. */\r\n    public mapper: (sourceData: any) => CalendarSeries[];\r\n\r\n    /** If specified, this is the list controller that should be used for editing the item. */\r\n    public listController: ListControllerBase<any, any>;\r\n\r\n    /** If set to true, the export buttons are visible. */\r\n    public showExport = false;\r\n\r\n    private _today: string;\r\n\r\n    private _mode: \"align-weekdays\" | \"align-left\" | \"horizontal\" | \"list\";\r\n\r\n    private _series: CalendarSeries[];\r\n\r\n    private HOLIDAY_COLOR = \"#BBB\";\r\n    private WEEKEND_COLOR = \"#DDD\";\r\n    private EVENT_COLOR = \"#009fd8\";\r\n\r\n    constructor(private uiHelpers: UiHelpers, private $http: angular.IHttpService) {\r\n      // for dependency injection\r\n    }\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit = () => {\r\n      // Default values if not set, also validate and harmonize them for dates only (remove time and convert e.g. \"today\")\r\n      this.start = Dates.asDate(this.start) || Dates.getDate(\"today\", 1, 1);\r\n      this.end = Dates.asDate(this.end) || Dates.getDate(\"today\", 12, 31);\r\n      this.today = Dates.asDate(this.today) || Dates.getToday();\r\n      this.weekdays = Array.from(\"1234567\").map((x) => Translations.getWithDefault(`SALAXY.ENUM.Weekday.day${x}.short`, \"d\" + x));\r\n      this.initHeader();\r\n    };\r\n\r\n    /** Initialize the header (days) */\r\n    public initHeader() {\r\n      switch (this.mode) {\r\n        case \"align-left\":\r\n          this.weekdaysForMonth = [...Array(31)].map((val, ix) => ({ ix, text: (ix + 1).toString()}));\r\n          break;\r\n        case \"horizontal\":\r\n          break;\r\n        default:\r\n          // Align the weekdays\r\n          for (let i = 0; i < 5; i++) {\r\n            this.weekdaysForMonth.push(...this.weekdays.map((x, index) => ({ ix: i * 7 + index, weekday: index + 1, text: x}) ));\r\n          }\r\n          this.weekdaysForMonth.push({ ix: 5 * 7 + 0, weekday: 1, text: this.weekdays[0]} , { ix: 5 * 7 + 1, weekday: 2, text: this.weekdays[1]});\r\n          break;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Specifies how the weekdays are aligned from one month to another.\r\n     * \"horizontal\" shows all months side-by-side horizontally, so there is no alignment.\r\n     */\r\n    public get mode(): \"align-weekdays\" | \"align-left\" | \"horizontal\" | \"list\" {\r\n      switch (this._mode) {\r\n        case \"align-left\":\r\n        case \"horizontal\":\r\n        case \"list\":\r\n          return this._mode;\r\n        default:\r\n          return \"align-weekdays\";\r\n      }\r\n    }\r\n    public set mode(value: \"align-weekdays\" | \"align-left\" | \"horizontal\" | \"list\") {\r\n      this._mode = value;\r\n    }\r\n\r\n    /** Gets the Today date for the calendar as ISO date yyyy-MM-dd. */\r\n    public get today(): string {\r\n      if (!this._today) {\r\n        this._today = Dates.getToday();\r\n      }\r\n      return this._today;\r\n    }\r\n    /** Sets the Today date as dately object (e.g. ISO string, JS Date or key string \"today\") */\r\n    public set today(value: string) {\r\n      this._today = Dates.asDate(value);\r\n    }\r\n\r\n    /** Gets all days of all months */\r\n    public get allDays(): CalendarDay[] {\r\n      // TODO: create typing to months / allDays results.\r\n      return this.uiHelpers.cache(this, \"allDays\", () => {\r\n        return this.months.reduce((acc, current) => acc.concat(current.days), []);\r\n      }, () => this.cacheCounter);\r\n    }\r\n\r\n    /**\r\n     * Gets the data harmonized as an array of Calendar Series\r\n     */\r\n    public get series(): CalendarSeries[] {\r\n      return this._series;\r\n    }\r\n\r\n    /**\r\n     * Gets the monthly list: Only the dates that have events on them.\r\n     * Only the start of event is considered except for the first month where all intercepting properties are.\r\n     */\r\n    public get monthlyList(): CalendarMonth[] {\r\n      return this.uiHelpers.cache(this, \"monthList\", () => {\r\n        const months = this.months.map((month) => {\r\n          const monthResult: CalendarMonth = {\r\n            daysInMonth: month.daysInMonth,\r\n            firstDayDayOfWeek: month.firstDayDayOfWeek,\r\n            month: month.month,\r\n            title: month.title,\r\n            year: month.year,\r\n            days: month.days.map((day) => {\r\n              let dayEventsCount = 0;\r\n              Object.keys(day.events).reduce((acc, key) => {\r\n                // TODO: We are only using dayEventsCount => Figure out a simpler way to find it.\r\n                acc[key] = day.events[key];\r\n                dayEventsCount += acc[key].length;\r\n                return acc;\r\n              }, {});\r\n              if (dayEventsCount) {\r\n                return {\r\n                  day: day.day,\r\n                  date: day.date,\r\n                  weekday: day.weekday,\r\n                  weekdayText: day.weekdayText,\r\n                  dayType: day.dayType,\r\n                  events: day.events.map((series) => series.filter((val) => day.date === val.start)),\r\n                  periods: null, // Add support if needed\r\n                  singleDays: null,\r\n                };\r\n              }\r\n              return null;\r\n            }).filter(x => !!x),\r\n          };\r\n          return monthResult;\r\n        });\r\n        return months;\r\n      }, () => this.cacheCounter);\r\n    }\r\n\r\n    /** The collection of months that the calendar renders. */\r\n    public get months(): CalendarMonth[] {\r\n      return this.uiHelpers.cache(this, \"months\", () => {\r\n        const result = [];\r\n        const startDay = Dates.startEnd(this.start || \"today\",\"start-month\");\r\n        const endDay = Dates.startEnd(this.end || \"today\",\"start-month\");\r\n        this.assureNormalizedCopy();\r\n        const data = this.series || [];\r\n        if (!Dates.isValidDateTime(startDay) || !Dates.isValidDateTime(endDay) || startDay > endDay) {\r\n          console.error(\"Invalid date range in CalendarController.\");\r\n          return [];\r\n        }\r\n        let currentMonthDay = startDay;\r\n        while (currentMonthDay <= endDay) {\r\n          const daysInMonth = Dates.getDaysInMonth(currentMonthDay);\r\n          const firstDayDayOfWeek = Dates.getWeekday(currentMonthDay);\r\n\r\n          const month: CalendarMonth = {\r\n            month: Dates.getMonth(currentMonthDay),\r\n            year: Dates.getYear(currentMonthDay),\r\n            title: Translations.get(`SALAXY.ENUM.CalendarMonth.month${Dates.getMonth(currentMonthDay)}.label`),\r\n            firstDayDayOfWeek,\r\n            daysInMonth,\r\n            days: [],\r\n          };\r\n          for (let day = 1; day <= daysInMonth; day++) {\r\n            const date = Dates.setDay(currentMonthDay,day);\r\n            const weekday = Dates.getWeekday(date);\r\n\r\n            // TODO: Do we need separate periods/singleDays any more?\r\n            const periods = data.map((series) => series.events.filter((val) => val.end && !val.icon && val.start <= date && val.end >= date));\r\n            const singleDays = data.map((series) => series.events.filter((val) => (!val.end || val.icon) && date === val.start));\r\n            // TODO: Is it more efficient to concatenate from the 2 above?\r\n            const events = data.map((series) => series.events.filter((val) => date === val.start || (val.end && !val.icon && val.start < date && val.end >= date)));\r\n            month.days.push({\r\n              day,\r\n              date,\r\n              weekday,\r\n              weekdayText: this.weekdays[weekday - 1],\r\n              dayType: date === this.today ? \"today\" : (Dates.isHoliday(date) ? \"holiday\" : \"normal\"),\r\n              events,\r\n              periods,\r\n              singleDays,\r\n            });\r\n          }\r\n          result.push(month);\r\n          currentMonthDay = Dates.add(currentMonthDay,1,\"month\");\r\n        }\r\n        return result;\r\n      }, this.getCacheKey);\r\n    }\r\n\r\n    /**\r\n     * Gets the short text \"ma\", \"ti\", \"ke\", \"to\", \"pe\", \"la\", \"su\".\r\n     * @param date Date as ISO string or date\r\n     */\r\n    public getShortWeekdayText(date: any) {\r\n      return this.weekdays[Dates.getWeekday(date) - 1];\r\n    }\r\n\r\n    /** Gets the CSS class(es) for a calendar event. */\r\n    public getCssClass(event: CalendarUiEvent): string {\r\n      if (!event) {\r\n        return null;\r\n      }\r\n      if (event.icon) {\r\n        // This is an icon (<i>-tag).\r\n        return `fa ${event.icon} fa-fw event-single-day ${event.cssClass || \"text-info\"} clickable`;\r\n      }\r\n      return `event-period ${event.cssClass || \"salaxy-cal-event-primary\"} clickable`;\r\n    }\r\n\r\n    /**\r\n     * Get the event CSS style for a single day. Main thing is to set the disposition and smaller size if the day has overlapping items.\r\n     * @param event Event for which to calculate the styles.\r\n     * @param allEvents All events in the given series/type: Either period or singleDay.\r\n     */\r\n    public getEventStyle(event: CalendarUiEvent, allEvents: CalendarUiEvent[]): any {\r\n      if (event.icon) {\r\n        const ix = allEvents.indexOf(event);\r\n        switch (allEvents.length) {\r\n          case 1:\r\n            return null; /* bottom: 4px; left: -4px; font-size: 16px; */\r\n          case 2:\r\n            return {\r\n              \"font-size\": \"12px\",\r\n              bottom: (ix === 1 ? 0 : 8) + \"px\",\r\n              left: (ix === 1 ? 2 : -4) + \"px\",\r\n            };\r\n          case 3:\r\n            return {\r\n              \"font-size\": \"10px\",\r\n              bottom: (ix > 1 ? 0 : 8) + \"px\",\r\n              left: (ix === 0 ? -4 : (ix === 2 ? 0 : 4)) + \"px\",\r\n            };\r\n          default:\r\n            return {\r\n              \"font-size\": \"10px\",\r\n              bottom: (ix > 1 ? 0 : 8) + \"px\",\r\n              left: (ix === 0 || ix === 2 ? -4 : 4) + \"px\",\r\n            };\r\n        }\r\n      } else {\r\n        if (allEvents.length > 1) {\r\n          const height = (this.mode === \"horizontal\" ? 30 : 16)/allEvents.length;\r\n          const ix = allEvents.indexOf(event);\r\n          return {\r\n            height: height + \"px\",\r\n            bottom: (height*(allEvents.length-1-ix)) + \"px\",\r\n          };\r\n        }\r\n      }\r\n      return null;\r\n    }\r\n\r\n    /**\r\n     * A date in the calendar was clicked.\r\n     * @param day Day that was clicked.\r\n     * @param series The series that contains the event.\r\n     * If null, the click is in header etc. where series is not available.\r\n     * @param $event The AngularJS event used to stop propagation.\r\n     */\r\n    public dateClicked(day: CalendarDay, series: CalendarSeries, $event: angular.IAngularEvent) {\r\n      $event.stopPropagation();\r\n      series = series || this.series[0];\r\n      if (this.listController && series) {\r\n        this.listController.parent = series.data;\r\n        const newItem = this.listController.getBlank();\r\n        if (newItem.period) {\r\n          // HACK: Could we move this to object specific CRUD or List controllers.\r\n          newItem.period.start = day.date;\r\n          newItem.period.end = day.date;\r\n        }\r\n        this.listController.showEditDialog(newItem, true);\r\n        return;\r\n      }\r\n      this.onListSelect({\r\n        type: \"day\",\r\n        date: day.date,\r\n        day,\r\n        series,\r\n      });\r\n    }\r\n\r\n    /**\r\n     * Called by view when an event is clicked.\r\n     * @param ev Event that is being clicked\r\n     * @param day Day on which the event occurs\r\n     * @param series The series that contains the event. If null, the first series is taken.\r\n     * @param $event AngularJS event: Used for stopping propagation.\r\n     */\r\n    public eventClicked(ev: CalendarUiEvent, day: CalendarDay, series: CalendarSeries, $event: angular.IAngularEvent) {\r\n      $event.stopPropagation();\r\n      series = series || this.series[0];\r\n      if (this.listController && series) {\r\n        this.listController.parent = series.data;\r\n        this.listController.showEditDialog(ev.data);\r\n        return;\r\n      }\r\n      this.onListSelect({\r\n        type: \"event\",\r\n        date: day.date,\r\n        day,\r\n        calEvent: ev,\r\n        series,\r\n      });\r\n    }\r\n\r\n    /**\r\n     * A series title in the calendar was clicked.\r\n     * @param series The series.\r\n     * @param $event The AngularJS event used to stop propagation.\r\n     */\r\n      public seriesClicked(series: CalendarSeries, $event: angular.IAngularEvent) {\r\n        $event.stopPropagation();\r\n        this.onListSelect({\r\n          type: \"series\",\r\n          date: undefined,\r\n          day: undefined,\r\n          series,\r\n        });\r\n      }\r\n\r\n      /**\r\n       * Exports the calendar as a PDF.\r\n       * This method shows a loading indicator, constructs a URL for the PDF request,\r\n       * and handles the PDF request.\r\n       */\r\n      public exportCalendarPdf(): void {\r\n        const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n        const url = `${Configs.current.reportServer}/pdf?reportType=calendar&language=${encodeURIComponent(Translations.getLanguage())}&disposition=inline`;\r\n        this.handlePdfRequest(url, false, { object: {months: this.months, series: this.series} }, loading);\r\n      }\r\n\r\n      private async handlePdfRequest(\r\n        url: string,\r\n        inline: boolean,\r\n        payload: any,\r\n        loading: any\r\n      ): Promise<void> {\r\n        try {\r\n          await this.fetchPdf(url, payload, inline);\r\n        } catch (error) {\r\n          //HACK: Implement failover functionality to cloud (azure)\r\n          if (\r\n            url.includes(Configs.current.reportServer) &&\r\n            Configs.current.getEnv() === \"prod\"\r\n          ) {\r\n            url = url.replace(\r\n              Configs.current.reportServer,\r\n              \"https://failover-reports.salaxy.com\"\r\n            );\r\n            try {\r\n              await this.fetchPdf(url, payload, inline);\r\n            } catch (error) {\r\n              console.error(error);\r\n            }\r\n          } else {\r\n            console.error(error);\r\n          }\r\n        }\r\n        if (loading) {\r\n          loading.dismiss();\r\n        }\r\n      }\r\n      private async fetchPdf(\r\n        url: string,\r\n        payload: any,\r\n        inline: boolean\r\n      ): Promise<void> {\r\n        let response: any;\r\n        if (payload) {\r\n          response = await this.$http.post(url, payload, { responseType: \"blob\" });\r\n        } else {\r\n          response = await this.$http.get(url, { responseType: \"blob\" });\r\n        }\r\n        if (response.data) {\r\n          if (inline) {\r\n            this.uiHelpers.openFile(response.data as any);\r\n          } else {\r\n            this.uiHelpers.downloadFile(\r\n              response.data as any,\r\n              decodeURIComponent(response.headers(\"content-disposition\")).match(\r\n                /filename\\s*=\\s*\"?(?<file>.*?)(?:\\s*;|\"|\\s*$)/\r\n              )?.groups?.file\r\n            );\r\n          }\r\n        }\r\n      }\r\n\r\n      /**\r\n       * Export the calendar as Excel.\r\n       */\r\n      public exportCalendarExcel(): void {\r\n        const headers = this.generateExcelHeaders();\r\n        const dataRows = this.generateExcelDataRows();\r\n        const finalResult = [headers, ...dataRows];\r\n        ExcelHelpers.export(finalResult, \"lomakalenteri\");\r\n      }\r\n      private generateExcelHeaders(): string[] {\r\n        const headers = [\"Työntekijä\"];\r\n        this.allDays.forEach((day) => {\r\n            headers.push(Dates.getFormattedDate(day.date));\r\n        });\r\n        return headers;\r\n      }\r\n\r\n      private generateExcelDataRows(): any[] {\r\n        return this.series.map((series) => this.generateExcelDataRow(series));\r\n      }\r\n\r\n    private generateExcelDataRow(series: any): any[] {\r\n      const result = [];\r\n      result.push(`${series.title} ${HolidaysLogic.getPlannedLeavesCount(series.data, \"all\")}/${series.data.accrual.endSaldo} pv`);\r\n      this.allDays.forEach((day) => {\r\n          const isEventOnDay = series.events.some((ev) => day.date >= ev.start && day.date <= ev.end);\r\n          result.push(isEventOnDay ? 1 : \" \");\r\n      });\r\n      return result;\r\n    }\r\n\r\n    /**\r\n     * Copies the data as normalized data set so that we can harmonize the dates and potentially make other changes in the future.\r\n     * Copy is shallow copy of CalendarUiEvent.\r\n     */\r\n    private assureNormalizedCopy(): CalendarSeries[] {\r\n      // TODO: The whole data pump is now dependent of the trigger of \"months\" getter ,which checks the cache key.\r\n      //       This process could be more explicit / clearer (perhaps in this method?).\r\n      const result: CalendarSeries[] = [];\r\n      if (!this.data) {\r\n        return result;\r\n      }\r\n      if (this.mapper) {\r\n        const newData: CalendarSeries[] = this.mapper(this.data);\r\n        newData.forEach((item, ix) => {\r\n          result.push({\r\n            key: item.key || \"Series\" + ix,\r\n            title: item.title,\r\n            description: item.description,\r\n            avatar: item.avatar,\r\n            events: item.events.map((ev) => Object.assign({}, ev)),\r\n            data: item.data,\r\n          });\r\n        });\r\n      } else {\r\n        // Make a copy of the data and in process map to CalendarSeries[] array.\r\n        const defaultSeries: CalendarSeries = {\r\n          key: \"default\",\r\n          avatar: null,\r\n          title: null,\r\n          events: [],\r\n          data: null,\r\n        };\r\n        this.data.forEach((item, ix) => {\r\n          if (typeof item === \"string\") {\r\n            defaultSeries.events.push({ start: item });\r\n          } else if ((item as CalendarUiEvent)?.start) {\r\n            defaultSeries.events.push(Object.assign({}, item));\r\n          } else if ((item as CalendarSeries)?.key === \"default\") {\r\n            defaultSeries.events.push(...item.events.map((ev) => Object.assign({}, ev)));\r\n            defaultSeries.avatar = item.avatar || defaultSeries.avatar;\r\n            defaultSeries.title = item.title || defaultSeries.title;\r\n            defaultSeries.description = item.description || defaultSeries.description;\r\n          } else if (Array.isArray((item as CalendarSeries)?.events)) {\r\n            result.push({\r\n              key: item.key || \"Series\" + ix,\r\n              title: item.title,\r\n              description: item.description,\r\n              avatar: item.avatar,\r\n              events: item.events.map((ev) => Object.assign({}, ev)),\r\n              data: item.data,\r\n            });\r\n          }\r\n        });\r\n        if (defaultSeries.events.length) {\r\n          result.splice(0, 0, defaultSeries);\r\n        }\r\n      }\r\n      // Harmonize data\r\n      result.forEach((series) => {\r\n        series.events.forEach((ev) => {\r\n          ev.start = Dates.asDate(ev.start);\r\n          ev.end = Dates.asDate(ev.end);\r\n          if (!ev.end) {\r\n            ev.icon = ev.icon || \"fa-circle\";\r\n          }\r\n        });\r\n      });\r\n      this.cacheCounter++;\r\n      this._series = result;\r\n    }\r\n\r\n    /** Get a simplified cache key for caching months / days. */\r\n    private getCacheKey = () => {\r\n      return angular.copy({\r\n        data: this.data,\r\n        start: \"\" + this.start,\r\n        end: \"\" + this.end,\r\n        mode: this.mode || \"\",\r\n        today: this._today,\r\n      });\r\n    };\r\n\r\n    /**\r\n     * Cache counter is updated by months getter, which is the foundation of data refresh and observes full getCacheKey.\r\n     * Rest of the methods can just check this simpler cacheCounter for refreshes.\r\n     */\r\n    private cacheCounter = 0;\r\n\r\n}\r\n","/*!\n* chartjs-plugin-annotation v3.0.1\n* https://www.chartjs.org/chartjs-plugin-annotation/index\n * (c) 2023 chartjs-plugin-annotation Contributors\n * Released under the MIT License\n */\nimport { Element, defaults, Animations, Chart } from 'chart.js';\nimport { distanceBetweenPoints, defined, isFunction, callback, isObject, valueOrDefault, toRadians, isArray, toFont, addRoundedRectPath, toTRBLCorners, QUARTER_PI, PI, HALF_PI, TWO_THIRDS_PI, TAU, isNumber, RAD_PER_DEG, toPadding, isFinite, toDegrees, clipArea, unclipArea } from 'chart.js/helpers';\n\n/**\n * @typedef { import(\"chart.js\").ChartEvent } ChartEvent\n * @typedef { import('../../types/element').AnnotationElement } AnnotationElement\n */\n\nconst interaction = {\n  modes: {\n    /**\n     * Point mode returns all elements that hit test based on the event position\n     * @param {Object} state - the state of the plugin\n     * @param {ChartEvent} event - the event we are find things at\n     * @return {AnnotationElement[]} - elements that are found\n     */\n    point(state, event) {\n      return filterElements(state, event, {intersect: true});\n    },\n\n    /**\n     * Nearest mode returns the element closest to the event position\n     * @param {Object} state - the state of the plugin\n     * @param {ChartEvent} event - the event we are find things at\n     * @param {Object} options - interaction options to use\n     * @return {AnnotationElement[]} - elements that are found (only 1 element)\n     */\n    nearest(state, event, options) {\n      return getNearestItem(state, event, options);\n    },\n    /**\n     * x mode returns the elements that hit-test at the current x coordinate\n     * @param {Object} state - the state of the plugin\n     * @param {ChartEvent} event - the event we are find things at\n     * @param {Object} options - interaction options to use\n     * @return {AnnotationElement[]} - elements that are found\n     */\n    x(state, event, options) {\n      return filterElements(state, event, {intersect: options.intersect, axis: 'x'});\n    },\n\n    /**\n     * y mode returns the elements that hit-test at the current y coordinate\n     * @param {Object} state - the state of the plugin\n     * @param {ChartEvent} event - the event we are find things at\n     * @param {Object} options - interaction options to use\n     * @return {AnnotationElement[]} - elements that are found\n     */\n    y(state, event, options) {\n      return filterElements(state, event, {intersect: options.intersect, axis: 'y'});\n    }\n  }\n};\n\n/**\n * Returns all elements that hit test based on the event position\n * @param {Object} state - the state of the plugin\n * @param {ChartEvent} event - the event we are find things at\n * @param {Object} options - interaction options to use\n * @return {AnnotationElement[]} - elements that are found\n */\nfunction getElements(state, event, options) {\n  const mode = interaction.modes[options.mode] || interaction.modes.nearest;\n  return mode(state, event, options);\n}\n\nfunction inRangeByAxis(element, event, axis) {\n  if (axis !== 'x' && axis !== 'y') {\n    return element.inRange(event.x, event.y, 'x', true) || element.inRange(event.x, event.y, 'y', true);\n  }\n  return element.inRange(event.x, event.y, axis, true);\n}\n\nfunction getPointByAxis(event, center, axis) {\n  if (axis === 'x') {\n    return {x: event.x, y: center.y};\n  } else if (axis === 'y') {\n    return {x: center.x, y: event.y};\n  }\n  return center;\n}\n\nfunction filterElements(state, event, options) {\n  return state.visibleElements.filter((element) => options.intersect ? element.inRange(event.x, event.y) : inRangeByAxis(element, event, options.axis));\n}\n\nfunction getNearestItem(state, event, options) {\n  let minDistance = Number.POSITIVE_INFINITY;\n\n  return filterElements(state, event, options)\n    .reduce((nearestItems, element) => {\n      const center = element.getCenterPoint();\n      const evenPoint = getPointByAxis(event, center, options.axis);\n      const distance = distanceBetweenPoints(event, evenPoint);\n      if (distance < minDistance) {\n        nearestItems = [element];\n        minDistance = distance;\n      } else if (distance === minDistance) {\n        // Can have multiple items at the same distance in which case we sort by size\n        nearestItems.push(element);\n      }\n\n      return nearestItems;\n    }, [])\n    .sort((a, b) => a._index - b._index)\n    .slice(0, 1); // return only the top item;\n}\n\nconst isOlderPart = (act, req) => req > act || (act.length > req.length && act.slice(0, req.length) === req);\n\n/**\n * @typedef { import('chart.js').Point } Point\n * @typedef { import('chart.js').InteractionAxis } InteractionAxis\n * @typedef { import('../../types/element').AnnotationElement } AnnotationElement\n */\n\nconst EPSILON = 0.001;\nconst clamp = (x, from, to) => Math.min(to, Math.max(from, x));\n\n/**\n * @param {Object} obj\n * @param {number} from\n * @param {number} to\n * @returns {Object}\n */\nfunction clampAll(obj, from, to) {\n  for (const key of Object.keys(obj)) {\n    obj[key] = clamp(obj[key], from, to);\n  }\n  return obj;\n}\n\n/**\n * @param {Point} point\n * @param {Point} center\n * @param {number} radius\n * @param {number} borderWidth\n * @returns {boolean}\n */\nfunction inPointRange(point, center, radius, borderWidth) {\n  if (!point || !center || radius <= 0) {\n    return false;\n  }\n  const hBorderWidth = borderWidth / 2;\n  return (Math.pow(point.x - center.x, 2) + Math.pow(point.y - center.y, 2)) <= Math.pow(radius + hBorderWidth, 2);\n}\n\n/**\n * @param {Point} point\n * @param {{x: number, y: number, x2: number, y2: number}} rect\n * @param {InteractionAxis} axis\n * @param {number} borderWidth\n * @returns {boolean}\n */\nfunction inBoxRange(point, {x, y, x2, y2}, axis, borderWidth) {\n  const hBorderWidth = borderWidth / 2;\n  const inRangeX = point.x >= x - hBorderWidth - EPSILON && point.x <= x2 + hBorderWidth + EPSILON;\n  const inRangeY = point.y >= y - hBorderWidth - EPSILON && point.y <= y2 + hBorderWidth + EPSILON;\n  if (axis === 'x') {\n    return inRangeX;\n  } else if (axis === 'y') {\n    return inRangeY;\n  }\n  return inRangeX && inRangeY;\n}\n\n/**\n * @param {AnnotationElement} element\n * @param {boolean} useFinalPosition\n * @returns {Point}\n */\nfunction getElementCenterPoint(element, useFinalPosition) {\n  const {centerX, centerY} = element.getProps(['centerX', 'centerY'], useFinalPosition);\n  return {x: centerX, y: centerY};\n}\n\n/**\n * @param {string} pkg\n * @param {string} min\n * @param {string} ver\n * @param {boolean} [strict=true]\n * @returns {boolean}\n */\nfunction requireVersion(pkg, min, ver, strict = true) {\n  const parts = ver.split('.');\n  let i = 0;\n  for (const req of min.split('.')) {\n    const act = parts[i++];\n    if (parseInt(req, 10) < parseInt(act, 10)) {\n      break;\n    }\n    if (isOlderPart(act, req)) {\n      if (strict) {\n        throw new Error(`${pkg} v${ver} is not supported. v${min} or newer is required.`);\n      } else {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nconst isPercentString = (s) => typeof s === 'string' && s.endsWith('%');\nconst toPercent = (s) => parseFloat(s) / 100;\nconst toPositivePercent = (s) => clamp(toPercent(s), 0, 1);\n\nconst boxAppering = (x, y) => ({x, y, x2: x, y2: y, width: 0, height: 0});\nconst defaultInitAnimation = {\n  box: (properties) => boxAppering(properties.centerX, properties.centerY),\n  ellipse: (properties) => ({centerX: properties.centerX, centerY: properties.centerX, radius: 0, width: 0, height: 0}),\n  label: (properties) => boxAppering(properties.centerX, properties.centerY),\n  line: (properties) => boxAppering(properties.x, properties.y),\n  point: (properties) => ({centerX: properties.centerX, centerY: properties.centerY, radius: 0, width: 0, height: 0}),\n  polygon: (properties) => boxAppering(properties.centerX, properties.centerY)\n};\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import('../../types/element').AnnotationBoxModel } AnnotationBoxModel\n * @typedef { import('../../types/element').AnnotationElement } AnnotationElement\n * @typedef { import('../../types/options').AnnotationPointCoordinates } AnnotationPointCoordinates\n * @typedef { import('../../types/label').CoreLabelOptions } CoreLabelOptions\n * @typedef { import('../../types/label').LabelPositionObject } LabelPositionObject\n */\n\n/**\n * @param {number} size\n * @param {number|string} position\n * @returns {number}\n */\nfunction getRelativePosition(size, position) {\n  if (position === 'start') {\n    return 0;\n  }\n  if (position === 'end') {\n    return size;\n  }\n  if (isPercentString(position)) {\n    return toPositivePercent(position) * size;\n  }\n  return size / 2;\n}\n\n/**\n * @param {number} size\n * @param {number|string} value\n * @param {boolean} [positivePercent=true]\n * @returns {number}\n */\nfunction getSize(size, value, positivePercent = true) {\n  if (typeof value === 'number') {\n    return value;\n  } else if (isPercentString(value)) {\n    return (positivePercent ? toPositivePercent(value) : toPercent(value)) * size;\n  }\n  return size;\n}\n\n/**\n * @param {{x: number, width: number}} size\n * @param {CoreLabelOptions} options\n * @returns {number}\n */\nfunction calculateTextAlignment(size, options) {\n  const {x, width} = size;\n  const textAlign = options.textAlign;\n  if (textAlign === 'center') {\n    return x + width / 2;\n  } else if (textAlign === 'end' || textAlign === 'right') {\n    return x + width;\n  }\n  return x;\n}\n\n/**\n * @param {{x: number|string, y: number|string}|string|number} value\n * @param {string|number} defaultValue\n * @returns {{x: number|string, y: number|string}}\n */\nfunction toPosition(value, defaultValue = 'center') {\n  if (isObject(value)) {\n    return {\n      x: valueOrDefault(value.x, defaultValue),\n      y: valueOrDefault(value.y, defaultValue),\n    };\n  }\n  value = valueOrDefault(value, defaultValue);\n  return {\n    x: value,\n    y: value\n  };\n}\n\n/**\n * @param {AnnotationPointCoordinates} options\n * @returns {boolean}\n */\nfunction isBoundToPoint(options) {\n  return options && (defined(options.xValue) || defined(options.yValue));\n}\n\n/**\n * @param {Chart} chart\n * @param {AnnotationBoxModel} properties\n * @param {CoreAnnotationOptions} options\n * @returns {AnnotationElement}\n */\nfunction initAnimationProperties(chart, properties, options) {\n  const initAnim = options.init;\n  if (!initAnim) {\n    return;\n  } else if (initAnim === true) {\n    return applyDefault(properties, options);\n  }\n  return execCallback(chart, properties, options);\n}\n\n/**\n * @param {Object} options\n * @param {Array} hooks\n * @param {Object} hooksContainer\n * @returns {boolean}\n */\nfunction loadHooks(options, hooks, hooksContainer) {\n  let activated = false;\n  hooks.forEach(hook => {\n    if (isFunction(options[hook])) {\n      activated = true;\n      hooksContainer[hook] = options[hook];\n    } else if (defined(hooksContainer[hook])) {\n      delete hooksContainer[hook];\n    }\n  });\n  return activated;\n}\n\nfunction applyDefault(properties, options) {\n  const type = options.type || 'line';\n  return defaultInitAnimation[type](properties);\n}\n\nfunction execCallback(chart, properties, options) {\n  const result = callback(options.init, [{chart, properties, options}]);\n  if (result === true) {\n    return applyDefault(properties, options);\n  } else if (isObject(result)) {\n    return result;\n  }\n}\n\nconst widthCache = new Map();\nconst notRadius = (radius) => isNaN(radius) || radius <= 0;\nconst fontsKey = (fonts) => fonts.reduce(function(prev, item) {\n  prev += item.string;\n  return prev;\n}, '');\n\n/**\n * @typedef { import('chart.js').Point } Point\n * @typedef { import('../../types/label').CoreLabelOptions } CoreLabelOptions\n * @typedef { import('../../types/options').PointAnnotationOptions } PointAnnotationOptions\n */\n\n/**\n * Determine if content is an image or a canvas.\n * @param {*} content\n * @returns boolean|undefined\n * @todo move this function to chart.js helpers\n */\nfunction isImageOrCanvas(content) {\n  if (content && typeof content === 'object') {\n    const type = content.toString();\n    return (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]');\n  }\n}\n\n/**\n * Set the translation on the canvas if the rotation must be applied.\n * @param {CanvasRenderingContext2D} ctx - chart canvas context\n * @param {Point} point - the point of translation\n * @param {number} rotation - rotation (in degrees) to apply\n */\nfunction translate(ctx, {x, y}, rotation) {\n  if (rotation) {\n    ctx.translate(x, y);\n    ctx.rotate(toRadians(rotation));\n    ctx.translate(-x, -y);\n  }\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {Object} options\n * @returns {boolean|undefined}\n */\nfunction setBorderStyle(ctx, options) {\n  if (options && options.borderWidth) {\n    ctx.lineCap = options.borderCapStyle;\n    ctx.setLineDash(options.borderDash);\n    ctx.lineDashOffset = options.borderDashOffset;\n    ctx.lineJoin = options.borderJoinStyle;\n    ctx.lineWidth = options.borderWidth;\n    ctx.strokeStyle = options.borderColor;\n    return true;\n  }\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {Object} options\n */\nfunction setShadowStyle(ctx, options) {\n  ctx.shadowColor = options.backgroundShadowColor;\n  ctx.shadowBlur = options.shadowBlur;\n  ctx.shadowOffsetX = options.shadowOffsetX;\n  ctx.shadowOffsetY = options.shadowOffsetY;\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {CoreLabelOptions} options\n * @returns {{width: number, height: number}}\n */\nfunction measureLabelSize(ctx, options) {\n  const content = options.content;\n  if (isImageOrCanvas(content)) {\n    return {\n      width: getSize(content.width, options.width),\n      height: getSize(content.height, options.height)\n    };\n  }\n  const optFont = options.font;\n  const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)];\n  const strokeWidth = options.textStrokeWidth;\n  const lines = isArray(content) ? content : [content];\n  const mapKey = lines.join() + fontsKey(fonts) + strokeWidth + (ctx._measureText ? '-spriting' : '');\n  if (!widthCache.has(mapKey)) {\n    widthCache.set(mapKey, calculateLabelSize(ctx, lines, fonts, strokeWidth));\n  }\n  return widthCache.get(mapKey);\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {{x: number, y: number, width: number, height: number}} rect\n * @param {Object} options\n */\nfunction drawBox(ctx, rect, options) {\n  const {x, y, width, height} = rect;\n  ctx.save();\n  setShadowStyle(ctx, options);\n  const stroke = setBorderStyle(ctx, options);\n  ctx.fillStyle = options.backgroundColor;\n  ctx.beginPath();\n  addRoundedRectPath(ctx, {\n    x, y, w: width, h: height,\n    radius: clampAll(toTRBLCorners(options.borderRadius), 0, Math.min(width, height) / 2)\n  });\n  ctx.closePath();\n  ctx.fill();\n  if (stroke) {\n    ctx.shadowColor = options.borderShadowColor;\n    ctx.stroke();\n  }\n  ctx.restore();\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {{x: number, y: number, width: number, height: number}} rect\n * @param {CoreLabelOptions} options\n */\nfunction drawLabel(ctx, rect, options) {\n  const content = options.content;\n  if (isImageOrCanvas(content)) {\n    ctx.save();\n    ctx.globalAlpha = getOpacity(options.opacity, content.style.opacity);\n    ctx.drawImage(content, rect.x, rect.y, rect.width, rect.height);\n    ctx.restore();\n    return;\n  }\n  const labels = isArray(content) ? content : [content];\n  const optFont = options.font;\n  const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)];\n  const optColor = options.color;\n  const colors = isArray(optColor) ? optColor : [optColor];\n  const x = calculateTextAlignment(rect, options);\n  const y = rect.y + options.textStrokeWidth / 2;\n  ctx.save();\n  ctx.textBaseline = 'middle';\n  ctx.textAlign = options.textAlign;\n  if (setTextStrokeStyle(ctx, options)) {\n    applyLabelDecoration(ctx, {x, y}, labels, fonts);\n  }\n  applyLabelContent(ctx, {x, y}, labels, {fonts, colors});\n  ctx.restore();\n}\n\nfunction setTextStrokeStyle(ctx, options) {\n  if (options.textStrokeWidth > 0) {\n    // https://stackoverflow.com/questions/13627111/drawing-text-with-an-outer-stroke-with-html5s-canvas\n    ctx.lineJoin = 'round';\n    ctx.miterLimit = 2;\n    ctx.lineWidth = options.textStrokeWidth;\n    ctx.strokeStyle = options.textStrokeColor;\n    return true;\n  }\n}\n\n/**\n * @param {CanvasRenderingContext2D} ctx\n * @param {{radius: number, options: PointAnnotationOptions}} element\n * @param {number} x\n * @param {number} y\n */\nfunction drawPoint(ctx, element, x, y) {\n  const {radius, options} = element;\n  const style = options.pointStyle;\n  const rotation = options.rotation;\n  let rad = (rotation || 0) * RAD_PER_DEG;\n\n  if (isImageOrCanvas(style)) {\n    ctx.save();\n    ctx.translate(x, y);\n    ctx.rotate(rad);\n    ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);\n    ctx.restore();\n    return;\n  }\n  if (notRadius(radius)) {\n    return;\n  }\n  drawPointStyle(ctx, {x, y, radius, rotation, style, rad});\n}\n\nfunction drawPointStyle(ctx, {x, y, radius, rotation, style, rad}) {\n  let xOffset, yOffset, size, cornerRadius;\n  ctx.beginPath();\n\n  switch (style) {\n  // Default includes circle\n  default:\n    ctx.arc(x, y, radius, 0, TAU);\n    ctx.closePath();\n    break;\n  case 'triangle':\n    ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n    rad += TWO_THIRDS_PI;\n    ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n    rad += TWO_THIRDS_PI;\n    ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n    ctx.closePath();\n    break;\n  case 'rectRounded':\n    // NOTE: the rounded rect implementation changed to use `arc` instead of\n    // `quadraticCurveTo` since it generates better results when rect is\n    // almost a circle. 0.516 (instead of 0.5) produces results with visually\n    // closer proportion to the previous impl and it is inscribed in the\n    // circle with `radius`. For more details, see the following PRs:\n    // https://github.com/chartjs/Chart.js/issues/5597\n    // https://github.com/chartjs/Chart.js/issues/5858\n    cornerRadius = radius * 0.516;\n    size = radius - cornerRadius;\n    xOffset = Math.cos(rad + QUARTER_PI) * size;\n    yOffset = Math.sin(rad + QUARTER_PI) * size;\n    ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);\n    ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad);\n    ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI);\n    ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);\n    ctx.closePath();\n    break;\n  case 'rect':\n    if (!rotation) {\n      size = Math.SQRT1_2 * radius;\n      ctx.rect(x - size, y - size, 2 * size, 2 * size);\n      break;\n    }\n    rad += QUARTER_PI;\n    /* falls through */\n  case 'rectRot':\n    xOffset = Math.cos(rad) * radius;\n    yOffset = Math.sin(rad) * radius;\n    ctx.moveTo(x - xOffset, y - yOffset);\n    ctx.lineTo(x + yOffset, y - xOffset);\n    ctx.lineTo(x + xOffset, y + yOffset);\n    ctx.lineTo(x - yOffset, y + xOffset);\n    ctx.closePath();\n    break;\n  case 'crossRot':\n    rad += QUARTER_PI;\n    /* falls through */\n  case 'cross':\n    xOffset = Math.cos(rad) * radius;\n    yOffset = Math.sin(rad) * radius;\n    ctx.moveTo(x - xOffset, y - yOffset);\n    ctx.lineTo(x + xOffset, y + yOffset);\n    ctx.moveTo(x + yOffset, y - xOffset);\n    ctx.lineTo(x - yOffset, y + xOffset);\n    break;\n  case 'star':\n    xOffset = Math.cos(rad) * radius;\n    yOffset = Math.sin(rad) * radius;\n    ctx.moveTo(x - xOffset, y - yOffset);\n    ctx.lineTo(x + xOffset, y + yOffset);\n    ctx.moveTo(x + yOffset, y - xOffset);\n    ctx.lineTo(x - yOffset, y + xOffset);\n    rad += QUARTER_PI;\n    xOffset = Math.cos(rad) * radius;\n    yOffset = Math.sin(rad) * radius;\n    ctx.moveTo(x - xOffset, y - yOffset);\n    ctx.lineTo(x + xOffset, y + yOffset);\n    ctx.moveTo(x + yOffset, y - xOffset);\n    ctx.lineTo(x - yOffset, y + xOffset);\n    break;\n  case 'line':\n    xOffset = Math.cos(rad) * radius;\n    yOffset = Math.sin(rad) * radius;\n    ctx.moveTo(x - xOffset, y - yOffset);\n    ctx.lineTo(x + xOffset, y + yOffset);\n    break;\n  case 'dash':\n    ctx.moveTo(x, y);\n    ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius);\n    break;\n  }\n\n  ctx.fill();\n}\n\nfunction calculateLabelSize(ctx, lines, fonts, strokeWidth) {\n  ctx.save();\n  const count = lines.length;\n  let width = 0;\n  let height = strokeWidth;\n  for (let i = 0; i < count; i++) {\n    const font = fonts[Math.min(i, fonts.length - 1)];\n    ctx.font = font.string;\n    const text = lines[i];\n    width = Math.max(width, ctx.measureText(text).width + strokeWidth);\n    height += font.lineHeight;\n  }\n  ctx.restore();\n  return {width, height};\n}\n\nfunction applyLabelDecoration(ctx, {x, y}, labels, fonts) {\n  ctx.beginPath();\n  let lhs = 0;\n  labels.forEach(function(l, i) {\n    const f = fonts[Math.min(i, fonts.length - 1)];\n    const lh = f.lineHeight;\n    ctx.font = f.string;\n    ctx.strokeText(l, x, y + lh / 2 + lhs);\n    lhs += lh;\n  });\n  ctx.stroke();\n}\n\nfunction applyLabelContent(ctx, {x, y}, labels, {fonts, colors}) {\n  let lhs = 0;\n  labels.forEach(function(l, i) {\n    const c = colors[Math.min(i, colors.length - 1)];\n    const f = fonts[Math.min(i, fonts.length - 1)];\n    const lh = f.lineHeight;\n    ctx.beginPath();\n    ctx.font = f.string;\n    ctx.fillStyle = c;\n    ctx.fillText(l, x, y + lh / 2 + lhs);\n    lhs += lh;\n    ctx.fill();\n  });\n}\n\nfunction getOpacity(value, elementValue) {\n  const opacity = isNumber(value) ? value : elementValue;\n  return isNumber(opacity) ? clamp(opacity, 0, 1) : 1;\n}\n\nconst limitedLineScale = {\n  xScaleID: {min: 'xMin', max: 'xMax', start: 'left', end: 'right', startProp: 'x', endProp: 'x2'},\n  yScaleID: {min: 'yMin', max: 'yMax', start: 'bottom', end: 'top', startProp: 'y', endProp: 'y2'}\n};\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import(\"chart.js\").Scale } Scale\n * @typedef { import(\"chart.js\").Point } Point\n * @typedef { import('../../types/element').AnnotationBoxModel } AnnotationBoxModel\n * @typedef { import('../../types/options').CoreAnnotationOptions } CoreAnnotationOptions\n * @typedef { import('../../types/options').LineAnnotationOptions } LineAnnotationOptions\n * @typedef { import('../../types/options').PointAnnotationOptions } PointAnnotationOptions\n * @typedef { import('../../types/options').PolygonAnnotationOptions } PolygonAnnotationOptions\n */\n\n/**\n * @param {Scale} scale\n * @param {number|string} value\n * @param {number} fallback\n * @returns {number}\n */\nfunction scaleValue(scale, value, fallback) {\n  value = typeof value === 'number' ? value : scale.parse(value);\n  return isFinite(value) ? scale.getPixelForValue(value) : fallback;\n}\n\n/**\n * Search the scale defined in chartjs by the axis related to the annotation options key.\n * @param {{ [key: string]: Scale }} scales\n * @param {CoreAnnotationOptions} options\n * @param {string} key\n * @returns {string}\n */\nfunction retrieveScaleID(scales, options, key) {\n  const scaleID = options[key];\n  if (scaleID || key === 'scaleID') {\n    return scaleID;\n  }\n  const axis = key.charAt(0);\n  const axes = Object.values(scales).filter((scale) => scale.axis && scale.axis === axis);\n  if (axes.length) {\n    return axes[0].id;\n  }\n  return axis;\n}\n\n/**\n * @param {Scale} scale\n * @param {{min: number, max: number, start: number, end: number}} options\n * @returns {{start: number, end: number}|undefined}\n */\nfunction getDimensionByScale(scale, options) {\n  if (scale) {\n    const reverse = scale.options.reverse;\n    const start = scaleValue(scale, options.min, reverse ? options.end : options.start);\n    const end = scaleValue(scale, options.max, reverse ? options.start : options.end);\n    return {\n      start,\n      end\n    };\n  }\n}\n\n/**\n * @param {Chart} chart\n * @param {CoreAnnotationOptions} options\n * @returns {Point}\n */\nfunction getChartPoint(chart, options) {\n  const {chartArea, scales} = chart;\n  const xScale = scales[retrieveScaleID(scales, options, 'xScaleID')];\n  const yScale = scales[retrieveScaleID(scales, options, 'yScaleID')];\n  let x = chartArea.width / 2;\n  let y = chartArea.height / 2;\n\n  if (xScale) {\n    x = scaleValue(xScale, options.xValue, xScale.left + xScale.width / 2);\n  }\n\n  if (yScale) {\n    y = scaleValue(yScale, options.yValue, yScale.top + yScale.height / 2);\n  }\n  return {x, y};\n}\n\n/**\n * @param {Chart} chart\n * @param {CoreAnnotationOptions} options\n * @returns {AnnotationBoxModel}\n */\nfunction resolveBoxProperties(chart, options) {\n  const scales = chart.scales;\n  const xScale = scales[retrieveScaleID(scales, options, 'xScaleID')];\n  const yScale = scales[retrieveScaleID(scales, options, 'yScaleID')];\n\n  if (!xScale && !yScale) {\n    return {};\n  }\n\n  let {left: x, right: x2} = xScale || chart.chartArea;\n  let {top: y, bottom: y2} = yScale || chart.chartArea;\n  const xDim = getChartDimensionByScale(xScale, {min: options.xMin, max: options.xMax, start: x, end: x2});\n  x = xDim.start;\n  x2 = xDim.end;\n  const yDim = getChartDimensionByScale(yScale, {min: options.yMin, max: options.yMax, start: y2, end: y});\n  y = yDim.start;\n  y2 = yDim.end;\n\n  return {\n    x,\n    y,\n    x2,\n    y2,\n    width: x2 - x,\n    height: y2 - y,\n    centerX: x + (x2 - x) / 2,\n    centerY: y + (y2 - y) / 2\n  };\n}\n\n/**\n * @param {Chart} chart\n * @param {PointAnnotationOptions|PolygonAnnotationOptions} options\n * @returns {AnnotationBoxModel}\n */\nfunction resolvePointProperties(chart, options) {\n  if (!isBoundToPoint(options)) {\n    const box = resolveBoxProperties(chart, options);\n    let radius = options.radius;\n    if (!radius || isNaN(radius)) {\n      radius = Math.min(box.width, box.height) / 2;\n      options.radius = radius;\n    }\n    const size = radius * 2;\n    const adjustCenterX = box.centerX + options.xAdjust;\n    const adjustCenterY = box.centerY + options.yAdjust;\n    return {\n      x: adjustCenterX - radius,\n      y: adjustCenterY - radius,\n      x2: adjustCenterX + radius,\n      y2: adjustCenterY + radius,\n      centerX: adjustCenterX,\n      centerY: adjustCenterY,\n      width: size,\n      height: size,\n      radius\n    };\n  }\n  return getChartCircle(chart, options);\n}\n/**\n * @param {Chart} chart\n * @param {LineAnnotationOptions} options\n * @returns {AnnotationBoxModel}\n */\nfunction resolveLineProperties(chart, options) {\n  const {scales, chartArea} = chart;\n  const scale = scales[options.scaleID];\n  const area = {x: chartArea.left, y: chartArea.top, x2: chartArea.right, y2: chartArea.bottom};\n\n  if (scale) {\n    resolveFullLineProperties(scale, area, options);\n  } else {\n    resolveLimitedLineProperties(scales, area, options);\n  }\n  return area;\n}\n\n/**\n * @param {Chart} chart\n * @param {CoreAnnotationOptions} options\n * @param {boolean} [centerBased=false]\n * @returns {AnnotationBoxModel}\n */\nfunction resolveBoxAndLabelProperties(chart, options) {\n  const properties = resolveBoxProperties(chart, options);\n  properties.initProperties = initAnimationProperties(chart, properties, options);\n  properties.elements = [{\n    type: 'label',\n    optionScope: 'label',\n    properties: resolveLabelElementProperties$1(chart, properties, options),\n    initProperties: properties.initProperties\n  }];\n  return properties;\n}\n\nfunction getChartCircle(chart, options) {\n  const point = getChartPoint(chart, options);\n  const size = options.radius * 2;\n  return {\n    x: point.x - options.radius + options.xAdjust,\n    y: point.y - options.radius + options.yAdjust,\n    x2: point.x + options.radius + options.xAdjust,\n    y2: point.y + options.radius + options.yAdjust,\n    centerX: point.x + options.xAdjust,\n    centerY: point.y + options.yAdjust,\n    radius: options.radius,\n    width: size,\n    height: size\n  };\n}\n\nfunction getChartDimensionByScale(scale, options) {\n  const result = getDimensionByScale(scale, options) || options;\n  return {\n    start: Math.min(result.start, result.end),\n    end: Math.max(result.start, result.end)\n  };\n}\n\nfunction resolveFullLineProperties(scale, area, options) {\n  const min = scaleValue(scale, options.value, NaN);\n  const max = scaleValue(scale, options.endValue, min);\n  if (scale.isHorizontal()) {\n    area.x = min;\n    area.x2 = max;\n  } else {\n    area.y = min;\n    area.y2 = max;\n  }\n}\n\nfunction resolveLimitedLineProperties(scales, area, options) {\n  for (const scaleId of Object.keys(limitedLineScale)) {\n    const scale = scales[retrieveScaleID(scales, options, scaleId)];\n    if (scale) {\n      const {min, max, start, end, startProp, endProp} = limitedLineScale[scaleId];\n      const dim = getDimensionByScale(scale, {min: options[min], max: options[max], start: scale[start], end: scale[end]});\n      area[startProp] = dim.start;\n      area[endProp] = dim.end;\n    }\n  }\n}\n\nfunction calculateX({properties, options}, labelSize, position, padding) {\n  const {x: start, x2: end, width: size} = properties;\n  return calculatePosition$1({start, end, size, borderWidth: options.borderWidth}, {\n    position: position.x,\n    padding: {start: padding.left, end: padding.right},\n    adjust: options.label.xAdjust,\n    size: labelSize.width\n  });\n}\n\nfunction calculateY({properties, options}, labelSize, position, padding) {\n  const {y: start, y2: end, height: size} = properties;\n  return calculatePosition$1({start, end, size, borderWidth: options.borderWidth}, {\n    position: position.y,\n    padding: {start: padding.top, end: padding.bottom},\n    adjust: options.label.yAdjust,\n    size: labelSize.height\n  });\n}\n\nfunction calculatePosition$1(boxOpts, labelOpts) {\n  const {start, end, borderWidth} = boxOpts;\n  const {position, padding: {start: padStart, end: padEnd}, adjust} = labelOpts;\n  const availableSize = end - borderWidth - start - padStart - padEnd - labelOpts.size;\n  return start + borderWidth / 2 + adjust + getRelativePosition(availableSize, position);\n}\n\nfunction resolveLabelElementProperties$1(chart, properties, options) {\n  const label = options.label;\n  label.backgroundColor = 'transparent';\n  label.callout.display = false;\n  const position = toPosition(label.position);\n  const padding = toPadding(label.padding);\n  const labelSize = measureLabelSize(chart.ctx, label);\n  const x = calculateX({properties, options}, labelSize, position, padding);\n  const y = calculateY({properties, options}, labelSize, position, padding);\n  const width = labelSize.width + padding.width;\n  const height = labelSize.height + padding.height;\n  return {\n    x,\n    y,\n    x2: x + width,\n    y2: y + height,\n    width,\n    height,\n    centerX: x + width / 2,\n    centerY: y + height / 2,\n    rotation: label.rotation\n  };\n\n}\n\n/**\n * @typedef {import('chart.js').Point} Point\n */\n\n/**\n * Rotate a `point` relative to `center` point by `angle`\n * @param {Point} point - the point to rotate\n * @param {Point} center - center point for rotation\n * @param {number} angle - angle for rotation, in radians\n * @returns {Point} rotated point\n */\nfunction rotated(point, center, angle) {\n  const cos = Math.cos(angle);\n  const sin = Math.sin(angle);\n  const cx = center.x;\n  const cy = center.y;\n\n  return {\n    x: cx + cos * (point.x - cx) - sin * (point.y - cy),\n    y: cy + sin * (point.x - cx) + cos * (point.y - cy)\n  };\n}\n\nconst moveHooks = ['enter', 'leave'];\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import('../../types/options').AnnotationPluginOptions } AnnotationPluginOptions\n */\n\nconst eventHooks = moveHooks.concat('click');\n\n/**\n * @param {Chart} chart\n * @param {Object} state\n * @param {AnnotationPluginOptions} options\n */\nfunction updateListeners(chart, state, options) {\n  state.listened = loadHooks(options, eventHooks, state.listeners);\n  state.moveListened = false;\n  state._getElements = getElements; // for testing\n\n  moveHooks.forEach(hook => {\n    if (isFunction(options[hook])) {\n      state.moveListened = true;\n    }\n  });\n\n  if (!state.listened || !state.moveListened) {\n    state.annotations.forEach(scope => {\n      if (!state.listened && isFunction(scope.click)) {\n        state.listened = true;\n      }\n      if (!state.moveListened) {\n        moveHooks.forEach(hook => {\n          if (isFunction(scope[hook])) {\n            state.listened = true;\n            state.moveListened = true;\n          }\n        });\n      }\n    });\n  }\n}\n\n/**\n * @param {Object} state\n * @param {ChartEvent} event\n * @param {AnnotationPluginOptions} options\n * @return {boolean|undefined}\n */\nfunction handleEvent(state, event, options) {\n  if (state.listened) {\n    switch (event.type) {\n    case 'mousemove':\n    case 'mouseout':\n      return handleMoveEvents(state, event, options);\n    case 'click':\n      return handleClickEvents(state, event, options);\n    }\n  }\n}\n\nfunction handleMoveEvents(state, event, options) {\n  if (!state.moveListened) {\n    return;\n  }\n\n  let elements;\n\n  if (event.type === 'mousemove') {\n    elements = getElements(state, event, options.interaction);\n  } else {\n    elements = [];\n  }\n\n  const previous = state.hovered;\n  state.hovered = elements;\n\n  const context = {state, event};\n  let changed = dispatchMoveEvents(context, 'leave', previous, elements);\n  return dispatchMoveEvents(context, 'enter', elements, previous) || changed;\n}\n\nfunction dispatchMoveEvents({state, event}, hook, elements, checkElements) {\n  let changed;\n  for (const element of elements) {\n    if (checkElements.indexOf(element) < 0) {\n      changed = dispatchEvent(element.options[hook] || state.listeners[hook], element, event) || changed;\n    }\n  }\n  return changed;\n}\n\nfunction handleClickEvents(state, event, options) {\n  const listeners = state.listeners;\n  const elements = getElements(state, event, options.interaction);\n  let changed;\n  for (const element of elements) {\n    changed = dispatchEvent(element.options.click || listeners.click, element, event) || changed;\n  }\n  return changed;\n}\n\nfunction dispatchEvent(handler, element, event) {\n  return callback(handler, [element.$context, event]) === true;\n}\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import('../../types/options').AnnotationPluginOptions } AnnotationPluginOptions\n * @typedef { import('../../types/element').AnnotationElement } AnnotationElement\n */\n\nconst elementHooks = ['afterDraw', 'beforeDraw'];\n\n/**\n * @param {Chart} chart\n * @param {Object} state\n * @param {AnnotationPluginOptions} options\n */\nfunction updateHooks(chart, state, options) {\n  const visibleElements = state.visibleElements;\n  state.hooked = loadHooks(options, elementHooks, state.hooks);\n\n  if (!state.hooked) {\n    visibleElements.forEach(scope => {\n      if (!state.hooked) {\n        elementHooks.forEach(hook => {\n          if (isFunction(scope.options[hook])) {\n            state.hooked = true;\n          }\n        });\n      }\n    });\n  }\n}\n\n/**\n * @param {Object} state\n * @param {AnnotationElement} element\n * @param {string} hook\n */\nfunction invokeHook(state, element, hook) {\n  if (state.hooked) {\n    const callbackHook = element.options[hook] || state.hooks[hook];\n    return callback(callbackHook, [element.$context]);\n  }\n}\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import(\"chart.js\").Scale } Scale\n * @typedef { import('../../types/options').CoreAnnotationOptions } CoreAnnotationOptions\n */\n\n/**\n * @param {Chart} chart\n * @param {Scale} scale\n * @param {CoreAnnotationOptions[]} annotations\n */\nfunction adjustScaleRange(chart, scale, annotations) {\n  const range = getScaleLimits(chart.scales, scale, annotations);\n  let changed = changeScaleLimit(scale, range, 'min', 'suggestedMin');\n  changed = changeScaleLimit(scale, range, 'max', 'suggestedMax') || changed;\n  if (changed && isFunction(scale.handleTickRangeOptions)) {\n    scale.handleTickRangeOptions();\n  }\n}\n\n/**\n * @param {CoreAnnotationOptions[]} annotations\n * @param {{ [key: string]: Scale }} scales\n */\nfunction verifyScaleOptions(annotations, scales) {\n  for (const annotation of annotations) {\n    verifyScaleIDs(annotation, scales);\n  }\n}\n\nfunction changeScaleLimit(scale, range, limit, suggestedLimit) {\n  if (isFinite(range[limit]) && !scaleLimitDefined(scale.options, limit, suggestedLimit)) {\n    const changed = scale[limit] !== range[limit];\n    scale[limit] = range[limit];\n    return changed;\n  }\n}\n\nfunction scaleLimitDefined(scaleOptions, limit, suggestedLimit) {\n  return defined(scaleOptions[limit]) || defined(scaleOptions[suggestedLimit]);\n}\n\nfunction verifyScaleIDs(annotation, scales) {\n  for (const key of ['scaleID', 'xScaleID', 'yScaleID']) {\n    const scaleID = retrieveScaleID(scales, annotation, key);\n    if (scaleID && !scales[scaleID] && verifyProperties(annotation, key)) {\n      console.warn(`No scale found with id '${scaleID}' for annotation '${annotation.id}'`);\n    }\n  }\n}\n\nfunction verifyProperties(annotation, key) {\n  if (key === 'scaleID') {\n    return true;\n  }\n  const axis = key.charAt(0);\n  for (const prop of ['Min', 'Max', 'Value']) {\n    if (defined(annotation[axis + prop])) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfunction getScaleLimits(scales, scale, annotations) {\n  const axis = scale.axis;\n  const scaleID = scale.id;\n  const scaleIDOption = axis + 'ScaleID';\n  const limits = {\n    min: valueOrDefault(scale.min, Number.NEGATIVE_INFINITY),\n    max: valueOrDefault(scale.max, Number.POSITIVE_INFINITY)\n  };\n  for (const annotation of annotations) {\n    if (annotation.scaleID === scaleID) {\n      updateLimits(annotation, scale, ['value', 'endValue'], limits);\n    } else if (retrieveScaleID(scales, annotation, scaleIDOption) === scaleID) {\n      updateLimits(annotation, scale, [axis + 'Min', axis + 'Max', axis + 'Value'], limits);\n    }\n  }\n  return limits;\n}\n\nfunction updateLimits(annotation, scale, props, limits) {\n  for (const prop of props) {\n    const raw = annotation[prop];\n    if (defined(raw)) {\n      const value = scale.parse(raw);\n      limits.min = Math.min(limits.min, value);\n      limits.max = Math.max(limits.max, value);\n    }\n  }\n}\n\nclass BoxAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    const {x, y} = rotated({x: mouseX, y: mouseY}, this.getCenterPoint(useFinalPosition), toRadians(-this.options.rotation));\n    return inBoxRange({x, y}, this.getProps(['x', 'y', 'x2', 'y2'], useFinalPosition), axis, this.options.borderWidth);\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    ctx.save();\n    translate(ctx, this.getCenterPoint(), this.options.rotation);\n    drawBox(ctx, this, this.options);\n    ctx.restore();\n  }\n\n  get label() {\n    return this.elements && this.elements[0];\n  }\n\n  resolveElementProperties(chart, options) {\n    return resolveBoxAndLabelProperties(chart, options);\n  }\n}\n\nBoxAnnotation.id = 'boxAnnotation';\n\nBoxAnnotation.defaults = {\n  adjustScaleRange: true,\n  backgroundShadowColor: 'transparent',\n  borderCapStyle: 'butt',\n  borderDash: [],\n  borderDashOffset: 0,\n  borderJoinStyle: 'miter',\n  borderRadius: 0,\n  borderShadowColor: 'transparent',\n  borderWidth: 1,\n  display: true,\n  init: undefined,\n  label: {\n    backgroundColor: 'transparent',\n    borderWidth: 0,\n    callout: {\n      display: false\n    },\n    color: 'black',\n    content: null,\n    display: false,\n    drawTime: undefined,\n    font: {\n      family: undefined,\n      lineHeight: undefined,\n      size: undefined,\n      style: undefined,\n      weight: 'bold'\n    },\n    height: undefined,\n    opacity: undefined,\n    padding: 6,\n    position: 'center',\n    rotation: undefined,\n    textAlign: 'start',\n    textStrokeColor: undefined,\n    textStrokeWidth: 0,\n    width: undefined,\n    xAdjust: 0,\n    yAdjust: 0,\n    z: undefined\n  },\n  rotation: 0,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  z: 0\n};\n\nBoxAnnotation.defaultRoutes = {\n  borderColor: 'color',\n  backgroundColor: 'color'\n};\n\nBoxAnnotation.descriptors = {\n  label: {\n    _fallback: true\n  }\n};\n\nconst positions = ['left', 'bottom', 'top', 'right'];\n\nclass LabelAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    const {x, y} = rotated({x: mouseX, y: mouseY}, this.getCenterPoint(useFinalPosition), toRadians(-this.rotation));\n    return inBoxRange({x, y}, this.getProps(['x', 'y', 'x2', 'y2'], useFinalPosition), axis, this.options.borderWidth);\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    const options = this.options;\n    const visible = !defined(this._visible) || this._visible;\n    if (!options.display || !options.content || !visible) {\n      return;\n    }\n    ctx.save();\n    translate(ctx, this.getCenterPoint(), this.rotation);\n    drawCallout(ctx, this);\n    drawBox(ctx, this, options);\n    drawLabel(ctx, getLabelSize(this), options);\n    ctx.restore();\n  }\n\n  resolveElementProperties(chart, options) {\n    let point;\n    if (!isBoundToPoint(options)) {\n      const {centerX, centerY} = resolveBoxProperties(chart, options);\n      point = {x: centerX, y: centerY};\n    } else {\n      point = getChartPoint(chart, options);\n    }\n    const padding = toPadding(options.padding);\n    const labelSize = measureLabelSize(chart.ctx, options);\n    const boxSize = measureRect(point, labelSize, options, padding);\n    return {\n      initProperties: initAnimationProperties(chart, boxSize, options),\n      pointX: point.x,\n      pointY: point.y,\n      ...boxSize,\n      rotation: options.rotation\n    };\n  }\n}\n\nLabelAnnotation.id = 'labelAnnotation';\n\nLabelAnnotation.defaults = {\n  adjustScaleRange: true,\n  backgroundColor: 'transparent',\n  backgroundShadowColor: 'transparent',\n  borderCapStyle: 'butt',\n  borderDash: [],\n  borderDashOffset: 0,\n  borderJoinStyle: 'miter',\n  borderRadius: 0,\n  borderShadowColor: 'transparent',\n  borderWidth: 0,\n  callout: {\n    borderCapStyle: 'butt',\n    borderColor: undefined,\n    borderDash: [],\n    borderDashOffset: 0,\n    borderJoinStyle: 'miter',\n    borderWidth: 1,\n    display: false,\n    margin: 5,\n    position: 'auto',\n    side: 5,\n    start: '50%',\n  },\n  color: 'black',\n  content: null,\n  display: true,\n  font: {\n    family: undefined,\n    lineHeight: undefined,\n    size: undefined,\n    style: undefined,\n    weight: undefined\n  },\n  height: undefined,\n  init: undefined,\n  opacity: undefined,\n  padding: 6,\n  position: 'center',\n  rotation: 0,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  textAlign: 'center',\n  textStrokeColor: undefined,\n  textStrokeWidth: 0,\n  width: undefined,\n  xAdjust: 0,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  xValue: undefined,\n  yAdjust: 0,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  yValue: undefined,\n  z: 0\n};\n\nLabelAnnotation.defaultRoutes = {\n  borderColor: 'color'\n};\n\nfunction measureRect(point, size, options, padding) {\n  const width = size.width + padding.width + options.borderWidth;\n  const height = size.height + padding.height + options.borderWidth;\n  const position = toPosition(options.position, 'center');\n  const x = calculatePosition(point.x, width, options.xAdjust, position.x);\n  const y = calculatePosition(point.y, height, options.yAdjust, position.y);\n\n  return {\n    x,\n    y,\n    x2: x + width,\n    y2: y + height,\n    width,\n    height,\n    centerX: x + width / 2,\n    centerY: y + height / 2\n  };\n}\n\nfunction calculatePosition(start, size, adjust = 0, position) {\n  return start - getRelativePosition(size, position) + adjust;\n}\n\nfunction drawCallout(ctx, element) {\n  const {pointX, pointY, options} = element;\n  const callout = options.callout;\n  const calloutPosition = callout && callout.display && resolveCalloutPosition(element, callout);\n  if (!calloutPosition || isPointInRange(element, callout, calloutPosition)) {\n    return;\n  }\n\n  ctx.save();\n  ctx.beginPath();\n  const stroke = setBorderStyle(ctx, callout);\n  if (!stroke) {\n    return ctx.restore();\n  }\n  const {separatorStart, separatorEnd} = getCalloutSeparatorCoord(element, calloutPosition);\n  const {sideStart, sideEnd} = getCalloutSideCoord(element, calloutPosition, separatorStart);\n  if (callout.margin > 0 || options.borderWidth === 0) {\n    ctx.moveTo(separatorStart.x, separatorStart.y);\n    ctx.lineTo(separatorEnd.x, separatorEnd.y);\n  }\n  ctx.moveTo(sideStart.x, sideStart.y);\n  ctx.lineTo(sideEnd.x, sideEnd.y);\n  const rotatedPoint = rotated({x: pointX, y: pointY}, element.getCenterPoint(), toRadians(-element.rotation));\n  ctx.lineTo(rotatedPoint.x, rotatedPoint.y);\n  ctx.stroke();\n  ctx.restore();\n}\n\nfunction getCalloutSeparatorCoord(element, position) {\n  const {x, y, x2, y2} = element;\n  const adjust = getCalloutSeparatorAdjust(element, position);\n  let separatorStart, separatorEnd;\n  if (position === 'left' || position === 'right') {\n    separatorStart = {x: x + adjust, y};\n    separatorEnd = {x: separatorStart.x, y: y2};\n  } else {\n    //  position 'top' or 'bottom'\n    separatorStart = {x, y: y + adjust};\n    separatorEnd = {x: x2, y: separatorStart.y};\n  }\n  return {separatorStart, separatorEnd};\n}\n\nfunction getCalloutSeparatorAdjust(element, position) {\n  const {width, height, options} = element;\n  const adjust = options.callout.margin + options.borderWidth / 2;\n  if (position === 'right') {\n    return width + adjust;\n  } else if (position === 'bottom') {\n    return height + adjust;\n  }\n  return -adjust;\n}\n\nfunction getCalloutSideCoord(element, position, separatorStart) {\n  const {y, width, height, options} = element;\n  const start = options.callout.start;\n  const side = getCalloutSideAdjust(position, options.callout);\n  let sideStart, sideEnd;\n  if (position === 'left' || position === 'right') {\n    sideStart = {x: separatorStart.x, y: y + getSize(height, start)};\n    sideEnd = {x: sideStart.x + side, y: sideStart.y};\n  } else {\n    //  position 'top' or 'bottom'\n    sideStart = {x: separatorStart.x + getSize(width, start), y: separatorStart.y};\n    sideEnd = {x: sideStart.x, y: sideStart.y + side};\n  }\n  return {sideStart, sideEnd};\n}\n\nfunction getCalloutSideAdjust(position, options) {\n  const side = options.side;\n  if (position === 'left' || position === 'top') {\n    return -side;\n  }\n  return side;\n}\n\nfunction resolveCalloutPosition(element, options) {\n  const position = options.position;\n  if (positions.includes(position)) {\n    return position;\n  }\n  return resolveCalloutAutoPosition(element, options);\n}\n\nfunction resolveCalloutAutoPosition(element, options) {\n  const {x, y, x2, y2, width, height, pointX, pointY, centerX, centerY, rotation} = element;\n  const center = {x: centerX, y: centerY};\n  const start = options.start;\n  const xAdjust = getSize(width, start);\n  const yAdjust = getSize(height, start);\n  const xPoints = [x, x + xAdjust, x + xAdjust, x2];\n  const yPoints = [y + yAdjust, y2, y, y2];\n  const result = [];\n  for (let index = 0; index < 4; index++) {\n    const rotatedPoint = rotated({x: xPoints[index], y: yPoints[index]}, center, toRadians(rotation));\n    result.push({\n      position: positions[index],\n      distance: distanceBetweenPoints(rotatedPoint, {x: pointX, y: pointY})\n    });\n  }\n  return result.sort((a, b) => a.distance - b.distance)[0].position;\n}\n\nfunction getLabelSize({x, y, width, height, options}) {\n  const hBorderWidth = options.borderWidth / 2;\n  const padding = toPadding(options.padding);\n  return {\n    x: x + padding.left + hBorderWidth,\n    y: y + padding.top + hBorderWidth,\n    width: width - padding.left - padding.right - options.borderWidth,\n    height: height - padding.top - padding.bottom - options.borderWidth\n  };\n}\n\nfunction isPointInRange(element, callout, position) {\n  const {pointX, pointY} = element;\n  const margin = callout.margin;\n  let x = pointX;\n  let y = pointY;\n  if (position === 'left') {\n    x += margin;\n  } else if (position === 'right') {\n    x -= margin;\n  } else if (position === 'top') {\n    y += margin;\n  } else if (position === 'bottom') {\n    y -= margin;\n  }\n  return element.inRange(x, y);\n}\n\nconst pointInLine = (p1, p2, t) => ({x: p1.x + t * (p2.x - p1.x), y: p1.y + t * (p2.y - p1.y)});\nconst interpolateX = (y, p1, p2) => pointInLine(p1, p2, Math.abs((y - p1.y) / (p2.y - p1.y))).x;\nconst interpolateY = (x, p1, p2) => pointInLine(p1, p2, Math.abs((x - p1.x) / (p2.x - p1.x))).y;\nconst sqr = v => v * v;\nconst rangeLimit = (mouseX, mouseY, {x, y, x2, y2}, axis) => axis === 'y' ? {start: Math.min(y, y2), end: Math.max(y, y2), value: mouseY} : {start: Math.min(x, x2), end: Math.max(x, x2), value: mouseX};\n// http://www.independent-software.com/determining-coordinates-on-a-html-canvas-bezier-curve.html\nconst coordInCurve = (start, cp, end, t) => (1 - t) * (1 - t) * start + 2 * (1 - t) * t * cp + t * t * end;\nconst pointInCurve = (start, cp, end, t) => ({x: coordInCurve(start.x, cp.x, end.x, t), y: coordInCurve(start.y, cp.y, end.y, t)});\nconst coordAngleInCurve = (start, cp, end, t) => 2 * (1 - t) * (cp - start) + 2 * t * (end - cp);\nconst angleInCurve = (start, cp, end, t) => -Math.atan2(coordAngleInCurve(start.x, cp.x, end.x, t), coordAngleInCurve(start.y, cp.y, end.y, t)) + 0.5 * PI;\n\nclass LineAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    const hBorderWidth = this.options.borderWidth / 2;\n    if (axis !== 'x' && axis !== 'y') {\n      const point = {mouseX, mouseY};\n      const {path, ctx} = this;\n      if (path) {\n        setBorderStyle(ctx, this.options);\n        const {chart} = this.$context;\n        const mx = mouseX * chart.currentDevicePixelRatio;\n        const my = mouseY * chart.currentDevicePixelRatio;\n        const result = ctx.isPointInStroke(path, mx, my) || isOnLabel(this, point, useFinalPosition);\n        ctx.restore();\n        return result;\n      }\n      const epsilon = sqr(hBorderWidth);\n      return intersects(this, point, epsilon, useFinalPosition) || isOnLabel(this, point, useFinalPosition);\n    }\n    return inAxisRange(this, {mouseX, mouseY}, axis, {hBorderWidth, useFinalPosition});\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    const {x, y, x2, y2, cp, options} = this;\n\n    ctx.save();\n    if (!setBorderStyle(ctx, options)) {\n      // no border width, then line is not drawn\n      return ctx.restore();\n    }\n    setShadowStyle(ctx, options);\n\n    const length = Math.sqrt(Math.pow(x2 - x, 2) + Math.pow(y2 - y, 2));\n    if (options.curve && cp) {\n      drawCurve(ctx, this, cp, length);\n      return ctx.restore();\n    }\n    const {startOpts, endOpts, startAdjust, endAdjust} = getArrowHeads(this);\n    const angle = Math.atan2(y2 - y, x2 - x);\n    ctx.translate(x, y);\n    ctx.rotate(angle);\n    ctx.beginPath();\n    ctx.moveTo(0 + startAdjust, 0);\n    ctx.lineTo(length - endAdjust, 0);\n    ctx.shadowColor = options.borderShadowColor;\n    ctx.stroke();\n    drawArrowHead(ctx, 0, startAdjust, startOpts);\n    drawArrowHead(ctx, length, -endAdjust, endOpts);\n    ctx.restore();\n  }\n\n  get label() {\n    return this.elements && this.elements[0];\n  }\n\n  resolveElementProperties(chart, options) {\n    const area = resolveLineProperties(chart, options);\n    const {x, y, x2, y2} = area;\n    const inside = isLineInArea(area, chart.chartArea);\n    const properties = inside\n      ? limitLineToArea({x, y}, {x: x2, y: y2}, chart.chartArea)\n      : {x, y, x2, y2, width: Math.abs(x2 - x), height: Math.abs(y2 - y)};\n    properties.centerX = (x2 + x) / 2;\n    properties.centerY = (y2 + y) / 2;\n    properties.initProperties = initAnimationProperties(chart, properties, options);\n    if (options.curve) {\n      const p1 = {x: properties.x, y: properties.y};\n      const p2 = {x: properties.x2, y: properties.y2};\n      properties.cp = getControlPoint(properties, options, distanceBetweenPoints(p1, p2));\n    }\n    const labelProperties = resolveLabelElementProperties(chart, properties, options.label);\n    // additonal prop to manage zoom/pan\n    labelProperties._visible = inside;\n\n    properties.elements = [{\n      type: 'label',\n      optionScope: 'label',\n      properties: labelProperties,\n      initProperties: properties.initProperties\n    }];\n    return properties;\n  }\n}\n\nLineAnnotation.id = 'lineAnnotation';\n\nconst arrowHeadsDefaults = {\n  backgroundColor: undefined,\n  backgroundShadowColor: undefined,\n  borderColor: undefined,\n  borderDash: undefined,\n  borderDashOffset: undefined,\n  borderShadowColor: undefined,\n  borderWidth: undefined,\n  display: undefined,\n  fill: undefined,\n  length: undefined,\n  shadowBlur: undefined,\n  shadowOffsetX: undefined,\n  shadowOffsetY: undefined,\n  width: undefined\n};\n\nLineAnnotation.defaults = {\n  adjustScaleRange: true,\n  arrowHeads: {\n    display: false,\n    end: Object.assign({}, arrowHeadsDefaults),\n    fill: false,\n    length: 12,\n    start: Object.assign({}, arrowHeadsDefaults),\n    width: 6\n  },\n  borderDash: [],\n  borderDashOffset: 0,\n  borderShadowColor: 'transparent',\n  borderWidth: 2,\n  curve: false,\n  controlPoint: {\n    y: '-50%'\n  },\n  display: true,\n  endValue: undefined,\n  init: undefined,\n  label: {\n    backgroundColor: 'rgba(0,0,0,0.8)',\n    backgroundShadowColor: 'transparent',\n    borderCapStyle: 'butt',\n    borderColor: 'black',\n    borderDash: [],\n    borderDashOffset: 0,\n    borderJoinStyle: 'miter',\n    borderRadius: 6,\n    borderShadowColor: 'transparent',\n    borderWidth: 0,\n    callout: Object.assign({}, LabelAnnotation.defaults.callout),\n    color: '#fff',\n    content: null,\n    display: false,\n    drawTime: undefined,\n    font: {\n      family: undefined,\n      lineHeight: undefined,\n      size: undefined,\n      style: undefined,\n      weight: 'bold'\n    },\n    height: undefined,\n    opacity: undefined,\n    padding: 6,\n    position: 'center',\n    rotation: 0,\n    shadowBlur: 0,\n    shadowOffsetX: 0,\n    shadowOffsetY: 0,\n    textAlign: 'center',\n    textStrokeColor: undefined,\n    textStrokeWidth: 0,\n    width: undefined,\n    xAdjust: 0,\n    yAdjust: 0,\n    z: undefined\n  },\n  scaleID: undefined,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  value: undefined,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  z: 0\n};\n\nLineAnnotation.descriptors = {\n  arrowHeads: {\n    start: {\n      _fallback: true\n    },\n    end: {\n      _fallback: true\n    },\n    _fallback: true\n  }\n};\n\nLineAnnotation.defaultRoutes = {\n  borderColor: 'color'\n};\n\nfunction inAxisRange(element, {mouseX, mouseY}, axis, {hBorderWidth, useFinalPosition}) {\n  const limit = rangeLimit(mouseX, mouseY, element.getProps(['x', 'y', 'x2', 'y2'], useFinalPosition), axis);\n  return (limit.value >= limit.start - hBorderWidth && limit.value <= limit.end + hBorderWidth) || isOnLabel(element, {mouseX, mouseY}, useFinalPosition, axis);\n}\n\nfunction isLineInArea({x, y, x2, y2}, {top, right, bottom, left}) {\n  return !(\n    (x < left && x2 < left) ||\n    (x > right && x2 > right) ||\n    (y < top && y2 < top) ||\n    (y > bottom && y2 > bottom)\n  );\n}\n\nfunction limitPointToArea({x, y}, p2, {top, right, bottom, left}) {\n  if (x < left) {\n    y = interpolateY(left, {x, y}, p2);\n    x = left;\n  }\n  if (x > right) {\n    y = interpolateY(right, {x, y}, p2);\n    x = right;\n  }\n  if (y < top) {\n    x = interpolateX(top, {x, y}, p2);\n    y = top;\n  }\n  if (y > bottom) {\n    x = interpolateX(bottom, {x, y}, p2);\n    y = bottom;\n  }\n  return {x, y};\n}\n\nfunction limitLineToArea(p1, p2, area) {\n  const {x, y} = limitPointToArea(p1, p2, area);\n  const {x: x2, y: y2} = limitPointToArea(p2, p1, area);\n  return {x, y, x2, y2, width: Math.abs(x2 - x), height: Math.abs(y2 - y)};\n}\n\nfunction intersects(element, {mouseX, mouseY}, epsilon = EPSILON, useFinalPosition) {\n  // Adapted from https://stackoverflow.com/a/6853926/25507\n  const {x: x1, y: y1, x2, y2} = element.getProps(['x', 'y', 'x2', 'y2'], useFinalPosition);\n  const dx = x2 - x1;\n  const dy = y2 - y1;\n  const lenSq = sqr(dx) + sqr(dy);\n  const t = lenSq === 0 ? -1 : ((mouseX - x1) * dx + (mouseY - y1) * dy) / lenSq;\n  let xx, yy;\n  if (t < 0) {\n    xx = x1;\n    yy = y1;\n  } else if (t > 1) {\n    xx = x2;\n    yy = y2;\n  } else {\n    xx = x1 + t * dx;\n    yy = y1 + t * dy;\n  }\n  return (sqr(mouseX - xx) + sqr(mouseY - yy)) <= epsilon;\n}\n\nfunction isOnLabel(element, {mouseX, mouseY}, useFinalPosition, axis) {\n  const label = element.label;\n  return label.options.display && label.inRange(mouseX, mouseY, axis, useFinalPosition);\n}\n\nfunction resolveLabelElementProperties(chart, properties, options) {\n  const borderWidth = options.borderWidth;\n  const padding = toPadding(options.padding);\n  const textSize = measureLabelSize(chart.ctx, options);\n  const width = textSize.width + padding.width + borderWidth;\n  const height = textSize.height + padding.height + borderWidth;\n  return calculateLabelPosition(properties, options, {width, height, padding}, chart.chartArea);\n}\n\nfunction calculateAutoRotation(properties) {\n  const {x, y, x2, y2} = properties;\n  const rotation = Math.atan2(y2 - y, x2 - x);\n  // Flip the rotation if it goes > PI/2 or < -PI/2, so label stays upright\n  return rotation > PI / 2 ? rotation - PI : rotation < PI / -2 ? rotation + PI : rotation;\n}\n\nfunction calculateLabelPosition(properties, label, sizes, chartArea) {\n  const {width, height, padding} = sizes;\n  const {xAdjust, yAdjust} = label;\n  const p1 = {x: properties.x, y: properties.y};\n  const p2 = {x: properties.x2, y: properties.y2};\n  const rotation = label.rotation === 'auto' ? calculateAutoRotation(properties) : toRadians(label.rotation);\n  const size = rotatedSize(width, height, rotation);\n  const t = calculateT(properties, label, {labelSize: size, padding}, chartArea);\n  const pt = properties.cp ? pointInCurve(p1, properties.cp, p2, t) : pointInLine(p1, p2, t);\n  const xCoordinateSizes = {size: size.w, min: chartArea.left, max: chartArea.right, padding: padding.left};\n  const yCoordinateSizes = {size: size.h, min: chartArea.top, max: chartArea.bottom, padding: padding.top};\n  const centerX = adjustLabelCoordinate(pt.x, xCoordinateSizes) + xAdjust;\n  const centerY = adjustLabelCoordinate(pt.y, yCoordinateSizes) + yAdjust;\n  return {\n    x: centerX - (width / 2),\n    y: centerY - (height / 2),\n    x2: centerX + (width / 2),\n    y2: centerY + (height / 2),\n    centerX,\n    centerY,\n    pointX: pt.x,\n    pointY: pt.y,\n    width,\n    height,\n    rotation: toDegrees(rotation)\n  };\n}\n\nfunction rotatedSize(width, height, rotation) {\n  const cos = Math.cos(rotation);\n  const sin = Math.sin(rotation);\n  return {\n    w: Math.abs(width * cos) + Math.abs(height * sin),\n    h: Math.abs(width * sin) + Math.abs(height * cos)\n  };\n}\n\nfunction calculateT(properties, label, sizes, chartArea) {\n  let t;\n  const space = spaceAround(properties, chartArea);\n  if (label.position === 'start') {\n    t = calculateTAdjust({w: properties.x2 - properties.x, h: properties.y2 - properties.y}, sizes, label, space);\n  } else if (label.position === 'end') {\n    t = 1 - calculateTAdjust({w: properties.x - properties.x2, h: properties.y - properties.y2}, sizes, label, space);\n  } else {\n    t = getRelativePosition(1, label.position);\n  }\n  return t;\n}\n\nfunction calculateTAdjust(lineSize, sizes, label, space) {\n  const {labelSize, padding} = sizes;\n  const lineW = lineSize.w * space.dx;\n  const lineH = lineSize.h * space.dy;\n  const x = (lineW > 0) && ((labelSize.w / 2 + padding.left - space.x) / lineW);\n  const y = (lineH > 0) && ((labelSize.h / 2 + padding.top - space.y) / lineH);\n  return clamp(Math.max(x, y), 0, 0.25);\n}\n\nfunction spaceAround(properties, chartArea) {\n  const {x, x2, y, y2} = properties;\n  const t = Math.min(y, y2) - chartArea.top;\n  const l = Math.min(x, x2) - chartArea.left;\n  const b = chartArea.bottom - Math.max(y, y2);\n  const r = chartArea.right - Math.max(x, x2);\n  return {\n    x: Math.min(l, r),\n    y: Math.min(t, b),\n    dx: l <= r ? 1 : -1,\n    dy: t <= b ? 1 : -1\n  };\n}\n\nfunction adjustLabelCoordinate(coordinate, labelSizes) {\n  const {size, min, max, padding} = labelSizes;\n  const halfSize = size / 2;\n  if (size > max - min) {\n    // if it does not fit, display as much as possible\n    return (max + min) / 2;\n  }\n  if (min >= (coordinate - padding - halfSize)) {\n    coordinate = min + padding + halfSize;\n  }\n  if (max <= (coordinate + padding + halfSize)) {\n    coordinate = max - padding - halfSize;\n  }\n  return coordinate;\n}\n\nfunction getArrowHeads(line) {\n  const options = line.options;\n  const arrowStartOpts = options.arrowHeads && options.arrowHeads.start;\n  const arrowEndOpts = options.arrowHeads && options.arrowHeads.end;\n  return {\n    startOpts: arrowStartOpts,\n    endOpts: arrowEndOpts,\n    startAdjust: getLineAdjust(line, arrowStartOpts),\n    endAdjust: getLineAdjust(line, arrowEndOpts)\n  };\n}\n\nfunction getLineAdjust(line, arrowOpts) {\n  if (!arrowOpts || !arrowOpts.display) {\n    return 0;\n  }\n  const {length, width} = arrowOpts;\n  const adjust = line.options.borderWidth / 2;\n  const p1 = {x: length, y: width + adjust};\n  const p2 = {x: 0, y: adjust};\n  return Math.abs(interpolateX(0, p1, p2));\n}\n\nfunction drawArrowHead(ctx, offset, adjust, arrowOpts) {\n  if (!arrowOpts || !arrowOpts.display) {\n    return;\n  }\n  const {length, width, fill, backgroundColor, borderColor} = arrowOpts;\n  const arrowOffsetX = Math.abs(offset - length) + adjust;\n  ctx.beginPath();\n  setShadowStyle(ctx, arrowOpts);\n  setBorderStyle(ctx, arrowOpts);\n  ctx.moveTo(arrowOffsetX, -width);\n  ctx.lineTo(offset + adjust, 0);\n  ctx.lineTo(arrowOffsetX, width);\n  if (fill === true) {\n    ctx.fillStyle = backgroundColor || borderColor;\n    ctx.closePath();\n    ctx.fill();\n    ctx.shadowColor = 'transparent';\n  } else {\n    ctx.shadowColor = arrowOpts.borderShadowColor;\n  }\n  ctx.stroke();\n}\n\nfunction getControlPoint(properties, options, distance) {\n  const {x, y, x2, y2, centerX, centerY} = properties;\n  const angle = Math.atan2(y2 - y, x2 - x);\n  const cp = toPosition(options.controlPoint, 0);\n  const point = {\n    x: centerX + getSize(distance, cp.x, false),\n    y: centerY + getSize(distance, cp.y, false)\n  };\n  return rotated(point, {x: centerX, y: centerY}, angle);\n}\n\nfunction drawArrowHeadOnCurve(ctx, {x, y}, {angle, adjust}, arrowOpts) {\n  if (!arrowOpts || !arrowOpts.display) {\n    return;\n  }\n  ctx.save();\n  ctx.translate(x, y);\n  ctx.rotate(angle);\n  drawArrowHead(ctx, 0, -adjust, arrowOpts);\n  ctx.restore();\n}\n\nfunction drawCurve(ctx, element, cp, length) {\n  const {x, y, x2, y2, options} = element;\n  const {startOpts, endOpts, startAdjust, endAdjust} = getArrowHeads(element);\n  const p1 = {x, y};\n  const p2 = {x: x2, y: y2};\n  const startAngle = angleInCurve(p1, cp, p2, 0);\n  const endAngle = angleInCurve(p1, cp, p2, 1) - PI;\n  const ps = pointInCurve(p1, cp, p2, startAdjust / length);\n  const pe = pointInCurve(p1, cp, p2, 1 - endAdjust / length);\n\n  const path = new Path2D();\n  ctx.beginPath();\n  path.moveTo(ps.x, ps.y);\n  path.quadraticCurveTo(cp.x, cp.y, pe.x, pe.y);\n  ctx.shadowColor = options.borderShadowColor;\n  ctx.stroke(path);\n  element.path = path;\n  element.ctx = ctx;\n  drawArrowHeadOnCurve(ctx, ps, {angle: startAngle, adjust: startAdjust}, startOpts);\n  drawArrowHeadOnCurve(ctx, pe, {angle: endAngle, adjust: endAdjust}, endOpts);\n}\n\nclass EllipseAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    const rotation = this.options.rotation;\n    const borderWidth = this.options.borderWidth;\n    if (axis !== 'x' && axis !== 'y') {\n      return pointInEllipse({x: mouseX, y: mouseY}, this.getProps(['width', 'height', 'centerX', 'centerY'], useFinalPosition), rotation, borderWidth);\n    }\n    const {x, y, x2, y2} = this.getProps(['x', 'y', 'x2', 'y2'], useFinalPosition);\n    const hBorderWidth = borderWidth / 2;\n    const limit = axis === 'y' ? {start: y, end: y2} : {start: x, end: x2};\n    const rotatedPoint = rotated({x: mouseX, y: mouseY}, this.getCenterPoint(useFinalPosition), toRadians(-rotation));\n    return rotatedPoint[axis] >= limit.start - hBorderWidth - EPSILON && rotatedPoint[axis] <= limit.end + hBorderWidth + EPSILON;\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    const {width, height, centerX, centerY, options} = this;\n    ctx.save();\n    translate(ctx, this.getCenterPoint(), options.rotation);\n    setShadowStyle(ctx, this.options);\n    ctx.beginPath();\n    ctx.fillStyle = options.backgroundColor;\n    const stroke = setBorderStyle(ctx, options);\n    ctx.ellipse(centerX, centerY, height / 2, width / 2, PI / 2, 0, 2 * PI);\n    ctx.fill();\n    if (stroke) {\n      ctx.shadowColor = options.borderShadowColor;\n      ctx.stroke();\n    }\n    ctx.restore();\n  }\n\n  get label() {\n    return this.elements && this.elements[0];\n  }\n\n  resolveElementProperties(chart, options) {\n    return resolveBoxAndLabelProperties(chart, options);\n  }\n\n}\n\nEllipseAnnotation.id = 'ellipseAnnotation';\n\nEllipseAnnotation.defaults = {\n  adjustScaleRange: true,\n  backgroundShadowColor: 'transparent',\n  borderDash: [],\n  borderDashOffset: 0,\n  borderShadowColor: 'transparent',\n  borderWidth: 1,\n  display: true,\n  init: undefined,\n  label: Object.assign({}, BoxAnnotation.defaults.label),\n  rotation: 0,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  z: 0\n};\n\nEllipseAnnotation.defaultRoutes = {\n  borderColor: 'color',\n  backgroundColor: 'color'\n};\n\nEllipseAnnotation.descriptors = {\n  label: {\n    _fallback: true\n  }\n};\n\nfunction pointInEllipse(p, ellipse, rotation, borderWidth) {\n  const {width, height, centerX, centerY} = ellipse;\n  const xRadius = width / 2;\n  const yRadius = height / 2;\n\n  if (xRadius <= 0 || yRadius <= 0) {\n    return false;\n  }\n  // https://stackoverflow.com/questions/7946187/point-and-ellipse-rotated-position-test-algorithm\n  const angle = toRadians(rotation || 0);\n  const hBorderWidth = borderWidth / 2 || 0;\n  const cosAngle = Math.cos(angle);\n  const sinAngle = Math.sin(angle);\n  const a = Math.pow(cosAngle * (p.x - centerX) + sinAngle * (p.y - centerY), 2);\n  const b = Math.pow(sinAngle * (p.x - centerX) - cosAngle * (p.y - centerY), 2);\n  return (a / Math.pow(xRadius + hBorderWidth, 2)) + (b / Math.pow(yRadius + hBorderWidth, 2)) <= 1.0001;\n}\n\nclass PointAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    const {x, y, x2, y2, width} = this.getProps(['x', 'y', 'x2', 'y2', 'width'], useFinalPosition);\n    const borderWidth = this.options.borderWidth;\n    if (axis !== 'x' && axis !== 'y') {\n      return inPointRange({x: mouseX, y: mouseY}, this.getCenterPoint(useFinalPosition), width / 2, borderWidth);\n    }\n    const hBorderWidth = borderWidth / 2;\n    const limit = axis === 'y' ? {start: y, end: y2, value: mouseY} : {start: x, end: x2, value: mouseX};\n    return limit.value >= limit.start - hBorderWidth && limit.value <= limit.end + hBorderWidth;\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    const options = this.options;\n    const borderWidth = options.borderWidth;\n    if (options.radius < 0.1) {\n      return;\n    }\n    ctx.save();\n    ctx.fillStyle = options.backgroundColor;\n    setShadowStyle(ctx, options);\n    const stroke = setBorderStyle(ctx, options);\n    drawPoint(ctx, this, this.centerX, this.centerY);\n    if (stroke && !isImageOrCanvas(options.pointStyle)) {\n      ctx.shadowColor = options.borderShadowColor;\n      ctx.stroke();\n    }\n    ctx.restore();\n    options.borderWidth = borderWidth;\n  }\n\n  resolveElementProperties(chart, options) {\n    const properties = resolvePointProperties(chart, options);\n    properties.initProperties = initAnimationProperties(chart, properties, options);\n    return properties;\n  }\n}\n\nPointAnnotation.id = 'pointAnnotation';\n\nPointAnnotation.defaults = {\n  adjustScaleRange: true,\n  backgroundShadowColor: 'transparent',\n  borderDash: [],\n  borderDashOffset: 0,\n  borderShadowColor: 'transparent',\n  borderWidth: 1,\n  display: true,\n  init: undefined,\n  pointStyle: 'circle',\n  radius: 10,\n  rotation: 0,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  xAdjust: 0,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  xValue: undefined,\n  yAdjust: 0,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  yValue: undefined,\n  z: 0\n};\n\nPointAnnotation.defaultRoutes = {\n  borderColor: 'color',\n  backgroundColor: 'color'\n};\n\nclass PolygonAnnotation extends Element {\n\n  inRange(mouseX, mouseY, axis, useFinalPosition) {\n    if (axis !== 'x' && axis !== 'y') {\n      return this.options.radius >= 0.1 && this.elements.length > 1 && pointIsInPolygon(this.elements, mouseX, mouseY, useFinalPosition);\n    }\n    const rotatedPoint = rotated({x: mouseX, y: mouseY}, this.getCenterPoint(useFinalPosition), toRadians(-this.options.rotation));\n    const axisPoints = this.elements.map((point) => axis === 'y' ? point.bY : point.bX);\n    const start = Math.min(...axisPoints);\n    const end = Math.max(...axisPoints);\n    return rotatedPoint[axis] >= start && rotatedPoint[axis] <= end;\n  }\n\n  getCenterPoint(useFinalPosition) {\n    return getElementCenterPoint(this, useFinalPosition);\n  }\n\n  draw(ctx) {\n    const {elements, options} = this;\n    ctx.save();\n    ctx.beginPath();\n    ctx.fillStyle = options.backgroundColor;\n    setShadowStyle(ctx, options);\n    const stroke = setBorderStyle(ctx, options);\n    let first = true;\n    for (const el of elements) {\n      if (first) {\n        ctx.moveTo(el.x, el.y);\n        first = false;\n      } else {\n        ctx.lineTo(el.x, el.y);\n      }\n    }\n    ctx.closePath();\n    ctx.fill();\n    // If no border, don't draw it\n    if (stroke) {\n      ctx.shadowColor = options.borderShadowColor;\n      ctx.stroke();\n    }\n    ctx.restore();\n  }\n\n  resolveElementProperties(chart, options) {\n    const properties = resolvePointProperties(chart, options);\n    const {sides, rotation} = options;\n    const elements = [];\n    const angle = (2 * PI) / sides;\n    let rad = rotation * RAD_PER_DEG;\n    for (let i = 0; i < sides; i++, rad += angle) {\n      const elProps = buildPointElement(properties, options, rad);\n      elProps.initProperties = initAnimationProperties(chart, properties, options);\n      elements.push(elProps);\n    }\n    properties.elements = elements;\n    return properties;\n  }\n}\n\nPolygonAnnotation.id = 'polygonAnnotation';\n\nPolygonAnnotation.defaults = {\n  adjustScaleRange: true,\n  backgroundShadowColor: 'transparent',\n  borderCapStyle: 'butt',\n  borderDash: [],\n  borderDashOffset: 0,\n  borderJoinStyle: 'miter',\n  borderShadowColor: 'transparent',\n  borderWidth: 1,\n  display: true,\n  init: undefined,\n  point: {\n    radius: 0\n  },\n  radius: 10,\n  rotation: 0,\n  shadowBlur: 0,\n  shadowOffsetX: 0,\n  shadowOffsetY: 0,\n  sides: 3,\n  xAdjust: 0,\n  xMax: undefined,\n  xMin: undefined,\n  xScaleID: undefined,\n  xValue: undefined,\n  yAdjust: 0,\n  yMax: undefined,\n  yMin: undefined,\n  yScaleID: undefined,\n  yValue: undefined,\n  z: 0\n};\n\nPolygonAnnotation.defaultRoutes = {\n  borderColor: 'color',\n  backgroundColor: 'color'\n};\n\nfunction buildPointElement({centerX, centerY}, {radius, borderWidth}, rad) {\n  const halfBorder = borderWidth / 2;\n  const sin = Math.sin(rad);\n  const cos = Math.cos(rad);\n  const point = {x: centerX + sin * radius, y: centerY - cos * radius};\n  return {\n    type: 'point',\n    optionScope: 'point',\n    properties: {\n      x: point.x,\n      y: point.y,\n      centerX: point.x,\n      centerY: point.y,\n      bX: centerX + sin * (radius + halfBorder),\n      bY: centerY - cos * (radius + halfBorder)\n    }\n  };\n}\n\nfunction pointIsInPolygon(points, x, y, useFinalPosition) {\n  let isInside = false;\n  let A = points[points.length - 1].getProps(['bX', 'bY'], useFinalPosition);\n  for (const point of points) {\n    const B = point.getProps(['bX', 'bY'], useFinalPosition);\n    if ((B.bY > y) !== (A.bY > y) && x < (A.bX - B.bX) * (y - B.bY) / (A.bY - B.bY) + B.bX) {\n      isInside = !isInside;\n    }\n    A = B;\n  }\n  return isInside;\n}\n\nconst annotationTypes = {\n  box: BoxAnnotation,\n  ellipse: EllipseAnnotation,\n  label: LabelAnnotation,\n  line: LineAnnotation,\n  point: PointAnnotation,\n  polygon: PolygonAnnotation\n};\n\n/**\n * Register fallback for annotation elements\n * For example lineAnnotation options would be looked through:\n * - the annotation object (options.plugins.annotation.annotations[id])\n * - element options (options.elements.lineAnnotation)\n * - element defaults (defaults.elements.lineAnnotation)\n * - annotation plugin defaults (defaults.plugins.annotation, this is what we are registering here)\n */\nObject.keys(annotationTypes).forEach(key => {\n  defaults.describe(`elements.${annotationTypes[key].id}`, {\n    _fallback: 'plugins.annotation.common'\n  });\n});\n\nconst directUpdater = {\n  update: Object.assign\n};\n\nconst hooks$1 = eventHooks.concat(elementHooks);\nconst resolve = (value, optDefs) => isObject(optDefs) ? resolveObj(value, optDefs) : value;\n\n\n/**\n * @typedef { import(\"chart.js\").Chart } Chart\n * @typedef { import(\"chart.js\").UpdateMode } UpdateMode\n * @typedef { import('../../types/options').AnnotationPluginOptions } AnnotationPluginOptions\n */\n\n/**\n * @param {string} prop\n * @returns {boolean}\n */\nconst isIndexable = (prop) => prop === 'color' || prop === 'font';\n\n/**\n * Resolve the annotation type, checking if is supported.\n * @param {string} [type=line] - annotation type\n * @returns {string} resolved annotation type\n */\nfunction resolveType(type = 'line') {\n  if (annotationTypes[type]) {\n    return type;\n  }\n  console.warn(`Unknown annotation type: '${type}', defaulting to 'line'`);\n  return 'line';\n}\n\n/**\n * @param {Chart} chart\n * @param {Object} state\n * @param {AnnotationPluginOptions} options\n * @param {UpdateMode} mode\n */\nfunction updateElements(chart, state, options, mode) {\n  const animations = resolveAnimations(chart, options.animations, mode);\n\n  const annotations = state.annotations;\n  const elements = resyncElements(state.elements, annotations);\n\n  for (let i = 0; i < annotations.length; i++) {\n    const annotationOptions = annotations[i];\n    const element = getOrCreateElement(elements, i, annotationOptions.type);\n    const resolver = annotationOptions.setContext(getContext(chart, element, annotationOptions));\n    const properties = element.resolveElementProperties(chart, resolver);\n\n    properties.skip = toSkip(properties);\n\n    if ('elements' in properties) {\n      updateSubElements(element, properties.elements, resolver, animations);\n      // Remove the sub-element definitions from properties, so the actual elements\n      // are not overwritten by their definitions\n      delete properties.elements;\n    }\n\n    if (!defined(element.x)) {\n      // If the element is newly created, assing the properties directly - to\n      // make them readily awailable to any scriptable options. If we do not do this,\n      // the properties retruned by `resolveElementProperties` are available only\n      // after options resolution.\n      Object.assign(element, properties);\n    }\n\n    Object.assign(element, properties.initProperties);\n    properties.options = resolveAnnotationOptions(resolver);\n\n    animations.update(element, properties);\n  }\n}\n\nfunction toSkip(properties) {\n  return isNaN(properties.x) || isNaN(properties.y);\n}\n\nfunction resolveAnimations(chart, animOpts, mode) {\n  if (mode === 'reset' || mode === 'none' || mode === 'resize') {\n    return directUpdater;\n  }\n  return new Animations(chart, animOpts);\n}\n\nfunction updateSubElements(mainElement, elements, resolver, animations) {\n  const subElements = mainElement.elements || (mainElement.elements = []);\n  subElements.length = elements.length;\n  for (let i = 0; i < elements.length; i++) {\n    const definition = elements[i];\n    const properties = definition.properties;\n    const subElement = getOrCreateElement(subElements, i, definition.type, definition.initProperties);\n    const subResolver = resolver[definition.optionScope].override(definition);\n    properties.options = resolveAnnotationOptions(subResolver);\n    animations.update(subElement, properties);\n  }\n}\n\nfunction getOrCreateElement(elements, index, type, initProperties) {\n  const elementClass = annotationTypes[resolveType(type)];\n  let element = elements[index];\n  if (!element || !(element instanceof elementClass)) {\n    element = elements[index] = new elementClass();\n    Object.assign(element, initProperties);\n  }\n  return element;\n}\n\nfunction resolveAnnotationOptions(resolver) {\n  const elementClass = annotationTypes[resolveType(resolver.type)];\n  const result = {};\n  result.id = resolver.id;\n  result.type = resolver.type;\n  result.drawTime = resolver.drawTime;\n  Object.assign(result,\n    resolveObj(resolver, elementClass.defaults),\n    resolveObj(resolver, elementClass.defaultRoutes));\n  for (const hook of hooks$1) {\n    result[hook] = resolver[hook];\n  }\n  return result;\n}\n\nfunction resolveObj(resolver, defs) {\n  const result = {};\n  for (const prop of Object.keys(defs)) {\n    const optDefs = defs[prop];\n    const value = resolver[prop];\n    if (isIndexable(prop) && isArray(value)) {\n      result[prop] = value.map((item) => resolve(item, optDefs));\n    } else {\n      result[prop] = resolve(value, optDefs);\n    }\n  }\n  return result;\n}\n\nfunction getContext(chart, element, annotation) {\n  return element.$context || (element.$context = Object.assign(Object.create(chart.getContext()), {\n    element,\n    id: annotation.id,\n    type: 'annotation'\n  }));\n}\n\nfunction resyncElements(elements, annotations) {\n  const count = annotations.length;\n  const start = elements.length;\n\n  if (start < count) {\n    const add = count - start;\n    elements.splice(start, 0, ...new Array(add));\n  } else if (start > count) {\n    elements.splice(count, start - count);\n  }\n  return elements;\n}\n\nvar version = \"3.0.1\";\n\nconst chartStates = new Map();\nconst hooks = eventHooks.concat(elementHooks);\n\nvar annotation = {\n  id: 'annotation',\n\n  version,\n\n  beforeRegister() {\n    requireVersion('chart.js', '4.0', Chart.version);\n  },\n\n  afterRegister() {\n    Chart.register(annotationTypes);\n  },\n\n  afterUnregister() {\n    Chart.unregister(annotationTypes);\n  },\n\n  beforeInit(chart) {\n    chartStates.set(chart, {\n      annotations: [],\n      elements: [],\n      visibleElements: [],\n      listeners: {},\n      listened: false,\n      moveListened: false,\n      hooks: {},\n      hooked: false,\n      hovered: []\n    });\n  },\n\n  beforeUpdate(chart, args, options) {\n    const state = chartStates.get(chart);\n    const annotations = state.annotations = [];\n\n    let annotationOptions = options.annotations;\n    if (isObject(annotationOptions)) {\n      Object.keys(annotationOptions).forEach(key => {\n        const value = annotationOptions[key];\n        if (isObject(value)) {\n          value.id = key;\n          annotations.push(value);\n        }\n      });\n    } else if (isArray(annotationOptions)) {\n      annotations.push(...annotationOptions);\n    }\n    verifyScaleOptions(annotations, chart.scales);\n  },\n\n  afterDataLimits(chart, args) {\n    const state = chartStates.get(chart);\n    adjustScaleRange(chart, args.scale, state.annotations.filter(a => a.display && a.adjustScaleRange));\n  },\n\n  afterUpdate(chart, args, options) {\n    const state = chartStates.get(chart);\n    updateListeners(chart, state, options);\n    updateElements(chart, state, options, args.mode);\n    state.visibleElements = state.elements.filter(el => !el.skip && el.options.display);\n    updateHooks(chart, state, options);\n  },\n\n  beforeDatasetsDraw(chart, _args, options) {\n    draw(chart, 'beforeDatasetsDraw', options.clip);\n  },\n\n  afterDatasetsDraw(chart, _args, options) {\n    draw(chart, 'afterDatasetsDraw', options.clip);\n  },\n\n  beforeDraw(chart, _args, options) {\n    draw(chart, 'beforeDraw', options.clip);\n  },\n\n  afterDraw(chart, _args, options) {\n    draw(chart, 'afterDraw', options.clip);\n  },\n\n  beforeEvent(chart, args, options) {\n    const state = chartStates.get(chart);\n    if (handleEvent(state, args.event, options)) {\n      args.changed = true;\n    }\n  },\n\n  afterDestroy(chart) {\n    chartStates.delete(chart);\n  },\n\n  _getState(chart) {\n    return chartStates.get(chart);\n  },\n\n  defaults: {\n    animations: {\n      numbers: {\n        properties: ['x', 'y', 'x2', 'y2', 'width', 'height', 'centerX', 'centerY', 'pointX', 'pointY', 'radius'],\n        type: 'number'\n      },\n    },\n    clip: true,\n    interaction: {\n      mode: undefined,\n      axis: undefined,\n      intersect: undefined\n    },\n    common: {\n      drawTime: 'afterDatasetsDraw',\n      init: false,\n      label: {\n      }\n    }\n  },\n\n  descriptors: {\n    _indexable: false,\n    _scriptable: (prop) => !hooks.includes(prop) && prop !== 'init',\n    annotations: {\n      _allKeys: false,\n      _fallback: (prop, opts) => `elements.${annotationTypes[resolveType(opts.type)].id}`\n    },\n    interaction: {\n      _fallback: true\n    },\n    common: {\n      label: {\n        _indexable: isIndexable,\n        _fallback: true\n      },\n      _indexable: isIndexable\n    }\n  },\n\n  additionalOptionScopes: ['']\n};\n\nfunction draw(chart, caller, clip) {\n  const {ctx, chartArea} = chart;\n  const state = chartStates.get(chart);\n\n  if (clip) {\n    clipArea(ctx, chartArea);\n  }\n\n  const drawableElements = getDrawableElements(state.visibleElements, caller).sort((a, b) => a.element.options.z - b.element.options.z);\n  for (const item of drawableElements) {\n    drawElement(ctx, chartArea, state, item);\n  }\n\n  if (clip) {\n    unclipArea(ctx);\n  }\n}\n\nfunction getDrawableElements(elements, caller) {\n  const drawableElements = [];\n  for (const el of elements) {\n    if (el.options.drawTime === caller) {\n      drawableElements.push({element: el, main: true});\n    }\n    if (el.elements && el.elements.length) {\n      for (const sub of el.elements) {\n        if (sub.options.display && sub.options.drawTime === caller) {\n          drawableElements.push({element: sub});\n        }\n      }\n    }\n  }\n  return drawableElements;\n}\n\nfunction drawElement(ctx, chartArea, state, item) {\n  const el = item.element;\n  if (item.main) {\n    invokeHook(state, el, 'beforeDraw');\n    el.draw(ctx, chartArea);\n    invokeHook(state, el, 'afterDraw');\n  } else {\n    el.draw(ctx, chartArea);\n  }\n}\n\nexport { annotation as default };\n","!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){\"use strict\";var t=1e3,e=6e4,n=36e5,r=\"millisecond\",i=\"second\",s=\"minute\",u=\"hour\",a=\"day\",o=\"week\",c=\"month\",f=\"quarter\",h=\"year\",d=\"date\",l=\"Invalid Date\",$=/^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[Tt\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/,y=/\\[([^\\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:\"en\",weekdays:\"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday\".split(\"_\"),months:\"January_February_March_April_May_June_July_August_September_October_November_December\".split(\"_\"),ordinal:function(t){var e=[\"th\",\"st\",\"nd\",\"rd\"],n=t%100;return\"[\"+t+(e[(n-20)%10]||e[n]||e[0])+\"]\"}},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:\"\"+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?\"+\":\"-\")+m(r,2,\"0\")+\":\"+m(i,2,\"0\")},m:function t(e,n){if(e.date()<n.date())return-t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return+(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||\"\").toLowerCase().replace(/s$/,\"\")},u:function(t){return void 0===t}},g=\"en\",D={};D[g]=M;var p=\"$isDayjsObject\",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if(\"string\"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split(\"-\");if(!i&&u.length>1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n=\"object\"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if(\"string\"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||\"0\").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return b},m.isValid=function(){return!(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate(\"s\"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v=\"set\"+(this.$u?\"UTC\":\"\");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+\"Hours\",0);case u:return $(v+\"Minutes\",1);case s:return $(v+\"Seconds\",2);case i:return $(v+\"Milliseconds\",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f=\"set\"+(this.$u?\"UTC\":\"\"),l=(n={},n[a]=f+\"Date\",n[d]=f+\"Date\",n[c]=f+\"Month\",n[h]=f+\"FullYear\",n[u]=f+\"Hours\",n[s]=f+\"Minutes\",n[i]=f+\"Seconds\",n[r]=f+\"Milliseconds\",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||\"YYYY-MM-DDTHH:mm:ssZ\",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,\"0\")},$=f||function(t,e,n){var r=t<12?\"AM\":\"PM\";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case\"YY\":return String(e.$y).slice(-2);case\"YYYY\":return b.s(e.$y,4,\"0\");case\"M\":return a+1;case\"MM\":return b.s(a+1,2,\"0\");case\"MMM\":return h(n.monthsShort,a,c,3);case\"MMMM\":return h(c,a);case\"D\":return e.$D;case\"DD\":return b.s(e.$D,2,\"0\");case\"d\":return String(e.$W);case\"dd\":return h(n.weekdaysMin,e.$W,o,2);case\"ddd\":return h(n.weekdaysShort,e.$W,o,3);case\"dddd\":return o[e.$W];case\"H\":return String(s);case\"HH\":return b.s(s,2,\"0\");case\"h\":return d(1);case\"hh\":return d(2);case\"a\":return $(s,u,!0);case\"A\":return $(s,u,!1);case\"m\":return String(u);case\"mm\":return b.s(u,2,\"0\");case\"s\":return String(e.$s);case\"ss\":return b.s(e.$s,2,\"0\");case\"SSS\":return b.s(e.$ms,3,\"0\");case\"Z\":return i}return null}(t)||i.replace(\":\",\"\")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[[\"$ms\",r],[\"$s\",i],[\"$m\",s],[\"$H\",u],[\"$W\",a],[\"$M\",c],[\"$y\",h],[\"$D\",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])}})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_customParseFormat=t()}(this,(function(){\"use strict\";var e={LTS:\"h:mm:ss A\",LT:\"h:mm A\",L:\"MM/DD/YYYY\",LL:\"MMMM D, YYYY\",LLL:\"MMMM D, YYYY h:mm A\",LLLL:\"dddd, MMMM D, YYYY h:mm A\"},t=/(\\[[^[]*\\])|([-_:/.,()\\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,n=/\\d\\d/,r=/\\d\\d?/,i=/\\d*[^-_:/,()\\s\\d]+/,o={},s=function(e){return(e=+e)+(e>68?1900:2e3)};var a=function(e){return function(t){this[e]=+t}},f=[/[+-]\\d\\d:?(\\d\\d)?|Z/,function(e){(this.zone||(this.zone={})).offset=function(e){if(!e)return 0;if(\"Z\"===e)return 0;var t=e.match(/([+-]|\\d\\d)/g),n=60*t[1]+(+t[2]||0);return 0===n?0:\"+\"===t[0]?-n:n}(e)}],h=function(e){var t=o[e];return t&&(t.indexOf?t:t.s.concat(t.f))},u=function(e,t){var n,r=o.meridiem;if(r){for(var i=1;i<=24;i+=1)if(e.indexOf(r(i,0,t))>-1){n=i>12;break}}else n=e===(t?\"pm\":\"PM\");return n},d={A:[i,function(e){this.afternoon=u(e,!1)}],a:[i,function(e){this.afternoon=u(e,!0)}],S:[/\\d/,function(e){this.milliseconds=100*+e}],SS:[n,function(e){this.milliseconds=10*+e}],SSS:[/\\d{3}/,function(e){this.milliseconds=+e}],s:[r,a(\"seconds\")],ss:[r,a(\"seconds\")],m:[r,a(\"minutes\")],mm:[r,a(\"minutes\")],H:[r,a(\"hours\")],h:[r,a(\"hours\")],HH:[r,a(\"hours\")],hh:[r,a(\"hours\")],D:[r,a(\"day\")],DD:[n,a(\"day\")],Do:[i,function(e){var t=o.ordinal,n=e.match(/\\d+/);if(this.day=n[0],t)for(var r=1;r<=31;r+=1)t(r).replace(/\\[|\\]/g,\"\")===e&&(this.day=r)}],M:[r,a(\"month\")],MM:[n,a(\"month\")],MMM:[i,function(e){var t=h(\"months\"),n=(h(\"monthsShort\")||t.map((function(e){return e.slice(0,3)}))).indexOf(e)+1;if(n<1)throw new Error;this.month=n%12||n}],MMMM:[i,function(e){var t=h(\"months\").indexOf(e)+1;if(t<1)throw new Error;this.month=t%12||t}],Y:[/[+-]?\\d+/,a(\"year\")],YY:[n,function(e){this.year=s(e)}],YYYY:[/\\d{4}/,a(\"year\")],Z:f,ZZ:f};function c(n){var r,i;r=n,i=o&&o.formats;for(var s=(n=r.replace(/(\\[[^\\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var o=r&&r.toUpperCase();return n||i[r]||e[r]||i[o].replace(/(\\[[^\\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,n){return t||n.slice(1)}))}))).match(t),a=s.length,f=0;f<a;f+=1){var h=s[f],u=d[h],c=u&&u[0],l=u&&u[1];s[f]=l?{regex:c,parser:l}:h.replace(/^\\[|\\]$/g,\"\")}return function(e){for(var t={},n=0,r=0;n<a;n+=1){var i=s[n];if(\"string\"==typeof i)r+=i.length;else{var o=i.regex,f=i.parser,h=e.slice(r),u=o.exec(h)[0];f.call(t,u),e=e.replace(u,\"\")}}return function(e){var t=e.afternoon;if(void 0!==t){var n=e.hours;t?n<12&&(e.hours+=12):12===n&&(e.hours=0),delete e.afternoon}}(t),t}}return function(e,t,n){n.p.customParseFormat=!0,e&&e.parseTwoDigitYear&&(s=e.parseTwoDigitYear);var r=t.prototype,i=r.parse;r.parse=function(e){var t=e.date,r=e.utc,s=e.args;this.$u=r;var a=s[1];if(\"string\"==typeof a){var f=!0===s[2],h=!0===s[3],u=f||h,d=s[2];h&&(d=s[2]),o=this.$locale(),!f&&d&&(o=n.Ls[d]),this.$d=function(e,t,n){try{if([\"x\",\"X\"].indexOf(t)>-1)return new Date((\"X\"===t?1e3:1)*e);var r=c(t)(e),i=r.year,o=r.month,s=r.day,a=r.hours,f=r.minutes,h=r.seconds,u=r.milliseconds,d=r.zone,l=new Date,m=s||(i||o?1:l.getDate()),M=i||l.getFullYear(),Y=0;i&&!o||(Y=o>0?o-1:l.getMonth());var p=a||0,v=f||0,D=h||0,g=u||0;return d?new Date(Date.UTC(M,Y,m,p,v,D,g+60*d.offset*1e3)):n?new Date(Date.UTC(M,Y,m,p,v,D,g)):new Date(M,Y,m,p,v,D,g)}catch(e){return new Date(\"\")}}(t,a,r),this.init(),d&&!0!==d&&(this.$L=this.locale(d).$L),u&&t!=this.format(a)&&(this.$d=new Date(\"\")),o={}}else if(a instanceof Array)for(var l=a.length,m=1;m<=l;m+=1){s[1]=a[m-1];var M=n.apply(this,s);if(M.isValid()){this.$d=M.$d,this.$L=M.$L,this.init();break}m===l&&(this.$d=new Date(\"\"))}else i.call(this,e)}}}));","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_advancedFormat=t()}(this,(function(){\"use strict\";return function(e,t){var r=t.prototype,n=r.format;r.format=function(e){var t=this,r=this.$locale();if(!this.isValid())return n.bind(this)(e);var s=this.$utils(),a=(e||\"YYYY-MM-DDTHH:mm:ssZ\").replace(/\\[([^\\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,(function(e){switch(e){case\"Q\":return Math.ceil((t.$M+1)/3);case\"Do\":return r.ordinal(t.$D);case\"gggg\":return t.weekYear();case\"GGGG\":return t.isoWeekYear();case\"wo\":return r.ordinal(t.week(),\"W\");case\"w\":case\"ww\":return s.s(t.week(),\"w\"===e?1:2,\"0\");case\"W\":case\"WW\":return s.s(t.isoWeek(),\"W\"===e?1:2,\"0\");case\"k\":case\"kk\":return s.s(String(0===t.$H?24:t.$H),\"k\"===e?1:2,\"0\");case\"X\":return Math.floor(t.$d.getTime()/1e3);case\"x\":return t.$d.getTime();case\"z\":return\"[\"+t.offsetName()+\"]\";case\"zzz\":return\"[\"+t.offsetName(\"long\")+\"]\";default:return e}}));return n.bind(this)(a)}}}));","!function(t,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=n():\"function\"==typeof define&&define.amd?define(n):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs_plugin_quarterOfYear=n()}(this,(function(){\"use strict\";var t=\"month\",n=\"quarter\";return function(e,i){var r=i.prototype;r.quarter=function(t){return this.$utils().u(t)?Math.ceil((this.month()+1)/3):this.month(this.month()%3+3*(t-1))};var s=r.add;r.add=function(e,i){return e=Number(e),this.$utils().p(i)===n?this.add(3*e,t):s.bind(this)(e,i)};var u=r.startOf;r.startOf=function(e,i){var r=this.$utils(),s=!!r.u(i)||i;if(r.p(e)===n){var o=this.quarter()-1;return s?this.month(3*o).startOf(t).startOf(\"day\"):this.month(3*o+2).endOf(t).endOf(\"day\")}return u.bind(this)(e,i)}}}));","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_localizedFormat=t()}(this,(function(){\"use strict\";var e={LTS:\"h:mm:ss A\",LT:\"h:mm A\",L:\"MM/DD/YYYY\",LL:\"MMMM D, YYYY\",LLL:\"MMMM D, YYYY h:mm A\",LLLL:\"dddd, MMMM D, YYYY h:mm A\"};return function(t,o,n){var r=o.prototype,i=r.format;n.en.formats=e,r.format=function(t){void 0===t&&(t=\"YYYY-MM-DDTHH:mm:ssZ\");var o=this.$locale().formats,n=function(t,o){return t.replace(/(\\[[^\\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var i=r&&r.toUpperCase();return n||o[r]||e[r]||o[i].replace(/(\\[[^\\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,o){return t||o.slice(1)}))}))}(t,void 0===o?{}:o);return i.call(this,n)}}}));","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_isoWeek=t()}(this,(function(){\"use strict\";var e=\"day\";return function(t,i,s){var a=function(t){return t.add(4-t.isoWeekday(),e)},d=i.prototype;d.isoWeekYear=function(){return a(this).year()},d.isoWeek=function(t){if(!this.$utils().u(t))return this.add(7*(t-this.isoWeek()),e);var i,d,n,o,r=a(this),u=(i=this.isoWeekYear(),d=this.$u,n=(d?s.utc:s)().year(i).startOf(\"year\"),o=4-n.isoWeekday(),n.isoWeekday()>4&&(o+=7),n.add(o,e));return r.diff(u,\"week\")+1},d.isoWeekday=function(e){return this.$utils().u(e)?this.day()||7:this.day(this.day()%7?e:e-7)};var n=d.startOf;d.startOf=function(e,t){var i=this.$utils(),s=!!i.u(t)||t;return\"isoweek\"===i.p(e)?s?this.date(this.date()-(this.isoWeekday()-1)).startOf(\"day\"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf(\"day\"):n.bind(this)(e,t)}}}));","import { _adapters } from 'chart.js';\nimport dayjs from 'dayjs';\nimport CustomParseFormat from 'dayjs/plugin/customParseFormat.js';\nimport AdvancedFormat from 'dayjs/plugin/advancedFormat.js';\nimport QuarterOfYear from 'dayjs/plugin/quarterOfYear.js';\nimport LocalizedFormat from 'dayjs/plugin/localizedFormat.js';\nimport isoWeek from 'dayjs/plugin/isoWeek.js';\n\ndayjs.extend(AdvancedFormat);\ndayjs.extend(QuarterOfYear);\ndayjs.extend(LocalizedFormat);\ndayjs.extend(CustomParseFormat);\ndayjs.extend(isoWeek);\nvar FORMATS = {\n  datetime: 'MMM D, YYYY, h:mm:ss a',\n  millisecond: 'h:mm:ss.SSS a',\n  second: 'h:mm:ss a',\n  minute: 'h:mm a',\n  hour: 'hA',\n  day: 'MMM D',\n  week: 'll',\n  month: 'MMM YYYY',\n  quarter: '[Q]Q - YYYY',\n  year: 'YYYY'\n};\n_adapters._date.override({\n  //_id: 'dayjs', //DEBUG,\n  formats: function formats() {\n    return FORMATS;\n  },\n  parse: function parse(value, format) {\n    var valueType = typeof value;\n    if (value === null || valueType === 'undefined') {\n      return null;\n    }\n    if (valueType === 'string' && typeof format === 'string') {\n      return dayjs(value, format).isValid() ? dayjs(value, format).valueOf() : null;\n    } else if (!(value instanceof dayjs)) {\n      return dayjs(value).isValid() ? dayjs(value).valueOf() : null;\n    }\n    return null;\n  },\n  format: function format(time, _format) {\n    return dayjs(time).format(_format);\n  },\n  add: function add(time, amount, unit) {\n    return dayjs(time).add(amount, unit).valueOf();\n  },\n  diff: function diff(max, min, unit) {\n    return dayjs(max).diff(dayjs(min), unit);\n  },\n  startOf: function startOf(time, unit, weekday) {\n    if (unit === 'isoWeek') {\n      // Ensure that weekday has a valid format\n      //const formattedWeekday\n      var validatedWeekday = typeof weekday === 'number' && weekday > 0 && weekday < 7 ? weekday : 1;\n      return dayjs(time).isoWeekday(validatedWeekday).startOf('day').valueOf();\n    }\n    return dayjs(time).startOf(unit).valueOf();\n  },\n  endOf: function endOf(time, unit) {\n    return dayjs(time).endOf(unit).valueOf();\n  }\n});\n//# sourceMappingURL=chartjs-adapter-dayjs-4.esm.js.map\n","import angular from \"angular\";\r\nimport { Chart, registerables, ChartConfiguration, ChartType, ScatterDataPoint, BubbleDataPoint } from \"chart.js\";\r\nimport annotationPlugin from \"chartjs-plugin-annotation\";\r\nimport \"chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm\";\r\n/** Register chart registerables (ex. tooltip) */\r\nChart.register(...registerables, annotationPlugin);\r\n\r\n/**\r\n Controller rendering chart by provided config\r\n */\r\nexport class ChartController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$element\", \"$timeout\", \"$scope\"];\r\n\r\n  /** Configuration of chart */\r\n  public config: ChartConfiguration<ChartType, number[] | ScatterDataPoint[] | BubbleDataPoint[], unknown>;\r\n  private chart: Chart = undefined;\r\n  /** Custom height of chart */\r\n  public customHeight: string;\r\n  /** Custom width of chart */\r\n  public customWidth: string;\r\n  /** Custom class of chart */\r\n  public customClass: string;\r\n  constructor(\r\n    private $element: JQLite,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $scope: angular.IScope,\r\n  ) {}\r\n\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public init() {\r\n      this.customHeight = this.customHeight ?? \"\";\r\n      this.customWidth = this.customWidth ?? \"\";\r\n      this.customClass = this.customClass ?? \"\";\r\n      this.$timeout(() => {\r\n        this.createChart();\r\n      });\r\n      this.$scope.$watch(() => this.config?.data, (newValue) => {\r\n        if (newValue) {\r\n          this.updateChart();\r\n        }\r\n      }, true);\r\n    }\r\n\r\n      /** Creates chart based on data and options to canvas or updates chart if it already exists */\r\n  public createChart(): void {\r\n    if (!this.chart) {\r\n      const ctx = (this.$element.find(\"canvas\")[0] as HTMLCanvasElement)?.getContext(\"2d\");\r\n      if (ctx && this.config) {\r\n        this.chart = new Chart(ctx, this.config);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates provided current chart\r\n   * \"none\" parameters means no animation for update\r\n   */\r\n  public updateChart(): void {\r\n    if(this.chart) {\r\n      this.chart.data = this.config?.data;\r\n      this.chart.update(\"none\");\r\n    }\r\n  }\r\n}\r\n","\r\nimport angular from \"angular\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Provides user interface for the JSON Formatter UI that shows JSON as collapsible\r\n * tree view for debugging purposes.\r\n */\r\nexport class JsonFormatterController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /**\r\n   * Data that is shown in the component.\r\n   * This property is being watched for changes in each $digest cycle so it needs to be cached\r\n   */\r\n  public json: any;\r\n\r\n  /** If true json is compared to compare-to value. */\r\n  public compare: boolean;\r\n\r\n  /** The original JavaScript to which to show DIFF (show changes in data). */\r\n  public compareTo: any;\r\n\r\n  /** Key of the property that is shown in the component */\r\n  public key: string;\r\n\r\n  /** User interface type. Default is inline tree view. Dialog shows a button for a dialog. */\r\n  public type: \"default\" | \"dialog\";\r\n\r\n  /**\r\n   * Number of children that are currently open.\r\n   * Null sets the default value 1. Set zero for 0.\r\n   */\r\n  public open: number | null;\r\n\r\n  /** If true, the node is currently open */\r\n  public isOpen: boolean;\r\n\r\n  /** If true, the current value (string) is interpreted as date */\r\n  public isDate: boolean;\r\n\r\n  /** If true, the current value (string) is interpreted as URL */\r\n  public isUrl: boolean;\r\n\r\n  /** Gets the changes object. Null if no changes or change detection is not enabled. */\r\n  public changes: any;\r\n\r\n  /** JavaScript type for the object */\r\n  public jsonType: string;\r\n\r\n  /** Keys that existed in compareTo, but are no longer present in json. */\r\n  public deletedKeys: string[];\r\n\r\n  /** Component configuration */\r\n  public config = {\r\n    hoverPreviewEnabled: false,\r\n    hoverPreviewArrayCount: 100,\r\n    hoverPreviewFieldCount: 5,\r\n  };\r\n\r\n  /**\r\n   * Creates a new instance of the directive.\r\n   */\r\n  constructor(private uiHelpers: UiHelpers) {\r\n    // For dependency injection\r\n  }\r\n\r\n  /**\r\n   * Initialize default values.\r\n   */\r\n  public $onInit() {\r\n    if (this.open == null) {\r\n      this.open = 1;\r\n    }\r\n    this.isOpen = !!this.open;\r\n    this.jsonType = this.getType(this.json);\r\n    this.changes = this.getChanges();\r\n    this.deletedKeys = this.getDeletedKeys();\r\n  }\r\n\r\n  /** Escapes quotation marks in text */\r\n  public escapeString(str) {\r\n    return str.replace(/\"/g, \"\\\\\\\"\");\r\n  }\r\n\r\n  /** From http://stackoverflow.com/a/332429 */\r\n  public getObjectName(object) {\r\n    if (object === undefined) {\r\n      return \"\";\r\n    }\r\n    if (object === null) {\r\n      return \"Object\";\r\n    }\r\n    if (typeof object === \"object\" && !object.constructor) {\r\n      return \"Object\";\r\n    }\r\n\r\n    // ES6 default gives name to constructor\r\n    if (object.__proto__ !== undefined && object.__proto__.constructor !== undefined && object.__proto__.constructor.name !== undefined) {\r\n      return object.__proto__.constructor.name;\r\n    }\r\n\r\n    const funcNameRegex = /function (.{1,})\\(/;\r\n    const results = (funcNameRegex).exec((object).constructor.toString());\r\n    if (results && results.length > 1) {\r\n      return results[1];\r\n    } else {\r\n      return \"\";\r\n    }\r\n  }\r\n\r\n  /** Gets the object type as string */\r\n  public getType(object) {\r\n    if (object === null) { return \"null\"; }\r\n    const type = typeof object;\r\n    if (type === \"string\") {\r\n      // Add custom type for date\r\n      if ((new Date(object)).toString() !== \"Invalid Date\") {\r\n        this.isDate = true;\r\n      }\r\n      // Add custom type for URLs\r\n      if (object.indexOf(\"http\") === 0) {\r\n        this.isUrl = true;\r\n      }\r\n    }\r\n    return type;\r\n  }\r\n\r\n  /** Gets the value preview text. */\r\n  public getValuePreview(value) {\r\n    const type = this.getType(value);\r\n    if (type === \"null\" || type === \"undefined\") { return type; }\r\n    if (type === \"string\") {\r\n      value = \"\\\"\" + this.escapeString(value) + \"\\\"\";\r\n    }\r\n    if (type === \"function\") {\r\n      // Remove content of the function\r\n      return value.toString()\r\n        .replace(/[\\r\\n]/g, \"\")\r\n        .replace(/\\{.*\\}/, \"\") + \"{…}\";\r\n    }\r\n    return value;\r\n  }\r\n\r\n  /** Gets a preview of the object. */\r\n  public getPreview(object) {\r\n    let value = \"\";\r\n    if (angular.isObject(object)) {\r\n      value = this.getObjectName(object);\r\n      if (angular.isArray(object)) {\r\n        value += \"[\" + object.length + \"]\";\r\n      }\r\n    } else {\r\n      value = this.getValuePreview(object);\r\n    }\r\n    return value;\r\n  }\r\n\r\n  /** Returns true, if json is an array */\r\n  public isArray() {\r\n    return angular.isArray(this.json);\r\n  }\r\n\r\n  /** Returns true, if json is an object (including an array). */\r\n  public isObject() {\r\n    return angular.isObject(this.json);\r\n  }\r\n\r\n  /** Gets the keys for the object. Only returns keys whgere showKey is true. */\r\n  public getKeys(): string[] {\r\n    if (this.isObject()) {\r\n      return Object.keys(this.json)\r\n        .filter((key) => this.showKey(key))\r\n        .map((key) => {\r\n          if (key === \"\") { return \"\\\"\\\"\"; }\r\n          return key;\r\n        });\r\n    }\r\n  }\r\n\r\n  /** Hides keys like $$hashKey */\r\n  public showKey(key: string) {\r\n    if (!key) {\r\n      // This would be an error, but probably show it to understand errors.\r\n      return true;\r\n    }\r\n    if (key === \"$ref\") {\r\n      // At least this key starting with $ needs to be shown. Perhaps there are others?\r\n      return true;\r\n    }\r\n    if (key.startsWith(\"$\")) {\r\n      return false;\r\n    }\r\n    return true;\r\n  }\r\n\r\n  /** If true, the current JSON has a key */\r\n  public get hasKey() {\r\n    return typeof this.key !== \"undefined\";\r\n  }\r\n\r\n  /** Gets the constructor name */\r\n  public getConstructorName() {\r\n    return this.getObjectName(this.json);\r\n  }\r\n\r\n  /** Returns true if the the object is an empty object. */\r\n  public isEmptyObject() {\r\n    return this.getKeys() && !this.getKeys().length &&\r\n      this.isOpen && !this.isArray();\r\n  }\r\n\r\n  /** Opens / closes the node */\r\n  public toggleOpen() {\r\n    this.isOpen = !this.isOpen;\r\n  }\r\n\r\n  /** Returns the number of open levels for immediate children (this open - 1, but not less than 0). */\r\n  public childrenOpen() {\r\n    if (this.open > 1) {\r\n      return this.open - 1;\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /** Opens the link in a new window. */\r\n  public openLink(isUrl) {\r\n    if (isUrl) {\r\n      window.location.href = this.json;\r\n    }\r\n  }\r\n\r\n  /** Parses value (gets a preview) */\r\n  public parseValue(value) {\r\n    return this.getValuePreview(value);\r\n  }\r\n\r\n  /** Shows the current JSON as dialog. */\r\n  public showDialog() {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/helpers/JsonFormatterDialog.html\", this.json, {\r\n      compare: this.compare,\r\n      compareTo: this.compareTo,\r\n      key: this.key,\r\n      open: this.open,\r\n      type: \"default\",\r\n      title: this.key ? \"JSON Preview \" + this.key : \"JSON Preview\",\r\n    });\r\n  }\r\n\r\n  /** Returns true if the thumbnail should be shown */\r\n  public showThumbnail() {\r\n    return !!this.config.hoverPreviewEnabled && this.isObject() && !this.isOpen;\r\n  }\r\n\r\n  /** Gets the thumbnail value. */\r\n  public getThumbnail() {\r\n    if (this.isArray()) {\r\n\r\n      // if array length is greater then 100 it shows \"Array[101]\"\r\n      if (this.json.length > this.config.hoverPreviewArrayCount) {\r\n        return \"Array[\" + this.json.length + \"]\";\r\n      } else {\r\n        // eslint-disable-next-line @typescript-eslint/unbound-method\r\n        return \"[\" + this.json.map(this.getPreview).join(\", \") + \"]\";\r\n      }\r\n    } else {\r\n\r\n      const keys = this.getKeys();\r\n\r\n      // the first five keys (like Chrome Developer Tool)\r\n      const narrowKeys = keys.slice(0, this.config.hoverPreviewFieldCount);\r\n\r\n      // json value schematic information\r\n      const kvs = narrowKeys.map((key) => key + \":\" + this.getPreview(this.json[key]));\r\n\r\n      // if keys count greater then 5 then show ellipsis\r\n      const ellipsis = keys.length >= 5 ? \"…\" : \"\";\r\n\r\n      return \"{\" + kvs.join(\", \") + ellipsis + \"}\";\r\n    }\r\n  }\r\n\r\n  /** Gets the keys that are not in the current, but are in the original. */\r\n  private getDeletedKeys(): string[] {\r\n    if (!this.compare || !angular.isObject(this.compareTo)) {\r\n      return [];\r\n    }\r\n    const currentKeys = this.getKeys();\r\n    return Object.keys(this.compareTo).map((key) => {\r\n      if (key === \"\") { return \"\\\"\\\"\"; }\r\n      if (currentKeys.find((ck) => ck === key)) {\r\n        return null;\r\n      }\r\n      return key;\r\n    }).filter((key) => key != null);\r\n  }\r\n\r\n  /** Gets the changes compared to the original element */\r\n  private getChanges() {\r\n    if (!this.compare || angular.equals(this.json, this.compareTo)) {\r\n      return null;\r\n    }\r\n    let type = \"changed\";\r\n    let icon = \"*\";\r\n    const oldValue = this.getValuePreview(this.compareTo);\r\n    if (oldValue === \"undefined\" || oldValue === \"null\") {\r\n      type = \"new\";\r\n      icon = \"+\";\r\n    } else if (this.jsonType === \"null\" || this.jsonType === \"undefined\") {\r\n      type = \"deleted\";\r\n      icon = \"-\";\r\n    }\r\n    return {\r\n      type,\r\n      oldValue,\r\n      icon,\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { SitemapNode, SitemapVisibility, InvoicesLogic, Configs } from \"@salaxy/core\";\r\nimport { NaviService, SessionService, UserSettingsService } from \"../../services\";\r\nimport { SitemapHelper } from \"../../helpers\";\r\nimport { CurrentRoute } from \"../../helpers/CurrentRoute\";\r\n\r\n/**\r\n * Helper controller to generate navigation components and views:\r\n * Top- and side-menus, paths and controls that show the current title.\r\n * These controls take the navigation logic from an object (sitemap) and are aware of current node / open page on that sitemap.\r\n *\r\n * NOTE: This is just an optional helper to make creating simple demo sites easier.\r\n * There is no need to use NaviService, NaviController or components in your custom site!\r\n * You can use something completely different.\r\n */\r\nexport class NaviController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"NaviService\", \"SessionService\", \"UserSettingsService\"];\r\n\r\n  /**\r\n   * Display mode of the sitemap / navi: \"default\", \"accordion\" or \"horizontal\"\r\n   * default: Shows full two levels of the tree. Typically used as sitemap in the content area.\r\n   * accordion: Shows first level of the navi tree and second level only it is in the current path. Typically used in left menu navigation.\r\n   * horizontal: Full navi on top bar. Second tier in dropdowns.\r\n   * 3-levels: Accordion with 3 levels.\r\n   */\r\n  public mode: \"default\" | \"accordion\" | \"horizontal\" | \"3-levels\" = \"default\";\r\n\r\n  /**\r\n   * - layout: \"default\" or \"iframe\"\r\n   * - default: Basic layout with full navigation (left sidebar or horizontal).\r\n   * - iframe: Layout without first tier navigation on left sidebar. Second tier navigation items are under dropdown in top bar / header if mode is default.\r\n   * On horizontal mode full navigation is on top bar.\r\n   */\r\n  public layout: \"default\" | \"iframe\";\r\n\r\n  /**\r\n   * Creates a new NaviController\r\n   * @param naviService - Service that stores the navigation state.\r\n   * @ignore\r\n   */\r\n  constructor(private naviService: NaviService, private sessionService: SessionService, private userSettingsService: UserSettingsService) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n\r\n    if (this.mode !== \"accordion\" && this.mode !== \"3-levels\" && this.mode !== \"horizontal\") {\r\n      this.mode = \"default\";\r\n    }\r\n\r\n  };\r\n\r\n  /**\r\n   * Contains information about the current sitemap node (if resoved) and other data related to route.\r\n   * This property takes into account that the current node may not be found,\r\n   * i.e. current.node may be null, current.path may be [].\r\n   * However, the \"route\" as an object should never be null.\r\n   * All the other properties in this controller use first node as default for historical reasons.\r\n   */\r\n  public get route(): CurrentRoute {\r\n    return this.naviService.current;\r\n  }\r\n\r\n  /**\r\n   * Returns the main sitemap object that is used in rendering the navigation.\r\n   * Set the sitemap by setting the angular constant or object \"SITEMAP\"\r\n   */\r\n  public get sitemap(): SitemapNode[] {\r\n    return this.naviService.getSitemap();\r\n  }\r\n\r\n  /**\r\n   * If true, the layout should show a full-page loader instead of normal pages.\r\n   * Controllers in normal pages should be destoyed (e.g. using ng-if) so that this can also\r\n   * be used in reloading the AngularJS user interface without full Browser reload.\r\n   */\r\n  public get showFullPageLoader() {\r\n    return this.sessionService.isLoading;\r\n  }\r\n\r\n  /**\r\n   * Gets the user-specific setting (service), stored in the local storage.\r\n   */\r\n  public get userSettings() {\r\n    return this.userSettingsService;\r\n  }\r\n\r\n  /**\r\n   * Temporary visibility helper for the new Payroll 4 version.\r\n   */\r\n  public get newPayrollVersion() {\r\n    const show = this.sessionService.isInRole(\"newPayroll\") || this.sessionService.isInRole(\"test\");\r\n    const result = {\r\n      /** If true, the switch for selecting version 4 is shown to the user. */\r\n      show,\r\n      /** If true the new version is in use. */\r\n      use: show && (this.userSettings.ng1Binder(\"payroll.newVersion\").val ?? false) as boolean,\r\n    };\r\n    if (this.sessionService.session.settings.integration?.serverUrl) {\r\n      // Integration server requires the new version\r\n      result.show = false;\r\n      result.use = true;\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Returns route for the given path\r\n   * @param path Page URL path for the node.\r\n   * @returns Route for the path.\r\n   */\r\n  public getRoute(path: string = null): CurrentRoute {\r\n    if (!path) {\r\n      return this.route;\r\n    }\r\n    return new CurrentRoute(this.naviService.getNodesByPath(path));\r\n  }\r\n\r\n  /**\r\n   * Retuns the identifier of the currently selected section.\r\n   * If nothing else is selected, it will return the first section, by convention called 'home'.\r\n   */\r\n  public getSectionId() {\r\n    if (!this.naviService.currentSection) {\r\n      return \"home\";\r\n    }\r\n    return this.naviService.currentSection.id;\r\n  }\r\n\r\n  /**\r\n   * Gets the navi URL from a sitemap node.\r\n   * Currently, removes \"*\" at the end if url ends with \"/*\", but may be used for additional logic in the future.\r\n   */\r\n  public getUrl(node: SitemapNode): string {\r\n    if (!node || !node.url) {\r\n      return null;\r\n    }\r\n    if (node.url.endsWith(\"/*\")) {\r\n      return node.url.substr(0, node.url.length - 1);\r\n    }\r\n    return node.url;\r\n  }\r\n\r\n  /** Toggles the isNaviOpen property */\r\n  public toggleNavi() {\r\n    this.naviService.isNaviOpen = !this.naviService.isNaviOpen;\r\n  }\r\n\r\n  /**\r\n   * True if the navigation (e.g. left sidebar) is open.\r\n   * Typically, this property is used only in narrow (mobile) view, otherwise the sidebar is always shown.\r\n   */\r\n  public get isNaviOpen() { return this.naviService.isNaviOpen; }\r\n  public set isNaviOpen(value: boolean) { this.naviService.isNaviOpen = value; }\r\n\r\n  /** Toggles the isSidebarOpen property */\r\n  public toggleSidebar() {\r\n    this.naviService.isSidebarOpen = !this.naviService.isSidebarOpen;\r\n  }\r\n\r\n  /**\r\n   * True if the secondary sidebar (e.g. right sidebar) is open.\r\n   */\r\n  public get isSidebarOpen() { return this.naviService.isSidebarOpen; }\r\n  public set isSidebarOpen(value: boolean) { this.naviService.isSidebarOpen = value; }\r\n\r\n  /**\r\n   * Gets the current section: The first level node in the sitemap\r\n   * @returns Section filtered by the roles.\r\n   */\r\n  public getSection(): SitemapNode {\r\n    return this.naviService.getCurrentSection();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the node should be hidden in the navi.\r\n   * @param node Node to check. If null, the current node is checked (not defaulted to first node).\r\n   */\r\n  public getHidden(node: SitemapNode = null): boolean {\r\n    return SitemapHelper.getVisibility(node || this.route.node, SitemapVisibility.Hidden);\r\n  }\r\n\r\n  /**\r\n   * Gets the visibility:disabled flag for the current node OR any node in the path\r\n   */\r\n  public getDisabled(): boolean {\r\n    return this.route.node?.visibility == SitemapVisibility.Disabled || !!(this.route.path).find((x) => x.visibility == SitemapVisibility.Disabled);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the node has non-hidden children.\r\n   * @param node Node to check\r\n   */\r\n  public hasChildren(node: SitemapNode): boolean {\r\n    return !!node?.children.find((x) => !SitemapHelper.getVisibility(x, SitemapVisibility.Hidden));\r\n  }\r\n\r\n  /**\r\n   * Filters away the hidden nodes from node array.\r\n   * @param nodes Node array.\r\n   */\r\n  public filterHidden(nodes: SitemapNode[]): SitemapNode[] {\r\n    if (!nodes) {\r\n      return [];\r\n    }\r\n    return nodes.filter((x) => !SitemapHelper.getVisibility(x, SitemapVisibility.Hidden));\r\n  }\r\n\r\n  /**\r\n   * Returns true if the given node is the currently selected node.\r\n   */\r\n  public isCurrent(siteMapNode: SitemapNode): boolean {\r\n    return this.naviService.isCurrent(siteMapNode);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the given node is the currently selected node.\r\n   */\r\n  public isCurrentSection(section: SitemapNode): boolean {\r\n    return this.naviService.isCurrentSection(section);\r\n  }\r\n\r\n  /**\r\n   * In test environment, returns true if the sitemap node has role \"test\" and it is visible only because of that role.\r\n   * @param siteMapNode Node in the sitemap.\r\n   */\r\n  public isTest(siteMapNode: SitemapNode): boolean {\r\n    return siteMapNode.visibleTestOnly >= 0;\r\n  }\r\n\r\n  /**\r\n   * Navigate to given path\r\n   * @param path - Path to navigate.\r\n   * @param checkSession - If true, triggers session refresh\r\n   */\r\n  public navigateTo(path: string, checkSession = false) {\r\n    this.naviService.navigateTo(path, checkSession);\r\n  }\r\n\r\n  /** Returns the page / node title */\r\n  public get title() {\r\n    return this.naviService.title || this.naviService.sectionTitle || \"\\xa0\";\r\n  }\r\n\r\n  /** Gets the currently selected node. */\r\n  public get current() {\r\n    return this.naviService.currentNode;\r\n  }\r\n\r\n  /** Current path from root to the current node. */\r\n  public get currentPath(): SitemapNode[] {\r\n    return this.naviService.currentPath;\r\n  }\r\n\r\n  /** Returns true if the current window is in an IFrame */\r\n  public get isInIframe(): boolean {\r\n    try {\r\n      return window.self !== window.top;\r\n    } catch (e) {\r\n      return true;\r\n    }\r\n  }\r\n\r\n  /** Returns current year. Used for example in copyright texts in footers */\r\n  public getCurrentYear(): number {\r\n    return new Date().getFullYear();\r\n  }\r\n\r\n  /**\r\n   * Determines whether to show the KYC (Know Your Customer) information.\r\n   * @returns A boolean value indicating whether to show the KYC information.\r\n   */\r\n  public get showKyc(): boolean {\r\n    return this.isCfaCustomer && !(this.sessionService.session?.currentAccount?.identity as any)?.kycUpdatedAt;\r\n  }\r\n\r\n  /**\r\n   * Determines whether the customer is a cfa customer.\r\n   * @returns A boolean value indicating whether the customer is a cfa customer.\r\n   */\r\n  public get isCfaCustomer(): boolean {\r\n    return !!this.sessionService.session?.settings?.paymentChannels?.some((x) => InvoicesLogic.isCfa(x));\r\n  }\r\n\r\n  /** Returns current application */\r\n  public get applicationId(): string {\r\n    return Configs.current.applicationId;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Translations } from \"@salaxy/core\";\r\n\r\n/**\r\n * Controller rendering a Spinner (please wait) user interfaces.\r\n */\r\nexport class SpinnerController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** If true, the spinner is shown full screen. */\r\n  public fullScreen: boolean;\r\n\r\n  /**\r\n   * Heading is the larger text under the spinner.\r\n   * The text is translated.\r\n   * Also, if language dictionaries are not available, SALAXY.UI_Terms.loading and .loginInProgress are\r\n   * resolved to Finnish terms \"Ladataan...\" and \"Kirjaudutaan...\"\r\n   */\r\n  public heading: string;\r\n\r\n  /**\r\n   * Small text - use pre for line breaks.\r\n   * The text is translated.\r\n   */\r\n  public text: string;\r\n\r\n  /**\r\n   * Creates a new SpinnerController\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    //\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    // initialization\r\n  };\r\n\r\n  /**\r\n   * Gets the header with default Finnish texts for \"SALAXY.UI_Terms.loading\" and \"SALAXY.UI_Terms.loginInProgress\".\r\n   * Other untranslated language terms (starting with \"SALAXY.\") return an empty text. Other texts are printed as is.\r\n   */\r\n  public getHeading() {\r\n    if (!this.heading) {\r\n      return null;\r\n    }\r\n    const knownTerms = {\r\n      \"SALAXY.UI_Terms.loading\": \"Ladataan...\",\r\n      \"SALAXY.UI_Terms.loginInProgress\": \"Kirjaudutaan...\",\r\n    };\r\n    let defaultText = this.heading;\r\n    if (defaultText.startsWith(\"SALAXY.\")) {\r\n      defaultText = knownTerms[this.heading];\r\n    }\r\n    return Translations.getWithDefault(this.heading, defaultText);\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { TabsController } from \"./TabsController\";\r\n\r\n/**\r\n * Controller for a single tab pane in the tabs control.\r\n */\r\nexport class TabController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$element\"];\r\n\r\n  /** Tabs controller */\r\n  public tabsCtrl: TabsController;\r\n\r\n  /** Selected tab flag. */\r\n  public selected = false;\r\n\r\n  /** Flag to disable tab. */\r\n  public disable = false;\r\n\r\n  /** Unique name/id for the tab. */\r\n  public index: any = null;\r\n\r\n  /** Text heading for the tab */\r\n  public heading: string = null;\r\n\r\n  /** Selection event handler */\r\n  public onSelect: ( args: {\r\n    /** Selection event. */\r\n    $event: angular.IAngularEvent,\r\n  }) => void;\r\n\r\n  /** Heading DOM node for the tab. */\r\n  public headingElement = null;\r\n\r\n  /** Content DOM node for the tab. */\r\n  public contentElement = null;\r\n\r\n  /** Sorting field */\r\n  public sort = 0;\r\n\r\n  /**\r\n   * Creates a new TabController.\r\n   * @ignore\r\n   */\r\n  constructor(private $element) {\r\n    // instantiation\r\n  }\r\n\r\n  /**\r\n   * Change event handler. Re-sets the one-way bound fields.\r\n   * This is needed, because the parent scope cannot detect the changes without the re-set.\r\n   */\r\n  public $onChanges(changes: any) {\r\n    if (changes.disable) {\r\n      this.disable = changes.disable.currentValue;\r\n    }\r\n    if (changes.index) {\r\n      this.index = changes.index.currentValue;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Registers this tab to the tabs controller.\r\n   * Passes the heading DOM element to be displayed in the header.\r\n   */\r\n  public $onInit() {\r\n    this.sort = this.getPosition(this.$element);\r\n    this.headingElement = this.findTranscludeElement(this.$element, \"heading\");\r\n    this.contentElement = this.findTranscludeElement(this.$element, \"content\");\r\n    this.index = this.tabsCtrl.register(this);\r\n  }\r\n\r\n  /**\r\n   * De-registers this tab from the tabs controller.\r\n   */\r\n  public $onDestroy() {\r\n    this.tabsCtrl.deregister(this);\r\n  }\r\n\r\n  /**\r\n   * Tries to find the element with ng-transclude='heading' attribute.\r\n   * @param el - Element to check.\r\n   */\r\n  private findTranscludeElement(el: any, slot): any {\r\n    if (el.attr(\"ng-transclude\") === slot) {\r\n      return el[0];\r\n    }\r\n    const children = el.children();\r\n    for (let i = 0; i < children.length; i++) {\r\n      const found = this.findTranscludeElement(children.eq(i), slot);\r\n      if (found) {\r\n        return found;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private getPosition(el: any) {\r\n    // find current salaxy-tab\r\n    const salaxyTabNode = this.findParentTag(el, \"salaxy-tab\");\r\n    if (!salaxyTabNode) {\r\n      return 0;\r\n    }\r\n    // find parent salaxy-tabs\r\n    const salaxyTabsNode = this.findParentTag(salaxyTabNode, \"salaxy-tabs\");\r\n    if (!salaxyTabsNode) {\r\n      return 0;\r\n    }\r\n    // find all salaxy-tab nodes under salaxy-tabs\r\n    const salaxyTabNodes = [];\r\n    this.findChildren(salaxyTabsNode, salaxyTabNodes, \"salaxy-tab\");\r\n    // return child index\r\n    for (let i = 0; i < salaxyTabNodes.length; i++) {\r\n      if (salaxyTabNode[0] === salaxyTabNodes[i][0]) {\r\n        return i;\r\n      }\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  private findParentTag(el: any, tagName: string): any {\r\n    if (el[0].tagName.toLowerCase() === tagName) {\r\n      return el;\r\n    }\r\n\r\n    const parent = el.parent();\r\n    if (parent.length === 1) {\r\n      return this.findParentTag(parent, tagName);\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private findChildren(el: any, nodes: any[], tagName: string) {\r\n    if (el[0].tagName.toLowerCase() === tagName) {\r\n      nodes.push(el);\r\n      return;\r\n    }\r\n\r\n    const children = el.children();\r\n    for (let i = 0; i < children.length; i++) {\r\n      this.findChildren(children.eq(i), nodes, tagName);\r\n    }\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { TabController } from \"./TabController\";\r\n\r\n/**\r\n * Controller for the tabs control.\r\n */\r\nexport class TabsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /** Tabs array. Contains all registered tabs. */\r\n  public tabs: TabController[] = [];\r\n\r\n  /**\r\n   * Creates a new TabsController.\r\n   * @ignore\r\n   */\r\n  constructor() {\r\n    // instantiation\r\n  }\r\n\r\n  /** Set the values and defaults on init */\r\n  public $onInit() {\r\n    // initialization\r\n  }\r\n\r\n  /**\r\n   * Registers a single tab to this controller.\r\n   * @param tab - Tab to register.\r\n   */\r\n  public register(tab: TabController): any {\r\n    this.tabs.push(tab);\r\n    this.setSortOrder(tab);\r\n    this.tabs.sort((t1, t2) => {\r\n      if (t1.sort > t2.sort) {\r\n        return 1;\r\n      }\r\n      if (t1.sort < t2.sort) {\r\n        return -1;\r\n      }\r\n      return 0;\r\n    });\r\n\r\n    const index = this.findIndex(tab);\r\n\r\n    if (this.tabs.length === 1) {\r\n      tab.selected = true;\r\n    }\r\n\r\n    return tab.index || index;\r\n  }\r\n\r\n  /**\r\n   * De-registers a single tab from this controller.\r\n   * @param tab - Tab to de-register.\r\n   */\r\n  public deregister(tab: TabController) {\r\n    const index = this.findIndex(tab);\r\n\r\n    if (this.tabs[index].index === this.active) {\r\n      const newActiveTabIndex = index === (this.tabs.length - 1) ?\r\n        index - 1 : (index + 1) % this.tabs.length;\r\n      this.select(this.tabs[newActiveTabIndex]);\r\n    }\r\n\r\n    this.tabs.splice(index, 1);\r\n  }\r\n\r\n  /**\r\n   * Sets the selected tab as selected.\r\n   * @param selectedTab - Selected tab.\r\n   */\r\n  public select(selectedTab: TabController, evt?: angular.IAngularEvent) {\r\n    if (selectedTab && selectedTab.disable === true) {\r\n      return;\r\n    }\r\n    for (const tab of this.tabs) {\r\n      if (tab.selected && tab !== selectedTab) {\r\n        tab.selected = false;\r\n      }\r\n    }\r\n    if (!selectedTab) {\r\n      return;\r\n    }\r\n    selectedTab.selected = true;\r\n    selectedTab.onSelect({\r\n        $event: evt,\r\n      });\r\n  }\r\n\r\n  /** Get the index of the active tab. */\r\n  public get active() {\r\n    for (const tab of this.tabs) {\r\n      if (tab.selected) {\r\n        return tab.index;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Set the index of the active tab. */\r\n  public set active(value) {\r\n    if (!value) {\r\n      return;\r\n    }\r\n    for (const tab of this.tabs) {\r\n      if (tab.index === value) {\r\n        this.select(tab);\r\n        return;\r\n      }\r\n    }\r\n  }\r\n\r\n  private findIndex(tab: any) {\r\n    for (let i = 0; i < this.tabs.length; i++) {\r\n      if (this.tabs[i] === tab) {\r\n        return i;\r\n      }\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  private setSortOrder(newTab: any) {\r\n    // latest wins\r\n    let resort = false;\r\n    for (const tab of this.tabs) {\r\n      if (tab !== newTab && tab.sort === newTab.sort) {\r\n        resort = true;\r\n      }\r\n    }\r\n    if (resort) {\r\n      for (const tab of this.tabs) {\r\n        if (tab !== newTab && tab.sort >= newTab.sort) {\r\n          tab.sort++;\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Arrays, Translations } from \"@salaxy/core\";\r\nimport {\r\n  UiHelpers,\r\n  UiTranslatorService,\r\n  UiTranslatorDictionaryItem\r\n} from \"../../services\";\r\n\r\n/**\r\n * Tool that allows translate user interfaces.\r\n */\r\nexport class UiTranslatorController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"$timeout\", \"UiTranslatorService\"];\r\n\r\n  /** User interface mode for the component. */\r\n  public mode: \"table\" | \"fieldset\";\r\n\r\n  /** Array of dictionary items shown in the component (the original unedited values). */\r\n  public allKeyValues: Array<UiTranslatorDictionaryItem> = [];\r\n\r\n  /** Local variable used to store texts that have been edited. */\r\n  public serviceModelTexts: Array<{ fullKey: string, fi?: string, en?: string, sv?: string }> = [];\r\n\r\n  /** Contains boolean values to indicate whether columns should be shown or not. */\r\n  public showCols: UiTranslatorDictionaryItem = {\r\n    fullKey: \"true\",\r\n    fi: \"true\",\r\n    en: \"true\",\r\n    sv: \"true\",\r\n  };\r\n\r\n  /** AngularJS filter for the translator table: rows filtering.  */\r\n  public listFilter: UiTranslatorDictionaryItem = {};\r\n\r\n  /** Show spinner if the data is loading. */\r\n  public isLoading = false;\r\n\r\n  /**\r\n   * Texts from serviceModel that are being edited\r\n   * This is in format { [key: string]: string } where key\r\n   * is a full key starting from the language, e.g. \"fi.SALAXY.NG1_Sitemap.home\"\r\n   * and value is always an indidivual text (never an object).\r\n   */\r\n  public texts: { [key: string]: string };\r\n\r\n  private _filter: string | string[];\r\n\r\n  /**\r\n   * Creates a new UiTranslatorController\r\n   * @ignore\r\n   */\r\n  constructor(private uiHelpers: UiHelpers, private $timeout: angular.ITimeoutService, private uiTranslatorService: UiTranslatorService) {\r\n    // For dependency injection.\r\n  }\r\n\r\n  /** Init */\r\n  public $onInit = () => {\r\n    this.initTranslationTable();\r\n    this.initTexts();\r\n  };\r\n\r\n  /**\r\n   * Beginning of the full key that is used to filtering the dictionary items (allKeyValues filter).\r\n   * The value may be a string, array or comma separated string of values.\r\n   */\r\n  public get filter(): string | string[] {\r\n    return this._filter;\r\n  }\r\n  public set filter(value: string | string[]) {\r\n    this._filter = value;\r\n    this.updateAllKeyValues();\r\n  }\r\n\r\n  /** Updates this.text and keeps reference to parent */\r\n  public updateTexts() {\r\n    angular.copy(this.toTexts(), this.texts);\r\n  }\r\n\r\n  /**\r\n   * Check if key exists in serviceModelTexts for specified language.\r\n   * @param fullkey Dictionary key\r\n   * @param lang Language that is checked.\r\n   * @returns True if the provided key exists\r\n   */\r\n  public checkIfExistsInTexts(fullkey: string, lang: string): boolean {\r\n    return !!this.serviceModelTexts.find(x => x.fullKey === fullkey && lang in x);\r\n  }\r\n\r\n  /**\r\n   * Check if item can be deleted from serviceModelTexts\r\n   * @param fullKey dictionary key\r\n   * @returns True if the item can be deleted.\r\n   */\r\n  public canDeleteFromText(fullKey: string): boolean {\r\n    return !!this.serviceModelTexts.find(x => x.fullKey === fullKey);\r\n  }\r\n\r\n  /**\r\n   * Finds and return item from serviceModelTexts\r\n   * @param fullkey search value\r\n   * @returns serviceModelTexts item\r\n   */\r\n  public getEditableText(fullkey: string): { fullKey: string, fi?: string, en?: string, sv?: string } {\r\n    return this.serviceModelTexts.find(({ fullKey }) => fullKey === fullkey);\r\n  }\r\n\r\n  /**\r\n   * Adds item to serviceModelTexts\r\n   * @param fullKey fullKey to be added\r\n   */\r\n  public addToTexts(fullKey: string, lang: string): void {\r\n    const index = this.serviceModelTexts.findIndex(x => x.fullKey === fullKey);\r\n    if (index > -1) {\r\n      this.serviceModelTexts[index][lang] = \"\";\r\n    } else {\r\n      const obj: any = { fullKey: fullKey };\r\n      obj[lang] = \"\";\r\n      this.serviceModelTexts.push(obj);\r\n    }\r\n    this.updateTexts();\r\n  }\r\n\r\n  /**\r\n   * Remove item from serviceModelTexts\r\n   * @param fullKey fullKey search value\r\n   */\r\n  public removeFromTexts(fullKey: string): void {\r\n    const index = this.serviceModelTexts.findIndex(x => x.fullKey === fullKey);\r\n    this.serviceModelTexts.splice(index, 1);\r\n    this.updateTexts();\r\n  }\r\n\r\n  /**\r\n   * Save current diff to JSON file\r\n   */\r\n  public downloadTexts(): void {\r\n    const diff = this.getDiffDictionary();\r\n    const str = JSON.stringify(diff);\r\n    const bytes = new TextEncoder().encode(str);\r\n    const blob = new Blob([bytes], {\r\n      type: \"application/json;charset=utf-8\"\r\n    });\r\n    this.uiHelpers.downloadFile(blob, \"diff\");\r\n  }\r\n\r\n  private initTranslationTable() {\r\n    this.isLoading = true;\r\n    this.$timeout().then(() => {\r\n      if (this.uiTranslatorService.getDictionary().length < 1) {\r\n        Translations.instance.getBaseDictionary().then(baseDictionary => {\r\n          this.createKeyValues(baseDictionary, \"\");\r\n          this.updateAllKeyValues();\r\n          this.$timeout(); // getBaseDictionary uses fetch() => Need to call timeout to trigger the UI refresh.\r\n          this.isLoading = false;\r\n        });\r\n      } else {\r\n        this.updateAllKeyValues();\r\n        this.isLoading = false;\r\n      }\r\n    });\r\n  }\r\n\r\n  private initTexts() {\r\n    this.serviceModelTexts = this.fromTexts(this.texts);\r\n  }\r\n\r\n  private fromTexts(texts: any) {\r\n    texts = texts || {};\r\n    const arr: Array<{ fullKey: string, fi?: string, en?: string, sv?: string }> = [];\r\n    Object.keys(texts).forEach(key => {\r\n      const lang = key.substr(0, 2);\r\n      const fullKey = key.substring(3);\r\n      // First iteration, arr is empty\r\n      if (!arr.length) {\r\n        const serviceModelTranslation: { fullKey: string, fi?: string, en?: string, sv?: string } = { fullKey: fullKey };\r\n        serviceModelTranslation[lang] = texts[key];\r\n        arr.push(serviceModelTranslation);\r\n      } else {\r\n        // Find index of fullKey\r\n        const index = arr.findIndex(item => item.fullKey === fullKey);\r\n        if (index > -1) {\r\n          // index exists, add texts[key] to object\r\n          arr[index][lang] = texts[key];\r\n        } else {\r\n          // index not found, add new object to array\r\n          const serviceModelTranslation: { fullKey: string, fi?: string, en?: string, sv?: string } = { fullKey: fullKey };\r\n          serviceModelTranslation[lang] = texts[key];\r\n          arr.push(serviceModelTranslation);\r\n        }\r\n      }\r\n    });\r\n    return arr;\r\n  }\r\n\r\n  private toTexts() {\r\n    const obj: { [key: string]: string } = {};\r\n    this.serviceModelTexts.forEach(text => {\r\n      Object.keys(text).forEach(key => {\r\n        if (key !== \"fullKey\") {\r\n          const newFullKey = `${key}.${text.fullKey}`;\r\n          obj[newFullKey] = text[key];\r\n        }\r\n      });\r\n    });\r\n    return obj;\r\n  }\r\n\r\n  private updateAllKeyValues() {\r\n    this.allKeyValues = this.uiTranslatorService.getDictionary();\r\n    const filter = Arrays.assureArray(this.filter);\r\n    if (filter.length) {\r\n      this.allKeyValues = this.allKeyValues.filter(x => filter.find((f) => x.fullKey.startsWith(f)));\r\n    }\r\n  }\r\n\r\n  private createKeyValues(dictionary: any, path: string) {\r\n    Object.keys(dictionary).forEach(key => {\r\n      if (typeof dictionary[key] === \"object\") {\r\n        this.createKeyValues(dictionary[key], `${path}.${key}`);\r\n      } else {\r\n        const fullPath = `${path}.${key}`;\r\n        const fullKey = fullPath.substring(4);\r\n        const lang = fullPath.slice(1, 3);\r\n        const allKeyValues = this.uiTranslatorService.getDictionary();\r\n        const index = allKeyValues.findIndex(item => item.fullKey === fullKey);\r\n        if (index > -1) {\r\n          allKeyValues[index][lang] = dictionary[key];\r\n        } else {\r\n          const splitKeys = fullKey.split(\".\");\r\n          const obj: UiTranslatorDictionaryItem = {\r\n            fullKey,\r\n            shortKey: splitKeys[splitKeys.length - 1],\r\n            fileName: splitKeys[1],\r\n            keyComponent: splitKeys[2],\r\n            keyValue: splitKeys[3]\r\n          };\r\n          obj[lang] = dictionary[key];\r\n          this.uiTranslatorService.addToDictionary(obj);\r\n        }\r\n      }\r\n    });\r\n  }\r\n  private getDiffDictionary() {\r\n    const diffBase = {\r\n      fi: {},\r\n      en: {},\r\n      sv: {}\r\n    };\r\n    this.serviceModelTexts.forEach(item => {\r\n      const subKeys = item.fullKey.split(\".\");\r\n      Object.keys(diffBase).forEach(lang => {\r\n        let currentNode = diffBase[lang];\r\n        for (let i = 0; i < subKeys.length; i++) {\r\n          if (i === subKeys.length - 1) {\r\n            currentNode = currentNode[subKeys[i]] = item[lang];\r\n          } else {\r\n            // Check if subKeys[i] key exists in currentNode\r\n            if (!(subKeys[i] in currentNode)) {\r\n              // Not found, create new key with subKeys[i], assign it to {} and set to currentNode\r\n              currentNode = currentNode[subKeys[i]] = {};\r\n            } else {\r\n              // Found, assign currentNode to currentNode[subKeys[i]]\r\n              currentNode = currentNode[subKeys[i]];\r\n            }\r\n          }\r\n        }\r\n      });\r\n    });\r\n    return diffBase;\r\n  }\r\n}\r\n\r\n","import angular from \"angular\";\r\nimport { ApiCrudObject, ApiListItem, Calculations, DataMappersLogic, Exportable } from \"@salaxy/core\";\r\nimport { ApiCrudObjectController } from \"../bases/ApiCrudObjectController\";\r\nimport { ODataQueryController } from \"../bases\";\r\nimport { FileService, JsonSchemaService } from \"../../services\";\r\n\r\n/**\r\n * Controller that provides export and import for odata tables and API crud objects.\r\n */\r\nexport class ODataActionsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"FileService\", \"JsonSchemaService\"];\r\n\r\n  /** The API crud object controller. */\r\n  public $crud: ApiCrudObjectController<ApiCrudObject, ApiListItem>;\r\n\r\n  /** Enclosing ODataQueryController */\r\n  public $odata : ODataQueryController;\r\n\r\n  private calculationsUrl = new Calculations(null).getBaseUrl();\r\n\r\n  /**\r\n   * Constructor for Dependency Injection.\r\n   */\r\n  constructor(private fileService: FileService, private jsonSchemaService: JsonSchemaService) {\r\n  }\r\n\r\n  /**\r\n   * Returns Exportable api for the used crud.\r\n   * @returns Exportable api.\r\n   */\r\n  public getExportable(): Exportable<ApiCrudObject> {\r\n    // TODO: Move this to Calculations related controller and remove getExportable() away from here.\r\n    const baseUrl = this.$crud.getApi().getBaseUrl();\r\n    switch (baseUrl) {\r\n      case this.calculationsUrl:\r\n        return {\r\n          getExportMappers: () => DataMappersLogic.getMappers([\"Calculation\", \"CalculationListItem\"]),\r\n          getExportMapper: (id) => DataMappersLogic.getBuiltInMapper(id, this.jsonSchemaService.getCache()),\r\n          exporters: this.fileService.getDefaultExporters(),\r\n          getSingle: (item) => this.$crud.getApi().getSingle(item.id),\r\n          list: (maxCount?, notify?) => this.$odata.exportItems(maxCount ?? 0, notify),\r\n        };\r\n      default:\r\n        return null;\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { ApiValidation, Culture, DataMapper, FileParser, Importable, ImportBatch, InputEnumOption } from \"@salaxy/core\";\r\nimport { EditDialogKnownActions, UiHelpers, WizardService, WizardStep } from \"../../services\";\r\n\r\n/**\r\n * Controller that provides import functionality for any data.\r\n */\r\nexport class ImportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"WizardService\", \"$timeout\"];\r\n\r\n  /** The importable api. */\r\n  private _api: Importable<any>;\r\n\r\n  /** Locale for reading the raw data (CSV delimiter, numbers and dates). */\r\n  public localeId: Culture = Culture.Fi;\r\n\r\n  /** Available file parsers for import. */\r\n  public fileParsers: FileParser[];\r\n\r\n  /** Currently selected file parser.  */\r\n  public currentFileParser: FileParser;\r\n\r\n  /** Current mapper that is used to import the data */\r\n  public mapper: DataMapper<any, any> = null;\r\n\r\n  /** Wizard steps */\r\n  public importSteps: WizardStep[] = [\r\n    {\r\n      title: \"Liitä / lataa taulukko\",\r\n      view: \"salaxy-components/modals/import/ImportStep1.html\",\r\n    },\r\n    {\r\n      title: \"Asetukset\",\r\n      view: \"salaxy-components/modals/import/ImportStep2.html\",\r\n    },\r\n    {\r\n      title: \"Validointi\",\r\n      view: \"salaxy-components/modals/import/ImportStep3.html\",\r\n    },\r\n    {\r\n      title: \"Tallennus\",\r\n      view: \"salaxy-components/modals/import/ImportStep4.html\",\r\n    },\r\n  ];\r\n\r\n  /** Raw data to import. */\r\n  public batch: ImportBatch<any> = null;\r\n\r\n  /** Progress indicator from 0 to 100 where 0 is not in progress. */\r\n  public progress = 0;\r\n\r\n  /**\r\n   * Status messages from asynchronous process (import / validation to server).\r\n   * Only shown if isInProgress = true;\r\n   */\r\n  public progressMessage: string = null;\r\n\r\n  /** Results (errors and warnings) from the last run (import validation etc.). */\r\n  public lastResult: ApiValidation = null;\r\n\r\n  /** All object mappers. */\r\n  private _objectMappers: InputEnumOption[] = null;\r\n\r\n  /**\r\n   * Constructor for Dependency Injection.\r\n   * @param uiHelpers Salaxy ui helpers.\r\n   * @param wizardService Wizard service.\r\n   */\r\n  constructor(private uiHelpers: UiHelpers, private wizardService: WizardService, private $timeout: angular.ITimeoutService) {\r\n\r\n  }\r\n\r\n  /** Gets or sets the Importable api that defines how the data is imported. */\r\n  public get api():Importable<any> {\r\n    return this._api;\r\n  }\r\n  public set api(value: Importable<any>) {\r\n    this._api = value;\r\n    this.createBatch();\r\n  }\r\n\r\n  /** Available object mappers for export */\r\n  public get objectMappers(): InputEnumOption[] {\r\n    if (!this._objectMappers) {\r\n        this._objectMappers = this.api.getImportMappers();\r\n        if (this._objectMappers?.length == 1) {\r\n          this.setMapper(this._objectMappers[0].value);\r\n        }\r\n    }\r\n    return this._objectMappers;\r\n  }\r\n\r\n  /** Clears the last validation result. */\r\n  public clearLastResult() {\r\n    if (this.batch) {\r\n      this.batch.clearValidation();\r\n    }\r\n    this.lastResult = null;\r\n  }\r\n\r\n  /**\r\n   * Shows import dialog.\r\n   * @param api Optional API implementing Importable that is set to the controller.\r\n   * The API must be set to the controller as property or in this parameter or showImport() will fail\r\n   */\r\n  public showImport(api: Importable<any> = null): void {\r\n    if (api) {\r\n      this.api = api;\r\n    }\r\n    if (!this.api) {\r\n      throw new Error(\"Importable API not specified in showImport()\");\r\n    }\r\n    this.wizardService.setSteps(this.importSteps);\r\n    this.wizardService.activeStepNumber = 1;\r\n\r\n    const dialogData = {\r\n      $parent: this,\r\n    };\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/import/Import.html\",\r\n      \"WizardController\",\r\n      dialogData,\r\n      null,\r\n      \"lg\").then( () => {\r\n        // Resolve promise here if needed in future versions.\r\n      });\r\n  }\r\n\r\n  /** Paste data from clipboard. */\r\n  public pasteFromClipboard(): Promise<string> {\r\n    this.createBatch();\r\n    return (navigator as any).clipboard.readText().then((text) => {\r\n      this.batch.rawData = text;\r\n      // Ensure refresh in UI\r\n      return this.$timeout(() => {\r\n        return text;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Reads the file\r\n   * @param file Selected file\r\n   */\r\n  public readFile(file: File): Promise<string> {\r\n    if (!file) {\r\n      return Promise.resolve(null);\r\n    }\r\n    // TODO detect if excel file and read content using Excel reader.\r\n    if (file.name) {\r\n      if (file.name.toLowerCase().match(/\\.xl(s|sx)$/g)) {\r\n        this.uiHelpers.showAlert(\"Tiedoston muotoa ei tueta\", \"Excel-tiedostot eivät ole vielä tuettuja. Käytä csv tai tab -muotoa.\");\r\n        return Promise.resolve(null);\r\n      }\r\n    }\r\n\r\n    const read = new Promise<string>((resolve, reject) => {\r\n      const reader = new FileReader();\r\n      reader.onloadend = () => {\r\n        resolve(reader.result as string);\r\n      };\r\n      reader.onerror = () => reject;\r\n      reader.readAsText(file);\r\n    });\r\n\r\n    this.createBatch();\r\n\r\n    return read.then((text) => {\r\n      this.batch.rawData = text;\r\n      // Ensure refresh in UI\r\n      return this.$timeout(() => {\r\n        return text;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Creates / resets the import batch as new using the current api\r\n   * (should be selected before) and mapper (may be null / not yet selected).\r\n   */\r\n  public createBatch(): void {\r\n    this.batch = new ImportBatch(this.mapper, this.api);\r\n    this.fileParsers = this.api.parsers ?? [];\r\n    this.currentFileParser = null;\r\n  }\r\n\r\n  /**\r\n   * Read batch raw data.\r\n   * @returns The status of the read as API validation object (also saved to lastResult).\r\n   */\r\n  public readBatch(): ApiValidation {\r\n    if (!this.currentFileParser) {\r\n      const parserGuess = FileParser.guessParser(this.fileParsers, this.batch.rawData);\r\n      if (parserGuess) {\r\n        this.currentFileParser = parserGuess.parser;\r\n        this.localeId = parserGuess.locale;\r\n      } else {\r\n        return;\r\n      }\r\n    }\r\n    this.lastResult = this.batch.read(null, this.currentFileParser, this.localeId);\r\n    return this.lastResult;\r\n  }\r\n\r\n  /**\r\n   * Sets the import mapper by ID.\r\n   * @param id Identifier of the new object mapper.\r\n   * @returns The mapper once it has been loaded / resolved.\r\n   */\r\n  public setMapper(id: string): Promise<DataMapper<any, any>> {\r\n    return this.api.getImportMapper(id).then((mapper) => {\r\n      this.mapper = mapper;\r\n      this.batch.setMapper(mapper);\r\n      this.readBatch();\r\n      this.$timeout();\r\n      return mapper;\r\n    });\r\n  }\r\n\r\n  /** Read batch data */\r\n  public mapBatch() {\r\n    this.batch.map();\r\n  }\r\n\r\n  /** Validate batch data */\r\n  public validateBatch() {\r\n    this.setProgress(1, \"Tarkistetaan...\");\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    const notify = (message, index, count, result) => {\r\n      this.setProgress(index + 1, \"Tarkistetaan...\", count);\r\n    };\r\n    this.batch.validate(notify).then(() => {\r\n      this.setProgress(0);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Imports the batch data.\r\n   * @param $close Close function of the UI Bootstrap dialog.\r\n   */\r\n  public importBatch($close: (action: EditDialogKnownActions) => void): void {\r\n    this.setProgress(1, \"Tallennetaan... \");\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    const notify = (message, index, count, result) => {\r\n      this.setProgress(index + 1, \"Tallennetaan...\", count);\r\n    };\r\n    this.lastResult = null;\r\n    this.batch.import(notify).then((result) => {\r\n      this.setProgress(0);\r\n      this.lastResult = result;\r\n      if (!result.errors?.length) {\r\n        $close(EditDialogKnownActions.Ok);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the progress indicator\r\n   * @param value Value of the progress 0-100. If the process is just starting, use 1.\r\n   * If not in progress, use 0. If the count is null, you may also use absolute value (index+1) here:\r\n   * The system will convert it to 1-100 first assuming there is 10 items, then that there is 100 items.\r\n   * @param message Progress message\r\n   * @param count Total count of items if known.\r\n   */\r\n  private setProgress(value: number, message: string = null, count: number = null) {\r\n    if (!value) {\r\n      this.progress = 0;\r\n      this.progressMessage = null;\r\n      return;\r\n    }\r\n    if (count) {\r\n      this.progress = value / count * 100;\r\n    } else {\r\n      if (value < 10) {\r\n        this.progress = value * 10; // First assume 10 items\r\n      } else if (value < 100) {\r\n        this.progress = value;\r\n      } else if (value < 1000) {\r\n        this.progress = value / 10;\r\n      } else {\r\n        this.progress = 90;\r\n      }\r\n    }\r\n    if (this.progress > 100) {\r\n      this.progress = 100;\r\n    }\r\n    if (this.progress < 1) {\r\n      this.progress = 1;\r\n    }\r\n    this.progressMessage = message ? message + \" \" : \"\";\r\n    if (value != 1 && value != 100) {\r\n      this.progressMessage += `(${value}${count ? \"/\" + count : \"\"})`;\r\n    }\r\n  }\r\n\r\n  /** Toggles the debug view on/off. */\r\n  public toggleDebug() {\r\n    const isDebug = !(this as any).isDebug;\r\n    (this as any).isDebug = isDebug;\r\n    const dialog = document.getElementById(\"salaxyDialog\");\r\n    if (dialog) {\r\n      if (isDebug) {\r\n        dialog.style.width = \"98vw\";\r\n      } else {\r\n        dialog.style.width = null;\r\n      }\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { Culture, DataMapper, DataMapperInfo, Exportable, FileExporter, ExportLogic, InputEnumOption, Translations } from \"@salaxy/core\";\r\nimport { AlertService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller that provides export functionality for any data.\r\n */\r\nexport class ExportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AlertService\", \"UiHelpers\"];\r\n\r\n  /**\r\n   * Maximum length of the data export.\r\n   * Because of the implementation of the enum input, the value is number as a string.\r\n   * -1 has a special meaning as the items that have already been loaded to the preview.\r\n   */\r\n  public maxCount = \"0\";\r\n\r\n  /** Values available in the  */\r\n  public maxCountOptions: InputEnumOption[] = [\r\n    {\r\n      value: \"0\",\r\n      text: Translations.get(\"SALAXY.NG1.ExportComponent.exportLengths.all\"),\r\n    },\r\n    {\r\n      value: \"-1\",\r\n      text: Translations.get(\"SALAXY.NG1.ExportComponent.exportLengths.current\"),\r\n    },\r\n    {\r\n      value: \"1000\",\r\n      text: Translations.get(\"SALAXY.NG1.ExportComponent.exportLengths.short\"),\r\n    },\r\n    {\r\n      value: \"10000\",\r\n      text: Translations.get(\"SALAXY.NG1.ExportComponent.exportLengths.long\"),\r\n    },\r\n  ];\r\n\r\n  /** Locale for exports */\r\n  public localeId: Culture = Culture.Fi;\r\n\r\n  /** Exporters supported by the current API. */\r\n  public exporters: FileExporter[];\r\n\r\n  /** Currently selected exporter. */\r\n  public currentExporter: FileExporter;\r\n\r\n  /** Current mapper once loaded. */\r\n  public mapper: DataMapper<any, any> = null;\r\n\r\n  /** Flag for export in progress: Shows a small spinner in the export button (wizard). */\r\n  public isExporting = false;\r\n\r\n  /** Messages from exports shown in the UI. */\r\n  public exportMessage: string = null;\r\n\r\n  /** All mappers defined by the current Exportable API. */\r\n  public allMappers: DataMapperInfo[] = null;\r\n\r\n  /** Available list item mappers for export */\r\n  public listItemMappers: DataMapperInfo[] = null;\r\n\r\n  /** Available object mappers for export */\r\n  public objectMappers: DataMapperInfo[] = null;\r\n\r\n  private _api: Exportable<any>;\r\n\r\n  constructor(private alertService: AlertService, private uiHelpers: UiHelpers) {\r\n\r\n  }\r\n\r\n  /** Gets or sets the API that implements the Exportable interface. */\r\n  public get api():Exportable<any> {\r\n    return this._api;\r\n  }\r\n  public set api(value: Exportable<any>) {\r\n    this._api = value;\r\n    this.exporters = this.api.exporters ?? [];\r\n    this.currentExporter = this.exporters[0];\r\n    this.allMappers = this.api.getExportMappers();\r\n    this.listItemMappers = this.api.getExportMappers().filter(x => (x.sourceSchema || \"\").indexOf(\"ListItem\") > 0);\r\n    this.objectMappers = this.api.getExportMappers().filter(x => (x.sourceSchema || \"\").indexOf(\"ListItem\") < 0);\r\n  }\r\n\r\n  /**\r\n   * Shows an export dialog for full export.\r\n   * @param api Optional API implementing Exportable that is set to the controller.\r\n   * The API must be set to the controller as property or in this parameter or showExport() will fail\r\n   */\r\n  public showExport(api: Exportable<any>) {\r\n    this.api = api || this.api;\r\n    if (!this.api) {\r\n      throw new Error(\"Exportable API not specified in showExport()\");\r\n    }\r\n    this.currentExporter = this.exporters[0];\r\n    const loader = this.uiHelpers.showLoading();\r\n    this.api.getExportMapper((this.listItemMappers[0] || this.allMappers[0]).uri).then((mapper) => {\r\n      this.mapper = mapper;\r\n      const dialogData = {\r\n        $parent: this,\r\n      };\r\n      loader.dismiss();\r\n      this.uiHelpers.showDialog(\"salaxy-components/modals/export/Export.html\", null, dialogData, null, \"lg\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Executes an immediate quick export - typically directly from a view.\r\n   * Shows the Loader while data is being loaded for the export.\r\n   * @param exporterId Exporter ID. If null, the first exporter in API is used.\r\n   * @param api Optional API implementing Exportable that is set to the controller.\r\n   * The API must be set to the controller as property or in this parameter or quickExport() will fail\r\n   * @param mapper Optional mapper to use in the export. This may be the full DataMapperInfo object or just its uri.\r\n   * If null and mapper has already been set, keeps the current mapper,\r\n   * If null and current mapper is null, sets the first available list mapper, then any mapper. No mappers fails.\r\n   */\r\n  public quickExport(exporterId: string, api: Exportable<any>, mapper: DataMapperInfo | string = null): Promise<void> {\r\n    this.api = api || this.api;\r\n    if (!this.api) {\r\n      throw new Error(\"Exportable API not specified in quickExport()\");\r\n    }\r\n    const loader = this.uiHelpers.showLoading();\r\n    return this.export(mapper, exporterId).then(() => {\r\n      loader.dismiss();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Exports data to desired format.\r\n   * @param mapper The mapper to use in the export. This may be the full DataMapperInfo object or just its uri.\r\n   * If null and mapper has already been set, keeps the current mapper,\r\n   * If null and current mapper is null, sets the first available list mapper, then any mapper. No mappers fails.\r\n   * @param exporterId Identifies the exporter defining the file type and how the result is presented (copy-paste, download, send to external...).\r\n   * If no exporter is selected for the controller, the first exporter in API is used.\r\n   */\r\n  public export(mapper: DataMapperInfo | string = null, exporterId: string = null): Promise<void> {\r\n    if (exporterId) {\r\n      this.currentExporter = this.exporters.find((x) => x.id == exporterId);\r\n    }\r\n    this.currentExporter = this.currentExporter || this.api.exporters[0];\r\n    return this.setExportMapper(mapper).then(() => {\r\n      this.isExporting = true;\r\n      this.exportMessage = Translations.get(\"SALAXY.NG1.ExportComponent.export.creating\");\r\n      const notify = (message, index, count) => {\r\n        this.exportMessage = `${message} (${index + 1}${count ? \"/\" + count : \"\"})`;\r\n      };\r\n      return ExportLogic.getExportData(this.api, this.mapper, Number(this.maxCount), notify).then((rows) => {\r\n        this.isExporting = false;\r\n        this.exportMessage = null;\r\n        if (!rows || !rows.length) {\r\n          this.alertService.addError(Translations.get(\"SALAXY.NG1.ExportComponent.export.noRows\"));\r\n          return;\r\n        }\r\n        this.currentExporter.export(rows, this.localeId);\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Loads the mapper definition and sets the current mapper to it.\r\n   * @param newMapper New mapper to load and set as current: DataMapperInfo or its uri.\r\n   * If null and mapper has already been set, keeps the current mapper,\r\n   * If null and current mapper is null, sets the first available list mapper, then any mapper. No mappers fails.\r\n   */\r\n  public setExportMapper(newMapper: DataMapperInfo | string): Promise<DataMapper<any, any>> {\r\n    let uri = (newMapper as DataMapperInfo)?.uri || newMapper as string;\r\n    if (!uri) {\r\n      if (this.mapper) {\r\n        return Promise.resolve(this.mapper);\r\n      } else {\r\n        uri = (this.listItemMappers[0] || this.allMappers[0]).uri;\r\n      }\r\n    }\r\n    if (this.mapper?.uri == uri) {\r\n      return Promise.resolve(this.mapper);\r\n    }\r\n    this.mapper = null;\r\n    return this.api.getExportMapper(uri).then((mapper) => {\r\n      this.mapper = mapper;\r\n      return mapper;\r\n    });\r\n  }\r\n\r\n  /** Toggles the debug view on/off. */\r\n  public toggleDebug() {\r\n    const isDebug = !(this as any).isDebug;\r\n    (this as any).isDebug = isDebug;\r\n    const dialog = document.getElementById(\"salaxyDialog\");\r\n    if (dialog) {\r\n      if (isDebug) {\r\n        dialog.style.width = \"98vw\";\r\n      } else {\r\n        dialog.style.width = null;\r\n      }\r\n    }\r\n  }\r\n}\r\n","/* Tabulator v5.6.1 (c) Oliver Folkerd 2024 */\nclass CoreFeature{\n\n\tconstructor(table){\n\t\tthis.table = table;\n\t}\n\n\t//////////////////////////////////////////\n\t/////////////// DataLoad /////////////////\n\t//////////////////////////////////////////\n\n\treloadData(data, silent, columnsChanged){\n\t\treturn this.table.dataLoader.load(data, undefined, undefined, undefined, silent, columnsChanged);\n\t}\n\n\t//////////////////////////////////////////\n\t///////////// Localization ///////////////\n\t//////////////////////////////////////////\n\n\tlangText(){\n\t\treturn this.table.modules.localize.getText(...arguments);\n\t}\n\n\tlangBind(){\n\t\treturn this.table.modules.localize.bind(...arguments);\n\t}\n\n\tlangLocale(){\n\t\treturn this.table.modules.localize.getLocale(...arguments);\n\t}\n\n\n\t//////////////////////////////////////////\n\t////////// Inter Table Comms /////////////\n\t//////////////////////////////////////////\n\n\tcommsConnections(){\n\t\treturn this.table.modules.comms.getConnections(...arguments);\n\t}\n\n\tcommsSend(){\n\t\treturn this.table.modules.comms.send(...arguments);\n\t}\n\n\t//////////////////////////////////////////\n\t//////////////// Layout  /////////////////\n\t//////////////////////////////////////////\n\n\tlayoutMode(){\n\t\treturn this.table.modules.layout.getMode();\n\t}\n\n\tlayoutRefresh(force){\n\t\treturn this.table.modules.layout.layout(force);\n\t}\n\n\n\t//////////////////////////////////////////\n\t/////////////// Event Bus ////////////////\n\t//////////////////////////////////////////\n\n\tsubscribe(){\n\t\treturn this.table.eventBus.subscribe(...arguments);\n\t}\n\n\tunsubscribe(){\n\t\treturn this.table.eventBus.unsubscribe(...arguments);\n\t}\n\n\tsubscribed(key){\n\t\treturn this.table.eventBus.subscribed(key);\n\t}\n\n\tsubscriptionChange(){\n\t\treturn this.table.eventBus.subscriptionChange(...arguments);\n\t}\n\n\tdispatch(){\n\t\treturn this.table.eventBus.dispatch(...arguments);\n\t}\n\n\tchain(){\n\t\treturn this.table.eventBus.chain(...arguments);\n\t}\n\n\tconfirm(){\n\t\treturn this.table.eventBus.confirm(...arguments);\n\t}\n\n\tdispatchExternal(){\n\t\treturn this.table.externalEvents.dispatch(...arguments);\n\t}\n\n\tsubscribedExternal(key){\n\t\treturn this.table.externalEvents.subscribed(key);\n\t}\n\n\tsubscriptionChangeExternal(){\n\t\treturn this.table.externalEvents.subscriptionChange(...arguments);\n\t}\n\n\t//////////////////////////////////////////\n\t//////////////// Options /////////////////\n\t//////////////////////////////////////////\n\n\toptions(key){\n\t\treturn this.table.options[key];\n\t}\n\n\tsetOption(key, value){\n\t\tif(typeof value !== \"undefined\"){\n\t\t\tthis.table.options[key] = value;\n\t\t}\n\n\t\treturn this.table.options[key];\n\t}\n\n\t//////////////////////////////////////////\n\t/////////// Deprecation Checks ///////////\n\t//////////////////////////////////////////\n\n\tdeprecationCheck(oldOption, newOption,  convert){\n\t\treturn this.table.deprecationAdvisor.check(oldOption, newOption,  convert);\n\t}\n\n\tdeprecationCheckMsg(oldOption, msg){\n\t\treturn this.table.deprecationAdvisor.checkMsg(oldOption, msg);\n\t}\n\n\tdeprecationMsg(msg){\n\t\treturn this.table.deprecationAdvisor.msg(msg);\n\t}\n\t//////////////////////////////////////////\n\t//////////////// Modules /////////////////\n\t//////////////////////////////////////////\n\n\tmodule(key){\n\t\treturn this.table.module(key);\n\t}\n}\n\nclass Helpers{\n\n\tstatic elVisible(el){\n\t\treturn !(el.offsetWidth <= 0 && el.offsetHeight <= 0);\n\t}\n\n\tstatic elOffset(el){\n\t\tvar box = el.getBoundingClientRect();\n\n\t\treturn {\n\t\t\ttop: box.top + window.pageYOffset - document.documentElement.clientTop,\n\t\t\tleft: box.left + window.pageXOffset - document.documentElement.clientLeft\n\t\t};\n\t}\n\n\tstatic retrieveNestedData(separator, field, data){\n\t\tvar structure = separator ? field.split(separator) : [field],\n\t\tlength = structure.length,\n\t\toutput;\n\n\t\tfor(let i = 0; i < length; i++){\n\n\t\t\tdata = data[structure[i]];\n\n\t\t\toutput = data;\n\n\t\t\tif(!data){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tstatic deepClone(obj, clone, list = []){\n\t\tvar objectProto = {}.__proto__,\n\t\tarrayProto = [].__proto__;\n\n\t\tif (!clone){\n\t\t\tclone = Object.assign(Array.isArray(obj) ? [] : {}, obj);\n\t\t}\n\n\t\tfor(var i in obj) {\n\t\t\tlet subject = obj[i],\n\t\t\tmatch, copy;\n\n\t\t\tif(subject != null && typeof subject === \"object\" && (subject.__proto__ === objectProto || subject.__proto__ === arrayProto)){\n\t\t\t\tmatch = list.findIndex((item) => {\n\t\t\t\t\treturn item.subject === subject;\n\t\t\t\t});\n\n\t\t\t\tif(match > -1){\n\t\t\t\t\tclone[i] = list[match].copy;\n\t\t\t\t}else {\n\t\t\t\t\tcopy = Object.assign(Array.isArray(subject) ? [] : {}, subject);\n\n\t\t\t\t\tlist.unshift({subject, copy});\n\n\t\t\t\t\tclone[i] = this.deepClone(subject, copy, list);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn clone;\n\t}\n}\n\nclass Popup extends CoreFeature{\n\tconstructor(table, element, parent){\n\t\tsuper(table);\n\t\t\n\t\tthis.element = element;\n\t\tthis.container = this._lookupContainer();\n\t\t\n\t\tthis.parent = parent;\n\t\t\n\t\tthis.reversedX = false;\n\t\tthis.childPopup = null;\n\t\tthis.blurable = false;\n\t\tthis.blurCallback = null;\n\t\tthis.blurEventsBound = false;\n\t\tthis.renderedCallback = null;\n\t\t\n\t\tthis.visible = false;\n\t\tthis.hideable = true;\n\t\t\n\t\tthis.element.classList.add(\"tabulator-popup-container\");\n\t\t\n\t\tthis.blurEvent = this.hide.bind(this, false);\n\t\tthis.escEvent = this._escapeCheck.bind(this);\n\t\t\n\t\tthis.destroyBinding = this.tableDestroyed.bind(this);\n\t\tthis.destroyed = false;\n\t}\n\t\n\ttableDestroyed(){\n\t\tthis.destroyed = true;\n\t\tthis.hide(true);\n\t}\n\t\n\t_lookupContainer(){\n\t\tvar container = this.table.options.popupContainer;\n\t\t\n\t\tif(typeof container === \"string\"){\n\t\t\tcontainer = document.querySelector(container);\n\t\t\t\n\t\t\tif(!container){\n\t\t\t\tconsole.warn(\"Menu Error - no container element found matching selector:\",  this.table.options.popupContainer , \"(defaulting to document body)\");\n\t\t\t}\n\t\t}else if (container === true){\n\t\t\tcontainer = this.table.element;\n\t\t}\n\t\t\n\t\tif(container && !this._checkContainerIsParent(container)){\n\t\t\tcontainer = false;\n\t\t\tconsole.warn(\"Menu Error - container element does not contain this table:\",  this.table.options.popupContainer , \"(defaulting to document body)\");\n\t\t}\n\t\t\n\t\tif(!container){\n\t\t\tcontainer = document.body;\n\t\t}\n\t\t\n\t\treturn container;\n\t}\n\t\n\t_checkContainerIsParent(container, element = this.table.element){\n\t\tif(container === element){\n\t\t\treturn true;\n\t\t}else {\n\t\t\treturn element.parentNode ? this._checkContainerIsParent(container, element.parentNode) : false;\n\t\t}\n\t}\n\t\n\trenderCallback(callback){\n\t\tthis.renderedCallback = callback;\n\t}\n\t\n\tcontainerEventCoords(e){\n\t\tvar touch = !(e instanceof MouseEvent);\n\t\t\n\t\tvar x = touch ? e.touches[0].pageX : e.pageX;\n\t\tvar y = touch ? e.touches[0].pageY : e.pageY;\n\t\t\n\t\tif(this.container !== document.body){\n\t\t\tlet parentOffset = Helpers.elOffset(this.container);\n\t\t\t\n\t\t\tx -= parentOffset.left;\n\t\t\ty -= parentOffset.top;\n\t\t}\n\t\t\n\t\treturn {x, y};\n\t}\n\t\n\telementPositionCoords(element, position = \"right\"){\n\t\tvar offset = Helpers.elOffset(element),\n\t\tcontainerOffset, x, y;\n\t\t\n\t\tif(this.container !== document.body){\n\t\t\tcontainerOffset = Helpers.elOffset(this.container);\n\t\t\t\n\t\t\toffset.left -= containerOffset.left;\n\t\t\toffset.top -= containerOffset.top;\n\t\t}\n\t\t\n\t\tswitch(position){\n\t\t\tcase \"right\":\n\t\t\t\tx = offset.left + element.offsetWidth;\n\t\t\t\ty = offset.top - 1;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"bottom\":\n\t\t\t\tx = offset.left;\n\t\t\t\ty = offset.top + element.offsetHeight;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"left\":\n\t\t\t\tx = offset.left;\n\t\t\t\ty = offset.top - 1;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"top\":\n\t\t\t\tx = offset.left;\n\t\t\t\ty = offset.top;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"center\":\n\t\t\t\tx = offset.left + (element.offsetWidth / 2);\n\t\t\t\ty = offset.top + (element.offsetHeight / 2);\n\t\t\t\tbreak;\n\t\t\t\n\t\t}\n\t\t\n\t\treturn {x, y, offset};\n\t}\n\t\n\tshow(origin, position){\n\t\tvar x, y, parentEl, parentOffset, coords;\n\t\t\n\t\tif(this.destroyed || this.table.destroyed){\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\tif(origin instanceof HTMLElement){\n\t\t\tparentEl = origin;\n\t\t\tcoords = this.elementPositionCoords(origin, position);\n\t\t\t\n\t\t\tparentOffset = coords.offset;\n\t\t\tx = coords.x;\n\t\t\ty = coords.y;\n\t\t\t\n\t\t}else if(typeof origin === \"number\"){\n\t\t\tparentOffset = {top:0, left:0};\n\t\t\tx = origin;\n\t\t\ty = position;\n\t\t}else {\n\t\t\tcoords = this.containerEventCoords(origin);\n\t\t\t\n\t\t\tx = coords.x;\n\t\t\ty = coords.y;\n\t\t\t\n\t\t\tthis.reversedX = false;\n\t\t}\n\t\t\n\t\tthis.element.style.top = y + \"px\";\n\t\tthis.element.style.left = x + \"px\";\n\t\t\n\t\tthis.container.appendChild(this.element);\n\t\t\n\t\tif(typeof this.renderedCallback === \"function\"){\n\t\t\tthis.renderedCallback();\n\t\t}\n\t\t\n\t\tthis._fitToScreen(x, y, parentEl, parentOffset, position);\n\t\t\n\t\tthis.visible = true;\n\t\t\n\t\tthis.subscribe(\"table-destroy\", this.destroyBinding);\n\t\t\n\t\tthis.element.addEventListener(\"mousedown\", (e) => {\n\t\t\te.stopPropagation();\n\t\t});\n\t\t\n\t\treturn this;\n\t}\n\t\n\t_fitToScreen(x, y, parentEl, parentOffset, position){\n\t\tvar scrollTop = this.container === document.body ? document.documentElement.scrollTop : this.container.scrollTop;\n\t\t\n\t\t//move menu to start on right edge if it is too close to the edge of the screen\n\t\tif((x + this.element.offsetWidth) >= this.container.offsetWidth || this.reversedX){\n\t\t\tthis.element.style.left = \"\";\n\t\t\t\n\t\t\tif(parentEl){\n\t\t\t\tthis.element.style.right = (this.container.offsetWidth - parentOffset.left) + \"px\";\n\t\t\t}else {\n\t\t\t\tthis.element.style.right = (this.container.offsetWidth - x) + \"px\";\n\t\t\t}\n\t\t\t\n\t\t\tthis.reversedX = true;\n\t\t}\n\t\t\n\t\t//move menu to start on bottom edge if it is too close to the edge of the screen\n\t\tif((y + this.element.offsetHeight) > Math.max(this.container.offsetHeight, scrollTop ? this.container.scrollHeight : 0)) {\n\t\t\tif(parentEl){\n\t\t\t\tswitch(position){\n\t\t\t\t\tcase \"bottom\":\n\t\t\t\t\t\tthis.element.style.top = (parseInt(this.element.style.top) - this.element.offsetHeight - parentEl.offsetHeight - 1) + \"px\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthis.element.style.top = (parseInt(this.element.style.top) - this.element.offsetHeight + parentEl.offsetHeight + 1) + \"px\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tthis.element.style.top = (parseInt(this.element.style.top) - this.element.offsetHeight) + \"px\";\n\t\t\t}\n\t\t}\n\t}\n\t\n\tisVisible(){\n\t\treturn this.visible;\n\t}\n\t\n\thideOnBlur(callback){\n\t\tthis.blurable = true;\n\t\t\n\t\tif(this.visible){\n\t\t\tsetTimeout(() => {\n\t\t\t\tif(this.visible){\n\t\t\t\t\tthis.table.rowManager.element.addEventListener(\"scroll\", this.blurEvent);\n\t\t\t\t\tthis.subscribe(\"cell-editing\", this.blurEvent);\n\t\t\t\t\tdocument.body.addEventListener(\"click\", this.blurEvent);\n\t\t\t\t\tdocument.body.addEventListener(\"contextmenu\", this.blurEvent);\n\t\t\t\t\tdocument.body.addEventListener(\"mousedown\", this.blurEvent);\n\t\t\t\t\twindow.addEventListener(\"resize\", this.blurEvent);\n\t\t\t\t\tdocument.body.addEventListener(\"keydown\", this.escEvent);\n\n\t\t\t\t\tthis.blurEventsBound = true;\n\t\t\t\t}\n\t\t\t}, 100);\n\t\t\t\n\t\t\tthis.blurCallback = callback;\n\t\t}\n\t\t\n\t\treturn this;\n\t}\n\t\n\t_escapeCheck(e){\n\t\tif(e.keyCode == 27){\n\t\t\tthis.hide();\n\t\t}\n\t}\n\t\n\tblockHide(){\n\t\tthis.hideable = false;\n\t}\n\t\n\trestoreHide(){\n\t\tthis.hideable = true;\n\t}\n\t\n\thide(silent = false){\n\t\tif(this.visible && this.hideable){\n\t\t\tif(this.blurable && this.blurEventsBound){\n\t\t\t\tdocument.body.removeEventListener(\"keydown\", this.escEvent);\n\t\t\t\tdocument.body.removeEventListener(\"click\", this.blurEvent);\n\t\t\t\tdocument.body.removeEventListener(\"contextmenu\", this.blurEvent);\n\t\t\t\tdocument.body.removeEventListener(\"mousedown\", this.blurEvent);\n\t\t\t\twindow.removeEventListener(\"resize\", this.blurEvent);\n\t\t\t\tthis.table.rowManager.element.removeEventListener(\"scroll\", this.blurEvent);\n\t\t\t\tthis.unsubscribe(\"cell-editing\", this.blurEvent);\n\n\t\t\t\tthis.blurEventsBound = false;\n\t\t\t}\n\t\t\t\n\t\t\tif(this.childPopup){\n\t\t\t\tthis.childPopup.hide();\n\t\t\t}\n\t\t\t\n\t\t\tif(this.parent){\n\t\t\t\tthis.parent.childPopup = null;\n\t\t\t}\n\t\t\t\n\t\t\tif(this.element.parentNode){\n\t\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t\t}\n\t\t\t\n\t\t\tthis.visible = false;\n\t\t\t\n\t\t\tif(this.blurCallback && !silent){\n\t\t\t\tthis.blurCallback();\n\t\t\t}\n\t\t\t\n\t\t\tthis.unsubscribe(\"table-destroy\", this.destroyBinding);\n\t\t}\n\t\t\n\t\treturn this;\n\t}\n\t\n\tchild(element){\n\t\tif(this.childPopup){\n\t\t\tthis.childPopup.hide();\n\t\t}\n\t\t\n\t\tthis.childPopup = new Popup(this.table, element, this);\n\t\t\n\t\treturn this.childPopup;\n\t}\n}\n\nclass Module extends CoreFeature{\n\t\n\tconstructor(table, name){\n\t\tsuper(table);\n\t\t\n\t\tthis._handler = null;\n\t}\n\t\n\tinitialize(){\n\t\t// setup module when table is initialized, to be overridden in module\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t////// Options Registration ///////\n\t///////////////////////////////////\n\t\n\tregisterTableOption(key, value){\n\t\tthis.table.optionsList.register(key, value);\n\t}\n\t\n\tregisterColumnOption(key, value){\n\t\tthis.table.columnManager.optionsList.register(key, value);\n\t}\n\t\n\t///////////////////////////////////\n\t/// Public Function Registration ///\n\t///////////////////////////////////\n\t\n\tregisterTableFunction(name, func){\n\t\tif(typeof this.table[name] === \"undefined\"){\n\t\t\tthis.table[name] = (...args) => {\n\t\t\t\tthis.table.initGuard(name);\n\t\t\t\t\n\t\t\t\treturn func(...args);\n\t\t\t};\n\t\t}else {\n\t\t\tconsole.warn(\"Unable to bind table function, name already in use\", name);\n\t\t}\n\t}\n\t\n\tregisterComponentFunction(component, func, handler){\n\t\treturn this.table.componentFunctionBinder.bind(component, func, handler);\n\t}\n\t\n\t///////////////////////////////////\n\t////////// Data Pipeline //////////\n\t///////////////////////////////////\n\t\n\tregisterDataHandler(handler, priority){\n\t\tthis.table.rowManager.registerDataPipelineHandler(handler, priority);\n\t\tthis._handler = handler;\n\t}\n\t\n\tregisterDisplayHandler(handler, priority){\n\t\tthis.table.rowManager.registerDisplayPipelineHandler(handler, priority);\n\t\tthis._handler = handler;\n\t}\n\t\n\tdisplayRows(adjust){\n\t\tvar index = this.table.rowManager.displayRows.length - 1, \n\t\tlookupIndex;\n\t\t\n\t\tif(this._handler){\n\t\t\tlookupIndex = this.table.rowManager.displayPipeline.findIndex((item) => {\n\t\t\t\treturn item.handler === this._handler;\n\t\t\t});\n\n\t\t\tif(lookupIndex > -1){\n\t\t\t\tindex = lookupIndex;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(adjust){\n\t\t\tindex = index + adjust;\n\t\t}\n\n\t\tif(this._handler){\n\t\t\tif(index > -1){\n\t\t\t\treturn this.table.rowManager.getDisplayRows(index);\n\t\t\t}else {\n\t\t\t\treturn this.activeRows();\n\t\t\t}\n\t\t}\t\n\t}\n\t\n\tactiveRows(){\n\t\treturn this.table.rowManager.activeRows;\n\t}\n\t\n\trefreshData(renderInPosition, handler){\n\t\tif(!handler){\n\t\t\thandler = this._handler;\n\t\t}\n\t\t\n\t\tif(handler){\n\t\t\tthis.table.rowManager.refreshActiveData(handler, false, renderInPosition);\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t//////// Footer Management ////////\n\t///////////////////////////////////\n\t\n\tfooterAppend(element){\n\t\treturn this.table.footerManager.append(element);\n\t}\n\t\n\tfooterPrepend(element){\n\t\treturn this.table.footerManager.prepend(element);\n\t}\n\t\n\tfooterRemove(element){\n\t\treturn this.table.footerManager.remove(element);\n\t} \n\t\n\t///////////////////////////////////\n\t//////// Popups Management ////////\n\t///////////////////////////////////\n\t\n\tpopup(menuEl, menuContainer){\n\t\treturn new Popup(this.table, menuEl, menuContainer);\n\t}\n\t\n\t///////////////////////////////////\n\t//////// Alert Management ////////\n\t///////////////////////////////////\n\t\n\talert(content, type){\n\t\treturn this.table.alertManager.alert(content, type);\n\t}\n\t\n\tclearAlert(){\n\t\treturn this.table.alertManager.clear();\n\t}\n\t\n}\n\nvar defaultAccessors = {};\n\nclass Accessor extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.allowedTypes = [\"\", \"data\", \"download\", \"clipboard\", \"print\", \"htmlOutput\"]; //list of accessor types\n\n\t\tthis.registerColumnOption(\"accessor\");\n\t\tthis.registerColumnOption(\"accessorParams\");\n\t\tthis.registerColumnOption(\"accessorData\");\n\t\tthis.registerColumnOption(\"accessorDataParams\");\n\t\tthis.registerColumnOption(\"accessorDownload\");\n\t\tthis.registerColumnOption(\"accessorDownloadParams\");\n\t\tthis.registerColumnOption(\"accessorClipboard\");\n\t\tthis.registerColumnOption(\"accessorClipboardParams\");\n\t\tthis.registerColumnOption(\"accessorPrint\");\n\t\tthis.registerColumnOption(\"accessorPrintParams\");\n\t\tthis.registerColumnOption(\"accessorHtmlOutput\");\n\t\tthis.registerColumnOption(\"accessorHtmlOutputParams\");\n\t}\n\n\tinitialize(){\n\t\tthis.subscribe(\"column-layout\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"row-data-retrieve\", this.transformRow.bind(this));\n\t}\n\n\t//initialize column accessor\n\tinitializeColumn(column){\n\t\tvar match = false,\n\t\tconfig = {};\n\n\t\tthis.allowedTypes.forEach((type) => {\n\t\t\tvar key = \"accessor\" + (type.charAt(0).toUpperCase() + type.slice(1)),\n\t\t\taccessor;\n\n\t\t\tif(column.definition[key]){\n\t\t\t\taccessor = this.lookupAccessor(column.definition[key]);\n\n\t\t\t\tif(accessor){\n\t\t\t\t\tmatch = true;\n\n\t\t\t\t\tconfig[key] = {\n\t\t\t\t\t\taccessor:accessor,\n\t\t\t\t\t\tparams: column.definition[key + \"Params\"] || {},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif(match){\n\t\t\tcolumn.modules.accessor = config;\n\t\t}\n\t}\n\n\tlookupAccessor(value){\n\t\tvar accessor = false;\n\n\t\t//set column accessor\n\t\tswitch(typeof value){\n\t\t\tcase \"string\":\n\t\t\t\tif(Accessor.accessors[value]){\n\t\t\t\t\taccessor = Accessor.accessors[value];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Accessor Error - No such accessor found, ignoring: \", value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\taccessor = value;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn accessor;\n\t}\n\n\t//apply accessor to row\n\ttransformRow(row, type){\n\t\tvar key = \"accessor\" + (type.charAt(0).toUpperCase() + type.slice(1)),\n\t\trowComponent = row.getComponent();\n\n\t\t//clone data object with deep copy to isolate internal data from returned result\n\t\tvar data = Helpers.deepClone(row.data || {});\n\n\t\tthis.table.columnManager.traverse(function(column){\n\t\t\tvar value, accessor, params, colComponent;\n\n\t\t\tif(column.modules.accessor){\n\n\t\t\t\taccessor = column.modules.accessor[key] || column.modules.accessor.accessor || false;\n\n\t\t\t\tif(accessor){\n\t\t\t\t\tvalue = column.getFieldValue(data);\n\n\t\t\t\t\tif(value != \"undefined\"){\n\t\t\t\t\t\tcolComponent = column.getComponent();\n\t\t\t\t\t\tparams = typeof accessor.params === \"function\" ? accessor.params(value, data, type, colComponent, rowComponent) : accessor.params;\n\t\t\t\t\t\tcolumn.setFieldValue(data, accessor.accessor(value, data, type, params, colComponent, rowComponent));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn data;\n\t}\n}\n\n//load defaults\nAccessor.moduleName = \"accessor\";\nAccessor.accessors = defaultAccessors;\n\nvar defaultConfig = {\n\tmethod: \"GET\",\n};\n\nfunction generateParamsList(data, prefix){\n\tvar output = [];\n\n\tprefix = prefix || \"\";\n\n\tif(Array.isArray(data)){\n\t\tdata.forEach((item, i) => {\n\t\t\toutput = output.concat(generateParamsList(item, prefix ? prefix + \"[\" + i + \"]\" : i));\n\t\t});\n\t}else if (typeof data === \"object\"){\n\t\tfor (var key in data){\n\t\t\toutput = output.concat(generateParamsList(data[key], prefix ? prefix + \"[\" + key + \"]\" : key));\n\t\t}\n\t}else {\n\t\toutput.push({key:prefix, value:data});\n\t}\n\n\treturn output;\n}\n\nfunction serializeParams(params){\n\tvar output = generateParamsList(params),\n\tencoded = [];\n\n\toutput.forEach(function(item){\n\t\tencoded.push(encodeURIComponent(item.key) + \"=\" + encodeURIComponent(item.value));\n\t});\n\n\treturn encoded.join(\"&\");\n}\n\nfunction urlBuilder(url, config, params){\n\tif(url){\n\t\tif(params && Object.keys(params).length){\n\t\t\tif(!config.method || config.method.toLowerCase() == \"get\"){\n\t\t\t\tconfig.method = \"get\";\n\n\t\t\t\turl += (url.includes(\"?\") ? \"&\" : \"?\") + serializeParams(params);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn url;\n}\n\nfunction defaultLoaderPromise(url, config, params){\n\tvar contentType;\n\n\treturn new Promise((resolve, reject) => {\n\t\t//set url\n\t\turl = this.urlGenerator.call(this.table, url, config, params);\n\n\t\t//set body content if not GET request\n\t\tif(config.method.toUpperCase() != \"GET\"){\n\t\t\tcontentType = typeof this.table.options.ajaxContentType === \"object\" ?  this.table.options.ajaxContentType : this.contentTypeFormatters[this.table.options.ajaxContentType];\n\t\t\tif(contentType){\n\n\t\t\t\tfor(var key in contentType.headers){\n\t\t\t\t\tif(!config.headers){\n\t\t\t\t\t\tconfig.headers = {};\n\t\t\t\t\t}\n\n\t\t\t\t\tif(typeof config.headers[key] === \"undefined\"){\n\t\t\t\t\t\tconfig.headers[key] = contentType.headers[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconfig.body = contentType.body.call(this, url, config, params);\n\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Ajax Error - Invalid ajaxContentType value:\", this.table.options.ajaxContentType);\n\t\t\t}\n\t\t}\n\n\t\tif(url){\n\t\t\t//configure headers\n\t\t\tif(typeof config.headers === \"undefined\"){\n\t\t\t\tconfig.headers = {};\n\t\t\t}\n\n\t\t\tif(typeof config.headers.Accept === \"undefined\"){\n\t\t\t\tconfig.headers.Accept = \"application/json\";\n\t\t\t}\n\n\t\t\tif(typeof config.headers[\"X-Requested-With\"] === \"undefined\"){\n\t\t\t\tconfig.headers[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t}\n\n\t\t\tif(typeof config.mode === \"undefined\"){\n\t\t\t\tconfig.mode = \"cors\";\n\t\t\t}\n\n\t\t\tif(config.mode == \"cors\"){\n\t\t\t\tif(typeof config.headers[\"Origin\"] === \"undefined\"){\n\t\t\t\t\tconfig.headers[\"Origin\"] = window.location.origin;\n\t\t\t\t}\n        \n\t\t\t\tif(typeof config.credentials === \"undefined\"){\n\t\t\t\t\tconfig.credentials = 'same-origin';\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(typeof config.credentials === \"undefined\"){\n\t\t\t\t\tconfig.credentials = 'include';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//send request\n\t\t\tfetch(url, config)\n\t\t\t\t.then((response)=>{\n\t\t\t\t\tif(response.ok) {\n\t\t\t\t\t\tresponse.json()\n\t\t\t\t\t\t\t.then((data)=>{\n\t\t\t\t\t\t\t\tresolve(data);\n\t\t\t\t\t\t\t}).catch((error)=>{\n\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t\tconsole.warn(\"Ajax Load Error - Invalid JSON returned\", error);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.error(\"Ajax Load Error - Connection Error: \" + response.status, response.statusText);\n\t\t\t\t\t\treject(response);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((error)=>{\n\t\t\t\t\tconsole.error(\"Ajax Load Error - Connection Error: \", error);\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t}else {\n\t\t\tconsole.warn(\"Ajax Load Error - No URL Set\");\n\t\t\tresolve([]);\n\t\t}\n\t});\n}\n\nfunction generateParamsList$1(data, prefix){\n\tvar output = [];\n\n\tprefix = prefix || \"\";\n\n\tif(Array.isArray(data)){\n\t\tdata.forEach((item, i) => {\n\t\t\toutput = output.concat(generateParamsList$1(item, prefix ? prefix + \"[\" + i + \"]\" : i));\n\t\t});\n\t}else if (typeof data === \"object\"){\n\t\tfor (var key in data){\n\t\t\toutput = output.concat(generateParamsList$1(data[key], prefix ? prefix + \"[\" + key + \"]\" : key));\n\t\t}\n\t}else {\n\t\toutput.push({key:prefix, value:data});\n\t}\n\n\treturn output;\n}\n\nvar defaultContentTypeFormatters = {\n\t\"json\":{\n\t\theaders:{\n\t\t\t'Content-Type': 'application/json',\n\t\t},\n\t\tbody:function(url, config, params){\n\t\t\treturn JSON.stringify(params);\n\t\t},\n\t},\n\t\"form\":{\n\t\theaders:{\n\t\t},\n\t\tbody:function(url, config, params){\n\n\t\t\tvar output = generateParamsList$1(params),\n\t\t\tform = new FormData();\n\n\t\t\toutput.forEach(function(item){\n\t\t\t\tform.append(item.key, item.value);\n\t\t\t});\n\n\t\t\treturn form;\n\t\t},\n\t},\n};\n\nclass Ajax extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.config = {}; //hold config object for ajax request\n\t\tthis.url = \"\"; //request URL\n\t\tthis.urlGenerator = false;\n\t\tthis.params = false; //request parameters\n\t\t\n\t\tthis.loaderPromise = false;\n\t\t\n\t\tthis.registerTableOption(\"ajaxURL\", false); //url for ajax loading\n\t\tthis.registerTableOption(\"ajaxURLGenerator\", false);\n\t\tthis.registerTableOption(\"ajaxParams\", {});  //params for ajax loading\n\t\tthis.registerTableOption(\"ajaxConfig\", \"get\"); //ajax request type\n\t\tthis.registerTableOption(\"ajaxContentType\", \"form\"); //ajax request type\n\t\tthis.registerTableOption(\"ajaxRequestFunc\", false); //promise function\n\t\t\n\t\tthis.registerTableOption(\"ajaxRequesting\", function(){});\n\t\tthis.registerTableOption(\"ajaxResponse\", false);\n\t\t\n\t\tthis.contentTypeFormatters = Ajax.contentTypeFormatters;\n\t}\n\t\n\t//initialize setup options\n\tinitialize(){\n\t\tthis.loaderPromise = this.table.options.ajaxRequestFunc || Ajax.defaultLoaderPromise;\n\t\tthis.urlGenerator = this.table.options.ajaxURLGenerator || Ajax.defaultURLGenerator;\n\t\t\n\t\tif(this.table.options.ajaxURL){\n\t\t\tthis.setUrl(this.table.options.ajaxURL);\n\t\t}\n\n\n\t\tthis.setDefaultConfig(this.table.options.ajaxConfig);\n\t\t\n\t\tthis.registerTableFunction(\"getAjaxUrl\", this.getUrl.bind(this));\n\t\t\n\t\tthis.subscribe(\"data-loading\", this.requestDataCheck.bind(this));\n\t\tthis.subscribe(\"data-params\", this.requestParams.bind(this));\n\t\tthis.subscribe(\"data-load\", this.requestData.bind(this));\n\t}\n\t\n\trequestParams(data, config, silent, params){\n\t\tvar ajaxParams = this.table.options.ajaxParams;\n\t\t\n\t\tif(ajaxParams){\n\t\t\tif(typeof ajaxParams === \"function\"){\n\t\t\t\tajaxParams = ajaxParams.call(this.table);\n\t\t\t}\n\t\t\t\n\t\t\tparams = Object.assign(Object.assign({}, ajaxParams), params);\n\t\t}\t\t\n\t\t\n\t\treturn params;\n\t}\n\t\n\trequestDataCheck(data, params, config, silent){\n\t\treturn !!((!data && this.url) || typeof data === \"string\");\n\t}\n\t\n\trequestData(url, params, config, silent, previousData){\n\t\tvar ajaxConfig;\n\t\t\n\t\tif(!previousData && this.requestDataCheck(url)){\n\t\t\tif(url){\n\t\t\t\tthis.setUrl(url);\n\t\t\t}\n\t\t\t\n\t\t\tajaxConfig = this.generateConfig(config);\n\t\t\t\n\t\t\treturn this.sendRequest(this.url, params, ajaxConfig);\n\t\t}else {\n\t\t\treturn previousData;\n\t\t}\n\t}\n\t\n\tsetDefaultConfig(config = {}){\n\t\tthis.config = Object.assign({}, Ajax.defaultConfig);\n\n\t\tif(typeof config == \"string\"){\n\t\t\tthis.config.method = config;\n\t\t}else {\n\t\t\tObject.assign(this.config, config);\n\t\t}\n\t}\n\t\n\t//load config object\n\tgenerateConfig(config = {}){\n\t\tvar ajaxConfig = Object.assign({}, this.config);\n\t\t\n\t\tif(typeof config == \"string\"){\n\t\t\tajaxConfig.method = config;\n\t\t}else {\n\t\t\tObject.assign(ajaxConfig, config);\n\t\t}\n\t\t\n\t\treturn ajaxConfig;\n\t}\n\t\n\t//set request url\n\tsetUrl(url){\n\t\tthis.url = url;\n\t}\n\t\n\t//get request url\n\tgetUrl(){\n\t\treturn this.url;\n\t}\n\t\n\t//send ajax request\n\tsendRequest(url, params, config){\n\t\tif(this.table.options.ajaxRequesting.call(this.table, url, params) !== false){\n\t\t\treturn this.loaderPromise(url, config, params)\n\t\t\t\t.then((data)=>{\n\t\t\t\t\tif(this.table.options.ajaxResponse){\n\t\t\t\t\t\tdata = this.table.options.ajaxResponse.call(this.table, url, params, data);\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\treturn data;\n\t\t\t\t});\n\t\t}else {\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n}\n\nAjax.moduleName = \"ajax\";\n\n//load defaults\nAjax.defaultConfig = defaultConfig;\nAjax.defaultURLGenerator = urlBuilder;\nAjax.defaultLoaderPromise = defaultLoaderPromise;\nAjax.contentTypeFormatters = defaultContentTypeFormatters;\n\nvar defaultPasteActions = {\n\treplace:function(data){\n\t\treturn this.table.setData(data);\n\t},\n\tupdate:function(data){\n\t\treturn this.table.updateOrAddData(data);\n\t},\n\tinsert:function(data){\n\t\treturn this.table.addData(data);\n\t},\n\trange:function(data){\n\t\tvar rows = [],\n\t\trange = this.table.modules.selectRange.activeRange,\n\t\tsingleCell = false,\n\t\tbounds, startCell, startRow, rowWidth, dataLength;\n\n\t\tdataLength = data.length;\n\t\t\n\t\tif(range){\n\t\t\tbounds = range.getBounds();\n\t\t\tstartCell = bounds.start;\n\t\t\t\n\t\t\tif(bounds.start === bounds.end){\n\t\t\t\tsingleCell = true;\n\t\t\t}\n\t\t\t\n\t\t\tif(startCell){\n\t\t\t\trows = this.table.rowManager.activeRows.slice();\n\t\t\t\tstartRow = rows.indexOf(startCell.row);\n\n\t\t\t\tif(singleCell){\n\t\t\t\t\trowWidth = data.length;\n\t\t\t\t}else {\n\t\t\t\t\trowWidth = (rows.indexOf(bounds.end.row) - startRow) + 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif(startRow >-1){\n\t\t\t\t\tthis.table.blockRedraw();\n\t\t\t\t\t\n\t\t\t\t\trows = rows.slice(startRow, startRow + rowWidth);\n\t\t\t\t\t\n\t\t\t\t\trows.forEach((row, i) => {\n\t\t\t\t\t\trow.updateData(data[i % dataLength]);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.table.restoreRedraw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn rows;\n\t}\n};\n\nvar defaultPasteParsers = {\n\ttable:function(clipboard){\n\t\tvar data = [],\n\t\theaderFindSuccess = true,\n\t\tcolumns = this.table.columnManager.columns,\n\t\tcolumnMap = [],\n\t\trows = [];\n\t\t\n\t\t//get data from clipboard into array of columns and rows.\n\t\tclipboard = clipboard.split(\"\\n\");\n\t\t\n\t\tclipboard.forEach(function(row){\n\t\t\tdata.push(row.split(\"\\t\"));\n\t\t});\n\t\t\n\t\tif(data.length && !(data.length === 1 && data[0].length < 2)){\n\t\t\t\n\t\t\t//check if headers are present by title\n\t\t\tdata[0].forEach(function(value){\n\t\t\t\tvar column = columns.find(function(column){\n\t\t\t\t\treturn value && column.definition.title && value.trim() && column.definition.title.trim() === value.trim();\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif(column){\n\t\t\t\t\tcolumnMap.push(column);\n\t\t\t\t}else {\n\t\t\t\t\theaderFindSuccess = false;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t//check if column headers are present by field\n\t\t\tif(!headerFindSuccess){\n\t\t\t\theaderFindSuccess = true;\n\t\t\t\tcolumnMap = [];\n\t\t\t\t\n\t\t\t\tdata[0].forEach(function(value){\n\t\t\t\t\tvar column = columns.find(function(column){\n\t\t\t\t\t\treturn value && column.field && value.trim() && column.field.trim() === value.trim();\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif(column){\n\t\t\t\t\t\tcolumnMap.push(column);\n\t\t\t\t\t}else {\n\t\t\t\t\t\theaderFindSuccess = false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif(!headerFindSuccess){\n\t\t\t\t\tcolumnMap = this.table.columnManager.columnsByIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t//remove header row if found\n\t\t\tif(headerFindSuccess){\n\t\t\t\tdata.shift();\n\t\t\t}\n\t\t\t\n\t\t\tdata.forEach(function(item){\n\t\t\t\tvar row = {};\n\t\t\t\t\n\t\t\t\titem.forEach(function(value, i){\n\t\t\t\t\tif(columnMap[i]){\n\t\t\t\t\t\trow[columnMap[i].field] = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\trows.push(row);\n\t\t\t});\n\t\t\t\n\t\t\treturn rows;\n\t\t}else {\n\t\t\treturn false;\n\t\t}\n\t},\n\trange:function(clipboard){\n\t\tvar data = [],\n\t\trows = [],\n\t\trange = this.table.modules.selectRange.activeRange,\n\t\tsingleCell = false,\n\t\tbounds, startCell, colWidth, columnMap, startCol;\n\t\t\n\t\tif(range){\n\t\t\tbounds = range.getBounds();\n\t\t\tstartCell = bounds.start;\n\n\t\t\tif(bounds.start === bounds.end){\n\t\t\t\tsingleCell = true;\n\t\t\t}\n\t\t\t\n\t\t\tif(startCell){\n\t\t\t\t//get data from clipboard into array of columns and rows.\n\t\t\t\tclipboard = clipboard.split(\"\\n\");\n\t\t\t\t\n\t\t\t\tclipboard.forEach(function(row){\n\t\t\t\t\tdata.push(row.split(\"\\t\"));\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif(data.length){\n\t\t\t\t\tcolumnMap = this.table.columnManager.getVisibleColumnsByIndex();\n\t\t\t\t\tstartCol = columnMap.indexOf(startCell.column);\n\n\t\t\t\t\tif(startCol > -1){\n\t\t\t\t\t\tif(singleCell){\n\t\t\t\t\t\t\tcolWidth = data[0].length;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tcolWidth = (columnMap.indexOf(bounds.end.column) - startCol) + 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcolumnMap = columnMap.slice(startCol, startCol + colWidth);\n\n\t\t\t\t\t\tdata.forEach((item) => {\n\t\t\t\t\t\t\tvar row = {};\n\t\t\t\t\t\t\tvar itemLength = item.length;\n\n\t\t\t\t\t\t\tcolumnMap.forEach(function(col, i){\n\t\t\t\t\t\t\t\trow[col.field] = item[i % itemLength];\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\trows.push(row);\t\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn rows;\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n};\n\nclass Clipboard extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.mode = true;\n\t\tthis.pasteParser = function(){};\n\t\tthis.pasteAction = function(){};\n\t\tthis.customSelection = false;\n\t\tthis.rowRange = false;\n\t\tthis.blocked = true; //block copy actions not originating from this command\n\n\t\tthis.registerTableOption(\"clipboard\", false); //enable clipboard\n\t\tthis.registerTableOption(\"clipboardCopyStyled\", true); //formatted table data\n\t\tthis.registerTableOption(\"clipboardCopyConfig\", false); //clipboard config\n\t\tthis.registerTableOption(\"clipboardCopyFormatter\", false); //DEPRECATED - REMOVE in 5.0\n\t\tthis.registerTableOption(\"clipboardCopyRowRange\", \"active\"); //restrict clipboard to visible rows only\n\t\tthis.registerTableOption(\"clipboardPasteParser\", \"table\"); //convert pasted clipboard data to rows\n\t\tthis.registerTableOption(\"clipboardPasteAction\", \"insert\"); //how to insert pasted data into the table\n\n\t\tthis.registerColumnOption(\"clipboard\");\n\t\tthis.registerColumnOption(\"titleClipboard\");\n\t}\n\n\tinitialize(){\n\t\tthis.mode = this.table.options.clipboard;\n\n\t\tthis.rowRange = this.table.options.clipboardCopyRowRange;\n\n\t\tif(this.mode === true || this.mode === \"copy\"){\n\t\t\tthis.table.element.addEventListener(\"copy\", (e) => {\n\t\t\t\tvar plain, html, list;\n\n\t\t\t\tif(!this.blocked){\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\tif(this.customSelection){\n\t\t\t\t\t\tplain = this.customSelection;\n\n\t\t\t\t\t\tif(this.table.options.clipboardCopyFormatter){\n\t\t\t\t\t\t\tplain = this.table.options.clipboardCopyFormatter(\"plain\", plain);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\n\t\t\t\t\t\tlist = this.table.modules.export.generateExportList(this.table.options.clipboardCopyConfig, this.table.options.clipboardCopyStyled, this.rowRange, \"clipboard\");\n\n\t\t\t\t\t\thtml = this.table.modules.export.generateHTMLTable(list);\n\t\t\t\t\t\tplain = html ? this.generatePlainContent(list) : \"\";\n\n\t\t\t\t\t\tif(this.table.options.clipboardCopyFormatter){\n\t\t\t\t\t\t\tplain = this.table.options.clipboardCopyFormatter(\"plain\", plain);\n\t\t\t\t\t\t\thtml = this.table.options.clipboardCopyFormatter(\"html\", html);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (window.clipboardData && window.clipboardData.setData) {\n\t\t\t\t\t\twindow.clipboardData.setData('Text', plain);\n\t\t\t\t\t} else if (e.clipboardData && e.clipboardData.setData) {\n\t\t\t\t\t\te.clipboardData.setData('text/plain', plain);\n\t\t\t\t\t\tif(html){\n\t\t\t\t\t\t\te.clipboardData.setData('text/html', html);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (e.originalEvent && e.originalEvent.clipboardData.setData) {\n\t\t\t\t\t\te.originalEvent.clipboardData.setData('text/plain', plain);\n\t\t\t\t\t\tif(html){\n\t\t\t\t\t\t\te.originalEvent.clipboardData.setData('text/html', html);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.dispatchExternal(\"clipboardCopied\", plain, html);\n\n\t\t\t\t\tthis.reset();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif(this.mode === true || this.mode === \"paste\"){\n\t\t\tthis.table.element.addEventListener(\"paste\", (e) => {\n\t\t\t\tthis.paste(e);\n\t\t\t});\n\t\t}\n\n\t\tthis.setPasteParser(this.table.options.clipboardPasteParser);\n\t\tthis.setPasteAction(this.table.options.clipboardPasteAction);\n\n\t\tthis.registerTableFunction(\"copyToClipboard\", this.copy.bind(this));\n\t}\n\n\treset(){\n\t\tthis.blocked = true;\n\t\tthis.customSelection = false;\n\t}\n\n\tgeneratePlainContent (list) {\n\t\tvar output = [];\n\n\t\tlist.forEach((row) => {\n\t\t\tvar rowData = [];\n\n\t\t\trow.columns.forEach((col) => {\n\t\t\t\tvar value = \"\";\n\n\t\t\t\tif(col){\n\n\t\t\t\t\tif(row.type === \"group\"){\n\t\t\t\t\t\tcol.value = col.component.getKey();\n\t\t\t\t\t}\n\n\t\t\t\t\tif(col.value === null){\n\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t}else {\n\t\t\t\t\t\tswitch(typeof col.value){\n\t\t\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\t\t\tvalue = JSON.stringify(col.value);\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tvalue = col.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trowData.push(value);\n\t\t\t});\n\n\t\t\toutput.push(rowData.join(\"\\t\"));\n\t\t});\n\n\t\treturn output.join(\"\\n\");\n\t}\n\n\tcopy (range, internal) {\n\t\tvar sel, textRange;\n\t\tthis.blocked = false;\n\t\tthis.customSelection = false;\n\t\n\n\t\tif (this.mode === true || this.mode === \"copy\") {\n\n\t\t\tthis.rowRange = range || this.table.options.clipboardCopyRowRange;\n\n\t\t\tif (typeof window.getSelection != \"undefined\" && typeof document.createRange != \"undefined\") {\n\t\t\t\trange = document.createRange();\n\t\t\t\trange.selectNodeContents(this.table.element);\n\t\t\t\tsel = window.getSelection();\n\n\t\t\t\tif (sel.toString() && internal) {\n\t\t\t\t\tthis.customSelection = sel.toString();\n\t\t\t\t}\n\n\t\t\t\tsel.removeAllRanges();\n\t\t\t\tsel.addRange(range);\n\t\t\t} else if (typeof document.selection != \"undefined\" && typeof document.body.createTextRange != \"undefined\") {\n\t\t\t\ttextRange = document.body.createTextRange();\n\t\t\t\ttextRange.moveToElementText(this.table.element);\n\t\t\t\ttextRange.select();\n\t\t\t}\n\n\t\t\tdocument.execCommand('copy');\n\n\t\t\tif (sel) {\n\t\t\t\tsel.removeAllRanges();\n\t\t\t}\n\t\t}\n\t}\n\n\t//PASTE EVENT HANDLING\n\tsetPasteAction(action){\n\n\t\tswitch(typeof action){\n\t\t\tcase \"string\":\n\t\t\t\tthis.pasteAction = Clipboard.pasteActions[action];\n\n\t\t\t\tif(!this.pasteAction){\n\t\t\t\t\tconsole.warn(\"Clipboard Error - No such paste action found:\", action);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\tthis.pasteAction = action;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tsetPasteParser(parser){\n\t\tswitch(typeof parser){\n\t\t\tcase \"string\":\n\t\t\t\tthis.pasteParser = Clipboard.pasteParsers[parser];\n\n\t\t\t\tif(!this.pasteParser){\n\t\t\t\t\tconsole.warn(\"Clipboard Error - No such paste parser found:\", parser);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\tthis.pasteParser = parser;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tpaste(e){\n\t\tvar data, rowData, rows;\n\n\t\tif(this.checkPasteOrigin(e)){\n\n\t\t\tdata = this.getPasteData(e);\n\n\t\t\trowData = this.pasteParser.call(this, data);\n\n\t\t\tif(rowData){\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif(this.table.modExists(\"mutator\")){\n\t\t\t\t\trowData = this.mutateData(rowData);\n\t\t\t\t}\n\n\t\t\t\trows = this.pasteAction.call(this, rowData);\n\n\t\t\t\tthis.dispatchExternal(\"clipboardPasted\", data, rowData, rows);\n\t\t\t}else {\n\t\t\t\tthis.dispatchExternal(\"clipboardPasteError\", data);\n\t\t\t}\n\t\t}\n\t}\n\n\tmutateData(data){\n\t\tvar output = [];\n\n\t\tif(Array.isArray(data)){\n\t\t\tdata.forEach((row) => {\n\t\t\t\toutput.push(this.table.modules.mutator.transformRow(row, \"clipboard\"));\n\t\t\t});\n\t\t}else {\n\t\t\toutput = data;\n\t\t}\n\n\t\treturn output;\n\t}\n\n\n\tcheckPasteOrigin(e){\n\t\tvar valid = true;\n\t\tvar blocked = this.confirm(\"clipboard-paste\", [e]);\n\n\t\tif(blocked || ![\"DIV\", \"SPAN\"].includes(e.target.tagName)){\n\t\t\tvalid = false;\n\t\t}\n\n\t\treturn valid;\n\t}\n\n\tgetPasteData(e){\n\t\tvar data;\n\n\t\tif (window.clipboardData && window.clipboardData.getData) {\n\t\t\tdata = window.clipboardData.getData('Text');\n\t\t} else if (e.clipboardData && e.clipboardData.getData) {\n\t\t\tdata = e.clipboardData.getData('text/plain');\n\t\t} else if (e.originalEvent && e.originalEvent.clipboardData.getData) {\n\t\t\tdata = e.originalEvent.clipboardData.getData('text/plain');\n\t\t}\n\n\t\treturn data;\n\t}\n}\n\nClipboard.moduleName = \"clipboard\";\n\n//load defaults\nClipboard.pasteActions = defaultPasteActions;\nClipboard.pasteParsers = defaultPasteParsers;\n\nclass CalcComponent{\n\tconstructor (row){\n\t\tthis._row = row;\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function(target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t}else {\n\t\t\t\t\treturn target._row.table.componentFunctionBinder.handle(\"row\", target._row, name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tgetData(transform){\n\t\treturn this._row.getData(transform);\n\t}\n\n\tgetElement(){\n\t\treturn this._row.getElement();\n\t}\n\n\tgetTable(){\n\t\treturn this._row.table;\n\t}\n\n\tgetCells(){\n\t\tvar cells = [];\n\n\t\tthis._row.getCells().forEach(function(cell){\n\t\t\tcells.push(cell.getComponent());\n\t\t});\n\n\t\treturn cells;\n\t}\n\n\tgetCell(column){\n\t\tvar cell = this._row.getCell(column);\n\t\treturn cell ? cell.getComponent() : false;\n\t}\n\n\t_getSelf(){\n\t\treturn this._row;\n\t}\n}\n\n//public cell object\nclass CellComponent {\n\n\tconstructor (cell){\n\t\tthis._cell = cell;\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function(target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t}else {\n\t\t\t\t\treturn target._cell.table.componentFunctionBinder.handle(\"cell\", target._cell, name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tgetValue(){\n\t\treturn this._cell.getValue();\n\t}\n\n\tgetOldValue(){\n\t\treturn this._cell.getOldValue();\n\t}\n\n\tgetInitialValue(){\n\t\treturn this._cell.initialValue;\n\t}\n\n\tgetElement(){\n\t\treturn this._cell.getElement();\n\t}\n\n\tgetRow(){\n\t\treturn this._cell.row.getComponent();\n\t}\n\n\tgetData(transform){\n\t\treturn this._cell.row.getData(transform);\n\t}\n\tgetType(){\n\t\treturn \"cell\";\n\t}\n\tgetField(){\n\t\treturn this._cell.column.getField();\n\t}\n\n\tgetColumn(){\n\t\treturn this._cell.column.getComponent();\n\t}\n\n\tsetValue(value, mutate){\n\t\tif(typeof mutate == \"undefined\"){\n\t\t\tmutate = true;\n\t\t}\n\n\t\tthis._cell.setValue(value, mutate);\n\t}\n\n\trestoreOldValue(){\n\t\tthis._cell.setValueActual(this._cell.getOldValue());\n\t}\n\n\trestoreInitialValue(){\n\t\tthis._cell.setValueActual(this._cell.initialValue);\n\t}\n\n\tcheckHeight(){\n\t\tthis._cell.checkHeight();\n\t}\n\n\tgetTable(){\n\t\treturn this._cell.table;\n\t}\n\n\t_getSelf(){\n\t\treturn this._cell;\n\t}\n}\n\nclass Cell extends CoreFeature{\n\tconstructor(column, row){\n\t\tsuper(column.table);\n\n\t\tthis.table = column.table;\n\t\tthis.column = column;\n\t\tthis.row = row;\n\t\tthis.element = null;\n\t\tthis.value = null;\n\t\tthis.initialValue;\n\t\tthis.oldValue = null;\n\t\tthis.modules = {};\n\n\t\tthis.height = null;\n\t\tthis.width = null;\n\t\tthis.minWidth = null;\n\n\t\tthis.component = null;\n\n\t\tthis.loaded = false; //track if the cell has been added to the DOM yet\n\n\t\tthis.build();\n\t}\n\n\t//////////////// Setup Functions /////////////////\n\t//generate element\n\tbuild(){\n\t\tthis.generateElement();\n\n\t\tthis.setWidth();\n\n\t\tthis._configureCell();\n\n\t\tthis.setValueActual(this.column.getFieldValue(this.row.data));\n\n\t\tthis.initialValue = this.value;\n\t}\n\n\tgenerateElement(){\n\t\tthis.element = document.createElement('div');\n\t\tthis.element.className = \"tabulator-cell\";\n\t\tthis.element.setAttribute(\"role\", \"gridcell\");\n\t}\n\n\t_configureCell(){\n\t\tvar element = this.element,\n\t\tfield = this.column.getField(),\n\t\tvertAligns = {\n\t\t\ttop:\"flex-start\",\n\t\t\tbottom:\"flex-end\",\n\t\t\tmiddle:\"center\",\n\t\t},\n\t\thozAligns = {\n\t\t\tleft:\"flex-start\",\n\t\t\tright:\"flex-end\",\n\t\t\tcenter:\"center\",\n\t\t};\n\n\t\t//set text alignment\n\t\telement.style.textAlign = this.column.hozAlign;\n\n\t\tif(this.column.vertAlign){\n\t\t\telement.style.display = \"inline-flex\";\n\n\t\t\telement.style.alignItems = vertAligns[this.column.vertAlign] || \"\";\n\n\t\t\tif(this.column.hozAlign){\n\t\t\t\telement.style.justifyContent = hozAligns[this.column.hozAlign] || \"\";\n\t\t\t}\n\t\t}\n\n\t\tif(field){\n\t\t\telement.setAttribute(\"tabulator-field\", field);\n\t\t}\n\n\t\t//add class to cell if needed\n\t\tif(this.column.definition.cssClass){\n\t\t\tvar classNames = this.column.definition.cssClass.split(\" \");\n\t\t\tclassNames.forEach((className) => {\n\t\t\t\telement.classList.add(className);\n\t\t\t});\n\t\t}\n\n\t\tthis.dispatch(\"cell-init\", this);\n\n\t\t//hide cell if not visible\n\t\tif(!this.column.visible){\n\t\t\tthis.hide();\n\t\t}\n\t}\n\n\t//generate cell contents\n\t_generateContents(){\n\t\tvar val;\n\n\t\tval = this.chain(\"cell-format\", this, null, () => {\n\t\t\treturn this.element.innerHTML = this.value;\n\t\t});\n\n\t\tswitch(typeof val){\n\t\t\tcase \"object\":\n\t\t\t\tif(val instanceof Node){\n\n\t\t\t\t\t//clear previous cell contents\n\t\t\t\t\twhile(this.element.firstChild) this.element.removeChild(this.element.firstChild);\n\n\t\t\t\t\tthis.element.appendChild(val);\n\t\t\t\t}else {\n\t\t\t\t\tthis.element.innerHTML = \"\";\n\n\t\t\t\t\tif(val != null){\n\t\t\t\t\t\tconsole.warn(\"Format Error - Formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:\", val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"undefined\":\n\t\t\t\tthis.element.innerHTML = \"\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.element.innerHTML = val;\n\t\t}\n\t}\n\n\tcellRendered(){\n\t\tthis.dispatch(\"cell-rendered\", this);\n\t}\n\n\t//////////////////// Getters ////////////////////\n\tgetElement(containerOnly){\n\t\tif(!this.loaded){\n\t\t\tthis.loaded = true;\n\t\t\tif(!containerOnly){\n\t\t\t\tthis.layoutElement();\n\t\t\t}\n\t\t}\n\n\t\treturn this.element;\n\t}\n\n\tgetValue(){\n\t\treturn this.value;\n\t}\n\n\tgetOldValue(){\n\t\treturn this.oldValue;\n\t}\n\n\t//////////////////// Actions ////////////////////\n\tsetValue(value, mutate, force){\n\t\tvar changed = this.setValueProcessData(value, mutate, force);\n\n\t\tif(changed){\n\t\t\tthis.dispatch(\"cell-value-updated\", this);\n\n\t\t\tthis.cellRendered();\n\n\t\t\tif(this.column.definition.cellEdited){\n\t\t\t\tthis.column.definition.cellEdited.call(this.table, this.getComponent());\n\t\t\t}\n\n\t\t\tthis.dispatchExternal(\"cellEdited\", this.getComponent());\n\n\t\t\tif(this.subscribedExternal(\"dataChanged\")){\n\t\t\t\tthis.dispatchExternal(\"dataChanged\", this.table.rowManager.getData());\n\t\t\t}\n\t\t}\n\t}\n\n\tsetValueProcessData(value, mutate, force){\n\t\tvar changed = false;\n\n\t\tif(this.value !== value || force){\n\n\t\t\tchanged = true;\n\n\t\t\tif(mutate){\n\t\t\t\tvalue = this.chain(\"cell-value-changing\", [this, value], null, value);\n\t\t\t}\n\t\t}\n\n\t\tthis.setValueActual(value);\n\n\t\tif(changed){\n\t\t\tthis.dispatch(\"cell-value-changed\", this);\n\t\t}\n\n\t\treturn changed;\n\t}\n\n\tsetValueActual(value){\n\t\tthis.oldValue = this.value;\n\n\t\tthis.value = value;\n\n\t\tthis.dispatch(\"cell-value-save-before\", this);\n\n\t\tthis.column.setFieldValue(this.row.data, value);\n\n\t\tthis.dispatch(\"cell-value-save-after\", this);\n\n\t\tif(this.loaded){\n\t\t\tthis.layoutElement();\n\t\t}\n\t}\n\n\tlayoutElement(){\n\t\tthis._generateContents();\n\n\t\tthis.dispatch(\"cell-layout\", this);\n\t}\n\n\tsetWidth(){\n\t\tthis.width = this.column.width;\n\t\tthis.element.style.width = this.column.widthStyled;\n\t}\n\n\tclearWidth(){\n\t\tthis.width = \"\";\n\t\tthis.element.style.width = \"\";\n\t}\n\n\tgetWidth(){\n\t\treturn this.width || this.element.offsetWidth;\n\t}\n\n\tsetMinWidth(){\n\t\tthis.minWidth = this.column.minWidth;\n\t\tthis.element.style.minWidth = this.column.minWidthStyled;\n\t}\n\n\tsetMaxWidth(){\n\t\tthis.maxWidth = this.column.maxWidth;\n\t\tthis.element.style.maxWidth = this.column.maxWidthStyled;\n\t}\n\n\tcheckHeight(){\n\t\t// var height = this.element.css(\"height\");\n\t\tthis.row.reinitializeHeight();\n\t}\n\n\tclearHeight(){\n\t\tthis.element.style.height = \"\";\n\t\tthis.height = null;\n\n\t\tthis.dispatch(\"cell-height\", this, \"\");\n\t}\n\n\tsetHeight(){\n\t\tthis.height = this.row.height;\n\t\tthis.element.style.height = this.row.heightStyled;\n\n\t\tthis.dispatch(\"cell-height\", this, this.row.heightStyled);\n\t}\n\n\tgetHeight(){\n\t\treturn this.height || this.element.offsetHeight;\n\t}\n\n\tshow(){\n\t\tthis.element.style.display = this.column.vertAlign ? \"inline-flex\" : \"\";\n\t}\n\n\thide(){\n\t\tthis.element.style.display = \"none\";\n\t}\n\n\tdelete(){\n\t\tthis.dispatch(\"cell-delete\", this);\n\n\t\tif(!this.table.rowManager.redrawBlock && this.element.parentNode){\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\n\t\tthis.element = false;\n\t\tthis.column.deleteCell(this);\n\t\tthis.row.deleteCell(this);\n\t\tthis.calcs = {};\n\t}\n\n\tgetIndex(){\n\t\treturn this.row.getCellIndex(this);\n\t}\n\n\t//////////////// Object Generation /////////////////\n\tgetComponent(){\n\t\tif(!this.component){\n\t\t\tthis.component = new CellComponent(this);\n\t\t}\n\n\t\treturn this.component;\n\t}\n}\n\n//public column object\nclass ColumnComponent {\n\tconstructor (column){\n\t\tthis._column = column;\n\t\tthis.type = \"ColumnComponent\";\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function(target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t}else {\n\t\t\t\t\treturn target._column.table.componentFunctionBinder.handle(\"column\", target._column, name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tgetElement(){\n\t\treturn this._column.getElement();\n\t}\n\n\tgetDefinition(){\n\t\treturn this._column.getDefinition();\n\t}\n\n\tgetField(){\n\t\treturn this._column.getField();\n\t}\n\n\tgetTitleDownload() {\n\t\treturn this._column.getTitleDownload();\n\t}\n\n\tgetCells(){\n\t\tvar cells = [];\n\n\t\tthis._column.cells.forEach(function(cell){\n\t\t\tcells.push(cell.getComponent());\n\t\t});\n\n\t\treturn cells;\n\t}\n\n\tisVisible(){\n\t\treturn this._column.visible;\n\t}\n\n\tshow(){\n\t\tif(this._column.isGroup){\n\t\t\tthis._column.columns.forEach(function(column){\n\t\t\t\tcolumn.show();\n\t\t\t});\n\t\t}else {\n\t\t\tthis._column.show();\n\t\t}\n\t}\n\n\thide(){\n\t\tif(this._column.isGroup){\n\t\t\tthis._column.columns.forEach(function(column){\n\t\t\t\tcolumn.hide();\n\t\t\t});\n\t\t}else {\n\t\t\tthis._column.hide();\n\t\t}\n\t}\n\n\ttoggle(){\n\t\tif(this._column.visible){\n\t\t\tthis.hide();\n\t\t}else {\n\t\t\tthis.show();\n\t\t}\n\t}\n\n\tdelete(){\n\t\treturn this._column.delete();\n\t}\n\n\tgetSubColumns(){\n\t\tvar output = [];\n\n\t\tif(this._column.columns.length){\n\t\t\tthis._column.columns.forEach(function(column){\n\t\t\t\toutput.push(column.getComponent());\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tgetParentColumn(){\n\t\treturn this._column.parent instanceof Column ? this._column.parent.getComponent() : false;\n\t}\n\n\t_getSelf(){\n\t\treturn this._column;\n\t}\n\n\tscrollTo(position, ifVisible){\n\t\treturn this._column.table.columnManager.scrollToColumn(this._column, position, ifVisible);\n\t}\n\n\tgetTable(){\n\t\treturn this._column.table;\n\t}\n\n\tmove(to, after){\n\t\tvar toColumn = this._column.table.columnManager.findColumn(to);\n\n\t\tif(toColumn){\n\t\t\tthis._column.table.columnManager.moveColumn(this._column, toColumn, after);\n\t\t}else {\n\t\t\tconsole.warn(\"Move Error - No matching column found:\", toColumn);\n\t\t}\n\t}\n\n\tgetNextColumn(){\n\t\tvar nextCol = this._column.nextColumn();\n\n\t\treturn nextCol ? nextCol.getComponent() : false;\n\t}\n\n\tgetPrevColumn(){\n\t\tvar prevCol = this._column.prevColumn();\n\n\t\treturn prevCol ? prevCol.getComponent() : false;\n\t}\n\n\tupdateDefinition(updates){\n\t\treturn this._column.updateDefinition(updates);\n\t}\n\n\tgetWidth(){\n\t\treturn this._column.getWidth();\n\t}\n\n\tsetWidth(width){\n\t\tvar result;\n\n\t\tif(width === true){\n\t\t\tresult =  this._column.reinitializeWidth(true);\n\t\t}else {\n\t\t\tresult =  this._column.setWidth(width);\n\t\t}\n\n\t\tthis._column.table.columnManager.rerenderColumns(true);\n\n\t\treturn result;\n\t}\n}\n\nvar defaultColumnOptions = {\n\t\"title\": undefined,\n\t\"field\": undefined,\n\t\"columns\": undefined,\n\t\"visible\": undefined,\n\t\"hozAlign\": undefined,\n\t\"vertAlign\": undefined,\n\t\"width\": undefined,\n\t\"minWidth\": 40,\n\t\"maxWidth\": undefined,\n\t\"maxInitialWidth\": undefined,\n\t\"cssClass\": undefined,\n\t\"variableHeight\": undefined,\n\t\"headerVertical\": undefined,\n\t\"headerHozAlign\": undefined,\n\t\"headerWordWrap\": false,\n\t\"editableTitle\": undefined,\n};\n\nclass Column extends CoreFeature{\n\n\tconstructor(def, parent){\n\t\tsuper(parent.table);\n\n\t\tthis.definition = def; //column definition\n\t\tthis.parent = parent; //hold parent object\n\t\tthis.type = \"column\"; //type of element\n\t\tthis.columns = []; //child columns\n\t\tthis.cells = []; //cells bound to this column\n\t\tthis.element = this.createElement(); //column header element\n\t\tthis.contentElement = false;\n\t\tthis.titleHolderElement = false;\n\t\tthis.titleElement = false;\n\t\tthis.groupElement = this.createGroupElement(); //column group holder element\n\t\tthis.isGroup = false;\n\t\tthis.hozAlign = \"\"; //horizontal text alignment\n\t\tthis.vertAlign = \"\"; //vert text alignment\n\n\t\t//multi dimensional filed handling\n\t\tthis.field =\"\";\n\t\tthis.fieldStructure = \"\";\n\t\tthis.getFieldValue = \"\";\n\t\tthis.setFieldValue = \"\";\n\n\t\tthis.titleDownload = null;\n\t\tthis.titleFormatterRendered = false;\n\n\t\tthis.mapDefinitions();\n\n\t\tthis.setField(this.definition.field);\n\n\t\tthis.modules = {}; //hold module variables;\n\n\t\tthis.width = null; //column width\n\t\tthis.widthStyled = \"\"; //column width pre-styled to improve render efficiency\n\t\tthis.maxWidth = null; //column maximum width\n\t\tthis.maxWidthStyled = \"\"; //column maximum pre-styled to improve render efficiency\n\t\tthis.maxInitialWidth = null;\n\t\tthis.minWidth = null; //column minimum width\n\t\tthis.minWidthStyled = \"\"; //column minimum pre-styled to improve render efficiency\n\t\tthis.widthFixed = false; //user has specified a width for this column\n\n\t\tthis.visible = true; //default visible state\n\n\t\tthis.component = null;\n\n\t\t//initialize column\n\t\tif(this.definition.columns){\n\n\t\t\tthis.isGroup = true;\n\n\t\t\tthis.definition.columns.forEach((def, i) => {\n\t\t\t\tvar newCol = new Column(def, this);\n\t\t\t\tthis.attachColumn(newCol);\n\t\t\t});\n\n\t\t\tthis.checkColumnVisibility();\n\t\t}else {\n\t\t\tparent.registerColumnField(this);\n\t\t}\n\n\t\tthis._initialize();\n\t}\n\n\tcreateElement (){\n\t\tvar el = document.createElement(\"div\");\n\n\t\tel.classList.add(\"tabulator-col\");\n\t\tel.setAttribute(\"role\", \"columnheader\");\n\t\tel.setAttribute(\"aria-sort\", \"none\");\n\n\t\tswitch(this.table.options.columnHeaderVertAlign){\n\t\t\tcase \"middle\":\n\t\t\t\tel.style.justifyContent = \"center\";\n\t\t\t\tbreak;\n\t\t\tcase \"bottom\":\n\t\t\t\tel.style.justifyContent = \"flex-end\";\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn el;\n\t}\n\n\tcreateGroupElement (){\n\t\tvar el = document.createElement(\"div\");\n\n\t\tel.classList.add(\"tabulator-col-group-cols\");\n\n\t\treturn el;\n\t}\n\n\tmapDefinitions(){\n\t\tvar defaults = this.table.options.columnDefaults;\n\n\t\t//map columnDefaults onto column definitions\n\t\tif(defaults){\n\t\t\tfor(let key in defaults){\n\t\t\t\tif(typeof this.definition[key] === \"undefined\"){\n\t\t\t\t\tthis.definition[key] = defaults[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.definition = this.table.columnManager.optionsList.generate(Column.defaultOptionList, this.definition);\n\t}\n\n\tcheckDefinition(){\n\t\tObject.keys(this.definition).forEach((key) => {\n\t\t\tif(Column.defaultOptionList.indexOf(key) === -1){\n\t\t\t\tconsole.warn(\"Invalid column definition option in '\" + (this.field || this.definition.title) + \"' column:\", key);\n\t\t\t}\n\t\t});\n\t}\n\n\tsetField(field){\n\t\tthis.field = field;\n\t\tthis.fieldStructure = field ? (this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator) : [field]) : [];\n\t\tthis.getFieldValue = this.fieldStructure.length > 1 ? this._getNestedData : this._getFlatData;\n\t\tthis.setFieldValue = this.fieldStructure.length > 1 ? this._setNestedData : this._setFlatData;\n\t}\n\n\t//register column position with column manager\n\tregisterColumnPosition(column){\n\t\tthis.parent.registerColumnPosition(column);\n\t}\n\n\t//register column position with column manager\n\tregisterColumnField(column){\n\t\tthis.parent.registerColumnField(column);\n\t}\n\n\t//trigger position registration\n\treRegisterPosition(){\n\t\tif(this.isGroup){\n\t\t\tthis.columns.forEach(function(column){\n\t\t\t\tcolumn.reRegisterPosition();\n\t\t\t});\n\t\t}else {\n\t\t\tthis.registerColumnPosition(this);\n\t\t}\n\t}\n\n\t//build header element\n\t_initialize(){\n\t\tvar def = this.definition;\n\n\t\twhile(this.element.firstChild) this.element.removeChild(this.element.firstChild);\n\n\t\tif(def.headerVertical){\n\t\t\tthis.element.classList.add(\"tabulator-col-vertical\");\n\n\t\t\tif(def.headerVertical === \"flip\"){\n\t\t\t\tthis.element.classList.add(\"tabulator-col-vertical-flip\");\n\t\t\t}\n\t\t}\n\n\t\tthis.contentElement = this._buildColumnHeaderContent();\n\n\t\tthis.element.appendChild(this.contentElement);\n\n\t\tif(this.isGroup){\n\t\t\tthis._buildGroupHeader();\n\t\t}else {\n\t\t\tthis._buildColumnHeader();\n\t\t}\n\n\t\tthis.dispatch(\"column-init\", this);\n\t}\n\n\t//build header element for header\n\t_buildColumnHeader(){\n\t\tvar def = this.definition;\n\n\t\tthis.dispatch(\"column-layout\", this);\n\n\t\t//set column visibility\n\t\tif(typeof def.visible != \"undefined\"){\n\t\t\tif(def.visible){\n\t\t\t\tthis.show(true);\n\t\t\t}else {\n\t\t\t\tthis.hide(true);\n\t\t\t}\n\t\t}\n\n\t\t//assign additional css classes to column header\n\t\tif(def.cssClass){\n\t\t\tvar classNames = def.cssClass.split(\" \");\n\t\t\tclassNames.forEach((className) => {\n\t\t\t\tthis.element.classList.add(className);\n\t\t\t});\n\t\t}\n\n\t\tif(def.field){\n\t\t\tthis.element.setAttribute(\"tabulator-field\", def.field);\n\t\t}\n\n\t\t//set min width if present\n\t\tthis.setMinWidth(parseInt(def.minWidth));\n\n\t\tif (def.maxInitialWidth) {\n\t\t\tthis.maxInitialWidth = parseInt(def.maxInitialWidth);\n\t\t}\n\t\t\n\t\tif(def.maxWidth){\n\t\t\tthis.setMaxWidth(parseInt(def.maxWidth));\n\t\t}\n\n\t\tthis.reinitializeWidth();\n\n\t\t//set horizontal text alignment\n\t\tthis.hozAlign = this.definition.hozAlign;\n\t\tthis.vertAlign = this.definition.vertAlign;\n\n\t\tthis.titleElement.style.textAlign = this.definition.headerHozAlign;\n\t}\n\n\t_buildColumnHeaderContent(){\n\t\tvar contentElement = document.createElement(\"div\");\n\t\tcontentElement.classList.add(\"tabulator-col-content\");\n\n\t\tthis.titleHolderElement = document.createElement(\"div\");\n\t\tthis.titleHolderElement.classList.add(\"tabulator-col-title-holder\");\n\n\t\tcontentElement.appendChild(this.titleHolderElement);\n\n\t\tthis.titleElement = this._buildColumnHeaderTitle();\n\n\t\tthis.titleHolderElement.appendChild(this.titleElement);\n\n\t\treturn contentElement;\n\t}\n\n\t//build title element of column\n\t_buildColumnHeaderTitle(){\n\t\tvar def = this.definition;\n\n\t\tvar titleHolderElement = document.createElement(\"div\");\n\t\ttitleHolderElement.classList.add(\"tabulator-col-title\");\n\t\t\n\t\tif(def.headerWordWrap){\n\t\t\ttitleHolderElement.classList.add(\"tabulator-col-title-wrap\");\n\t\t}\n\n\t\tif(def.editableTitle){\n\t\t\tvar titleElement = document.createElement(\"input\");\n\t\t\ttitleElement.classList.add(\"tabulator-title-editor\");\n\n\t\t\ttitleElement.addEventListener(\"click\", (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t\ttitleElement.focus();\n\t\t\t});\n\n\t\t\ttitleElement.addEventListener(\"mousedown\", (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t\ttitleElement.addEventListener(\"change\", () => {\n\t\t\t\tdef.title = titleElement.value;\n\t\t\t\tthis.dispatchExternal(\"columnTitleChanged\", this.getComponent());\n\t\t\t});\n\n\t\t\ttitleHolderElement.appendChild(titleElement);\n\n\t\t\tif(def.field){\n\t\t\t\tthis.langBind(\"columns|\" + def.field, (text) => {\n\t\t\t\t\ttitleElement.value = text || (def.title || \"&nbsp;\");\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\ttitleElement.value  = def.title || \"&nbsp;\";\n\t\t\t}\n\n\t\t}else {\n\t\t\tif(def.field){\n\t\t\t\tthis.langBind(\"columns|\" + def.field, (text) => {\n\t\t\t\t\tthis._formatColumnHeaderTitle(titleHolderElement, text || (def.title || \"&nbsp;\"));\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tthis._formatColumnHeaderTitle(titleHolderElement, def.title || \"&nbsp;\");\n\t\t\t}\n\t\t}\n\n\t\treturn titleHolderElement;\n\t}\n\n\t_formatColumnHeaderTitle(el, title){\n\t\tvar contents = this.chain(\"column-format\", [this, title, el], null, () => {\n\t\t\treturn title;\n\t\t});\n\n\t\tswitch(typeof contents){\n\t\t\tcase \"object\":\n\t\t\t\tif(contents instanceof Node){\n\t\t\t\t\tel.appendChild(contents);\n\t\t\t\t}else {\n\t\t\t\t\tel.innerHTML = \"\";\n\t\t\t\t\tconsole.warn(\"Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:\", contents);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"undefined\":\n\t\t\t\tel.innerHTML = \"\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tel.innerHTML = contents;\n\t\t}\n\t}\n\n\t//build header element for column group\n\t_buildGroupHeader(){\n\t\tthis.element.classList.add(\"tabulator-col-group\");\n\t\tthis.element.setAttribute(\"role\", \"columngroup\");\n\t\tthis.element.setAttribute(\"aria-title\", this.definition.title);\n\n\t\t//asign additional css classes to column header\n\t\tif(this.definition.cssClass){\n\t\t\tvar classNames = this.definition.cssClass.split(\" \");\n\t\t\tclassNames.forEach((className) => {\n\t\t\t\tthis.element.classList.add(className);\n\t\t\t});\n\t\t}\n\n\t\tthis.titleElement.style.textAlign = this.definition.headerHozAlign;\n\n\t\tthis.element.appendChild(this.groupElement);\n\t}\n\n\t//flat field lookup\n\t_getFlatData(data){\n\t\treturn data[this.field];\n\t}\n\n\t//nested field lookup\n\t_getNestedData(data){\n\t\tvar dataObj = data,\n\t\tstructure = this.fieldStructure,\n\t\tlength = structure.length,\n\t\toutput;\n\n\t\tfor(let i = 0; i < length; i++){\n\n\t\t\tdataObj = dataObj[structure[i]];\n\n\t\t\toutput = dataObj;\n\n\t\t\tif(!dataObj){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t}\n\n\t//flat field set\n\t_setFlatData(data, value){\n\t\tif(this.field){\n\t\t\tdata[this.field] = value;\n\t\t}\n\t}\n\n\t//nested field set\n\t_setNestedData(data, value){\n\t\tvar dataObj = data,\n\t\tstructure = this.fieldStructure,\n\t\tlength = structure.length;\n\n\t\tfor(let i = 0; i < length; i++){\n\n\t\t\tif(i == length -1){\n\t\t\t\tdataObj[structure[i]] = value;\n\t\t\t}else {\n\t\t\t\tif(!dataObj[structure[i]]){\n\t\t\t\t\tif(typeof value !== \"undefined\"){\n\t\t\t\t\t\tdataObj[structure[i]] = {};\n\t\t\t\t\t}else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdataObj = dataObj[structure[i]];\n\t\t\t}\n\t\t}\n\t}\n\n\t//attach column to this group\n\tattachColumn(column){\n\t\tif(this.groupElement){\n\t\t\tthis.columns.push(column);\n\t\t\tthis.groupElement.appendChild(column.getElement());\n\n\t\t\tcolumn.columnRendered();\n\t\t}else {\n\t\t\tconsole.warn(\"Column Warning - Column being attached to another column instead of column group\");\n\t\t}\n\t}\n\n\t//vertically align header in column\n\tverticalAlign(alignment, height){\n\n\t\t//calculate height of column header and group holder element\n\t\tvar parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : (height || this.parent.getHeadersElement().clientHeight);\n\t\t// var parentHeight = this.parent.isGroup ? this.parent.getGroupElement().clientHeight : this.parent.getHeadersElement().clientHeight;\n\n\t\tthis.element.style.height = parentHeight + \"px\";\n\n\t\tthis.dispatch(\"column-height\", this, this.element.style.height);\n\n\t\tif(this.isGroup){\n\t\t\tthis.groupElement.style.minHeight = (parentHeight - this.contentElement.offsetHeight) + \"px\";\n\t\t}\n\n\t\t//vertically align cell contents\n\t\t// if(!this.isGroup && alignment !== \"top\"){\n\t\t// \tif(alignment === \"bottom\"){\n\t\t// \t\tthis.element.style.paddingTop = (this.element.clientHeight - this.contentElement.offsetHeight) + \"px\";\n\t\t// \t}else{\n\t\t// \t\tthis.element.style.paddingTop = ((this.element.clientHeight - this.contentElement.offsetHeight) / 2) + \"px\";\n\t\t// \t}\n\t\t// }\n\n\t\tthis.columns.forEach(function(column){\n\t\t\tcolumn.verticalAlign(alignment);\n\t\t});\n\t}\n\n\t//clear vertical alignment\n\tclearVerticalAlign(){\n\t\tthis.element.style.paddingTop = \"\";\n\t\tthis.element.style.height = \"\";\n\t\tthis.element.style.minHeight = \"\";\n\t\tthis.groupElement.style.minHeight = \"\";\n\n\t\tthis.columns.forEach(function(column){\n\t\t\tcolumn.clearVerticalAlign();\n\t\t});\n\n\t\tthis.dispatch(\"column-height\", this, \"\");\n\t}\n\n\t//// Retrieve Column Information ////\n\t//return column header element\n\tgetElement(){\n\t\treturn this.element;\n\t}\n\n\t//return column group element\n\tgetGroupElement(){\n\t\treturn this.groupElement;\n\t}\n\n\t//return field name\n\tgetField(){\n\t\treturn this.field;\n\t}\n\n\tgetTitleDownload() {\n\t\treturn this.titleDownload;\n\t}\n\n\t//return the first column in a group\n\tgetFirstColumn(){\n\t\tif(!this.isGroup){\n\t\t\treturn this;\n\t\t}else {\n\t\t\tif(this.columns.length){\n\t\t\t\treturn this.columns[0].getFirstColumn();\n\t\t\t}else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t//return the last column in a group\n\tgetLastColumn(){\n\t\tif(!this.isGroup){\n\t\t\treturn this;\n\t\t}else {\n\t\t\tif(this.columns.length){\n\t\t\t\treturn this.columns[this.columns.length -1].getLastColumn();\n\t\t\t}else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t//return all columns in a group\n\tgetColumns(traverse){\n\t\tvar columns = [];\n\n\t\tif(traverse){\n\t\t\tthis.columns.forEach((column) => {\n\t\t\t\tcolumns.push(column);\n\t\t\t\t\t\n\t\t\t\tcolumns = columns.concat(column.getColumns(true));\n\t\t\t});\n\t\t}else {\n\t\t\tcolumns = this.columns;\n\t\t}\n\t\t\n\t\treturn columns;\n\t}\n\n\t//return all columns in a group\n\tgetCells(){\n\t\treturn this.cells;\n\t}\n\n\t//retrieve the top column in a group of columns\n\tgetTopColumn(){\n\t\tif(this.parent.isGroup){\n\t\t\treturn this.parent.getTopColumn();\n\t\t}else {\n\t\t\treturn this;\n\t\t}\n\t}\n\n\t//return column definition object\n\tgetDefinition(updateBranches){\n\t\tvar colDefs = [];\n\n\t\tif(this.isGroup && updateBranches){\n\t\t\tthis.columns.forEach(function(column){\n\t\t\t\tcolDefs.push(column.getDefinition(true));\n\t\t\t});\n\n\t\t\tthis.definition.columns = colDefs;\n\t\t}\n\n\t\treturn this.definition;\n\t}\n\n\t//////////////////// Actions ////////////////////\n\tcheckColumnVisibility(){\n\t\tvar visible = false;\n\n\t\tthis.columns.forEach(function(column){\n\t\t\tif(column.visible){\n\t\t\t\tvisible = true;\n\t\t\t}\n\t\t});\n\n\t\tif(visible){\n\t\t\tthis.show();\n\t\t\tthis.dispatchExternal(\"columnVisibilityChanged\", this.getComponent(), false);\n\t\t}else {\n\t\t\tthis.hide();\n\t\t}\n\t}\n\n\t//show column\n\tshow(silent, responsiveToggle){\n\t\tif(!this.visible){\n\t\t\tthis.visible = true;\n\n\t\t\tthis.element.style.display = \"\";\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.checkColumnVisibility();\n\t\t\t}\n\n\t\t\tthis.cells.forEach(function(cell){\n\t\t\t\tcell.show();\n\t\t\t});\n\n\t\t\tif(!this.isGroup && this.width === null){\n\t\t\t\tthis.reinitializeWidth();\n\t\t\t}\n\n\t\t\tthis.table.columnManager.verticalAlignHeaders();\n\n\t\t\tthis.dispatch(\"column-show\", this, responsiveToggle);\n\n\t\t\tif(!silent){\n\t\t\t\tthis.dispatchExternal(\"columnVisibilityChanged\", this.getComponent(), true);\n\t\t\t}\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.matchChildWidths();\n\t\t\t}\n\n\t\t\tif(!this.silent){\n\t\t\t\tthis.table.columnManager.rerenderColumns();\n\t\t\t}\n\t\t}\n\t}\n\n\t//hide column\n\thide(silent, responsiveToggle){\n\t\tif(this.visible){\n\t\t\tthis.visible = false;\n\n\t\t\tthis.element.style.display = \"none\";\n\n\t\t\tthis.table.columnManager.verticalAlignHeaders();\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.checkColumnVisibility();\n\t\t\t}\n\n\t\t\tthis.cells.forEach(function(cell){\n\t\t\t\tcell.hide();\n\t\t\t});\n\n\t\t\tthis.dispatch(\"column-hide\", this, responsiveToggle);\n\n\t\t\tif(!silent){\n\t\t\t\tthis.dispatchExternal(\"columnVisibilityChanged\", this.getComponent(), false);\n\t\t\t}\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.matchChildWidths();\n\t\t\t}\n\n\t\t\tif(!this.silent){\n\t\t\t\tthis.table.columnManager.rerenderColumns();\n\t\t\t}\n\t\t}\n\t}\n\n\tmatchChildWidths(){\n\t\tvar childWidth = 0;\n\n\t\tif(this.contentElement && this.columns.length){\n\t\t\tthis.columns.forEach(function(column){\n\t\t\t\tif(column.visible){\n\t\t\t\t\tchildWidth += column.getWidth();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.contentElement.style.maxWidth = (childWidth - 1) + \"px\";\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.matchChildWidths();\n\t\t\t}\n\t\t}\n\t}\n\n\tremoveChild(child){\n\t\tvar index = this.columns.indexOf(child);\n\n\t\tif(index > -1){\n\t\t\tthis.columns.splice(index, 1);\n\t\t}\n\n\t\tif(!this.columns.length){\n\t\t\tthis.delete();\n\t\t}\n\t}\n\n\tsetWidth(width){\n\t\tthis.widthFixed = true;\n\t\tthis.setWidthActual(width);\n\t}\n\n\tsetWidthActual(width){\n\t\tif(isNaN(width)){\n\t\t\twidth = Math.floor((this.table.element.clientWidth/100) * parseInt(width));\n\t\t}\n\n\t\twidth = Math.max(this.minWidth, width);\n\n\t\tif(this.maxWidth){\n\t\t\twidth = Math.min(this.maxWidth, width);\n\t\t}\n\n\t\tthis.width = width;\n\t\tthis.widthStyled = width ? width + \"px\" : \"\";\n\n\t\tthis.element.style.width = this.widthStyled;\n\n\t\tif(!this.isGroup){\n\t\t\tthis.cells.forEach(function(cell){\n\t\t\t\tcell.setWidth();\n\t\t\t});\n\t\t}\n\n\t\tif(this.parent.isGroup){\n\t\t\tthis.parent.matchChildWidths();\n\t\t}\n\n\t\tthis.dispatch(\"column-width\", this);\n\t}\n\n\tcheckCellHeights(){\n\t\tvar rows = [];\n\n\t\tthis.cells.forEach(function(cell){\n\t\t\tif(cell.row.heightInitialized){\n\t\t\t\tif(cell.row.getElement().offsetParent !== null){\n\t\t\t\t\trows.push(cell.row);\n\t\t\t\t\tcell.row.clearCellHeight();\n\t\t\t\t}else {\n\t\t\t\t\tcell.row.heightInitialized = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\trows.forEach(function(row){\n\t\t\trow.calcHeight();\n\t\t});\n\n\t\trows.forEach(function(row){\n\t\t\trow.setCellHeight();\n\t\t});\n\t}\n\n\tgetWidth(){\n\t\tvar width = 0;\n\n\t\tif(this.isGroup){\n\t\t\tthis.columns.forEach(function(column){\n\t\t\t\tif(column.visible){\n\t\t\t\t\twidth += column.getWidth();\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\twidth = this.width;\n\t\t}\n\n\t\treturn width;\n\t}\n\n\tgetLeftOffset(){\n\t\tvar offset = this.element.offsetLeft;\n\n\t\tif(this.parent.isGroup){\n\t\t\toffset += this.parent.getLeftOffset();\n\t\t}\n\n\t\treturn offset;\n\t}\n\n\tgetHeight(){\n\t\treturn Math.ceil(this.element.getBoundingClientRect().height);\n\t}\n\n\tsetMinWidth(minWidth){\n\t\tif(this.maxWidth && minWidth > this.maxWidth){\n\t\t\tminWidth = this.maxWidth;\n\n\t\t\tconsole.warn(\"the minWidth (\"+ minWidth + \"px) for column '\" + this.field + \"' cannot be bigger that its maxWidth (\"+ this.maxWidthStyled + \")\");\n\t\t}\n\n\t\tthis.minWidth = minWidth;\n\t\tthis.minWidthStyled = minWidth ? minWidth + \"px\" : \"\";\n\n\t\tthis.element.style.minWidth = this.minWidthStyled;\n\n\t\tthis.cells.forEach(function(cell){\n\t\t\tcell.setMinWidth();\n\t\t});\n\t}\n\n\tsetMaxWidth(maxWidth){\n\t\tif(this.minWidth && maxWidth < this.minWidth){\n\t\t\tmaxWidth = this.minWidth;\n\n\t\t\tconsole.warn(\"the maxWidth (\"+ maxWidth + \"px) for column '\" + this.field + \"' cannot be smaller that its minWidth (\"+ this.minWidthStyled + \")\");\n\t\t}\n\n\t\tthis.maxWidth = maxWidth;\n\t\tthis.maxWidthStyled = maxWidth ? maxWidth + \"px\" : \"\";\n\n\t\tthis.element.style.maxWidth = this.maxWidthStyled;\n\n\t\tthis.cells.forEach(function(cell){\n\t\t\tcell.setMaxWidth();\n\t\t});\n\t}\n\n\tdelete(){\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif(this.isGroup){\n\t\t\t\tthis.columns.forEach(function(column){\n\t\t\t\t\tcolumn.delete();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.dispatch(\"column-delete\", this);\n\n\t\t\tvar cellCount = this.cells.length;\n\n\t\t\tfor(let i = 0; i < cellCount; i++){\n\t\t\t\tthis.cells[0].delete();\n\t\t\t}\n\n\t\t\tif(this.element.parentNode){\n\t\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t\t}\n\n\t\t\tthis.element = false;\n\t\t\tthis.contentElement = false;\n\t\t\tthis.titleElement = false;\n\t\t\tthis.groupElement = false;\n\n\t\t\tif(this.parent.isGroup){\n\t\t\t\tthis.parent.removeChild(this);\n\t\t\t}\n\n\t\t\tthis.table.columnManager.deregisterColumn(this);\n\n\t\t\tthis.table.columnManager.rerenderColumns(true);\n\n\t\t\tthis.dispatch(\"column-deleted\", this);\n\n\t\t\tresolve();\n\t\t});\n\t}\n\n\tcolumnRendered(){\n\t\tif(this.titleFormatterRendered){\n\t\t\tthis.titleFormatterRendered();\n\t\t}\n\n\t\tthis.dispatch(\"column-rendered\", this);\n\t}\n\n\t//////////////// Cell Management /////////////////\n\t//generate cell for this column\n\tgenerateCell(row){\n\t\tvar cell = new Cell(this, row);\n\n\t\tthis.cells.push(cell);\n\n\t\treturn cell;\n\t}\n\n\tnextColumn(){\n\t\tvar index = this.table.columnManager.findColumnIndex(this);\n\t\treturn index > -1 ? this._nextVisibleColumn(index + 1) : false;\n\t}\n\n\t_nextVisibleColumn(index){\n\t\tvar column = this.table.columnManager.getColumnByIndex(index);\n\t\treturn !column || column.visible ? column : this._nextVisibleColumn(index + 1);\n\t}\n\n\tprevColumn(){\n\t\tvar index = this.table.columnManager.findColumnIndex(this);\n\t\treturn index > -1 ? this._prevVisibleColumn(index - 1) : false;\n\t}\n\n\t_prevVisibleColumn(index){\n\t\tvar column = this.table.columnManager.getColumnByIndex(index);\n\t\treturn !column || column.visible ? column : this._prevVisibleColumn(index - 1);\n\t}\n\n\treinitializeWidth(force){\n\t\tthis.widthFixed = false;\n\n\t\t//set width if present\n\t\tif(typeof this.definition.width !== \"undefined\" && !force){\n\t\t\t// maxInitialWidth ignored here as width specified\n\t\t\tthis.setWidth(this.definition.width);\n\t\t}\n\n\t\tthis.dispatch(\"column-width-fit-before\", this);\n\n\t\tthis.fitToData(force);\n\n\t\tthis.dispatch(\"column-width-fit-after\", this);\n\t}\n\n\t//set column width to maximum cell width for non group columns\n\tfitToData(force){\n\t\tif(this.isGroup){\n\t\t\treturn;\n\t\t}\n\n\t\tif(!this.widthFixed){\n\t\t\tthis.element.style.width = \"\";\n\n\t\t\tthis.cells.forEach((cell) => {\n\t\t\t\tcell.clearWidth();\n\t\t\t});\n\t\t}\n\n\t\tvar maxWidth = this.element.offsetWidth;\n\n\t\tif(!this.width || !this.widthFixed){\n\t\t\tthis.cells.forEach((cell) => {\n\t\t\t\tvar width = cell.getWidth();\n\n\t\t\t\tif(width > maxWidth){\n\t\t\t\t\tmaxWidth = width;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif(maxWidth){\n\t\t\t\tvar setTo = maxWidth + 1;\n\t\t\t\tif (this.maxInitialWidth && !force) {\n\t\t\t\t\tsetTo = Math.min(setTo, this.maxInitialWidth);\n\t\t\t\t}\n\t\t\t\tthis.setWidthActual(setTo);\n\t\t\t}\n\t\t}\n\t}\n\n\tupdateDefinition(updates){\n\t\tvar definition;\n\n\t\tif(!this.isGroup){\n\t\t\tif(!this.parent.isGroup){\n\t\t\t\tdefinition = Object.assign({}, this.getDefinition());\n\t\t\t\tdefinition = Object.assign(definition, updates);\n\n\t\t\t\treturn this.table.columnManager.addColumn(definition, false, this)\n\t\t\t\t\t.then((column) => {\n\n\t\t\t\t\t\tif(definition.field == this.field){\n\t\t\t\t\t\t\tthis.field = false; //clear field name to prevent deletion of duplicate column from arrays\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn this.delete()\n\t\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\t\treturn column.getComponent();\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tconsole.error(\"Column Update Error - The updateDefinition function is only available on ungrouped columns\");\n\t\t\t\treturn Promise.reject(\"Column Update Error - The updateDefinition function is only available on columns, not column groups\");\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.error(\"Column Update Error - The updateDefinition function is only available on ungrouped columns\");\n\t\t\treturn Promise.reject(\"Column Update Error - The updateDefinition function is only available on columns, not column groups\");\n\t\t}\n\t}\n\n\tdeleteCell(cell){\n\t\tvar index = this.cells.indexOf(cell);\n\n\t\tif(index > -1){\n\t\t\tthis.cells.splice(index, 1);\n\t\t}\n\t}\n\n\t//////////////// Object Generation /////////////////\n\tgetComponent(){\n\t\tif(!this.component){\n\t\t\tthis.component = new ColumnComponent(this);\n\t\t}\n\n\t\treturn this.component;\n\t}\n\n\tgetPosition(){\n\t\treturn this.table.columnManager.getVisibleColumnsByIndex().indexOf(this) + 1;\n\t}\n}\n\nColumn.defaultOptionList = defaultColumnOptions;\n\n//public row object\nclass RowComponent {\n\n\tconstructor (row){\n\t\tthis._row = row;\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function(target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t}else {\n\t\t\t\t\treturn target._row.table.componentFunctionBinder.handle(\"row\", target._row, name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tgetData(transform){\n\t\treturn this._row.getData(transform);\n\t}\n\n\tgetElement(){\n\t\treturn this._row.getElement();\n\t}\n\n\tgetCells(){\n\t\tvar cells = [];\n\n\t\tthis._row.getCells().forEach(function(cell){\n\t\t\tcells.push(cell.getComponent());\n\t\t});\n\n\t\treturn cells;\n\t}\n\n\tgetCell(column){\n\t\tvar cell = this._row.getCell(column);\n\t\treturn cell ? cell.getComponent() : false;\n\t}\n\n\tgetIndex(){\n\t\treturn this._row.getData(\"data\")[this._row.table.options.index];\n\t}\n\n\tgetPosition(){\n\t\treturn this._row.getPosition();\n\t}\n\n\twatchPosition(callback){\n\t\treturn this._row.watchPosition(callback);\n\t}\n\n\tdelete(){\n\t\treturn this._row.delete();\n\t}\n\n\tscrollTo(position, ifVisible){\n\t\treturn this._row.table.rowManager.scrollToRow(this._row, position, ifVisible);\n\t}\n\n\tmove(to, after){\n\t\tthis._row.moveToRow(to, after);\n\t}\n\n\tupdate(data){\n\t\treturn this._row.updateData(data);\n\t}\n\n\tnormalizeHeight(){\n\t\tthis._row.normalizeHeight(true);\n\t}\n\n\t_getSelf(){\n\t\treturn this._row;\n\t}\n\n\treformat(){\n\t\treturn this._row.reinitialize();\n\t}\n\n\tgetTable(){\n\t\treturn this._row.table;\n\t}\n\n\tgetNextRow(){\n\t\tvar row = this._row.nextRow();\n\t\treturn row ? row.getComponent() : row;\n\t}\n\n\tgetPrevRow(){\n\t\tvar row = this._row.prevRow();\n\t\treturn row ? row.getComponent() : row;\n\t}\n}\n\nclass Row extends CoreFeature{\n\tconstructor (data, parent, type = \"row\"){\n\t\tsuper(parent.table);\n\t\t\n\t\tthis.parent = parent;\n\t\tthis.data = {};\n\t\tthis.type = type; //type of element\n\t\tthis.element = false;\n\t\tthis.modules = {}; //hold module variables;\n\t\tthis.cells = [];\n\t\tthis.height = 0; //hold element height\n\t\tthis.heightStyled = \"\"; //hold element height pre-styled to improve render efficiency\n\t\tthis.manualHeight = false; //user has manually set row height\n\t\tthis.outerHeight = 0; //hold elements outer height\n\t\tthis.initialized = false; //element has been rendered\n\t\tthis.heightInitialized = false; //element has resized cells to fit\n\t\tthis.position = 0; //store position of element in row list\n\t\tthis.positionWatchers = [];\n\t\t\n\t\tthis.component = null;\n\t\t\n\t\tthis.created = false;\n\t\t\n\t\tthis.setData(data);\n\t}\n\t\n\tcreate(){\n\t\tif(!this.created){\n\t\t\tthis.created = true;\n\t\t\tthis.generateElement();\n\t\t}\n\t}\n\t\n\tcreateElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-row\");\n\t\tel.setAttribute(\"role\", \"row\");\n\t\t\n\t\tthis.element = el;\n\t}\n\t\n\tgetElement(){\n\t\tthis.create();\n\t\treturn this.element;\n\t}\n\t\n\tdetachElement(){\n\t\tif (this.element && this.element.parentNode){\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n\t\n\tgenerateElement(){\n\t\tthis.createElement();\n\t\tthis.dispatch(\"row-init\", this);\n\t}\n\t\n\tgenerateCells(){\n\t\tthis.cells = this.table.columnManager.generateCells(this);\n\t}\n\t\n\t//functions to setup on first render\n\tinitialize(force, inFragment){\n\t\tthis.create();\n\t\t\n\t\tif(!this.initialized || force){\n\t\t\t\n\t\t\tthis.deleteCells();\n\t\t\t\n\t\t\twhile(this.element.firstChild) this.element.removeChild(this.element.firstChild);\n\t\t\t\n\t\t\tthis.dispatch(\"row-layout-before\", this);\n\t\t\t\n\t\t\tthis.generateCells();\n\t\t\t\n\t\t\tthis.initialized = true;\n\t\t\t\n\t\t\tthis.table.columnManager.renderer.renderRowCells(this, inFragment);\n\t\t\t\n\t\t\tif(force){\n\t\t\t\tthis.normalizeHeight();\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"row-layout\", this);\n\t\t\t\n\t\t\tif(this.table.options.rowFormatter){\n\t\t\t\tthis.table.options.rowFormatter(this.getComponent());\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"row-layout-after\", this);\n\t\t}else {\n\t\t\tthis.table.columnManager.renderer.rerenderRowCells(this, inFragment);\n\t\t}\n\t}\n\n\trendered(){\n\t\tthis.cells.forEach((cell) => {\n\t\t\tcell.cellRendered();\n\t\t});\n\t}\n\t\n\treinitializeHeight(){\n\t\tthis.heightInitialized = false;\n\t\t\n\t\tif(this.element && this.element.offsetParent !== null){\n\t\t\tthis.normalizeHeight(true);\n\t\t}\n\t}\n\n\tdeinitialize(){\n\t\tthis.initialized = false;\n\t}\n\t\n\tdeinitializeHeight(){\n\t\tthis.heightInitialized = false;\n\t}\n\t\n\treinitialize(children){\n\t\tthis.initialized = false;\n\t\tthis.heightInitialized = false;\n\t\t\n\t\tif(!this.manualHeight){\n\t\t\tthis.height = 0;\n\t\t\tthis.heightStyled = \"\";\n\t\t}\n\t\t\n\t\tif(this.element && this.element.offsetParent !== null){\n\t\t\tthis.initialize(true);\n\t\t}\n\t\t\n\t\tthis.dispatch(\"row-relayout\", this);\n\t}\n\t\n\t//get heights when doing bulk row style calcs in virtual DOM\n\tcalcHeight(force){\n\t\tvar maxHeight = 0,\n\t\tminHeight;\n\t\t\n\t\tif(this.table.options.rowHeight){\n\t\t\tthis.height = this.table.options.rowHeight;\n\t\t}else {\n\t\t\tminHeight = this.table.options.resizableRows ? this.element.clientHeight : 0;\n\t\t\t\n\t\t\tthis.cells.forEach(function(cell){\n\t\t\t\tvar height = cell.getHeight();\n\t\t\t\tif(height > maxHeight){\n\t\t\t\t\tmaxHeight = height;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tif(force){\n\t\t\t\tthis.height = Math.max(maxHeight, minHeight);\n\t\t\t}else {\n\t\t\t\tthis.height = this.manualHeight ? this.height : Math.max(maxHeight, minHeight);\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.heightStyled = this.height ? this.height + \"px\" : \"\";\n\t\tthis.outerHeight = this.element.offsetHeight;\n\t}\n\t\n\t//set of cells\n\tsetCellHeight(){\n\t\tthis.cells.forEach(function(cell){\n\t\t\tcell.setHeight();\n\t\t});\n\t\t\n\t\tthis.heightInitialized = true;\n\t}\n\t\n\tclearCellHeight(){\n\t\tthis.cells.forEach(function(cell){\n\t\t\tcell.clearHeight();\n\t\t});\n\t}\n\t\n\t//normalize the height of elements in the row\n\tnormalizeHeight(force){\n\t\tif(force && !this.table.options.rowHeight){\n\t\t\tthis.clearCellHeight();\n\t\t}\n\t\t\n\t\tthis.calcHeight(force);\n\t\t\n\t\tthis.setCellHeight();\n\t}\n\t\n\t//set height of rows\n\tsetHeight(height, force){\n\t\tif(this.height != height || force){\n\t\t\t\n\t\t\tthis.manualHeight = true;\n\t\t\t\n\t\t\tthis.height = height;\n\t\t\tthis.heightStyled = height ? height + \"px\" : \"\";\n\t\t\t\n\t\t\tthis.setCellHeight();\n\t\t\t\n\t\t\t// this.outerHeight = this.element.outerHeight();\n\t\t\tthis.outerHeight = this.element.offsetHeight;\n\t\t}\n\t}\n\t\n\t//return rows outer height\n\tgetHeight(){\n\t\treturn this.outerHeight;\n\t}\n\t\n\t//return rows outer Width\n\tgetWidth(){\n\t\treturn this.element.offsetWidth;\n\t}\n\t\n\t//////////////// Cell Management /////////////////\n\tdeleteCell(cell){\n\t\tvar index = this.cells.indexOf(cell);\n\t\t\n\t\tif(index > -1){\n\t\t\tthis.cells.splice(index, 1);\n\t\t}\n\t}\n\t\n\t//////////////// Data Management /////////////////\n\tsetData(data){\n\t\tthis.data = this.chain(\"row-data-init-before\", [this, data], undefined, data);\n\t\t\n\t\tthis.dispatch(\"row-data-init-after\", this);\n\t}\n\t\n\t//update the rows data\n\tupdateData(updatedData){\n\t\tvar visible = this.element && Helpers.elVisible(this.element),\n\t\ttempData = {},\n\t\tnewRowData;\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tif(typeof updatedData === \"string\"){\n\t\t\t\tupdatedData = JSON.parse(updatedData);\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"row-data-save-before\", this);\n\t\t\t\n\t\t\tif(this.subscribed(\"row-data-changing\")){\n\t\t\t\ttempData = Object.assign(tempData, this.data);\n\t\t\t\ttempData = Object.assign(tempData, updatedData);\n\t\t\t}\n\t\t\t\n\t\t\tnewRowData = this.chain(\"row-data-changing\", [this, tempData, updatedData], null, updatedData);\n\t\t\t\n\t\t\t//set data\n\t\t\tfor (let attrname in newRowData) {\n\t\t\t\tthis.data[attrname] = newRowData[attrname];\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"row-data-save-after\", this);\n\t\t\t\n\t\t\t//update affected cells only\n\t\t\tfor (let attrname in updatedData) {\n\t\t\t\t\n\t\t\t\tlet columns = this.table.columnManager.getColumnsByFieldRoot(attrname);\n\t\t\t\t\n\t\t\t\tcolumns.forEach((column) => {\n\t\t\t\t\tlet cell = this.getCell(column.getField());\n\t\t\t\t\t\n\t\t\t\t\tif(cell){\n\t\t\t\t\t\tlet value = column.getFieldValue(newRowData);\n\t\t\t\t\t\tif(cell.getValue() !== value){\n\t\t\t\t\t\t\tcell.setValueProcessData(value);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(visible){\n\t\t\t\t\t\t\t\tcell.cellRendered();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t//Partial reinitialization if visible\n\t\t\tif(visible){\n\t\t\t\tthis.normalizeHeight(true);\n\t\t\t\t\n\t\t\t\tif(this.table.options.rowFormatter){\n\t\t\t\t\tthis.table.options.rowFormatter(this.getComponent());\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.initialized = false;\n\t\t\t\tthis.height = 0;\n\t\t\t\tthis.heightStyled = \"\";\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"row-data-changed\", this, visible, updatedData);\n\t\t\t\n\t\t\t//this.reinitialize();\n\t\t\t\n\t\t\tthis.dispatchExternal(\"rowUpdated\", this.getComponent());\n\t\t\t\n\t\t\tif(this.subscribedExternal(\"dataChanged\")){\n\t\t\t\tthis.dispatchExternal(\"dataChanged\", this.table.rowManager.getData());\n\t\t\t}\n\t\t\t\n\t\t\tresolve();\n\t\t});\n\t}\n\t\n\tgetData(transform){\n\t\tif(transform){\n\t\t\treturn this.chain(\"row-data-retrieve\", [this, transform], null, this.data);\n\t\t}\n\t\t\n\t\treturn this.data;\n\t}\n\t\n\tgetCell(column){\n\t\tvar match = false;\n\t\t\n\t\tcolumn = this.table.columnManager.findColumn(column);\n\t\t\n\t\tif(!this.initialized && this.cells.length === 0){\n\t\t\tthis.generateCells();\n\t\t}\n\t\t\n\t\tmatch = this.cells.find(function(cell){\n\t\t\treturn cell.column === column;\n\t\t});\n\t\t\n\t\treturn match;\n\t}\n\t\n\tgetCellIndex(findCell){\n\t\treturn this.cells.findIndex(function(cell){\n\t\t\treturn cell === findCell;\n\t\t});\n\t}\n\t\n\tfindCell(subject){\n\t\treturn this.cells.find((cell) => {\n\t\t\treturn cell.element === subject;\n\t\t});\n\t}\n\t\n\tgetCells(){\n\t\tif(!this.initialized && this.cells.length === 0){\n\t\t\tthis.generateCells();\n\t\t}\n\t\t\n\t\treturn this.cells;\n\t}\n\t\n\tnextRow(){\n\t\tvar row = this.table.rowManager.nextDisplayRow(this, true);\n\t\treturn row || false;\n\t}\n\t\n\tprevRow(){\n\t\tvar row = this.table.rowManager.prevDisplayRow(this, true);\n\t\treturn row || false;\n\t}\n\t\n\tmoveToRow(to, before){\n\t\tvar toRow = this.table.rowManager.findRow(to);\n\t\t\n\t\tif(toRow){\n\t\t\tthis.table.rowManager.moveRowActual(this, toRow, !before);\n\t\t\tthis.table.rowManager.refreshActiveData(\"display\", false, true);\n\t\t}else {\n\t\t\tconsole.warn(\"Move Error - No matching row found:\", to);\n\t\t}\n\t}\n\t\n\t///////////////////// Actions  /////////////////////\n\tdelete(){\n\t\tthis.dispatch(\"row-delete\", this);\n\t\t\n\t\tthis.deleteActual();\n\t\t\n\t\treturn Promise.resolve();\n\t}\n\t\n\tdeleteActual(blockRedraw){\n\t\tthis.detachModules();\n\t\t\n\t\tthis.table.rowManager.deleteRow(this, blockRedraw);\n\t\t\n\t\tthis.deleteCells();\n\t\t\n\t\tthis.initialized = false;\n\t\tthis.heightInitialized = false;\n\t\tthis.element = false;\n\t\t\n\t\tthis.dispatch(\"row-deleted\", this);\n\t}\n\t\n\tdetachModules(){\n\t\tthis.dispatch(\"row-deleting\", this);\n\t}\n\t\n\tdeleteCells(){\n\t\tvar cellCount = this.cells.length;\n\t\t\n\t\tfor(let i = 0; i < cellCount; i++){\n\t\t\tthis.cells[0].delete();\n\t\t}\n\t}\n\t\n\twipe(){\n\t\tthis.detachModules();\n\t\tthis.deleteCells();\n\t\t\n\t\tif(this.element){\n\t\t\twhile(this.element.firstChild) this.element.removeChild(this.element.firstChild);\n\t\t\t\n\t\t\tif(this.element.parentNode){\n\t\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.element = false;\n\t\tthis.modules = {};\n\t}\n\n\tisDisplayed(){\n\t\treturn this.table.rowManager.getDisplayRows().includes(this);\n\t}\n\n\tgetPosition(){\n\t\treturn this.isDisplayed() ? this.position : false;\n\t}\n\n\tsetPosition(position){\n\t\tif(position != this.position){\n\t\t\tthis.position = position;\n\n\t\t\tthis.positionWatchers.forEach((callback) => {\n\t\t\t\tcallback(this.position);\n\t\t\t});\n\t\t}\n\t}\n\n\twatchPosition(callback){\n\t\tthis.positionWatchers.push(callback);\n\n\t\tcallback(this.position);\n\t}\n\t\n\tgetGroup(){\n\t\treturn this.modules.group || false;\n\t}\n\t\n\t//////////////// Object Generation /////////////////\n\tgetComponent(){\n\t\tif(!this.component){\n\t\t\tthis.component = new RowComponent(this);\n\t\t}\n\t\t\n\t\treturn this.component;\n\t}\n}\n\nvar defaultCalculations = {\n\t\"avg\":function(values, data, calcParams){\n\t\tvar output = 0,\n\t\tprecision = typeof calcParams.precision !== \"undefined\" ? calcParams.precision : 2;\n\n\t\tif(values.length){\n\t\t\toutput = values.reduce(function(sum, value){\n\t\t\t\treturn Number(sum) + Number(value);\n\t\t\t});\n\n\t\t\toutput = output / values.length;\n\n\t\t\toutput = precision !== false ? output.toFixed(precision) : output;\n\t\t}\n\n\t\treturn parseFloat(output).toString();\n\t},\n\t\"max\":function(values, data, calcParams){\n\t\tvar output = null,\n\t\tprecision = typeof calcParams.precision !== \"undefined\" ? calcParams.precision : false;\n\n\t\tvalues.forEach(function(value){\n\n\t\t\tvalue = Number(value);\n\n\t\t\tif(value > output || output === null){\n\t\t\t\toutput = value;\n\t\t\t}\n\t\t});\n\n\t\treturn output !== null ? (precision !== false ? output.toFixed(precision) : output) : \"\";\n\t},\n\t\"min\":function(values, data, calcParams){\n\t\tvar output = null,\n\t\tprecision = typeof calcParams.precision !== \"undefined\" ? calcParams.precision : false;\n\n\t\tvalues.forEach(function(value){\n\n\t\t\tvalue = Number(value);\n\n\t\t\tif(value < output || output === null){\n\t\t\t\toutput = value;\n\t\t\t}\n\t\t});\n\n\t\treturn output !== null ? (precision !== false ? output.toFixed(precision) : output) : \"\";\n\t},\n\t\"sum\":function(values, data, calcParams){\n\t\tvar output = 0,\n\t\tprecision = typeof calcParams.precision !== \"undefined\" ? calcParams.precision : false;\n\n\t\tif(values.length){\n\t\t\tvalues.forEach(function(value){\n\t\t\t\tvalue = Number(value);\n\n\t\t\t\toutput += !isNaN(value) ? Number(value) : 0;\n\t\t\t});\n\t\t}\n\n\t\treturn precision !== false ? output.toFixed(precision) : output;\n\t},\n\t\"concat\":function(values, data, calcParams){\n\t\tvar output = 0;\n\n\t\tif(values.length){\n\t\t\toutput = values.reduce(function(sum, value){\n\t\t\t\treturn String(sum) + String(value);\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t},\n\t\"count\":function(values, data, calcParams){\n\t\tvar output = 0;\n\n\t\tif(values.length){\n\t\t\tvalues.forEach(function(value){\n\t\t\t\tif(value){\n\t\t\t\t\toutput ++;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t},\n\t\"unique\":function(values, data, calcParams){\n\t\tvar unique = values.filter((value, index) => {\n\t\t\treturn (values || value === 0) && values.indexOf(value) === index;\n\t\t});\n\n\t\treturn unique.length;\n\t},\n};\n\nclass ColumnCalcs extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.topCalcs = [];\n\t\tthis.botCalcs = [];\n\t\tthis.genColumn = false;\n\t\tthis.topElement = this.createElement();\n\t\tthis.botElement = this.createElement();\n\t\tthis.topRow = false;\n\t\tthis.botRow = false;\n\t\tthis.topInitialized = false;\n\t\tthis.botInitialized = false;\n\t\t\n\t\tthis.blocked = false;\n\t\tthis.recalcAfterBlock = false;\n\t\t\n\t\tthis.registerTableOption(\"columnCalcs\", true);\n\t\t\n\t\tthis.registerColumnOption(\"topCalc\");\n\t\tthis.registerColumnOption(\"topCalcParams\");\n\t\tthis.registerColumnOption(\"topCalcFormatter\");\n\t\tthis.registerColumnOption(\"topCalcFormatterParams\");\n\t\tthis.registerColumnOption(\"bottomCalc\");\n\t\tthis.registerColumnOption(\"bottomCalcParams\");\n\t\tthis.registerColumnOption(\"bottomCalcFormatter\");\n\t\tthis.registerColumnOption(\"bottomCalcFormatterParams\");\n\t}\n\t\n\tcreateElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\tel.classList.add(\"tabulator-calcs-holder\");\n\t\treturn el;\n\t}\n\t\n\tinitialize(){\n\t\tthis.genColumn = new Column({field:\"value\"}, this);\n\t\t\n\t\tthis.subscribe(\"cell-value-changed\", this.cellValueChanged.bind(this));\n\t\tthis.subscribe(\"column-init\", this.initializeColumnCheck.bind(this));\n\t\tthis.subscribe(\"row-deleted\", this.rowsUpdated.bind(this));\n\t\tthis.subscribe(\"scroll-horizontal\", this.scrollHorizontal.bind(this));\n\t\tthis.subscribe(\"row-added\", this.rowsUpdated.bind(this));\n\t\tthis.subscribe(\"column-moved\", this.recalcActiveRows.bind(this));\n\t\tthis.subscribe(\"column-add\", this.recalcActiveRows.bind(this));\n\t\tthis.subscribe(\"data-refreshed\", this.recalcActiveRowsRefresh.bind(this));\n\t\tthis.subscribe(\"table-redraw\", this.tableRedraw.bind(this));\n\t\tthis.subscribe(\"rows-visible\", this.visibleRows.bind(this));\n\t\tthis.subscribe(\"scrollbar-vertical\", this.adjustForScrollbar.bind(this));\n\t\t\n\t\tthis.subscribe(\"redraw-blocked\", this.blockRedraw.bind(this));\n\t\tthis.subscribe(\"redraw-restored\", this.restoreRedraw.bind(this));\n\n\t\tthis.subscribe(\"table-redrawing\", this.resizeHolderWidth.bind(this));\n\t\tthis.subscribe(\"column-resized\", this.resizeHolderWidth.bind(this));\n\t\tthis.subscribe(\"column-show\", this.resizeHolderWidth.bind(this));\n\t\tthis.subscribe(\"column-hide\", this.resizeHolderWidth.bind(this));\n\t\t\n\t\tthis.registerTableFunction(\"getCalcResults\", this.getResults.bind(this));\n\t\tthis.registerTableFunction(\"recalc\", this.userRecalc.bind(this));\n\n\n\t\tthis.resizeHolderWidth();\n\t}\n\n\tresizeHolderWidth(){\n\t\tthis.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + \"px\";\n\t}\n\n\t\n\ttableRedraw(force){\n\t\tthis.recalc(this.table.rowManager.activeRows);\n\t\t\n\t\tif(force){\n\t\t\tthis.redraw();\n\t\t}\n\t}\n\t\n\tblockRedraw(){\n\t\tthis.blocked = true;\n\t\tthis.recalcAfterBlock = false;\n\t}\n\t\n\t\n\trestoreRedraw(){\n\t\tthis.blocked = false;\n\t\t\n\t\tif(this.recalcAfterBlock){\n\t\t\tthis.recalcAfterBlock = false;\n\t\t\tthis.recalcActiveRowsRefresh();\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\tuserRecalc(){\n\t\tthis.recalc(this.table.rowManager.activeRows);\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\tblockCheck(){\n\t\tif(this.blocked){\n\t\t\tthis.recalcAfterBlock = true;\n\t\t}\n\t\t\n\t\treturn this.blocked;\n\t}\n\t\n\tvisibleRows(viewable, rows){\n\t\tif(this.topRow){\n\t\t\trows.unshift(this.topRow);\n\t\t}\n\t\t\n\t\tif(this.botRow){\n\t\t\trows.push(this.botRow);\n\t\t}\n\t\t\n\t\treturn rows;\n\t}\n\t\n\trowsUpdated(row){\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.recalcRowGroup(row);\n\t\t}else {\n\t\t\tthis.recalcActiveRows();\n\t\t}\n\t}\n\t\n\trecalcActiveRowsRefresh(){\n\t\tif(this.table.options.groupBy && this.table.options.dataTreeStartExpanded && this.table.options.dataTree){\n\t\t\tthis.recalcAll();\n\t\t}else {\n\t\t\tthis.recalcActiveRows();\n\t\t}\n\t}\n\t\n\trecalcActiveRows(){\n\t\tthis.recalc(this.table.rowManager.activeRows);\n\t}\n\t\n\tcellValueChanged(cell){\n\t\tif(cell.column.definition.topCalc || cell.column.definition.bottomCalc){\n\t\t\tif(this.table.options.groupBy){\n\t\t\t\tif(this.table.options.columnCalcs == \"table\" || this.table.options.columnCalcs == \"both\"){\n\t\t\t\t\tthis.recalcActiveRows();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.table.options.columnCalcs != \"table\"){\n\t\t\t\t\tthis.recalcRowGroup(cell.row);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.recalcActiveRows();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tinitializeColumnCheck(column){\n\t\tif(column.definition.topCalc || column.definition.bottomCalc){\n\t\t\tthis.initializeColumn(column);\n\t\t}\n\t}\n\t\n\t//initialize column calcs\n\tinitializeColumn(column){\n\t\tvar def = column.definition;\n\t\t\n\t\tvar config = {\n\t\t\ttopCalcParams:def.topCalcParams || {},\n\t\t\tbotCalcParams:def.bottomCalcParams || {},\n\t\t};\n\t\t\n\t\tif(def.topCalc){\n\t\t\t\n\t\t\tswitch(typeof def.topCalc){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tif(ColumnCalcs.calculations[def.topCalc]){\n\t\t\t\t\t\tconfig.topCalc = ColumnCalcs.calculations[def.topCalc];\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Column Calc Error - No such calculation found, ignoring: \", def.topCalc);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"function\":\n\t\t\t\t\tconfig.topCalc = def.topCalc;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif(config.topCalc){\n\t\t\t\tcolumn.modules.columnCalcs = config;\n\t\t\t\tthis.topCalcs.push(column);\n\t\t\t\t\n\t\t\t\tif(this.table.options.columnCalcs != \"group\"){\n\t\t\t\t\tthis.initializeTopRow();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t}\n\t\t\n\t\tif(def.bottomCalc){\n\t\t\tswitch(typeof def.bottomCalc){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tif(ColumnCalcs.calculations[def.bottomCalc]){\n\t\t\t\t\t\tconfig.botCalc = ColumnCalcs.calculations[def.bottomCalc];\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Column Calc Error - No such calculation found, ignoring: \", def.bottomCalc);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"function\":\n\t\t\t\t\tconfig.botCalc = def.bottomCalc;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif(config.botCalc){\n\t\t\t\tcolumn.modules.columnCalcs = config;\n\t\t\t\tthis.botCalcs.push(column);\n\t\t\t\t\n\t\t\t\tif(this.table.options.columnCalcs != \"group\"){\n\t\t\t\t\tthis.initializeBottomRow();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\t//dummy functions to handle being mock column manager\n\tregisterColumnField(){}\n\t\n\tremoveCalcs(){\n\t\tvar changed = false;\n\t\t\n\t\tif(this.topInitialized){\n\t\t\tthis.topInitialized = false;\n\t\t\tthis.topElement.parentNode.removeChild(this.topElement);\n\t\t\tchanged = true;\n\t\t}\n\t\t\n\t\tif(this.botInitialized){\n\t\t\tthis.botInitialized = false;\n\t\t\tthis.footerRemove(this.botElement);\n\t\t\tchanged = true;\n\t\t}\n\t\t\n\t\tif(changed){\n\t\t\tthis.table.rowManager.adjustTableSize();\n\t\t}\n\t}\n\t\n\treinitializeCalcs(){\n\t\tif(this.topCalcs.length){\n\t\t\tthis.initializeTopRow();\n\t\t}\n\n\t\tif(this.botCalcs.length){\n\t\t\tthis.initializeBottomRow();\n\t\t}\n\t}\n\t\n\tinitializeTopRow(){\n\t\tvar\tfragment = document.createDocumentFragment();\n\t\t\n\t\tif(!this.topInitialized){\n\n\t\t\tfragment.appendChild(document.createElement(\"br\"));\n\t\t\tfragment.appendChild(this.topElement);\n\n\t\t\tthis.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling);\n\t\t\tthis.topInitialized = true;\n\t\t}\n\t}\n\t\n\tinitializeBottomRow(){\n\t\tif(!this.botInitialized){\n\t\t\tthis.footerPrepend(this.botElement);\n\t\t\tthis.botInitialized = true;\n\t\t}\n\t}\n\t\n\tscrollHorizontal(left){\n\t\tif(this.botInitialized && this.botRow){\n\t\t\tthis.botElement.scrollLeft = left;\n\t\t}\n\t}\n\t\n\trecalc(rows){\n\t\tvar data, row;\n\t\t\n\t\tif(!this.blockCheck()){\n\t\t\tif(this.topInitialized || this.botInitialized){\n\t\t\t\tdata = this.rowsToData(rows);\n\t\t\t\t\n\t\t\t\tif(this.topInitialized){\n\t\t\t\t\tif(this.topRow){\n\t\t\t\t\t\tthis.topRow.deleteCells();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\trow = this.generateRow(\"top\", data);\n\t\t\t\t\tthis.topRow = row;\n\t\t\t\t\twhile(this.topElement.firstChild) this.topElement.removeChild(this.topElement.firstChild);\n\t\t\t\t\tthis.topElement.appendChild(row.getElement());\n\t\t\t\t\trow.initialize(true);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.botInitialized){\n\t\t\t\t\tif(this.botRow){\n\t\t\t\t\t\tthis.botRow.deleteCells();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\trow = this.generateRow(\"bottom\", data);\n\t\t\t\t\tthis.botRow = row;\n\t\t\t\t\twhile(this.botElement.firstChild) this.botElement.removeChild(this.botElement.firstChild);\n\t\t\t\t\tthis.botElement.appendChild(row.getElement());\n\t\t\t\t\trow.initialize(true);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.table.rowManager.adjustTableSize();\n\t\t\t\t\n\t\t\t\t//set resizable handles\n\t\t\t\tif(this.table.modExists(\"frozenColumns\")){\n\t\t\t\t\tthis.table.modules.frozenColumns.layout();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\trecalcRowGroup(row){\n\t\tthis.recalcGroup(this.table.modules.groupRows.getRowGroup(row));\n\t}\n\t\n\trecalcAll(){\n\t\tif(this.topCalcs.length || this.botCalcs.length){\n\t\t\tif(this.table.options.columnCalcs !== \"group\"){\n\t\t\t\tthis.recalcActiveRows();\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.options.groupBy && this.table.options.columnCalcs !== \"table\"){\n\t\t\t\t\n\t\t\t\tvar groups = this.table.modules.groupRows.getChildGroups();\n\t\t\t\t\n\t\t\t\tgroups.forEach((group) => {\n\t\t\t\t\tthis.recalcGroup(group);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\t\n\trecalcGroup(group){\n\t\tvar data, rowData;\n\t\t\n\t\tif(!this.blockCheck()){\n\t\t\tif(group){\n\t\t\t\tif(group.calcs){\n\t\t\t\t\tif(group.calcs.bottom){\n\t\t\t\t\t\tdata = this.rowsToData(group.rows);\n\t\t\t\t\t\trowData = this.generateRowData(\"bottom\", data);\n\t\t\t\t\t\t\n\t\t\t\t\t\tgroup.calcs.bottom.updateData(rowData);\n\t\t\t\t\t\tgroup.calcs.bottom.reinitialize();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif(group.calcs.top){\n\t\t\t\t\t\tdata = this.rowsToData(group.rows);\n\t\t\t\t\t\trowData = this.generateRowData(\"top\", data);\n\t\t\t\t\t\t\n\t\t\t\t\t\tgroup.calcs.top.updateData(rowData);\n\t\t\t\t\t\tgroup.calcs.top.reinitialize();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//generate top stats row\n\tgenerateTopRow(rows){\n\t\treturn this.generateRow(\"top\", this.rowsToData(rows));\n\t}\n\t//generate bottom stats row\n\tgenerateBottomRow(rows){\n\t\treturn this.generateRow(\"bottom\", this.rowsToData(rows));\n\t}\n\t\n\trowsToData(rows){\n\t\tvar data = [];\n\t\t\n\t\trows.forEach((row) => {\n\t\t\tdata.push(row.getData());\n\t\t\t\n\t\t\tif(this.table.options.dataTree && this.table.options.dataTreeChildColumnCalcs){\n\t\t\t\tif(row.modules.dataTree && row.modules.dataTree.open){\n\t\t\t\t\tvar children = this.rowsToData(this.table.modules.dataTree.getFilteredTreeChildren(row));\n\t\t\t\t\tdata = data.concat(children);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn data;\n\t}\n\t\n\t//generate stats row\n\tgenerateRow(pos, data){\n\t\tvar rowData = this.generateRowData(pos, data),\n\t\trow;\n\t\t\n\t\tif(this.table.modExists(\"mutator\")){\n\t\t\tthis.table.modules.mutator.disable();\n\t\t}\n\t\t\n\t\trow = new Row(rowData, this, \"calc\");\n\t\t\n\t\tif(this.table.modExists(\"mutator\")){\n\t\t\tthis.table.modules.mutator.enable();\n\t\t}\n\t\t\n\t\trow.getElement().classList.add(\"tabulator-calcs\", \"tabulator-calcs-\" + pos);\n\t\t\n\t\trow.component = false;\n\t\t\n\t\trow.getComponent = () => {\n\t\t\tif(!row.component){\n\t\t\t\trow.component = new CalcComponent(row);\n\t\t\t}\n\t\t\t\n\t\t\treturn row.component;\n\t\t};\n\t\t\n\t\trow.generateCells = () => {\n\t\t\t\n\t\t\tvar cells = [];\n\t\t\t\n\t\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\t\t\n\t\t\t\t//set field name of mock column\n\t\t\t\tthis.genColumn.setField(column.getField());\n\t\t\t\tthis.genColumn.hozAlign = column.hozAlign;\n\t\t\t\t\n\t\t\t\tif(column.definition[pos + \"CalcFormatter\"] && this.table.modExists(\"format\")){\n\t\t\t\t\tthis.genColumn.modules.format = {\n\t\t\t\t\t\tformatter: this.table.modules.format.getFormatter(column.definition[pos + \"CalcFormatter\"]),\n\t\t\t\t\t\tparams: column.definition[pos + \"CalcFormatterParams\"] || {},\n\t\t\t\t\t};\n\t\t\t\t}else {\n\t\t\t\t\tthis.genColumn.modules.format = {\n\t\t\t\t\t\tformatter: this.table.modules.format.getFormatter(\"plaintext\"),\n\t\t\t\t\t\tparams:{}\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//ensure css class definition is replicated to calculation cell\n\t\t\t\tthis.genColumn.definition.cssClass = column.definition.cssClass;\n\t\t\t\t\n\t\t\t\t//generate cell and assign to correct column\n\t\t\t\tvar cell = new Cell(this.genColumn, row);\n\t\t\t\tcell.getElement();\n\t\t\t\tcell.column = column;\n\t\t\t\tcell.setWidth();\n\t\t\t\t\n\t\t\t\tcolumn.cells.push(cell);\n\t\t\t\tcells.push(cell);\n\t\t\t\t\n\t\t\t\tif(!column.visible){\n\t\t\t\t\tcell.hide();\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\trow.cells = cells;\n\t\t};\n\t\t\n\t\treturn row;\n\t}\n\t\n\t//generate stats row\n\tgenerateRowData(pos, data){\n\t\tvar rowData = {},\n\t\tcalcs = pos == \"top\" ? this.topCalcs : this.botCalcs,\n\t\ttype = pos == \"top\" ? \"topCalc\" : \"botCalc\",\n\t\tparams, paramKey;\n\t\t\n\t\tcalcs.forEach(function(column){\n\t\t\tvar values = [];\n\t\t\t\n\t\t\tif(column.modules.columnCalcs && column.modules.columnCalcs[type]){\n\t\t\t\tdata.forEach(function(item){\n\t\t\t\t\tvalues.push(column.getFieldValue(item));\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tparamKey = type + \"Params\";\n\t\t\t\tparams = typeof column.modules.columnCalcs[paramKey] === \"function\" ? column.modules.columnCalcs[paramKey](values, data) : column.modules.columnCalcs[paramKey];\n\t\t\t\t\n\t\t\t\tcolumn.setFieldValue(rowData, column.modules.columnCalcs[type](values, data, params));\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn rowData;\n\t}\n\t\n\thasTopCalcs(){\n\t\treturn\t!!(this.topCalcs.length);\n\t}\n\t\n\thasBottomCalcs(){\n\t\treturn\t!!(this.botCalcs.length);\n\t}\n\t\n\t//handle table redraw\n\tredraw(){\n\t\tif(this.topRow){\n\t\t\tthis.topRow.normalizeHeight(true);\n\t\t}\n\t\tif(this.botRow){\n\t\t\tthis.botRow.normalizeHeight(true);\n\t\t}\n\t}\n\t\n\t//return the calculated\n\tgetResults(){\n\t\tvar results = {},\n\t\tgroups;\n\t\t\n\t\tif(this.table.options.groupBy && this.table.modExists(\"groupRows\")){\n\t\t\tgroups = this.table.modules.groupRows.getGroups(true);\n\t\t\t\n\t\t\tgroups.forEach((group) => {\n\t\t\t\tresults[group.getKey()] = this.getGroupResults(group);\n\t\t\t});\n\t\t}else {\n\t\t\tresults = {\n\t\t\t\ttop: this.topRow ? this.topRow.getData() : {},\n\t\t\t\tbottom: this.botRow ? this.botRow.getData() : {},\n\t\t\t};\n\t\t}\n\t\t\n\t\treturn results;\n\t}\n\t\n\t//get results from a group\n\tgetGroupResults(group){\n\t\tvar groupObj = group._getSelf(),\n\t\tsubGroups = group.getSubGroups(),\n\t\tsubGroupResults = {},\n\t\tresults = {};\n\t\t\n\t\tsubGroups.forEach((subgroup) => {\n\t\t\tsubGroupResults[subgroup.getKey()] = this.getGroupResults(subgroup);\n\t\t});\n\t\t\n\t\tresults = {\n\t\t\ttop: groupObj.calcs.top ? groupObj.calcs.top.getData() : {},\n\t\t\tbottom: groupObj.calcs.bottom ? groupObj.calcs.bottom.getData() : {},\n\t\t\tgroups: subGroupResults,\n\t\t};\n\t\t\n\t\treturn results;\n\t}\n\t\n\tadjustForScrollbar(width){\n\t\tif(this.botRow){\n\t\t\tif(this.table.rtl){\n\t\t\t\tthis.botElement.style.paddingLeft = width + \"px\";\n\t\t\t}else {\n\t\t\t\tthis.botElement.style.paddingRight = width + \"px\";\n\t\t\t}\n\t\t}\n\t}\n}\n\nColumnCalcs.moduleName = \"columnCalcs\";\n\n//load defaults\nColumnCalcs.calculations = defaultCalculations;\n\nclass DataTree extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.indent = 10;\n\t\tthis.field = \"\";\n\t\tthis.collapseEl = null;\n\t\tthis.expandEl = null;\n\t\tthis.branchEl = null;\n\t\tthis.elementField = false;\n\n\t\tthis.startOpen = function(){};\n\n\t\tthis.registerTableOption(\"dataTree\", false); //enable data tree\n\t\tthis.registerTableOption(\"dataTreeFilter\", true); //filter child rows\n\t\tthis.registerTableOption(\"dataTreeSort\", true); //sort child rows\n\t\tthis.registerTableOption(\"dataTreeElementColumn\", false);\n\t\tthis.registerTableOption(\"dataTreeBranchElement\", true);//show data tree branch element\n\t\tthis.registerTableOption(\"dataTreeChildIndent\", 9); //data tree child indent in px\n\t\tthis.registerTableOption(\"dataTreeChildField\", \"_children\");//data tre column field to look for child rows\n\t\tthis.registerTableOption(\"dataTreeCollapseElement\", false);//data tree row collapse element\n\t\tthis.registerTableOption(\"dataTreeExpandElement\", false);//data tree row expand element\n\t\tthis.registerTableOption(\"dataTreeStartExpanded\", false);\n\t\tthis.registerTableOption(\"dataTreeChildColumnCalcs\", false);//include visible data tree rows in column calculations\n\t\tthis.registerTableOption(\"dataTreeSelectPropagate\", false);//selecting a parent row selects its children\n\n\t\t//register component functions\n\t\tthis.registerComponentFunction(\"row\", \"treeCollapse\", this.collapseRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"treeExpand\", this.expandRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"treeToggle\", this.toggleRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"getTreeParent\", this.getTreeParent.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"getTreeChildren\", this.getRowChildren.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"addTreeChild\", this.addTreeChildRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"isTreeExpanded\", this.isRowExpanded.bind(this));\n\t}\n\n\tinitialize(){\n\t\tif(this.table.options.dataTree){\n\t\t\tvar dummyEl = null,\n\t\t\toptions = this.table.options;\n\n\t\t\tthis.field = options.dataTreeChildField;\n\t\t\tthis.indent = options.dataTreeChildIndent;\n\n\t\t\tif(this.options(\"movableRows\")){\n\t\t\t\tconsole.warn(\"The movableRows option is not available with dataTree enabled, moving of child rows could result in unpredictable behavior\");\n\t\t\t}\n\n\t\t\tif(options.dataTreeBranchElement){\n\n\t\t\t\tif(options.dataTreeBranchElement === true){\n\t\t\t\t\tthis.branchEl = document.createElement(\"div\");\n\t\t\t\t\tthis.branchEl.classList.add(\"tabulator-data-tree-branch\");\n\t\t\t\t}else {\n\t\t\t\t\tif(typeof options.dataTreeBranchElement === \"string\"){\n\t\t\t\t\t\tdummyEl = document.createElement(\"div\");\n\t\t\t\t\t\tdummyEl.innerHTML = options.dataTreeBranchElement;\n\t\t\t\t\t\tthis.branchEl = dummyEl.firstChild;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.branchEl = options.dataTreeBranchElement;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.branchEl = document.createElement(\"div\");\n\t\t\t\tthis.branchEl.classList.add(\"tabulator-data-tree-branch-empty\");\n\t\t\t}\n\n\t\t\tif(options.dataTreeCollapseElement){\n\t\t\t\tif(typeof options.dataTreeCollapseElement === \"string\"){\n\t\t\t\t\tdummyEl = document.createElement(\"div\");\n\t\t\t\t\tdummyEl.innerHTML = options.dataTreeCollapseElement;\n\t\t\t\t\tthis.collapseEl = dummyEl.firstChild;\n\t\t\t\t}else {\n\t\t\t\t\tthis.collapseEl = options.dataTreeCollapseElement;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.collapseEl = document.createElement(\"div\");\n\t\t\t\tthis.collapseEl.classList.add(\"tabulator-data-tree-control\");\n\t\t\t\tthis.collapseEl.tabIndex = 0;\n\t\t\t\tthis.collapseEl.innerHTML = \"<div class='tabulator-data-tree-control-collapse'></div>\";\n\t\t\t}\n\n\t\t\tif(options.dataTreeExpandElement){\n\t\t\t\tif(typeof options.dataTreeExpandElement === \"string\"){\n\t\t\t\t\tdummyEl = document.createElement(\"div\");\n\t\t\t\t\tdummyEl.innerHTML = options.dataTreeExpandElement;\n\t\t\t\t\tthis.expandEl = dummyEl.firstChild;\n\t\t\t\t}else {\n\t\t\t\t\tthis.expandEl = options.dataTreeExpandElement;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.expandEl = document.createElement(\"div\");\n\t\t\t\tthis.expandEl.classList.add(\"tabulator-data-tree-control\");\n\t\t\t\tthis.expandEl.tabIndex = 0;\n\t\t\t\tthis.expandEl.innerHTML = \"<div class='tabulator-data-tree-control-expand'></div>\";\n\t\t\t}\n\n\n\t\t\tswitch(typeof options.dataTreeStartExpanded){\n\t\t\t\tcase \"boolean\":\n\t\t\t\t\tthis.startOpen = function(row, index){\n\t\t\t\t\t\treturn options.dataTreeStartExpanded;\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"function\":\n\t\t\t\t\tthis.startOpen = options.dataTreeStartExpanded;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tthis.startOpen = function(row, index){\n\t\t\t\t\t\treturn options.dataTreeStartExpanded[index];\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis.subscribe(\"row-init\", this.initializeRow.bind(this));\n\t\t\tthis.subscribe(\"row-layout-after\", this.layoutRow.bind(this));\n\t\t\tthis.subscribe(\"row-deleted\", this.rowDelete.bind(this),0);\n\t\t\tthis.subscribe(\"row-data-changed\", this.rowDataChanged.bind(this), 10);\n\t\t\tthis.subscribe(\"cell-value-updated\", this.cellValueChanged.bind(this));\n\t\t\tthis.subscribe(\"edit-cancelled\", this.cellValueChanged.bind(this));\n\t\t\tthis.subscribe(\"column-moving-rows\", this.columnMoving.bind(this));\n\t\t\tthis.subscribe(\"table-built\", this.initializeElementField.bind(this));\n\t\t\tthis.subscribe(\"table-redrawing\", this.tableRedrawing.bind(this));\n\n\t\t\tthis.registerDisplayHandler(this.getRows.bind(this), 30);\n\t\t}\n\t}\n\n\ttableRedrawing(force){\n\t\tvar rows;\n\n\t\tif(force){\n\t\t\trows = this.table.rowManager.getRows();\n\t\t\t\n\t\t\trows.forEach((row) => {\n\t\t\t\tthis.reinitializeRowChildren(row);\n\t\t\t});\n\t\t}\n\t}\n\n\tinitializeElementField(){\n\t\tvar firstCol = this.table.columnManager.getFirstVisibleColumn();\n\n\t\tthis.elementField = this.table.options.dataTreeElementColumn || (firstCol ? firstCol.field : false);\n\t}\n\t\n\tgetRowChildren(row){\n\t\treturn this.getTreeChildren(row, true);\n\t}\n\n\tcolumnMoving(){\n\t\tvar rows = [];\n\n\t\tthis.table.rowManager.rows.forEach((row) => {\n\t\t\trows = rows.concat(this.getTreeChildren(row, false, true));\n\t\t});\n\n\t\treturn rows;\n\t}\n\n\trowDataChanged(row, visible, updatedData){\n\t\tif(this.redrawNeeded(updatedData)){\n\t\t\tthis.initializeRow(row);\n\n\t\t\tif(visible){\n\t\t\t\tthis.layoutRow(row);\n\t\t\t\tthis.refreshData(true);\n\t\t\t}\n\t\t}\n\t}\n\n\tcellValueChanged(cell){\n\t\tvar field = cell.column.getField();\n\n\t\tif(field === this.elementField){\n\t\t\tthis.layoutRow(cell.row);\n\t\t}\n\t}\n\n\tinitializeRow(row){\n\t\tvar childArray = row.getData()[this.field];\n\t\tvar isArray = Array.isArray(childArray);\n\n\t\tvar children = isArray || (!isArray && typeof childArray === \"object\" && childArray !== null);\n\n\t\tif(!children && row.modules.dataTree && row.modules.dataTree.branchEl){\n\t\t\trow.modules.dataTree.branchEl.parentNode.removeChild(row.modules.dataTree.branchEl);\n\t\t}\n\n\t\tif(!children && row.modules.dataTree && row.modules.dataTree.controlEl){\n\t\t\trow.modules.dataTree.controlEl.parentNode.removeChild(row.modules.dataTree.controlEl);\n\t\t}\n\n\t\trow.modules.dataTree = {\n\t\t\tindex: row.modules.dataTree ? row.modules.dataTree.index : 0,\n\t\t\topen: children ? (row.modules.dataTree ? row.modules.dataTree.open : this.startOpen(row.getComponent(), 0)) : false,\n\t\t\tcontrolEl: row.modules.dataTree && children ? row.modules.dataTree.controlEl : false,\n\t\t\tbranchEl: row.modules.dataTree && children ? row.modules.dataTree.branchEl : false,\n\t\t\tparent: row.modules.dataTree ? row.modules.dataTree.parent : false,\n\t\t\tchildren:children,\n\t\t};\n\t}\n\n\treinitializeRowChildren(row){\n\t\tvar children = this.getTreeChildren(row, false, true);\n\n\t\tchildren.forEach(function(child){\n\t\t\tchild.reinitialize(true);\n\t\t});\n\t}\n\n\tlayoutRow(row){\n\t\tvar cell = this.elementField ? row.getCell(this.elementField) : row.getCells()[0],\n\t\tel = cell.getElement(),\n\t\tconfig = row.modules.dataTree;\n\n\t\tif(config.branchEl){\n\t\t\tif(config.branchEl.parentNode){\n\t\t\t\tconfig.branchEl.parentNode.removeChild(config.branchEl);\n\t\t\t}\n\t\t\tconfig.branchEl = false;\n\t\t}\n\n\t\tif(config.controlEl){\n\t\t\tif(config.controlEl.parentNode){\n\t\t\t\tconfig.controlEl.parentNode.removeChild(config.controlEl);\n\t\t\t}\n\t\t\tconfig.controlEl = false;\n\t\t}\n\n\t\tthis.generateControlElement(row, el);\n\n\t\trow.getElement().classList.add(\"tabulator-tree-level-\" + config.index);\n\n\t\tif(config.index){\n\t\t\tif(this.branchEl){\n\t\t\t\tconfig.branchEl = this.branchEl.cloneNode(true);\n\t\t\t\tel.insertBefore(config.branchEl, el.firstChild);\n\n\t\t\t\tif(this.table.rtl){\n\t\t\t\t\tconfig.branchEl.style.marginRight = (((config.branchEl.offsetWidth + config.branchEl.style.marginLeft) * (config.index - 1)) + (config.index * this.indent)) + \"px\";\n\t\t\t\t}else {\n\t\t\t\t\tconfig.branchEl.style.marginLeft = (((config.branchEl.offsetWidth + config.branchEl.style.marginRight) * (config.index - 1)) + (config.index * this.indent)) + \"px\";\n\t\t\t\t}\n\t\t\t}else {\n\n\t\t\t\tif(this.table.rtl){\n\t\t\t\t\tel.style.paddingRight = parseInt(window.getComputedStyle(el, null).getPropertyValue('padding-right')) + (config.index * this.indent) + \"px\";\n\t\t\t\t}else {\n\t\t\t\t\tel.style.paddingLeft = parseInt(window.getComputedStyle(el, null).getPropertyValue('padding-left')) + (config.index * this.indent) + \"px\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgenerateControlElement(row, el){\n\t\tvar config = row.modules.dataTree,\n\t\toldControl = config.controlEl;\n\n\t\tel = el || row.getCells()[0].getElement();\n\n\t\tif(config.children !== false){\n\n\t\t\tif(config.open){\n\t\t\t\tconfig.controlEl = this.collapseEl.cloneNode(true);\n\t\t\t\tconfig.controlEl.addEventListener(\"click\", (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tthis.collapseRow(row);\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tconfig.controlEl = this.expandEl.cloneNode(true);\n\t\t\t\tconfig.controlEl.addEventListener(\"click\", (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tthis.expandRow(row);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconfig.controlEl.addEventListener(\"mousedown\", (e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\n\t\t\tif(oldControl && oldControl.parentNode === el){\n\t\t\t\toldControl.parentNode.replaceChild(config.controlEl,oldControl);\n\t\t\t}else {\n\t\t\t\tel.insertBefore(config.controlEl, el.firstChild);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetRows(rows){\n\t\tvar output = [];\n\n\t\trows.forEach((row, i) => {\n\t\t\tvar config, children;\n\n\t\t\toutput.push(row);\n\n\t\t\tif(row instanceof Row){\n\n\t\t\t\trow.create();\n\n\t\t\t\tconfig = row.modules.dataTree;\n\n\t\t\t\tif(!config.index && config.children !== false){\n\t\t\t\t\tchildren = this.getChildren(row);\n\n\t\t\t\t\tchildren.forEach((child) => {\n\t\t\t\t\t\tchild.create();\n\t\t\t\t\t\toutput.push(child);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\n\tgetChildren(row, allChildren){\n\t\tvar config = row.modules.dataTree,\n\t\tchildren = [],\n\t\toutput = [];\n\n\t\tif(config.children !== false && (config.open || allChildren)){\n\t\t\tif(!Array.isArray(config.children)){\n\t\t\t\tconfig.children = this.generateChildren(row);\n\t\t\t}\n\n\t\t\tif(this.table.modExists(\"filter\") && this.table.options.dataTreeFilter){\n\t\t\t\tchildren = this.table.modules.filter.filter(config.children);\n\t\t\t}else {\n\t\t\t\tchildren = config.children;\n\t\t\t}\n\n\t\t\tif(this.table.modExists(\"sort\") && this.table.options.dataTreeSort){\n\t\t\t\tthis.table.modules.sort.sort(children);\n\t\t\t}\n\n\t\t\tchildren.forEach((child) => {\n\t\t\t\toutput.push(child);\n\n\t\t\t\tvar subChildren = this.getChildren(child);\n\n\t\t\t\tsubChildren.forEach((sub) => {\n\t\t\t\t\toutput.push(sub);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tgenerateChildren(row){\n\t\tvar children = [];\n\n\t\tvar childArray = row.getData()[this.field];\n\n\t\tif(!Array.isArray(childArray)){\n\t\t\tchildArray = [childArray];\n\t\t}\n\n\t\tchildArray.forEach((childData) => {\n\t\t\tvar childRow = new Row(childData || {}, this.table.rowManager);\n\n\t\t\tchildRow.create();\n\n\t\t\tchildRow.modules.dataTree.index = row.modules.dataTree.index + 1;\n\t\t\tchildRow.modules.dataTree.parent = row;\n\n\t\t\tif(childRow.modules.dataTree.children){\n\t\t\t\tchildRow.modules.dataTree.open = this.startOpen(childRow.getComponent(), childRow.modules.dataTree.index);\n\t\t\t}\n\t\t\tchildren.push(childRow);\n\t\t});\n\n\t\treturn children;\n\t}\n\n\texpandRow(row, silent){\n\t\tvar config = row.modules.dataTree;\n\n\t\tif(config.children !== false){\n\t\t\tconfig.open = true;\n\n\t\t\trow.reinitialize();\n\n\t\t\tthis.refreshData(true);\n\n\t\t\tthis.dispatchExternal(\"dataTreeRowExpanded\", row.getComponent(), row.modules.dataTree.index);\n\t\t}\n\t}\n\n\tcollapseRow(row){\n\t\tvar config = row.modules.dataTree;\n\n\t\tif(config.children !== false){\n\t\t\tconfig.open = false;\n\n\t\t\trow.reinitialize();\n\n\t\t\tthis.refreshData(true);\n\n\t\t\tthis.dispatchExternal(\"dataTreeRowCollapsed\", row.getComponent(), row.modules.dataTree.index);\n\t\t}\n\t}\n\n\ttoggleRow(row){\n\t\tvar config = row.modules.dataTree;\n\n\t\tif(config.children !== false){\n\t\t\tif(config.open){\n\t\t\t\tthis.collapseRow(row);\n\t\t\t}else {\n\t\t\t\tthis.expandRow(row);\n\t\t\t}\n\t\t}\n\t}\n\n\tisRowExpanded(row){\n\t\treturn row.modules.dataTree.open;\n\t}\n\n\tgetTreeParent(row){\n\t\treturn row.modules.dataTree.parent ? row.modules.dataTree.parent.getComponent() : false;\n\t}\n\n\tgetTreeParentRoot(row){\n\t\treturn row.modules.dataTree && row.modules.dataTree.parent ? this.getTreeParentRoot(row.modules.dataTree.parent) : row;\n\t}\n\n\tgetFilteredTreeChildren(row){\n\t\tvar config = row.modules.dataTree,\n\t\toutput = [], children;\n\n\t\tif(config.children){\n\n\t\t\tif(!Array.isArray(config.children)){\n\t\t\t\tconfig.children = this.generateChildren(row);\n\t\t\t}\n\n\t\t\tif(this.table.modExists(\"filter\") && this.table.options.dataTreeFilter){\n\t\t\t\tchildren = this.table.modules.filter.filter(config.children);\n\t\t\t}else {\n\t\t\t\tchildren = config.children;\n\t\t\t}\n\n\t\t\tchildren.forEach((childRow) => {\n\t\t\t\tif(childRow instanceof Row){\n\t\t\t\t\toutput.push(childRow);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t}\n\n\trowDelete(row){\n\t\tvar parent = row.modules.dataTree.parent,\n\t\tchildIndex;\n\n\t\tif(parent){\n\t\t\tchildIndex = this.findChildIndex(row, parent);\n\n\t\t\tif(childIndex !== false){\n\t\t\t\tparent.data[this.field].splice(childIndex, 1);\n\t\t\t}\n\n\t\t\tif(!parent.data[this.field].length){\n\t\t\t\tdelete parent.data[this.field];\n\t\t\t}\n\n\t\t\tthis.initializeRow(parent);\n\t\t\tthis.layoutRow(parent);\n\t\t}\n\n\t\tthis.refreshData(true);\n\t}\n\n\taddTreeChildRow(row, data, top, index){\n\t\tvar childIndex = false;\n\n\t\tif(typeof data === \"string\"){\n\t\t\tdata = JSON.parse(data);\n\t\t}\n\n\t\tif(!Array.isArray(row.data[this.field])){\n\t\t\trow.data[this.field] = [];\n\n\t\t\trow.modules.dataTree.open = this.startOpen(row.getComponent(), row.modules.dataTree.index);\n\t\t}\n\n\t\tif(typeof index !== \"undefined\"){\n\t\t\tchildIndex = this.findChildIndex(index, row);\n\n\t\t\tif(childIndex !== false){\n\t\t\t\trow.data[this.field].splice((top ? childIndex : childIndex + 1), 0, data);\n\t\t\t}\n\t\t}\n\n\t\tif(childIndex === false){\n\t\t\tif(top){\n\t\t\t\trow.data[this.field].unshift(data);\n\t\t\t}else {\n\t\t\t\trow.data[this.field].push(data);\n\t\t\t}\n\t\t}\n\n\t\tthis.initializeRow(row);\n\t\tthis.layoutRow(row);\n\n\t\tthis.refreshData(true);\n\t}\n\n\tfindChildIndex(subject, parent){\n\t\tvar match = false;\n\n\t\tif(typeof subject == \"object\"){\n\n\t\t\tif(subject instanceof Row){\n\t\t\t\t//subject is row element\n\t\t\t\tmatch = subject.data;\n\t\t\t}else if(subject instanceof RowComponent){\n\t\t\t\t//subject is public row component\n\t\t\t\tmatch = subject._getSelf().data;\n\t\t\t}else if(typeof HTMLElement !== \"undefined\" && subject instanceof HTMLElement){\n\t\t\t\tif(parent.modules.dataTree){\n\t\t\t\t\tmatch = parent.modules.dataTree.children.find((childRow) => {\n\t\t\t\t\t\treturn childRow instanceof Row ? childRow.element === subject : false;\n\t\t\t\t\t});\n\n\t\t\t\t\tif(match){\n\t\t\t\t\t\tmatch = match.data;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else if(subject === null){\n\t\t\t\tmatch = false;\n\t\t\t}\n\n\t\t}else if(typeof subject == \"undefined\"){\n\t\t\tmatch = false;\n\t\t}else {\n\t\t\t//subject should be treated as the index of the row\n\t\t\tmatch = parent.data[this.field].find((row) => {\n\t\t\t\treturn row.data[this.table.options.index] == subject;\n\t\t\t});\n\t\t}\n\n\t\tif(match){\n\n\t\t\tif(Array.isArray(parent.data[this.field])){\n\t\t\t\tmatch = parent.data[this.field].indexOf(match);\n\t\t\t}\n\n\t\t\tif(match == -1){\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t}\n\n\t\t//catch all for any other type of input\n\n\t\treturn match;\n\t}\n\n\tgetTreeChildren(row, component, recurse){\n\t\tvar config = row.modules.dataTree,\n\t\toutput = [];\n\n\t\tif(config && config.children){\n\n\t\t\tif(!Array.isArray(config.children)){\n\t\t\t\tconfig.children = this.generateChildren(row);\n\t\t\t}\n\n\t\t\tconfig.children.forEach((childRow) => {\n\t\t\t\tif(childRow instanceof Row){\n\t\t\t\t\toutput.push(component ? childRow.getComponent() : childRow);\n\n\t\t\t\t\tif(recurse){\n\t\t\t\t\t\toutput = output.concat(this.getTreeChildren(childRow, component, recurse));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tgetChildField(){\n\t\treturn this.field;\n\t}\n\n\tredrawNeeded(data){\n\t\treturn (this.field ? typeof data[this.field] !== \"undefined\" : false) || (this.elementField ? typeof data[this.elementField] !== \"undefined\" : false);\n\t}\n}\n\nDataTree.moduleName = \"dataTree\";\n\nfunction csv(list, options = {}, setFileContents){\n\tvar delimiter = options.delimiter ? options.delimiter : \",\",\n\tfileContents = [],\n\theaders = [];\n\n\tlist.forEach((row) => {\n\t\tvar item = [];\n\n\t\tswitch(row.type){\n\t\t\tcase \"group\":\n\t\t\t\tconsole.warn(\"Download Warning - CSV downloader cannot process row groups\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"calc\":\n\t\t\t\tconsole.warn(\"Download Warning - CSV downloader cannot process column calculations\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"header\":\n\t\t\t\trow.columns.forEach((col, i) => {\n\t\t\t\t\tif(col && col.depth === 1){\n\t\t\t\t\t\theaders[i] = typeof col.value == \"undefined\"  || col.value === null ? \"\" : ('\"' + String(col.value).split('\"').join('\"\"') + '\"');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"row\":\n\t\t\t\trow.columns.forEach((col) => {\n\n\t\t\t\t\tif(col){\n\n\t\t\t\t\t\tswitch(typeof col.value){\n\t\t\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\t\t\tcol.value = col.value !== null ? JSON.stringify(col.value) : \"\";\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\t\t\tcol.value = \"\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\titem.push('\"' + String(col.value).split('\"').join('\"\"') + '\"');\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tfileContents.push(item.join(delimiter));\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tif(headers.length){\n\t\tfileContents.unshift(headers.join(delimiter));\n\t}\n\n\tfileContents = fileContents.join(\"\\n\");\n\n\tif(options.bom){\n\t\tfileContents = \"\\ufeff\" + fileContents;\n\t}\n\n\tsetFileContents(fileContents, \"text/csv\");\n}\n\nfunction json(list, options, setFileContents){\n\tvar fileContents = [];\n\n\tlist.forEach((row) => {\n\t\tvar item = {};\n\n\t\tswitch(row.type){\n\t\t\tcase \"header\":\n\t\t\t\tbreak;\n\n\t\t\tcase \"group\":\n\t\t\t\tconsole.warn(\"Download Warning - JSON downloader cannot process row groups\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"calc\":\n\t\t\t\tconsole.warn(\"Download Warning - JSON downloader cannot process column calculations\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"row\":\n\t\t\t\trow.columns.forEach((col) => {\n\t\t\t\t\tif(col){\n\t\t\t\t\t\titem[col.component.getTitleDownload() || col.component.getField()] = col.value;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tfileContents.push(item);\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tfileContents = JSON.stringify(fileContents, null, '\\t');\n\n\tsetFileContents(fileContents, \"application/json\");\n}\n\nfunction pdf(list, options = {}, setFileContents){\n\tvar header = [],\n\tbody = [],\n\tautoTableParams = {},\n\trowGroupStyles = options.rowGroupStyles || {\n\t\tfontStyle: \"bold\",\n\t\tfontSize: 12,\n\t\tcellPadding: 6,\n\t\tfillColor: 220,\n\t},\n\trowCalcStyles = options.rowCalcStyles || {\n\t\tfontStyle: \"bold\",\n\t\tfontSize: 10,\n\t\tcellPadding: 4,\n\t\tfillColor: 232,\n\t},\n\tjsPDFParams = options.jsPDF || {},\n\ttitle = options.title ? options.title : \"\";\n\n\tif(!jsPDFParams.orientation){\n\t\tjsPDFParams.orientation = options.orientation || \"landscape\";\n\t}\n\n\tif(!jsPDFParams.unit){\n\t\tjsPDFParams.unit = \"pt\";\n\t}\n\n\t//parse row list\n\tlist.forEach((row) => {\n\t\tswitch(row.type){\n\t\t\tcase \"header\":\n\t\t\t\theader.push(parseRow(row));\n\t\t\t\tbreak;\n\n\t\t\tcase \"group\":\n\t\t\t\tbody.push(parseRow(row, rowGroupStyles));\n\t\t\t\tbreak;\n\n\t\t\tcase \"calc\":\n\t\t\t\tbody.push(parseRow(row, rowCalcStyles));\n\t\t\t\tbreak;\n\n\t\t\tcase \"row\":\n\t\t\t\tbody.push(parseRow(row));\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tfunction parseRow(row, styles){\n\t\tvar rowData = [];\n\n\t\trow.columns.forEach((col) =>{\n\t\t\tvar cell;\n\n\t\t\tif(col){\n\t\t\t\tswitch(typeof col.value){\n\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\tcol.value = col.value !== null ? JSON.stringify(col.value) : \"\";\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\tcol.value = \"\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcell = {\n\t\t\t\t\tcontent:col.value,\n\t\t\t\t\tcolSpan:col.width,\n\t\t\t\t\trowSpan:col.height,\n\t\t\t\t};\n\n\t\t\t\tif(styles){\n\t\t\t\t\tcell.styles = styles;\n\t\t\t\t}\n\n\t\t\t\trowData.push(cell);\n\t\t\t}\n\t\t});\n\n\t\treturn rowData;\n\t}\n\n\n\t//configure PDF\n\tvar doc = new jspdf.jsPDF(jsPDFParams); //set document to landscape, better for most tables\n\n\tif(options.autoTable){\n\t\tif(typeof options.autoTable === \"function\"){\n\t\t\tautoTableParams = options.autoTable(doc) || {};\n\t\t}else {\n\t\t\tautoTableParams = options.autoTable;\n\t\t}\n\t}\n\n\tif(title){\n\t\tautoTableParams.didDrawPage = function(data) {\n\t\t\tdoc.text(title, 40, 30);\n\t\t};\n\t}\n\n\tautoTableParams.head = header;\n\tautoTableParams.body = body;\n\n\tdoc.autoTable(autoTableParams);\n\n\tif(options.documentProcessing){\n\t\toptions.documentProcessing(doc);\n\t}\n\n\tsetFileContents(doc.output(\"arraybuffer\"), \"application/pdf\");\n}\n\nfunction xlsx(list, options, setFileContents){\n\tvar self = this,\n\tsheetName = options.sheetName || \"Sheet1\",\n\tworkbook = XLSX.utils.book_new(),\n\ttableFeatures = new CoreFeature(this),\n\tcompression =  'compress' in options ? options.compress : true,\n\twriteOptions = options.writeOptions || {bookType:'xlsx', bookSST:true, compression},\n\toutput;\n\n\twriteOptions.type = 'binary';\n\n\tworkbook.SheetNames = [];\n\tworkbook.Sheets = {};\n\n\tfunction generateSheet(){\n\t\tvar rows = [],\n\t\tmerges = [],\n\t\tworksheet = {},\n\t\trange = {s: {c:0, r:0}, e: {c:(list[0] ? list[0].columns.reduce((a, b) => a + (b && b.width ? b.width : 1), 0) : 0), r:list.length }};\n\n\t\t//parse row list\n\t\tlist.forEach((row, i) => {\n\t\t\tvar rowData = [];\n\n\t\t\trow.columns.forEach(function(col, j){\n\n\t\t\t\tif(col){\n\t\t\t\t\trowData.push(!(col.value instanceof Date) && typeof col.value === \"object\" ? JSON.stringify(col.value) : col.value);\n\n\t\t\t\t\tif(col.width > 1 || col.height > -1){\n\t\t\t\t\t\tif(col.height > 1 || col.width > 1){\n\t\t\t\t\t\t\tmerges.push({s:{r:i,c:j},e:{r:i + col.height - 1,c:j + col.width - 1}});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\trowData.push(\"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\trows.push(rowData);\n\t\t});\n\n\t\t//convert rows to worksheet\n\t\tXLSX.utils.sheet_add_aoa(worksheet, rows);\n\n\t\tworksheet['!ref'] = XLSX.utils.encode_range(range);\n\n\t\tif(merges.length){\n\t\t\tworksheet[\"!merges\"] = merges;\n\t\t}\n\n\t\treturn worksheet;\n\t}\n\n\tif(options.sheetOnly){\n\t\tsetFileContents(generateSheet());\n\t\treturn;\n\t}\n\n\tif(options.sheets){\n\t\tfor(var sheet in options.sheets){\n\n\t\t\tif(options.sheets[sheet] === true){\n\t\t\t\tworkbook.SheetNames.push(sheet);\n\t\t\t\tworkbook.Sheets[sheet] = generateSheet();\n\t\t\t}else {\n\n\t\t\t\tworkbook.SheetNames.push(sheet);\n\n\t\t\t\ttableFeatures.commsSend(options.sheets[sheet], \"download\", \"intercept\",{\n\t\t\t\t\ttype:\"xlsx\",\n\t\t\t\t\toptions:{sheetOnly:true},\n\t\t\t\t\tactive:self.active,\n\t\t\t\t\tintercept:function(data){\n\t\t\t\t\t\tworkbook.Sheets[sheet] = data;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}else {\n\t\tworkbook.SheetNames.push(sheetName);\n\t\tworkbook.Sheets[sheetName] = generateSheet();\n\t}\n\n\tif(options.documentProcessing){\n\t\tworkbook = options.documentProcessing(workbook);\n\t}\n\n\t//convert workbook to binary array\n\tfunction s2ab(s) {\n\t\tvar buf = new ArrayBuffer(s.length);\n\t\tvar view = new Uint8Array(buf);\n\t\tfor (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;\n\t\treturn buf;\n\t}\n\n\toutput = XLSX.write(workbook, writeOptions);\n\n\tsetFileContents(s2ab(output), \"application/octet-stream\");\n}\n\nfunction html(list, options, setFileContents){\n\tif(this.modExists(\"export\", true)){\n\t\tsetFileContents(this.modules.export.generateHTMLTable(list), \"text/html\");\n\t}\n}\n\nfunction jsonLines (list, options, setFileContents) {\n\tconst fileContents = [];\n\n\tlist.forEach((row) => {\n\t\tconst item = {};\n\n\t\tswitch (row.type) {\n\t\t\tcase \"header\":\n\t\t\t\tbreak;\n\n\t\t\tcase \"group\":\n\t\t\t\tconsole.warn(\"Download Warning - JSON downloader cannot process row groups\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"calc\":\n\t\t\t\tconsole.warn(\"Download Warning - JSON downloader cannot process column calculations\");\n\t\t\t\tbreak;\n\n\t\t\tcase \"row\":\n\t\t\t\trow.columns.forEach((col) => {\n\t\t\t\t\tif (col) {\n\t\t\t\t\t\titem[col.component.getTitleDownload() || col.component.getField()] = col.value;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tfileContents.push(JSON.stringify(item));\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tsetFileContents(fileContents.join(\"\\n\"), \"application/x-ndjson\");\n}\n\nvar defaultDownloaders = {\n\tcsv:csv,\n\tjson:json,\n\tjsonLines:jsonLines,\n\tpdf:pdf,\n\txlsx:xlsx,\n\thtml:html,\n};\n\nclass Download extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.registerTableOption(\"downloadEncoder\", function(data, mimeType){\n\t\t\treturn new Blob([data],{type:mimeType});\n\t\t}); //function to manipulate download data\n\t\tthis.registerTableOption(\"downloadReady\", undefined); //warn of function deprecation\n\t\tthis.registerTableOption(\"downloadConfig\", {}); //download config\n\t\tthis.registerTableOption(\"downloadRowRange\", \"active\"); //restrict download to active rows only\n\n\t\tthis.registerColumnOption(\"download\");\n\t\tthis.registerColumnOption(\"titleDownload\");\n\t}\n\n\tinitialize(){\n\t\tthis.deprecatedOptionsCheck();\n\n\t\tthis.registerTableFunction(\"download\", this.download.bind(this));\n\t\tthis.registerTableFunction(\"downloadToTab\", this.downloadToTab.bind(this));\n\t}\n\n\tdeprecatedOptionsCheck(){\n\t\tthis.deprecationCheck(\"downloadReady\", \"downloadEncoder\");\n\t}\t\n\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\n\tdownloadToTab(type, filename, options, active){\n\t\tthis.download(type, filename, options, active, true);\n\t}\n\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\n\t//trigger file download\n\tdownload(type, filename, options, range, interceptCallback){\n\t\tvar downloadFunc = false;\n\n\t\tfunction buildLink(data, mime){\n\t\t\tif(interceptCallback){\n\t\t\t\tif(interceptCallback === true){\n\t\t\t\t\tthis.triggerDownload(data, mime, type, filename, true);\n\t\t\t\t}else {\n\t\t\t\t\tinterceptCallback(data);\n\t\t\t\t}\n\n\t\t\t}else {\n\t\t\t\tthis.triggerDownload(data, mime, type, filename);\n\t\t\t}\n\t\t}\n\n\t\tif(typeof type == \"function\"){\n\t\t\tdownloadFunc = type;\n\t\t}else {\n\t\t\tif(Download.downloaders[type]){\n\t\t\t\tdownloadFunc = Download.downloaders[type];\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Download Error - No such download type found: \", type);\n\t\t\t}\n\t\t}\n\n\t\tif(downloadFunc){\n\t\t\tvar list = this.generateExportList(range);\n\n\t\t\tdownloadFunc.call(this.table, list , options || {}, buildLink.bind(this));\n\t\t}\n\t}\n\n\tgenerateExportList(range){\n\t\tvar list = this.table.modules.export.generateExportList(this.table.options.downloadConfig, false, range || this.table.options.downloadRowRange, \"download\");\n\n\t\t//assign group header formatter\n\t\tvar groupHeader = this.table.options.groupHeaderDownload;\n\n\t\tif(groupHeader && !Array.isArray(groupHeader)){\n\t\t\tgroupHeader = [groupHeader];\n\t\t}\n\n\t\tlist.forEach((row) => {\n\t\t\tvar group;\n\n\t\t\tif(row.type === \"group\"){\n\t\t\t\tgroup = row.columns[0];\n\n\t\t\t\tif(groupHeader && groupHeader[row.indent]){\n\t\t\t\t\tgroup.value = groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn list;\n\t}\n\n\ttriggerDownload(data, mime, type, filename, newTab){\n\t\tvar element = document.createElement('a'),\n\t\tblob = this.table.options.downloadEncoder(data, mime);\n\n\t\tif(blob){\n\t\t\tif(newTab){\n\t\t\t\twindow.open(window.URL.createObjectURL(blob));\n\t\t\t}else {\n\t\t\t\tfilename = filename || \"Tabulator.\" + (typeof type === \"function\" ? \"txt\" : type);\n\t\t\t\t\n\t\t\t\tif(navigator.msSaveOrOpenBlob){\n\t\t\t\t\tnavigator.msSaveOrOpenBlob(blob, filename);\n\t\t\t\t}else {\n\t\t\t\t\telement.setAttribute('href', window.URL.createObjectURL(blob));\n\n\t\t\t\t\t//set file title\n\t\t\t\t\telement.setAttribute('download', filename);\n\n\t\t\t\t\t//trigger download\n\t\t\t\t\telement.style.display = 'none';\n\t\t\t\t\tdocument.body.appendChild(element);\n\t\t\t\t\telement.click();\n\n\t\t\t\t\t//remove temporary link element\n\t\t\t\t\tdocument.body.removeChild(element);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.dispatchExternal(\"downloadComplete\");\n\t\t}\n\t}\n\n\tcommsReceived(table, action, data){\n\t\tswitch(action){\n\t\t\tcase \"intercept\":\n\t\t\t\tthis.download(data.type, \"\", data.options, data.active, data.intercept);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nDownload.moduleName = \"download\";\n\n//load defaults\nDownload.downloaders = defaultDownloaders;\n\nfunction maskInput(el, options){\n\tvar mask = options.mask,\n\tmaskLetter = typeof options.maskLetterChar !== \"undefined\" ? options.maskLetterChar : \"A\",\n\tmaskNumber = typeof options.maskNumberChar !== \"undefined\" ? options.maskNumberChar : \"9\",\n\tmaskWildcard = typeof options.maskWildcardChar !== \"undefined\" ? options.maskWildcardChar : \"*\";\n\n\tfunction fillSymbols(index){\n\t\tvar symbol = mask[index];\n\t\tif(typeof symbol !== \"undefined\" && symbol !== maskWildcard && symbol !== maskLetter && symbol !== maskNumber){\n\t\t\tel.value = el.value + \"\" + symbol;\n\t\t\tfillSymbols(index+1);\n\t\t}\n\t}\n\n\tel.addEventListener(\"keydown\", (e) => {\n\t\tvar index = el.value.length,\n\t\tchar = e.key;\n\n\t\tif(e.keyCode > 46 && !e.ctrlKey && !e.metaKey){\n\t\t\tif(index >= mask.length){\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\treturn false;\n\t\t\t}else {\n\t\t\t\tswitch(mask[index]){\n\t\t\t\t\tcase maskLetter:\n\t\t\t\t\t\tif(char.toUpperCase() == char.toLowerCase()){\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase maskNumber:\n\t\t\t\t\t\tif(isNaN(char)){\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase maskWildcard:\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif(char !== mask[index]){\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn;\n\t});\n\n\tel.addEventListener(\"keyup\", (e) => {\n\t\tif(e.keyCode > 46){\n\t\t\tif(options.maskAutoFill){\n\t\t\t\tfillSymbols(el.value.length);\n\t\t\t}\n\t\t}\n\t});\n\n\n\tif(!el.placeholder){\n\t\tel.placeholder = mask;\n\t}\n\n\tif(options.maskAutoFill){\n\t\tfillSymbols(el.value.length);\n\t}\n}\n\n//input element\nfunction input(cell, onRendered, success, cancel, editorParams){\n\t//create and style input\n\tvar cellValue = cell.getValue(),\n\tinput = document.createElement(\"input\");\n\n\tinput.setAttribute(\"type\", editorParams.search ? \"search\" : \"text\");\n\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\n\tinput.value = typeof cellValue !== \"undefined\" ? cellValue : \"\";\n\n\tonRendered(function(){\n\t\tif(cell.getType() === \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction onChange(e){\n\t\tif(((cellValue === null || typeof cellValue === \"undefined\") && input.value !== \"\") || input.value !== cellValue){\n\t\t\tif(success(input.value)){\n\t\t\t\tcellValue = input.value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\n\t//submit new value on blur or change\n\tinput.addEventListener(\"change\", onChange);\n\tinput.addEventListener(\"blur\", onChange);\n\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\t// case 9:\n\t\t\tcase 13:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tif(editorParams.mask){\n\t\tmaskInput(input, editorParams);\n\t}\n\n\treturn input;\n}\n\n//resizable text area element\nfunction textarea(cell, onRendered, success, cancel, editorParams){\n\tvar cellValue = cell.getValue(),\n\tvertNav = editorParams.verticalNavigation || \"hybrid\",\n\tvalue = String(cellValue !== null && typeof cellValue !== \"undefined\"  ? cellValue : \"\"),\n\tinput = document.createElement(\"textarea\"),\n\tscrollHeight = 0;\n\n\t//create and style input\n\tinput.style.display = \"block\";\n\tinput.style.padding = \"2px\";\n\tinput.style.height = \"100%\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\tinput.style.whiteSpace = \"pre-wrap\";\n\tinput.style.resize = \"none\";\n\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\n\tinput.value = value;\n\n\tonRendered(function(){\n\t\tif(cell.getType() === \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\n\t\t\tinput.scrollHeight;\n\t\t\tinput.style.height = input.scrollHeight + \"px\";\n\t\t\tcell.getRow().normalizeHeight();\n\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction onChange(e){\n\n\t\tif(((cellValue === null || typeof cellValue === \"undefined\") && input.value !== \"\") || input.value !== cellValue){\n\n\t\t\tif(success(input.value)){\n\t\t\t\tcellValue = input.value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\n\t\t\tsetTimeout(function(){\n\t\t\t\tcell.getRow().normalizeHeight();\n\t\t\t},300);\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\n\t//submit new value on blur or change\n\tinput.addEventListener(\"change\", onChange);\n\tinput.addEventListener(\"blur\", onChange);\n\n\tinput.addEventListener(\"keyup\", function(){\n\n\t\tinput.style.height = \"\";\n\n\t\tvar heightNow = input.scrollHeight;\n\n\t\tinput.style.height = heightNow + \"px\";\n\n\t\tif(heightNow != scrollHeight){\n\t\t\tscrollHeight = heightNow;\n\t\t\tcell.getRow().normalizeHeight();\n\t\t}\n\t});\n\n\tinput.addEventListener(\"keydown\", function(e){\n\n\t\tswitch(e.keyCode){\n\n\t\t\tcase 13:\n\t\t\t\tif(e.shiftKey && editorParams.shiftEnterSubmit){\n\t\t\t\t\tonChange();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\n\t\t\tcase 38: //up arrow\n\t\t\t\tif(vertNav == \"editor\" || (vertNav == \"hybrid\" && input.selectionStart)){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 40: //down arrow\n\t\t\t\tif(vertNav == \"editor\" || (vertNav == \"hybrid\" && input.selectionStart !== input.value.length)){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tif(editorParams.mask){\n\t\tmaskInput(input, editorParams);\n\t}\n\n\treturn input;\n}\n\n//input element with type of number\nfunction number(cell, onRendered, success, cancel, editorParams){\n\tvar cellValue = cell.getValue(),\n\tvertNav = editorParams.verticalNavigation || \"editor\",\n\tinput = document.createElement(\"input\");\n\n\tinput.setAttribute(\"type\", \"number\");\n\n\tif(typeof editorParams.max != \"undefined\"){\n\t\tinput.setAttribute(\"max\", editorParams.max);\n\t}\n\n\tif(typeof editorParams.min != \"undefined\"){\n\t\tinput.setAttribute(\"min\", editorParams.min);\n\t}\n\n\tif(typeof editorParams.step != \"undefined\"){\n\t\tinput.setAttribute(\"step\", editorParams.step);\n\t}\n\n\t//create and style input\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\n\tinput.value = cellValue;\n\n\tvar blurFunc = function(e){\n\t\tonChange();\n\t};\n\n\tonRendered(function () {\n\t\tif(cell.getType() === \"cell\"){\n\t\t\t//submit new value on blur\n\t\t\tinput.removeEventListener(\"blur\", blurFunc);\n\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\n\t\t\t//submit new value on blur\n\t\t\tinput.addEventListener(\"blur\", blurFunc);\n\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction onChange(){\n\t\tvar value = input.value;\n\n\t\tif(!isNaN(value) && value !==\"\"){\n\t\t\tvalue = Number(value);\n\t\t}\n\n\t\tif(value !== cellValue){\n\t\t\tif(success(value)){\n\t\t\t\tcellValue = value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\tcase 13:\n\t\t\t// case 9:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\n\t\t\tcase 38: //up arrow\n\t\t\tcase 40: //down arrow\n\t\t\t\tif(vertNav == \"editor\"){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tif(editorParams.mask){\n\t\tmaskInput(input, editorParams);\n\t}\n\n\treturn input;\n}\n\n//input element with type of number\nfunction range(cell, onRendered, success, cancel, editorParams){\n\tvar cellValue = cell.getValue(),\n\tinput = document.createElement(\"input\");\n\t\n\tinput.setAttribute(\"type\", \"range\");\n\t\n\tif (typeof editorParams.max != \"undefined\") {\n\t\tinput.setAttribute(\"max\", editorParams.max);\n\t}\n\t\n\tif (typeof editorParams.min != \"undefined\") {\n\t\tinput.setAttribute(\"min\", editorParams.min);\n\t}\n\t\n\tif (typeof editorParams.step != \"undefined\") {\n\t\tinput.setAttribute(\"step\", editorParams.step);\n\t}\n\t\n\t//create and style input\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\t\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tinput.value = cellValue;\n\t\n\tonRendered(function () {\n\t\tif(cell.getType() === \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\t\t}\n\t});\n\t\n\tfunction onChange(){\n\t\tvar value = input.value;\n\t\t\n\t\tif(!isNaN(value) && value !==\"\"){\n\t\t\tvalue = Number(value);\n\t\t}\n\t\t\n\t\tif(value != cellValue){\n\t\t\tif(success(value)){\n\t\t\t\tcellValue = value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\t\n\t//submit new value on blur\n\tinput.addEventListener(\"blur\", function(e){\n\t\tonChange();\n\t});\n\t\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\tcase 13:\n\t\t\t// case 9:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t\n\treturn input;\n}\n\n//input element\nfunction date(cell, onRendered, success, cancel, editorParams){\n\tvar inputFormat = editorParams.format,\n\tvertNav = editorParams.verticalNavigation || \"editor\",\n\tDT = inputFormat ? (window.DateTime || luxon.DateTime) : null;\n\t\n\t//create and style input\n\tvar cellValue = cell.getValue(),\n\tinput = document.createElement(\"input\");\n\t\n\tfunction convertDate(value){\n\t\tvar newDatetime;\n\t\t\n\t\tif(DT.isDateTime(value)){\n\t\t\tnewDatetime = value;\n\t\t}else if(inputFormat === \"iso\"){\n\t\t\tnewDatetime = DT.fromISO(String(value));\n\t\t}else {\n\t\t\tnewDatetime = DT.fromFormat(String(value), inputFormat);\n\t\t}\n\t\t\n\t\treturn newDatetime.toFormat(\"yyyy-MM-dd\");\n\t}\n\t\n\tinput.type = \"date\";\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\n\tif(editorParams.max){\n\t\tinput.setAttribute(\"max\", inputFormat ? convertDate(editorParams.max) : editorParams.max);\n\t}\n\n\tif(editorParams.min){\n\t\tinput.setAttribute(\"min\", inputFormat ? convertDate(editorParams.min) : editorParams.min);\n\t}\n\t\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tcellValue = typeof cellValue !== \"undefined\" ? cellValue : \"\";\n\t\n\tif(inputFormat){\n\t\tif(DT){\t\t\n\t\t\tcellValue = convertDate(cellValue);\t\t\t\n\t\t}else {\n\t\t\tconsole.error(\"Editor Error - 'date' editor 'format' param is dependant on luxon.js\");\n\t\t}\n\t}\n\t\n\tinput.value = cellValue;\n\t\n\tonRendered(function(){\n\t\tif(cell.getType() === \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\t\t\t\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction onChange(){\n\t\tvar value = input.value,\n\t\tluxDate;\n\t\t\n\t\tif(((cellValue === null || typeof cellValue === \"undefined\") && value !== \"\") || value !== cellValue){\n\t\t\t\n\t\t\tif(value && inputFormat){\n\t\t\t\tluxDate = DT.fromFormat(String(value), \"yyyy-MM-dd\");\n\n\t\t\t\tswitch(inputFormat){\n\t\t\t\t\tcase true:\n\t\t\t\t\t\tvalue = luxDate;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"iso\":\n\t\t\t\t\t\tvalue = luxDate.toISO();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = luxDate.toFormat(inputFormat);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(success(value)){\n\t\t\t\tcellValue = input.value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\t\n\t//submit new value on blur\n\tinput.addEventListener(\"blur\", function(e) {\n\t\tif (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {\n\t\t\tonChange(); // only on a \"true\" blur; not when focusing browser's date/time picker\n\t\t}\n\t});\n\t\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\t// case 9:\n\t\t\tcase 13:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 38: //up arrow\n\t\t\tcase 40: //down arrow\n\t\t\t\tif(vertNav == \"editor\"){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t\n\treturn input;\n}\n\n//input element\nfunction time(cell, onRendered, success, cancel, editorParams){\n\tvar inputFormat = editorParams.format,\n\tvertNav = editorParams.verticalNavigation || \"editor\",\n\tDT = inputFormat ? (window.DateTime || luxon.DateTime) : null, \n\tnewDatetime;\n\t\n\t//create and style input\n\tvar cellValue = cell.getValue(),\n\tinput = document.createElement(\"input\");\n\t\n\tinput.type = \"time\";\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\t\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tcellValue = typeof cellValue !== \"undefined\" ? cellValue : \"\";\n\t\n\tif(inputFormat){\n\t\tif(DT){\n\t\t\tif(DT.isDateTime(cellValue)){\n\t\t\t\tnewDatetime = cellValue;\n\t\t\t}else if(inputFormat === \"iso\"){\n\t\t\t\tnewDatetime = DT.fromISO(String(cellValue));\n\t\t\t}else {\n\t\t\t\tnewDatetime = DT.fromFormat(String(cellValue), inputFormat);\n\t\t\t}\n\t\t\t\n\t\t\tcellValue = newDatetime.toFormat(\"HH:mm\");\n\t\t\t\n\t\t}else {\n\t\t\tconsole.error(\"Editor Error - 'date' editor 'format' param is dependant on luxon.js\");\n\t\t}\n\t}\n\n\tconsole.log(\"val\", cellValue);\n\t\n\tinput.value = cellValue;\n\t\n\tonRendered(function(){\n\t\tif(cell.getType() == \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\t\t\t\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction onChange(){\n\t\tvar value = input.value,\n\t\tluxTime;\n\t\t\n\t\tif(((cellValue === null || typeof cellValue === \"undefined\") && value !== \"\") || value !== cellValue){\n\t\t\t\n\t\t\tif(value && inputFormat){\n\t\t\t\tluxTime = DT.fromFormat(String(value), \"hh:mm\");\n\n\t\t\t\tswitch(inputFormat){\n\t\t\t\t\tcase true:\n\t\t\t\t\t\tvalue = luxTime;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"iso\":\n\t\t\t\t\t\tvalue = luxTime.toISO();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = luxTime.toFormat(inputFormat);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(success(value)){\n\t\t\t\tcellValue = input.value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\t\n\t//submit new value on blur\n\tinput.addEventListener(\"blur\", function(e) {\n\t\tif (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {\n\t\t\tonChange(); // only on a \"true\" blur; not when focusing browser's date/time picker\n\t\t}\n\t});\n\t\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\t// case 9:\n\t\t\tcase 13:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\n\t\t\tcase 38: //up arrow\n\t\t\tcase 40: //down arrow\n\t\t\t\tif(vertNav == \"editor\"){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t\n\treturn input;\n}\n\n//input element\nfunction datetime(cell, onRendered, success, cancel, editorParams){\n\tvar inputFormat = editorParams.format,\n\tvertNav = editorParams.verticalNavigation || \"editor\",\n\tDT = inputFormat ? (window.DateTime || luxon.DateTime) : null, \n\tnewDatetime;\n\t\n\t//create and style input\n\tvar cellValue = cell.getValue(),\n\tinput = document.createElement(\"input\");\n\t\n\tinput.type = \"datetime-local\";\n\tinput.style.padding = \"4px\";\n\tinput.style.width = \"100%\";\n\tinput.style.boxSizing = \"border-box\";\n\t\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tcellValue = typeof cellValue !== \"undefined\" ? cellValue : \"\";\n\t\n\tif(inputFormat){\n\t\tif(DT){\n\t\t\tif(DT.isDateTime(cellValue)){\n\t\t\t\tnewDatetime = cellValue;\n\t\t\t}else if(inputFormat === \"iso\"){\n\t\t\t\tnewDatetime = DT.fromISO(String(cellValue));\n\t\t\t}else {\n\t\t\t\tnewDatetime = DT.fromFormat(String(cellValue), inputFormat);\n\t\t\t}\n\t\t\t\n\t\t\tcellValue = newDatetime.toFormat(\"yyyy-MM-dd\")  + \"T\" + newDatetime.toFormat(\"HH:mm\");\n\t\t}else {\n\t\t\tconsole.error(\"Editor Error - 'date' editor 'format' param is dependant on luxon.js\");\n\t\t}\n\t}\n\t\n\tinput.value = cellValue;\n\t\n\tonRendered(function(){\n\t\tif(cell.getType() === \"cell\"){\n\t\t\tinput.focus({preventScroll: true});\n\t\t\tinput.style.height = \"100%\";\n\t\t\t\n\t\t\tif(editorParams.selectContents){\n\t\t\t\tinput.select();\n\t\t\t}\n\t\t}\n\t});\n\t\n\tfunction onChange(){\n\t\tvar value = input.value,\n\t\tluxDateTime;\n\t\t\n\t\tif(((cellValue === null || typeof cellValue === \"undefined\") && value !== \"\") || value !== cellValue){\n\n\t\t\tif(value && inputFormat){\n\t\t\t\tluxDateTime = DT.fromISO(String(value));\n\n\t\t\t\tswitch(inputFormat){\n\t\t\t\t\tcase true:\n\t\t\t\t\t\tvalue = luxDateTime;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"iso\":\n\t\t\t\t\t\tvalue = luxDateTime.toISO();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvalue = luxDateTime.toFormat(inputFormat);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(success(value)){\n\t\t\t\tcellValue = input.value; //persist value if successfully validated incase editor is used as header filter\n\t\t\t}\n\t\t}else {\n\t\t\tcancel();\n\t\t}\n\t}\n\t\n\t//submit new value on blur\n\tinput.addEventListener(\"blur\", function(e) {\n\t\tif (e.relatedTarget || e.rangeParent || e.explicitOriginalTarget !== input) {\n\t\t\tonChange(); // only on a \"true\" blur; not when focusing browser's date/time picker\n\t\t}\n\t});\n\t\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\t// case 9:\n\t\t\tcase 13:\n\t\t\t\tonChange();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 27:\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 35:\n\t\t\tcase 36:\n\t\t\t\te.stopPropagation();\n\t\t\t\tbreak;\n\n\t\t\tcase 38: //up arrow\n\t\t\tcase 40: //down arrow\n\t\t\t\tif(vertNav == \"editor\"){\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t});\n\t\n\treturn input;\n}\n\nclass Edit{\n\tconstructor(editor, cell, onRendered, success, cancel, editorParams){\n\t\tthis.edit = editor;\n\t\tthis.table = editor.table;\n\t\tthis.cell = cell;\n\t\tthis.params = this._initializeParams(editorParams);\n\t\t\n\t\tthis.data = [];\n\t\tthis.displayItems = [];\n\t\tthis.currentItems = [];\n\t\tthis.focusedItem = null;\n\t\t\n\t\tthis.input = this._createInputElement();\n\t\tthis.listEl = this._createListElement();\n\t\t\n\t\tthis.initialValues = null; \n\t\t\n\t\tthis.isFilter = cell.getType() === \"header\";\n\t\t\n\t\tthis.filterTimeout = null;\n\t\tthis.filtered = false;\n\t\tthis.typing = false;\n\t\t\n\t\tthis.values = []; \n\t\tthis.popup = null;  \n\t\t\n\t\tthis.listIteration = 0;\n\t\t\n\t\tthis.lastAction=\"\";\n\t\tthis.filterTerm=\"\";\n\t\t\n\t\tthis.blurable = true;\n\t\t\n\t\tthis.actions = {\n\t\t\tsuccess:success,\n\t\t\tcancel:cancel\n\t\t};\n\t\t\n\t\tthis._deprecatedOptionsCheck();\n\t\tthis._initializeValue();\n\t\t\n\t\tonRendered(this._onRendered.bind(this));\n\t}\n\t\n\t_deprecatedOptionsCheck(){\n\t\tif(this.params.listItemFormatter){\n\t\t\tthis.cell.getTable().deprecationAdvisor.msg(\"The listItemFormatter editor param has been deprecated, please see the latest editor documentation for updated options\");\n\t\t}\n\t\t\n\t\tif(this.params.sortValuesList){\n\t\t\tthis.cell.getTable().deprecationAdvisor.msg(\"The sortValuesList editor param has been deprecated, please see the latest editor documentation for updated options\");\n\t\t}\n\t\t\n\t\tif(this.params.searchFunc){\n\t\t\tthis.cell.getTable().deprecationAdvisor.msg(\"The searchFunc editor param has been deprecated, please see the latest editor documentation for updated options\");\n\t\t}\n\t\t\n\t\tif(this.params.searchingPlaceholder){\n\t\t\tthis.cell.getTable().deprecationAdvisor.msg(\"The searchingPlaceholder editor param has been deprecated, please see the latest editor documentation for updated options\");\n\t\t}\n\t}\n\t\n\t_initializeValue(){\n\t\tvar initialValue = this.cell.getValue();\n\t\t\n\t\tif(typeof initialValue === \"undefined\" && typeof this.params.defaultValue !== \"undefined\"){\n\t\t\tinitialValue = this.params.defaultValue;\n\t\t}\n\t\t\n\t\tthis.initialValues = this.params.multiselect ? initialValue : [initialValue];\n\t\t\n\t\tif(this.isFilter){\n\t\t\tthis.input.value = this.initialValues ? this.initialValues.join(\",\") : \"\";\n\t\t\tthis.headerFilterInitialListGen();            \n\t\t}\n\t}\n\t\n\t_onRendered(){\n\t\tvar cellEl = this.cell.getElement();\n\t\t\n\t\tfunction clickStop(e){\n\t\t\te.stopPropagation();\n\t\t}\t\n\t\t\n\t\tif(!this.isFilter){\n\t\t\tthis.input.style.height = \"100%\";\n\t\t\tthis.input.focus({preventScroll: true});\n\t\t}\n\t\t\n\t\t\n\t\tcellEl.addEventListener(\"click\", clickStop);\n\t\t\n\t\tsetTimeout(() => {\n\t\t\tcellEl.removeEventListener(\"click\", clickStop);\n\t\t}, 1000);\n\t\t\n\t\tthis.input.addEventListener(\"mousedown\", this._preventPopupBlur.bind(this));\n\t}\n\t\n\t_createListElement(){\n\t\tvar listEl = document.createElement(\"div\");\n\t\tlistEl.classList.add(\"tabulator-edit-list\");\n\t\t\n\t\tlistEl.addEventListener(\"mousedown\", this._preventBlur.bind(this));\n\t\tlistEl.addEventListener(\"keydown\", this._inputKeyDown.bind(this));\n\t\t\n\t\treturn listEl;\n\t}\n\t\n\t_setListWidth(){\n\t\tvar element = this.isFilter ? this.input : this.cell.getElement();\n\t\t\n\t\tthis.listEl.style.minWidth = element.offsetWidth + \"px\";\n\t\t\n\t\tif(this.params.maxWidth){\n\t\t\tif(this.params.maxWidth === true){\n\t\t\t\tthis.listEl.style.maxWidth = element.offsetWidth + \"px\";\n\t\t\t}else if(typeof this.params.maxWidth === \"number\"){\n\t\t\t\tthis.listEl.style.maxWidth = this.params.maxWidth + \"px\";\n\t\t\t}else {\n\t\t\t\tthis.listEl.style.maxWidth = this.params.maxWidth;\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\t\n\t_createInputElement(){\n\t\tvar attribs = this.params.elementAttributes;\n\t\tvar input = document.createElement(\"input\");\n\t\t\n\t\tinput.setAttribute(\"type\", this.params.clearable ? \"search\" : \"text\");\n\t\t\n\t\tinput.style.padding = \"4px\";\n\t\tinput.style.width = \"100%\";\n\t\tinput.style.boxSizing = \"border-box\";\n\t\t\n\t\tif(!this.params.autocomplete){\n\t\t\tinput.style.cursor = \"default\";\n\t\t\tinput.style.caretColor = \"transparent\";\n\t\t\t// input.readOnly = (this.edit.currentCell != false);\n\t\t}\n\t\t\n\t\tif(attribs && typeof attribs == \"object\"){\n\t\t\tfor (let key in attribs){\n\t\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\t\tkey = key.slice(1);\n\t\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + attribs[\"+\" + key]);\n\t\t\t\t}else {\n\t\t\t\t\tinput.setAttribute(key, attribs[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(this.params.mask){\n\t\t\tmaskInput(input, this.params);\n\t\t}\n\t\t\n\t\tthis._bindInputEvents(input);\n\t\t\n\t\treturn input;\n\t}\n\t\n\t_initializeParams(params){\n\t\tvar valueKeys = [\"values\", \"valuesURL\", \"valuesLookup\"],\n\t\tvalueCheck;\n\t\t\n\t\tparams = Object.assign({}, params);\n\t\t\n\t\tparams.verticalNavigation = params.verticalNavigation || \"editor\";\n\t\tparams.placeholderLoading = typeof params.placeholderLoading === \"undefined\" ? \"Searching ...\" : params.placeholderLoading;\n\t\tparams.placeholderEmpty = typeof params.placeholderEmpty === \"undefined\" ? \"No Results Found\" : params.placeholderEmpty;\n\t\tparams.filterDelay = typeof params.filterDelay === \"undefined\" ? 300 : params.filterDelay;\n\t\t\n\t\tparams.emptyValue = Object.keys(params).includes(\"emptyValue\") ? params.emptyValue : \"\";\n\t\t\n\t\tvalueCheck = Object.keys(params).filter(key => valueKeys.includes(key)).length;\n\t\t\n\t\tif(!valueCheck){\n\t\t\tconsole.warn(\"list editor config error - either the values, valuesURL, or valuesLookup option must be set\");\n\t\t}else if(valueCheck > 1){\n\t\t\tconsole.warn(\"list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor\");\n\t\t}\n\t\t\n\t\tif(params.autocomplete){\n\t\t\tif(params.multiselect){\n\t\t\t\tparams.multiselect = false;\n\t\t\t\tconsole.warn(\"list editor config error - multiselect option is not available when autocomplete is enabled\");\n\t\t\t}\n\t\t}else {\n\t\t\tif(params.freetext){\n\t\t\t\tparams.freetext = false;\n\t\t\t\tconsole.warn(\"list editor config error - freetext option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t\t\n\t\t\tif(params.filterFunc){\n\t\t\t\tparams.filterFunc = false;\n\t\t\t\tconsole.warn(\"list editor config error - filterFunc option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t\t\n\t\t\tif(params.filterRemote){\n\t\t\t\tparams.filterRemote = false;\n\t\t\t\tconsole.warn(\"list editor config error - filterRemote option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t\t\n\t\t\tif(params.mask){\n\t\t\t\tparams.mask = false;\n\t\t\t\tconsole.warn(\"list editor config error - mask option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t\t\n\t\t\tif(params.allowEmpty){\n\t\t\t\tparams.allowEmpty = false;\n\t\t\t\tconsole.warn(\"list editor config error - allowEmpty option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t\t\n\t\t\tif(params.listOnEmpty){\n\t\t\t\tparams.listOnEmpty = false;\n\t\t\t\tconsole.warn(\"list editor config error - listOnEmpty option is only available when autocomplete is enabled\");\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(params.filterRemote && !(typeof params.valuesLookup === \"function\" || params.valuesURL)){\n\t\t\tparams.filterRemote = false;\n\t\t\tconsole.warn(\"list editor config error - filterRemote option should only be used when values list is populated from a remote source\");\n\t\t}\n\t\treturn params;\n\t}\n\t//////////////////////////////////////\n\t////////// Event Handling ////////////\n\t//////////////////////////////////////\n\t\n\t_bindInputEvents(input){\n\t\tinput.addEventListener(\"focus\", this._inputFocus.bind(this));\n\t\tinput.addEventListener(\"click\", this._inputClick.bind(this));\n\t\tinput.addEventListener(\"blur\", this._inputBlur.bind(this));\n\t\tinput.addEventListener(\"keydown\", this._inputKeyDown.bind(this));\n\t\tinput.addEventListener(\"search\", this._inputSearch.bind(this));\n\t\t\n\t\tif(this.params.autocomplete){\n\t\t\tinput.addEventListener(\"keyup\", this._inputKeyUp.bind(this));\n\t\t}\n\t}\n\t\n\t\n\t_inputFocus(e){\n\t\tthis.rebuildOptionsList();\n\t}\n\t\n\t_filter(){\n\t\tif(this.params.filterRemote){\n\t\t\tclearTimeout(this.filterTimeout);\n\t\t\t\n\t\t\tthis.filterTimeout = setTimeout(() => {\n\t\t\t\tthis.rebuildOptionsList();\n\t\t\t}, this.params.filterDelay);\n\t\t}else {\n\t\t\tthis._filterList();\n\t\t}\n\t}\n\t\n\t_inputClick(e){\n\t\te.stopPropagation();\n\t}\n\t\n\t_inputBlur(e){\n\t\tif(this.blurable){\n\t\t\tif(this.popup){\n\t\t\t\tthis.popup.hide();\n\t\t\t}else {\n\t\t\t\tthis._resolveValue(true);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_inputSearch(){\n\t\tthis._clearChoices();\n\t}\n\t\n\t_inputKeyDown(e){\n\t\tswitch(e.keyCode){\n\t\t\t\n\t\t\tcase 38: //up arrow\n\t\t\t\tthis._keyUp(e);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 40: //down arrow\n\t\t\t\tthis._keyDown(e);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 37: //left arrow\n\t\t\tcase 39: //right arrow\n\t\t\t\tthis._keySide(e);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 13: //enter\n\t\t\t\tthis._keyEnter();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 27: //escape\n\t\t\t\tthis._keyEsc();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 36: //home\n\t\t\tcase 35: //end\n\t\t\t\tthis._keyHomeEnd(e);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase 9: //tab\n\t\t\t\tthis._keyTab(e);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthis._keySelectLetter(e);\n\t\t}\n\t}\n\t\n\t_inputKeyUp(e){\n\t\tswitch(e.keyCode){\n\t\t\tcase 38: //up arrow\n\t\t\tcase 37: //left arrow\n\t\t\tcase 39: //up arrow\n\t\t\tcase 40: //right arrow\n\t\t\tcase 13: //enter\n\t\t\tcase 27: //escape\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthis._keyAutoCompLetter(e);\n\t\t}\n\t}\n\t\n\t_preventPopupBlur(){\n\t\tif(this.popup){\n\t\t\tthis.popup.blockHide();\n\t\t}\n\t\t\n\t\tsetTimeout(() =>{\n\t\t\tif(this.popup){\n\t\t\t\tthis.popup.restoreHide();\n\t\t\t}\n\t\t}, 10);\n\t}\n\t\n\t_preventBlur(){\n\t\tthis.blurable = false;\n\t\t\n\t\tsetTimeout(() =>{\n\t\t\tthis.blurable = true;\n\t\t}, 10);\n\t}\n\t\n\t//////////////////////////////////////\n\t//////// Keyboard Navigation /////////\n\t//////////////////////////////////////\n\t\n\t_keyTab(e){\n\t\tif(this.params.autocomplete && this.lastAction === \"typing\"){\n\t\t\tthis._resolveValue(true);\n\t\t}else {\n\t\t\tif(this.focusedItem){\n\t\t\t\tthis._chooseItem(this.focusedItem, true);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_keyUp(e){\n\t\tvar index = this.displayItems.indexOf(this.focusedItem);\n\t\t\n\t\tif(this.params.verticalNavigation == \"editor\" || (this.params.verticalNavigation == \"hybrid\" && index)){\n\t\t\te.stopImmediatePropagation();\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\t\n\t\t\tif(index > 0){\n\t\t\t\tthis._focusItem(this.displayItems[index - 1]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_keyDown(e){\n\t\tvar index = this.displayItems.indexOf(this.focusedItem);\n\t\t\n\t\tif(this.params.verticalNavigation == \"editor\" || (this.params.verticalNavigation == \"hybrid\" && index < this.displayItems.length - 1)){\n\t\t\te.stopImmediatePropagation();\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\t\n\t\t\tif(index < this.displayItems.length - 1){\n\t\t\t\tif(index == -1){\n\t\t\t\t\tthis._focusItem(this.displayItems[0]);\n\t\t\t\t}else {\n\t\t\t\t\tthis._focusItem(this.displayItems[index + 1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_keySide(e){\n\t\tif(!this.params.autocomplete){\n\t\t\te.stopImmediatePropagation();\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t}\n\t}\n\t\n\t_keyEnter(e){\n\t\tif(this.params.autocomplete && this.lastAction === \"typing\"){\n\t\t\tthis._resolveValue(true);\n\t\t}else {\n\t\t\tif(this.focusedItem){\n\t\t\t\tthis._chooseItem(this.focusedItem);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_keyEsc(e){\n\t\tthis._cancel();\n\t}\n\t\n\t_keyHomeEnd(e){\n\t\tif(this.params.autocomplete){\n\t\t\t//prevent table navigation while using input element\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\t}\n\t\n\t_keySelectLetter(e){\n\t\tif(!this.params.autocomplete){\n\t\t\t// if(this.edit.currentCell === false){\n\t\t\te.preventDefault();\n\t\t\t// }\n\t\t\t\n\t\t\tif(e.keyCode >= 38 && e.keyCode <= 90){\n\t\t\t\tthis._scrollToValue(e.keyCode);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_keyAutoCompLetter(e){\n\t\tthis._filter();\n\t\tthis.lastAction = \"typing\";\n\t\tthis.typing = true;\n\t}\n\t\n\t\n\t_scrollToValue(char){\n\t\tclearTimeout(this.filterTimeout);\n\t\t\n\t\tvar character = String.fromCharCode(char).toLowerCase();\n\t\tthis.filterTerm += character.toLowerCase();\n\t\t\n\t\tvar match = this.displayItems.find((item) => {\n\t\t\treturn typeof item.label !== \"undefined\" && item.label.toLowerCase().startsWith(this.filterTerm);\n\t\t});\n\t\t\n\t\tif(match){\n\t\t\tthis._focusItem(match);\n\t\t}\n\t\t\n\t\tthis.filterTimeout = setTimeout(() => {\n\t\t\tthis.filterTerm = \"\";\n\t\t}, 800);\n\t}\n\t\n\t_focusItem(item){\n\t\tthis.lastAction = \"focus\";\n\t\t\n\t\tif(this.focusedItem && this.focusedItem.element){\n\t\t\tthis.focusedItem.element.classList.remove(\"focused\");\n\t\t}\n\t\t\n\t\tthis.focusedItem = item;\n\t\t\n\t\tif(item && item.element){\n\t\t\titem.element.classList.add(\"focused\");\n\t\t\titem.element.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'start'});\n\t\t}\n\t}\n\t\n\t\n\t//////////////////////////////////////\n\t/////// Data List Generation /////////\n\t//////////////////////////////////////\n\theaderFilterInitialListGen(){\n\t\tthis._generateOptions(true);\n\t}\n\t\n\trebuildOptionsList(){\n\t\tthis._generateOptions()\n\t\t\t.then(this._sortOptions.bind(this))\n\t\t\t.then(this._buildList.bind(this))\n\t\t\t.then(this._showList.bind(this))\n\t\t\t.catch((e) => {\n\t\t\t\tif(!Number.isInteger(e)){\n\t\t\t\t\tconsole.error(\"List generation error\", e);\n\t\t\t\t}\n\t\t\t});\n\t}\n\t\n\t_filterList(){\n\t\tthis._buildList(this._filterOptions());\n\t\tthis._showList();\n\t}\n\t\n\t_generateOptions(silent){\n\t\tvar values = [];\n\t\tvar iteration = ++ this.listIteration;\n\t\t\n\t\tthis.filtered = false;\n\t\t\n\t\tif(this.params.values){\n\t\t\tvalues = this.params.values;\n\t\t}else if (this.params.valuesURL){\n\t\t\tvalues = this._ajaxRequest(this.params.valuesURL, this.input.value);\n\t\t}else {\n\t\t\tif(typeof this.params.valuesLookup === \"function\"){\n\t\t\t\tvalues = this.params.valuesLookup(this.cell, this.input.value);\n\t\t\t}else if(this.params.valuesLookup){\n\t\t\t\tvalues = this._uniqueColumnValues(this.params.valuesLookupField);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(values instanceof Promise){\n\t\t\tif(!silent){\n\t\t\t\tthis._addPlaceholder(this.params.placeholderLoading);\n\t\t\t}\n\t\t\t\n\t\t\treturn values.then()\n\t\t\t\t.then((responseValues) => {\n\t\t\t\t\tif(this.listIteration === iteration){\n\t\t\t\t\t\treturn this._parseList(responseValues);\n\t\t\t\t\t}else {\n\t\t\t\t\t\treturn Promise.reject(iteration);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}else {\n\t\t\treturn Promise.resolve(this._parseList(values));\n\t\t}\n\t}\n\t\n\t_addPlaceholder(contents){\n\t\tvar placeholder = document.createElement(\"div\");\n\t\t\n\t\tif(typeof contents === \"function\"){\n\t\t\tcontents = contents(this.cell.getComponent(), this.listEl);\n\t\t}\n\t\t\n\t\tif(contents){\n\t\t\tthis._clearList();\n\t\t\t\n\t\t\tif(contents instanceof HTMLElement){\n\t\t\t\tplaceholder = contents;\n\t\t\t}else {\n\t\t\t\tplaceholder.classList.add(\"tabulator-edit-list-placeholder\");\n\t\t\t\tplaceholder.innerHTML = contents;\n\t\t\t}\n\t\t\t\n\t\t\tthis.listEl.appendChild(placeholder);\n\t\t\t\n\t\t\tthis._showList();\n\t\t}\n\t}\n\t\n\t_ajaxRequest(url, term){\n\t\tvar params = this.params.filterRemote ? {term:term} : {};\n\t\turl = urlBuilder(url, {}, params);\n\t\t\n\t\treturn fetch(url)\n\t\t\t.then((response)=>{\n\t\t\t\tif(response.ok) {\n\t\t\t\t\treturn response.json()\n\t\t\t\t\t\t.catch((error)=>{\n\t\t\t\t\t\t\tconsole.warn(\"List Ajax Load Error - Invalid JSON returned\", error);\n\t\t\t\t\t\t\treturn Promise.reject(error);\n\t\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\tconsole.error(\"List Ajax Load Error - Connection Error: \" + response.status, response.statusText);\n\t\t\t\t\treturn Promise.reject(response);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error)=>{\n\t\t\t\tconsole.error(\"List Ajax Load Error - Connection Error: \", error);\n\t\t\t\treturn Promise.reject(error);\n\t\t\t});\n\t}\n\t\n\t_uniqueColumnValues(field){\n\t\tvar output = {},\n\t\tdata = this.table.getData(this.params.valuesLookup),\n\t\tcolumn;\n\t\t\n\t\tif(field){\n\t\t\tcolumn = this.table.columnManager.getColumnByField(field);\n\t\t}else {\n\t\t\tcolumn = this.cell.getColumn()._getSelf();\n\t\t}\n\t\t\n\t\tif(column){\n\t\t\tdata.forEach((row) => {\n\t\t\t\tvar val = column.getFieldValue(row);\n\t\t\t\t\n\t\t\t\tif(val !== null && typeof val !== \"undefined\" && val !== \"\"){\n\t\t\t\t\toutput[val] = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\tconsole.warn(\"unable to find matching column to create select lookup list:\", field);\n\t\t\toutput = [];\n\t\t}\n\t\t\n\t\treturn Object.keys(output);\n\t}\n\t\n\t\n\t_parseList(inputValues){\n\t\tvar data = [];\n\t\t\n\t\tif(!Array.isArray(inputValues)){\n\t\t\tinputValues = Object.entries(inputValues).map(([key, value]) => {\n\t\t\t\treturn {\n\t\t\t\t\tlabel:value,\n\t\t\t\t\tvalue:key,\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t\t\n\t\tinputValues.forEach((value) => {\n\t\t\tif(typeof value !== \"object\"){\n\t\t\t\tvalue = {\n\t\t\t\t\tlabel:value,\n\t\t\t\t\tvalue:value,\n\t\t\t\t};\n\t\t\t}\n\t\t\t\n\t\t\tthis._parseListItem(value, data, 0);\n\t\t});\n\t\t\n\t\tif(!this.currentItems.length && this.params.freetext){\n\t\t\tthis.input.value = this.initialValues;\n\t\t\tthis.typing = true;\n\t\t\tthis.lastAction = \"typing\";\n\t\t}\n\t\t\n\t\tthis.data = data;\n\t\t\n\t\treturn data;    \n\t}\n\t\n\t_parseListItem(option, data, level){\n\t\tvar item = {};\n\t\t\n\t\tif(option.options){\n\t\t\titem = this._parseListGroup(option, level + 1);\n\t\t}else {\n\t\t\titem = {\n\t\t\t\tlabel:option.label,\n\t\t\t\tvalue:option.value,\n\t\t\t\titemParams:option.itemParams,\n\t\t\t\telementAttributes: option.elementAttributes,\n\t\t\t\telement:false,\n\t\t\t\tselected:false,\n\t\t\t\tvisible:true,\n\t\t\t\tlevel:level,\n\t\t\t\toriginal:option,\n\t\t\t};\n\t\t\t\n\t\t\tif(this.initialValues && this.initialValues.indexOf(option.value) > -1){\n\t\t\t\tthis._chooseItem(item, true);\n\t\t\t}\n\t\t}\n\t\t\n\t\tdata.push(item);\n\t}\n\t\n\t_parseListGroup(option, level){\n\t\tvar item = {\n\t\t\tlabel:option.label,\n\t\t\tgroup:true,\n\t\t\titemParams:option.itemParams,\n\t\t\telementAttributes:option.elementAttributes,\n\t\t\telement:false,\n\t\t\tvisible:true,\n\t\t\tlevel:level,\n\t\t\toptions:[],\n\t\t\toriginal:option,\n\t\t};\n\t\t\n\t\toption.options.forEach((child) => {\n\t\t\tthis._parseListItem(child, item.options, level);\n\t\t});\n\t\t\n\t\treturn item;\n\t}\n\t\n\t_sortOptions(options){\n\t\tvar sorter;\n\t\t\n\t\tif(this.params.sort){\n\t\t\tsorter = typeof this.params.sort === \"function\" ? this.params.sort : this._defaultSortFunction.bind(this);\n\t\t\t\n\t\t\tthis._sortGroup(sorter, options);\n\t\t}\n\t\t\n\t\treturn options;\n\t}\n\t\n\t_sortGroup(sorter, options){\n\t\toptions.sort((a,b) => {\n\t\t\treturn sorter(a.label, b.label, a.value, b.value, a.original, b.original);\n\t\t});\n\t\t\n\t\toptions.forEach((option) => {\n\t\t\tif(option.group){\n\t\t\t\tthis._sortGroup(sorter, option.options);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t_defaultSortFunction(as, bs){\n\t\tvar a, b, a1, b1, i= 0, L, rx = /(\\d+)|(\\D+)/g, rd = /\\d/;\n\t\tvar emptyAlign = 0;\n\t\t\n\t\tif(this.params.sort === \"desc\"){\n\t\t\t[as, bs] = [bs, as];\n\t\t}\n\t\t\n\t\t//handle empty values\n\t\tif(!as && as!== 0){\n\t\t\temptyAlign =  !bs && bs!== 0 ? 0 : -1;\n\t\t}else if(!bs && bs!== 0){\n\t\t\temptyAlign =  1;\n\t\t}else {\n\t\t\tif(isFinite(as) && isFinite(bs)) return as - bs;\n\t\t\ta = String(as).toLowerCase();\n\t\t\tb = String(bs).toLowerCase();\n\t\t\tif(a === b) return 0;\n\t\t\tif(!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1;\n\t\t\ta = a.match(rx);\n\t\t\tb = b.match(rx);\n\t\t\tL = a.length > b.length ? b.length : a.length;\n\t\t\twhile(i < L){\n\t\t\t\ta1= a[i];\n\t\t\t\tb1= b[i++];\n\t\t\t\tif(a1 !== b1){\n\t\t\t\t\tif(isFinite(a1) && isFinite(b1)){\n\t\t\t\t\t\tif(a1.charAt(0) === \"0\") a1 = \".\" + a1;\n\t\t\t\t\t\tif(b1.charAt(0) === \"0\") b1 = \".\" + b1;\n\t\t\t\t\t\treturn a1 - b1;\n\t\t\t\t\t}\n\t\t\t\t\telse return a1 > b1 ? 1 : -1;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn a.length > b.length;\n\t\t}\n\t\t\n\t\treturn emptyAlign;\n\t}\n\t\n\t_filterOptions(){\n\t\tvar filterFunc = this.params.filterFunc || this._defaultFilterFunc,\n\t\tterm = this.input.value;\n\t\t\n\t\tif(term){\n\t\t\tthis.filtered = true;\n\t\t\t\n\t\t\tthis.data.forEach((item) => {\n\t\t\t\tthis._filterItem(filterFunc, term, item);\n\t\t\t});\n\t\t}else {\n\t\t\tthis.filtered = false;\n\t\t}\n\t\t\n\t\treturn this.data;\n\t}\n\t\n\t_filterItem(func, term, item){\n\t\tvar matches = false;\n\t\t\n\t\tif(!item.group){\n\t\t\titem.visible = func(term, item.label, item.value, item.original);\n\t\t}else {\n\t\t\titem.options.forEach((option) => {\n\t\t\t\tif(this._filterItem(func, term, option)){\n\t\t\t\t\tmatches = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\titem.visible = matches;\n\t\t}\n\t\t\n\t\treturn item.visible;\n\t}\n\t\n\t_defaultFilterFunc(term, label, value, item){\n\t\tterm = String(term).toLowerCase();\n\t\t\n\t\tif(label !== null && typeof label !== \"undefined\"){\n\t\t\tif(String(label).toLowerCase().indexOf(term) > -1 || String(value).toLowerCase().indexOf(term) > -1){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\t//////////////////////////////////////\n\t/////////// Display List /////////////\n\t//////////////////////////////////////\n\t\n\t_clearList(){\n\t\twhile(this.listEl.firstChild) this.listEl.removeChild(this.listEl.firstChild);\n\t\t\n\t\tthis.displayItems = [];\n\t}\n\t\n\t_buildList(data){\n\t\tthis._clearList();\n\t\t\n\t\tdata.forEach((option) => {\n\t\t\tthis._buildItem(option);\n\t\t});\n\t\t\n\t\tif(!this.displayItems.length){\n\t\t\tthis._addPlaceholder(this.params.placeholderEmpty);\n\t\t}  \n\t}\n\t\n\t_buildItem(item){\n\t\tvar el = item.element,\n\t\tcontents;\n\t\t\n\t\tif(!this.filtered || item.visible){\n\t\t\t\n\t\t\tif(!el){\n\t\t\t\tel = document.createElement(\"div\");\n\t\t\t\tel.tabIndex = 0;\n\t\t\t\t\n\t\t\t\tcontents = this.params.itemFormatter ? this.params.itemFormatter(item.label, item.value, item.original, el) : item.label;\n\t\t\t\t\n\t\t\t\tif(contents instanceof HTMLElement){\n\t\t\t\t\tel.appendChild(contents);\n\t\t\t\t}else {\n\t\t\t\t\tel.innerHTML = contents;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(item.group){\n\t\t\t\t\tel.classList.add(\"tabulator-edit-list-group\");\n\t\t\t\t}else {\n\t\t\t\t\tel.classList.add(\"tabulator-edit-list-item\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tel.classList.add(\"tabulator-edit-list-group-level-\" + item.level);\n\t\t\t\t\n\t\t\t\tif(item.elementAttributes && typeof item.elementAttributes == \"object\"){\n\t\t\t\t\tfor (let key in item.elementAttributes){\n\t\t\t\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\t\t\t\tkey = key.slice(1);\n\t\t\t\t\t\t\tel.setAttribute(key, this.input.getAttribute(key) + item.elementAttributes[\"+\" + key]);\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tel.setAttribute(key, item.elementAttributes[key]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(item.group){\n\t\t\t\t\tel.addEventListener(\"click\", this._groupClick.bind(this, item));\n\t\t\t\t}else {\n\t\t\t\t\tel.addEventListener(\"click\", this._itemClick.bind(this, item));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tel.addEventListener(\"mousedown\", this._preventBlur.bind(this));\n\t\t\t\t\n\t\t\t\titem.element = el;\n\t\t\t}\n\t\t\t\n\t\t\tthis._styleItem(item);\n\t\t\t\n\t\t\tthis.listEl.appendChild(el);\n\t\t\t\n\t\t\tif(item.group){\n\t\t\t\titem.options.forEach((option) => {\n\t\t\t\t\tthis._buildItem(option);\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tthis.displayItems.push(item);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_showList(){\n\t\tvar startVis = this.popup && this.popup.isVisible();\n\t\t\n\t\tif(this.input.parentNode){\n\t\t\tif(this.params.autocomplete && this.input.value === \"\" && !this.params.listOnEmpty){\n\t\t\t\tif(this.popup){\n\t\t\t\t\tthis.popup.hide(true);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tthis._setListWidth();\n\t\t\t\n\t\t\tif(!this.popup){\n\t\t\t\tthis.popup = this.edit.popup(this.listEl);\n\t\t\t}\n\t\t\t\n\t\t\tthis.popup.show(this.cell.getElement(), \"bottom\");\n\t\t\t\n\t\t\tif(!startVis){\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.popup.hideOnBlur(this._resolveValue.bind(this, true));\n\t\t\t\t}, 10);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_styleItem(item){\n\t\tif(item && item.element){\n\t\t\tif(item.selected){\n\t\t\t\titem.element.classList.add(\"active\");\n\t\t\t}else {\n\t\t\t\titem.element.classList.remove(\"active\");\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//////////////////////////////////////\n\t///////// User Interaction ///////////\n\t//////////////////////////////////////\n\t\n\t_itemClick(item, e){\n\t\te.stopPropagation();\n\t\t\n\t\tthis._chooseItem(item);\n\t}\n\t\n\t_groupClick(item, e){\n\t\te.stopPropagation();\n\t}\n\t\n\t\n\t//////////////////////////////////////\n\t////// Current Item Management ///////\n\t//////////////////////////////////////\n\t\n\t_cancel(){\n\t\tthis.popup.hide(true);\n\t\tthis.actions.cancel();\n\t}\n\t\n\t_clearChoices(){\n\t\tthis.typing = true;\n\t\t\n\t\tthis.currentItems.forEach((item) => {\n\t\t\titem.selected = false;\n\t\t\tthis._styleItem(item);\n\t\t});\n\t\t\n\t\tthis.currentItems = [];\n\t\t\n\t\tthis.focusedItem = null;\n\t}\n\t\n\t_chooseItem(item, silent){\n\t\tvar index;\n\t\t\n\t\tthis.typing = false;\n\t\t\n\t\tif(this.params.multiselect){\n\t\t\tindex = this.currentItems.indexOf(item);\n\t\t\t\n\t\t\tif(index > -1){\n\t\t\t\tthis.currentItems.splice(index, 1);\n\t\t\t\titem.selected = false;\n\t\t\t}else {\n\t\t\t\tthis.currentItems.push(item);\n\t\t\t\titem.selected = true;\n\t\t\t}\n\t\t\t\n\t\t\tthis.input.value = this.currentItems.map(item => item.label).join(\",\");\n\t\t\t\n\t\t\tthis._styleItem(item);\n\t\t\t\n\t\t}else {\n\t\t\tthis.currentItems = [item];\n\t\t\titem.selected = true;\n\t\t\t\n\t\t\tthis.input.value = item.label;\n\t\t\t\n\t\t\tthis._styleItem(item);\n\t\t\t\n\t\t\tif(!silent){\n\t\t\t\tthis._resolveValue();\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis._focusItem(item);\n\t}\n\t\n\t_resolveValue(blur){\n\t\tvar output, initialValue;\n\t\t\n\t\tif(this.popup){\n\t\t\tthis.popup.hide(true);\n\t\t}\n\t\t\n\t\tif(this.params.multiselect){\n\t\t\toutput = this.currentItems.map(item => item.value);\n\t\t}else {\n\t\t\tif(blur && this.params.autocomplete && this.typing){\n\t\t\t\tif(this.params.freetext || (this.params.allowEmpty && this.input.value === \"\")){\n\t\t\t\t\toutput = this.input.value;\n\t\t\t\t}else {\n\t\t\t\t\tthis.actions.cancel();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(this.currentItems[0]){\n\t\t\t\t\toutput = this.currentItems[0].value;\n\t\t\t\t}else {\n\t\t\t\t\tinitialValue = Array.isArray(this.initialValues) ? this.initialValues[0] : this.initialValues;\n\t\t\t\t\t\n\t\t\t\t\tif(initialValue === null || typeof initialValue === \"undefined\" || initialValue === \"\"){\n\t\t\t\t\t\toutput = initialValue;\n\t\t\t\t\t}else {\n\t\t\t\t\t\toutput = this.params.emptyValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(output === \"\"){\n\t\t\toutput = this.params.emptyValue;\n\t\t}\n\t\t\n\t\tthis.actions.success(output);\n\t\t\n\t\tif(this.isFilter){\n\t\t\tthis.initialValues = output && !Array.isArray(output) ? [output] : output;\n\t\t\tthis.currentItems = [];\n\t\t}\n\t}\n\t\n}\n\nfunction select(cell, onRendered, success, cancel, editorParams){\n\n\tthis.deprecationMsg(\"The select editor has been deprecated, please use the new list editor\");\n\n\tvar list = new Edit(this, cell, onRendered, success, cancel, editorParams);\n\n\treturn list.input;\n}\n\nfunction list(cell, onRendered, success, cancel, editorParams){\n\tvar list = new Edit(this, cell, onRendered, success, cancel, editorParams);\n\n\treturn list.input;\n}\n\nfunction autocomplete(cell, onRendered, success, cancel, editorParams){\n\n\tthis.deprecationMsg(\"The autocomplete editor has been deprecated, please use the new list editor with the 'autocomplete' editorParam\");\n\n\teditorParams.autocomplete = true;\n\n\tvar list = new Edit(this, cell, onRendered, success, cancel, editorParams);\n\n\treturn list.input;\n}\n\n//star rating\nfunction star(cell, onRendered, success, cancel, editorParams){\n\tvar self = this,\n\telement = cell.getElement(),\n\tvalue = cell.getValue(),\n\tmaxStars = element.getElementsByTagName(\"svg\").length || 5,\n\tsize = element.getElementsByTagName(\"svg\")[0] ? element.getElementsByTagName(\"svg\")[0].getAttribute(\"width\") : 14,\n\tstars = [],\n\tstarsHolder = document.createElement(\"div\"),\n\tstar = document.createElementNS('http://www.w3.org/2000/svg', \"svg\");\n\n\n\t//change star type\n\tfunction starChange(val){\n\t\tstars.forEach(function(star, i){\n\t\t\tif(i < val){\n\t\t\t\tif(self.table.browser == \"ie\"){\n\t\t\t\t\tstar.setAttribute(\"class\", \"tabulator-star-active\");\n\t\t\t\t}else {\n\t\t\t\t\tstar.classList.replace(\"tabulator-star-inactive\", \"tabulator-star-active\");\n\t\t\t\t}\n\n\t\t\t\tstar.innerHTML = '<polygon fill=\"#488CE9\" stroke=\"#014AAE\" stroke-width=\"37.6152\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" points=\"259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 \"/>';\n\t\t\t}else {\n\t\t\t\tif(self.table.browser == \"ie\"){\n\t\t\t\t\tstar.setAttribute(\"class\", \"tabulator-star-inactive\");\n\t\t\t\t}else {\n\t\t\t\t\tstar.classList.replace(\"tabulator-star-active\", \"tabulator-star-inactive\");\n\t\t\t\t}\n\n\t\t\t\tstar.innerHTML = '<polygon fill=\"#010155\" stroke=\"#686868\" stroke-width=\"37.6152\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" points=\"259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 \"/>';\n\t\t\t}\n\t\t});\n\t}\n\n\t//build stars\n\tfunction buildStar(i){\n\n\t\tvar starHolder =  document.createElement(\"span\");\n\t\tvar nextStar = star.cloneNode(true);\n\n\t\tstars.push(nextStar);\n\n\t\tstarHolder.addEventListener(\"mouseenter\", function(e){\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t\tstarChange(i);\n\t\t});\n\n\t\tstarHolder.addEventListener(\"mousemove\", function(e){\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t});\n\n\t\tstarHolder.addEventListener(\"click\", function(e){\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t\tsuccess(i);\n\t\t\telement.blur();\n\t\t});\n\n\t\tstarHolder.appendChild(nextStar);\n\t\tstarsHolder.appendChild(starHolder);\n\n\t}\n\n\t//handle keyboard navigation value change\n\tfunction changeValue(val){\n\t\tvalue = val;\n\t\tstarChange(val);\n\t}\n\n\t//style cell\n\telement.style.whiteSpace = \"nowrap\";\n\telement.style.overflow = \"hidden\";\n\telement.style.textOverflow = \"ellipsis\";\n\n\t//style holding element\n\tstarsHolder.style.verticalAlign = \"middle\";\n\tstarsHolder.style.display = \"inline-block\";\n\tstarsHolder.style.padding = \"4px\";\n\n\t//style star\n\tstar.setAttribute(\"width\", size);\n\tstar.setAttribute(\"height\", size);\n\tstar.setAttribute(\"viewBox\", \"0 0 512 512\");\n\tstar.setAttribute(\"xml:space\", \"preserve\");\n\tstar.style.padding = \"0 1px\";\n\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tstarsHolder.setAttribute(key, starsHolder.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tstarsHolder.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\n\t//create correct number of stars\n\tfor(var i=1;i<= maxStars;i++){\n\t\tbuildStar(i);\n\t}\n\n\t//ensure value does not exceed number of stars\n\tvalue = Math.min(parseInt(value), maxStars);\n\n\t// set initial styling of stars\n\tstarChange(value);\n\n\tstarsHolder.addEventListener(\"mousemove\", function(e){\n\t\tstarChange(0);\n\t});\n\n\tstarsHolder.addEventListener(\"click\", function(e){\n\t\tsuccess(0);\n\t});\n\n\telement.addEventListener(\"blur\", function(e){\n\t\tcancel();\n\t});\n\n\t//allow key based navigation\n\telement.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\tcase 39: //right arrow\n\t\t\t\tchangeValue(value + 1);\n\t\t\t\tbreak;\n\n\t\t\tcase 37: //left arrow\n\t\t\t\tchangeValue(value - 1);\n\t\t\t\tbreak;\n\n\t\t\tcase 13: //enter\n\t\t\t\tsuccess(value);\n\t\t\t\tbreak;\n\n\t\t\tcase 27: //escape\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\treturn starsHolder;\n}\n\n//draggable progress bar\nfunction progress(cell, onRendered, success, cancel, editorParams){\n\tvar element = cell.getElement(),\n\tmax = typeof editorParams.max === \"undefined\" ? ((element.getElementsByTagName(\"div\")[0] && element.getElementsByTagName(\"div\")[0].getAttribute(\"max\")) || 100) : editorParams.max,\n\tmin = typeof editorParams.min === \"undefined\" ? ((element.getElementsByTagName(\"div\")[0] && element.getElementsByTagName(\"div\")[0].getAttribute(\"min\")) || 0) : editorParams.min,\n\tpercent = (max - min) / 100,\n\tvalue = cell.getValue() || 0,\n\thandle = document.createElement(\"div\"),\n\tbar = document.createElement(\"div\"),\n\tmouseDrag, mouseDragWidth;\n\n\t//set new value\n\tfunction updateValue(){\n\t\tvar style = window.getComputedStyle(element, null);\n\n\t\tvar calcVal = (percent * Math.round(bar.offsetWidth / ((element.clientWidth - parseInt(style.getPropertyValue(\"padding-left\")) - parseInt(style.getPropertyValue(\"padding-right\")))/100))) + min;\n\t\tsuccess(calcVal);\n\t\telement.setAttribute(\"aria-valuenow\", calcVal);\n\t\telement.setAttribute(\"aria-label\", value);\n\t}\n\n\t//style handle\n\thandle.style.position = \"absolute\";\n\thandle.style.right = \"0\";\n\thandle.style.top = \"0\";\n\thandle.style.bottom = \"0\";\n\thandle.style.width = \"5px\";\n\thandle.classList.add(\"tabulator-progress-handle\");\n\n\t//style bar\n\tbar.style.display = \"inline-block\";\n\tbar.style.position = \"relative\";\n\t// bar.style.top = \"8px\";\n\t// bar.style.bottom = \"8px\";\n\t// bar.style.left = \"4px\";\n\t// bar.style.marginRight = \"4px\";\n\tbar.style.height = \"100%\";\n\tbar.style.backgroundColor = \"#488CE9\";\n\tbar.style.maxWidth = \"100%\";\n\tbar.style.minWidth = \"0%\";\n\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tbar.setAttribute(key, bar.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tbar.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\n\t//style cell\n\telement.style.padding = \"4px 4px\";\n\n\t//make sure value is in range\n\tvalue = Math.min(parseFloat(value), max);\n\tvalue = Math.max(parseFloat(value), min);\n\n\t//workout percentage\n\tvalue = Math.round((value - min) / percent);\n\t// bar.style.right = value + \"%\";\n\tbar.style.width = value + \"%\";\n\n\telement.setAttribute(\"aria-valuemin\", min);\n\telement.setAttribute(\"aria-valuemax\", max);\n\n\tbar.appendChild(handle);\n\n\thandle.addEventListener(\"mousedown\", function(e){\n\t\tmouseDrag = e.screenX;\n\t\tmouseDragWidth = bar.offsetWidth;\n\t});\n\n\thandle.addEventListener(\"mouseover\", function(){\n\t\thandle.style.cursor = \"ew-resize\";\n\t});\n\n\telement.addEventListener(\"mousemove\", function(e){\n\t\tif(mouseDrag){\n\t\t\tbar.style.width = (mouseDragWidth + e.screenX - mouseDrag) + \"px\";\n\t\t}\n\t});\n\n\telement.addEventListener(\"mouseup\", function(e){\n\t\tif(mouseDrag){\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\n\t\t\tmouseDrag = false;\n\t\t\tmouseDragWidth = false;\n\n\t\t\tupdateValue();\n\t\t}\n\t});\n\n\t//allow key based navigation\n\telement.addEventListener(\"keydown\", function(e){\n\t\tswitch(e.keyCode){\n\t\t\tcase 39: //right arrow\n\t\t\t\te.preventDefault();\n\t\t\t\tbar.style.width = (bar.clientWidth + element.clientWidth/100) + \"px\";\n\t\t\t\tbreak;\n\n\t\t\tcase 37: //left arrow\n\t\t\t\te.preventDefault();\n\t\t\t\tbar.style.width = (bar.clientWidth - element.clientWidth/100) + \"px\";\n\t\t\t\tbreak;\n\n\t\t\tcase 9: //tab\n\t\t\tcase 13: //enter\n\t\t\t\tupdateValue();\n\t\t\t\tbreak;\n\n\t\t\tcase 27: //escape\n\t\t\t\tcancel();\n\t\t\t\tbreak;\n\n\t\t}\n\t});\n\n\telement.addEventListener(\"blur\", function(){\n\t\tcancel();\n\t});\n\n\treturn bar;\n}\n\n//checkbox\nfunction tickCross(cell, onRendered, success, cancel, editorParams){\n\tvar value = cell.getValue(),\n\tinput = document.createElement(\"input\"),\n\ttristate = editorParams.tristate,\n\tindetermValue = typeof editorParams.indeterminateValue === \"undefined\" ? null : editorParams.indeterminateValue,\n\tindetermState = false,\n\ttrueValueSet = Object.keys(editorParams).includes(\"trueValue\"),\n\tfalseValueSet = Object.keys(editorParams).includes(\"falseValue\");\n\t\n\tinput.setAttribute(\"type\", \"checkbox\");\n\tinput.style.marginTop = \"5px\";\n\tinput.style.boxSizing = \"border-box\";\n\t\n\tif(editorParams.elementAttributes && typeof editorParams.elementAttributes == \"object\"){\n\t\tfor (let key in editorParams.elementAttributes){\n\t\t\tif(key.charAt(0) == \"+\"){\n\t\t\t\tkey = key.slice(1);\n\t\t\t\tinput.setAttribute(key, input.getAttribute(key) + editorParams.elementAttributes[\"+\" + key]);\n\t\t\t}else {\n\t\t\t\tinput.setAttribute(key, editorParams.elementAttributes[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tinput.value = value;\n\t\n\tif(tristate && (typeof value === \"undefined\" || value === indetermValue || value === \"\")){\n\t\tindetermState = true;\n\t\tinput.indeterminate = true;\n\t}\n\t\n\tif(this.table.browser != \"firefox\" && this.table.browser != \"safari\"){ //prevent blur issue on mac firefox\n\t\tonRendered(function(){\n\t\t\tif(cell.getType() === \"cell\"){\n\t\t\t\tinput.focus({preventScroll: true});\n\t\t\t}\n\t\t});\n\t}\n\t\n\tinput.checked = trueValueSet ? value === editorParams.trueValue : (value === true || value === \"true\" || value === \"True\" || value === 1);\n\t\n\tfunction setValue(blur){\n\t\tvar checkedValue = input.checked;\n\t\t\n\t\tif(trueValueSet && checkedValue){\n\t\t\tcheckedValue = editorParams.trueValue;\n\t\t}else if(falseValueSet && !checkedValue){\n\t\t\tcheckedValue = editorParams.falseValue;\n\t\t}\n\t\t\n\t\tif(tristate){\n\t\t\tif(!blur){\n\t\t\t\tif(input.checked && !indetermState){\n\t\t\t\t\tinput.checked = false;\n\t\t\t\t\tinput.indeterminate = true;\n\t\t\t\t\tindetermState = true;\n\t\t\t\t\treturn indetermValue;\n\t\t\t\t}else {\n\t\t\t\t\tindetermState = false;\n\t\t\t\t\treturn checkedValue;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(indetermState){\n\t\t\t\t\treturn indetermValue;\n\t\t\t\t}else {\n\t\t\t\t\treturn checkedValue;\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\treturn checkedValue;\n\t\t}\n\t}\n\t\n\t//submit new value on blur\n\tinput.addEventListener(\"change\", function(e){\n\t\tsuccess(setValue());\n\t});\n\n\tinput.addEventListener(\"blur\", function(e){\n\t\tsuccess(setValue(true));\n\t});\n\t\n\t//submit new value on enter\n\tinput.addEventListener(\"keydown\", function(e){\n\t\tif(e.keyCode == 13){\n\t\t\tsuccess(setValue());\n\t\t}\n\t\tif(e.keyCode == 27){\n\t\t\tcancel();\n\t\t}\n\t});\n\t\n\treturn input;\n}\n\nvar defaultEditors = {\n\tinput:input,\n\ttextarea:textarea,\n\tnumber:number,\n\trange:range,\n\tdate:date,\n\ttime:time,\n\tdatetime:datetime,\n\tselect:select,\n\tlist:list,\n\tautocomplete:autocomplete,\n\tstar:star,\n\tprogress:progress,\n\ttickCross:tickCross,\n};\n\nclass Edit$1 extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.currentCell = false; //hold currently editing cell\n\t\tthis.mouseClick = false; //hold mousedown state to prevent click binding being overridden by editor opening\n\t\tthis.recursionBlock = false; //prevent focus recursion\n\t\tthis.invalidEdit = false;\n\t\tthis.editedCells = [];\n\t\t\n\t\tthis.editors = Edit$1.editors;\n\t\t\n\t\tthis.registerColumnOption(\"editable\");\n\t\tthis.registerColumnOption(\"editor\");\n\t\tthis.registerColumnOption(\"editorParams\");\n\t\t\n\t\tthis.registerColumnOption(\"cellEditing\");\n\t\tthis.registerColumnOption(\"cellEdited\");\n\t\tthis.registerColumnOption(\"cellEditCancelled\");\n\t\t\n\t\tthis.registerTableOption(\"editTriggerEvent\", \"focus\");\n\t\t\n\t\tthis.registerTableFunction(\"getEditedCells\", this.getEditedCells.bind(this));\n\t\tthis.registerTableFunction(\"clearCellEdited\", this.clearCellEdited.bind(this));\n\t\tthis.registerTableFunction(\"navigatePrev\", this.navigatePrev.bind(this));\n\t\tthis.registerTableFunction(\"navigateNext\", this.navigateNext.bind(this));\n\t\tthis.registerTableFunction(\"navigateLeft\", this.navigateLeft.bind(this));\n\t\tthis.registerTableFunction(\"navigateRight\", this.navigateRight.bind(this));\n\t\tthis.registerTableFunction(\"navigateUp\", this.navigateUp.bind(this));\n\t\tthis.registerTableFunction(\"navigateDown\", this.navigateDown.bind(this));\n\t\t\n\t\tthis.registerComponentFunction(\"cell\", \"isEdited\", this.cellIsEdited.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"clearEdited\", this.clearEdited.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"edit\", this.editCell.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"cancelEdit\", this.cellCancelEdit.bind(this));\n\t\t\n\t\tthis.registerComponentFunction(\"cell\", \"navigatePrev\", this.navigatePrev.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"navigateNext\", this.navigateNext.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"navigateLeft\", this.navigateLeft.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"navigateRight\", this.navigateRight.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"navigateUp\", this.navigateUp.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"navigateDown\", this.navigateDown.bind(this));\n\t}\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"cell-init\", this.bindEditor.bind(this));\n\t\tthis.subscribe(\"cell-delete\", this.clearEdited.bind(this));\n\t\tthis.subscribe(\"cell-value-changed\", this.updateCellClass.bind(this));\n\t\tthis.subscribe(\"column-layout\", this.initializeColumnCheck.bind(this));\n\t\tthis.subscribe(\"column-delete\", this.columnDeleteCheck.bind(this));\n\t\tthis.subscribe(\"row-deleting\", this.rowDeleteCheck.bind(this));\n\t\tthis.subscribe(\"row-layout\", this.rowEditableCheck.bind(this));\n\t\tthis.subscribe(\"data-refreshing\", this.cancelEdit.bind(this));\n\t\tthis.subscribe(\"clipboard-paste\", this.pasteBlocker.bind(this));\n\t\t\n\t\tthis.subscribe(\"keybinding-nav-prev\", this.navigatePrev.bind(this, undefined));\n\t\tthis.subscribe(\"keybinding-nav-next\", this.keybindingNavigateNext.bind(this));\n\t\t\n\t\t\n\t\t// this.subscribe(\"keybinding-nav-left\", this.navigateLeft.bind(this, undefined));\n\t\t// this.subscribe(\"keybinding-nav-right\", this.navigateRight.bind(this, undefined));\n\t\tthis.subscribe(\"keybinding-nav-up\", this.navigateUp.bind(this, undefined));\n\t\tthis.subscribe(\"keybinding-nav-down\", this.navigateDown.bind(this, undefined));\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////// Paste Negation //////////\n\t///////////////////////////////////\n\t\n\tpasteBlocker(e){\n\t\tif(this.currentCell){\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t////// Keybinding Functions ///////\n\t///////////////////////////////////\n\t\n\tkeybindingNavigateNext(e){\n\t\tvar cell = this.currentCell,\n\t\tnewRow = this.options(\"tabEndNewRow\");\n\n\t\tif(cell){\n\t\t\tif(!this.navigateNext(cell, e)){\n\t\t\t\tif(newRow){\n\t\t\t\t\tcell.getElement().firstChild.blur();\n\t\t\t\t\t\n\t\t\t\t\tif(!this.invalidEdit){\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(newRow === true){\n\t\t\t\t\t\t\tnewRow = this.table.addRow({});\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif(typeof newRow == \"function\"){\n\t\t\t\t\t\t\t\tnewRow = this.table.addRow(newRow(cell.row.getComponent()));\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tnewRow = this.table.addRow(Object.assign({}, newRow));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tnewRow.then(() => {\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tcell.getComponent().navigateNext();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Cell Functions //////////\n\t///////////////////////////////////\n\t\n\tcellIsEdited(cell){\n\t\treturn !! cell.modules.edit && cell.modules.edit.edited;\n\t}\n\t\n\tcellCancelEdit(cell){\n\t\tif(cell === this.currentCell){\n\t\t\tthis.table.modules.edit.cancelEdit();\n\t\t}else {\n\t\t\tconsole.warn(\"Cancel Editor Error - This cell is not currently being edited \");\n\t\t}\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\tupdateCellClass(cell){\n\t\tif(this.allowEdit(cell)) {\n\t\t\tcell.getElement().classList.add(\"tabulator-editable\");\n\t\t}\n\t\telse {\n\t\t\tcell.getElement().classList.remove(\"tabulator-editable\");\n\t\t}\n\t}\n\t\n\tclearCellEdited(cells){\n\t\tif(!cells){\n\t\t\tcells = this.table.modules.edit.getEditedCells();\n\t\t}\n\t\t\n\t\tif(!Array.isArray(cells)){\n\t\t\tcells = [cells];\n\t\t}\n\t\t\n\t\tcells.forEach((cell) => {\n\t\t\tthis.table.modules.edit.clearEdited(cell._getSelf());\n\t\t});\n\t}\n\t\n\tnavigatePrev(cell = this.currentCell, e){\n\t\tvar nextCell, prevRow;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tnextCell = this.navigateLeft();\n\t\t\t\n\t\t\tif(nextCell){\n\t\t\t\treturn true;\n\t\t\t}else {\n\t\t\t\tprevRow = this.table.rowManager.prevDisplayRow(cell.row, true);\n\t\t\t\t\n\t\t\t\tif(prevRow){\n\t\t\t\t\tnextCell = this.findPrevEditableCell(prevRow, prevRow.cells.length);\n\t\t\t\t\t\n\t\t\t\t\tif(nextCell){\n\t\t\t\t\t\tnextCell.getComponent().edit();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tnavigateNext(cell = this.currentCell, e){\n\t\tvar nextCell, nextRow;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tnextCell = this.navigateRight();\n\t\t\t\n\t\t\tif(nextCell){\n\t\t\t\treturn true;\n\t\t\t}else {\n\t\t\t\tnextRow = this.table.rowManager.nextDisplayRow(cell.row, true);\n\t\t\t\t\n\t\t\t\tif(nextRow){\n\t\t\t\t\tnextCell = this.findNextEditableCell(nextRow, -1);\n\t\t\t\t\t\n\t\t\t\t\tif(nextCell){\n\t\t\t\t\t\tnextCell.getComponent().edit();\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tnavigateLeft(cell = this.currentCell, e){\n\t\tvar index, nextCell;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tindex = cell.getIndex();\n\t\t\tnextCell = this.findPrevEditableCell(cell.row, index);\n\t\t\t\n\t\t\tif(nextCell){\n\t\t\t\tnextCell.getComponent().edit();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tnavigateRight(cell = this.currentCell, e){\n\t\tvar index, nextCell;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tindex = cell.getIndex();\n\t\t\tnextCell = this.findNextEditableCell(cell.row, index);\n\t\t\t\n\t\t\tif(nextCell){\n\t\t\t\tnextCell.getComponent().edit();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tnavigateUp(cell = this.currentCell, e){\n\t\tvar index, nextRow;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tindex = cell.getIndex();\n\t\t\tnextRow = this.table.rowManager.prevDisplayRow(cell.row, true);\n\t\t\t\n\t\t\tif(nextRow){\n\t\t\t\tnextRow.cells[index].getComponent().edit();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tnavigateDown(cell = this.currentCell, e){\n\t\tvar index, nextRow;\n\t\t\n\t\tif(cell){\n\t\t\t\n\t\t\tif(e){\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\t\n\t\t\tindex = cell.getIndex();\n\t\t\tnextRow = this.table.rowManager.nextDisplayRow(cell.row, true);\n\t\t\t\n\t\t\tif(nextRow){\n\t\t\t\tnextRow.cells[index].getComponent().edit();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tfindNextEditableCell(row, index){\n\t\tvar nextCell = false;\n\t\t\n\t\tif(index < row.cells.length-1){\n\t\t\tfor(var i = index+1; i < row.cells.length; i++){\n\t\t\t\tlet cell = row.cells[i];\n\t\t\t\t\n\t\t\t\tif(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){\n\t\t\t\t\tlet allowEdit = this.allowEdit(cell);\n\t\t\t\t\t\n\t\t\t\t\tif(allowEdit){\n\t\t\t\t\t\tnextCell = cell;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn nextCell;\n\t}\n\t\n\tfindPrevEditableCell(row, index){\n\t\tvar prevCell = false;\n\t\t\n\t\tif(index > 0){\n\t\t\tfor(var i = index-1; i >= 0; i--){\n\t\t\t\tlet cell = row.cells[i];\n\t\t\t\t\n\t\t\t\tif(cell.column.modules.edit && Helpers.elVisible(cell.getElement())){\n\t\t\t\t\tlet allowEdit = this.allowEdit(cell);\n\t\t\t\t\t\n\t\t\t\t\tif(allowEdit){\n\t\t\t\t\t\tprevCell = cell;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn prevCell;\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\tinitializeColumnCheck(column){\n\t\tif(typeof column.definition.editor !== \"undefined\"){\n\t\t\tthis.initializeColumn(column);\n\t\t}\n\t}\n\t\n\tcolumnDeleteCheck(column){\n\t\tif(this.currentCell && this.currentCell.column === column){\n\t\t\tthis.cancelEdit();\n\t\t}\n\t}\n\t\n\trowDeleteCheck(row){\n\t\tif(this.currentCell && this.currentCell.row === row){\n\t\t\tthis.cancelEdit();\n\t\t}\n\t}\n\t\n\trowEditableCheck(row){\n\t\trow.getCells().forEach((cell) => {\n\t\t\tif(cell.column.modules.edit && typeof cell.column.modules.edit.check === \"function\"){\n\t\t\t\tthis.updateCellClass(cell);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//initialize column editor\n\tinitializeColumn(column){\n\t\tvar config = {\n\t\t\teditor:false,\n\t\t\tblocked:false,\n\t\t\tcheck:column.definition.editable,\n\t\t\tparams:column.definition.editorParams || {}\n\t\t};\n\t\t\n\t\t//set column editor\n\t\tswitch(typeof column.definition.editor){\n\t\t\tcase \"string\":\n\t\t\t\tif(this.editors[column.definition.editor]){\n\t\t\t\t\tconfig.editor = this.editors[column.definition.editor];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Editor Error - No such editor found: \", column.definition.editor);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"function\":\n\t\t\t\tconfig.editor = column.definition.editor;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"boolean\":\n\t\t\t\tif(column.definition.editor === true){\n\t\t\t\t\tif(typeof column.definition.formatter !== \"function\"){\n\t\t\t\t\t\tif(this.editors[column.definition.formatter]){\n\t\t\t\t\t\t\tconfig.editor = this.editors[column.definition.formatter];\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tconfig.editor = this.editors[\"input\"];\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Editor Error - Cannot auto lookup editor for a custom formatter: \", column.definition.formatter);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif(config.editor){\n\t\t\tcolumn.modules.edit = config;\n\t\t}\n\t}\n\t\n\tgetCurrentCell(){\n\t\treturn this.currentCell ? this.currentCell.getComponent() : false;\n\t}\n\t\n\tclearEditor(cancel){\n\t\tvar cell = this.currentCell,\n\t\tcellEl;\n\t\t\n\t\tthis.invalidEdit = false;\n\t\t\n\t\tif(cell){\n\t\t\tthis.currentCell = false;\n\t\t\t\n\t\t\tcellEl = cell.getElement();\n\t\t\t\n\t\t\tthis.dispatch(\"edit-editor-clear\", cell, cancel);\n\t\t\t\n\t\t\tcellEl.classList.remove(\"tabulator-editing\");\n\t\t\t\n\t\t\twhile(cellEl.firstChild) cellEl.removeChild(cellEl.firstChild);\n\t\t\t\n\t\t\tcell.row.getElement().classList.remove(\"tabulator-editing\");\n\t\t\t\n\t\t\tcell.table.element.classList.remove(\"tabulator-editing\");\n\t\t}\n\t}\n\t\n\tcancelEdit(){\n\t\tif(this.currentCell){\n\t\t\tvar cell = this.currentCell;\n\t\t\tvar component = this.currentCell.getComponent();\n\t\t\t\n\t\t\tthis.clearEditor(true);\n\t\t\tcell.setValueActual(cell.getValue());\n\t\t\tcell.cellRendered();\n\t\t\t\n\t\t\tif(cell.column.definition.editor == \"textarea\" || cell.column.definition.variableHeight){\n\t\t\t\tcell.row.normalizeHeight(true);\n\t\t\t}\n\t\t\t\n\t\t\tif(cell.column.definition.cellEditCancelled){\n\t\t\t\tcell.column.definition.cellEditCancelled.call(this.table, component);\n\t\t\t}\n\t\t\t\n\t\t\tthis.dispatch(\"edit-cancelled\", cell);\n\t\t\tthis.dispatchExternal(\"cellEditCancelled\", component);\n\t\t}\n\t}\n\t\n\t//return a formatted value for a cell\n\tbindEditor(cell){\n\t\tif(cell.column.modules.edit){\n\t\t\tvar self = this,\n\t\t\telement = cell.getElement(true);\n\t\t\t\n\t\t\tthis.updateCellClass(cell);\n\t\t\telement.setAttribute(\"tabindex\", 0);\n\t\t\t\n\t\t\telement.addEventListener(\"mousedown\", function(e){\n\t\t\t\tif (e.button === 2) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t}else {\n\t\t\t\t\tself.mouseClick = true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif(this.options(\"editTriggerEvent\") === \"dblclick\"){\n\t\t\t\telement.addEventListener(\"dblclick\", function(e){\n\t\t\t\t\tif(!element.classList.contains(\"tabulator-editing\")){\n\t\t\t\t\t\telement.focus({preventScroll: true});\n\t\t\t\t\t\tself.edit(cell, e, false);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\tif(this.options(\"editTriggerEvent\") === \"focus\" || this.options(\"editTriggerEvent\") === \"click\"){\n\t\t\t\telement.addEventListener(\"click\", function(e){\n\t\t\t\t\tif(!element.classList.contains(\"tabulator-editing\")){\n\t\t\t\t\t\telement.focus({preventScroll: true});\n\t\t\t\t\t\tself.edit(cell, e, false);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tif(this.options(\"editTriggerEvent\") === \"focus\"){\n\t\t\t\telement.addEventListener(\"focus\", function(e){\n\t\t\t\t\tif(!self.recursionBlock){\n\t\t\t\t\t\tself.edit(cell, e, false);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfocusCellNoEvent(cell, block){\n\t\tthis.recursionBlock = true;\n\t\t\n\t\tif(!(block && this.table.browser === \"ie\")){\n\t\t\tcell.getElement().focus({preventScroll: true});\n\t\t}\n\t\t\n\t\tthis.recursionBlock = false;\n\t}\n\t\n\teditCell(cell, forceEdit){\n\t\tthis.focusCellNoEvent(cell);\n\t\tthis.edit(cell, false, forceEdit);\n\t}\n\t\n\tfocusScrollAdjust(cell){\n\t\tif(this.table.rowManager.getRenderMode() == \"virtual\"){\n\t\t\tvar topEdge = this.table.rowManager.element.scrollTop,\n\t\t\tbottomEdge = this.table.rowManager.element.clientHeight + this.table.rowManager.element.scrollTop,\n\t\t\trowEl = cell.row.getElement();\n\t\t\t\n\t\t\tif(rowEl.offsetTop < topEdge){\n\t\t\t\tthis.table.rowManager.element.scrollTop -= (topEdge - rowEl.offsetTop);\n\t\t\t}else {\n\t\t\t\tif(rowEl.offsetTop + rowEl.offsetHeight  > bottomEdge){\n\t\t\t\t\tthis.table.rowManager.element.scrollTop += (rowEl.offsetTop + rowEl.offsetHeight - bottomEdge);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvar leftEdge = this.table.rowManager.element.scrollLeft,\n\t\t\trightEdge = this.table.rowManager.element.clientWidth + this.table.rowManager.element.scrollLeft,\n\t\t\tcellEl = cell.getElement();\n\t\t\t\n\t\t\tif(this.table.modExists(\"frozenColumns\")){\n\t\t\t\tleftEdge += parseInt(this.table.modules.frozenColumns.leftMargin || 0);\n\t\t\t\trightEdge -= parseInt(this.table.modules.frozenColumns.rightMargin || 0);\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.options.renderHorizontal === \"virtual\"){\n\t\t\t\tleftEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);\n\t\t\t\trightEdge -= parseInt(this.table.columnManager.renderer.vDomPadLeft);\n\t\t\t}\n\t\t\t\n\t\t\tif(cellEl.offsetLeft < leftEdge){\n\t\t\t\tthis.table.rowManager.element.scrollLeft -= (leftEdge - cellEl.offsetLeft);\n\t\t\t}else {\n\t\t\t\tif(cellEl.offsetLeft + cellEl.offsetWidth  > rightEdge){\n\t\t\t\t\tthis.table.rowManager.element.scrollLeft += (cellEl.offsetLeft + cellEl.offsetWidth - rightEdge);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tallowEdit(cell) {\n\t\tvar check = cell.column.modules.edit ? true : false;\n\t\t\n\t\tif(cell.column.modules.edit){\n\t\t\tswitch(typeof cell.column.modules.edit.check){\n\t\t\t\tcase \"function\":\n\t\t\t\t\tif(cell.row.initialized){\n\t\t\t\t\t\tcheck = cell.column.modules.edit.check(cell.getComponent());\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"string\":\n\t\t\t\t\tcheck = !!cell.row.data[cell.column.modules.edit.check];\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"boolean\":\n\t\t\t\t\tcheck = cell.column.modules.edit.check;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn check;\n\t}\n\t\n\tedit(cell, e, forceEdit){\n\t\tvar self = this,\n\t\tallowEdit = true,\n\t\trendered = function(){},\n\t\telement = cell.getElement(),\n\t\teditFinished = false,\n\t\tcellEditor, component, params;\n\n\t\t//prevent editing if another cell is refusing to leave focus (eg. validation fail)\n\t\t\n\t\tif(this.currentCell){\n\t\t\tif(!this.invalidEdit && this.currentCell !== cell){\n\t\t\t\tthis.cancelEdit();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t//handle successful value change\n\t\tfunction success(value){\n\t\t\tif(self.currentCell === cell && !editFinished){\n\t\t\t\tvar valid = self.chain(\"edit-success\", [cell, value], true, true);\n\n\t\t\t\tif(valid === true || self.table.options.validationMode === \"highlight\"){\n\n\t\t\t\t\teditFinished = true;\n\n\t\t\t\t\tself.clearEditor();\n\t\t\t\t\t\n\t\t\t\t\tif(!cell.modules.edit){\n\t\t\t\t\t\tcell.modules.edit = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcell.modules.edit.edited = true;\n\t\t\t\t\t\n\t\t\t\t\tif(self.editedCells.indexOf(cell) == -1){\n\t\t\t\t\t\tself.editedCells.push(cell);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcell.setValue(value, true);\n\n\t\t\t\t\treturn valid === true;\n\t\t\t\t}else {\n\t\t\t\t\teditFinished = true;\n\t\t\t\t\tself.invalidEdit = true;\n\t\t\t\t\tself.focusCellNoEvent(cell, true);\n\t\t\t\t\trendered();\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\teditFinished = false;\n\t\t\t\t\t}, 10);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t//handle aborted edit\n\t\tfunction cancel(){\n\t\t\t// editFinished = true;\n\n\t\t\tif(self.currentCell === cell && !editFinished){\n\t\t\t\tself.cancelEdit();\n\t\t\t}\n\t\t}\n\t\t\n\t\tfunction onRendered(callback){\n\t\t\trendered = callback;\n\t\t}\n\t\t\n\t\tif(!cell.column.modules.edit.blocked){\n\t\t\tif(e){\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t\t\n\t\t\tallowEdit = this.allowEdit(cell);\n\t\t\t\n\t\t\tif(allowEdit || forceEdit){\n\t\t\t\tself.cancelEdit();\n\t\t\t\t\n\t\t\t\tself.currentCell = cell;\n\t\t\t\t\n\t\t\t\tthis.focusScrollAdjust(cell);\n\t\t\t\t\n\t\t\t\tcomponent = cell.getComponent();\n\t\t\t\t\n\t\t\t\tif(this.mouseClick){\n\t\t\t\t\tthis.mouseClick = false;\n\t\t\t\t\t\n\t\t\t\t\tif(cell.column.definition.cellClick){\n\t\t\t\t\t\tcell.column.definition.cellClick.call(this.table, e, component);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(cell.column.definition.cellEditing){\n\t\t\t\t\tcell.column.definition.cellEditing.call(this.table, component);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.dispatch(\"cell-editing\", cell);\n\t\t\t\tthis.dispatchExternal(\"cellEditing\", component);\n\t\t\t\t\n\t\t\t\tparams = typeof cell.column.modules.edit.params === \"function\" ? cell.column.modules.edit.params(component) : cell.column.modules.edit.params;\n\t\t\t\t\n\t\t\t\tcellEditor = cell.column.modules.edit.editor.call(self, component, onRendered, success, cancel, params);\n\t\t\t\t\n\t\t\t\t//if editor returned, add to DOM, if false, abort edit\n\t\t\t\tif(this.currentCell && cellEditor !== false){\n\t\t\t\t\tif(cellEditor instanceof Node){\n\t\t\t\t\t\telement.classList.add(\"tabulator-editing\");\n\t\t\t\t\t\tcell.row.getElement().classList.add(\"tabulator-editing\");\n\t\t\t\t\t\tcell.table.element.classList.add(\"tabulator-editing\");\n\t\t\t\t\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\t\t\t\t\t\telement.appendChild(cellEditor);\n\t\t\t\t\t\t\n\t\t\t\t\t\t//trigger onRendered Callback\n\t\t\t\t\t\trendered();\n\t\t\t\t\t\t\n\t\t\t\t\t\t//prevent editing from triggering rowClick event\n\t\t\t\t\t\tvar children = element.children;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor (var i = 0; i < children.length; i++) {\n\t\t\t\t\t\t\tchildren[i].addEventListener(\"click\", function(e){\n\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Edit Error - Editor should return an instance of Node, the editor returned:\", cellEditor);\n\t\t\t\t\t\tthis.blur(element);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tthis.blur(element);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn true;\n\t\t\t}else {\n\t\t\t\tthis.mouseClick = false;\n\t\t\t\tthis.blur(element);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}else {\n\t\t\tthis.mouseClick = false;\n\t\t\tthis.blur(element);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tblur(element){\n\t\tif(!this.confirm(\"edit-blur\", [element]) ){\n\t\t\telement.blur();\n\t\t}\n\t}\n\t\n\tgetEditedCells(){\n\t\tvar output = [];\n\t\t\n\t\tthis.editedCells.forEach((cell) => {\n\t\t\toutput.push(cell.getComponent());\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tclearEdited(cell){\n\t\tvar editIndex;\n\t\t\n\t\tif(cell.modules.edit && cell.modules.edit.edited){\n\t\t\tcell.modules.edit.edited = false;\n\t\t\t\n\t\t\tthis.dispatch(\"edit-edited-clear\", cell);\n\t\t}\n\t\t\n\t\teditIndex = this.editedCells.indexOf(cell);\n\t\t\n\t\tif(editIndex > -1){\n\t\t\tthis.editedCells.splice(editIndex, 1);\n\t\t}\n\t}\n}\n\nEdit$1.moduleName = \"edit\";\n\n//load defaults\nEdit$1.editors = defaultEditors;\n\nclass ExportRow{\n\tconstructor(type, columns, component, indent){\n\t\tthis.type = type;\n\t\tthis.columns = columns;\n\t\tthis.component = component || false;\n\t\tthis.indent = indent || 0;\n\t}\n}\n\nclass ExportColumn{\n\tconstructor(value, component, width, height, depth){\n\t\tthis.value = value;\n\t\tthis.component = component || false;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.depth = depth;\n\t}\n}\n\nclass Export extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.config = {};\n\t\tthis.cloneTableStyle = true;\n\t\tthis.colVisProp = \"\";\n\t\t\n\t\tthis.registerTableOption(\"htmlOutputConfig\", false); //html output config\n\t\t\n\t\tthis.registerColumnOption(\"htmlOutput\");\n\t\tthis.registerColumnOption(\"titleHtmlOutput\");\n\t}\n\t\n\tinitialize(){\n\t\tthis.registerTableFunction(\"getHtml\", this.getHtml.bind(this));\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\t\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\tgenerateExportList(config, style, range, colVisProp){\n\t\tthis.cloneTableStyle = style;\n\t\tthis.config = config || {};\n\t\tthis.colVisProp = colVisProp;\n\n\t\tvar headers, body;\n\t\t\n\t\tif (range === 'range') {\n\t\t\tvar columns = this.table.modules.selectRange.selectedColumns();\n\t\t\theaders = this.config.columnHeaders !== false\n\t\t\t\t? this.headersToExportRows(this.generateColumnGroupHeaders(columns))\n\t\t\t\t: [];\n\t\t\tbody = this.bodyToExportRows(this.rowLookup(range), this.table.modules.selectRange.selectedColumns(true));\n\t\t} else {\n\t\t\theaders = this.config.columnHeaders !== false ? this.headersToExportRows(this.generateColumnGroupHeaders()) : [];\n\t\t\tbody = this.bodyToExportRows(this.rowLookup(range));\n\t\t}\n\n\t\treturn headers.concat(body);\n\t}\n\t\n\tgenerateTable(config, style, range, colVisProp){\n\t\tvar list = this.generateExportList(config, style, range, colVisProp);\n\t\t\n\t\treturn this.generateTableElement(list);\n\t}\n\t\n\trowLookup(range){\n\t\tvar rows = [];\n\t\t\n\t\tif(typeof range == \"function\"){\n\t\t\trange.call(this.table).forEach((row) =>{\n\t\t\t\trow = this.table.rowManager.findRow(row);\n\t\t\t\t\n\t\t\t\tif(row){\n\t\t\t\t\trows.push(row);\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\tswitch(range){\n\t\t\t\tcase true:\n\t\t\t\tcase \"visible\":\n\t\t\t\t\trows = this.table.rowManager.getVisibleRows(false, true);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"all\":\n\t\t\t\t\trows = this.table.rowManager.rows;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"selected\":\n\t\t\t\t\trows = this.table.modules.selectRow.selectedRows;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"range\":\n\t\t\t\t\trows = this.table.modules.selectRange.selectedRows();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"active\":\n\t\t\t\tdefault:\n\t\t\t\t\tif(this.table.options.pagination){\n\t\t\t\t\t\trows = this.table.rowManager.getDisplayRows(this.table.rowManager.displayRows.length - 2);\n\t\t\t\t\t}else {\n\t\t\t\t\t\trows = this.table.rowManager.getDisplayRows();\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn Object.assign([], rows);\n\t}\n\t\n\tgenerateColumnGroupHeaders(columns){\n\t\tvar output = [];\n\t\t\n\t\tif (!columns) {\n\t\t\tcolumns = this.config.columnGroups !== false ? this.table.columnManager.columns : this.table.columnManager.columnsByIndex;\n\t\t}\n\t\t\n\t\tcolumns.forEach((column) => {\n\t\t\tvar colData = this.processColumnGroup(column);\n\t\t\t\n\t\t\tif(colData){\n\t\t\t\toutput.push(colData);\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\t\n\tprocessColumnGroup(column){\n\t\tvar subGroups = column.columns,\n\t\tmaxDepth = 0,\n\t\ttitle = column.definition[\"title\" + (this.colVisProp.charAt(0).toUpperCase() + this.colVisProp.slice(1))] || column.definition.title;\n\t\t\n\t\tvar groupData = {\n\t\t\ttitle:title,\n\t\t\tcolumn:column,\n\t\t\tdepth:1,\n\t\t};\n\t\t\n\t\tif(subGroups.length){\n\t\t\tgroupData.subGroups = [];\n\t\t\tgroupData.width = 0;\n\t\t\t\n\t\t\tsubGroups.forEach((subGroup) => {\n\t\t\t\tvar subGroupData = this.processColumnGroup(subGroup);\n\t\t\t\t\n\t\t\t\tif(subGroupData){\n\t\t\t\t\tgroupData.width += subGroupData.width;\n\t\t\t\t\tgroupData.subGroups.push(subGroupData);\n\t\t\t\t\t\n\t\t\t\t\tif(subGroupData.depth > maxDepth){\n\t\t\t\t\t\tmaxDepth = subGroupData.depth;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tgroupData.depth += maxDepth;\n\t\t\t\n\t\t\tif(!groupData.width){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}else {\n\t\t\tif(this.columnVisCheck(column)){\n\t\t\t\tgroupData.width = 1;\n\t\t\t}else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn groupData;\n\t}\n\t\n\tcolumnVisCheck(column){\n\t\tvar visProp = column.definition[this.colVisProp];\n\t\t\n\t\tif(typeof visProp === \"function\"){\n\t\t\tvisProp = visProp.call(this.table, column.getComponent());\n\t\t}\n\t\t\n\t\treturn visProp !== false && (column.visible || (!column.visible && visProp));\n\t}\n\t\n\theadersToExportRows(columns){\n\t\tvar headers = [],\n\t\theaderDepth = 0,\n\t\texportRows = [];\n\t\t\n\t\tfunction parseColumnGroup(column, level){\n\t\t\t\n\t\t\tvar depth = headerDepth - level;\n\t\t\t\n\t\t\tif(typeof headers[level] === \"undefined\"){\n\t\t\t\theaders[level] = [];\n\t\t\t}\n\t\t\t\n\t\t\tcolumn.height = column.subGroups ? 1 : (depth - column.depth) + 1;\n\t\t\t\n\t\t\theaders[level].push(column);\n\t\t\t\n\t\t\tif(column.height > 1){\n\t\t\t\tfor(let i = 1; i < column.height; i ++){\n\t\t\t\t\t\n\t\t\t\t\tif(typeof headers[level + i] === \"undefined\"){\n\t\t\t\t\t\theaders[level + i] = [];\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\theaders[level + i].push(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(column.width > 1){\n\t\t\t\tfor(let i = 1; i < column.width; i ++){\n\t\t\t\t\theaders[level].push(false);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(column.subGroups){\n\t\t\t\tcolumn.subGroups.forEach(function(subGroup){\n\t\t\t\t\tparseColumnGroup(subGroup, level+1);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\t//calculate maximum header depth\n\t\tcolumns.forEach(function(column){\n\t\t\tif(column.depth > headerDepth){\n\t\t\t\theaderDepth = column.depth;\n\t\t\t}\n\t\t});\n\t\t\n\t\tcolumns.forEach(function(column){\n\t\t\tparseColumnGroup(column,0);\n\t\t});\n\t\t\n\t\theaders.forEach((header) => {\n\t\t\tvar columns = [];\n\t\t\t\n\t\t\theader.forEach((col) => {\n\t\t\t\tif(col){\n\t\t\t\t\tlet title = typeof col.title === \"undefined\" ? \"\" : col.title;\n\t\t\t\t\tcolumns.push(new ExportColumn(title, col.column.getComponent(), col.width, col.height, col.depth));\n\t\t\t\t}else {\n\t\t\t\t\tcolumns.push(null);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\texportRows.push(new ExportRow(\"header\", columns));\n\t\t});\n\t\t\n\t\treturn exportRows;\n\t}\n\t\n\tbodyToExportRows(rows, columns = []){\n\t\tvar exportRows = [];\n\t\t\n\t\tif (columns.length === 0) {\n\t\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\t\tif (this.columnVisCheck(column)) {\n\t\t\t\t\tcolumns.push(column.getComponent());\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tif(this.config.columnCalcs !== false && this.table.modExists(\"columnCalcs\")){\n\t\t\tif(this.table.modules.columnCalcs.topInitialized){\n\t\t\t\trows.unshift(this.table.modules.columnCalcs.topRow);\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.modules.columnCalcs.botInitialized){\n\t\t\t\trows.push(this.table.modules.columnCalcs.botRow);\n\t\t\t}\n\t\t}\n\n\t\trows = rows.filter((row) => {\n\t\t\tswitch(row.type){\n\t\t\t\tcase \"group\":\n\t\t\t\t\treturn this.config.rowGroups !== false;\n\t\t\t\t\n\t\t\t\tcase \"calc\":\n\t\t\t\t\treturn this.config.columnCalcs !== false;\n\t\t\t\t\n\t\t\t\tcase \"row\":\n\t\t\t\t\treturn !(this.table.options.dataTree && this.config.dataTree === false && row.modules.dataTree.parent);\n\t\t\t}\n\t\t\t\n\t\t\treturn true;\n\t\t});\n\t\t\n\t\trows.forEach((row, i) => {\n\t\t\tvar rowData = row.getData(this.colVisProp);\n\t\t\tvar exportCols = [];\n\t\t\tvar indent = 0;\n\t\t\t\n\t\t\tswitch(row.type){\n\t\t\t\tcase \"group\":\n\t\t\t\t\tindent = row.level;\n\t\t\t\t\texportCols.push(new ExportColumn(row.key, row.getComponent(), columns.length, 1));\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"calc\" :\n\t\t\t\tcase \"row\" :\n\t\t\t\t\tcolumns.forEach((col) => {\n\t\t\t\t\t\texportCols.push(new ExportColumn(col._column.getFieldValue(rowData), col, 1, 1));\n\t\t\t\t\t});\n\t\t\t\t\n\t\t\t\t\tif(this.table.options.dataTree && this.config.dataTree !== false){\n\t\t\t\t\t\tindent = row.modules.dataTree.index;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\texportRows.push(new ExportRow(row.type, exportCols, row.getComponent(), indent));\n\t\t});\n\t\t\n\t\treturn exportRows;\n\t}\n\t\n\tgenerateTableElement(list){\n\t\tvar table = document.createElement(\"table\"),\n\t\theaderEl = document.createElement(\"thead\"),\n\t\tbodyEl = document.createElement(\"tbody\"),\n\t\tstyles = this.lookupTableStyles(),\n\t\trowFormatter = this.table.options[\"rowFormatter\" + (this.colVisProp.charAt(0).toUpperCase() + this.colVisProp.slice(1))],\n\t\tsetup = {};\n\t\t\n\t\tsetup.rowFormatter = rowFormatter !== null ? rowFormatter : this.table.options.rowFormatter;\n\t\t\n\t\tif(this.table.options.dataTree &&this.config.dataTree !== false && this.table.modExists(\"columnCalcs\")){\n\t\t\tsetup.treeElementField = this.table.modules.dataTree.elementField;\n\t\t}\n\t\t\n\t\t//assign group header formatter\n\t\tsetup.groupHeader = this.table.options[\"groupHeader\" + (this.colVisProp.charAt(0).toUpperCase() + this.colVisProp.slice(1))];\n\t\t\n\t\tif(setup.groupHeader && !Array.isArray(setup.groupHeader)){\n\t\t\tsetup.groupHeader = [setup.groupHeader];\n\t\t}\n\t\t\n\t\ttable.classList.add(\"tabulator-print-table\");\n\t\t\n\t\tthis.mapElementStyles(this.table.columnManager.getHeadersElement(), headerEl, [\"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"background-color\", \"color\", \"font-weight\", \"font-family\", \"font-size\"]);\n\t\t\n\t\t\n\t\tif(list.length > 1000){\n\t\t\tconsole.warn(\"It may take a long time to render an HTML table with more than 1000 rows\");\n\t\t}\n\t\t\n\t\tlist.forEach((row, i) => {\n\t\t\tlet rowEl;\n\t\t\t\n\t\t\tswitch(row.type){\n\t\t\t\tcase \"header\":\n\t\t\t\t\theaderEl.appendChild(this.generateHeaderElement(row, setup, styles));\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"group\":\n\t\t\t\t\tbodyEl.appendChild(this.generateGroupElement(row, setup, styles));\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"calc\":\n\t\t\t\t\tbodyEl.appendChild(this.generateCalcElement(row, setup, styles));\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"row\":\n\t\t\t\t\trowEl = this.generateRowElement(row, setup, styles);\n\t\t\t\t\n\t\t\t\t\tthis.mapElementStyles(((i % 2) && styles.evenRow) ? styles.evenRow : styles.oddRow, rowEl, [\"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"color\", \"font-weight\", \"font-family\", \"font-size\", \"background-color\"]);\n\t\t\t\t\tbodyEl.appendChild(rowEl);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(headerEl.innerHTML){\n\t\t\ttable.appendChild(headerEl);\n\t\t}\n\t\t\n\t\ttable.appendChild(bodyEl);\n\t\t\n\t\t\n\t\tthis.mapElementStyles(this.table.element, table, [\"border-top\", \"border-left\", \"border-right\", \"border-bottom\"]);\n\t\treturn table;\n\t}\n\t\n\tlookupTableStyles(){\n\t\tvar styles = {};\n\t\t\n\t\t//lookup row styles\n\t\tif(this.cloneTableStyle && window.getComputedStyle){\n\t\t\tstyles.oddRow = this.table.element.querySelector(\".tabulator-row-odd:not(.tabulator-group):not(.tabulator-calcs)\");\n\t\t\tstyles.evenRow = this.table.element.querySelector(\".tabulator-row-even:not(.tabulator-group):not(.tabulator-calcs)\");\n\t\t\tstyles.calcRow = this.table.element.querySelector(\".tabulator-row.tabulator-calcs\");\n\t\t\tstyles.firstRow = this.table.element.querySelector(\".tabulator-row:not(.tabulator-group):not(.tabulator-calcs)\");\n\t\t\tstyles.firstGroup = this.table.element.getElementsByClassName(\"tabulator-group\")[0];\n\t\t\t\n\t\t\tif(styles.firstRow){\n\t\t\t\tstyles.styleCells = styles.firstRow.getElementsByClassName(\"tabulator-cell\");\n\t\t\t\tstyles.firstCell = styles.styleCells[0];\n\t\t\t\tstyles.lastCell = styles.styleCells[styles.styleCells.length - 1];\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn styles;\n\t}\n\t\n\tgenerateHeaderElement(row, setup, styles){\n\t\tvar rowEl = document.createElement(\"tr\");\n\t\t\n\t\trow.columns.forEach((column) => {\n\t\t\tif(column){\n\t\t\t\tvar cellEl = document.createElement(\"th\");\n\t\t\t\tvar classNames = column.component._column.definition.cssClass ? column.component._column.definition.cssClass.split(\" \") : [];\n\t\t\t\t\n\t\t\t\tcellEl.colSpan = column.width;\n\t\t\t\tcellEl.rowSpan = column.height;\n\t\t\t\t\n\t\t\t\tcellEl.innerHTML = column.value;\n\t\t\t\t\n\t\t\t\tif(this.cloneTableStyle){\n\t\t\t\t\tcellEl.style.boxSizing = \"border-box\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tclassNames.forEach(function(className) {\n\t\t\t\t\tcellEl.classList.add(className);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.mapElementStyles(column.component.getElement(), cellEl, [\"text-align\", \"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"background-color\", \"color\", \"font-weight\", \"font-family\", \"font-size\"]);\n\t\t\t\tthis.mapElementStyles(column.component._column.contentElement, cellEl, [\"padding-top\", \"padding-left\", \"padding-right\", \"padding-bottom\"]);\n\t\t\t\t\n\t\t\t\tif(column.component._column.visible){\n\t\t\t\t\tthis.mapElementStyles(column.component.getElement(), cellEl, [\"width\"]);\n\t\t\t\t}else {\n\t\t\t\t\tif(column.component._column.definition.width){\n\t\t\t\t\t\tcellEl.style.width = column.component._column.definition.width + \"px\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(column.component._column.parent){\n\t\t\t\t\tthis.mapElementStyles(column.component._column.parent.groupElement, cellEl, [\"border-top\"]);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\trowEl.appendChild(cellEl);\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn rowEl;\n\t}\n\t\n\tgenerateGroupElement(row, setup, styles){\n\t\t\n\t\tvar rowEl = document.createElement(\"tr\"),\n\t\tcellEl = document.createElement(\"td\"),\n\t\tgroup = row.columns[0];\n\t\t\n\t\trowEl.classList.add(\"tabulator-print-table-row\");\n\t\t\n\t\tif(setup.groupHeader && setup.groupHeader[row.indent]){\n\t\t\tgroup.value = setup.groupHeader[row.indent](group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);\n\t\t}else {\n\t\t\tif(setup.groupHeader !== false){\n\t\t\t\tgroup.value = row.component._group.generator(group.value, row.component._group.getRowCount(), row.component._group.getData(), row.component);\n\t\t\t}\n\t\t}\n\t\t\n\t\tcellEl.colSpan = group.width;\n\t\tcellEl.innerHTML = group.value;\n\t\t\n\t\trowEl.classList.add(\"tabulator-print-table-group\");\n\t\trowEl.classList.add(\"tabulator-group-level-\" + row.indent);\n\t\t\n\t\tif(group.component.isVisible()){\n\t\t\trowEl.classList.add(\"tabulator-group-visible\");\n\t\t}\n\t\t\n\t\tthis.mapElementStyles(styles.firstGroup, rowEl, [\"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"color\", \"font-weight\", \"font-family\", \"font-size\", \"background-color\"]);\n\t\tthis.mapElementStyles(styles.firstGroup, cellEl, [\"padding-top\", \"padding-left\", \"padding-right\", \"padding-bottom\"]);\n\t\t\n\t\trowEl.appendChild(cellEl);\n\t\t\n\t\treturn rowEl;\n\t}\n\t\n\tgenerateCalcElement(row, setup, styles){\n\t\tvar rowEl = this.generateRowElement(row, setup, styles);\n\t\t\n\t\trowEl.classList.add(\"tabulator-print-table-calcs\");\n\t\tthis.mapElementStyles(styles.calcRow, rowEl, [\"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"color\", \"font-weight\", \"font-family\", \"font-size\", \"background-color\"]);\n\t\t\n\t\treturn rowEl;\n\t}\n\t\n\tgenerateRowElement(row, setup, styles){\n\t\tvar rowEl = document.createElement(\"tr\");\n\t\t\n\t\trowEl.classList.add(\"tabulator-print-table-row\");\n\t\t\n\t\trow.columns.forEach((col, i) => {\n\t\t\tif(col){\n\t\t\t\tvar cellEl = document.createElement(\"td\"),\n\t\t\t\tcolumn = col.component._column,\n\t\t\t\ttable =  this.table,\n\t\t\t\tindex = table.columnManager.findColumnIndex(column),\n\t\t\t\tvalue = col.value,\n\t\t\t\tcellStyle;\n\t\t\t\t\n\t\t\t\tvar cellWrapper = {\n\t\t\t\t\tmodules:{},\n\t\t\t\t\tgetValue:function(){\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t},\n\t\t\t\t\tgetField:function(){\n\t\t\t\t\t\treturn column.definition.field;\n\t\t\t\t\t},\n\t\t\t\t\tgetElement:function(){\n\t\t\t\t\t\treturn cellEl;\n\t\t\t\t\t},\n\t\t\t\t\tgetType:function(){\n\t\t\t\t\t\treturn \"cell\";\n\t\t\t\t\t},\n\t\t\t\t\tgetColumn:function(){\n\t\t\t\t\t\treturn column.getComponent();\n\t\t\t\t\t},\n\t\t\t\t\tgetData:function(){\n\t\t\t\t\t\treturn row.component.getData();\n\t\t\t\t\t},\n\t\t\t\t\tgetRow:function(){\n\t\t\t\t\t\treturn row.component;\n\t\t\t\t\t},\n\t\t\t\t\tgetTable:function(){\n\t\t\t\t\t\treturn table;\n\t\t\t\t\t},\n\t\t\t\t\tgetComponent:function(){\n\t\t\t\t\t\treturn cellWrapper;\n\t\t\t\t\t},\n\t\t\t\t\tcolumn:column,\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tvar classNames = column.definition.cssClass ? column.definition.cssClass.split(\" \") : [];\n\t\t\t\t\n\t\t\t\tclassNames.forEach(function(className) {\n\t\t\t\t\tcellEl.classList.add(className);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif(this.table.modExists(\"format\") && this.config.formatCells !== false){\n\t\t\t\t\tvalue = this.table.modules.format.formatExportValue(cellWrapper, this.colVisProp);\n\t\t\t\t}else {\n\t\t\t\t\tswitch(typeof value){\n\t\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\t\tvalue = value !== null ? JSON.stringify(value) : \"\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(value instanceof Node){\n\t\t\t\t\tcellEl.appendChild(value);\n\t\t\t\t}else {\n\t\t\t\t\tcellEl.innerHTML = value;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcellStyle = styles.styleCells && styles.styleCells[index] ? styles.styleCells[index] : styles.firstCell;\n\t\t\t\t\n\t\t\t\tif(cellStyle){\n\t\t\t\t\tthis.mapElementStyles(cellStyle, cellEl, [\"padding-top\", \"padding-left\", \"padding-right\", \"padding-bottom\", \"border-top\", \"border-left\", \"border-right\", \"border-bottom\", \"color\", \"font-weight\", \"font-family\", \"font-size\", \"text-align\"]);\n\t\t\t\t\t\n\t\t\t\t\tif(column.definition.align){\n\t\t\t\t\t\tcellEl.style.textAlign = column.definition.align;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.table.options.dataTree && this.config.dataTree !== false){\n\t\t\t\t\tif((setup.treeElementField && setup.treeElementField == column.field) || (!setup.treeElementField && i == 0)){\n\t\t\t\t\t\tif(row.component._row.modules.dataTree.controlEl){\n\t\t\t\t\t\t\tcellEl.insertBefore(row.component._row.modules.dataTree.controlEl.cloneNode(true), cellEl.firstChild);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(row.component._row.modules.dataTree.branchEl){\n\t\t\t\t\t\t\tcellEl.insertBefore(row.component._row.modules.dataTree.branchEl.cloneNode(true), cellEl.firstChild);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\trowEl.appendChild(cellEl);\n\t\t\t\t\n\t\t\t\tif(cellWrapper.modules.format && cellWrapper.modules.format.renderedCallback){\n\t\t\t\t\tcellWrapper.modules.format.renderedCallback();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(setup.rowFormatter && row.type === \"row\" && this.config.formatCells !== false){\n\t\t\tlet formatComponent = Object.assign(row.component);\n\n\t\t\tformatComponent.getElement = function(){return rowEl;};\n\n\t\t\tsetup.rowFormatter(row.component);\n\t\t}\n\t\t\n\t\treturn rowEl;\n\t}\n\t\n\tgenerateHTMLTable(list){\n\t\tvar holder = document.createElement(\"div\");\n\t\t\n\t\tholder.appendChild(this.generateTableElement(list));\n\t\t\n\t\treturn holder.innerHTML;\n\t}\n\t\n\tgetHtml(visible, style, config, colVisProp){\n\t\tvar list = this.generateExportList(config || this.table.options.htmlOutputConfig, style, visible, colVisProp || \"htmlOutput\");\n\t\t\n\t\treturn this.generateHTMLTable(list);\n\t}\n\t\n\tmapElementStyles(from, to, props){\n\t\tif(this.cloneTableStyle && from && to){\n\t\t\t\n\t\t\tvar lookup = {\n\t\t\t\t\"background-color\" : \"backgroundColor\",\n\t\t\t\t\"color\" : \"fontColor\",\n\t\t\t\t\"width\" : \"width\",\n\t\t\t\t\"font-weight\" : \"fontWeight\",\n\t\t\t\t\"font-family\" : \"fontFamily\",\n\t\t\t\t\"font-size\" : \"fontSize\",\n\t\t\t\t\"text-align\" : \"textAlign\",\n\t\t\t\t\"border-top\" : \"borderTop\",\n\t\t\t\t\"border-left\" : \"borderLeft\",\n\t\t\t\t\"border-right\" : \"borderRight\",\n\t\t\t\t\"border-bottom\" : \"borderBottom\",\n\t\t\t\t\"padding-top\" : \"paddingTop\",\n\t\t\t\t\"padding-left\" : \"paddingLeft\",\n\t\t\t\t\"padding-right\" : \"paddingRight\",\n\t\t\t\t\"padding-bottom\" : \"paddingBottom\",\n\t\t\t};\n\t\t\t\n\t\t\tif(window.getComputedStyle){\n\t\t\t\tvar fromStyle = window.getComputedStyle(from);\n\t\t\t\t\n\t\t\t\tprops.forEach(function(prop){\n\t\t\t\t\tif(!to.style[lookup[prop]]){\n\t\t\t\t\t\tto.style[lookup[prop]] = fromStyle.getPropertyValue(prop);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\nExport.moduleName = \"export\";\n\nvar defaultFilters = {\n\n\t//equal to\n\t\"=\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal == filterVal ? true : false;\n\t},\n\n\t//less than\n\t\"<\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal < filterVal ? true : false;\n\t},\n\n\t//less than or equal to\n\t\"<=\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal <= filterVal ? true : false;\n\t},\n\n\t//greater than\n\t\">\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal > filterVal ? true : false;\n\t},\n\n\t//greater than or equal to\n\t\">=\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal >= filterVal ? true : false;\n\t},\n\n\t//not equal to\n\t\"!=\":function(filterVal, rowVal, rowData, filterParams){\n\t\treturn rowVal != filterVal ? true : false;\n\t},\n\n\t\"regex\":function(filterVal, rowVal, rowData, filterParams){\n\n\t\tif(typeof filterVal == \"string\"){\n\t\t\tfilterVal = new RegExp(filterVal);\n\t\t}\n\n\t\treturn filterVal.test(rowVal);\n\t},\n\n\t//contains the string\n\t\"like\":function(filterVal, rowVal, rowData, filterParams){\n\t\tif(filterVal === null || typeof filterVal === \"undefined\"){\n\t\t\treturn rowVal === filterVal ? true : false;\n\t\t}else {\n\t\t\tif(typeof rowVal !== 'undefined' && rowVal !== null){\n\t\t\t\treturn String(rowVal).toLowerCase().indexOf(filterVal.toLowerCase()) > -1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t},\n\n\t//contains the keywords\n\t\"keywords\":function(filterVal, rowVal, rowData, filterParams){\n\t\tvar keywords = filterVal.toLowerCase().split(typeof filterParams.separator === \"undefined\" ? \" \" : filterParams.separator),\n\t\tvalue = String(rowVal === null || typeof rowVal === \"undefined\" ? \"\" : rowVal).toLowerCase(),\n\t\tmatches = [];\n\n\t\tkeywords.forEach((keyword) =>{\n\t\t\tif(value.includes(keyword)){\n\t\t\t\tmatches.push(true);\n\t\t\t}\n\t\t});\n\n\t\treturn filterParams.matchAll ? matches.length === keywords.length : !!matches.length;\n\t},\n\n\t//starts with the string\n\t\"starts\":function(filterVal, rowVal, rowData, filterParams){\n\t\tif(filterVal === null || typeof filterVal === \"undefined\"){\n\t\t\treturn rowVal === filterVal ? true : false;\n\t\t}else {\n\t\t\tif(typeof rowVal !== 'undefined' && rowVal !== null){\n\t\t\t\treturn String(rowVal).toLowerCase().startsWith(filterVal.toLowerCase());\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t},\n\n\t//ends with the string\n\t\"ends\":function(filterVal, rowVal, rowData, filterParams){\n\t\tif(filterVal === null || typeof filterVal === \"undefined\"){\n\t\t\treturn rowVal === filterVal ? true : false;\n\t\t}else {\n\t\t\tif(typeof rowVal !== 'undefined' && rowVal !== null){\n\t\t\t\treturn String(rowVal).toLowerCase().endsWith(filterVal.toLowerCase());\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t},\n\n\t//in array\n\t\"in\":function(filterVal, rowVal, rowData, filterParams){\n\t\tif(Array.isArray(filterVal)){\n\t\t\treturn filterVal.length ? filterVal.indexOf(rowVal) > -1 : true;\n\t\t}else {\n\t\t\tconsole.warn(\"Filter Error - filter value is not an array:\", filterVal);\n\t\t\treturn false;\n\t\t}\n\t},\n};\n\nclass Filter extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.filterList = []; //hold filter list\n\t\tthis.headerFilters = {}; //hold column filters\n\t\tthis.headerFilterColumns = []; //hold columns that use header filters\n\n\t\tthis.prevHeaderFilterChangeCheck = \"\";\n\t\tthis.prevHeaderFilterChangeCheck = \"{}\";\n\n\t\tthis.changed = false; //has filtering changed since last render\n\t\tthis.tableInitialized = false;\n\n\t\tthis.registerTableOption(\"filterMode\", \"local\"); //local or remote filtering\n\n\t\tthis.registerTableOption(\"initialFilter\", false); //initial filtering criteria\n\t\tthis.registerTableOption(\"initialHeaderFilter\", false); //initial header filtering criteria\n\t\tthis.registerTableOption(\"headerFilterLiveFilterDelay\", 300); //delay before updating column after user types in header filter\n\t\tthis.registerTableOption(\"placeholderHeaderFilter\", false); //placeholder when header filter is empty\n\n\t\tthis.registerColumnOption(\"headerFilter\");\n\t\tthis.registerColumnOption(\"headerFilterPlaceholder\");\n\t\tthis.registerColumnOption(\"headerFilterParams\");\n\t\tthis.registerColumnOption(\"headerFilterEmptyCheck\");\n\t\tthis.registerColumnOption(\"headerFilterFunc\");\n\t\tthis.registerColumnOption(\"headerFilterFuncParams\");\n\t\tthis.registerColumnOption(\"headerFilterLiveFilter\");\n\n\t\tthis.registerTableFunction(\"searchRows\", this.searchRows.bind(this));\n\t\tthis.registerTableFunction(\"searchData\", this.searchData.bind(this));\n\n\t\tthis.registerTableFunction(\"setFilter\", this.userSetFilter.bind(this));\n\t\tthis.registerTableFunction(\"refreshFilter\", this.userRefreshFilter.bind(this));\n\t\tthis.registerTableFunction(\"addFilter\", this.userAddFilter.bind(this));\n\t\tthis.registerTableFunction(\"getFilters\", this.getFilters.bind(this));\n\t\tthis.registerTableFunction(\"setHeaderFilterFocus\", this.userSetHeaderFilterFocus.bind(this));\n\t\tthis.registerTableFunction(\"getHeaderFilterValue\", this.userGetHeaderFilterValue.bind(this));\n\t\tthis.registerTableFunction(\"setHeaderFilterValue\", this.userSetHeaderFilterValue.bind(this));\n\t\tthis.registerTableFunction(\"getHeaderFilters\", this.getHeaderFilters.bind(this));\n\t\tthis.registerTableFunction(\"removeFilter\", this.userRemoveFilter.bind(this));\n\t\tthis.registerTableFunction(\"clearFilter\", this.userClearFilter.bind(this));\n\t\tthis.registerTableFunction(\"clearHeaderFilter\", this.userClearHeaderFilter.bind(this));\n\n\t\tthis.registerComponentFunction(\"column\", \"headerFilterFocus\", this.setHeaderFilterFocus.bind(this));\n\t\tthis.registerComponentFunction(\"column\", \"reloadHeaderFilter\", this.reloadHeaderFilter.bind(this));\n\t\tthis.registerComponentFunction(\"column\", \"getHeaderFilterValue\", this.getHeaderFilterValue.bind(this));\n\t\tthis.registerComponentFunction(\"column\", \"setHeaderFilterValue\", this.setHeaderFilterValue.bind(this));\n\t}\n\n\tinitialize(){\n\t\tthis.subscribe(\"column-init\", this.initializeColumnHeaderFilter.bind(this));\n\t\tthis.subscribe(\"column-width-fit-before\", this.hideHeaderFilterElements.bind(this));\n\t\tthis.subscribe(\"column-width-fit-after\", this.showHeaderFilterElements.bind(this));\n\t\tthis.subscribe(\"table-built\", this.tableBuilt.bind(this));\n\t\tthis.subscribe(\"placeholder\", this.generatePlaceholder.bind(this));\n\n\t\tif(this.table.options.filterMode === \"remote\"){\n\t\t\tthis.subscribe(\"data-params\", this.remoteFilterParams.bind(this));\n\t\t}\n\n\t\tthis.registerDataHandler(this.filter.bind(this), 10);\n\t}\n\n\ttableBuilt(){\n\t\tif(this.table.options.initialFilter){\n\t\t\tthis.setFilter(this.table.options.initialFilter);\n\t\t}\n\n\t\tif(this.table.options.initialHeaderFilter){\n\t\t\tthis.table.options.initialHeaderFilter.forEach((item) => {\n\n\t\t\t\tvar column = this.table.columnManager.findColumn(item.field);\n\n\t\t\t\tif(column){\n\t\t\t\t\tthis.setHeaderFilterValue(column, item.value);\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Column Filter Error - No matching column found:\", item.field);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis.tableInitialized = true;\n\t}\n\n\tremoteFilterParams(data, config, silent, params){\n\t\tparams.filter = this.getFilters(true, true);\n\t\treturn params;\n\t}\n\n\tgeneratePlaceholder(text){\n\t\tif(this.table.options.placeholderHeaderFilter && Object.keys(this.headerFilters).length){\n\t\t\treturn this.table.options.placeholderHeaderFilter;\n\t\t}\n\t}\n\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\n\t//set standard filters\n\tuserSetFilter(field, type, value, params){\n\t\tthis.setFilter(field, type, value, params);\n\t\tthis.refreshFilter();\n\t}\n\n\t//set standard filters\n\tuserRefreshFilter(){\n\t\tthis.refreshFilter();\n\t}\n\n\t//add filter to array\n\tuserAddFilter(field, type, value, params){\n\t\tthis.addFilter(field, type, value, params);\n\t\tthis.refreshFilter();\n\t}\n\n\tuserSetHeaderFilterFocus(field){\n\t\tvar column = this.table.columnManager.findColumn(field);\n\n\t\tif(column){\n\t\t\tthis.setHeaderFilterFocus(column);\n\t\t}else {\n\t\t\tconsole.warn(\"Column Filter Focus Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tuserGetHeaderFilterValue(field) {\n\t\tvar column = this.table.columnManager.findColumn(field);\n\n\t\tif(column){\n\t\t\treturn this.getHeaderFilterValue(column);\n\t\t}else {\n\t\t\tconsole.warn(\"Column Filter Error - No matching column found:\", field);\n\t\t}\n\t}\n\n\tuserSetHeaderFilterValue(field, value){\n\t\tvar column = this.table.columnManager.findColumn(field);\n\n\t\tif(column){\n\t\t\tthis.setHeaderFilterValue(column, value);\n\t\t}else {\n\t\t\tconsole.warn(\"Column Filter Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//remove filter from array\n\tuserRemoveFilter(field, type, value){\n\t\tthis.removeFilter(field, type, value);\n\t\tthis.refreshFilter();\n\t}\n\n\t//clear filters\n\tuserClearFilter(all){\n\t\tthis.clearFilter(all);\n\t\tthis.refreshFilter();\n\t}\n\n\t//clear header filters\n\tuserClearHeaderFilter(){\n\t\tthis.clearHeaderFilter();\n\t\tthis.refreshFilter();\n\t}\n\n\n\t//search for specific row components\n\tsearchRows(field, type, value){\n\t\treturn this.search(\"rows\", field, type, value);\n\t}\n\n\t//search for specific data\n\tsearchData(field, type, value){\n\t\treturn this.search(\"data\", field, type, value);\n\t}\n\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\n\tinitializeColumnHeaderFilter(column){\n\t\tvar def = column.definition;\n\n\t\tif(def.headerFilter){\n\t\t\tthis.initializeColumn(column);\n\t\t}\n\t}\n\n\t//initialize column header filter\n\tinitializeColumn(column, value){\n\t\tvar self = this,\n\t\tfield = column.getField();\n\n\t\t//handle successfully value change\n\t\tfunction success(value){\n\t\t\tvar filterType = (column.modules.filter.tagType == \"input\" && column.modules.filter.attrType == \"text\") || column.modules.filter.tagType == \"textarea\" ? \"partial\" : \"match\",\n\t\t\ttype = \"\",\n\t\t\tfilterChangeCheck = \"\",\n\t\t\tfilterFunc;\n\n\t\t\tif(typeof column.modules.filter.prevSuccess === \"undefined\" || column.modules.filter.prevSuccess !== value){\n\n\t\t\t\tcolumn.modules.filter.prevSuccess = value;\n\n\t\t\t\tif(!column.modules.filter.emptyFunc(value)){\n\t\t\t\t\tcolumn.modules.filter.value = value;\n\n\t\t\t\t\tswitch(typeof column.definition.headerFilterFunc){\n\t\t\t\t\t\tcase \"string\":\n\t\t\t\t\t\t\tif(Filter.filters[column.definition.headerFilterFunc]){\n\t\t\t\t\t\t\t\ttype = column.definition.headerFilterFunc;\n\t\t\t\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\t\t\t\tvar params = column.definition.headerFilterFuncParams || {};\n\t\t\t\t\t\t\t\t\tvar fieldVal = column.getFieldValue(data);\n\n\t\t\t\t\t\t\t\t\tparams = typeof params === \"function\" ? params(value, fieldVal, data) : params;\n\n\t\t\t\t\t\t\t\t\treturn Filter.filters[column.definition.headerFilterFunc](value, fieldVal, data, params);\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tconsole.warn(\"Header Filter Error - Matching filter function not found: \", column.definition.headerFilterFunc);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase \"function\":\n\t\t\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\t\t\tvar params = column.definition.headerFilterFuncParams || {};\n\t\t\t\t\t\t\t\tvar fieldVal = column.getFieldValue(data);\n\n\t\t\t\t\t\t\t\tparams = typeof params === \"function\" ? params(value, fieldVal, data) : params;\n\n\t\t\t\t\t\t\t\treturn column.definition.headerFilterFunc(value, fieldVal, data, params);\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\ttype = filterFunc;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!filterFunc){\n\t\t\t\t\t\tswitch(filterType){\n\t\t\t\t\t\t\tcase \"partial\":\n\t\t\t\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\t\t\t\tvar colVal = column.getFieldValue(data);\n\n\t\t\t\t\t\t\t\t\tif(typeof colVal !== 'undefined' && colVal !== null){\n\t\t\t\t\t\t\t\t\t\treturn String(colVal).toLowerCase().indexOf(String(value).toLowerCase()) > -1;\n\t\t\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\ttype = \"like\";\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\t\t\t\treturn column.getFieldValue(data) == value;\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\ttype = \"=\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tself.headerFilters[field] = {value:value, func:filterFunc, type:type};\n\t\t\t\t}else {\n\t\t\t\t\tdelete self.headerFilters[field];\n\t\t\t\t}\n\n\t\t\t\tcolumn.modules.filter.value = value;\n\n\t\t\t\tfilterChangeCheck = JSON.stringify(self.headerFilters);\n\n\t\t\t\tif(self.prevHeaderFilterChangeCheck !== filterChangeCheck){\n\t\t\t\t\tself.prevHeaderFilterChangeCheck = filterChangeCheck;\n\n\t\t\t\t\tself.trackChanges();\n\t\t\t\t\tself.refreshFilter();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tcolumn.modules.filter = {\n\t\t\tsuccess:success,\n\t\t\tattrType:false,\n\t\t\ttagType:false,\n\t\t\temptyFunc:false,\n\t\t};\n\n\t\tthis.generateHeaderFilterElement(column);\n\t}\n\n\tgenerateHeaderFilterElement(column, initialValue, reinitialize){\n\t\tvar self = this,\n\t\tsuccess = column.modules.filter.success,\n\t\tfield = column.getField(),\n\t\tfilterElement, editor, editorElement, cellWrapper, typingTimer, searchTrigger, params, onRenderedCallback;\n\n\t\tcolumn.modules.filter.value = initialValue;\n\n\t\t//handle aborted edit\n\t\tfunction cancel(){}\n\n\t\tfunction onRendered(callback){\n\t\t\tonRenderedCallback = callback;\n\t\t}\n\n\t\tif(column.modules.filter.headerElement && column.modules.filter.headerElement.parentNode){\n\t\t\tcolumn.contentElement.removeChild(column.modules.filter.headerElement.parentNode);\n\t\t}\n\n\t\tif(field){\n\n\t\t\t//set empty value function\n\t\t\tcolumn.modules.filter.emptyFunc = column.definition.headerFilterEmptyCheck || function(value){\n\t\t\t\treturn !value && value !== 0;\n\t\t\t};\n\n\t\t\tfilterElement = document.createElement(\"div\");\n\t\t\tfilterElement.classList.add(\"tabulator-header-filter\");\n\n\t\t\t//set column editor\n\t\t\tswitch(typeof column.definition.headerFilter){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tif(self.table.modules.edit.editors[column.definition.headerFilter]){\n\t\t\t\t\t\teditor = self.table.modules.edit.editors[column.definition.headerFilter];\n\n\t\t\t\t\t\tif((column.definition.headerFilter === \"tick\" || column.definition.headerFilter === \"tickCross\") && !column.definition.headerFilterEmptyCheck){\n\t\t\t\t\t\t\tcolumn.modules.filter.emptyFunc = function(value){\n\t\t\t\t\t\t\t\treturn value !== true && value !== false;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Filter Error - Cannot build header filter, No such editor found: \", column.definition.editor);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"function\":\n\t\t\t\t\teditor = column.definition.headerFilter;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"boolean\":\n\t\t\t\t\tif(column.modules.edit && column.modules.edit.editor){\n\t\t\t\t\t\teditor = column.modules.edit.editor;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(column.definition.formatter && self.table.modules.edit.editors[column.definition.formatter]){\n\t\t\t\t\t\t\teditor = self.table.modules.edit.editors[column.definition.formatter];\n\n\t\t\t\t\t\t\tif((column.definition.formatter === \"tick\" || column.definition.formatter === \"tickCross\") && !column.definition.headerFilterEmptyCheck){\n\t\t\t\t\t\t\t\tcolumn.modules.filter.emptyFunc = function(value){\n\t\t\t\t\t\t\t\t\treturn value !== true && value !== false;\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\teditor = self.table.modules.edit.editors[\"input\"];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(editor){\n\n\t\t\t\tcellWrapper = {\n\t\t\t\t\tgetValue:function(){\n\t\t\t\t\t\treturn typeof initialValue !== \"undefined\" ? initialValue : \"\";\n\t\t\t\t\t},\n\t\t\t\t\tgetField:function(){\n\t\t\t\t\t\treturn column.definition.field;\n\t\t\t\t\t},\n\t\t\t\t\tgetElement:function(){\n\t\t\t\t\t\treturn filterElement;\n\t\t\t\t\t},\n\t\t\t\t\tgetColumn:function(){\n\t\t\t\t\t\treturn column.getComponent();\n\t\t\t\t\t},\n\t\t\t\t\tgetTable:() => {\n\t\t\t\t\t\treturn this.table;\n\t\t\t\t\t},\n\t\t\t\t\tgetType:() => {\n\t\t\t\t\t\treturn \"header\";\n\t\t\t\t\t},\n\t\t\t\t\tgetRow:function(){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnormalizeHeight:function(){\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tparams = column.definition.headerFilterParams || {};\n\n\t\t\t\tparams = typeof params === \"function\" ? params.call(self.table, cellWrapper) : params;\n\n\t\t\t\teditorElement = editor.call(this.table.modules.edit, cellWrapper, onRendered, success, cancel, params);\n\n\t\t\t\tif(!editorElement){\n\t\t\t\t\tconsole.warn(\"Filter Error - Cannot add filter to \" + field + \" column, editor returned a value of false\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif(!(editorElement instanceof Node)){\n\t\t\t\t\tconsole.warn(\"Filter Error - Cannot add filter to \" + field + \" column, editor should return an instance of Node, the editor returned:\", editorElement);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t//set Placeholder Text\n\t\t\t\tself.langBind(\"headerFilters|columns|\" + column.definition.field, function(value){\n\t\t\t\t\teditorElement.setAttribute(\"placeholder\", typeof value !== \"undefined\" && value ? value : (column.definition.headerFilterPlaceholder || self.langText(\"headerFilters|default\")));\n\t\t\t\t});\n\n\t\t\t\t//focus on element on click\n\t\t\t\teditorElement.addEventListener(\"click\", function(e){\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\teditorElement.focus();\n\t\t\t\t});\n\n\t\t\t\teditorElement.addEventListener(\"focus\", (e) => {\n\t\t\t\t\tvar left = this.table.columnManager.contentsElement.scrollLeft;\n\n\t\t\t\t\tvar headerPos = this.table.rowManager.element.scrollLeft;\n\n\t\t\t\t\tif(left !== headerPos){\n\t\t\t\t\t\tthis.table.rowManager.scrollHorizontal(left);\n\t\t\t\t\t\tthis.table.columnManager.scrollHorizontal(left);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t//live update filters as user types\n\t\t\t\ttypingTimer = false;\n\n\t\t\t\tsearchTrigger = function(e){\n\t\t\t\t\tif(typingTimer){\n\t\t\t\t\t\tclearTimeout(typingTimer);\n\t\t\t\t\t}\n\n\t\t\t\t\ttypingTimer = setTimeout(function(){\n\t\t\t\t\t\tsuccess(editorElement.value);\n\t\t\t\t\t},self.table.options.headerFilterLiveFilterDelay);\n\t\t\t\t};\n\n\t\t\t\tcolumn.modules.filter.headerElement = editorElement;\n\t\t\t\tcolumn.modules.filter.attrType = editorElement.hasAttribute(\"type\") ? editorElement.getAttribute(\"type\").toLowerCase() : \"\" ;\n\t\t\t\tcolumn.modules.filter.tagType = editorElement.tagName.toLowerCase();\n\n\t\t\t\tif(column.definition.headerFilterLiveFilter !== false){\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\tcolumn.definition.headerFilter === 'autocomplete' ||\n\t\t\t\t\t\t\tcolumn.definition.headerFilter === 'tickCross' ||\n\t\t\t\t\t\t\t((column.definition.editor === 'autocomplete' ||\n\t\t\t\t\t\t\t\tcolumn.definition.editor === 'tickCross') &&\n\t\t\t\t\t\t\tcolumn.definition.headerFilter === true)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\teditorElement.addEventListener(\"keyup\", searchTrigger);\n\t\t\t\t\t\teditorElement.addEventListener(\"search\", searchTrigger);\n\n\n\t\t\t\t\t\t//update number filtered columns on change\n\t\t\t\t\t\tif(column.modules.filter.attrType == \"number\"){\n\t\t\t\t\t\t\teditorElement.addEventListener(\"change\", function(e){\n\t\t\t\t\t\t\t\tsuccess(editorElement.value);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//change text inputs to search inputs to allow for clearing of field\n\t\t\t\t\t\tif(column.modules.filter.attrType == \"text\" && this.table.browser !== \"ie\"){\n\t\t\t\t\t\t\teditorElement.setAttribute(\"type\", \"search\");\n\t\t\t\t\t\t// editorElement.off(\"change blur\"); //prevent blur from triggering filter and preventing selection click\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\t//prevent input and select elements from propagating click to column sorters etc\n\t\t\t\t\tif(column.modules.filter.tagType == \"input\" || column.modules.filter.tagType == \"select\" || column.modules.filter.tagType == \"textarea\"){\n\t\t\t\t\t\teditorElement.addEventListener(\"mousedown\",function(e){\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfilterElement.appendChild(editorElement);\n\n\t\t\t\tcolumn.contentElement.appendChild(filterElement);\n\n\t\t\t\tif(!reinitialize){\n\t\t\t\t\tself.headerFilterColumns.push(column);\n\t\t\t\t}\n\n\t\t\t\tif(onRenderedCallback){\n\t\t\t\t\tonRenderedCallback();\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.warn(\"Filter Error - Cannot add header filter, column has no field set:\", column.definition.title);\n\t\t}\n\t}\n\n\t//hide all header filter elements (used to ensure correct column widths in \"fitData\" layout mode)\n\thideHeaderFilterElements(){\n\t\tthis.headerFilterColumns.forEach(function(column){\n\t\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\t\tcolumn.modules.filter.headerElement.style.display = 'none';\n\t\t\t}\n\t\t});\n\t}\n\n\t//show all header filter elements (used to ensure correct column widths in \"fitData\" layout mode)\n\tshowHeaderFilterElements(){\n\t\tthis.headerFilterColumns.forEach(function(column){\n\t\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\t\tcolumn.modules.filter.headerElement.style.display = '';\n\t\t\t}\n\t\t});\n\t}\n\n\t//programmatically set focus of header filter\n\tsetHeaderFilterFocus(column){\n\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\tcolumn.modules.filter.headerElement.focus();\n\t\t}else {\n\t\t\tconsole.warn(\"Column Filter Focus Error - No header filter set on column:\", column.getField());\n\t\t}\n\t}\n\n\t//programmatically get value of header filter\n\tgetHeaderFilterValue(column){\n\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\treturn column.modules.filter.value;\n\t\t} else {\n\t\t\tconsole.warn(\"Column Filter Error - No header filter set on column:\", column.getField());\n\t\t}\n\t}\n\n\t//programmatically set value of header filter\n\tsetHeaderFilterValue(column, value){\n\t\tif (column){\n\t\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\t\tthis.generateHeaderFilterElement(column, value, true);\n\t\t\t\tcolumn.modules.filter.success(value);\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Column Filter Error - No header filter set on column:\", column.getField());\n\t\t\t}\n\t\t}\n\t}\n\n\treloadHeaderFilter(column){\n\t\tif (column){\n\t\t\tif(column.modules.filter && column.modules.filter.headerElement){\n\t\t\t\tthis.generateHeaderFilterElement(column, column.modules.filter.value, true);\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Column Filter Error - No header filter set on column:\", column.getField());\n\t\t\t}\n\t\t}\n\t}\n\n\trefreshFilter(){\n\t\tif(this.tableInitialized){\n\t\t\tif(this.table.options.filterMode === \"remote\"){\n\t\t\t\tthis.reloadData(null, false, false);\n\t\t\t}else {\n\t\t\t\tthis.refreshData(true);\n\t\t\t}\n\t\t}\n\n\t\t//TODO - Persist left position of row manager\n\t\t// left = this.scrollLeft;\n\t\t// this.scrollHorizontal(left);\n\t}\n\n\t//check if the filters has changed since last use\n\ttrackChanges(){\n\t\tthis.changed = true;\n\t\tthis.dispatch(\"filter-changed\");\n\t}\n\n\t//check if the filters has changed since last use\n\thasChanged(){\n\t\tvar changed = this.changed;\n\t\tthis.changed = false;\n\t\treturn changed;\n\t}\n\n\t//set standard filters\n\tsetFilter(field, type, value, params){\n\t\tthis.filterList = [];\n\n\t\tif(!Array.isArray(field)){\n\t\t\tfield = [{field:field, type:type, value:value, params:params}];\n\t\t}\n\n\t\tthis.addFilter(field);\n\t}\n\n\t//add filter to array\n\taddFilter(field, type, value, params){\n\t\tvar changed = false;\n\n\t\tif(!Array.isArray(field)){\n\t\t\tfield = [{field:field, type:type, value:value, params:params}];\n\t\t}\n\n\t\tfield.forEach((filter) => {\n\t\t\tfilter = this.findFilter(filter);\n\n\t\t\tif(filter){\n\t\t\t\tthis.filterList.push(filter);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t});\n\n\t\tif(changed){\n\t\t\tthis.trackChanges();\n\t\t}\n\t}\n\n\tfindFilter(filter){\n\t\tvar column;\n\n\t\tif(Array.isArray(filter)){\n\t\t\treturn this.findSubFilters(filter);\n\t\t}\n\n\t\tvar filterFunc = false;\n\n\t\tif(typeof filter.field == \"function\"){\n\t\t\tfilterFunc = function(data){\n\t\t\t\treturn filter.field(data, filter.type || {});// pass params to custom filter function\n\t\t\t};\n\t\t}else {\n\n\t\t\tif(Filter.filters[filter.type]){\n\n\t\t\t\tcolumn = this.table.columnManager.getColumnByField(filter.field);\n\n\t\t\t\tif(column){\n\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\treturn Filter.filters[filter.type](filter.value, column.getFieldValue(data), data, filter.params || {});\n\t\t\t\t\t};\n\t\t\t\t}else {\n\t\t\t\t\tfilterFunc = function(data){\n\t\t\t\t\t\treturn Filter.filters[filter.type](filter.value, data[filter.field], data, filter.params || {});\n\t\t\t\t\t};\n\t\t\t\t}\n\n\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Filter Error - No such filter type found, ignoring: \", filter.type);\n\t\t\t}\n\t\t}\n\n\t\tfilter.func = filterFunc;\n\n\t\treturn filter.func ? filter : false;\n\t}\n\n\tfindSubFilters(filters){\n\t\tvar output = [];\n\n\t\tfilters.forEach((filter) => {\n\t\t\tfilter = this.findFilter(filter);\n\n\t\t\tif(filter){\n\t\t\t\toutput.push(filter);\n\t\t\t}\n\t\t});\n\n\t\treturn output.length ? output : false;\n\t}\n\n\t//get all filters\n\tgetFilters(all, ajax){\n\t\tvar output = [];\n\n\t\tif(all){\n\t\t\toutput = this.getHeaderFilters();\n\t\t}\n\n\t\tif(ajax){\n\t\t\toutput.forEach(function(item){\n\t\t\t\tif(typeof item.type == \"function\"){\n\t\t\t\t\titem.type = \"function\";\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\toutput = output.concat(this.filtersToArray(this.filterList, ajax));\n\n\t\treturn output;\n\t}\n\n\t//filter to Object\n\tfiltersToArray(filterList, ajax){\n\t\tvar output = [];\n\n\t\tfilterList.forEach((filter) => {\n\t\t\tvar item;\n\n\t\t\tif(Array.isArray(filter)){\n\t\t\t\toutput.push(this.filtersToArray(filter, ajax));\n\t\t\t}else {\n\t\t\t\titem = {field:filter.field, type:filter.type, value:filter.value};\n\n\t\t\t\tif(ajax){\n\t\t\t\t\tif(typeof item.type == \"function\"){\n\t\t\t\t\t\titem.type = \"function\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\toutput.push(item);\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\n\t//get all filters\n\tgetHeaderFilters(){\n\t\tvar output = [];\n\n\t\tfor(var key in this.headerFilters){\n\t\t\toutput.push({field:key, type:this.headerFilters[key].type, value:this.headerFilters[key].value});\n\t\t}\n\n\t\treturn output;\n\t}\n\n\t//remove filter from array\n\tremoveFilter(field, type, value){\n\t\tif(!Array.isArray(field)){\n\t\t\tfield = [{field:field, type:type, value:value}];\n\t\t}\n\n\t\tfield.forEach((filter) => {\n\t\t\tvar index = -1;\n\n\t\t\tif(typeof filter.field == \"object\"){\n\t\t\t\tindex = this.filterList.findIndex((element) => {\n\t\t\t\t\treturn filter === element;\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tindex = this.filterList.findIndex((element) => {\n\t\t\t\t\treturn filter.field === element.field && filter.type === element.type  && filter.value === element.value;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif(index > -1){\n\t\t\t\tthis.filterList.splice(index, 1);\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Filter Error - No matching filter type found, ignoring: \", filter.type);\n\t\t\t}\n\t\t});\n\n\t\tthis.trackChanges();\n\t}\n\n\t//clear filters\n\tclearFilter(all){\n\t\tthis.filterList = [];\n\n\t\tif(all){\n\t\t\tthis.clearHeaderFilter();\n\t\t}\n\n\t\tthis.trackChanges();\n\t}\n\n\t//clear header filters\n\tclearHeaderFilter(){\n\t\tthis.headerFilters = {};\n\t\tthis.prevHeaderFilterChangeCheck = \"{}\";\n\n\t\tthis.headerFilterColumns.forEach((column) => {\n\t\t\tif(typeof column.modules.filter.value !== \"undefined\"){\n\t\t\t\tdelete column.modules.filter.value;\n\t\t\t}\n\t\t\tcolumn.modules.filter.prevSuccess = undefined;\n\t\t\tthis.reloadHeaderFilter(column);\n\t\t});\n\n\t\tthis.trackChanges();\n\t}\n\n\t//search data and return matching rows\n\tsearch (searchType, field, type, value){\n\t\tvar activeRows = [],\n\t\tfilterList = [];\n\n\t\tif(!Array.isArray(field)){\n\t\t\tfield = [{field:field, type:type, value:value}];\n\t\t}\n\n\t\tfield.forEach((filter) => {\n\t\t\tfilter = this.findFilter(filter);\n\n\t\t\tif(filter){\n\t\t\t\tfilterList.push(filter);\n\t\t\t}\n\t\t});\n\n\t\tthis.table.rowManager.rows.forEach((row) => {\n\t\t\tvar match = true;\n\n\t\t\tfilterList.forEach((filter) => {\n\t\t\t\tif(!this.filterRecurse(filter, row.getData())){\n\t\t\t\t\tmatch = false;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif(match){\n\t\t\t\tactiveRows.push(searchType === \"data\" ? row.getData(\"data\") : row.getComponent());\n\t\t\t}\n\n\t\t});\n\n\t\treturn activeRows;\n\t}\n\n\t//filter row array\n\tfilter(rowList, filters){\n\t\tvar activeRows = [],\n\t\tactiveRowComponents = [];\n\n\t\tif(this.subscribedExternal(\"dataFiltering\")){\n\t\t\tthis.dispatchExternal(\"dataFiltering\", this.getFilters(true));\n\t\t}\n\n\t\tif(this.table.options.filterMode !== \"remote\" && (this.filterList.length || Object.keys(this.headerFilters).length)){\n\n\t\t\trowList.forEach((row) => {\n\t\t\t\tif(this.filterRow(row)){\n\t\t\t\t\tactiveRows.push(row);\n\t\t\t\t}\n\t\t\t});\n\n\t\t}else {\n\t\t\tactiveRows = rowList.slice(0);\n\t\t}\n\n\t\tif(this.subscribedExternal(\"dataFiltered\")){\n\n\t\t\tactiveRows.forEach((row) => {\n\t\t\t\tactiveRowComponents.push(row.getComponent());\n\t\t\t});\n\n\t\t\tthis.dispatchExternal(\"dataFiltered\", this.getFilters(true), activeRowComponents);\n\t\t}\n\n\t\treturn activeRows;\n\t}\n\n\t//filter individual row\n\tfilterRow(row, filters){\n\t\tvar match = true,\n\t\tdata = row.getData();\n\n\t\tthis.filterList.forEach((filter) => {\n\t\t\tif(!this.filterRecurse(filter, data)){\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t});\n\n\n\t\tfor(var field in this.headerFilters){\n\t\t\tif(!this.headerFilters[field].func(data)){\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t}\n\n\t\treturn match;\n\t}\n\n\tfilterRecurse(filter, data){\n\t\tvar match = false;\n\n\t\tif(Array.isArray(filter)){\n\t\t\tfilter.forEach((subFilter) => {\n\t\t\t\tif(this.filterRecurse(subFilter, data)){\n\t\t\t\t\tmatch = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\tmatch = filter.func(data);\n\t\t}\n\n\t\treturn match;\n\t}\n}\n\nFilter.moduleName = \"filter\";\n\n//load defaults\nFilter.filters = defaultFilters;\n\nfunction plaintext(cell, formatterParams, onRendered){\n\treturn this.emptyToSpace(this.sanitizeHTML(cell.getValue()));\n}\n\nfunction html$1(cell, formatterParams, onRendered){\n\treturn cell.getValue();\n}\n\nfunction textarea$1(cell, formatterParams, onRendered){\n\tcell.getElement().style.whiteSpace = \"pre-wrap\";\n\treturn this.emptyToSpace(this.sanitizeHTML(cell.getValue()));\n}\n\nfunction money(cell, formatterParams, onRendered){\n\tvar floatVal = parseFloat(cell.getValue()),\n\tsign = \"\",\n\tnumber, integer, decimal, rgx, value;\n\n\tvar decimalSym = formatterParams.decimal || \".\";\n\tvar thousandSym = formatterParams.thousand || \",\";\n\tvar negativeSign = formatterParams.negativeSign || \"-\";\n\tvar symbol = formatterParams.symbol || \"\";\n\tvar after = !!formatterParams.symbolAfter;\n\tvar precision = typeof formatterParams.precision !== \"undefined\" ? formatterParams.precision : 2;\n\n\tif(isNaN(floatVal)){\n\t\treturn this.emptyToSpace(this.sanitizeHTML(cell.getValue()));\n\t}\n\n\tif(floatVal < 0){\n\t\tfloatVal = Math.abs(floatVal);\n\t\tsign = negativeSign;\n\t}\n\n\tnumber = precision !== false ? floatVal.toFixed(precision) : floatVal;\n\tnumber = String(number).split(\".\");\n\n\tinteger = number[0];\n\tdecimal = number.length > 1 ? decimalSym + number[1] : \"\";\n\n\tif (formatterParams.thousand !== false) {\n\t\trgx = /(\\d+)(\\d{3})/;\n\n\t\twhile (rgx.test(integer)){\n\t\t\tinteger = integer.replace(rgx, \"$1\" + thousandSym + \"$2\");\n\t\t}\n\t}\n\n\tvalue = integer + decimal;\n\t\n\tif(sign === true){\n\t\tvalue = \"(\" + value  + \")\";\n\t\treturn after ? value + symbol : symbol + value;\n\t}else {\n\t\treturn after ? sign + value + symbol : sign + symbol + value;\n\t}\n}\n\nfunction link(cell, formatterParams, onRendered){\n\tvar value = cell.getValue(),\n\turlPrefix = formatterParams.urlPrefix || \"\",\n\tdownload = formatterParams.download,\n\tlabel = value,\n\tel = document.createElement(\"a\"),\n\tdata;\n\n\tfunction labelTraverse(path, data){\n\t\tvar item = path.shift(),\n\t\tvalue = data[item];\n\t\t\n\t\tif(path.length && typeof value === \"object\"){\n\t\t\treturn labelTraverse(path, value);\n\t\t}\n\n\t\treturn value;\n\t}\n\n\tif(formatterParams.labelField){\n\t\tdata = cell.getData();\n\t\tlabel = labelTraverse(formatterParams.labelField.split(this.table.options.nestedFieldSeparator), data);\n\t}\n\n\tif(formatterParams.label){\n\t\tswitch(typeof formatterParams.label){\n\t\t\tcase \"string\":\n\t\t\t\tlabel = formatterParams.label;\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\tlabel = formatterParams.label(cell);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(label){\n\t\tif(formatterParams.urlField){\n\t\t\tdata = cell.getData();\n\n\t\t\tvalue = Helpers.retrieveNestedData(this.table.options.nestedFieldSeparator, formatterParams.urlField, data);\n\t\t}\n\n\t\tif(formatterParams.url){\n\t\t\tswitch(typeof formatterParams.url){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tvalue = formatterParams.url;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"function\":\n\t\t\t\t\tvalue = formatterParams.url(cell);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tel.setAttribute(\"href\", urlPrefix + value);\n\n\t\tif(formatterParams.target){\n\t\t\tel.setAttribute(\"target\", formatterParams.target);\n\t\t}\n\n\t\tif(formatterParams.download){\n\n\t\t\tif(typeof download == \"function\"){\n\t\t\t\tdownload = download(cell);\n\t\t\t}else {\n\t\t\t\tdownload = download === true ? \"\" : download;\n\t\t\t}\n\n\t\t\tel.setAttribute(\"download\", download);\n\t\t}\n\n\t\tel.innerHTML = this.emptyToSpace(this.sanitizeHTML(label));\n\n\t\treturn el;\n\t}else {\n\t\treturn \"&nbsp;\";\n\t}\n}\n\nfunction image(cell, formatterParams, onRendered){\n\tvar el = document.createElement(\"img\"),\n\tsrc = cell.getValue();\n\n\tif(formatterParams.urlPrefix){\n\t\tsrc = formatterParams.urlPrefix + cell.getValue();\n\t}\n\n\tif(formatterParams.urlSuffix){\n\t\tsrc = src + formatterParams.urlSuffix;\n\t}\n\n\tel.setAttribute(\"src\", src);\n\n\tswitch(typeof formatterParams.height){\n\t\tcase \"number\":\n\t\t\tel.style.height = formatterParams.height + \"px\";\n\t\t\tbreak;\n\n\t\tcase \"string\":\n\t\t\tel.style.height = formatterParams.height;\n\t\t\tbreak;\n\t}\n\n\tswitch(typeof formatterParams.width){\n\t\tcase \"number\":\n\t\t\tel.style.width = formatterParams.width + \"px\";\n\t\t\tbreak;\n\n\t\tcase \"string\":\n\t\t\tel.style.width = formatterParams.width;\n\t\t\tbreak;\n\t}\n\n\tel.addEventListener(\"load\", function(){\n\t\tcell.getRow().normalizeHeight();\n\t});\n\n\treturn el;\n}\n\nfunction tickCross$1(cell, formatterParams, onRendered){\n\tvar value = cell.getValue(),\n\telement = cell.getElement(),\n\tempty = formatterParams.allowEmpty,\n\ttruthy = formatterParams.allowTruthy,\n\ttrueValueSet = Object.keys(formatterParams).includes(\"trueValue\"),\n\ttick = typeof formatterParams.tickElement !== \"undefined\" ? formatterParams.tickElement : '<svg enable-background=\"new 0 0 24 24\" height=\"14\" width=\"14\" viewBox=\"0 0 24 24\" xml:space=\"preserve\" ><path fill=\"#2DC214\" clip-rule=\"evenodd\" d=\"M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34  c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351  l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07  l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z\" fill-rule=\"evenodd\"/></svg>',\n\tcross = typeof formatterParams.crossElement !== \"undefined\" ? formatterParams.crossElement : '<svg enable-background=\"new 0 0 24 24\" height=\"14\" width=\"14\"  viewBox=\"0 0 24 24\" xml:space=\"preserve\" ><path fill=\"#CE1515\" d=\"M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272  c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0  l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269  c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73  L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z\"/></svg>';\n\n\tif((trueValueSet && value === formatterParams.trueValue) || (!trueValueSet && ((truthy && value) || (value === true || value === \"true\" || value === \"True\" || value === 1 || value === \"1\")))){\n\t\telement.setAttribute(\"aria-checked\", true);\n\t\treturn tick || \"\";\n\t}else {\n\t\tif(empty && (value === \"null\" || value === \"\" || value === null || typeof value === \"undefined\")){\n\t\t\telement.setAttribute(\"aria-checked\", \"mixed\");\n\t\t\treturn \"\";\n\t\t}else {\n\t\t\telement.setAttribute(\"aria-checked\", false);\n\t\t\treturn cross || \"\";\n\t\t}\n\t}\n}\n\nfunction datetime$1(cell, formatterParams, onRendered){\n\tvar DT = window.DateTime || luxon.DateTime;\n\tvar inputFormat = formatterParams.inputFormat || \"yyyy-MM-dd HH:mm:ss\";\n\tvar\toutputFormat = formatterParams.outputFormat || \"dd/MM/yyyy HH:mm:ss\";\n\tvar\tinvalid = typeof formatterParams.invalidPlaceholder !== \"undefined\" ? formatterParams.invalidPlaceholder : \"\";\n\tvar value = cell.getValue();\n\n\tif(typeof DT != \"undefined\"){\n\t\tvar newDatetime;\n\n\t\tif(DT.isDateTime(value)){\n\t\t\tnewDatetime = value;\n\t\t}else if(inputFormat === \"iso\"){\n\t\t\tnewDatetime = DT.fromISO(String(value));\n\t\t}else {\n\t\t\tnewDatetime = DT.fromFormat(String(value), inputFormat);\n\t\t}\n\n\t\tif(newDatetime.isValid){\n\t\t\tif(formatterParams.timezone){\n\t\t\t\tnewDatetime = newDatetime.setZone(formatterParams.timezone);\n\t\t\t}\n\n\t\t\treturn newDatetime.toFormat(outputFormat);\n\t\t}else {\n\t\t\tif(invalid === true || !value){\n\t\t\t\treturn value;\n\t\t\t}else if(typeof invalid === \"function\"){\n\t\t\t\treturn invalid(value);\n\t\t\t}else {\n\t\t\t\treturn invalid;\n\t\t\t}\n\t\t}\n\t}else {\n\t\tconsole.error(\"Format Error - 'datetime' formatter is dependant on luxon.js\");\n\t}\n}\n\nfunction datetimediff (cell, formatterParams, onRendered) {\n\tvar DT = window.DateTime || luxon.DateTime;\n\tvar inputFormat = formatterParams.inputFormat || \"yyyy-MM-dd HH:mm:ss\";\n\tvar invalid = typeof formatterParams.invalidPlaceholder !== \"undefined\" ? formatterParams.invalidPlaceholder : \"\";\n\tvar suffix = typeof formatterParams.suffix !== \"undefined\" ? formatterParams.suffix : false;\n\tvar unit = typeof formatterParams.unit !== \"undefined\" ? formatterParams.unit : \"days\";\n\tvar humanize = typeof formatterParams.humanize !== \"undefined\" ? formatterParams.humanize : false;\n\tvar date = typeof formatterParams.date !== \"undefined\" ? formatterParams.date : DT.now();\n\tvar value = cell.getValue();\n\n\tif(typeof DT != \"undefined\"){\n\t\tvar newDatetime;\n\n\t\tif(DT.isDateTime(value)){\n\t\t\tnewDatetime = value;\n\t\t}else if(inputFormat === \"iso\"){\n\t\t\tnewDatetime = DT.fromISO(String(value));\n\t\t}else {\n\t\t\tnewDatetime = DT.fromFormat(String(value), inputFormat);\n\t\t}\n\n\t\tif (newDatetime.isValid){\n\t\t\tif(humanize){\n\t\t\t\treturn newDatetime.diff(date, unit).toHuman()  + (suffix ? \" \" + suffix : \"\");\n\t\t\t}else {\n\t\t\t\treturn parseInt(newDatetime.diff(date, unit)[unit]) + (suffix ? \" \" + suffix : \"\");\n\t\t\t}\n\t\t} else {\n\n\t\t\tif (invalid === true) {\n\t\t\t\treturn value;\n\t\t\t} else if (typeof invalid === \"function\") {\n\t\t\t\treturn invalid(value);\n\t\t\t} else {\n\t\t\t\treturn invalid;\n\t\t\t}\n\t\t}\n\t}else {\n\t\tconsole.error(\"Format Error - 'datetimediff' formatter is dependant on luxon.js\");\n\t}\n}\n\nfunction lookup (cell, formatterParams, onRendered) {\n\tvar value = cell.getValue();\n\n\tif (typeof formatterParams[value] === \"undefined\") {\n\t\tconsole.warn('Missing display value for ' + value);\n\t\treturn value;\n\t}\n\n\treturn formatterParams[value];\n}\n\nfunction star$1(cell, formatterParams, onRendered){\n\tvar value = cell.getValue(),\n\telement = cell.getElement(),\n\tmaxStars = formatterParams && formatterParams.stars ? formatterParams.stars : 5,\n\tstars = document.createElement(\"span\"),\n\tstar = document.createElementNS('http://www.w3.org/2000/svg', \"svg\"),\n\tstarActive = '<polygon fill=\"#FFEA00\" stroke=\"#C1AB60\" stroke-width=\"37.6152\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" points=\"259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 \"/>',\n\tstarInactive = '<polygon fill=\"#D2D2D2\" stroke=\"#686868\" stroke-width=\"37.6152\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" points=\"259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 \"/>';\n\n\t//style stars holder\n\tstars.style.verticalAlign = \"middle\";\n\n\t//style star\n\tstar.setAttribute(\"width\", \"14\");\n\tstar.setAttribute(\"height\", \"14\");\n\tstar.setAttribute(\"viewBox\", \"0 0 512 512\");\n\tstar.setAttribute(\"xml:space\", \"preserve\");\n\tstar.style.padding = \"0 1px\";\n\n\tvalue = value && !isNaN(value) ? parseInt(value) : 0;\n\n\tvalue = Math.max(0, Math.min(value, maxStars));\n\n\tfor(var i=1;i<= maxStars;i++){\n\t\tvar nextStar = star.cloneNode(true);\n\t\tnextStar.innerHTML = i <= value ? starActive : starInactive;\n\n\t\tstars.appendChild(nextStar);\n\t}\n\n\telement.style.whiteSpace = \"nowrap\";\n\telement.style.overflow = \"hidden\";\n\telement.style.textOverflow = \"ellipsis\";\n\n\telement.setAttribute(\"aria-label\", value);\n\n\treturn stars;\n}\n\nfunction traffic(cell, formatterParams, onRendered){\n\tvar value = this.sanitizeHTML(cell.getValue()) || 0,\n\tel = document.createElement(\"span\"),\n\tmax = formatterParams && formatterParams.max ? formatterParams.max : 100,\n\tmin = formatterParams && formatterParams.min ? formatterParams.min : 0,\n\tcolors = formatterParams && typeof formatterParams.color !== \"undefined\" ? formatterParams.color : [\"red\", \"orange\", \"green\"],\n\tcolor = \"#666666\",\n\tpercent, percentValue;\n\n\tif(isNaN(value) || typeof cell.getValue() === \"undefined\"){\n\t\treturn;\n\t}\n\n\tel.classList.add(\"tabulator-traffic-light\");\n\n\t//make sure value is in range\n\tpercentValue = parseFloat(value) <= max ? parseFloat(value) : max;\n\tpercentValue = parseFloat(percentValue) >= min ? parseFloat(percentValue) : min;\n\n\t//workout percentage\n\tpercent = (max - min) / 100;\n\tpercentValue = Math.round((percentValue - min) / percent);\n\n\t//set color\n\tswitch(typeof colors){\n\t\tcase \"string\":\n\t\t\tcolor = colors;\n\t\t\tbreak;\n\t\tcase \"function\":\n\t\t\tcolor = colors(value);\n\t\t\tbreak;\n\t\tcase \"object\":\n\t\t\tif(Array.isArray(colors)){\n\t\t\t\tvar unit = 100 / colors.length;\n\t\t\t\tvar index = Math.floor(percentValue / unit);\n\n\t\t\t\tindex = Math.min(index, colors.length - 1);\n\t\t\t\tindex = Math.max(index, 0);\n\t\t\t\tcolor = colors[index];\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\n\tel.style.backgroundColor = color;\n\n\treturn el;\n}\n\nfunction progress$1(cell, formatterParams = {}, onRendered){ //progress bar\n\tvar value = this.sanitizeHTML(cell.getValue()) || 0,\n\telement = cell.getElement(),\n\tmax = formatterParams.max ? formatterParams.max : 100,\n\tmin = formatterParams.min ? formatterParams.min : 0,\n\tlegendAlign = formatterParams.legendAlign ? formatterParams.legendAlign : \"center\",\n\tpercent, percentValue, color, legend, legendColor;\n\n\t//make sure value is in range\n\tpercentValue = parseFloat(value) <= max ? parseFloat(value) : max;\n\tpercentValue = parseFloat(percentValue) >= min ? parseFloat(percentValue) : min;\n\n\t//workout percentage\n\tpercent = (max - min) / 100;\n\tpercentValue = Math.round((percentValue - min) / percent);\n\n\t//set bar color\n\tswitch(typeof formatterParams.color){\n\t\tcase \"string\":\n\t\t\tcolor = formatterParams.color;\n\t\t\tbreak;\n\t\tcase \"function\":\n\t\t\tcolor = formatterParams.color(value);\n\t\t\tbreak;\n\t\tcase \"object\":\n\t\t\tif(Array.isArray(formatterParams.color)){\n\t\t\t\tlet unit = 100 / formatterParams.color.length;\n\t\t\t\tlet index = Math.floor(percentValue / unit);\n\n\t\t\t\tindex = Math.min(index, formatterParams.color.length - 1);\n\t\t\t\tindex = Math.max(index, 0);\n\t\t\t\tcolor = formatterParams.color[index];\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\tcolor = \"#2DC214\";\n\t}\n\n\t//generate legend\n\tswitch(typeof formatterParams.legend){\n\t\tcase \"string\":\n\t\t\tlegend = formatterParams.legend;\n\t\t\tbreak;\n\t\tcase \"function\":\n\t\t\tlegend = formatterParams.legend(value);\n\t\t\tbreak;\n\t\tcase \"boolean\":\n\t\t\tlegend = value;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tlegend = false;\n\t}\n\n\t//set legend color\n\tswitch(typeof formatterParams.legendColor){\n\t\tcase \"string\":\n\t\t\tlegendColor = formatterParams.legendColor;\n\t\t\tbreak;\n\t\tcase \"function\":\n\t\t\tlegendColor = formatterParams.legendColor(value);\n\t\t\tbreak;\n\t\tcase \"object\":\n\t\t\tif(Array.isArray(formatterParams.legendColor)){\n\t\t\t\tlet unit = 100 / formatterParams.legendColor.length;\n\t\t\t\tlet index = Math.floor(percentValue / unit);\n\n\t\t\t\tindex = Math.min(index, formatterParams.legendColor.length - 1);\n\t\t\t\tindex = Math.max(index, 0);\n\t\t\t\tlegendColor = formatterParams.legendColor[index];\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tlegendColor = \"#000\";\n\t}\n\n\telement.style.minWidth = \"30px\";\n\telement.style.position = \"relative\";\n\n\telement.setAttribute(\"aria-label\", percentValue);\n\n\tvar barEl = document.createElement(\"div\");\n\tbarEl.style.display = \"inline-block\";\n\tbarEl.style.width = percentValue + \"%\";\n\tbarEl.style.backgroundColor = color;\n\tbarEl.style.height = \"100%\";\n\n\tbarEl.setAttribute('data-max', max);\n\tbarEl.setAttribute('data-min', min);\n\n\tvar barContainer = document.createElement(\"div\");\n\tbarContainer.style.position = \"relative\";\n\tbarContainer.style.width = \"100%\";\n\tbarContainer.style.height = \"100%\";\n\n\tif(legend){\n\t\tvar legendEl = document.createElement(\"div\");\n\t\tlegendEl.style.position = \"absolute\";\n\t\tlegendEl.style.top = 0;\n\t\tlegendEl.style.left = 0;\n\t\tlegendEl.style.textAlign = legendAlign;\n\t\tlegendEl.style.width = \"100%\";\n\t\tlegendEl.style.color = legendColor;\n\t\tlegendEl.innerHTML = legend;\n\t}\n\n\tonRendered(function(){\n\n\t\t//handle custom element needed if formatter is to be included in printed/downloaded output\n\t\tif(!(cell instanceof CellComponent)){\n\t\t\tvar holderEl = document.createElement(\"div\");\n\t\t\tholderEl.style.position = \"absolute\";\n\t\t\tholderEl.style.top = \"4px\";\n\t\t\tholderEl.style.bottom = \"4px\";\n\t\t\tholderEl.style.left = \"4px\";\n\t\t\tholderEl.style.right = \"4px\";\n\n\t\t\telement.appendChild(holderEl);\n\n\t\t\telement = holderEl;\n\t\t}\n\n\t\telement.appendChild(barContainer);\n\t\tbarContainer.appendChild(barEl);\n\n\t\tif(legend){\n\t\t\tbarContainer.appendChild(legendEl);\n\t\t}\n\t});\n\n\treturn \"\";\n}\n\nfunction color(cell, formatterParams, onRendered){\n\tcell.getElement().style.backgroundColor = this.sanitizeHTML(cell.getValue());\n\treturn \"\";\n}\n\nfunction buttonTick(cell, formatterParams, onRendered){\n\treturn '<svg enable-background=\"new 0 0 24 24\" height=\"14\" width=\"14\" viewBox=\"0 0 24 24\" xml:space=\"preserve\" ><path fill=\"#2DC214\" clip-rule=\"evenodd\" d=\"M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34  c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351  l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07  l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z\" fill-rule=\"evenodd\"/></svg>';\n}\n\nfunction buttonCross(cell, formatterParams, onRendered){\n\treturn '<svg enable-background=\"new 0 0 24 24\" height=\"14\" width=\"14\" viewBox=\"0 0 24 24\" xml:space=\"preserve\" ><path fill=\"#CE1515\" d=\"M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272  c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0  l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269  c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73  L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z\"/></svg>';\n}\n\nfunction rownum(cell, formatterParams, onRendered){\n\tvar content = document.createElement(\"span\");\n\tvar row = cell.getRow();\n\tvar table = cell.getTable();\n\n\trow.watchPosition((position) => {\n\t\tif (formatterParams.relativeToPage) {\n\t\t\tposition += table.modules.page.getPageSize() * (table.modules.page.getPage() - 1);\n\t\t}\n\t\tcontent.innerText = position;\n\t});\n\t\n\treturn content;\n}\n\nfunction handle(cell, formatterParams, onRendered){\n\tcell.getElement().classList.add(\"tabulator-row-handle\");\n\treturn \"<div class='tabulator-row-handle-box'><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div></div>\";\n}\n\nfunction responsiveCollapse(cell, formatterParams, onRendered){\n\tvar el = document.createElement(\"div\"),\n\tconfig = cell.getRow()._row.modules.responsiveLayout;\n\n\tel.classList.add(\"tabulator-responsive-collapse-toggle\");\n\t\n\tel.innerHTML = `<svg class='tabulator-responsive-collapse-toggle-open' viewbox=\"0 0 24 24\">\n  <line x1=\"7\" y1=\"12\" x2=\"17\" y2=\"12\" fill=\"none\" stroke-width=\"3\" stroke-linecap=\"round\" />\n  <line y1=\"7\" x1=\"12\" y2=\"17\" x2=\"12\" fill=\"none\" stroke-width=\"3\" stroke-linecap=\"round\" />\n</svg>\n\n<svg class='tabulator-responsive-collapse-toggle-close' viewbox=\"0 0 24 24\">\n  <line x1=\"7\" y1=\"12\" x2=\"17\" y2=\"12\"  fill=\"none\" stroke-width=\"3\" stroke-linecap=\"round\" />\n</svg>`;\n\n\tcell.getElement().classList.add(\"tabulator-row-handle\");\n\n\tfunction toggleList(isOpen){\n\t\tvar collapseEl = config.element;\n\n\t\tconfig.open = isOpen;\n\n\t\tif(collapseEl){\n\n\t\t\tif(config.open){\n\t\t\t\tel.classList.add(\"open\");\n\t\t\t\tcollapseEl.style.display = '';\n\t\t\t}else {\n\t\t\t\tel.classList.remove(\"open\");\n\t\t\t\tcollapseEl.style.display = 'none';\n\t\t\t}\n\t\t}\n\t}\n\n\tel.addEventListener(\"click\", function(e){\n\t\te.stopImmediatePropagation();\n\t\ttoggleList(!config.open);\n\t\tcell.getTable().rowManager.adjustTableSize();\n\t});\n\n\ttoggleList(config.open);\n\n\treturn el;\n}\n\nfunction rowSelection(cell, formatterParams, onRendered){\n\tvar checkbox = document.createElement(\"input\");\n\tvar blocked = false;\n\n\tcheckbox.type = 'checkbox';\n\n\tcheckbox.setAttribute(\"aria-label\", \"Select Row\");\n\t\n\tif(this.table.modExists(\"selectRow\", true)){\n\n\t\tcheckbox.addEventListener(\"click\", (e) => {\n\t\t\te.stopPropagation();\n\t\t});\n\n\t\tif(typeof cell.getRow == 'function'){\n\t\t\tvar row = cell.getRow();\n\n\t\t\tif(row instanceof RowComponent){\n\n\t\t\t\tcheckbox.addEventListener(\"change\", (e) => {\n\t\t\t\t\tif(this.table.options.selectableRowsRangeMode === \"click\"){\n\t\t\t\t\t\tif(!blocked){\n\t\t\t\t\t\t\trow.toggleSelect();\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tblocked = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\trow.toggleSelect();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif(this.table.options.selectableRowsRangeMode === \"click\"){\n\t\t\t\t\tcheckbox.addEventListener(\"click\", (e) => {\n\t\t\t\t\t\tblocked = true;\n\t\t\t\t\t\tthis.table.modules.selectRow.handleComplexRowClick(row._row, e);\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tcheckbox.checked = row.isSelected && row.isSelected();\n\t\t\t\tthis.table.modules.selectRow.registerRowSelectCheckbox(row, checkbox);\n\t\t\t}else {\n\t\t\t\tcheckbox = \"\";\n\t\t\t}\n\t\t}else {\n\t\t\tcheckbox.addEventListener(\"change\", (e) => {\n\t\t\t\tif(this.table.modules.selectRow.selectedRows.length){\n\t\t\t\t\tthis.table.deselectRow();\n\t\t\t\t}else {\n\t\t\t\t\tthis.table.selectRow(formatterParams.rowRange);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.table.modules.selectRow.registerHeaderSelectCheckbox(checkbox);\n\t\t}\n\t}\n\n\treturn checkbox;\n}\n\nvar defaultFormatters = {\n\tplaintext:plaintext,\n\thtml:html$1,\n\ttextarea:textarea$1,\n\tmoney:money,\n\tlink:link,\n\timage:image,\n\ttickCross:tickCross$1,\n\tdatetime:datetime$1,\n\tdatetimediff:datetimediff,\n\tlookup:lookup,\n\tstar:star$1,\n\ttraffic:traffic,\n\tprogress:progress$1,\n\tcolor:color,\n\tbuttonTick:buttonTick,\n\tbuttonCross:buttonCross,\n\trownum:rownum,\n\thandle:handle,\n\tresponsiveCollapse:responsiveCollapse,\n\trowSelection:rowSelection,\n};\n\nclass Format extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.registerColumnOption(\"formatter\");\n\t\tthis.registerColumnOption(\"formatterParams\");\n\t\t\n\t\tthis.registerColumnOption(\"formatterPrint\");\n\t\tthis.registerColumnOption(\"formatterPrintParams\");\n\t\tthis.registerColumnOption(\"formatterClipboard\");\n\t\tthis.registerColumnOption(\"formatterClipboardParams\");\n\t\tthis.registerColumnOption(\"formatterHtmlOutput\");\n\t\tthis.registerColumnOption(\"formatterHtmlOutputParams\");\n\t\tthis.registerColumnOption(\"titleFormatter\");\n\t\tthis.registerColumnOption(\"titleFormatterParams\");\n\t}\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"cell-format\", this.formatValue.bind(this));\n\t\tthis.subscribe(\"cell-rendered\", this.cellRendered.bind(this));\n\t\tthis.subscribe(\"column-layout\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"column-format\", this.formatHeader.bind(this));\n\t}\n\t\n\t//initialize column formatter\n\tinitializeColumn(column){\n\t\tcolumn.modules.format = this.lookupFormatter(column, \"\");\n\t\t\n\t\tif(typeof column.definition.formatterPrint !== \"undefined\"){\n\t\t\tcolumn.modules.format.print = this.lookupFormatter(column, \"Print\");\n\t\t}\n\t\t\n\t\tif(typeof column.definition.formatterClipboard !== \"undefined\"){\n\t\t\tcolumn.modules.format.clipboard = this.lookupFormatter(column, \"Clipboard\");\n\t\t}\n\t\t\n\t\tif(typeof column.definition.formatterHtmlOutput !== \"undefined\"){\n\t\t\tcolumn.modules.format.htmlOutput = this.lookupFormatter(column, \"HtmlOutput\");\n\t\t}\n\t}\n\t\n\tlookupFormatter(column, type){\n\t\tvar config = {params:column.definition[\"formatter\" + type + \"Params\"] || {}},\n\t\tformatter = column.definition[\"formatter\" + type];\n\t\t\n\t\t//set column formatter\n\t\tswitch(typeof formatter){\n\t\t\tcase \"string\":\n\t\t\t\tif(Format.formatters[formatter]){\n\t\t\t\t\tconfig.formatter = Format.formatters[formatter];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Formatter Error - No such formatter found: \", formatter);\n\t\t\t\t\tconfig.formatter = Format.formatters.plaintext;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"function\":\n\t\t\t\tconfig.formatter = formatter;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tconfig.formatter = Format.formatters.plaintext;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\treturn config;\n\t}\n\t\n\tcellRendered(cell){\n\t\tif(cell.modules.format && cell.modules.format.renderedCallback && !cell.modules.format.rendered){\n\t\t\tcell.modules.format.renderedCallback();\n\t\t\tcell.modules.format.rendered = true;\n\t\t}\n\t}\n\t\n\t//return a formatted value for a column header\n\tformatHeader(column, title, el){\n\t\tvar formatter, params, onRendered, mockCell;\n\t\t\n\t\tif(column.definition.titleFormatter){\n\t\t\tformatter = this.getFormatter(column.definition.titleFormatter);\n\t\t\t\n\t\t\tonRendered = (callback) => {\n\t\t\t\tcolumn.titleFormatterRendered = callback;\n\t\t\t};\n\t\t\t\n\t\t\tmockCell = {\n\t\t\t\tgetValue:function(){\n\t\t\t\t\treturn title;\n\t\t\t\t},\n\t\t\t\tgetElement:function(){\n\t\t\t\t\treturn el;\n\t\t\t\t},\n\t\t\t\tgetType:function(){\n\t\t\t\t\treturn \"header\";\n\t\t\t\t},\n\t\t\t\tgetColumn:function(){\n\t\t\t\t\treturn column.getComponent();\n\t\t\t\t},\n\t\t\t\tgetTable:() => {\n\t\t\t\t\treturn this.table;\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tparams = column.definition.titleFormatterParams || {};\n\t\t\t\n\t\t\tparams = typeof params === \"function\" ? params() : params;\n\t\t\t\n\t\t\treturn formatter.call(this, mockCell, params, onRendered);\n\t\t}else {\n\t\t\treturn title;\n\t\t}\n\t}\n\t\n\t\n\t//return a formatted value for a cell\n\tformatValue(cell){\n\t\tvar component = cell.getComponent(),\n\t\tparams = typeof cell.column.modules.format.params === \"function\" ? cell.column.modules.format.params(component) : cell.column.modules.format.params;\n\t\t\n\t\tfunction onRendered(callback){\n\t\t\tif(!cell.modules.format){\n\t\t\t\tcell.modules.format = {};\n\t\t\t}\n\t\t\t\n\t\t\tcell.modules.format.renderedCallback = callback;\n\t\t\tcell.modules.format.rendered = false;\n\t\t}\n\t\t\n\t\treturn cell.column.modules.format.formatter.call(this, component, params, onRendered);\n\t}\n\t\n\tformatExportValue(cell, type){\n\t\tvar formatter = cell.column.modules.format[type],\n\t\tparams;\n\t\t\n\t\tif(formatter){\n\t\t\tparams = typeof formatter.params === \"function\" ? formatter.params(cell.getComponent()) : formatter.params;\n\t\t\t\n\t\t\tfunction onRendered(callback){\n\t\t\t\tif(!cell.modules.format){\n\t\t\t\t\tcell.modules.format = {};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcell.modules.format.renderedCallback = callback;\n\t\t\t\tcell.modules.format.rendered = false;\n\t\t\t}\n\t\t\t\n\t\t\treturn formatter.formatter.call(this, cell.getComponent(), params, onRendered);\n\t\t\t\n\t\t}else {\n\t\t\treturn this.formatValue(cell);\n\t\t}\n\t}\n\t\n\tsanitizeHTML(value){\n\t\tif(value){\n\t\t\tvar entityMap = {\n\t\t\t\t'&': '&amp;',\n\t\t\t\t'<': '&lt;',\n\t\t\t\t'>': '&gt;',\n\t\t\t\t'\"': '&quot;',\n\t\t\t\t\"'\": '&#39;',\n\t\t\t\t'/': '&#x2F;',\n\t\t\t\t'`': '&#x60;',\n\t\t\t\t'=': '&#x3D;'\n\t\t\t};\n\t\t\t\n\t\t\treturn String(value).replace(/[&<>\"'`=/]/g, function (s) {\n\t\t\t\treturn entityMap[s];\n\t\t\t});\n\t\t}else {\n\t\t\treturn value;\n\t\t}\n\t}\n\t\n\temptyToSpace(value){\n\t\treturn value === null || typeof value === \"undefined\" || value === \"\" ? \"&nbsp;\" : value;\n\t}\n\t\n\t//get formatter for cell\n\tgetFormatter(formatter){\n\t\tswitch(typeof formatter){\n\t\t\tcase \"string\":\n\t\t\t\tif(Format.formatters[formatter]){\n\t\t\t\t\tformatter = Format.formatters[formatter];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Formatter Error - No such formatter found: \", formatter);\n\t\t\t\t\tformatter = Format.formatters.plaintext;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"function\":\n\t\t\t//Custom formatter Function, do nothing\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tformatter = Format.formatters.plaintext;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\treturn formatter;\n\t}\n}\n\nFormat.moduleName = \"format\";\n\n//load defaults\nFormat.formatters = defaultFormatters;\n\nclass FrozenColumns extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.leftColumns = [];\n\t\tthis.rightColumns = [];\n\t\tthis.initializationMode = \"left\";\n\t\tthis.active = false;\n\t\tthis.blocked = true;\n\t\t\n\t\tthis.registerColumnOption(\"frozen\");\n\t}\n\t\n\t//reset initial state\n\treset(){\n\t\tthis.initializationMode = \"left\";\n\t\tthis.leftColumns = [];\n\t\tthis.rightColumns = [];\n\t\tthis.active = false;\n\t}\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"cell-layout\", this.layoutCell.bind(this));\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"column-width\", this.layout.bind(this));\n\t\tthis.subscribe(\"row-layout-after\", this.layoutRow.bind(this));\n\t\tthis.subscribe(\"table-layout\", this.layout.bind(this));\n\t\tthis.subscribe(\"columns-loading\", this.reset.bind(this));\n\t\t\n\t\tthis.subscribe(\"column-add\", this.reinitializeColumns.bind(this));\n\t\tthis.subscribe(\"column-deleted\", this.reinitializeColumns.bind(this));\n\t\tthis.subscribe(\"column-hide\", this.reinitializeColumns.bind(this));\n\t\tthis.subscribe(\"column-show\", this.reinitializeColumns.bind(this));\n\t\tthis.subscribe(\"columns-loaded\", this.reinitializeColumns.bind(this));\n\t\t\n\t\tthis.subscribe(\"table-redraw\", this.layout.bind(this));\n\t\tthis.subscribe(\"layout-refreshing\", this.blockLayout.bind(this));\n\t\tthis.subscribe(\"layout-refreshed\", this.unblockLayout.bind(this));\n\t\tthis.subscribe(\"scrollbar-vertical\", this.adjustForScrollbar.bind(this));\n\t}\n\t\n\tblockLayout(){\n\t\tthis.blocked = true;\n\t}\n\t\n\tunblockLayout(){\n\t\tthis.blocked = false;\n\t}\n\t\n\tlayoutCell(cell){\n\t\tthis.layoutElement(cell.element, cell.column);\n\t}\n\t\n\treinitializeColumns(){\n\t\tthis.reset();\n\t\t\n\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\tthis.initializeColumn(column);\n\t\t});\n\n\t\tthis.layout();\n\t}\n\t\n\t//initialize specific column\n\tinitializeColumn(column){\n\t\tvar config = {margin:0, edge:false};\n\t\t\n\t\tif(!column.isGroup){\t\t\t\n\t\t\tif(this.frozenCheck(column)){\n\t\t\t\tconfig.position = this.initializationMode;\n\t\t\t\t\n\t\t\t\tif(this.initializationMode == \"left\"){\n\t\t\t\t\tthis.leftColumns.push(column);\n\t\t\t\t}else {\n\t\t\t\t\tthis.rightColumns.unshift(column);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.active = true;\n\t\t\t\t\n\t\t\t\tcolumn.modules.frozen = config;\n\t\t\t}else {\n\t\t\t\tthis.initializationMode = \"right\";\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfrozenCheck(column){\n\t\tif(column.parent.isGroup && column.definition.frozen){\n\t\t\tconsole.warn(\"Frozen Column Error - Parent column group must be frozen, not individual columns or sub column groups\");\n\t\t}\n\t\t\n\t\tif(column.parent.isGroup){\n\t\t\treturn this.frozenCheck(column.parent);\n\t\t}else {\n\t\t\treturn column.definition.frozen;\n\t\t}\n\t}\n\t\n\t//layout calculation rows\n\tlayoutCalcRows(){\n\t\tif(this.table.modExists(\"columnCalcs\")){\n\t\t\tif(this.table.modules.columnCalcs.topInitialized && this.table.modules.columnCalcs.topRow){\n\t\t\t\tthis.layoutRow(this.table.modules.columnCalcs.topRow);\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.modules.columnCalcs.botInitialized && this.table.modules.columnCalcs.botRow){\n\t\t\t\tthis.layoutRow(this.table.modules.columnCalcs.botRow);\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.modExists(\"groupRows\")){\n\t\t\t\tthis.layoutGroupCalcs(this.table.modules.groupRows.getGroups());\n\t\t\t}\n\t\t}\n\t}\n\t\n\tlayoutGroupCalcs(groups){\n\t\tgroups.forEach((group) => {\n\t\t\tif(group.calcs.top){\n\t\t\t\tthis.layoutRow(group.calcs.top);\n\t\t\t}\n\t\t\t\n\t\t\tif(group.calcs.bottom){\n\t\t\t\tthis.layoutRow(group.calcs.bottom);\n\t\t\t}\n\t\t\t\n\t\t\tif(group.groupList && group.groupList.length){\n\t\t\t\tthis.layoutGroupCalcs(group.groupList);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//calculate column positions and layout headers\n\tlayoutColumnPosition(allCells){\n\t\tvar leftParents = [];\n\t\t\n\t\tvar leftMargin = 0;\n\t\tvar rightMargin = 0;\n\t\t\n\t\tthis.leftColumns.forEach((column, i) => {\t\n\t\t\tcolumn.modules.frozen.marginValue = leftMargin;\n\t\t\tcolumn.modules.frozen.margin = column.modules.frozen.marginValue + \"px\";\n\t\t\t\n\t\t\tif(column.visible){\n\t\t\t\tleftMargin += column.getWidth();\n\t\t\t}\n\t\t\t\n\t\t\tif(i == this.leftColumns.length - 1){\n\t\t\t\tcolumn.modules.frozen.edge = true;\n\t\t\t}else {\n\t\t\t\tcolumn.modules.frozen.edge = false;\n\t\t\t}\n\t\t\t\n\t\t\tif(column.parent.isGroup){\n\t\t\t\tvar parentEl = this.getColGroupParentElement(column);\n\t\t\t\tif(!leftParents.includes(parentEl)){\n\t\t\t\t\tthis.layoutElement(parentEl, column);\n\t\t\t\t\tleftParents.push(parentEl);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tparentEl.classList.toggle(\"tabulator-frozen-left\",  column.modules.frozen.edge && column.modules.frozen.position === \"left\");\n\t\t\t\tparentEl.classList.toggle(\"tabulator-frozen-right\", column.modules.frozen.edge && column.modules.frozen.position === \"right\");\n\t\t\t}else {\n\t\t\t\tthis.layoutElement(column.getElement(), column);\n\t\t\t}\n\t\t\t\n\t\t\tif(allCells){\n\t\t\t\tcolumn.cells.forEach((cell) => {\n\t\t\t\t\tthis.layoutElement(cell.getElement(true), column);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.rightColumns.forEach((column, i) => {\n\t\t\t\n\t\t\tcolumn.modules.frozen.marginValue = rightMargin;\n\t\t\tcolumn.modules.frozen.margin = column.modules.frozen.marginValue + \"px\";\n\t\t\t\n\t\t\tif(column.visible){\n\t\t\t\trightMargin += column.getWidth();\n\t\t\t}\n\t\t\t\n\t\t\tif(i == this.rightColumns.length - 1){\n\t\t\t\tcolumn.modules.frozen.edge = true;\n\t\t\t}else {\n\t\t\t\tcolumn.modules.frozen.edge = false;\n\t\t\t}\n\t\t\t\n\t\t\tif(column.parent.isGroup){\n\t\t\t\tthis.layoutElement(this.getColGroupParentElement(column), column);\n\t\t\t}else {\n\t\t\t\tthis.layoutElement(column.getElement(), column);\n\t\t\t}\n\t\t\t\n\t\t\tif(allCells){\n\t\t\t\tcolumn.cells.forEach((cell) => {\n\t\t\t\t\tthis.layoutElement(cell.getElement(true), column);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\t\n\tgetColGroupParentElement(column){\n\t\treturn column.parent.isGroup ? this.getColGroupParentElement(column.parent) : column.getElement();\n\t}\n\t\n\t//layout columns appropriately\n\tlayout(){\t\n\t\tif(this.active && !this.blocked){\n\t\t\t//calculate left columns\n\t\t\tthis.layoutColumnPosition();\n\t\t\t\n\t\t\tthis.reinitializeRows();\n\t\t\t\n\t\t\tthis.layoutCalcRows();\n\t\t}\n\t}\n\t\n\treinitializeRows(){\n\t\tvar visibleRows = this.table.rowManager.getVisibleRows(true);\n\t\tvar otherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));\n\t\t\n\t\totherRows.forEach((row) =>{\n\t\t\trow.deinitialize();\n\t\t});\n\t\t\n\t\tvisibleRows.forEach((row) =>{\n\t\t\tif(row.type === \"row\"){\n\t\t\t\tthis.layoutRow(row);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tlayoutRow(row){\n\t\tif(this.table.options.layout === \"fitDataFill\" && this.rightColumns.length){\n\t\t\tthis.table.rowManager.getTableElement().style.minWidth = \"calc(100% - \" + this.rightMargin + \")\";\n\t\t}\n\t\t\n\t\tthis.leftColumns.forEach((column) => {\n\t\t\tvar cell = row.getCell(column);\n\t\t\t\n\t\t\tif(cell){\n\t\t\t\tthis.layoutElement(cell.getElement(true), column);\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.rightColumns.forEach((column) => {\n\t\t\tvar cell = row.getCell(column);\n\t\t\t\n\t\t\tif(cell){\n\t\t\t\tthis.layoutElement(cell.getElement(true), column);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tlayoutElement(element, column){\n\t\tvar position;\n\t\t\n\t\tif(column.modules.frozen && element){\n\t\t\telement.style.position = \"sticky\";\n\n\t\t\tif(this.table.rtl){\n\t\t\t\tposition = column.modules.frozen.position === \"left\" ? \"right\" : \"left\";\n\t\t\t}else {\n\t\t\t\tposition = column.modules.frozen.position;\n\t\t\t}\n\t\t\n\t\t\telement.style[position] = column.modules.frozen.margin;\n\n\t\t\telement.classList.add(\"tabulator-frozen\");\n\t\t\t\n\t\t\telement.classList.toggle(\"tabulator-frozen-left\",  column.modules.frozen.edge && column.modules.frozen.position === \"left\");\n\t\t\telement.classList.toggle(\"tabulator-frozen-right\", column.modules.frozen.edge && column.modules.frozen.position === \"right\");\n\t\t}\n\t}\n\n\tadjustForScrollbar(width){\n\t\tif(this.rightColumns.length){\n\t\t\tthis.table.columnManager.getContentsElement().style.width = \"calc(100% - \" + width + \"px)\";\n\t\t}\n\t}\n\t\n\t_calcSpace(columns, index){\n\t\tvar width = 0;\n\t\t\n\t\tfor (let i = 0; i < index; i++){\n\t\t\tif(columns[i].visible){\n\t\t\t\twidth += columns[i].getWidth();\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn width;\n\t}\n}\n\nFrozenColumns.moduleName = \"frozenColumns\";\n\nclass FrozenRows extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.topElement = document.createElement(\"div\");\n\t\tthis.rows = [];\n\n\t\t//register component functions\n\t\tthis.registerComponentFunction(\"row\", \"freeze\", this.freezeRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"unfreeze\", this.unfreezeRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"isFrozen\", this.isRowFrozen.bind(this));\n\n\t\t//register table options\n\t\tthis.registerTableOption(\"frozenRowsField\", \"id\"); //field to choose frozen rows by\n\t\tthis.registerTableOption(\"frozenRows\", false); //holder for frozen row identifiers\n\t}\n\n\tinitialize(){\n\t\tvar\tfragment = document.createDocumentFragment();\n\t\t\n\t\tthis.rows = [];\n\n\t\tthis.topElement.classList.add(\"tabulator-frozen-rows-holder\");\n\t\t\n\t\tfragment.appendChild(document.createElement(\"br\"));\n\t\tfragment.appendChild(this.topElement);\n\n\t\t// this.table.columnManager.element.append(this.topElement);\n\t\tthis.table.columnManager.getContentsElement().insertBefore(fragment, this.table.columnManager.headersElement.nextSibling);\n\n\t\tthis.subscribe(\"row-deleting\", this.detachRow.bind(this));\n\t\tthis.subscribe(\"rows-visible\", this.visibleRows.bind(this));\n\n\t\tthis.registerDisplayHandler(this.getRows.bind(this), 10);\n\n\t\tif(this.table.options.frozenRows){\n\t\t\tthis.subscribe(\"data-processed\", this.initializeRows.bind(this));\n\t\t\tthis.subscribe(\"row-added\", this.initializeRow.bind(this));\n\t\t\tthis.subscribe(\"table-redrawing\", this.resizeHolderWidth.bind(this));\n\t\t\tthis.subscribe(\"column-resized\", this.resizeHolderWidth.bind(this));\n\t\t\tthis.subscribe(\"column-show\", this.resizeHolderWidth.bind(this));\n\t\t\tthis.subscribe(\"column-hide\", this.resizeHolderWidth.bind(this));\n\t\t}\n\n\t\tthis.resizeHolderWidth();\n\t}\n\n\tresizeHolderWidth(){\n\t\tthis.topElement.style.minWidth = this.table.columnManager.headersElement.offsetWidth + \"px\";\n\t}\n\n\tinitializeRows(){\n\t\tthis.table.rowManager.getRows().forEach((row) => {\n\t\t\tthis.initializeRow(row);\n\t\t});\n\t}\n\n\tinitializeRow(row){\n\t\tvar frozenRows = this.table.options.frozenRows,\n\t\trowType = typeof frozenRows;\n\n\t\tif(rowType === \"number\"){\n\t\t\tif(row.getPosition() && (row.getPosition() + this.rows.length) <= frozenRows){\n\t\t\t\tthis.freezeRow(row);\n\t\t\t}\n\t\t}else if(rowType === \"function\"){\n\t\t\tif(frozenRows.call(this.table, row.getComponent())){\n\t\t\t\tthis.freezeRow(row);\n\t\t\t}\n\t\t}else if(Array.isArray(frozenRows)){\n\t\t\tif(frozenRows.includes(row.data[this.options(\"frozenRowsField\")])){\n\t\t\t\tthis.freezeRow(row);\n\t\t\t}\n\t\t}\n\t}\n\n\tisRowFrozen(row){\n\t\tvar index = this.rows.indexOf(row);\n\t\treturn index > -1;\n\t}\n\n\tisFrozen(){\n\t\treturn !!this.rows.length;\n\t}\n\n\tvisibleRows(viewable, rows){\n\t\tthis.rows.forEach((row) => {\n\t\t\trows.push(row);\n\t\t});\n\n\t\treturn rows;\n\t}\n\n\t//filter frozen rows out of display data\n\tgetRows(rows){\n\t\tvar output = rows.slice(0);\n\n\t\tthis.rows.forEach(function(row){\n\t\t\tvar index = output.indexOf(row);\n\n\t\t\tif(index > -1){\n\t\t\t\toutput.splice(index, 1);\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\n\tfreezeRow(row){\n\t\tif(!row.modules.frozen){\n\t\t\trow.modules.frozen = true;\n\t\t\tthis.topElement.appendChild(row.getElement());\n\t\t\trow.initialize();\n\t\t\trow.normalizeHeight();\n\t\t\n\t\t\tthis.rows.push(row);\n\n\t\t\tthis.refreshData(false, \"display\");\n\n\t\t\tthis.table.rowManager.adjustTableSize();\n\n\t\t\tthis.styleRows();\n\n\t\t}else {\n\t\t\tconsole.warn(\"Freeze Error - Row is already frozen\");\n\t\t}\n\t}\n\n\tunfreezeRow(row){\n\t\tif(row.modules.frozen){\n\n\t\t\trow.modules.frozen = false;\n\n\t\t\tthis.detachRow(row);\n\n\t\t\tthis.table.rowManager.adjustTableSize();\n\n\t\t\tthis.refreshData(false, \"display\");\n\n\t\t\tif(this.rows.length){\n\t\t\t\tthis.styleRows();\n\t\t\t}\n\n\t\t}else {\n\t\t\tconsole.warn(\"Freeze Error - Row is already unfrozen\");\n\t\t}\n\t}\n\n\tdetachRow(row){\n\t\tvar index = this.rows.indexOf(row);\n\n\t\tif(index > -1){\n\t\t\tvar rowEl = row.getElement();\n\n\t\t\tif(rowEl.parentNode){\n\t\t\t\trowEl.parentNode.removeChild(rowEl);\n\t\t\t}\n\n\t\t\tthis.rows.splice(index, 1);\n\t\t}\n\t}\n\n\tstyleRows(row){\n\t\tthis.rows.forEach((row, i) => {\n\t\t\tthis.table.rowManager.styleRow(row, i);\n\t\t});\n\t}\n}\n\nFrozenRows.moduleName = \"frozenRows\";\n\n//public group object\nclass GroupComponent {\n\tconstructor (group){\n\t\tthis._group = group;\n\t\tthis.type = \"GroupComponent\";\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function(target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t}else {\n\t\t\t\t\treturn target._group.groupManager.table.componentFunctionBinder.handle(\"group\", target._group, name);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tgetKey(){\n\t\treturn this._group.key;\n\t}\n\n\tgetField(){\n\t\treturn this._group.field;\n\t}\n\n\tgetElement(){\n\t\treturn this._group.element;\n\t}\n\n\tgetRows(){\n\t\treturn this._group.getRows(true);\n\t}\n\n\tgetSubGroups(){\n\t\treturn this._group.getSubGroups(true);\n\t}\n\n\tgetParentGroup(){\n\t\treturn this._group.parent ? this._group.parent.getComponent() : false;\n\t}\n\n\tisVisible(){\n\t\treturn this._group.visible;\n\t}\n\n\tshow(){\n\t\tthis._group.show();\n\t}\n\n\thide(){\n\t\tthis._group.hide();\n\t}\n\n\ttoggle(){\n\t\tthis._group.toggleVisibility();\n\t}\n\n\tscrollTo(position, ifVisible){\n\t\treturn this._group.groupManager.table.rowManager.scrollToRow(this._group, position, ifVisible);\n\t}\n\n\t_getSelf(){\n\t\treturn this._group;\n\t}\n\n\tgetTable(){\n\t\treturn this._group.groupManager.table;\n\t}\n}\n\n//Group functions\nclass Group{\n\t\n\tconstructor(groupManager, parent, level, key, field, generator, oldGroup){\n\t\tthis.groupManager = groupManager;\n\t\tthis.parent = parent;\n\t\tthis.key = key;\n\t\tthis.level = level;\n\t\tthis.field = field;\n\t\tthis.hasSubGroups = level < (groupManager.groupIDLookups.length - 1);\n\t\tthis.addRow = this.hasSubGroups ? this._addRowToGroup : this._addRow;\n\t\tthis.type = \"group\"; //type of element\n\t\tthis.old = oldGroup;\n\t\tthis.rows = [];\n\t\tthis.groups = [];\n\t\tthis.groupList = [];\n\t\tthis.generator = generator;\n\t\tthis.element = false;\n\t\tthis.elementContents = false;\n\t\tthis.height = 0;\n\t\tthis.outerHeight = 0;\n\t\tthis.initialized = false;\n\t\tthis.calcs = {};\n\t\tthis.initialized = false;\n\t\tthis.modules = {};\n\t\tthis.arrowElement = false;\n\t\t\n\t\tthis.visible = oldGroup ? oldGroup.visible : (typeof groupManager.startOpen[level] !== \"undefined\" ? groupManager.startOpen[level] : groupManager.startOpen[0]);\n\t\t\n\t\tthis.component = null;\n\t\t\n\t\tthis.createElements();\n\t\tthis.addBindings();\n\t\t\n\t\tthis.createValueGroups();\n\t}\n\t\n\twipe(elementsOnly){\n\t\tif(!elementsOnly){\n\t\t\tif(this.groupList.length){\n\t\t\t\tthis.groupList.forEach(function(group){\n\t\t\t\t\tgroup.wipe();\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tthis.rows.forEach((row) => {\n\t\t\t\t\tif(row.modules){\n\t\t\t\t\t\tdelete row.modules.group;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.element = false;\n\t\tthis.arrowElement = false;\n\t\tthis.elementContents = false;\n\t}\n\t\n\tcreateElements(){\n\t\tvar arrow = document.createElement(\"div\");\n\t\tarrow.classList.add(\"tabulator-arrow\");\n\t\t\n\t\tthis.element = document.createElement(\"div\");\n\t\tthis.element.classList.add(\"tabulator-row\");\n\t\tthis.element.classList.add(\"tabulator-group\");\n\t\tthis.element.classList.add(\"tabulator-group-level-\" + this.level);\n\t\tthis.element.setAttribute(\"role\", \"rowgroup\");\n\t\t\n\t\tthis.arrowElement = document.createElement(\"div\");\n\t\tthis.arrowElement.classList.add(\"tabulator-group-toggle\");\n\t\tthis.arrowElement.appendChild(arrow);\n\t\t\n\t\t//setup movable rows\n\t\tif(this.groupManager.table.options.movableRows !== false && this.groupManager.table.modExists(\"moveRow\")){\n\t\t\tthis.groupManager.table.modules.moveRow.initializeGroupHeader(this);\n\t\t}\n\t}\n\t\n\tcreateValueGroups(){\n\t\tvar level = this.level + 1;\n\t\tif(this.groupManager.allowedValues && this.groupManager.allowedValues[level]){\n\t\t\tthis.groupManager.allowedValues[level].forEach((value) => {\n\t\t\t\tthis._createGroup(value, level);\n\t\t\t});\n\t\t}\n\t}\n\t\n\taddBindings(){\n\t\tvar toggleElement;\n\t\t\n\t\tif(this.groupManager.table.options.groupToggleElement){\n\t\t\ttoggleElement = this.groupManager.table.options.groupToggleElement == \"arrow\" ? this.arrowElement : this.element;\n\t\t\t\n\t\t\ttoggleElement.addEventListener(\"click\", (e) => {\n\t\t\t\tif(this.groupManager.table.options.groupToggleElement === \"arrow\"){\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t}\n\n\t\t\t\t//allow click event to propagate before toggling visibility\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.toggleVisibility();\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\t\n\t_createGroup(groupID, level){\n\t\tvar groupKey = level + \"_\" + groupID;\n\t\tvar group = new Group(this.groupManager, this, level, groupID,  this.groupManager.groupIDLookups[level].field, this.groupManager.headerGenerator[level] || this.groupManager.headerGenerator[0], this.old ? this.old.groups[groupKey] : false);\n\t\t\n\t\tthis.groups[groupKey] = group;\n\t\tthis.groupList.push(group);\n\t}\n\t\n\t_addRowToGroup(row){\n\t\t\n\t\tvar level = this.level + 1;\n\t\t\n\t\tif(this.hasSubGroups){\n\t\t\tvar groupID = this.groupManager.groupIDLookups[level].func(row.getData()),\n\t\t\tgroupKey = level + \"_\" + groupID;\n\t\t\t\n\t\t\tif(this.groupManager.allowedValues && this.groupManager.allowedValues[level]){\n\t\t\t\tif(this.groups[groupKey]){\n\t\t\t\t\tthis.groups[groupKey].addRow(row);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(!this.groups[groupKey]){\n\t\t\t\t\tthis._createGroup(groupID, level);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.groups[groupKey].addRow(row);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_addRow(row){\n\t\tthis.rows.push(row);\n\t\trow.modules.group = this;\n\t}\n\t\n\tinsertRow(row, to, after){\n\t\tvar data = this.conformRowData({});\n\t\t\n\t\trow.updateData(data);\n\t\t\n\t\tvar toIndex = this.rows.indexOf(to);\n\t\t\n\t\tif(toIndex > -1){\n\t\t\tif(after){\n\t\t\t\tthis.rows.splice(toIndex+1, 0, row);\n\t\t\t}else {\n\t\t\t\tthis.rows.splice(toIndex, 0, row);\n\t\t\t}\n\t\t}else {\n\t\t\tif(after){\n\t\t\t\tthis.rows.push(row);\n\t\t\t}else {\n\t\t\t\tthis.rows.unshift(row);\n\t\t\t}\n\t\t}\n\t\t\n\t\trow.modules.group = this;\n\t\t\n\t\t// this.generateGroupHeaderContents();\n\t\t\n\t\tif(this.groupManager.table.modExists(\"columnCalcs\") && this.groupManager.table.options.columnCalcs != \"table\"){\n\t\t\tthis.groupManager.table.modules.columnCalcs.recalcGroup(this);\n\t\t}\n\t\t\n\t\tthis.groupManager.updateGroupRows(true);\n\t}\n\t\n\tscrollHeader(left){\n\t\tif(this.arrowElement){\n\t\t\tthis.arrowElement.style.marginLeft = left;\n\t\t\t\n\t\t\tthis.groupList.forEach(function(child){\n\t\t\t\tchild.scrollHeader(left);\n\t\t\t});\n\t\t}\n\t}\n\t\n\tgetRowIndex(row){}\n\t\n\t//update row data to match grouping constraints\n\tconformRowData(data){\n\t\tif(this.field){\n\t\t\tdata[this.field] = this.key;\n\t\t}else {\n\t\t\tconsole.warn(\"Data Conforming Error - Cannot conform row data to match new group as groupBy is a function\");\n\t\t}\n\t\t\n\t\tif(this.parent){\n\t\t\tdata = this.parent.conformRowData(data);\n\t\t}\n\t\t\n\t\treturn data;\n\t}\n\t\n\tremoveRow(row){\n\t\tvar index = this.rows.indexOf(row);\n\t\tvar el = row.getElement();\n\t\t\n\t\tif(index > -1){\n\t\t\tthis.rows.splice(index, 1);\n\t\t}\n\t\t\n\t\tif(!this.groupManager.table.options.groupValues && !this.rows.length){\n\t\t\tif(this.parent){\n\t\t\t\tthis.parent.removeGroup(this);\n\t\t\t}else {\n\t\t\t\tthis.groupManager.removeGroup(this);\n\t\t\t}\t\t\n\t\t\t\n\t\t\tthis.groupManager.updateGroupRows(true);\n\t\t\t\n\t\t}else {\n\t\t\t\n\t\t\tif(el.parentNode){\n\t\t\t\tel.parentNode.removeChild(el);\n\t\t\t}\n\t\t\t\n\t\t\tif(!this.groupManager.blockRedraw){\n\t\t\t\tthis.generateGroupHeaderContents();\n\t\t\t\t\n\t\t\t\tif(this.groupManager.table.modExists(\"columnCalcs\") && this.groupManager.table.options.columnCalcs != \"table\"){\n\t\t\t\t\tthis.groupManager.table.modules.columnCalcs.recalcGroup(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t}\n\t}\n\t\n\tremoveGroup(group){\n\t\tvar groupKey = group.level + \"_\" + group.key,\n\t\tindex;\n\t\t\n\t\tif(this.groups[groupKey]){\n\t\t\tdelete this.groups[groupKey];\n\t\t\t\n\t\t\tindex = this.groupList.indexOf(group);\n\t\t\t\n\t\t\tif(index > -1){\n\t\t\t\tthis.groupList.splice(index, 1);\n\t\t\t}\n\t\t\t\n\t\t\tif(!this.groupList.length){\n\t\t\t\tif(this.parent){\n\t\t\t\t\tthis.parent.removeGroup(this);\n\t\t\t\t}else {\n\t\t\t\t\tthis.groupManager.removeGroup(this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tgetHeadersAndRows(){\n\t\tvar output = [];\n\t\t\n\t\toutput.push(this);\n\t\t\n\t\tthis._visSet();\n\t\t\n\t\t\n\t\tif(this.calcs.top){\n\t\t\tthis.calcs.top.detachElement();\n\t\t\tthis.calcs.top.deleteCells();\n\t\t}\n\t\t\n\t\tif(this.calcs.bottom){\n\t\t\tthis.calcs.bottom.detachElement();\n\t\t\tthis.calcs.bottom.deleteCells();\n\t\t}\n\t\t\n\t\t\n\t\t\n\t\tif(this.visible){\n\t\t\tif(this.groupList.length){\n\t\t\t\tthis.groupList.forEach(function(group){\n\t\t\t\t\toutput = output.concat(group.getHeadersAndRows());\n\t\t\t\t});\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tif(this.groupManager.table.options.columnCalcs != \"table\" && this.groupManager.table.modExists(\"columnCalcs\") && this.groupManager.table.modules.columnCalcs.hasTopCalcs()){\n\t\t\t\t\tthis.calcs.top = this.groupManager.table.modules.columnCalcs.generateTopRow(this.rows);\n\t\t\t\t\toutput.push(this.calcs.top);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toutput = output.concat(this.rows);\n\t\t\t\t\n\t\t\t\tif(this.groupManager.table.options.columnCalcs != \"table\" &&  this.groupManager.table.modExists(\"columnCalcs\") && this.groupManager.table.modules.columnCalcs.hasBottomCalcs()){\n\t\t\t\t\tthis.calcs.bottom = this.groupManager.table.modules.columnCalcs.generateBottomRow(this.rows);\n\t\t\t\t\toutput.push(this.calcs.bottom);\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tif(!this.groupList.length && this.groupManager.table.options.columnCalcs != \"table\"){\n\t\t\t\t\n\t\t\t\tif(this.groupManager.table.modExists(\"columnCalcs\")){\n\t\t\t\t\tif(this.groupManager.table.modules.columnCalcs.hasTopCalcs()){\n\t\t\t\t\t\tif(this.groupManager.table.options.groupClosedShowCalcs){\n\t\t\t\t\t\t\tthis.calcs.top = this.groupManager.table.modules.columnCalcs.generateTopRow(this.rows);\n\t\t\t\t\t\t\toutput.push(this.calcs.top);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif(this.groupManager.table.modules.columnCalcs.hasBottomCalcs()){\t\t\t\t\t\t\n\t\t\t\t\t\tif(this.groupManager.table.options.groupClosedShowCalcs){\n\t\t\t\t\t\t\tthis.calcs.bottom = this.groupManager.table.modules.columnCalcs.generateBottomRow(this.rows);\n\t\t\t\t\t\t\toutput.push(this.calcs.bottom);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetData(visible, transform){\n\t\tvar output = [];\n\t\t\n\t\tthis._visSet();\n\t\t\n\t\tif(!visible || (visible && this.visible)){\n\t\t\tthis.rows.forEach((row) => {\n\t\t\t\toutput.push(row.getData(transform || \"data\"));\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetRowCount(){\n\t\tvar count = 0;\n\t\t\n\t\tif(this.groupList.length){\n\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\tcount += group.getRowCount();\n\t\t\t});\n\t\t}else {\n\t\t\tcount = this.rows.length;\n\t\t}\n\t\treturn count;\n\t}\n\n\t\n\ttoggleVisibility(){\n\t\tif(this.visible){\n\t\t\tthis.hide();\n\t\t}else {\n\t\t\tthis.show();\n\t\t}\n\t}\n\t\n\thide(){\n\t\tthis.visible = false;\n\t\t\n\t\tif(this.groupManager.table.rowManager.getRenderMode() == \"basic\" && !this.groupManager.table.options.pagination){\n\t\t\t\n\t\t\tthis.element.classList.remove(\"tabulator-group-visible\");\n\t\t\t\n\t\t\tif(this.groupList.length){\n\t\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\t\t\n\t\t\t\t\tvar rows = group.getHeadersAndRows();\n\t\t\t\t\t\n\t\t\t\t\trows.forEach((row) => {\n\t\t\t\t\t\trow.detachElement();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tthis.rows.forEach((row) => {\n\t\t\t\t\tvar rowEl = row.getElement();\n\t\t\t\t\trowEl.parentNode.removeChild(rowEl);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis.groupManager.updateGroupRows(true);\n\t\t\t\n\t\t}else {\n\t\t\tthis.groupManager.updateGroupRows(true);\n\t\t}\n\t\t\n\t\tthis.groupManager.table.externalEvents.dispatch(\"groupVisibilityChanged\", this.getComponent(), false);\n\t}\n\t\n\tshow(){\n\t\tthis.visible = true;\n\t\t\n\t\tif(this.groupManager.table.rowManager.getRenderMode() == \"basic\" && !this.groupManager.table.options.pagination){\n\t\t\t\n\t\t\tthis.element.classList.add(\"tabulator-group-visible\");\n\t\t\t\n\t\t\tvar prev = this.generateElement();\n\t\t\t\n\t\t\tif(this.groupList.length){\n\t\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\t\tvar rows = group.getHeadersAndRows();\n\t\t\t\t\t\n\t\t\t\t\trows.forEach((row) => {\n\t\t\t\t\t\tvar rowEl = row.getElement();\n\t\t\t\t\t\tprev.parentNode.insertBefore(rowEl, prev.nextSibling);\n\t\t\t\t\t\trow.initialize();\n\t\t\t\t\t\tprev = rowEl;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tthis.rows.forEach((row) => {\n\t\t\t\t\tvar rowEl = row.getElement();\n\t\t\t\t\tprev.parentNode.insertBefore(rowEl, prev.nextSibling);\n\t\t\t\t\trow.initialize();\n\t\t\t\t\tprev = rowEl;\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tthis.groupManager.updateGroupRows(true);\n\t\t}else {\n\t\t\tthis.groupManager.updateGroupRows(true);\n\t\t}\n\t\t\n\t\tthis.groupManager.table.externalEvents.dispatch(\"groupVisibilityChanged\", this.getComponent(), true);\n\t}\n\t\n\t_visSet(){\n\t\tvar data = [];\n\t\t\n\t\tif(typeof this.visible == \"function\"){\n\t\t\t\n\t\t\tthis.rows.forEach(function(row){\n\t\t\t\tdata.push(row.getData());\n\t\t\t});\n\t\t\t\n\t\t\tthis.visible = this.visible(this.key, this.getRowCount(), data, this.getComponent());\n\t\t}\n\t}\n\t\n\tgetRowGroup(row){\n\t\tvar match = false;\n\t\tif(this.groupList.length){\n\t\t\tthis.groupList.forEach(function(group){\n\t\t\t\tvar result = group.getRowGroup(row);\n\t\t\t\t\n\t\t\t\tif(result){\n\t\t\t\t\tmatch = result;\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\tif(this.rows.find(function(item){\n\t\t\t\treturn item === row;\n\t\t\t})){\n\t\t\t\tmatch = this;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn match;\n\t}\n\t\n\tgetSubGroups(component){\n\t\tvar output = [];\n\t\t\n\t\tthis.groupList.forEach(function(child){\n\t\t\toutput.push(component ? child.getComponent() : child);\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetRows(component, includeChildren){\n\t\tvar output = [];\n\t\t\n\t\tif(includeChildren && this.groupList.length){\n\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\toutput = output.concat(group.getRows(component, includeChildren));\n\t\t\t});\n\t\t}else {\n\t\t\tthis.rows.forEach(function(row){\n\t\t\t\toutput.push(component ? row.getComponent() : row);\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgenerateGroupHeaderContents(){\n\t\tvar data = [];\n\t\t\n\t\tvar rows = this.getRows(false, true);\n\t\t\n\t\trows.forEach(function(row){\n\t\t\tdata.push(row.getData());\n\t\t});\n\t\t\n\t\tthis.elementContents = this.generator(this.key, this.getRowCount(), data, this.getComponent());\n\t\t\n\t\twhile(this.element.firstChild) this.element.removeChild(this.element.firstChild);\n\t\t\n\t\tif(typeof this.elementContents === \"string\"){\n\t\t\tthis.element.innerHTML = this.elementContents;\n\t\t}else {\n\t\t\tthis.element.appendChild(this.elementContents);\n\t\t}\n\t\t\n\t\tthis.element.insertBefore(this.arrowElement, this.element.firstChild);\n\t}\n\t\n\tgetPath(path = []) {\n\t\tpath.unshift(this.key);\n\t\tif(this.parent) {\n\t\t\tthis.parent.getPath(path);\n\t\t}\n\t\treturn path;\n\t}\n\t\n\t////////////// Standard Row Functions //////////////\n\t\n\tgetElement(){\n\t\treturn this.elementContents ? this.element : this.generateElement();\n\t}\n\t\n\tgenerateElement(){\n\t\tthis.addBindings = false;\n\t\t\n\t\tthis._visSet();\n\t\t\n\t\tif(this.visible){\n\t\t\tthis.element.classList.add(\"tabulator-group-visible\");\n\t\t}else {\n\t\t\tthis.element.classList.remove(\"tabulator-group-visible\");\n\t\t}\n\t\t\n\t\tfor(var i = 0; i < this.element.childNodes.length; ++i){\n\t\t\tthis.element.childNodes[i].parentNode.removeChild(this.element.childNodes[i]);\n\t\t}\n\t\t\n\t\tthis.generateGroupHeaderContents();\n\t\t\n\t\t// this.addBindings();\n\t\t\n\t\treturn this.element;\n\t}\n\t\n\tdetachElement(){\n\t\tif (this.element && this.element.parentNode){\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n\t}\n\t\n\t//normalize the height of elements in the row\n\tnormalizeHeight(){\n\t\tthis.setHeight(this.element.clientHeight);\n\t}\n\t\n\tinitialize(force){\n\t\tif(!this.initialized || force){\n\t\t\tthis.normalizeHeight();\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\t\n\treinitialize(){\n\t\tthis.initialized = false;\n\t\tthis.height = 0;\n\t\t\n\t\tif(Helpers.elVisible(this.element)){\n\t\t\tthis.initialize(true);\n\t\t}\n\t}\n\t\n\tsetHeight(height){\n\t\tif(this.height != height){\n\t\t\tthis.height = height;\n\t\t\tthis.outerHeight = this.element.offsetHeight;\n\t\t}\n\t}\n\t\n\t//return rows outer height\n\tgetHeight(){\n\t\treturn this.outerHeight;\n\t}\n\t\n\tgetGroup(){\n\t\treturn this;\n\t}\n\t\n\treinitializeHeight(){}\n\t\n\tcalcHeight(){}\n\t\n\tsetCellHeight(){}\n\t\n\tclearCellHeight(){}\n\t\n\tdeinitializeHeight(){}\n\n\trendered(){}\n\t\n\t//////////////// Object Generation /////////////////\n\tgetComponent(){\n\t\tif(!this.component){\n\t\t\tthis.component = new GroupComponent(this);\n\t\t}\n\t\t\n\t\treturn this.component;\n\t}\n}\n\nclass GroupRows extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.groupIDLookups = false; //enable table grouping and set field to group by\n\t\tthis.startOpen = [function(){return false;}]; //starting state of group\n\t\tthis.headerGenerator = [function(){return \"\";}];\n\t\tthis.groupList = []; //ordered list of groups\n\t\tthis.allowedValues = false;\n\t\tthis.groups = {}; //hold row groups\n\t\t\n\t\tthis.displayHandler = this.getRows.bind(this);\n\n\t\tthis.blockRedraw = false;\n\t\t\n\t\t//register table options\n\t\tthis.registerTableOption(\"groupBy\", false); //enable table grouping and set field to group by\n\t\tthis.registerTableOption(\"groupStartOpen\", true); //starting state of group\n\t\tthis.registerTableOption(\"groupValues\", false);\n\t\tthis.registerTableOption(\"groupUpdateOnCellEdit\", false);\n\t\tthis.registerTableOption(\"groupHeader\", false); //header generation function\n\t\tthis.registerTableOption(\"groupHeaderPrint\", null);\n\t\tthis.registerTableOption(\"groupHeaderClipboard\", null);\n\t\tthis.registerTableOption(\"groupHeaderHtmlOutput\", null);\n\t\tthis.registerTableOption(\"groupHeaderDownload\", null);\n\t\tthis.registerTableOption(\"groupToggleElement\", \"arrow\");\n\t\tthis.registerTableOption(\"groupClosedShowCalcs\", false);\n\t\t\n\t\t//register table functions\n\t\tthis.registerTableFunction(\"setGroupBy\", this.setGroupBy.bind(this));\n\t\tthis.registerTableFunction(\"setGroupValues\", this.setGroupValues.bind(this));\n\t\tthis.registerTableFunction(\"setGroupStartOpen\", this.setGroupStartOpen.bind(this));\n\t\tthis.registerTableFunction(\"setGroupHeader\", this.setGroupHeader.bind(this));\n\t\tthis.registerTableFunction(\"getGroups\", this.userGetGroups.bind(this));\n\t\tthis.registerTableFunction(\"getGroupedData\", this.userGetGroupedData.bind(this));\n\t\t\n\t\t//register component functions\n\t\tthis.registerComponentFunction(\"row\", \"getGroup\", this.rowGetGroup.bind(this));\n\t}\n\t\n\t//initialize group configuration\n\tinitialize(){\n\t\tthis.subscribe(\"table-destroy\", this._blockRedrawing.bind(this));\n\t\tthis.subscribe(\"rows-wipe\", this._blockRedrawing.bind(this));\n\t\tthis.subscribe(\"rows-wiped\", this._restore_redrawing.bind(this));\n\n\t\tif(this.table.options.groupBy){\n\t\t\tif(this.table.options.groupUpdateOnCellEdit){\n\t\t\t\tthis.subscribe(\"cell-value-updated\", this.cellUpdated.bind(this));\n\t\t\t\tthis.subscribe(\"row-data-changed\", this.reassignRowToGroup.bind(this), 0);\n\t\t\t}\n\t\t\t\n\t\t\tthis.subscribe(\"table-built\", this.configureGroupSetup.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"row-deleting\", this.rowDeleting.bind(this));\n\t\t\tthis.subscribe(\"row-deleted\", this.rowsUpdated.bind(this));\n\t\t\tthis.subscribe(\"scroll-horizontal\", this.scrollHeaders.bind(this));\n\t\t\tthis.subscribe(\"rows-wipe\", this.wipe.bind(this));\n\t\t\tthis.subscribe(\"rows-added\", this.rowsUpdated.bind(this));\n\t\t\tthis.subscribe(\"row-moving\", this.rowMoving.bind(this));\n\t\t\tthis.subscribe(\"row-adding-index\", this.rowAddingIndex.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"rows-sample\", this.rowSample.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"render-virtual-fill\", this.virtualRenderFill.bind(this));\n\t\t\t\n\t\t\tthis.registerDisplayHandler(this.displayHandler, 20);\n\t\t\t\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\t\n\t_blockRedrawing(){\n\t\tthis.blockRedraw = true;\n\t}\n\n\t_restore_redrawing(){\n\t\tthis.blockRedraw = false;\n\t}\n\n\tconfigureGroupSetup(){\n\t\tif(this.table.options.groupBy){\n\t\t\tvar groupBy = this.table.options.groupBy,\n\t\t\tstartOpen = this.table.options.groupStartOpen,\n\t\t\tgroupHeader = this.table.options.groupHeader;\n\t\t\t\n\t\t\tthis.allowedValues = this.table.options.groupValues;\n\t\t\t\n\t\t\tif(Array.isArray(groupBy) && Array.isArray(groupHeader) && groupBy.length > groupHeader.length){\n\t\t\t\tconsole.warn(\"Error creating group headers, groupHeader array is shorter than groupBy array\");\n\t\t\t}\n\t\t\t\n\t\t\tthis.headerGenerator = [function(){return \"\";}];\n\t\t\tthis.startOpen = [function(){return false;}]; //starting state of group\n\t\t\t\n\t\t\tthis.langBind(\"groups|item\", (langValue, lang) => {\n\t\t\t\tthis.headerGenerator[0] = (value, count, data) => { //header layout function\n\t\t\t\t\treturn (typeof value === \"undefined\" ? \"\" : value) + \"<span>(\" + count + \" \" + ((count === 1) ? langValue : lang.groups.items) + \")</span>\";\n\t\t\t\t};\n\t\t\t});\n\t\t\t\n\t\t\tthis.groupIDLookups = [];\n\t\t\t\n\t\t\tif(groupBy){\n\t\t\t\tif(this.table.modExists(\"columnCalcs\") && this.table.options.columnCalcs != \"table\" && this.table.options.columnCalcs != \"both\"){\n\t\t\t\t\tthis.table.modules.columnCalcs.removeCalcs();\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(this.table.modExists(\"columnCalcs\") && this.table.options.columnCalcs != \"group\"){\n\t\t\t\t\t\n\t\t\t\t\tvar cols = this.table.columnManager.getRealColumns();\n\t\t\t\t\t\n\t\t\t\t\tcols.forEach((col) => {\n\t\t\t\t\t\tif(col.definition.topCalc){\n\t\t\t\t\t\t\tthis.table.modules.columnCalcs.initializeTopRow();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(col.definition.bottomCalc){\n\t\t\t\t\t\t\tthis.table.modules.columnCalcs.initializeBottomRow();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(!Array.isArray(groupBy)){\n\t\t\t\tgroupBy = [groupBy];\n\t\t\t}\n\t\t\t\n\t\t\tgroupBy.forEach((group, i) => {\n\t\t\t\tvar lookupFunc, column;\n\t\t\t\t\n\t\t\t\tif(typeof group == \"function\"){\n\t\t\t\t\tlookupFunc = group;\n\t\t\t\t}else {\n\t\t\t\t\tcolumn = this.table.columnManager.getColumnByField(group);\n\t\t\t\t\t\n\t\t\t\t\tif(column){\n\t\t\t\t\t\tlookupFunc = function(data){\n\t\t\t\t\t\t\treturn column.getFieldValue(data);\n\t\t\t\t\t\t};\n\t\t\t\t\t}else {\n\t\t\t\t\t\tlookupFunc = function(data){\n\t\t\t\t\t\t\treturn data[group];\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.groupIDLookups.push({\n\t\t\t\t\tfield: typeof group === \"function\" ? false : group,\n\t\t\t\t\tfunc:lookupFunc,\n\t\t\t\t\tvalues:this.allowedValues ? this.allowedValues[i] : false,\n\t\t\t\t});\n\t\t\t});\n\t\t\t\n\t\t\tif(startOpen){\n\t\t\t\tif(!Array.isArray(startOpen)){\n\t\t\t\t\tstartOpen = [startOpen];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tstartOpen.forEach((level) => {\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.startOpen = startOpen;\n\t\t\t}\n\t\t\t\n\t\t\tif(groupHeader){\n\t\t\t\tthis.headerGenerator = Array.isArray(groupHeader) ? groupHeader : [groupHeader];\n\t\t\t}\n\t\t}else {\n\t\t\tthis.groupList = [];\n\t\t\tthis.groups = {};\n\t\t}\n\t}\n\t\n\trowSample(rows, prevValue){\n\t\tif(this.table.options.groupBy){\n\t\t\tvar group = this.getGroups(false)[0];\n\t\t\t\n\t\t\tprevValue.push(group.getRows(false)[0]);\n\t\t}\n\t\t\n\t\treturn prevValue;\n\t}\n\t\n\tvirtualRenderFill(){\n\t\tvar el = this.table.rowManager.tableElement;\n\t\tvar rows = this.table.rowManager.getVisibleRows();\n\t\t\n\t\tif(this.table.options.groupBy){\n\t\t\trows = rows.filter((row) => {\n\t\t\t\treturn row.type !== \"group\";\n\t\t\t});\n\t\t\t\n\t\t\tel.style.minWidth = !rows.length ? this.table.columnManager.getWidth() + \"px\" : \"\";\n\t\t}else {\n\t\t\treturn rows;\n\t\t}\n\t}\n\t\n\trowAddingIndex(row, index, top){\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.assignRowToGroup(row);\n\t\t\t\n\t\t\tvar groupRows = row.modules.group.rows;\n\t\t\t\n\t\t\tif(groupRows.length > 1){\n\t\t\t\tif(!index || (index && groupRows.indexOf(index) == -1)){\n\t\t\t\t\tif(top){\n\t\t\t\t\t\tif(groupRows[0] !== row){\n\t\t\t\t\t\t\tindex = groupRows[0];\n\t\t\t\t\t\t\tthis.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(groupRows[groupRows.length -1] !== row){\n\t\t\t\t\t\t\tindex = groupRows[groupRows.length -1];\n\t\t\t\t\t\t\tthis.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tthis.table.rowManager.moveRowInArray(row.modules.group.rows, row, index, !top);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn index;\n\t\t}\n\t}\n\t\n\ttrackChanges(){\n\t\tthis.dispatch(\"group-changed\");\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\t\n\tsetGroupBy(groups){\n\t\tthis.table.options.groupBy = groups;\n\t\t\n\t\tif(!this.initialized){\n\t\t\tthis.initialize();\n\t\t}\n\t\t\n\t\tthis.configureGroupSetup();\n\n\t\tif(!groups && this.table.modExists(\"columnCalcs\") && this.table.options.columnCalcs === true){\n\t\t\tthis.table.modules.columnCalcs.reinitializeCalcs();\n\t\t}\n\t\t\n\t\tthis.refreshData();\n\t\t\n\t\tthis.trackChanges();\n\t}\n\t\n\tsetGroupValues(groupValues){\n\t\tthis.table.options.groupValues = groupValues;\n\t\tthis.configureGroupSetup();\n\t\tthis.refreshData();\n\t\t\n\t\tthis.trackChanges();\n\t}\n\t\n\tsetGroupStartOpen(values){\n\t\tthis.table.options.groupStartOpen = values;\n\t\tthis.configureGroupSetup();\n\t\t\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.refreshData();\n\t\t\t\n\t\t\tthis.trackChanges();\n\t\t}else {\n\t\t\tconsole.warn(\"Grouping Update - cant refresh view, no groups have been set\");\n\t\t}\n\t}\n\t\n\tsetGroupHeader(values){\n\t\tthis.table.options.groupHeader = values;\n\t\tthis.configureGroupSetup();\n\t\t\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.refreshData();\n\t\t\t\n\t\t\tthis.trackChanges();\n\t\t}else {\n\t\t\tconsole.warn(\"Grouping Update - cant refresh view, no groups have been set\");\n\t\t}\n\t}\n\t\n\tuserGetGroups(values){\n\t\treturn this.getGroups(true);\n\t}\n\t\n\t// get grouped table data in the same format as getData()\n\tuserGetGroupedData(){\n\t\treturn this.table.options.groupBy ? this.getGroupedData() : this.getData();\n\t}\n\t\n\t\n\t///////////////////////////////////////\n\t///////// Component Functions /////////\n\t///////////////////////////////////////\n\t\n\trowGetGroup(row){\n\t\treturn row.modules.group ? row.modules.group.getComponent() : false;\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\trowMoving(from, to, after){\n\t\tif(this.table.options.groupBy){\n\t\t\tif(!after && to instanceof Group){\n\t\t\t\tto = this.table.rowManager.prevDisplayRow(from) || to;\n\t\t\t}\n\t\t\t\n\t\t\tvar toGroup = to instanceof Group ? to : to.modules.group;\n\t\t\tvar fromGroup = from instanceof Group ? from : from.modules.group;\n\t\t\t\n\t\t\tif(toGroup === fromGroup){\n\t\t\t\tthis.table.rowManager.moveRowInArray(toGroup.rows, from, to, after);\n\t\t\t}else {\n\t\t\t\tif(fromGroup){\n\t\t\t\t\tfromGroup.removeRow(from);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\ttoGroup.insertRow(from, to, after);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t\n\trowDeleting(row){\n\t\t//remove from group\n\t\tif(this.table.options.groupBy && row.modules.group){\n\t\t\trow.modules.group.removeRow(row);\n\t\t}\n\t}\n\t\n\trowsUpdated(row){\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.updateGroupRows(true);\n\t\t}\t\n\t}\n\t\n\tcellUpdated(cell){\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.reassignRowToGroup(cell.row);\n\t\t}\n\t}\n\t\n\t//return appropriate rows with group headers\n\tgetRows(rows){\n\t\tif(this.table.options.groupBy && this.groupIDLookups.length){\n\t\t\t\n\t\t\tthis.dispatchExternal(\"dataGrouping\");\n\t\t\t\n\t\t\tthis.generateGroups(rows);\n\t\t\t\n\t\t\tif(this.subscribedExternal(\"dataGrouped\")){\n\t\t\t\tthis.dispatchExternal(\"dataGrouped\", this.getGroups(true));\n\t\t\t}\n\t\t\t\n\t\t\treturn this.updateGroupRows();\n\t\t\t\n\t\t}else {\n\t\t\treturn rows.slice(0);\n\t\t}\n\t}\n\t\n\tgetGroups(component){\n\t\tvar groupComponents = [];\n\t\t\n\t\tthis.groupList.forEach(function(group){\n\t\t\tgroupComponents.push(component ? group.getComponent() : group);\n\t\t});\n\t\t\n\t\treturn groupComponents;\n\t}\n\t\n\tgetChildGroups(group){\n\t\tvar groupComponents = [];\n\t\t\n\t\tif(!group){\n\t\t\tgroup = this;\n\t\t}\n\t\t\n\t\tgroup.groupList.forEach((child) => {\n\t\t\tif(child.groupList.length){\n\t\t\t\tgroupComponents = groupComponents.concat(this.getChildGroups(child));\n\t\t\t}else {\n\t\t\t\tgroupComponents.push(child);\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn groupComponents;\n\t}\n\t\n\twipe(){\n\t\tif(this.table.options.groupBy){\n\t\t\tthis.groupList.forEach(function(group){\n\t\t\t\tgroup.wipe();\n\t\t\t});\n\t\t\t\n\t\t\tthis.groupList = [];\n\t\t\tthis.groups = {};\n\t\t}\n\t}\n\t\n\tpullGroupListData(groupList) {\n\t\tvar groupListData = [];\n\t\t\n\t\tgroupList.forEach((group) => {\n\t\t\tvar groupHeader = {};\n\t\t\tgroupHeader.level = 0;\n\t\t\tgroupHeader.rowCount = 0;\n\t\t\tgroupHeader.headerContent = \"\";\n\t\t\tvar childData = [];\n\t\t\t\n\t\t\tif (group.hasSubGroups) {\n\t\t\t\tchildData = this.pullGroupListData(group.groupList);\n\t\t\t\t\n\t\t\t\tgroupHeader.level = group.level;\n\t\t\t\tgroupHeader.rowCount = childData.length - group.groupList.length; // data length minus number of sub-headers\n\t\t\t\tgroupHeader.headerContent = group.generator(group.key, groupHeader.rowCount, group.rows, group);\n\t\t\t\t\n\t\t\t\tgroupListData.push(groupHeader);\n\t\t\t\tgroupListData = groupListData.concat(childData);\n\t\t\t}\n\t\t\t\n\t\t\telse {\n\t\t\t\tgroupHeader.level = group.level;\n\t\t\t\tgroupHeader.headerContent = group.generator(group.key, group.rows.length, group.rows, group);\n\t\t\t\tgroupHeader.rowCount = group.getRows().length;\n\t\t\t\t\n\t\t\t\tgroupListData.push(groupHeader);\n\t\t\t\t\n\t\t\t\tgroup.getRows().forEach((row) => {\n\t\t\t\t\tgroupListData.push(row.getData(\"data\"));\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn groupListData;\n\t}\n\t\n\tgetGroupedData(){\n\t\t\n\t\treturn this.pullGroupListData(this.groupList);\n\t}\n\t\n\tgetRowGroup(row){\n\t\tvar match = false;\n\t\t\n\t\tif(this.options(\"dataTree\")){\n\t\t\trow = this.table.modules.dataTree.getTreeParentRoot(row);\n\t\t}\n\t\t\n\t\tthis.groupList.forEach((group) => {\n\t\t\tvar result = group.getRowGroup(row);\n\t\t\t\n\t\t\tif(result){\n\t\t\t\tmatch = result;\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn match;\n\t}\n\t\n\tcountGroups(){\n\t\treturn this.groupList.length;\n\t}\n\t\n\tgenerateGroups(rows){\n\t\tvar oldGroups = this.groups;\n\t\t\n\t\tthis.groups = {};\n\t\tthis.groupList = [];\n\t\t\n\t\tif(this.allowedValues && this.allowedValues[0]){\n\t\t\tthis.allowedValues[0].forEach((value) => {\n\t\t\t\tthis.createGroup(value, 0, oldGroups);\n\t\t\t});\n\t\t\t\n\t\t\trows.forEach((row) => {\n\t\t\t\tthis.assignRowToExistingGroup(row, oldGroups);\n\t\t\t});\n\t\t}else {\n\t\t\trows.forEach((row) => {\n\t\t\t\tthis.assignRowToGroup(row, oldGroups);\n\t\t\t});\n\t\t}\n\t\t\n\t\tObject.values(oldGroups).forEach((group) => {\n\t\t\tgroup.wipe(true);\n\t\t});\t\n\t}\n\t\n\t\n\tcreateGroup(groupID, level, oldGroups){\n\t\tvar groupKey = level + \"_\" + groupID,\n\t\tgroup;\n\t\t\n\t\toldGroups = oldGroups || [];\n\t\t\n\t\tgroup = new Group(this, false, level, groupID, this.groupIDLookups[0].field, this.headerGenerator[0], oldGroups[groupKey]);\n\t\t\n\t\tthis.groups[groupKey] = group;\n\t\tthis.groupList.push(group);\n\t}\n\t\n\tassignRowToExistingGroup(row, oldGroups){\n\t\tvar groupID = this.groupIDLookups[0].func(row.getData()),\n\t\tgroupKey = \"0_\" + groupID;\n\t\t\n\t\tif(this.groups[groupKey]){\n\t\t\tthis.groups[groupKey].addRow(row);\n\t\t}\n\t}\n\t\n\tassignRowToGroup(row, oldGroups){\n\t\tvar groupID = this.groupIDLookups[0].func(row.getData()),\n\t\tnewGroupNeeded = !this.groups[\"0_\" + groupID];\n\t\t\n\t\tif(newGroupNeeded){\n\t\t\tthis.createGroup(groupID, 0, oldGroups);\n\t\t}\n\t\t\n\t\tthis.groups[\"0_\" + groupID].addRow(row);\n\t\t\n\t\treturn !newGroupNeeded;\n\t}\n\t\n\treassignRowToGroup(row){\n\t\tif(row.type === \"row\"){\n\t\t\tvar oldRowGroup = row.modules.group,\n\t\t\toldGroupPath = oldRowGroup.getPath(),\n\t\t\tnewGroupPath = this.getExpectedPath(row),\n\t\t\tsamePath;\n\t\t\t\n\t\t\t// figure out if new group path is the same as old group path\n\t\t\tsamePath = (oldGroupPath.length == newGroupPath.length) && oldGroupPath.every((element, index) => {\n\t\t\t\treturn element === newGroupPath[index];\n\t\t\t});\n\t\t\t\n\t\t\t// refresh if they new path and old path aren't the same (aka the row's groupings have changed)\n\t\t\tif(!samePath) {\n\t\t\t\toldRowGroup.removeRow(row);\n\t\t\t\tthis.assignRowToGroup(row, this.groups);\n\t\t\t\tthis.refreshData(true);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tgetExpectedPath(row) {\n\t\tvar groupPath = [], rowData = row.getData();\n\t\t\n\t\tthis.groupIDLookups.forEach((groupId) => {\n\t\t\tgroupPath.push(groupId.func(rowData));\n\t\t});\n\t\t\n\t\treturn groupPath;\n\t}\n\t\n\tupdateGroupRows(force){\n\t\tvar output = [];\n\n\t\tif(!this.blockRedraw){\n\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\toutput = output.concat(group.getHeadersAndRows());\n\t\t\t});\n\t\t\t\n\t\t\tif(force){\n\t\t\t\tthis.refreshData(true);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tscrollHeaders(left){\n\t\tif(this.table.options.groupBy){\n\t\t\tif(this.table.options.renderHorizontal === \"virtual\"){\n\t\t\t\tleft -= this.table.columnManager.renderer.vDomPadLeft;\n\t\t\t}\n\t\t\t\n\t\t\tleft = left + \"px\";\n\t\t\t\n\t\t\tthis.groupList.forEach((group) => {\n\t\t\t\tgroup.scrollHeader(left);\n\t\t\t});\n\t\t}\n\t}\n\t\n\tremoveGroup(group){\n\t\tvar groupKey = group.level + \"_\" + group.key,\n\t\tindex;\n\t\t\n\t\tif(this.groups[groupKey]){\n\t\t\tdelete this.groups[groupKey];\n\t\t\t\n\t\t\tindex = this.groupList.indexOf(group);\n\t\t\t\n\t\t\tif(index > -1){\n\t\t\t\tthis.groupList.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tcheckBasicModeGroupHeaderWidth(){\n\t\tvar element = this.table.rowManager.tableElement,\n\t\tonlyGroupHeaders = true;\n\t\t\n\t\tthis.table.rowManager.getDisplayRows().forEach((row, index) =>{\n\t\t\tthis.table.rowManager.styleRow(row, index);\n\t\t\telement.appendChild(row.getElement());\n\t\t\trow.initialize(true);\n\t\t\t\n\t\t\tif(row.type !== \"group\"){\n\t\t\t\tonlyGroupHeaders = false;\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(onlyGroupHeaders){\n\t\t\telement.style.minWidth = this.table.columnManager.getWidth() + \"px\";\n\t\t}else {\n\t\t\telement.style.minWidth = \"\";\n\t\t}\n\t}\n\t\n}\n\nGroupRows.moduleName = \"groupRows\";\n\nvar defaultUndoers = {\n\tcellEdit: function(action){\n\t\taction.component.setValueProcessData(action.data.oldValue);\n\t\taction.component.cellRendered();\n\t},\n\n\trowAdd: function(action){\n\t\taction.component.deleteActual();\n\n\t\tthis.table.rowManager.checkPlaceholder();\n\t},\n\n\trowDelete: function(action){\n\t\tvar newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index);\n\n\t\tif(this.table.options.groupBy && this.table.modExists(\"groupRows\")){\n\t\t\tthis.table.modules.groupRows.updateGroupRows(true);\n\t\t}\n\n\t\tthis._rebindRow(action.component, newRow);\n\n\t\tthis.table.rowManager.checkPlaceholder();\n\t},\n\n\trowMove: function(action){\n\t\tvar after = (action.data.posFrom  - action.data.posTo) > 0;\n\n\t\tthis.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posFrom), after);\n\n\t\tthis.table.rowManager.regenerateRowPositions();\n\t\tthis.table.rowManager.reRenderInPosition();\n\t},\n};\n\nvar defaultRedoers = {\n\tcellEdit: function(action){\n\t\taction.component.setValueProcessData(action.data.newValue);\n\t\taction.component.cellRendered();\n\t},\n\n\trowAdd: function(action){\n\t\tvar newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index);\n\n\t\tif(this.table.options.groupBy && this.table.modExists(\"groupRows\")){\n\t\t\tthis.table.modules.groupRows.updateGroupRows(true);\n\t\t}\n\n\t\tthis._rebindRow(action.component, newRow);\n\n\t\tthis.table.rowManager.checkPlaceholder();\n\t},\n\n\trowDelete:function(action){\n\t\taction.component.deleteActual();\n\n\t\tthis.table.rowManager.checkPlaceholder();\n\t},\n\n\trowMove: function(action){\n\t\tthis.table.rowManager.moveRowActual(action.component, this.table.rowManager.getRowFromPosition(action.data.posTo), action.data.after);\n\t\t\n\t\tthis.table.rowManager.regenerateRowPositions();\n\t\tthis.table.rowManager.reRenderInPosition();\n\t},\n};\n\nclass History extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.history = [];\n\t\tthis.index = -1;\n\n\t\tthis.registerTableOption(\"history\", false); //enable edit history\n\t}\n\n\tinitialize(){\n\t\tif(this.table.options.history){\n\t\t\tthis.subscribe(\"cell-value-updated\", this.cellUpdated.bind(this));\n\t\t\tthis.subscribe(\"cell-delete\", this.clearComponentHistory.bind(this));\n\t\t\tthis.subscribe(\"row-delete\", this.rowDeleted.bind(this));\n\t\t\tthis.subscribe(\"rows-wipe\", this.clear.bind(this));\n\t\t\tthis.subscribe(\"row-added\", this.rowAdded.bind(this));\n\t\t\tthis.subscribe(\"row-move\", this.rowMoved.bind(this));\n\t\t}\n\n\t\tthis.registerTableFunction(\"undo\", this.undo.bind(this));\n\t\tthis.registerTableFunction(\"redo\", this.redo.bind(this));\n\t\tthis.registerTableFunction(\"getHistoryUndoSize\", this.getHistoryUndoSize.bind(this));\n\t\tthis.registerTableFunction(\"getHistoryRedoSize\", this.getHistoryRedoSize.bind(this));\n\t\tthis.registerTableFunction(\"clearHistory\", this.clear.bind(this));\n\t}\n\n\trowMoved(from, to, after){\n\t\tthis.action(\"rowMove\", from, {posFrom:from.getPosition(), posTo:to.getPosition(), to:to, after:after});\n\t}\n\n\trowAdded(row, data, pos, index){\n\t\tthis.action(\"rowAdd\", row, {data:data, pos:pos, index:index});\n\t}\n\n\trowDeleted(row){\n\t\tvar index, rows;\n\n\t\tif(this.table.options.groupBy){\n\n\t\t\trows = row.getComponent().getGroup()._getSelf().rows;\n\t\t\tindex = rows.indexOf(row);\n\n\t\t\tif(index){\n\t\t\t\tindex = rows[index-1];\n\t\t\t}\n\t\t}else {\n\t\t\tindex = row.table.rowManager.getRowIndex(row);\n\n\t\t\tif(index){\n\t\t\t\tindex = row.table.rowManager.rows[index-1];\n\t\t\t}\n\t\t}\n\n\t\tthis.action(\"rowDelete\", row, {data:row.getData(), pos:!index, index:index});\n\t}\n\n\tcellUpdated(cell){\n\t\tthis.action(\"cellEdit\", cell, {oldValue:cell.oldValue, newValue:cell.value});\n\t}\n\n\tclear(){\n\t\tthis.history = [];\n\t\tthis.index = -1;\n\t}\n\n\taction(type, component, data){\n\t\tthis.history = this.history.slice(0, this.index + 1);\n\n\t\tthis.history.push({\n\t\t\ttype:type,\n\t\t\tcomponent:component,\n\t\t\tdata:data,\n\t\t});\n\n\t\tthis.index ++;\n\t}\n\n\tgetHistoryUndoSize(){\n\t\treturn this.index + 1;\n\t}\n\n\tgetHistoryRedoSize(){\n\t\treturn this.history.length - (this.index + 1);\n\t}\n\n\tclearComponentHistory(component){\n\t\tvar index = this.history.findIndex(function(item){\n\t\t\treturn item.component === component;\n\t\t});\n\n\t\tif(index > -1){\n\t\t\tthis.history.splice(index, 1);\n\t\t\tif(index <= this.index){\n\t\t\t\tthis.index--;\n\t\t\t}\n\n\t\t\tthis.clearComponentHistory(component);\n\t\t}\n\t}\n\n\tundo(){\n\t\tif(this.index > -1){\n\t\t\tlet action = this.history[this.index];\n\n\t\t\tHistory.undoers[action.type].call(this, action);\n\n\t\t\tthis.index--;\n\n\t\t\tthis.dispatchExternal(\"historyUndo\", action.type, action.component.getComponent(), action.data);\n\n\t\t\treturn true;\n\t\t}else {\n\t\t\tconsole.warn(this.options(\"history\") ? \"History Undo Error - No more history to undo\" : \"History module not enabled\");\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tredo(){\n\t\tif(this.history.length-1 > this.index){\n\n\t\t\tthis.index++;\n\n\t\t\tlet action = this.history[this.index];\n\n\t\t\tHistory.redoers[action.type].call(this, action);\n\n\t\t\tthis.dispatchExternal(\"historyRedo\", action.type, action.component.getComponent(), action.data);\n\n\t\t\treturn true;\n\t\t}else {\n\t\t\tconsole.warn(this.options(\"history\") ? \"History Redo Error - No more history to redo\" : \"History module not enabled\");\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//rebind rows to new element after deletion\n\t_rebindRow(oldRow, newRow){\n\t\tthis.history.forEach(function(action){\n\t\t\tif(action.component instanceof Row){\n\t\t\t\tif(action.component === oldRow){\n\t\t\t\t\taction.component = newRow;\n\t\t\t\t}\n\t\t\t}else if(action.component instanceof Cell){\n\t\t\t\tif(action.component.row === oldRow){\n\t\t\t\t\tvar field = action.component.column.getField();\n\n\t\t\t\t\tif(field){\n\t\t\t\t\t\taction.component = newRow.getCell(field);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nHistory.moduleName = \"history\";\n\n//load defaults\nHistory.undoers = defaultUndoers;\nHistory.redoers = defaultRedoers;\n\nclass HtmlTableImport extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.fieldIndex = [];\n\t\tthis.hasIndex = false;\n\t}\n\n\tinitialize(){\n\t\tthis.tableElementCheck();\n\t}\n\n\ttableElementCheck(){\n\t\tif(this.table.originalElement && this.table.originalElement.tagName === \"TABLE\"){\n\t\t\tif(this.table.originalElement.childNodes.length){\n\t\t\t\tthis.parseTable();\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Unable to parse data from empty table tag, Tabulator should be initialized on a div tag unless importing data from a table element.\");\n\t\t\t}\n\t\t}\n\t}\n\n\tparseTable(){\n\t\tvar element = this.table.originalElement,\n\t\toptions = this.table.options,\n\t\theaders = element.getElementsByTagName(\"th\"),\n\t\trows = element.getElementsByTagName(\"tbody\")[0],\n\t\tdata = [];\n\n\t\tthis.hasIndex = false;\n\n\t\tthis.dispatchExternal(\"htmlImporting\");\n\n\t\trows = rows ? rows.getElementsByTagName(\"tr\") : [];\n\n\t\t//check for Tabulator inline options\n\t\tthis._extractOptions(element, options);\n\n\t\tif(headers.length){\n\t\t\tthis._extractHeaders(headers, rows);\n\t\t}else {\n\t\t\tthis._generateBlankHeaders(headers, rows);\n\t\t}\n\n\t\t//iterate through table rows and build data set\n\t\tfor(var index = 0; index < rows.length; index++){\n\t\t\tvar row = rows[index],\n\t\t\tcells = row.getElementsByTagName(\"td\"),\n\t\t\titem = {};\n\n\t\t\t//create index if the don't exist in table\n\t\t\tif(!this.hasIndex){\n\t\t\t\titem[options.index] = index;\n\t\t\t}\n\n\t\t\tfor(var i = 0; i < cells.length; i++){\n\t\t\t\tvar cell = cells[i];\n\t\t\t\tif(typeof this.fieldIndex[i] !== \"undefined\"){\n\t\t\t\t\titem[this.fieldIndex[i]] = cell.innerHTML;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//add row data to item\n\t\t\tdata.push(item);\n\t\t}\n\n\t\toptions.data = data;\n\n\t\tthis.dispatchExternal(\"htmlImported\");\n\t}\n\n\t//extract tabulator attribute options\n\t_extractOptions(element, options, defaultOptions){\n\t\tvar attributes = element.attributes;\n\t\tvar optionsArr = defaultOptions ? Object.keys(defaultOptions) : Object.keys(options);\n\t\tvar optionsList = {};\n\n\t\toptionsArr.forEach((item) => {\n\t\t\toptionsList[item.toLowerCase()] = item;\n\t\t});\n\n\t\tfor(var index in attributes){\n\t\t\tvar attrib = attributes[index];\n\t\t\tvar name;\n\n\t\t\tif(attrib && typeof attrib == \"object\" && attrib.name && attrib.name.indexOf(\"tabulator-\") === 0){\n\t\t\t\tname = attrib.name.replace(\"tabulator-\", \"\");\n\n\t\t\t\tif(typeof optionsList[name] !== \"undefined\"){\n\t\t\t\t\toptions[optionsList[name]] = this._attribValue(attrib.value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//get value of attribute\n\t_attribValue(value){\n\t\tif(value === \"true\"){\n\t\t\treturn true;\n\t\t}\n\n\t\tif(value === \"false\"){\n\t\t\treturn false;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t//find column if it has already been defined\n\t_findCol(title){\n\t\tvar match = this.table.options.columns.find((column) => {\n\t\t\treturn column.title === title;\n\t\t});\n\n\t\treturn match || false;\n\t}\n\n\t//extract column from headers\n\t_extractHeaders(headers, rows){\n\t\tfor(var index = 0; index < headers.length; index++){\n\t\t\tvar header = headers[index],\n\t\t\texists = false,\n\t\t\tcol = this._findCol(header.textContent),\n\t\t\twidth;\n\n\t\t\tif(col){\n\t\t\t\texists = true;\n\t\t\t}else {\n\t\t\t\tcol = {title:header.textContent.trim()};\n\t\t\t}\n\n\t\t\tif(!col.field) {\n\t\t\t\tcol.field = header.textContent.trim().toLowerCase().replaceAll(\" \", \"_\");\n\t\t\t}\n\n\t\t\twidth = header.getAttribute(\"width\");\n\n\t\t\tif(width && !col.width)\t{\n\t\t\t\tcol.width = width;\n\t\t\t}\n\n\t\t\t//check for Tabulator inline options\n\t\t\tthis._extractOptions(header, col, this.table.columnManager.optionsList.registeredDefaults);\n\n\t\t\tthis.fieldIndex[index] = col.field;\n\n\t\t\tif(col.field == this.table.options.index){\n\t\t\t\tthis.hasIndex = true;\n\t\t\t}\n\n\t\t\tif(!exists){\n\t\t\t\tthis.table.options.columns.push(col);\n\t\t\t}\n\n\t\t}\n\t}\n\n\t//generate blank headers\n\t_generateBlankHeaders(headers, rows){\n\t\tfor(var index = 0; index < headers.length; index++){\n\t\t\tvar header = headers[index],\n\t\t\tcol = {title:\"\", field:\"col\" + index};\n\n\t\t\tthis.fieldIndex[index] = col.field;\n\n\t\t\tvar width = header.getAttribute(\"width\");\n\n\t\t\tif(width){\n\t\t\t\tcol.width = width;\n\t\t\t}\n\n\t\t\tthis.table.options.columns.push(col);\n\t\t}\n\t}\n}\n\nHtmlTableImport.moduleName = \"htmlTableImport\";\n\nfunction csvImporter(input){\n\tvar data = [],\n\trow = 0, \n\tcol = 0,\n\tinQuote = false;\n    \n\t//Iterate over each character\n\tfor (let index = 0; index < input.length; index++) {\n\t\tlet char = input[index], \n\t\tnextChar = input[index+1];      \n        \n\t\t//Initialize empty row\n\t\tif(!data[row]){\n\t\t\tdata[row] = [];\n\t\t}\n\n\t\t//Initialize empty column\n\t\tif(!data[row][col]){\n\t\t\tdata[row][col] = \"\";\n\t\t}\n        \n\t\t//Handle quotation mark inside string\n\t\tif (char == '\"' && inQuote && nextChar == '\"') { \n\t\t\tdata[row][col] += char; \n\t\t\tindex++;\n\t\t\tcontinue; \n\t\t}\n        \n\t\t//Begin / End Quote\n\t\tif (char == '\"') { \n\t\t\tinQuote = !inQuote;\n\t\t\tcontinue;\n\t\t}\n        \n\t\t//Next column (if not in quote)\n\t\tif (char == ',' && !inQuote) { \n\t\t\tcol++;\n\t\t\tcontinue; \n\t\t}\n        \n\t\t//New row if new line and not in quote (CRLF) \n\t\tif (char == '\\r' && nextChar == '\\n' && !inQuote) { \n\t\t\tcol = 0; \n\t\t\trow++; \n\t\t\tindex++; \n\t\t\tcontinue; \n\t\t}\n        \n\t\t//New row if new line and not in quote (CR or LF) \n\t\tif ((char == '\\r' || char == '\\n') && !inQuote) { \n\t\t\tcol = 0;\n\t\t\trow++;\n\t\t\tcontinue; \n\t\t}\n\n\t\t//Normal Character, append to column\n\t\tdata[row][col] += char;\n\t}\n\n\treturn data;\n}\n\nfunction json$1(input){\n\ttry {\n\t\treturn JSON.parse(input);\n\t} catch(e) {\n\t\tconsole.warn(\"JSON Import Error - File contents is invalid JSON\", e);\n\t\treturn Promise.reject();\n\t}\n}\n\nfunction arrayImporter(input){\n\treturn input;\n}\n\nvar defaultImporters = {\n\tcsv:csvImporter,\n\tjson:json$1,\n\tarray:arrayImporter,\n};\n\nclass Import extends Module{\n    \n\tconstructor(table){\n\t\tsuper(table);\n        \n\t\tthis.registerTableOption(\"importFormat\");\n\t\tthis.registerTableOption(\"importReader\", \"text\");\n\t}\n    \n\tinitialize(){\n\t\tthis.registerTableFunction(\"import\", this.importFromFile.bind(this));\n\n\t\tif(this.table.options.importFormat){\n\t\t\tthis.subscribe(\"data-loading\", this.loadDataCheck.bind(this), 10);\n\t\t\tthis.subscribe(\"data-load\", this.loadData.bind(this), 10);\n\t\t}\n\t}\n\n\tloadDataCheck(data){\n\t\treturn this.table.options.importFormat && (typeof data === \"string\" || (Array.isArray(data) && data.length && Array.isArray(data)));\n\t}\n\n\tloadData(data, params, config, silent, previousData){\n\t\treturn this.importData(this.lookupImporter(), data)\n\t\t\t.then(this.structureData.bind(this))\n\t\t\t.catch((err) => {\n\t\t\t\tconsole.error(\"Import Error:\", err || \"Unable to import data\");\n\t\t\t\treturn Promise.reject(err);\n\t\t\t});\n\t}\n\n\tlookupImporter(importFormat){\n\t\tvar importer;\n        \n\t\tif(!importFormat){\n\t\t\timportFormat = this.table.options.importFormat;\n\t\t}\n        \n\t\tif(typeof importFormat === \"string\"){\n\t\t\timporter = Import.importers[importFormat];\n\t\t}else {\n\t\t\timporter = importFormat;\n\t\t}\n\n\t\tif(!importer){\n\t\t\tconsole.error(\"Import Error - Importer not found:\", importFormat);\n\t\t}\n        \n\t\treturn importer;\n\t}\n    \n\timportFromFile(importFormat, extension){\n\t\tvar importer = this.lookupImporter(importFormat);\n        \n\t\tif(importer){\n\t\t\treturn this.pickFile(extension)\n\t\t\t\t.then(this.importData.bind(this, importer))\n\t\t\t\t.then(this.structureData.bind(this))\n\t\t\t\t.then(this.setData.bind(this))\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(\"Import Error:\", err || \"Unable to import file\");\n\t\t\t\t\treturn Promise.reject(err);\n\t\t\t\t});\n\t\t}\n\t}\n    \n\tpickFile(extensions){\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.type = \"file\";\n\t\t\tinput.accept = extensions;\n            \n\t\t\tinput.addEventListener(\"change\", (e) => {\n\t\t\t\tvar file = input.files[0],\n\t\t\t\treader = new FileReader();\n                \n\t\t\t\tswitch(this.table.options.importReader){\n\t\t\t\t\tcase \"buffer\":\n\t\t\t\t\t\treader.readAsArrayBuffer(file);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"binary\":\n\t\t\t\t\t\treader.readAsBinaryString(file);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"url\":\n\t\t\t\t\t\treader.readAsDataURL(file);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"text\":\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treader.readAsText(file);\n\t\t\t\t}\n                  \n\t\t\t\treader.onload = (e) => {\n\t\t\t\t\tresolve(reader.result);\n\t\t\t\t};\n                \n\t\t\t\treader.onerror = (e) => {\n\t\t\t\t\tconsole.warn(\"File Load Error - Unable to read file\");\n\t\t\t\t\treject();\n\t\t\t\t};\n\t\t\t});\n            \n\t\t\tinput.click();\n\t\t});\n\t}\n    \n\timportData(importer, fileContents){\n\t\tvar data = importer.call(this.table, fileContents);\n        \n\t\tif(data instanceof Promise){\n\t\t\treturn data;\n\t\t}else {\n\t\t\treturn data ? Promise.resolve(data) : Promise.reject();\n\t\t}\n\t}\n\n\tstructureData(parsedData){\n\t\tvar data = [];\n        \n\t\tif(Array.isArray(parsedData) && parsedData.length && Array.isArray(parsedData[0])){\n\t\t\tif(this.table.options.autoColumns){\n\t\t\t\tdata = this.structureArrayToObject(parsedData);\n\t\t\t}else {\n\t\t\t\tdata = this.structureArrayToColumns(parsedData);\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}else {\n\t\t\treturn parsedData;\n\t\t}\n\t}\n\n\tstructureArrayToObject(parsedData){\n\t\tvar columns = parsedData.shift();\n\n\t\tvar data = parsedData.map((values) => {\n\t\t\tvar row = {};\n\n\t\t\tcolumns.forEach((key, i) => {\n\t\t\t\trow[key] = values[i];\n\t\t\t});\n\n\t\t\treturn row;\n\t\t});\n\n\t\treturn data;\n\t}\n\n\tstructureArrayToColumns(parsedData){\n\t\tvar data = [],\n\t\tcolumns = this.table.getColumns();\n\n\t\t//remove first row if it is the column names\n\t\tif(columns[0] && parsedData[0][0]){\n\t\t\tif(columns[0].getDefinition().title === parsedData[0][0]){\n\t\t\t\tparsedData.shift();\n\t\t\t}\n\t\t}\n        \n\t\t//convert row arrays to objects\n\t\tparsedData.forEach((rowData) => {\n\t\t\tvar row = {};\n\n\t\t\trowData.forEach((value, index) => {\n\t\t\t\tvar column = columns[index];\n\n\t\t\t\tif(column){\n\t\t\t\t\trow[column.getField()] = value;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tdata.push(row);\n\t\t});\n\n\t\treturn data;\n\t}\n    \n\tsetData(data){\n\t\treturn this.table.setData(data);\n\t}\n}\n\nImport.moduleName = \"import\";\n\n//load defaults\nImport.importers = defaultImporters;\n\nclass Interaction extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.eventMap = {\n\t\t\t//row events\n\t\t\trowClick:\"row-click\",\n\t\t\trowDblClick:\"row-dblclick\",\n\t\t\trowContext:\"row-contextmenu\",\n\t\t\trowMouseEnter:\"row-mouseenter\",\n\t\t\trowMouseLeave:\"row-mouseleave\",\n\t\t\trowMouseOver:\"row-mouseover\",\n\t\t\trowMouseOut:\"row-mouseout\",\n\t\t\trowMouseMove:\"row-mousemove\",\n\t\t\trowMouseDown:\"row-mousedown\",\n\t\t\trowMouseUp:\"row-mouseup\",\n\t\t\trowTap:\"row\",\n\t\t\trowDblTap:\"row\",\n\t\t\trowTapHold:\"row\",\n\n\t\t\t//cell events\n\t\t\tcellClick:\"cell-click\",\n\t\t\tcellDblClick:\"cell-dblclick\",\n\t\t\tcellContext:\"cell-contextmenu\",\n\t\t\tcellMouseEnter:\"cell-mouseenter\",\n\t\t\tcellMouseLeave:\"cell-mouseleave\",\n\t\t\tcellMouseOver:\"cell-mouseover\",\n\t\t\tcellMouseOut:\"cell-mouseout\",\n\t\t\tcellMouseMove:\"cell-mousemove\",\n\t\t\tcellMouseDown:\"cell-mousedown\",\n\t\t\tcellMouseUp:\"cell-mouseup\",\n\t\t\tcellTap:\"cell\",\n\t\t\tcellDblTap:\"cell\",\n\t\t\tcellTapHold:\"cell\",\n\n\t\t\t//column header events\n\t\t\theaderClick:\"column-click\",\n\t\t\theaderDblClick:\"column-dblclick\",\n\t\t\theaderContext:\"column-contextmenu\",\n\t\t\theaderMouseEnter:\"column-mouseenter\",\n\t\t\theaderMouseLeave:\"column-mouseleave\",\n\t\t\theaderMouseOver:\"column-mouseover\",\n\t\t\theaderMouseOut:\"column-mouseout\",\n\t\t\theaderMouseMove:\"column-mousemove\",\n\t\t\theaderMouseDown:\"column-mousedown\",\n\t\t\theaderMouseUp:\"column-mouseup\",\n\t\t\theaderTap:\"column\",\n\t\t\theaderDblTap:\"column\",\n\t\t\theaderTapHold:\"column\",\n\n\t\t\t//group header\n\t\t\tgroupClick:\"group-click\",\n\t\t\tgroupDblClick:\"group-dblclick\",\n\t\t\tgroupContext:\"group-contextmenu\",\n\t\t\tgroupMouseEnter:\"group-mouseenter\",\n\t\t\tgroupMouseLeave:\"group-mouseleave\",\n\t\t\tgroupMouseOver:\"group-mouseover\",\n\t\t\tgroupMouseOut:\"group-mouseout\",\n\t\t\tgroupMouseMove:\"group-mousemove\",\n\t\t\tgroupMouseDown:\"group-mousedown\",\n\t\t\tgroupMouseUp:\"group-mouseup\",\n\t\t\tgroupTap:\"group\",\n\t\t\tgroupDblTap:\"group\",\n\t\t\tgroupTapHold:\"group\",\n\t\t};\n\n\t\tthis.subscribers = {};\n\n\t\tthis.touchSubscribers = {};\n\n\t\tthis.columnSubscribers = {};\n\n\t\tthis.touchWatchers = {\n\t\t\trow:{\n\t\t\t\ttap:null,\n\t\t\t\ttapDbl:null,\n\t\t\t\ttapHold:null,\n\t\t\t},\n\t\t\tcell:{\n\t\t\t\ttap:null,\n\t\t\t\ttapDbl:null,\n\t\t\t\ttapHold:null,\n\t\t\t},\n\t\t\tcolumn:{\n\t\t\t\ttap:null,\n\t\t\t\ttapDbl:null,\n\t\t\t\ttapHold:null,\n\t\t\t},\n\t\t\tgroup:{\n\t\t\t\ttap:null,\n\t\t\t\ttapDbl:null,\n\t\t\t\ttapHold:null,\n\t\t\t}\n\t\t};\n\n\t\tthis.registerColumnOption(\"headerClick\");\n\t\tthis.registerColumnOption(\"headerDblClick\");\n\t\tthis.registerColumnOption(\"headerContext\");\n\t\tthis.registerColumnOption(\"headerMouseEnter\");\n\t\tthis.registerColumnOption(\"headerMouseLeave\");\n\t\tthis.registerColumnOption(\"headerMouseOver\");\n\t\tthis.registerColumnOption(\"headerMouseOut\");\n\t\tthis.registerColumnOption(\"headerMouseMove\");\n\t\tthis.registerColumnOption(\"headerMouseDown\");\n\t\tthis.registerColumnOption(\"headerMouseUp\");\n\t\tthis.registerColumnOption(\"headerTap\");\n\t\tthis.registerColumnOption(\"headerDblTap\");\n\t\tthis.registerColumnOption(\"headerTapHold\");\n\n\t\tthis.registerColumnOption(\"cellClick\");\n\t\tthis.registerColumnOption(\"cellDblClick\");\n\t\tthis.registerColumnOption(\"cellContext\");\n\t\tthis.registerColumnOption(\"cellMouseEnter\");\n\t\tthis.registerColumnOption(\"cellMouseLeave\");\n\t\tthis.registerColumnOption(\"cellMouseOver\");\n\t\tthis.registerColumnOption(\"cellMouseOut\");\n\t\tthis.registerColumnOption(\"cellMouseMove\");\n\t\tthis.registerColumnOption(\"cellMouseDown\");\n\t\tthis.registerColumnOption(\"cellMouseUp\");\n\t\tthis.registerColumnOption(\"cellTap\");\n\t\tthis.registerColumnOption(\"cellDblTap\");\n\t\tthis.registerColumnOption(\"cellTapHold\");\n\n\t}\n\n\tinitialize(){\n\t\tthis.initializeExternalEvents();\n\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"cell-dblclick\", this.cellContentsSelectionFixer.bind(this));\n\t\tthis.subscribe(\"scroll-horizontal\", this.clearTouchWatchers.bind(this));\n\t\tthis.subscribe(\"scroll-vertical\", this.clearTouchWatchers.bind(this));\n\t}\n\n\tclearTouchWatchers(){\n\t\tvar types = Object.values(this.touchWatchers);\n\n\t\ttypes.forEach((type) => {\n\t\t\tfor(let key in type){\n\t\t\t\ttype[key] = null;\n\t\t\t}\n\t\t});\n\t}\n\t\t\n\tcellContentsSelectionFixer(e, cell){\n\t\tvar range;\n\n\t\tif(this.table.modExists(\"edit\")){\n\t\t\tif (this.table.modules.edit.currentCell === cell){\n\t\t\t\treturn; //prevent instant selection of editor content\n\t\t\t}\n\t\t}\n\n\t\te.preventDefault();\n\n\t\ttry{\n\t\t\tif (document.selection) { // IE\n\t\t\t\trange = document.body.createTextRange();\n\t\t\t\trange.moveToElementText(cell.getElement());\n\t\t\t\trange.select();\n\t\t\t} else if (window.getSelection) {\n\t\t\t\trange = document.createRange();\n\t\t\t\trange.selectNode(cell.getElement());\n\t\t\t\twindow.getSelection().removeAllRanges();\n\t\t\t\twindow.getSelection().addRange(range);\n\t\t\t}\n\t\t}catch(e){}\n\t}\n\n\tinitializeExternalEvents(){\n\t\tfor(let key in this.eventMap){\n\t\t\tthis.subscriptionChangeExternal(key, this.subscriptionChanged.bind(this, key));\n\t\t}\n\t}\n\n\tsubscriptionChanged(key, added){\n\t\tif(added){\n\t\t\tif(!this.subscribers[key]){\n\t\t\t\tif(this.eventMap[key].includes(\"-\")){\n\t\t\t\t\tthis.subscribers[key] = this.handle.bind(this, key);\n\t\t\t\t\tthis.subscribe(this.eventMap[key], this.subscribers[key]);\n\t\t\t\t}else {\n\t\t\t\t\tthis.subscribeTouchEvents(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tif(this.eventMap[key].includes(\"-\")){\n\t\t\t\tif(this.subscribers[key] && !this.columnSubscribers[key]  && !this.subscribedExternal(key)){\n\t\t\t\t\tthis.unsubscribe(this.eventMap[key], this.subscribers[key]);\n\t\t\t\t\tdelete this.subscribers[key];\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.unsubscribeTouchEvents(key);\n\t\t\t}\n\t\t}\n\t}\n\n\n\tsubscribeTouchEvents(key){\n\t\tvar type = this.eventMap[key];\n\n\t\tif(!this.touchSubscribers[type + \"-touchstart\"]){\n\t\t\tthis.touchSubscribers[type + \"-touchstart\"] = this.handleTouch.bind(this, type, \"start\");\n\t\t\tthis.touchSubscribers[type + \"-touchend\"] = this.handleTouch.bind(this, type, \"end\");\n\n\t\t\tthis.subscribe(type + \"-touchstart\", this.touchSubscribers[type + \"-touchstart\"]);\n\t\t\tthis.subscribe(type + \"-touchend\", this.touchSubscribers[type + \"-touchend\"]);\n\t\t}\n\n\t\tthis.subscribers[key] = true;\n\t}\n\n\tunsubscribeTouchEvents(key){\n\t\tvar noTouch = true,\n\t\ttype = this.eventMap[key];\n\n\t\tif(this.subscribers[key] && !this.subscribedExternal(key)){\n\t\t\tdelete this.subscribers[key];\n\n\t\t\tfor(let i in this.eventMap){\n\t\t\t\tif(this.eventMap[i] === type){\n\t\t\t\t\tif(this.subscribers[i]){\n\t\t\t\t\t\tnoTouch = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(noTouch){\n\t\t\t\tthis.unsubscribe(type + \"-touchstart\", this.touchSubscribers[type + \"-touchstart\"]);\n\t\t\t\tthis.unsubscribe(type + \"-touchend\", this.touchSubscribers[type + \"-touchend\"]);\n\n\t\t\t\tdelete this.touchSubscribers[type + \"-touchstart\"];\n\t\t\t\tdelete this.touchSubscribers[type + \"-touchend\"];\n\t\t\t}\n\t\t}\n\t}\n\n\tinitializeColumn(column){\n\t\tvar def = column.definition;\n\n\t\tfor(let key in this.eventMap){\n\t\t\tif(def[key]){\n\t\t\t\tthis.subscriptionChanged(key, true);\n\n\t\t\t\tif(!this.columnSubscribers[key]){\n\t\t\t\t\tthis.columnSubscribers[key] = [];\n\t\t\t\t}\n\n\t\t\t\tthis.columnSubscribers[key].push(column);\n\t\t\t}\n\t\t}\n\t}\n\n\thandle(action, e, component){\n\t\tthis.dispatchEvent(action, e, component);\n\t}\n\n\thandleTouch(type, action, e, component){\n\t\tvar watchers = this.touchWatchers[type];\n\n\t\tif(type === \"column\"){\n\t\t\ttype = \"header\";\n\t\t}\n\n\t\tswitch(action){\n\t\t\tcase \"start\":\n\t\t\t\twatchers.tap = true;\n\n\t\t\t\tclearTimeout(watchers.tapHold);\n\n\t\t\t\twatchers.tapHold = setTimeout(() => {\n\t\t\t\t\tclearTimeout(watchers.tapHold);\n\t\t\t\t\twatchers.tapHold = null;\n\n\t\t\t\t\twatchers.tap = null;\n\t\t\t\t\tclearTimeout(watchers.tapDbl);\n\t\t\t\t\twatchers.tapDbl = null;\n\n\t\t\t\t\tthis.dispatchEvent(type + \"TapHold\", e,  component);\n\t\t\t\t}, 1000);\n\t\t\t\tbreak;\n\n\t\t\tcase \"end\":\n\t\t\t\tif(watchers.tap){\n\n\t\t\t\t\twatchers.tap = null;\n\t\t\t\t\tthis.dispatchEvent(type + \"Tap\", e,  component);\n\t\t\t\t}\n\n\t\t\t\tif(watchers.tapDbl){\n\t\t\t\t\tclearTimeout(watchers.tapDbl);\n\t\t\t\t\twatchers.tapDbl = null;\n\n\t\t\t\t\tthis.dispatchEvent(type + \"DblTap\", e,  component);\n\t\t\t\t}else {\n\t\t\t\t\twatchers.tapDbl = setTimeout(() => {\n\t\t\t\t\t\tclearTimeout(watchers.tapDbl);\n\t\t\t\t\t\twatchers.tapDbl = null;\n\t\t\t\t\t}, 300);\n\t\t\t\t}\n\n\t\t\t\tclearTimeout(watchers.tapHold);\n\t\t\t\twatchers.tapHold = null;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tdispatchEvent(action, e, component){\n\t\tvar componentObj = component.getComponent(),\n\t\tcallback;\n\n\t\tif(this.columnSubscribers[action]){\n\n\t\t\tif(component instanceof Cell){\n\t\t\t\tcallback = component.column.definition[action];\n\t\t\t}else if(component instanceof Column){\n\t\t\t\tcallback = component.definition[action];\n\t\t\t}\n\n\t\t\tif(callback){\n\t\t\t\tcallback(e, componentObj);\n\t\t\t}\n\t\t}\n\n\t\tthis.dispatchExternal(action, e, componentObj);\n\t}\n}\n\nInteraction.moduleName = \"interaction\";\n\nvar defaultBindings = {\n\tnavPrev:\"shift + 9\",\n\tnavNext:9,\n\tnavUp:38,\n\tnavDown:40,\n\tnavLeft:37,\n\tnavRight:39,\n\tscrollPageUp:33,\n\tscrollPageDown:34,\n\tscrollToStart:36,\n\tscrollToEnd:35,\n\tundo:[\"ctrl + 90\", \"meta + 90\"],\n\tredo:[\"ctrl + 89\", \"meta + 89\"],\n\tcopyToClipboard:[\"ctrl + 67\", \"meta + 67\"],\n\n\trangeJumpUp:[\"ctrl + 38\", \"meta + 38\"],\n\trangeJumpDown:[\"ctrl + 40\", \"meta + 40\"],\n\trangeJumpLeft:[\"ctrl + 37\", \"meta + 37\"],\n\trangeJumpRight:[\"ctrl + 39\", \"meta + 39\"],\n\trangeExpandUp:\"shift + 38\",\n\trangeExpandDown:\"shift + 40\",\n\trangeExpandLeft:\"shift + 37\",\n\trangeExpandRight:\"shift + 39\",\n\trangeExpandJumpUp:[\"ctrl + shift + 38\", \"meta + shift + 38\"],\n\trangeExpandJumpDown:[\"ctrl + shift + 40\", \"meta + shift + 40\"],\n\trangeExpandJumpLeft:[\"ctrl + shift + 37\", \"meta + shift + 37\"],\n\trangeExpandJumpRight:[\"ctrl + shift + 39\", \"meta + shift + 39\"],\n};\n\nvar defaultActions = {\n\tkeyBlock:function(e){\n\t\te.stopPropagation();\n\t\te.preventDefault();\n\t},\n\tscrollPageUp:function(e){\n\t\tvar rowManager = this.table.rowManager,\n\t\tnewPos = rowManager.scrollTop - rowManager.element.clientHeight;\n\n\t\te.preventDefault();\n\n\t\tif(rowManager.displayRowsCount){\n\t\t\tif(newPos >= 0){\n\t\t\t\trowManager.element.scrollTop = newPos;\n\t\t\t}else {\n\t\t\t\trowManager.scrollToRow(rowManager.getDisplayRows()[0]);\n\t\t\t}\n\t\t}\n\n\t\tthis.table.element.focus();\n\t},\n\tscrollPageDown:function(e){\n\t\tvar rowManager = this.table.rowManager,\n\t\tnewPos = rowManager.scrollTop + rowManager.element.clientHeight,\n\t\tscrollMax = rowManager.element.scrollHeight;\n\n\t\te.preventDefault();\n\n\t\tif(rowManager.displayRowsCount){\n\t\t\tif(newPos <= scrollMax){\n\t\t\t\trowManager.element.scrollTop = newPos;\n\t\t\t}else {\n\t\t\t\trowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]);\n\t\t\t}\n\t\t}\n\n\t\tthis.table.element.focus();\n\n\t},\n\tscrollToStart:function(e){\n\t\tvar rowManager = this.table.rowManager;\n\n\t\te.preventDefault();\n\n\t\tif(rowManager.displayRowsCount){\n\t\t\trowManager.scrollToRow(rowManager.getDisplayRows()[0]);\n\t\t}\n\n\t\tthis.table.element.focus();\n\t},\n\tscrollToEnd:function(e){\n\t\tvar rowManager = this.table.rowManager;\n\n\t\te.preventDefault();\n\n\t\tif(rowManager.displayRowsCount){\n\t\t\trowManager.scrollToRow(rowManager.getDisplayRows()[rowManager.displayRowsCount - 1]);\n\t\t}\n\n\t\tthis.table.element.focus();\n\t},\n\tnavPrev:function(e){\n\t\tthis.dispatch(\"keybinding-nav-prev\", e);\n\t},\n\n\tnavNext:function(e){\n\t\tthis.dispatch(\"keybinding-nav-next\", e);\n\t},\n\n\tnavLeft:function(e){\n\t\tthis.dispatch(\"keybinding-nav-left\", e);\n\t},\n\n\tnavRight:function(e){\n\t\tthis.dispatch(\"keybinding-nav-right\", e);\n\t},\n\n\tnavUp:function(e){\n\t\tthis.dispatch(\"keybinding-nav-up\", e);\n\t},\n\n\tnavDown:function(e){\n\t\tthis.dispatch(\"keybinding-nav-down\", e);\n\t},\n\n\trangeJumpLeft: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"left\", true, false);\n\t},\n\trangeJumpRight: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"right\", true, false);\n\t},\n\trangeJumpUp: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"up\", true, false);\n\t},\n\trangeJumpDown: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"down\", true, false);\n\t},\n\trangeExpandLeft: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"left\", false, true);\n\t},\n\trangeExpandRight: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"right\", false, true);\n\t},\n\trangeExpandUp: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"up\", false, true);\n\t},\n\trangeExpandDown: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"down\", false, true);\n\t},\n\trangeExpandJumpLeft: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"left\", true, true);\n\t},\n\trangeExpandJumpRight: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"right\", true, true);\n\t},\n\trangeExpandJumpUp: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"up\", true, true);\n\t},\n\trangeExpandJumpDown: function(e){\n\t\tthis.dispatch(\"keybinding-nav-range\", e, \"down\", true, true);\n\t},\n\n\tundo:function(e){\n\t\tvar cell = false;\n\t\tif(this.table.options.history && this.table.modExists(\"history\") && this.table.modExists(\"edit\")){\n\n\t\t\tcell = this.table.modules.edit.currentCell;\n\n\t\t\tif(!cell){\n\t\t\t\te.preventDefault();\n\t\t\t\tthis.table.modules.history.undo();\n\t\t\t}\n\t\t}\n\t},\n\n\tredo:function(e){\n\t\tvar cell = false;\n\t\tif(this.table.options.history && this.table.modExists(\"history\") && this.table.modExists(\"edit\")){\n\n\t\t\tcell = this.table.modules.edit.currentCell;\n\n\t\t\tif(!cell){\n\t\t\t\te.preventDefault();\n\t\t\t\tthis.table.modules.history.redo();\n\t\t\t}\n\t\t}\n\t},\n\n\tcopyToClipboard:function(e){\n\t\tif(!this.table.modules.edit.currentCell){\n\t\t\tif(this.table.modExists(\"clipboard\", true)){\n\t\t\t\tthis.table.modules.clipboard.copy(false, true);\n\t\t\t}\n\t\t}\n\t},\n};\n\nclass Keybindings extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.watchKeys = null;\n\t\tthis.pressedKeys = null;\n\t\tthis.keyupBinding = false;\n\t\tthis.keydownBinding = false;\n\n\t\tthis.registerTableOption(\"keybindings\", {}); //array for keybindings\n\t\tthis.registerTableOption(\"tabEndNewRow\", false); //create new row when tab to end of table\n\t}\n\n\tinitialize(){\n\t\tvar bindings = this.table.options.keybindings,\n\t\tmergedBindings = {};\n\n\t\tthis.watchKeys = {};\n\t\tthis.pressedKeys = [];\n\n\t\tif(bindings !== false){\n\t\t\tObject.assign(mergedBindings, Keybindings.bindings);\n\t\t\tObject.assign(mergedBindings, bindings);\n\n\t\t\tthis.mapBindings(mergedBindings);\n\t\t\tthis.bindEvents();\n\t\t}\n\n\t\tthis.subscribe(\"table-destroy\", this.clearBindings.bind(this));\n\t}\n\n\tmapBindings(bindings){\n\t\tfor(let key in bindings){\n\t\t\tif(Keybindings.actions[key]){\n\t\t\t\tif(bindings[key]){\n\t\t\t\t\tif(typeof bindings[key] !== \"object\"){\n\t\t\t\t\t\tbindings[key] = [bindings[key]];\n\t\t\t\t\t}\n\n\t\t\t\t\tbindings[key].forEach((binding) => {\n\t\t\t\t\t\tvar bindingList = Array.isArray(binding) ?  binding : [binding];\n\t\t\t\t\t\t\n\t\t\t\t\t\tbindingList.forEach((item) => {\n\t\t\t\t\t\t\tthis.mapBinding(key, item);\n\t\t\t\t\t\t});\t\t\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Key Binding Error - no such action:\", key);\n\t\t\t}\n\t\t}\n\t}\n\n\tmapBinding(action, symbolsList){\n\t\tvar binding = {\n\t\t\taction: Keybindings.actions[action],\n\t\t\tkeys: [],\n\t\t\tctrl: false,\n\t\t\tshift: false,\n\t\t\tmeta: false,\n\t\t};\n\n\t\tvar symbols = symbolsList.toString().toLowerCase().split(\" \").join(\"\").split(\"+\");\n\n\t\tsymbols.forEach((symbol) => {\n\t\t\tswitch(symbol){\n\t\t\t\tcase \"ctrl\":\n\t\t\t\t\tbinding.ctrl = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"shift\":\n\t\t\t\t\tbinding.shift = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"meta\":\n\t\t\t\t\tbinding.meta = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tsymbol = isNaN(symbol) ? symbol.toUpperCase().charCodeAt(0) : parseInt(symbol);\n\t\t\t\t\tbinding.keys.push(symbol);\n\n\t\t\t\t\tif(!this.watchKeys[symbol]){\n\t\t\t\t\t\tthis.watchKeys[symbol] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.watchKeys[symbol].push(binding);\n\t\t\t}\n\t\t});\n\t}\n\n\tbindEvents(){\n\t\tvar self = this;\n\n\t\tthis.keyupBinding = function(e){\n\t\t\tvar code = e.keyCode;\n\t\t\tvar bindings = self.watchKeys[code];\n\n\t\t\tif(bindings){\n\n\t\t\t\tself.pressedKeys.push(code);\n\n\t\t\t\tbindings.forEach(function(binding){\n\t\t\t\t\tself.checkBinding(e, binding);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tthis.keydownBinding = function(e){\n\t\t\tvar code = e.keyCode;\n\t\t\tvar bindings = self.watchKeys[code];\n\n\t\t\tif(bindings){\n\n\t\t\t\tvar index = self.pressedKeys.indexOf(code);\n\n\t\t\t\tif(index > -1){\n\t\t\t\t\tself.pressedKeys.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis.table.element.addEventListener(\"keydown\", this.keyupBinding);\n\n\t\tthis.table.element.addEventListener(\"keyup\", this.keydownBinding);\n\t}\n\n\tclearBindings(){\n\t\tif(this.keyupBinding){\n\t\t\tthis.table.element.removeEventListener(\"keydown\", this.keyupBinding);\n\t\t}\n\n\t\tif(this.keydownBinding){\n\t\t\tthis.table.element.removeEventListener(\"keyup\", this.keydownBinding);\n\t\t}\n\t}\n\n\tcheckBinding(e, binding){\n\t\tvar match = true;\n\n\t\tif(e.ctrlKey == binding.ctrl && e.shiftKey == binding.shift && e.metaKey == binding.meta){\n\t\t\tbinding.keys.forEach((key) => {\n\t\t\t\tvar index = this.pressedKeys.indexOf(key);\n\n\t\t\t\tif(index == -1){\n\t\t\t\t\tmatch = false;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif(match){\n\t\t\t\tbinding.action.call(this, e);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\nKeybindings.moduleName = \"keybindings\";\n\n//load defaults\nKeybindings.bindings = defaultBindings;\nKeybindings.actions = defaultActions;\n\nclass Menu extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.menuContainer = null;\n\t\tthis.nestedMenuBlock = false;\n\t\t\n\t\tthis.currentComponent = null;\n\t\tthis.rootPopup = null;\n\t\t\n\t\tthis.columnSubscribers = {};\n\t\t\n\t\tthis.registerTableOption(\"menuContainer\", undefined); //deprecated\n\t\t\n\t\tthis.registerTableOption(\"rowContextMenu\", false);\n\t\tthis.registerTableOption(\"rowClickMenu\", false);\n\t\tthis.registerTableOption(\"rowDblClickMenu\", false);\n\t\tthis.registerTableOption(\"groupContextMenu\", false);\n\t\tthis.registerTableOption(\"groupClickMenu\", false);\n\t\tthis.registerTableOption(\"groupDblClickMenu\", false);\n\t\t\n\t\tthis.registerColumnOption(\"headerContextMenu\");\n\t\tthis.registerColumnOption(\"headerClickMenu\");\n\t\tthis.registerColumnOption(\"headerDblClickMenu\");\n\t\tthis.registerColumnOption(\"headerMenu\");\n\t\tthis.registerColumnOption(\"headerMenuIcon\");\n\t\tthis.registerColumnOption(\"contextMenu\");\n\t\tthis.registerColumnOption(\"clickMenu\");\n\t\tthis.registerColumnOption(\"dblClickMenu\");\n\t\t\n\t}\n\t\n\tinitialize(){\n\t\tthis.deprecatedOptionsCheck();\n\t\tthis.initializeRowWatchers();\n\t\tthis.initializeGroupWatchers();\n\t\t\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t}\n\t\n\tdeprecatedOptionsCheck(){\n\t\tif(!this.deprecationCheck(\"menuContainer\", \"popupContainer\")){\n\t\t\tthis.table.options.popupContainer = this.table.options.menuContainer;\n\t\t}\n\t}\t\n\t\n\tinitializeRowWatchers(){\n\t\tif(this.table.options.rowContextMenu){\n\t\t\tthis.subscribe(\"row-contextmenu\", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu));\n\t\t\tthis.table.on(\"rowTapHold\", this.loadMenuEvent.bind(this, this.table.options.rowContextMenu));\n\t\t}\n\t\t\n\t\tif(this.table.options.rowClickMenu){\n\t\t\tthis.subscribe(\"row-click\", this.loadMenuEvent.bind(this, this.table.options.rowClickMenu));\n\t\t}\n\t\t\n\t\tif(this.table.options.rowDblClickMenu){\n\t\t\tthis.subscribe(\"row-dblclick\", this.loadMenuEvent.bind(this, this.table.options.rowDblClickMenu));\n\t\t}\n\t}\n\t\n\tinitializeGroupWatchers(){\n\t\tif(this.table.options.groupContextMenu){\n\t\t\tthis.subscribe(\"group-contextmenu\", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu));\n\t\t\tthis.table.on(\"groupTapHold\", this.loadMenuEvent.bind(this, this.table.options.groupContextMenu));\n\t\t}\n\t\t\n\t\tif(this.table.options.groupClickMenu){\n\t\t\tthis.subscribe(\"group-click\", this.loadMenuEvent.bind(this, this.table.options.groupClickMenu));\n\t\t}\n\t\t\n\t\tif(this.table.options.groupDblClickMenu){\n\t\t\tthis.subscribe(\"group-dblclick\", this.loadMenuEvent.bind(this, this.table.options.groupDblClickMenu));\n\t\t}\n\t}\n\n\tinitializeColumn(column){\n\t\tvar\tdef = column.definition;\n\t\t\n\t\t//handle column events\n\t\tif(def.headerContextMenu && !this.columnSubscribers.headerContextMenu){\n\t\t\tthis.columnSubscribers.headerContextMenu = this.loadMenuTableColumnEvent.bind(this, \"headerContextMenu\");\n\t\t\tthis.subscribe(\"column-contextmenu\", this.columnSubscribers.headerContextMenu);\n\t\t\tthis.table.on(\"headerTapHold\", this.loadMenuTableColumnEvent.bind(this, \"headerContextMenu\"));\n\t\t}\n\t\t\n\t\tif(def.headerClickMenu && !this.columnSubscribers.headerClickMenu){\n\t\t\tthis.columnSubscribers.headerClickMenu = this.loadMenuTableColumnEvent.bind(this, \"headerClickMenu\");\n\t\t\tthis.subscribe(\"column-click\", this.columnSubscribers.headerClickMenu);\n\t\t}\n\t\t\n\t\tif(def.headerDblClickMenu && !this.columnSubscribers.headerDblClickMenu){\n\t\t\tthis.columnSubscribers.headerDblClickMenu = this.loadMenuTableColumnEvent.bind(this, \"headerDblClickMenu\");\n\t\t\tthis.subscribe(\"column-dblclick\", this.columnSubscribers.headerDblClickMenu);\n\t\t}\n\t\t\n\t\tif(def.headerMenu){\n\t\t\tthis.initializeColumnHeaderMenu(column);\n\t\t}\n\t\t\n\t\t//handle cell events\n\t\tif(def.contextMenu && !this.columnSubscribers.contextMenu){\n\t\t\tthis.columnSubscribers.contextMenu = this.loadMenuTableCellEvent.bind(this, \"contextMenu\");\n\t\t\tthis.subscribe(\"cell-contextmenu\", this.columnSubscribers.contextMenu);\n\t\t\tthis.table.on(\"cellTapHold\", this.loadMenuTableCellEvent.bind(this, \"contextMenu\"));\n\t\t}\n\t\t\n\t\tif(def.clickMenu && !this.columnSubscribers.clickMenu){\n\t\t\tthis.columnSubscribers.clickMenu = this.loadMenuTableCellEvent.bind(this, \"clickMenu\");\n\t\t\tthis.subscribe(\"cell-click\", this.columnSubscribers.clickMenu);\n\t\t}\n\t\t\n\t\tif(def.dblClickMenu && !this.columnSubscribers.dblClickMenu){\n\t\t\tthis.columnSubscribers.dblClickMenu = this.loadMenuTableCellEvent.bind(this, \"dblClickMenu\");\n\t\t\tthis.subscribe(\"cell-dblclick\", this.columnSubscribers.dblClickMenu);\n\t\t}\n\t}\n\t\n\tinitializeColumnHeaderMenu(column){\n\t\tvar icon = column.definition.headerMenuIcon,\n\t\theaderMenuEl;\n\t\t\n\t\theaderMenuEl = document.createElement(\"span\");\n\t\theaderMenuEl.classList.add(\"tabulator-header-popup-button\");\n\t\t\n\t\tif(icon){\n\t\t\tif(typeof icon === \"function\"){\n\t\t\t\ticon = icon(column.getComponent());\n\t\t\t}\n\t\t\t\n\t\t\tif(icon instanceof HTMLElement){\n\t\t\t\theaderMenuEl.appendChild(icon);\n\t\t\t}else {\n\t\t\t\theaderMenuEl.innerHTML = icon;\n\t\t\t}\n\t\t}else {\n\t\t\theaderMenuEl.innerHTML = \"&vellip;\";\n\t\t}\n\t\t\n\t\theaderMenuEl.addEventListener(\"click\", (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\t\n\t\t\tthis.loadMenuEvent(column.definition.headerMenu, e, column);\n\t\t});\n\t\t\n\t\tcolumn.titleElement.insertBefore(headerMenuEl, column.titleElement.firstChild);\n\t}\n\t\n\tloadMenuTableCellEvent(option, e, cell){\n\t\tif(cell._cell){\n\t\t\tcell = cell._cell;\n\t\t}\n\t\t\n\t\tif(cell.column.definition[option]){\n\t\t\tthis.loadMenuEvent(cell.column.definition[option], e, cell);\n\t\t}\n\t}\n\t\n\tloadMenuTableColumnEvent(option, e, column){\n\t\tif(column._column){\n\t\t\tcolumn = column._column;\n\t\t}\n\t\t\n\t\tif(column.definition[option]){\n\t\t\tthis.loadMenuEvent(column.definition[option], e, column);\n\t\t}\n\t}\n\t\n\tloadMenuEvent(menu, e, component){\n\t\tif(component._group){\n\t\t\tcomponent = component._group;\n\t\t}else if(component._row){\n\t\t\tcomponent = component._row;\n\t\t}\n\t\t\n\t\tmenu = typeof menu == \"function\" ? menu.call(this.table, e, component.getComponent()) : menu;\n\t\t\n\t\tthis.loadMenu(e, component, menu);\n\t}\n\t\n\tloadMenu(e, component, menu, parentEl, parentPopup){\n\t\tvar touch = !(e instanceof MouseEvent),\t\t\n\t\tmenuEl = document.createElement(\"div\"),\n\t\tpopup;\n\t\t\n\t\tmenuEl.classList.add(\"tabulator-menu\");\n\t\t\n\t\tif(!touch){\n\t\t\te.preventDefault();\n\t\t}\n\t\t\n\t\t//abort if no menu set\n\t\tif(!menu || !menu.length){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif(!parentEl){\n\t\t\tif(this.nestedMenuBlock){\n\t\t\t\t//abort if child menu already open\n\t\t\t\tif(this.rootPopup){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.nestedMenuBlock = setTimeout(() => {\n\t\t\t\t\tthis.nestedMenuBlock = false;\n\t\t\t\t}, 100);\n\t\t\t}\n\t\t\t\n\t\t\tif(this.rootPopup){\n\t\t\t\tthis.rootPopup.hide();\t\n\t\t\t}\n\t\t\t\n\t\t\tthis.rootPopup = popup = this.popup(menuEl);\n\t\t\t\n\t\t}else {\n\t\t\tpopup = parentPopup.child(menuEl);\n\t\t}\n\t\t\n\t\tmenu.forEach((item) => {\n\t\t\tvar itemEl = document.createElement(\"div\"),\n\t\t\tlabel = item.label,\n\t\t\tdisabled = item.disabled;\n\t\t\t\n\t\t\tif(item.separator){\n\t\t\t\titemEl.classList.add(\"tabulator-menu-separator\");\n\t\t\t}else {\n\t\t\t\titemEl.classList.add(\"tabulator-menu-item\");\n\t\t\t\t\n\t\t\t\tif(typeof label == \"function\"){\n\t\t\t\t\tlabel = label.call(this.table, component.getComponent());\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(label instanceof Node){\n\t\t\t\t\titemEl.appendChild(label);\n\t\t\t\t}else {\n\t\t\t\t\titemEl.innerHTML = label;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(typeof disabled == \"function\"){\n\t\t\t\t\tdisabled = disabled.call(this.table, component.getComponent());\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(disabled){\n\t\t\t\t\titemEl.classList.add(\"tabulator-menu-item-disabled\");\n\t\t\t\t\titemEl.addEventListener(\"click\", (e) => {\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\tif(item.menu && item.menu.length){\n\t\t\t\t\t\titemEl.addEventListener(\"click\", (e) => {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\tthis.loadMenu(e, component, item.menu, itemEl, popup);\n\t\t\t\t\t\t});\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(item.action){\n\t\t\t\t\t\t\titemEl.addEventListener(\"click\", (e) => {\n\t\t\t\t\t\t\t\titem.action(e, component.getComponent());\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(item.menu && item.menu.length){\n\t\t\t\t\titemEl.classList.add(\"tabulator-menu-item-submenu\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tmenuEl.appendChild(itemEl);\n\t\t});\n\t\t\n\t\tmenuEl.addEventListener(\"click\", (e) => {\n\t\t\tif(this.rootPopup){\n\t\t\t\tthis.rootPopup.hide();\n\t\t\t}\n\t\t});\n\t\t\n\t\tpopup.show(parentEl || e);\n\t\t\n\t\tif(popup === this.rootPopup){\n\t\t\tthis.rootPopup.hideOnBlur(() => {\n\t\t\t\tthis.rootPopup = null;\n\t\t\t\t\n\t\t\t\tif(this.currentComponent){\n\t\t\t\t\tthis.dispatch(\"menu-closed\", menu, popup);\n\t\t\t\t\tthis.dispatchExternal(\"menuClosed\", this.currentComponent.getComponent());\n\t\t\t\t\tthis.currentComponent = null;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tthis.currentComponent = component;\n\t\t\t\n\t\t\tthis.dispatch(\"menu-opened\", menu, popup);\n\t\t\tthis.dispatchExternal(\"menuOpened\", component.getComponent());\n\t\t}\n\t}\n}\n\nMenu.moduleName = \"menu\";\n\nclass MoveColumns extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.placeholderElement = this.createPlaceholderElement();\n\t\tthis.hoverElement = false; //floating column header element\n\t\tthis.checkTimeout = false; //click check timeout holder\n\t\tthis.checkPeriod = 250; //period to wait on mousedown to consider this a move and not a click\n\t\tthis.moving = false; //currently moving column\n\t\tthis.toCol = false; //destination column\n\t\tthis.toColAfter = false; //position of moving column relative to the destination column\n\t\tthis.startX = 0; //starting position within header element\n\t\tthis.autoScrollMargin = 40; //auto scroll on edge when within margin\n\t\tthis.autoScrollStep = 5; //auto scroll distance in pixels\n\t\tthis.autoScrollTimeout = false; //auto scroll timeout\n\t\tthis.touchMove = false;\n\t\t\n\t\tthis.moveHover = this.moveHover.bind(this);\n\t\tthis.endMove = this.endMove.bind(this);\n\t\t\n\t\tthis.registerTableOption(\"movableColumns\", false); //enable movable columns\n\t}\n\t\n\tcreatePlaceholderElement(){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-col\");\n\t\tel.classList.add(\"tabulator-col-placeholder\");\n\t\t\n\t\treturn el;\n\t}\n\t\n\tinitialize(){\n\t\tif(this.table.options.movableColumns){\n\t\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\t\tthis.subscribe(\"alert-show\", this.abortMove.bind(this));\n\t\t}\n\t}\n\n\tabortMove(){\n\t\tclearTimeout(this.checkTimeout);\n\t}\n\t\n\tinitializeColumn(column){\n\t\tvar self = this,\n\t\tconfig = {},\n\t\tcolEl;\n\t\t\n\t\tif(!column.modules.frozen && !column.isGroup){\n\t\t\tcolEl = column.getElement();\n\t\t\t\n\t\t\tconfig.mousemove = function(e){\n\t\t\t\tif(column.parent === self.moving.parent){\n\t\t\t\t\tif((((self.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(colEl).left) + self.table.columnManager.contentsElement.scrollLeft) > (column.getWidth() / 2)){\n\t\t\t\t\t\tif(self.toCol !== column || !self.toColAfter){\n\t\t\t\t\t\t\tcolEl.parentNode.insertBefore(self.placeholderElement, colEl.nextSibling);\n\t\t\t\t\t\t\tself.moveColumn(column, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(self.toCol !== column || self.toColAfter){\n\t\t\t\t\t\t\tcolEl.parentNode.insertBefore(self.placeholderElement, colEl);\n\t\t\t\t\t\t\tself.moveColumn(column, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}.bind(self);\n\t\t\t\n\t\t\tcolEl.addEventListener(\"mousedown\", function(e){\n\t\t\t\tself.touchMove = false;\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tself.checkTimeout = setTimeout(function(){\n\t\t\t\t\t\tself.startMove(e, column);\n\t\t\t\t\t}, self.checkPeriod);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tcolEl.addEventListener(\"mouseup\", function(e){\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tif(self.checkTimeout){\n\t\t\t\t\t\tclearTimeout(self.checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tself.bindTouchEvents(column);\n\t\t}\n\t\t\n\t\tcolumn.modules.moveColumn = config;\n\t}\n\t\n\tbindTouchEvents(column){\n\t\tvar colEl = column.getElement(),\n\t\tstartXMove = false, //shifting center position of the cell\n\t\tnextCol, prevCol, nextColWidth, prevColWidth, nextColWidthLast, prevColWidthLast;\n\t\t\n\t\tcolEl.addEventListener(\"touchstart\", (e) => {\n\t\t\tthis.checkTimeout = setTimeout(() => {\n\t\t\t\tthis.touchMove = true;\n\t\t\t\tnextCol = column.nextColumn();\n\t\t\t\tnextColWidth = nextCol ? nextCol.getWidth()/2 : 0;\n\t\t\t\tprevCol = column.prevColumn();\n\t\t\t\tprevColWidth = prevCol ? prevCol.getWidth()/2 : 0;\n\t\t\t\tnextColWidthLast = 0;\n\t\t\t\tprevColWidthLast = 0;\n\t\t\t\tstartXMove = false;\n\t\t\t\t\n\t\t\t\tthis.startMove(e, column);\n\t\t\t}, this.checkPeriod);\n\t\t}, {passive: true});\n\t\t\n\t\tcolEl.addEventListener(\"touchmove\", (e) => {\n\t\t\tvar diff, moveToCol;\n\t\t\t\n\t\t\tif(this.moving){\n\t\t\t\tthis.moveHover(e);\n\t\t\t\t\n\t\t\t\tif(!startXMove){\n\t\t\t\t\tstartXMove = e.touches[0].pageX;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tdiff = e.touches[0].pageX - startXMove;\n\t\t\t\t\n\t\t\t\tif(diff > 0){\n\t\t\t\t\tif(nextCol && diff - nextColWidthLast > nextColWidth){\n\t\t\t\t\t\tmoveToCol = nextCol;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(moveToCol !== column){\n\t\t\t\t\t\t\tstartXMove = e.touches[0].pageX;\n\t\t\t\t\t\t\tmoveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement().nextSibling);\n\t\t\t\t\t\t\tthis.moveColumn(moveToCol, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tif(prevCol && -diff - prevColWidthLast >  prevColWidth){\n\t\t\t\t\t\tmoveToCol = prevCol;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(moveToCol !== column){\n\t\t\t\t\t\t\tstartXMove = e.touches[0].pageX;\n\t\t\t\t\t\t\tmoveToCol.getElement().parentNode.insertBefore(this.placeholderElement, moveToCol.getElement());\n\t\t\t\t\t\t\tthis.moveColumn(moveToCol, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(moveToCol){\n\t\t\t\t\tnextCol = moveToCol.nextColumn();\n\t\t\t\t\tnextColWidthLast = nextColWidth;\n\t\t\t\t\tnextColWidth = nextCol ? nextCol.getWidth() / 2 : 0;\n\t\t\t\t\tprevCol = moveToCol.prevColumn();\n\t\t\t\t\tprevColWidthLast = prevColWidth;\n\t\t\t\t\tprevColWidth = prevCol ? prevCol.getWidth() / 2 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}, {passive: true});\n\t\t\n\t\tcolEl.addEventListener(\"touchend\", (e) => {\n\t\t\tif(this.checkTimeout){\n\t\t\t\tclearTimeout(this.checkTimeout);\n\t\t\t}\n\t\t\tif(this.moving){\n\t\t\t\tthis.endMove(e);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tstartMove(e, column){\n\t\tvar element = column.getElement(),\n\t\theaderElement = this.table.columnManager.getContentsElement(),\n\t\theadersElement = this.table.columnManager.getHeadersElement();\n\t\t\n\t\tthis.moving = column;\n\t\tthis.startX = (this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(element).left;\n\t\t\n\t\tthis.table.element.classList.add(\"tabulator-block-select\");\n\t\t\n\t\t//create placeholder\n\t\tthis.placeholderElement.style.width = column.getWidth() + \"px\";\n\t\tthis.placeholderElement.style.height = column.getHeight() + \"px\";\n\t\t\n\t\telement.parentNode.insertBefore(this.placeholderElement, element);\n\t\telement.parentNode.removeChild(element);\n\t\t\n\t\t//create hover element\n\t\tthis.hoverElement = element.cloneNode(true);\n\t\tthis.hoverElement.classList.add(\"tabulator-moving\");\n\t\t\n\t\theaderElement.appendChild(this.hoverElement);\n\t\t\n\t\tthis.hoverElement.style.left = \"0\";\n\t\tthis.hoverElement.style.bottom = (headerElement.clientHeight - headersElement.offsetHeight) + \"px\";\n\t\t\n\t\tif(!this.touchMove){\n\t\t\tthis._bindMouseMove();\n\t\t\t\n\t\t\tdocument.body.addEventListener(\"mousemove\", this.moveHover);\n\t\t\tdocument.body.addEventListener(\"mouseup\", this.endMove);\n\t\t}\n\t\t\n\t\tthis.moveHover(e);\n\t}\n\t\n\t_bindMouseMove(){\n\t\tthis.table.columnManager.columnsByIndex.forEach(function(column){\n\t\t\tif(column.modules.moveColumn.mousemove){\n\t\t\t\tcolumn.getElement().addEventListener(\"mousemove\", column.modules.moveColumn.mousemove);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t_unbindMouseMove(){\n\t\tthis.table.columnManager.columnsByIndex.forEach(function(column){\n\t\t\tif(column.modules.moveColumn.mousemove){\n\t\t\t\tcolumn.getElement().removeEventListener(\"mousemove\", column.modules.moveColumn.mousemove);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tmoveColumn(column, after){\n\t\tvar movingCells = this.moving.getCells();\n\t\t\n\t\tthis.toCol = column;\n\t\tthis.toColAfter = after;\n\t\t\n\t\tif(after){\n\t\t\tcolumn.getCells().forEach(function(cell, i){\n\t\t\t\tvar cellEl = cell.getElement(true);\n\t\t\t\t\n\t\t\t\tif(cellEl.parentNode && movingCells[i]){\n\t\t\t\t\tcellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl.nextSibling);\n\t\t\t\t}\n\t\t\t});\n\t\t}else {\n\t\t\tcolumn.getCells().forEach(function(cell, i){\n\t\t\t\tvar cellEl = cell.getElement(true);\n\t\t\t\t\n\t\t\t\tif(cellEl.parentNode && movingCells[i]){\n\t\t\t\t\tcellEl.parentNode.insertBefore(movingCells[i].getElement(), cellEl);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\t\n\tendMove(e){\n\t\tif(e.which === 1 || this.touchMove){\n\t\t\tthis._unbindMouseMove();\n\t\t\t\n\t\t\tthis.placeholderElement.parentNode.insertBefore(this.moving.getElement(), this.placeholderElement.nextSibling);\n\t\t\tthis.placeholderElement.parentNode.removeChild(this.placeholderElement);\n\t\t\tthis.hoverElement.parentNode.removeChild(this.hoverElement);\n\t\t\t\n\t\t\tthis.table.element.classList.remove(\"tabulator-block-select\");\n\t\t\t\n\t\t\tif(this.toCol){\n\t\t\t\tthis.table.columnManager.moveColumnActual(this.moving, this.toCol, this.toColAfter);\n\t\t\t}\n\t\t\t\n\t\t\tthis.moving = false;\n\t\t\tthis.toCol = false;\n\t\t\tthis.toColAfter = false;\n\t\t\t\n\t\t\tif(!this.touchMove){\n\t\t\t\tdocument.body.removeEventListener(\"mousemove\", this.moveHover);\n\t\t\t\tdocument.body.removeEventListener(\"mouseup\", this.endMove);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tmoveHover(e){\n\t\tvar columnHolder = this.table.columnManager.getContentsElement(),\n\t\tscrollLeft = columnHolder.scrollLeft,\n\t\txPos = ((this.touchMove ? e.touches[0].pageX : e.pageX) - Helpers.elOffset(columnHolder).left) + scrollLeft,\n\t\tscrollPos;\n\t\t\n\t\tthis.hoverElement.style.left = (xPos - this.startX) + \"px\";\n\t\t\n\t\tif(xPos - scrollLeft < this.autoScrollMargin){\n\t\t\tif(!this.autoScrollTimeout){\n\t\t\t\tthis.autoScrollTimeout = setTimeout(() => {\n\t\t\t\t\tscrollPos = Math.max(0,scrollLeft-5);\n\t\t\t\t\tthis.table.rowManager.getElement().scrollLeft = scrollPos;\n\t\t\t\t\tthis.autoScrollTimeout = false;\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(scrollLeft + columnHolder.clientWidth - xPos < this.autoScrollMargin){\n\t\t\tif(!this.autoScrollTimeout){\n\t\t\t\tthis.autoScrollTimeout = setTimeout(() => {\n\t\t\t\t\tscrollPos = Math.min(columnHolder.clientWidth, scrollLeft+5);\n\t\t\t\t\tthis.table.rowManager.getElement().scrollLeft = scrollPos;\n\t\t\t\t\tthis.autoScrollTimeout = false;\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t}\n\t}\n}\n\nMoveColumns.moduleName = \"moveColumn\";\n\nclass MoveRows extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.placeholderElement = this.createPlaceholderElement();\n\t\tthis.hoverElement = false; //floating row header element\n\t\tthis.checkTimeout = false; //click check timeout holder\n\t\tthis.checkPeriod = 150; //period to wait on mousedown to consider this a move and not a click\n\t\tthis.moving = false; //currently moving row\n\t\tthis.toRow = false; //destination row\n\t\tthis.toRowAfter = false; //position of moving row relative to the destination row\n\t\tthis.hasHandle = false; //row has handle instead of fully movable row\n\t\tthis.startY = 0; //starting Y position within header element\n\t\tthis.startX = 0; //starting X position within header element\n\n\t\tthis.moveHover = this.moveHover.bind(this);\n\t\tthis.endMove = this.endMove.bind(this);\n\t\tthis.tableRowDropEvent = false;\n\n\t\tthis.touchMove = false;\n\n\t\tthis.connection = false;\n\t\tthis.connectionSelectorsTables = false;\n\t\tthis.connectionSelectorsElements = false;\n\t\tthis.connectionElements = [];\n\t\tthis.connections = [];\n\n\t\tthis.connectedTable = false;\n\t\tthis.connectedRow = false;\n\n\t\tthis.registerTableOption(\"movableRows\", false); //enable movable rows\n\t\tthis.registerTableOption(\"movableRowsConnectedTables\", false); //tables for movable rows to be connected to\n\t\tthis.registerTableOption(\"movableRowsConnectedElements\", false); //other elements for movable rows to be connected to\n\t\tthis.registerTableOption(\"movableRowsSender\", false);\n\t\tthis.registerTableOption(\"movableRowsReceiver\", \"insert\");\n\n\t\tthis.registerColumnOption(\"rowHandle\");\n\t}\n\n\tcreatePlaceholderElement(){\n\t\tvar el = document.createElement(\"div\");\n\n\t\tel.classList.add(\"tabulator-row\");\n\t\tel.classList.add(\"tabulator-row-placeholder\");\n\n\t\treturn el;\n\t}\n\n\tinitialize(){\n\t\tif(this.table.options.movableRows){\n\t\t\tthis.connectionSelectorsTables = this.table.options.movableRowsConnectedTables;\n\t\t\tthis.connectionSelectorsElements = this.table.options.movableRowsConnectedElements;\n\n\t\t\tthis.connection = this.connectionSelectorsTables || this.connectionSelectorsElements;\n\n\t\t\tthis.subscribe(\"cell-init\", this.initializeCell.bind(this));\n\t\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\t\tthis.subscribe(\"row-init\", this.initializeRow.bind(this));\n\t\t}\n\t}\n\n\tinitializeGroupHeader(group){\n\t\tvar self = this,\n\t\tconfig = {};\n\n\t\t//inter table drag drop\n\t\tconfig.mouseup = function(e){\n\t\t\tself.tableRowDrop(e, group);\n\t\t}.bind(self);\n\n\t\t//same table drag drop\n\t\tconfig.mousemove = function(e){\n\t\t\tvar rowEl;\n\n\t\t\tif(((e.pageY - Helpers.elOffset(group.element).top) + self.table.rowManager.element.scrollTop) > (group.getHeight() / 2)){\n\t\t\t\tif(self.toRow !== group || !self.toRowAfter){\n\t\t\t\t\trowEl = group.getElement();\n\t\t\t\t\trowEl.parentNode.insertBefore(self.placeholderElement, rowEl.nextSibling);\n\t\t\t\t\tself.moveRow(group, true);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(self.toRow !== group || self.toRowAfter){\n\t\t\t\t\trowEl = group.getElement();\n\t\t\t\t\tif(rowEl.previousSibling){\n\t\t\t\t\t\trowEl.parentNode.insertBefore(self.placeholderElement, rowEl);\n\t\t\t\t\t\tself.moveRow(group, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}.bind(self);\n\n\t\tgroup.modules.moveRow = config;\n\t}\n\n\tinitializeRow(row){\n\t\tvar self = this,\n\t\tconfig = {},\n\t\trowEl;\n\n\t\t//inter table drag drop\n\t\tconfig.mouseup = function(e){\n\t\t\tself.tableRowDrop(e, row);\n\t\t}.bind(self);\n\n\t\t//same table drag drop\n\t\tconfig.mousemove = function(e){\n\t\t\tvar rowEl = row.getElement();\n\n\t\t\tif(((e.pageY - Helpers.elOffset(rowEl).top) + self.table.rowManager.element.scrollTop) > (row.getHeight() / 2)){\n\t\t\t\tif(self.toRow !== row || !self.toRowAfter){\n\t\t\t\t\trowEl.parentNode.insertBefore(self.placeholderElement, rowEl.nextSibling);\n\t\t\t\t\tself.moveRow(row, true);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(self.toRow !== row || self.toRowAfter){\n\t\t\t\t\trowEl.parentNode.insertBefore(self.placeholderElement, rowEl);\n\t\t\t\t\tself.moveRow(row, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}.bind(self);\n\n\n\t\tif(!this.hasHandle){\n\n\t\t\trowEl = row.getElement();\n\n\t\t\trowEl.addEventListener(\"mousedown\", function(e){\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tself.checkTimeout = setTimeout(function(){\n\t\t\t\t\t\tself.startMove(e, row);\n\t\t\t\t\t}, self.checkPeriod);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\trowEl.addEventListener(\"mouseup\", function(e){\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tif(self.checkTimeout){\n\t\t\t\t\t\tclearTimeout(self.checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.bindTouchEvents(row, row.getElement());\n\t\t}\n\n\t\trow.modules.moveRow = config;\n\t}\n\n\tinitializeColumn(column){\n\t\tif(column.definition.rowHandle && this.table.options.movableRows !== false){\n\t\t\tthis.hasHandle = true;\n\t\t}\n\t}\n\n\tinitializeCell(cell){\n\t\tif(cell.column.definition.rowHandle && this.table.options.movableRows !== false){\n\t\t\tvar self = this,\n\t\t\tcellEl = cell.getElement(true);\n\n\t\t\tcellEl.addEventListener(\"mousedown\", function(e){\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tself.checkTimeout = setTimeout(function(){\n\t\t\t\t\t\tself.startMove(e, cell.row);\n\t\t\t\t\t}, self.checkPeriod);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tcellEl.addEventListener(\"mouseup\", function(e){\n\t\t\t\tif(e.which === 1){\n\t\t\t\t\tif(self.checkTimeout){\n\t\t\t\t\t\tclearTimeout(self.checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.bindTouchEvents(cell.row, cellEl);\n\t\t}\n\t}\n\n\tbindTouchEvents(row, element){\n\t\tvar startYMove = false, //shifting center position of the cell\n\t\tnextRow, prevRow, nextRowHeight, prevRowHeight, nextRowHeightLast, prevRowHeightLast;\n\n\t\telement.addEventListener(\"touchstart\", (e) => {\n\t\t\tthis.checkTimeout = setTimeout(() => {\n\t\t\t\tthis.touchMove = true;\n\t\t\t\tnextRow = row.nextRow();\n\t\t\t\tnextRowHeight = nextRow ? nextRow.getHeight()/2 : 0;\n\t\t\t\tprevRow = row.prevRow();\n\t\t\t\tprevRowHeight = prevRow ? prevRow.getHeight()/2 : 0;\n\t\t\t\tnextRowHeightLast = 0;\n\t\t\t\tprevRowHeightLast = 0;\n\t\t\t\tstartYMove = false;\n\n\t\t\t\tthis.startMove(e, row);\n\t\t\t}, this.checkPeriod);\n\t\t}, {passive: true});\n\t\tthis.moving, this.toRow, this.toRowAfter;\n\t\telement.addEventListener(\"touchmove\", (e) => {\n\n\t\t\tvar diff, moveToRow;\n\n\t\t\tif(this.moving){\n\t\t\t\te.preventDefault();\n\n\t\t\t\tthis.moveHover(e);\n\n\t\t\t\tif(!startYMove){\n\t\t\t\t\tstartYMove = e.touches[0].pageY;\n\t\t\t\t}\n\n\t\t\t\tdiff = e.touches[0].pageY - startYMove;\n\n\t\t\t\tif(diff > 0){\n\t\t\t\t\tif(nextRow && diff - nextRowHeightLast > nextRowHeight){\n\t\t\t\t\t\tmoveToRow = nextRow;\n\n\t\t\t\t\t\tif(moveToRow !== row){\n\t\t\t\t\t\t\tstartYMove = e.touches[0].pageY;\n\t\t\t\t\t\t\tmoveToRow.getElement().parentNode.insertBefore(this.placeholderElement, moveToRow.getElement().nextSibling);\n\t\t\t\t\t\t\tthis.moveRow(moveToRow, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tif(prevRow && -diff - prevRowHeightLast >  prevRowHeight){\n\t\t\t\t\t\tmoveToRow = prevRow;\n\n\t\t\t\t\t\tif(moveToRow !== row){\n\t\t\t\t\t\t\tstartYMove = e.touches[0].pageY;\n\t\t\t\t\t\t\tmoveToRow.getElement().parentNode.insertBefore(this.placeholderElement, moveToRow.getElement());\n\t\t\t\t\t\t\tthis.moveRow(moveToRow, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(moveToRow){\n\t\t\t\t\tnextRow = moveToRow.nextRow();\n\t\t\t\t\tnextRowHeightLast = nextRowHeight;\n\t\t\t\t\tnextRowHeight = nextRow ? nextRow.getHeight() / 2 : 0;\n\t\t\t\t\tprevRow = moveToRow.prevRow();\n\t\t\t\t\tprevRowHeightLast = prevRowHeight;\n\t\t\t\t\tprevRowHeight = prevRow ? prevRow.getHeight() / 2 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\telement.addEventListener(\"touchend\", (e) => {\n\t\t\tif(this.checkTimeout){\n\t\t\t\tclearTimeout(this.checkTimeout);\n\t\t\t}\n\t\t\tif(this.moving){\n\t\t\t\tthis.endMove(e);\n\t\t\t\tthis.touchMove = false;\n\t\t\t}\n\t\t});\n\t}\n\n\t_bindMouseMove(){\n\t\tthis.table.rowManager.getDisplayRows().forEach((row) => {\n\t\t\tif((row.type === \"row\" || row.type === \"group\") && row.modules.moveRow && row.modules.moveRow.mousemove){\n\t\t\t\trow.getElement().addEventListener(\"mousemove\", row.modules.moveRow.mousemove);\n\t\t\t}\n\t\t});\n\t}\n\n\t_unbindMouseMove(){\n\t\tthis.table.rowManager.getDisplayRows().forEach((row) => {\n\t\t\tif((row.type === \"row\" || row.type === \"group\") && row.modules.moveRow && row.modules.moveRow.mousemove){\n\t\t\t\trow.getElement().removeEventListener(\"mousemove\", row.modules.moveRow.mousemove);\n\t\t\t}\n\t\t});\n\t}\n\n\tstartMove(e, row){\n\t\tvar element = row.getElement();\n\n\t\tthis.setStartPosition(e, row);\n\n\t\tthis.moving = row;\n\n\t\tthis.table.element.classList.add(\"tabulator-block-select\");\n\n\t\t//create placeholder\n\t\tthis.placeholderElement.style.width = row.getWidth() + \"px\";\n\t\tthis.placeholderElement.style.height = row.getHeight() + \"px\";\n\n\t\tif(!this.connection){\n\t\t\telement.parentNode.insertBefore(this.placeholderElement, element);\n\t\t\telement.parentNode.removeChild(element);\n\t\t}else {\n\t\t\tthis.table.element.classList.add(\"tabulator-movingrow-sending\");\n\t\t\tthis.connectToTables(row);\n\t\t}\n\n\t\t//create hover element\n\t\tthis.hoverElement = element.cloneNode(true);\n\t\tthis.hoverElement.classList.add(\"tabulator-moving\");\n\n\t\tif(this.connection){\n\t\t\tdocument.body.appendChild(this.hoverElement);\n\t\t\tthis.hoverElement.style.left = \"0\";\n\t\t\tthis.hoverElement.style.top = \"0\";\n\t\t\tthis.hoverElement.style.width = this.table.element.clientWidth + \"px\";\n\t\t\tthis.hoverElement.style.whiteSpace = \"nowrap\";\n\t\t\tthis.hoverElement.style.overflow = \"hidden\";\n\t\t\tthis.hoverElement.style.pointerEvents = \"none\";\n\t\t}else {\n\t\t\tthis.table.rowManager.getTableElement().appendChild(this.hoverElement);\n\n\t\t\tthis.hoverElement.style.left = \"0\";\n\t\t\tthis.hoverElement.style.top = \"0\";\n\n\t\t\tthis._bindMouseMove();\n\t\t}\n\n\t\tdocument.body.addEventListener(\"mousemove\", this.moveHover);\n\t\tdocument.body.addEventListener(\"mouseup\", this.endMove);\n\n\t\tthis.dispatchExternal(\"rowMoving\", row.getComponent());\n\n\t\tthis.moveHover(e);\n\t}\n\n\tsetStartPosition(e, row){\n\t\tvar pageX = this.touchMove ? e.touches[0].pageX : e.pageX,\n\t\tpageY = this.touchMove ? e.touches[0].pageY : e.pageY,\n\t\telement, position;\n\n\t\telement = row.getElement();\n\t\tif(this.connection){\n\t\t\tposition = element.getBoundingClientRect();\n\n\t\t\tthis.startX = position.left - pageX + window.pageXOffset;\n\t\t\tthis.startY = position.top - pageY + window.pageYOffset;\n\t\t}else {\n\t\t\tthis.startY = (pageY - element.getBoundingClientRect().top);\n\t\t}\n\t}\n\n\tendMove(e){\n\t\tif(!e || e.which === 1 || this.touchMove){\n\t\t\tthis._unbindMouseMove();\n\n\t\t\tif(!this.connection){\n\t\t\t\tthis.placeholderElement.parentNode.insertBefore(this.moving.getElement(), this.placeholderElement.nextSibling);\n\t\t\t\tthis.placeholderElement.parentNode.removeChild(this.placeholderElement);\n\t\t\t}\n\n\t\t\tthis.hoverElement.parentNode.removeChild(this.hoverElement);\n\n\t\t\tthis.table.element.classList.remove(\"tabulator-block-select\");\n\n\t\t\tif(this.toRow){\n\t\t\t\tthis.table.rowManager.moveRow(this.moving, this.toRow, this.toRowAfter);\n\t\t\t}else {\n\t\t\t\tthis.dispatchExternal(\"rowMoveCancelled\", this.moving.getComponent());\n\t\t\t}\n\n\t\t\tthis.moving = false;\n\t\t\tthis.toRow = false;\n\t\t\tthis.toRowAfter = false;\n\n\t\t\tdocument.body.removeEventListener(\"mousemove\", this.moveHover);\n\t\t\tdocument.body.removeEventListener(\"mouseup\", this.endMove);\n\n\t\t\tif(this.connection){\n\t\t\t\tthis.table.element.classList.remove(\"tabulator-movingrow-sending\");\n\t\t\t\tthis.disconnectFromTables();\n\t\t\t}\n\t\t}\n\t}\n\n\tmoveRow(row, after){\n\t\tthis.toRow = row;\n\t\tthis.toRowAfter = after;\n\t}\n\n\tmoveHover(e){\n\t\tif(this.connection){\n\t\t\tthis.moveHoverConnections.call(this, e);\n\t\t}else {\n\t\t\tthis.moveHoverTable.call(this, e);\n\t\t}\n\t}\n\n\tmoveHoverTable(e){\n\t\tvar rowHolder = this.table.rowManager.getElement(),\n\t\tscrollTop = rowHolder.scrollTop,\n\t\tyPos = ((this.touchMove ? e.touches[0].pageY : e.pageY) - rowHolder.getBoundingClientRect().top) + scrollTop;\n\t\t\n\t\tthis.hoverElement.style.top = Math.min(yPos - this.startY, this.table.rowManager.element.scrollHeight - this.hoverElement.offsetHeight) + \"px\";\n\t}\n\n\tmoveHoverConnections(e){\n\t\tthis.hoverElement.style.left = (this.startX + (this.touchMove ? e.touches[0].pageX : e.pageX)) + \"px\";\n\t\tthis.hoverElement.style.top = (this.startY + (this.touchMove ? e.touches[0].pageY : e.pageY)) + \"px\";\n\t}\n\n\telementRowDrop(e, element, row){\n\t\tthis.dispatchExternal(\"movableRowsElementDrop\", e, element, row ? row.getComponent() : false);\n\t}\n\n\t//establish connection with other tables\n\tconnectToTables(row){\n\t\tvar connectionTables;\n\n\t\tif(this.connectionSelectorsTables){\n\t\t\tconnectionTables = this.commsConnections(this.connectionSelectorsTables);\n\n\t\t\tthis.dispatchExternal(\"movableRowsSendingStart\", connectionTables);\n\n\t\t\tthis.commsSend(this.connectionSelectorsTables, \"moveRow\", \"connect\", {\n\t\t\t\trow:row,\n\t\t\t});\n\t\t}\n\n\t\tif(this.connectionSelectorsElements){\n\n\t\t\tthis.connectionElements = [];\n\n\t\t\tif(!Array.isArray(this.connectionSelectorsElements)){\n\t\t\t\tthis.connectionSelectorsElements = [this.connectionSelectorsElements];\n\t\t\t}\n\n\t\t\tthis.connectionSelectorsElements.forEach((query) => {\n\t\t\t\tif(typeof query === \"string\"){\n\t\t\t\t\tthis.connectionElements = this.connectionElements.concat(Array.prototype.slice.call(document.querySelectorAll(query)));\n\t\t\t\t}else {\n\t\t\t\t\tthis.connectionElements.push(query);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.connectionElements.forEach((element) => {\n\t\t\t\tvar dropEvent = (e) => {\n\t\t\t\t\tthis.elementRowDrop(e, element, this.moving);\n\t\t\t\t};\n\n\t\t\t\telement.addEventListener(\"mouseup\", dropEvent);\n\t\t\t\telement.tabulatorElementDropEvent = dropEvent;\n\n\t\t\t\telement.classList.add(\"tabulator-movingrow-receiving\");\n\t\t\t});\n\t\t}\n\t}\n\n\t//disconnect from other tables\n\tdisconnectFromTables(){\n\t\tvar connectionTables;\n\n\t\tif(this.connectionSelectorsTables){\n\t\t\tconnectionTables = this.commsConnections(this.connectionSelectorsTables);\n\n\t\t\tthis.dispatchExternal(\"movableRowsSendingStop\", connectionTables);\n\n\t\t\tthis.commsSend(this.connectionSelectorsTables, \"moveRow\", \"disconnect\");\n\t\t}\n\n\t\tthis.connectionElements.forEach((element) => {\n\t\t\telement.classList.remove(\"tabulator-movingrow-receiving\");\n\t\t\telement.removeEventListener(\"mouseup\", element.tabulatorElementDropEvent);\n\t\t\tdelete element.tabulatorElementDropEvent;\n\t\t});\n\t}\n\n\t//accept incomming connection\n\tconnect(table, row){\n\t\tif(!this.connectedTable){\n\t\t\tthis.connectedTable = table;\n\t\t\tthis.connectedRow = row;\n\n\t\t\tthis.table.element.classList.add(\"tabulator-movingrow-receiving\");\n\n\t\t\tthis.table.rowManager.getDisplayRows().forEach((row) => {\n\t\t\t\tif(row.type === \"row\" && row.modules.moveRow && row.modules.moveRow.mouseup){\n\t\t\t\t\trow.getElement().addEventListener(\"mouseup\", row.modules.moveRow.mouseup);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.tableRowDropEvent = this.tableRowDrop.bind(this);\n\n\t\t\tthis.table.element.addEventListener(\"mouseup\", this.tableRowDropEvent);\n\n\t\t\tthis.dispatchExternal(\"movableRowsReceivingStart\", row, table);\n\n\t\t\treturn true;\n\t\t}else {\n\t\t\tconsole.warn(\"Move Row Error - Table cannot accept connection, already connected to table:\", this.connectedTable);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//close incoming connection\n\tdisconnect(table){\n\t\tif(table === this.connectedTable){\n\t\t\tthis.connectedTable = false;\n\t\t\tthis.connectedRow = false;\n\n\t\t\tthis.table.element.classList.remove(\"tabulator-movingrow-receiving\");\n\n\t\t\tthis.table.rowManager.getDisplayRows().forEach((row) =>{\n\t\t\t\tif(row.type === \"row\" && row.modules.moveRow && row.modules.moveRow.mouseup){\n\t\t\t\t\trow.getElement().removeEventListener(\"mouseup\", row.modules.moveRow.mouseup);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.table.element.removeEventListener(\"mouseup\", this.tableRowDropEvent);\n\n\t\t\tthis.dispatchExternal(\"movableRowsReceivingStop\", table);\n\t\t}else {\n\t\t\tconsole.warn(\"Move Row Error - trying to disconnect from non connected table\");\n\t\t}\n\t}\n\n\tdropComplete(table, row, success){\n\t\tvar sender = false;\n\n\t\tif(success){\n\n\t\t\tswitch(typeof this.table.options.movableRowsSender){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tsender = this.senders[this.table.options.movableRowsSender];\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"function\":\n\t\t\t\t\tsender = this.table.options.movableRowsSender;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(sender){\n\t\t\t\tsender.call(this, this.moving ? this.moving.getComponent() : undefined, row ? row.getComponent() : undefined, table);\n\t\t\t}else {\n\t\t\t\tif(this.table.options.movableRowsSender){\n\t\t\t\t\tconsole.warn(\"Mover Row Error - no matching sender found:\", this.table.options.movableRowsSender);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.dispatchExternal(\"movableRowsSent\", this.moving.getComponent(), row ? row.getComponent() : undefined, table);\n\t\t}else {\n\t\t\tthis.dispatchExternal(\"movableRowsSentFailed\", this.moving.getComponent(), row ? row.getComponent() : undefined, table);\n\t\t}\n\n\t\tthis.endMove();\n\t}\n\n\ttableRowDrop(e, row){\n\t\tvar receiver = false,\n\t\tsuccess = false;\n\n\t\te.stopImmediatePropagation();\n\n\t\tswitch(typeof this.table.options.movableRowsReceiver){\n\t\t\tcase \"string\":\n\t\t\t\treceiver = this.receivers[this.table.options.movableRowsReceiver];\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\treceiver = this.table.options.movableRowsReceiver;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(receiver){\n\t\t\tsuccess = receiver.call(this, this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable);\n\t\t}else {\n\t\t\tconsole.warn(\"Mover Row Error - no matching receiver found:\", this.table.options.movableRowsReceiver);\n\t\t}\n\n\t\tif(success){\n\t\t\tthis.dispatchExternal(\"movableRowsReceived\", this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable);\n\t\t}else {\n\t\t\tthis.dispatchExternal(\"movableRowsReceivedFailed\", this.connectedRow.getComponent(), row ? row.getComponent() : undefined, this.connectedTable);\n\t\t}\n\n\t\tthis.commsSend(this.connectedTable, \"moveRow\", \"dropcomplete\", {\n\t\t\trow:row,\n\t\t\tsuccess:success,\n\t\t});\n\t}\n\n\tcommsReceived(table, action, data){\n\t\tswitch(action){\n\t\t\tcase \"connect\":\n\t\t\t\treturn this.connect(table, data.row);\n\n\t\t\tcase \"disconnect\":\n\t\t\t\treturn this.disconnect(table);\n\n\t\t\tcase \"dropcomplete\":\n\t\t\t\treturn this.dropComplete(table, data.row, data.success);\n\t\t}\n\t}\n}\n\nMoveRows.prototype.receivers = {\n\tinsert:function(fromRow, toRow, fromTable){\n\t\tthis.table.addRow(fromRow.getData(), undefined, toRow);\n\t\treturn true;\n\t},\n\n\tadd:function(fromRow, toRow, fromTable){\n\t\tthis.table.addRow(fromRow.getData());\n\t\treturn true;\n\t},\n\n\tupdate:function(fromRow, toRow, fromTable){\n\t\tif(toRow){\n\t\t\ttoRow.update(fromRow.getData());\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t},\n\n\treplace:function(fromRow, toRow, fromTable){\n\t\tif(toRow){\n\t\t\tthis.table.addRow(fromRow.getData(), undefined, toRow);\n\t\t\ttoRow.delete();\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t},\n};\n\nMoveRows.prototype.senders = {\n\tdelete:function(fromRow, toRow, toTable){\n\t\tfromRow.delete();\n\t}\n};\n\nMoveRows.moduleName = \"moveRow\";\n\nvar defaultMutators = {};\n\nclass Mutator extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.allowedTypes = [\"\", \"data\", \"edit\", \"clipboard\"]; //list of mutation types\n\t\tthis.enabled = true;\n\n\t\tthis.registerColumnOption(\"mutator\");\n\t\tthis.registerColumnOption(\"mutatorParams\");\n\t\tthis.registerColumnOption(\"mutatorData\");\n\t\tthis.registerColumnOption(\"mutatorDataParams\");\n\t\tthis.registerColumnOption(\"mutatorEdit\");\n\t\tthis.registerColumnOption(\"mutatorEditParams\");\n\t\tthis.registerColumnOption(\"mutatorClipboard\");\n\t\tthis.registerColumnOption(\"mutatorClipboardParams\");\n\t\tthis.registerColumnOption(\"mutateLink\");\n\t}\n\n\tinitialize(){\n\t\tthis.subscribe(\"cell-value-changing\", this.transformCell.bind(this));\n\t\tthis.subscribe(\"cell-value-changed\", this.mutateLink.bind(this));\n\t\tthis.subscribe(\"column-layout\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"row-data-init-before\", this.rowDataChanged.bind(this));\n\t\tthis.subscribe(\"row-data-changing\", this.rowDataChanged.bind(this));\n\t}\n\n\trowDataChanged(row, tempData, updatedData){\n\t\treturn this.transformRow(tempData, \"data\", updatedData);\n\t}\n\n\t//initialize column mutator\n\tinitializeColumn(column){\n\t\tvar match = false,\n\t\tconfig = {};\n\n\t\tthis.allowedTypes.forEach((type) => {\n\t\t\tvar key = \"mutator\" + (type.charAt(0).toUpperCase() + type.slice(1)),\n\t\t\tmutator;\n\n\t\t\tif(column.definition[key]){\n\t\t\t\tmutator = this.lookupMutator(column.definition[key]);\n\n\t\t\t\tif(mutator){\n\t\t\t\t\tmatch = true;\n\n\t\t\t\t\tconfig[key] = {\n\t\t\t\t\t\tmutator:mutator,\n\t\t\t\t\t\tparams: column.definition[key + \"Params\"] || {},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif(match){\n\t\t\tcolumn.modules.mutate = config;\n\t\t}\n\t}\n\n\tlookupMutator(value){\n\t\tvar mutator = false;\n\n\t\t//set column mutator\n\t\tswitch(typeof value){\n\t\t\tcase \"string\":\n\t\t\t\tif(Mutator.mutators[value]){\n\t\t\t\t\tmutator = Mutator.mutators[value];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Mutator Error - No such mutator found, ignoring: \", value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"function\":\n\t\t\t\tmutator = value;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn mutator;\n\t}\n\n\t//apply mutator to row\n\ttransformRow(data, type, updatedData){\n\t\tvar key = \"mutator\" + (type.charAt(0).toUpperCase() + type.slice(1)),\n\t\tvalue;\n\n\t\tif(this.enabled){\n\n\t\t\tthis.table.columnManager.traverse((column) => {\n\t\t\t\tvar mutator, params, component;\n\n\t\t\t\tif(column.modules.mutate){\n\t\t\t\t\tmutator = column.modules.mutate[key] || column.modules.mutate.mutator || false;\n\n\t\t\t\t\tif(mutator){\n\t\t\t\t\t\tvalue = column.getFieldValue(typeof updatedData !== \"undefined\" ? updatedData : data);\n\n\t\t\t\t\t\tif((type == \"data\" && !updatedData)|| typeof value !== \"undefined\"){\n\t\t\t\t\t\t\tcomponent = column.getComponent();\n\t\t\t\t\t\t\tparams = typeof mutator.params === \"function\" ? mutator.params(value, data, type, component) : mutator.params;\n\t\t\t\t\t\t\tcolumn.setFieldValue(data, mutator.mutator(value, data, type, params, component));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn data;\n\t}\n\n\t//apply mutator to new cell value\n\ttransformCell(cell, value){\n\t\tif(cell.column.modules.mutate){\n\t\t\tvar mutator = cell.column.modules.mutate.mutatorEdit || cell.column.modules.mutate.mutator || false,\n\t\t\ttempData = {};\n\n\t\t\tif(mutator){\n\t\t\t\ttempData = Object.assign(tempData, cell.row.getData());\n\t\t\t\tcell.column.setFieldValue(tempData, value);\n\t\t\t\treturn mutator.mutator(value, tempData, \"edit\", mutator.params, cell.getComponent());\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t}\n\n\tmutateLink(cell){\n\t\tvar links = cell.column.definition.mutateLink;\n\n\t\tif(links){\n\t\t\tif(!Array.isArray(links)){\n\t\t\t\tlinks = [links];\n\t\t\t}\n\n\t\t\tlinks.forEach((link) => {\n\t\t\t\tvar linkCell = cell.row.getCell(link);\n\n\t\t\t\tif(linkCell){\n\t\t\t\t\tlinkCell.setValue(linkCell.getValue(), true, true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tenable(){\n\t\tthis.enabled = true;\n\t}\n\n\tdisable(){\n\t\tthis.enabled = false;\n\t}\n}\n\nMutator.moduleName = \"mutator\";\n\n//load defaults\nMutator.mutators = defaultMutators;\n\nfunction rows(pageSize, currentRow, currentPage, totalRows, totalPages){\n\tvar el = document.createElement(\"span\"),\n\tshowingEl = document.createElement(\"span\"),\n\tvalueEl = document.createElement(\"span\"),\n\tofEl = document.createElement(\"span\"),\n\ttotalEl = document.createElement(\"span\"),\n\trowsEl = document.createElement(\"span\");\n\n\tthis.table.modules.localize.langBind(\"pagination|counter|showing\", (value) => {\n\t\tshowingEl.innerHTML = value;\n\t});\n\n\tthis.table.modules.localize.langBind(\"pagination|counter|of\", (value) => {\n\t\tofEl.innerHTML = value;\n\t});\n\n\tthis.table.modules.localize.langBind(\"pagination|counter|rows\", (value) => {\n\t\trowsEl.innerHTML = value;\n\t});\n\n\tif(totalRows){\n\t\tvalueEl.innerHTML = \" \" + currentRow + \"-\" + Math.min((currentRow + pageSize - 1), totalRows) + \" \";\n\t\t\n\t\ttotalEl.innerHTML = \" \" + totalRows + \" \";\n\t\t\n\t\tel.appendChild(showingEl);\n\t\tel.appendChild(valueEl);\n\t\tel.appendChild(ofEl);\n\t\tel.appendChild(totalEl);\n\t\tel.appendChild(rowsEl);\n\t}else {\n\t\tvalueEl.innerHTML = \" 0 \";\n\n\t\tel.appendChild(showingEl);\n\t\tel.appendChild(valueEl);\n\t\tel.appendChild(rowsEl);\n\t}\n\t\n\treturn el;\n}\n\nfunction pages(pageSize, currentRow, currentPage, totalRows, totalPages){\n\n\tvar el = document.createElement(\"span\"),\n\tshowingEl = document.createElement(\"span\"),\n\tvalueEl = document.createElement(\"span\"),\n\tofEl = document.createElement(\"span\"),\n\ttotalEl = document.createElement(\"span\"),\n\trowsEl = document.createElement(\"span\");\n\t\n\tthis.table.modules.localize.langBind(\"pagination|counter|showing\", (value) => {\n\t\tshowingEl.innerHTML = value;\n\t});\n\t\n\tvalueEl.innerHTML = \" \" + currentPage + \" \";\n\t\n\tthis.table.modules.localize.langBind(\"pagination|counter|of\", (value) => {\n\t\tofEl.innerHTML = value;\n\t});\n\t\n\ttotalEl.innerHTML = \" \" + totalPages + \" \";\n\t\n\tthis.table.modules.localize.langBind(\"pagination|counter|pages\", (value) => {\n\t\trowsEl.innerHTML = value;\n\t});\n\t\n\tel.appendChild(showingEl);\n\tel.appendChild(valueEl);\n\tel.appendChild(ofEl);\n\tel.appendChild(totalEl);\n\tel.appendChild(rowsEl);\n\t\n\treturn el;\n}\n\nvar defaultPageCounters = {\n\trows:rows,\n\tpages:pages,\n};\n\nclass Page extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.mode = \"local\";\n\t\tthis.progressiveLoad = false;\n\t\t\n\t\tthis.element = null;\n\t\tthis.pageCounterElement = null;\n\t\tthis.pageCounter = null;\n\t\t\n\t\tthis.size = 0;\n\t\tthis.page = 1;\n\t\tthis.count = 5;\n\t\tthis.max = 1;\n\n\t\tthis.remoteRowCountEstimate = null;\n\t\t\n\t\tthis.initialLoad = true;\n\t\tthis.dataChanging = false; //flag to check if data is being changed by this module\n\t\t\n\t\tthis.pageSizes = [];\n\t\t\n\t\tthis.registerTableOption(\"pagination\", false); //set pagination type\n\t\tthis.registerTableOption(\"paginationMode\", \"local\"); //local or remote pagination\n\t\tthis.registerTableOption(\"paginationSize\", false); //set number of rows to a page\n\t\tthis.registerTableOption(\"paginationInitialPage\", 1); //initial page to show on load\n\t\tthis.registerTableOption(\"paginationCounter\", false);  // set pagination counter\n\t\tthis.registerTableOption(\"paginationCounterElement\", false);  // set pagination counter\n\t\tthis.registerTableOption(\"paginationButtonCount\", 5);  // set count of page button\n\t\tthis.registerTableOption(\"paginationSizeSelector\", false); //add pagination size selector element\n\t\tthis.registerTableOption(\"paginationElement\", false); //element to hold pagination numbers\n\t\t// this.registerTableOption(\"paginationDataSent\", {}); //pagination data sent to the server\n\t\t// this.registerTableOption(\"paginationDataReceived\", {}); //pagination data received from the server\n\t\tthis.registerTableOption(\"paginationAddRow\", \"page\"); //add rows on table or page\n\t\t\n\t\tthis.registerTableOption(\"progressiveLoad\", false); //progressive loading\n\t\tthis.registerTableOption(\"progressiveLoadDelay\", 0); //delay between requests\n\t\tthis.registerTableOption(\"progressiveLoadScrollMargin\", 0); //margin before scroll begins\n\t\t\n\t\tthis.registerTableFunction(\"setMaxPage\", this.setMaxPage.bind(this));\n\t\tthis.registerTableFunction(\"setPage\", this.setPage.bind(this));\n\t\tthis.registerTableFunction(\"setPageToRow\", this.userSetPageToRow.bind(this));\n\t\tthis.registerTableFunction(\"setPageSize\", this.userSetPageSize.bind(this));\n\t\tthis.registerTableFunction(\"getPageSize\", this.getPageSize.bind(this));\n\t\tthis.registerTableFunction(\"previousPage\", this.previousPage.bind(this));\n\t\tthis.registerTableFunction(\"nextPage\", this.nextPage.bind(this));\n\t\tthis.registerTableFunction(\"getPage\", this.getPage.bind(this));\n\t\tthis.registerTableFunction(\"getPageMax\", this.getPageMax.bind(this));\n\t\t\n\t\t//register component functions\n\t\tthis.registerComponentFunction(\"row\", \"pageTo\", this.setPageToRow.bind(this));\n\t}\n\t\n\tinitialize(){\n\t\tif(this.table.options.pagination){\n\t\t\tthis.subscribe(\"row-deleted\", this.rowsUpdated.bind(this));\n\t\t\tthis.subscribe(\"row-added\", this.rowsUpdated.bind(this));\n\t\t\tthis.subscribe(\"data-processed\", this.initialLoadComplete.bind(this));\n\t\t\tthis.subscribe(\"table-built\", this.calculatePageSizes.bind(this));\n\t\t\tthis.subscribe(\"footer-redraw\", this.footerRedraw.bind(this));\n\n\t\t\tif(this.table.options.paginationAddRow == \"page\"){\n\t\t\t\tthis.subscribe(\"row-adding-position\", this.rowAddingPosition.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.options.paginationMode === \"remote\"){\n\t\t\t\tthis.subscribe(\"data-params\", this.remotePageParams.bind(this));\n\t\t\t\tthis.subscribe(\"data-loaded\", this._parseRemoteData.bind(this));\n\t\t\t}\n\t\t\t\n\t\t\tif(this.table.options.progressiveLoad){\n\t\t\t\tconsole.error(\"Progressive Load Error - Pagination and progressive load cannot be used at the same time\");\n\t\t\t}\n\t\t\t\n\t\t\tthis.registerDisplayHandler(this.restOnRenderBefore.bind(this), 40);\n\t\t\tthis.registerDisplayHandler(this.getRows.bind(this), 50);\n\t\t\t\n\t\t\tthis.createElements();\n\t\t\tthis.initializePageCounter();\n\t\t\tthis.initializePaginator();\n\t\t}else if(this.table.options.progressiveLoad){\n\t\t\tthis.subscribe(\"data-params\", this.remotePageParams.bind(this));\n\t\t\tthis.subscribe(\"data-loaded\", this._parseRemoteData.bind(this));\n\t\t\tthis.subscribe(\"table-built\", this.calculatePageSizes.bind(this));\n\t\t\tthis.subscribe(\"data-processed\", this.initialLoadComplete.bind(this));\n\t\t\t\n\t\t\tthis.initializeProgressive(this.table.options.progressiveLoad);\n\t\t\t\n\t\t\tif(this.table.options.progressiveLoad === \"scroll\"){\n\t\t\t\tthis.subscribe(\"scroll-vertical\", this.scrollVertical.bind(this));\n\t\t\t}\n\t\t}\n\t}\n\t\n\trowAddingPosition(row, top){\n\t\tvar rowManager = this.table.rowManager,\n\t\tdisplayRows = rowManager.getDisplayRows(),\n\t\tindex;\n\t\t\n\t\tif(top){\n\t\t\tif(displayRows.length){\n\t\t\t\tindex = displayRows[0];\n\t\t\t}else {\n\t\t\t\tif(rowManager.activeRows.length){\n\t\t\t\t\tindex = rowManager.activeRows[rowManager.activeRows.length-1];\n\t\t\t\t\ttop = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tif(displayRows.length){\n\t\t\t\tindex = displayRows[displayRows.length - 1];\n\t\t\t\ttop = displayRows.length < this.size ? false : true;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn {index, top};\n\t}\n\t\n\tcalculatePageSizes(){\n\t\tvar testElRow, testElCell;\n\t\t\n\t\tif(this.table.options.paginationSize){\n\t\t\tthis.size = this.table.options.paginationSize;\n\t\t}else {\n\t\t\ttestElRow = document.createElement(\"div\");\n\t\t\ttestElRow.classList.add(\"tabulator-row\");\n\t\t\ttestElRow.style.visibility = \"hidden\";\n\t\t\t\n\t\t\ttestElCell = document.createElement(\"div\");\n\t\t\ttestElCell.classList.add(\"tabulator-cell\");\n\t\t\ttestElCell.innerHTML = \"Page Row Test\";\n\t\t\t\n\t\t\ttestElRow.appendChild(testElCell);\n\t\t\t\n\t\t\tthis.table.rowManager.getTableElement().appendChild(testElRow);\n\t\t\t\n\t\t\tthis.size = Math.floor(this.table.rowManager.getElement().clientHeight / testElRow.offsetHeight);\n\t\t\t\n\t\t\tthis.table.rowManager.getTableElement().removeChild(testElRow);\n\t\t}\n\n\t\tthis.dispatchExternal(\"pageSizeChanged\", this.size);\n\t\t\n\t\tthis.generatePageSizeSelectList();\n\t}\n\t\n\tinitialLoadComplete(){\n\t\tthis.initialLoad = false;\n\t}\n\t\n\tremotePageParams(data, config, silent, params){\n\t\tif(!this.initialLoad){\n\t\t\tif((this.progressiveLoad && !silent) || (!this.progressiveLoad && !this.dataChanging)){\n\t\t\t\tthis.reset(true);\n\t\t\t}\n\t\t}\n\t\t\n\t\t//configure request params\n\t\tparams.page = this.page;\n\t\t\n\t\t//set page size if defined\n\t\tif(this.size){\n\t\t\tparams.size = this.size;\n\t\t}\n\t\t\n\t\treturn params;\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\t\n\tuserSetPageToRow(row){\n\t\tif(this.table.options.pagination){\n\t\t\trow = this.table.rowManager.findRow(row);\n\t\t\t\n\t\t\tif(row){\n\t\t\t\treturn this.setPageToRow(row);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn Promise.reject();\n\t}\n\t\n\tuserSetPageSize(size){\n\t\tif(this.table.options.pagination){\n\t\t\tthis.setPageSize(size);\n\t\t\treturn this.setPage(1);\n\t\t}else {\n\t\t\treturn false;\n\t\t}\n\t}\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\tscrollVertical(top, dir){\n\t\tvar element, diff, margin;\n\t\tif(!dir && !this.table.dataLoader.loading){\n\t\t\telement = this.table.rowManager.getElement();\n\t\t\tdiff = element.scrollHeight - element.clientHeight - top;\n\t\t\tmargin = this.table.options.progressiveLoadScrollMargin || (element.clientHeight * 2);\n\t\t\t\n\t\t\tif(diff < margin){\n\t\t\t\tthis.nextPage()\n\t\t\t\t\t.catch(() => {}); //consume the exception thrown when on the last page\n\t\t\t}\n\t\t}\n\t}\n\t\n\trestOnRenderBefore(rows, renderInPosition){\n\t\tif(!renderInPosition){\n\t\t\tif(this.mode === \"local\"){\n\t\t\t\tthis.reset();\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn rows;\n\t}\n\t\n\trowsUpdated(){\n\t\tthis.refreshData(true, \"all\");\n\t}\n\t\n\tcreateElements(){\n\t\tvar button;\n\t\t\n\t\tthis.element = document.createElement(\"span\");\n\t\tthis.element.classList.add(\"tabulator-paginator\");\n\t\t\n\t\tthis.pagesElement = document.createElement(\"span\");\n\t\tthis.pagesElement.classList.add(\"tabulator-pages\");\n\t\t\n\t\tbutton = document.createElement(\"button\");\n\t\tbutton.classList.add(\"tabulator-page\");\n\t\tbutton.setAttribute(\"type\", \"button\");\n\t\tbutton.setAttribute(\"role\", \"button\");\n\t\tbutton.setAttribute(\"aria-label\", \"\");\n\t\tbutton.setAttribute(\"title\", \"\");\n\t\t\n\t\tthis.firstBut = button.cloneNode(true);\n\t\tthis.firstBut.setAttribute(\"data-page\", \"first\");\n\t\t\n\t\tthis.prevBut = button.cloneNode(true);\n\t\tthis.prevBut.setAttribute(\"data-page\", \"prev\");\n\t\t\n\t\tthis.nextBut = button.cloneNode(true);\n\t\tthis.nextBut.setAttribute(\"data-page\", \"next\");\n\t\t\n\t\tthis.lastBut = button.cloneNode(true);\n\t\tthis.lastBut.setAttribute(\"data-page\", \"last\");\n\t\t\n\t\tif(this.table.options.paginationSizeSelector){\n\t\t\tthis.pageSizeSelect = document.createElement(\"select\");\n\t\t\tthis.pageSizeSelect.classList.add(\"tabulator-page-size\");\n\t\t}\n\t}\n\t\n\tgeneratePageSizeSelectList(){\n\t\tvar pageSizes = [];\n\t\t\n\t\tif(this.pageSizeSelect){\n\t\t\t\n\t\t\tif(Array.isArray(this.table.options.paginationSizeSelector)){\n\t\t\t\tpageSizes = this.table.options.paginationSizeSelector;\n\t\t\t\tthis.pageSizes = pageSizes;\n\t\t\t\t\n\t\t\t\tif(this.pageSizes.indexOf(this.size) == -1){\n\t\t\t\t\tpageSizes.unshift(this.size);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\t\n\t\t\t\tif(this.pageSizes.indexOf(this.size) == -1){\n\t\t\t\t\tpageSizes = [];\n\t\t\t\t\t\n\t\t\t\t\tfor (let i = 1; i < 5; i++){\n\t\t\t\t\t\tpageSizes.push(this.size * i);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthis.pageSizes = pageSizes;\n\t\t\t\t}else {\n\t\t\t\t\tpageSizes = this.pageSizes;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\twhile(this.pageSizeSelect.firstChild) this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild);\n\t\t\t\n\t\t\tpageSizes.forEach((item) => {\n\t\t\t\tvar itemEl = document.createElement(\"option\");\n\t\t\t\titemEl.value = item;\n\t\t\t\t\n\t\t\t\tif(item === true){\n\t\t\t\t\tthis.langBind(\"pagination|all\", function(value){\n\t\t\t\t\t\titemEl.innerHTML = value;\n\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\titemEl.innerHTML = item;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tthis.pageSizeSelect.appendChild(itemEl);\n\t\t\t});\n\t\t\t\n\t\t\tthis.pageSizeSelect.value = this.size;\n\t\t}\n\t}\n\t\n\tinitializePageCounter(){\n\t\tvar counter = this.table.options.paginationCounter,\n\t\tpageCounter = null;\n\t\t\n\t\tif(counter){\n\t\t\tif(typeof counter === \"function\"){\n\t\t\t\tpageCounter = counter;\n\t\t\t}else {\n\t\t\t\tpageCounter = Page.pageCounters[counter];\n\t\t\t}\n\t\t\t\n\t\t\tif(pageCounter){\n\t\t\t\tthis.pageCounter = pageCounter;\n\t\t\t\t\n\t\t\t\tthis.pageCounterElement = document.createElement(\"span\");\n\t\t\t\tthis.pageCounterElement.classList.add(\"tabulator-page-counter\");\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Pagination Error - No such page counter found: \", counter);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//setup pagination\n\tinitializePaginator(hidden){\n\t\tvar pageSelectLabel, paginationCounterHolder;\n\t\t\n\t\tif(!hidden){\n\t\t\t//build pagination element\n\t\t\t\n\t\t\t//bind localizations\n\t\t\tthis.langBind(\"pagination|first\", (value) => {\n\t\t\t\tthis.firstBut.innerHTML = value;\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|first_title\", (value) => {\n\t\t\t\tthis.firstBut.setAttribute(\"aria-label\", value);\n\t\t\t\tthis.firstBut.setAttribute(\"title\", value);\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|prev\", (value) => {\n\t\t\t\tthis.prevBut.innerHTML = value;\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|prev_title\", (value) => {\n\t\t\t\tthis.prevBut.setAttribute(\"aria-label\", value);\n\t\t\t\tthis.prevBut.setAttribute(\"title\", value);\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|next\", (value) => {\n\t\t\t\tthis.nextBut.innerHTML = value;\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|next_title\", (value) => {\n\t\t\t\tthis.nextBut.setAttribute(\"aria-label\", value);\n\t\t\t\tthis.nextBut.setAttribute(\"title\", value);\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|last\", (value) => {\n\t\t\t\tthis.lastBut.innerHTML = value;\n\t\t\t});\n\t\t\t\n\t\t\tthis.langBind(\"pagination|last_title\", (value) => {\n\t\t\t\tthis.lastBut.setAttribute(\"aria-label\", value);\n\t\t\t\tthis.lastBut.setAttribute(\"title\", value);\n\t\t\t});\n\t\t\t\n\t\t\t//click bindings\n\t\t\tthis.firstBut.addEventListener(\"click\", () => {\n\t\t\t\tthis.setPage(1);\n\t\t\t});\n\t\t\t\n\t\t\tthis.prevBut.addEventListener(\"click\", () => {\n\t\t\t\tthis.previousPage();\n\t\t\t});\n\t\t\t\n\t\t\tthis.nextBut.addEventListener(\"click\", () => {\n\t\t\t\tthis.nextPage();\n\t\t\t});\n\t\t\t\n\t\t\tthis.lastBut.addEventListener(\"click\", () => {\n\t\t\t\tthis.setPage(this.max);\n\t\t\t});\n\t\t\t\n\t\t\tif(this.table.options.paginationElement){\n\t\t\t\tthis.element = this.table.options.paginationElement;\n\t\t\t}\n\t\t\t\n\t\t\tif(this.pageSizeSelect){\n\t\t\t\tpageSelectLabel = document.createElement(\"label\");\n\t\t\t\t\n\t\t\t\tthis.langBind(\"pagination|page_size\", (value) => {\n\t\t\t\t\tthis.pageSizeSelect.setAttribute(\"aria-label\", value);\n\t\t\t\t\tthis.pageSizeSelect.setAttribute(\"title\", value);\n\t\t\t\t\tpageSelectLabel.innerHTML = value;\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.element.appendChild(pageSelectLabel);\n\t\t\t\tthis.element.appendChild(this.pageSizeSelect);\n\t\t\t\t\n\t\t\t\tthis.pageSizeSelect.addEventListener(\"change\", (e) => {\n\t\t\t\t\tthis.setPageSize(this.pageSizeSelect.value == \"true\" ? true : this.pageSizeSelect.value);\n\t\t\t\t\tthis.setPage(1);\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t//append to DOM\n\t\t\tthis.element.appendChild(this.firstBut);\n\t\t\tthis.element.appendChild(this.prevBut);\n\t\t\tthis.element.appendChild(this.pagesElement);\n\t\t\tthis.element.appendChild(this.nextBut);\n\t\t\tthis.element.appendChild(this.lastBut);\n\t\t\t\n\t\t\tif(!this.table.options.paginationElement){\n\t\t\t\tif(this.table.options.paginationCounter){\n\n\t\t\t\t\tif(this.table.options.paginationCounterElement){\n\t\t\t\t\t\tif(this.table.options.paginationCounterElement instanceof HTMLElement){\n\t\t\t\t\t\t\tthis.table.options.paginationCounterElement.appendChild(this.pageCounterElement);\n\t\t\t\t\t\t}else if(typeof this.table.options.paginationCounterElement === \"string\"){\n\t\t\t\t\t\t\tpaginationCounterHolder = document.querySelector(this.table.options.paginationCounterElement);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(paginationCounterHolder){\n\t\t\t\t\t\t\t\tpaginationCounterHolder.appendChild(this.pageCounterElement);\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tconsole.warn(\"Pagination Error - Unable to find element matching paginationCounterElement selector:\", this.table.options.paginationCounterElement);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.footerAppend(this.pageCounterElement);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.footerAppend(this.element);\n\t\t\t}\n\t\t\t\n\t\t\tthis.page = this.table.options.paginationInitialPage;\n\t\t\tthis.count = this.table.options.paginationButtonCount;\n\t\t}\n\t\t\n\t\t//set default values\n\t\tthis.mode = this.table.options.paginationMode;\n\t}\n\t\n\tinitializeProgressive(mode){\n\t\tthis.initializePaginator(true);\n\t\tthis.mode = \"progressive_\" + mode;\n\t\tthis.progressiveLoad = true;\n\t}\n\t\n\ttrackChanges(){\n\t\tthis.dispatch(\"page-changed\");\n\t}\n\t\n\t//calculate maximum page from number of rows\n\tsetMaxRows(rowCount){\n\t\tif(!rowCount){\n\t\t\tthis.max = 1;\n\t\t}else {\n\t\t\tthis.max = this.size === true ?  1 : Math.ceil(rowCount/this.size);\n\t\t}\n\t\t\n\t\tif(this.page > this.max){\n\t\t\tthis.page = this.max;\n\t\t}\n\t}\n\t\n\t//reset to first page without triggering action\n\treset(force){\n\t\tif(!this.initialLoad){\n\t\t\tif(this.mode == \"local\" || force){\n\t\t\t\tthis.page = 1;\n\t\t\t\tthis.trackChanges();\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//set the maximum page\n\tsetMaxPage(max){\n\t\t\n\t\tmax = parseInt(max);\n\t\t\n\t\tthis.max = max || 1;\n\t\t\n\t\tif(this.page > this.max){\n\t\t\tthis.page = this.max;\n\t\t\tthis.trigger();\n\t\t}\n\t}\n\t\n\t//set current page number\n\tsetPage(page){\n\t\tswitch(page){\n\t\t\tcase \"first\":\n\t\t\t\treturn this.setPage(1);\n\t\n\t\t\tcase \"prev\":\n\t\t\t\treturn this.previousPage();\n\t\t\t\n\t\t\tcase \"next\":\n\t\t\t\treturn this.nextPage();\n\t\t\t\n\t\t\tcase \"last\":\n\t\t\t\treturn this.setPage(this.max);\n\t\t}\n\t\t\n\t\tpage = parseInt(page);\n\t\t\n\t\tif((page > 0 && page <= this.max) || this.mode !== \"local\"){\n\t\t\tthis.page = page;\n\t\t\t\n\t\t\tthis.trackChanges();\n\t\t\t\n\t\t\treturn this.trigger();\n\t\t}else {\n\t\t\tconsole.warn(\"Pagination Error - Requested page is out of range of 1 - \" + this.max + \":\", page);\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\tsetPageToRow(row){\n\t\tvar rows = this.displayRows(-1);\n\t\tvar index = rows.indexOf(row);\n\t\n\t\tif(index > -1){\n\t\t\tvar page = this.size === true ? 1 : Math.ceil((index + 1) / this.size);\n\t\t\t\n\t\t\treturn this.setPage(page);\n\t\t}else {\n\t\t\tconsole.warn(\"Pagination Error - Requested row is not visible\");\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\tsetPageSize(size){\n\t\tif(size !== true){\n\t\t\tsize = parseInt(size);\n\t\t}\n\n\t\tif(size > 0){\n\t\t\tthis.size = size;\n\t\t\tthis.dispatchExternal(\"pageSizeChanged\", size);\n\t\t}\n\t\t\n\t\tif(this.pageSizeSelect){\n\t\t\t// this.pageSizeSelect.value = size;\n\t\t\tthis.generatePageSizeSelectList();\n\t\t}\n\t\t\n\t\tthis.trackChanges();\n\t}\n\t\n\t_setPageCounter(totalRows, size, currentRow){\n\t\tvar content;\n\t\t\n\t\tif(this.pageCounter){\n\n\t\t\tif(this.mode === \"remote\"){\n\t\t\t\tsize = this.size;\n\t\t\t\tcurrentRow = ((this.page - 1) * this.size) + 1;\n\t\t\t\ttotalRows = this.remoteRowCountEstimate;\n\t\t\t}\n\n\t\t\tcontent = this.pageCounter.call(this, size, currentRow, this.page, totalRows, this.max);\n\t\t\t\n\t\t\tswitch(typeof content){\n\t\t\t\tcase \"object\":\n\t\t\t\t\tif(content instanceof Node){\n\t\t\t\t\t\n\t\t\t\t\t\t//clear previous cell contents\n\t\t\t\t\t\twhile(this.pageCounterElement.firstChild) this.pageCounterElement.removeChild(this.pageCounterElement.firstChild);\n\t\t\t\t\t\n\t\t\t\t\t\tthis.pageCounterElement.appendChild(content);\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.pageCounterElement.innerHTML = \"\";\n\t\t\t\t\t\n\t\t\t\t\t\tif(content != null){\n\t\t\t\t\t\t\tconsole.warn(\"Page Counter Error - Page Counter has returned a type of object, the only valid page counter object return is an instance of Node, the page counter returned:\", content);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"undefined\":\n\t\t\t\t\tthis.pageCounterElement.innerHTML = \"\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.pageCounterElement.innerHTML = content;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//setup the pagination buttons\n\t_setPageButtons(){\n\t\tlet leftSize = Math.floor((this.count-1) / 2);\n\t\tlet rightSize = Math.ceil((this.count-1) / 2);\n\t\tlet min = this.max - this.page + leftSize + 1 < this.count ? this.max-this.count+1: Math.max(this.page-leftSize,1);\n\t\tlet max = this.page <= rightSize? Math.min(this.count, this.max) :Math.min(this.page+rightSize, this.max);\n\t\t\n\t\twhile(this.pagesElement.firstChild) this.pagesElement.removeChild(this.pagesElement.firstChild);\n\t\t\n\t\tif(this.page == 1){\n\t\t\tthis.firstBut.disabled = true;\n\t\t\tthis.prevBut.disabled = true;\n\t\t}else {\n\t\t\tthis.firstBut.disabled = false;\n\t\t\tthis.prevBut.disabled = false;\n\t\t}\n\t\t\n\t\tif(this.page == this.max){\n\t\t\tthis.lastBut.disabled = true;\n\t\t\tthis.nextBut.disabled = true;\n\t\t}else {\n\t\t\tthis.lastBut.disabled = false;\n\t\t\tthis.nextBut.disabled = false;\n\t\t}\n\t\t\n\t\tfor(let i = min; i <= max; i++){\n\t\t\tif(i>0 && i <= this.max){\n\t\t\t\tthis.pagesElement.appendChild(this._generatePageButton(i));\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.footerRedraw();\n\t}\n\t\n\t_generatePageButton(page){\n\t\tvar button = document.createElement(\"button\");\n\t\t\n\t\tbutton.classList.add(\"tabulator-page\");\n\t\tif(page == this.page){\n\t\t\tbutton.classList.add(\"active\");\n\t\t}\n\t\t\n\t\tbutton.setAttribute(\"type\", \"button\");\n\t\tbutton.setAttribute(\"role\", \"button\");\n\t\t\n\t\tthis.langBind(\"pagination|page_title\", (value) => {\n\t\t\tbutton.setAttribute(\"aria-label\", value + \" \" + page);\n\t\t\tbutton.setAttribute(\"title\", value + \" \" + page);\n\t\t});\n\t\t\n\t\tbutton.setAttribute(\"data-page\", page);\n\t\tbutton.textContent = page;\n\t\t\n\t\tbutton.addEventListener(\"click\", (e) => {\n\t\t\tthis.setPage(page);\n\t\t});\n\t\t\n\t\treturn button;\n\t}\n\t\n\t//previous page\n\tpreviousPage(){\n\t\tif(this.page > 1){\n\t\t\tthis.page--;\n\t\t\t\n\t\t\tthis.trackChanges();\n\t\t\t\n\t\t\treturn this.trigger();\n\t\t\t\n\t\t}else {\n\t\t\tconsole.warn(\"Pagination Error - Previous page would be less than page 1:\", 0);\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\t//next page\n\tnextPage(){\n\t\tif(this.page < this.max){\n\t\t\tthis.page++;\n\t\t\t\n\t\t\tthis.trackChanges();\n\t\t\t\n\t\t\treturn this.trigger();\n\t\t\t\n\t\t}else {\n\t\t\tif(!this.progressiveLoad){\n\t\t\t\tconsole.warn(\"Pagination Error - Next page would be greater than maximum page of \" + this.max + \":\", this.max + 1);\n\t\t\t}\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\t//return current page number\n\tgetPage(){\n\t\treturn this.page;\n\t}\n\t\n\t//return max page number\n\tgetPageMax(){\n\t\treturn this.max;\n\t}\n\t\n\tgetPageSize(size){\n\t\treturn this.size;\n\t}\n\t\n\tgetMode(){\n\t\treturn this.mode;\n\t}\n\t\n\t//return appropriate rows for current page\n\tgetRows(data){\n\t\tvar actualRowPageSize = 0,\n\t\toutput, start, end, actualStartRow;\n\n\t\tvar actualRows = data.filter((row) => {\n\t\t\treturn row.type === \"row\";\n\t\t});\n\t\t\n\t\tif(this.mode == \"local\"){\n\t\t\toutput = [];\n\t\t\t\n\t\t\tthis.setMaxRows(data.length);\n\t\t\t\n\t\t\tif(this.size === true){\n\t\t\t\tstart = 0;\n\t\t\t\tend = data.length;\n\t\t\t}else {\n\t\t\t\tstart = this.size * (this.page - 1);\n\t\t\t\tend = start + parseInt(this.size);\n\t\t\t}\n\t\t\t\n\t\t\tthis._setPageButtons();\n\t\t\t\n\t\t\tfor(let i = start; i < end; i++){\n\t\t\t\tlet row = data[i];\n\n\t\t\t\tif(row){\n\t\t\t\t\toutput.push(row);\n\n\t\t\t\t\tif(row.type === \"row\"){\n\t\t\t\t\t\tif(!actualStartRow){\n\t\t\t\t\t\t\tactualStartRow = row;\n\t\t\t\t\t\t}\t\n\n\t\t\t\t\t\tactualRowPageSize++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis._setPageCounter(actualRows.length, actualRowPageSize, actualStartRow ? (actualRows.indexOf(actualStartRow) + 1) : 0);\n\t\t\t\n\t\t\treturn output;\n\t\t}else {\n\t\t\tthis._setPageButtons();\n\t\t\tthis._setPageCounter(actualRows.length);\n\t\t\t\n\t\t\treturn data.slice(0);\n\t\t}\n\t}\n\t\n\ttrigger(){\n\t\tvar left;\n\t\t\n\t\tswitch(this.mode){\n\t\t\tcase \"local\":\n\t\t\t\tleft = this.table.rowManager.scrollLeft;\n\t\t\t\n\t\t\t\tthis.refreshData();\n\t\t\t\tthis.table.rowManager.scrollHorizontal(left);\n\t\t\t\n\t\t\t\tthis.dispatchExternal(\"pageLoaded\", this.getPage());\n\t\t\t\n\t\t\t\treturn Promise.resolve();\n\t\t\t\n\t\t\tcase \"remote\":\n\t\t\t\tthis.dataChanging = true;\n\t\t\t\treturn this.reloadData(null)\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tthis.dataChanging = false;\n\t\t\t\t\t});\n\t\t\t\n\t\t\tcase \"progressive_load\":\n\t\t\tcase \"progressive_scroll\":\n\t\t\t\treturn this.reloadData(null, true);\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tconsole.warn(\"Pagination Error - no such pagination mode:\", this.mode);\n\t\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\t_parseRemoteData(data){\n\t\tvar margin;\n\t\t\n\t\tif(typeof data.last_page === \"undefined\"){\n\t\t\tconsole.warn(\"Remote Pagination Error - Server response missing '\" + (this.options(\"dataReceiveParams\").last_page || \"last_page\") + \"' property\");\n\t\t}\n\t\t\n\t\tif(data.data){\n\t\t\tthis.max = parseInt(data.last_page) || 1;\n\n\t\t\tthis.remoteRowCountEstimate = typeof data.last_row !== \"undefined\" ? data.last_row : (data.last_page * this.size - (this.page == data.last_page ? (this.size - data.data.length) : 0));\n\t\t\t\n\t\t\tif(this.progressiveLoad){\n\t\t\t\tswitch(this.mode){\n\t\t\t\t\tcase \"progressive_load\":\n\t\t\t\t\t\n\t\t\t\t\t\tif(this.page == 1){\n\t\t\t\t\t\t\tthis.table.rowManager.setData(data.data, false, this.page == 1);\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tthis.table.rowManager.addRows(data.data);\n\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\tif(this.page < this.max){\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tthis.nextPage();\n\t\t\t\t\t\t\t}, this.table.options.progressiveLoadDelay);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"progressive_scroll\":\n\t\t\t\t\t\tdata = this.page === 1 ? data.data : this.table.rowManager.getData().concat(data.data);\n\t\t\t\t\t\n\t\t\t\t\t\tthis.table.rowManager.setData(data, this.page !== 1, this.page == 1);\n\t\t\t\t\t\n\t\t\t\t\t\tmargin = this.table.options.progressiveLoadScrollMargin || (this.table.rowManager.element.clientHeight * 2);\n\t\t\t\t\t\n\t\t\t\t\t\tif(this.table.rowManager.element.scrollHeight <= (this.table.rowManager.element.clientHeight + margin)){\n\t\t\t\t\t\t\tif(this.page < this.max){\n\t\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\t\tthis.nextPage();\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn false;\n\t\t\t}else {\n\t\t\t\t// left = this.table.rowManager.scrollLeft;\n\t\t\t\tthis.dispatchExternal(\"pageLoaded\",  this.getPage());\n\t\t\t\t// this.table.rowManager.scrollHorizontal(left);\n\t\t\t\t// this.table.columnManager.scrollHorizontal(left);\n\t\t\t}\n\t\t\t\n\t\t}else {\n\t\t\tconsole.warn(\"Remote Pagination Error - Server response missing '\" + (this.options(\"dataReceiveParams\").data || \"data\") + \"' property\");\n\t\t}\n\t\t\n\t\treturn data.data;\n\t}\n\t\n\t//handle the footer element being redrawn\n\tfooterRedraw(){\n\t\tvar footer = this.table.footerManager.containerElement;\n\n\t\tif((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){\n\t\t\tthis.pagesElement.style.display = 'none';\n\t\t}else {\n\t\t\tthis.pagesElement.style.display = '';\n\t\t\t\n\t\t\tif((Math.ceil(footer.clientWidth) - footer.scrollWidth) < 0){\n\t\t\t\tthis.pagesElement.style.display = 'none';\n\t\t\t}\n\t\t}\n\t}\n}\n\nPage.moduleName = \"page\";\n\n//load defaults\nPage.pageCounters = defaultPageCounters;\n\n// read persistance information from storage\nvar defaultReaders = {\n\tlocal:function(id, type){\n\t\tvar data = localStorage.getItem(id + \"-\" + type);\n\n\t\treturn data ? JSON.parse(data) : false;\n\t},\n\tcookie:function(id, type){\n\t\tvar cookie = document.cookie,\n\t\tkey = id + \"-\" + type,\n\t\tcookiePos = cookie.indexOf(key + \"=\"),\n\t\tend, data;\n\n\t\t//if cookie exists, decode and load column data into tabulator\n\t\tif(cookiePos > -1){\n\t\t\tcookie = cookie.slice(cookiePos);\n\n\t\t\tend = cookie.indexOf(\";\");\n\n\t\t\tif(end > -1){\n\t\t\t\tcookie = cookie.slice(0, end);\n\t\t\t}\n\n\t\t\tdata = cookie.replace(key + \"=\", \"\");\n\t\t}\n\n\t\treturn data ? JSON.parse(data) : false;\n\t}\n};\n\n//write persistence information to storage\nvar defaultWriters = {\n\tlocal:function(id, type, data){\n\t\tlocalStorage.setItem(id + \"-\" + type, JSON.stringify(data));\n\t},\n\tcookie:function(id, type, data){\n\t\tvar expireDate = new Date();\n\n\t\texpireDate.setDate(expireDate.getDate() + 10000);\n\n\t\tdocument.cookie = id + \"-\" + type + \"=\" + JSON.stringify(data) + \"; expires=\" + expireDate.toUTCString();\n\t}\n};\n\nclass Persistence extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.mode = \"\";\n\t\tthis.id = \"\";\n\t\t// this.persistProps = [\"field\", \"width\", \"visible\"];\n\t\tthis.defWatcherBlock = false;\n\t\tthis.config = {};\n\t\tthis.readFunc = false;\n\t\tthis.writeFunc = false;\n\n\t\tthis.registerTableOption(\"persistence\", false);\n\t\tthis.registerTableOption(\"persistenceID\", \"\"); //key for persistent storage\n\t\tthis.registerTableOption(\"persistenceMode\", true); //mode for storing persistence information\n\t\tthis.registerTableOption(\"persistenceReaderFunc\", false); //function for handling persistence data reading\n\t\tthis.registerTableOption(\"persistenceWriterFunc\", false); //function for handling persistence data writing\n\t}\n\n\t// Test for whether localStorage is available for use.\n\tlocalStorageTest() {\n\t\tvar  testKey =  \"_tabulator_test\";\n\n\t\ttry {\n\t\t\twindow.localStorage.setItem( testKey, testKey);\n\t\t\twindow.localStorage.removeItem( testKey );\n\t\t\treturn true;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//setup parameters\n\tinitialize(){\n\t\tif(this.table.options.persistence){\n\t\t\t//determine persistent layout storage type\n\t\t\tvar mode = this.table.options.persistenceMode,\n\t\t\tid = this.table.options.persistenceID,\n\t\t\tretrievedData;\n\n\t\t\tthis.mode = mode !== true ?  mode : (this.localStorageTest() ? \"local\" : \"cookie\");\n\n\t\t\tif(this.table.options.persistenceReaderFunc){\n\t\t\t\tif(typeof this.table.options.persistenceReaderFunc === \"function\"){\n\t\t\t\t\tthis.readFunc = this.table.options.persistenceReaderFunc;\n\t\t\t\t}else {\n\t\t\t\t\tif(Persistence.readers[this.table.options.persistenceReaderFunc]){\n\t\t\t\t\t\tthis.readFunc = Persistence.readers[this.table.options.persistenceReaderFunc];\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Persistence Read Error - invalid reader set\", this.table.options.persistenceReaderFunc);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(Persistence.readers[this.mode]){\n\t\t\t\t\tthis.readFunc = Persistence.readers[this.mode];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Persistence Read Error - invalid reader set\", this.mode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(this.table.options.persistenceWriterFunc){\n\t\t\t\tif(typeof this.table.options.persistenceWriterFunc === \"function\"){\n\t\t\t\t\tthis.writeFunc = this.table.options.persistenceWriterFunc;\n\t\t\t\t}else {\n\t\t\t\t\tif(Persistence.writers[this.table.options.persistenceWriterFunc]){\n\t\t\t\t\t\tthis.writeFunc = Persistence.writers[this.table.options.persistenceWriterFunc];\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Persistence Write Error - invalid reader set\", this.table.options.persistenceWriterFunc);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(Persistence.writers[this.mode]){\n\t\t\t\t\tthis.writeFunc = Persistence.writers[this.mode];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Persistence Write Error - invalid writer set\", this.mode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//set storage tag\n\t\t\tthis.id = \"tabulator-\" + (id || (this.table.element.getAttribute(\"id\") || \"\"));\n\n\t\t\tthis.config = {\n\t\t\t\tsort:this.table.options.persistence === true || this.table.options.persistence.sort,\n\t\t\t\tfilter:this.table.options.persistence === true || this.table.options.persistence.filter,\n\t\t\t\theaderFilter:this.table.options.persistence === true || this.table.options.persistence.headerFilter,\n\t\t\t\tgroup:this.table.options.persistence === true || this.table.options.persistence.group,\n\t\t\t\tpage:this.table.options.persistence === true || this.table.options.persistence.page,\n\t\t\t\tcolumns:this.table.options.persistence === true ? [\"title\", \"width\", \"visible\"] : this.table.options.persistence.columns,\n\t\t\t};\n\n\t\t\t//load pagination data if needed\n\t\t\tif(this.config.page){\n\t\t\t\tretrievedData = this.retrieveData(\"page\");\n\n\t\t\t\tif(retrievedData){\n\t\t\t\t\tif(typeof retrievedData.paginationSize !== \"undefined\" && (this.config.page === true || this.config.page.size)){\n\t\t\t\t\t\tthis.table.options.paginationSize = retrievedData.paginationSize;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(typeof retrievedData.paginationInitialPage !== \"undefined\" && (this.config.page === true || this.config.page.page)){\n\t\t\t\t\t\tthis.table.options.paginationInitialPage = retrievedData.paginationInitialPage;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//load group data if needed\n\t\t\tif(this.config.group){\n\t\t\t\tretrievedData = this.retrieveData(\"group\");\n\n\t\t\t\tif(retrievedData){\n\t\t\t\t\tif(typeof retrievedData.groupBy !== \"undefined\" && (this.config.group === true || this.config.group.groupBy)){\n\t\t\t\t\t\tthis.table.options.groupBy = retrievedData.groupBy;\n\t\t\t\t\t}\n\t\t\t\t\tif(typeof retrievedData.groupStartOpen !== \"undefined\" && (this.config.group === true || this.config.group.groupStartOpen)){\n\t\t\t\t\t\tthis.table.options.groupStartOpen = retrievedData.groupStartOpen;\n\t\t\t\t\t}\n\t\t\t\t\tif(typeof retrievedData.groupHeader !== \"undefined\" && (this.config.group === true || this.config.group.groupHeader)){\n\t\t\t\t\t\tthis.table.options.groupHeader = retrievedData.groupHeader;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(this.config.columns){\n\t\t\t\tthis.table.options.columns = this.load(\"columns\", this.table.options.columns);\n\t\t\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\t\t\tthis.subscribe(\"column-show\", this.save.bind(this, \"columns\"));\n\t\t\t\tthis.subscribe(\"column-hide\", this.save.bind(this, \"columns\"));\n\t\t\t\tthis.subscribe(\"column-moved\", this.save.bind(this, \"columns\"));\n\t\t\t}\n\n\t\t\tthis.subscribe(\"table-built\", this.tableBuilt.bind(this), 0);\n\n\t\t\tthis.subscribe(\"table-redraw\", this.tableRedraw.bind(this));\n\n\t\t\tthis.subscribe(\"filter-changed\", this.eventSave.bind(this, \"filter\"));\n\t\t\tthis.subscribe(\"filter-changed\", this.eventSave.bind(this, \"headerFilter\"));\n\t\t\tthis.subscribe(\"sort-changed\", this.eventSave.bind(this, \"sort\"));\n\t\t\tthis.subscribe(\"group-changed\", this.eventSave.bind(this, \"group\"));\n\t\t\tthis.subscribe(\"page-changed\", this.eventSave.bind(this, \"page\"));\n\t\t\tthis.subscribe(\"column-resized\", this.eventSave.bind(this, \"columns\"));\n\t\t\tthis.subscribe(\"column-width\", this.eventSave.bind(this, \"columns\"));\n\t\t\tthis.subscribe(\"layout-refreshed\", this.eventSave.bind(this, \"columns\"));\n\t\t}\n\n\t\tthis.registerTableFunction(\"getColumnLayout\", this.getColumnLayout.bind(this));\n\t\tthis.registerTableFunction(\"setColumnLayout\", this.setColumnLayout.bind(this));\n\t}\n\n\teventSave(type){\n\t\tif(this.config[type]){\n\t\t\tthis.save(type);\n\t\t}\n\t}\n\n\ttableBuilt(){\n\t\tvar sorters, filters, headerFilters;\n\n\t\tif(this.config.sort){\n\t\t\tsorters = this.load(\"sort\");\n\n\t\t\tif(!sorters === false){\n\t\t\t\tthis.table.options.initialSort = sorters;\n\t\t\t}\n\t\t}\n\n\t\tif(this.config.filter){\n\t\t\tfilters = this.load(\"filter\");\n\n\t\t\tif(!filters === false){\n\t\t\t\tthis.table.options.initialFilter = filters;\n\t\t\t}\n\t\t}\n\t\tif(this.config.headerFilter){\n\t\t\theaderFilters = this.load(\"headerFilter\");\n\n\t\t\tif(!headerFilters === false){\n\t\t\t\tthis.table.options.initialHeaderFilter = headerFilters;\n\t\t\t}\n\t\t}\n\t\t\n\t}\n\n\ttableRedraw(force){\n\t\tif(force && this.config.columns){\n\t\t\tthis.save(\"columns\");\n\t\t}\n\t}\n\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\n\tgetColumnLayout(){\n\t\treturn this.parseColumns(this.table.columnManager.getColumns());\n\t}\n\n\tsetColumnLayout(layout){\n\t\tthis.table.columnManager.setColumns(this.mergeDefinition(this.table.options.columns, layout, true));\n\t\treturn true;\n\t}\n\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\n\tinitializeColumn(column){\n\t\tvar def, keys;\n\n\t\tif(this.config.columns){\n\t\t\tthis.defWatcherBlock = true;\n\n\t\t\tdef = column.getDefinition();\n\n\t\t\tkeys = this.config.columns === true ? Object.keys(def) : this.config.columns;\n\n\t\t\tkeys.forEach((key)=>{\n\t\t\t\tvar props = Object.getOwnPropertyDescriptor(def, key);\n\t\t\t\tvar value = def[key];\n\n\t\t\t\tif(props){\n\t\t\t\t\tObject.defineProperty(def, key, {\n\t\t\t\t\t\tset: (newValue) => {\n\t\t\t\t\t\t\tvalue = newValue;\n\n\t\t\t\t\t\t\tif(!this.defWatcherBlock){\n\t\t\t\t\t\t\t\tthis.save(\"columns\");\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif(props.set){\n\t\t\t\t\t\t\t\tprops.set(newValue);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tget:() => {\n\t\t\t\t\t\t\tif(props.get){\n\t\t\t\t\t\t\t\tprops.get();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.defWatcherBlock = false;\n\t\t}\n\t}\n\n\t//load saved definitions\n\tload(type, current){\n\t\tvar data = this.retrieveData(type);\n\n\t\tif(current){\n\t\t\tdata = data ? this.mergeDefinition(current, data) : current;\n\t\t}\n\n\t\treturn data;\n\t}\n\n\t//retrieve data from memory\n\tretrieveData(type){\n\t\treturn this.readFunc ? this.readFunc(this.id, type) : false;\n\t}\n\n\t//merge old and new column definitions\n\tmergeDefinition(oldCols, newCols, mergeAllNew){\n\t\tvar output = [];\n\n\t\tnewCols = newCols || [];\n\n\t\tnewCols.forEach((column, to) => {\n\t\t\tvar from = this._findColumn(oldCols, column),\n\t\t\tkeys;\n\n\t\t\tif(from){\n\t\t\t\tif(mergeAllNew){\n\t\t\t\t\tkeys = Object.keys(column);\n\t\t\t\t}else if(this.config.columns === true || this.config.columns == undefined){\n\t\t\t\t\tkeys =  Object.keys(from);\n\t\t\t\t\tkeys.push(\"width\");\n\t\t\t\t}else {\n\t\t\t\t\tkeys = this.config.columns;\n\t\t\t\t}\n\n\t\t\t\tkeys.forEach((key)=>{\n\t\t\t\t\tif(key !== \"columns\" && typeof column[key] !== \"undefined\"){\n\t\t\t\t\t\tfrom[key] = column[key];\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif(from.columns){\n\t\t\t\t\tfrom.columns = this.mergeDefinition(from.columns, column.columns);\n\t\t\t\t}\n\n\t\t\t\toutput.push(from);\n\t\t\t}\n\t\t});\n\n\t\toldCols.forEach((column, i) => {\n\t\t\tvar from = this._findColumn(newCols, column);\n\n\t\t\tif (!from) {\n\t\t\t\tif(output.length>i){\n\t\t\t\t\toutput.splice(i, 0, column);\n\t\t\t\t}else {\n\t\t\t\t\toutput.push(column);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\n\t//find matching columns\n\t_findColumn(columns, subject){\n\t\tvar type = subject.columns ? \"group\" : (subject.field ? \"field\" : \"object\");\n\n\t\treturn columns.find(function(col){\n\t\t\tswitch(type){\n\t\t\t\tcase \"group\":\n\t\t\t\t\treturn col.title === subject.title && col.columns.length === subject.columns.length;\n\n\t\t\t\tcase \"field\":\n\t\t\t\t\treturn col.field === subject.field;\n\n\t\t\t\tcase \"object\":\n\t\t\t\t\treturn col === subject;\n\t\t\t}\n\t\t});\n\t}\n\n\t//save data\n\tsave(type){\n\t\tvar data = {};\n\n\t\tswitch(type){\n\t\t\tcase \"columns\":\n\t\t\t\tdata = this.parseColumns(this.table.columnManager.getColumns());\n\t\t\t\tbreak;\n\n\t\t\tcase \"filter\":\n\t\t\t\tdata = this.table.modules.filter.getFilters();\n\t\t\t\tbreak;\n\n\t\t\tcase \"headerFilter\":\n\t\t\t\tdata = this.table.modules.filter.getHeaderFilters();\n\t\t\t\tbreak;\n\n\t\t\tcase \"sort\":\n\t\t\t\tdata = this.validateSorters(this.table.modules.sort.getSort());\n\t\t\t\tbreak;\n\n\t\t\tcase \"group\":\n\t\t\t\tdata = this.getGroupConfig();\n\t\t\t\tbreak;\n\n\t\t\tcase \"page\":\n\t\t\t\tdata = this.getPageConfig();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(this.writeFunc){\n\t\t\tthis.writeFunc(this.id, type, data);\n\t\t}\n\n\t}\n\n\t//ensure sorters contain no function data\n\tvalidateSorters(data){\n\t\tdata.forEach(function(item){\n\t\t\titem.column = item.field;\n\t\t\tdelete item.field;\n\t\t});\n\n\t\treturn data;\n\t}\n\n\tgetGroupConfig(){\n\t\tvar data = {};\n\n\t\tif(this.config.group){\n\t\t\tif(this.config.group === true || this.config.group.groupBy){\n\t\t\t\tdata.groupBy = this.table.options.groupBy;\n\t\t\t}\n\n\t\t\tif(this.config.group === true || this.config.group.groupStartOpen){\n\t\t\t\tdata.groupStartOpen = this.table.options.groupStartOpen;\n\t\t\t}\n\n\t\t\tif(this.config.group === true || this.config.group.groupHeader){\n\t\t\t\tdata.groupHeader = this.table.options.groupHeader;\n\t\t\t}\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tgetPageConfig(){\n\t\tvar data = {};\n\n\t\tif(this.config.page){\n\t\t\tif(this.config.page === true || this.config.page.size){\n\t\t\t\tdata.paginationSize = this.table.modules.page.getPageSize();\n\t\t\t}\n\n\t\t\tif(this.config.page === true || this.config.page.page){\n\t\t\t\tdata.paginationInitialPage = this.table.modules.page.getPage();\n\t\t\t}\n\t\t}\n\n\t\treturn data;\n\t}\n\n\n\t//parse columns for data to store\n\tparseColumns(columns){\n\t\tvar definitions = [],\n\t\texcludedKeys = [\"headerContextMenu\", \"headerMenu\", \"contextMenu\", \"clickMenu\"];\n\n\t\tcolumns.forEach((column) => {\n\t\t\tvar defStore = {},\n\t\t\tcolDef = column.getDefinition(),\n\t\t\tkeys;\n\n\t\t\tif(column.isGroup){\n\t\t\t\tdefStore.title = colDef.title;\n\t\t\t\tdefStore.columns = this.parseColumns(column.getColumns());\n\t\t\t}else {\n\t\t\t\tdefStore.field = column.getField();\n\n\t\t\t\tif(this.config.columns === true || this.config.columns == undefined){\n\t\t\t\t\tkeys =  Object.keys(colDef);\n\t\t\t\t\tkeys.push(\"width\");\n\t\t\t\t\tkeys.push(\"visible\");\n\t\t\t\t}else {\n\t\t\t\t\tkeys = this.config.columns;\n\t\t\t\t}\n\n\t\t\t\tkeys.forEach((key)=>{\n\t\t\t\t\tswitch(key){\n\t\t\t\t\t\tcase \"width\":\n\t\t\t\t\t\t\tdefStore.width = column.getWidth();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"visible\":\n\t\t\t\t\t\t\tdefStore.visible = column.visible;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tif(typeof colDef[key] !== \"function\" && excludedKeys.indexOf(key) === -1){\n\t\t\t\t\t\t\t\tdefStore[key] = colDef[key];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tdefinitions.push(defStore);\n\t\t});\n\n\t\treturn definitions;\n\t}\n}\n\nPersistence.moduleName = \"persistence\";\n\nPersistence.moduleInitOrder = -10;\n\n//load defaults\nPersistence.readers = defaultReaders;\nPersistence.writers = defaultWriters;\n\nclass Popup$1 extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.columnSubscribers = {};\n\t\t\n\t\tthis.registerTableOption(\"rowContextPopup\", false);\n\t\tthis.registerTableOption(\"rowClickPopup\", false);\n\t\tthis.registerTableOption(\"rowDblClickPopup\", false);\n\t\tthis.registerTableOption(\"groupContextPopup\", false);\n\t\tthis.registerTableOption(\"groupClickPopup\", false);\n\t\tthis.registerTableOption(\"groupDblClickPopup\", false);\n\t\t\n\t\tthis.registerColumnOption(\"headerContextPopup\");\n\t\tthis.registerColumnOption(\"headerClickPopup\");\n\t\tthis.registerColumnOption(\"headerDblClickPopup\");\n\t\tthis.registerColumnOption(\"headerPopup\");\n\t\tthis.registerColumnOption(\"headerPopupIcon\");\n\t\tthis.registerColumnOption(\"contextPopup\");\n\t\tthis.registerColumnOption(\"clickPopup\");\n\t\tthis.registerColumnOption(\"dblClickPopup\");\n\n\t\tthis.registerComponentFunction(\"cell\", \"popup\", this._componentPopupCall.bind(this));\n\t\tthis.registerComponentFunction(\"column\", \"popup\", this._componentPopupCall.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"popup\", this._componentPopupCall.bind(this));\n\t\tthis.registerComponentFunction(\"group\", \"popup\", this._componentPopupCall.bind(this));\n\t\t\n\t}\n\t\n\tinitialize(){\n\t\tthis.initializeRowWatchers();\n\t\tthis.initializeGroupWatchers();\n\t\t\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t}\n\n\t_componentPopupCall(component, contents, position){\n\t\tthis.loadPopupEvent(contents, null, component, position);\n\t}\n\t\n\tinitializeRowWatchers(){\n\t\tif(this.table.options.rowContextPopup){\n\t\t\tthis.subscribe(\"row-contextmenu\", this.loadPopupEvent.bind(this, this.table.options.rowContextPopup));\n\t\t\tthis.table.on(\"rowTapHold\", this.loadPopupEvent.bind(this, this.table.options.rowContextPopup));\n\t\t}\n\t\t\n\t\tif(this.table.options.rowClickPopup){\n\t\t\tthis.subscribe(\"row-click\", this.loadPopupEvent.bind(this, this.table.options.rowClickPopup));\n\t\t}\n\n\t\tif(this.table.options.rowDblClickPopup){\n\t\t\tthis.subscribe(\"row-dblclick\", this.loadPopupEvent.bind(this, this.table.options.rowDblClickPopup));\n\t\t}\n\t}\n\t\n\tinitializeGroupWatchers(){\n\t\tif(this.table.options.groupContextPopup){\n\t\t\tthis.subscribe(\"group-contextmenu\", this.loadPopupEvent.bind(this, this.table.options.groupContextPopup));\n\t\t\tthis.table.on(\"groupTapHold\", this.loadPopupEvent.bind(this, this.table.options.groupContextPopup));\n\t\t}\n\t\t\n\t\tif(this.table.options.groupClickPopup){\n\t\t\tthis.subscribe(\"group-click\", this.loadPopupEvent.bind(this, this.table.options.groupClickPopup));\n\t\t}\n\n\t\tif(this.table.options.groupDblClickPopup){\n\t\t\tthis.subscribe(\"group-dblclick\", this.loadPopupEvent.bind(this, this.table.options.groupDblClickPopup));\n\t\t}\n\t}\n\n\tinitializeColumn(column){\n\t\tvar def = column.definition;\n\t\t\n\t\t//handle column events\n\t\tif(def.headerContextPopup && !this.columnSubscribers.headerContextPopup){\n\t\t\tthis.columnSubscribers.headerContextPopup = this.loadPopupTableColumnEvent.bind(this, \"headerContextPopup\");\n\t\t\tthis.subscribe(\"column-contextmenu\", this.columnSubscribers.headerContextPopup);\n\t\t\tthis.table.on(\"headerTapHold\", this.loadPopupTableColumnEvent.bind(this, \"headerContextPopup\"));\n\t\t}\n\t\t\n\t\tif(def.headerClickPopup && !this.columnSubscribers.headerClickPopup){\n\t\t\tthis.columnSubscribers.headerClickPopup = this.loadPopupTableColumnEvent.bind(this, \"headerClickPopup\");\n\t\t\tthis.subscribe(\"column-click\", this.columnSubscribers.headerClickPopup);\n\t\t\n\t\t\n\t\t}if(def.headerDblClickPopup && !this.columnSubscribers.headerDblClickPopup){\n\t\t\tthis.columnSubscribers.headerDblClickPopup = this.loadPopupTableColumnEvent.bind(this, \"headerDblClickPopup\");\n\t\t\tthis.subscribe(\"column-dblclick\", this.columnSubscribers.headerDblClickPopup);\n\t\t}\n\t\t\n\t\tif(def.headerPopup){\n\t\t\tthis.initializeColumnHeaderPopup(column);\n\t\t}\n\t\t\n\t\t//handle cell events\n\t\tif(def.contextPopup && !this.columnSubscribers.contextPopup){\n\t\t\tthis.columnSubscribers.contextPopup = this.loadPopupTableCellEvent.bind(this, \"contextPopup\");\n\t\t\tthis.subscribe(\"cell-contextmenu\", this.columnSubscribers.contextPopup);\n\t\t\tthis.table.on(\"cellTapHold\", this.loadPopupTableCellEvent.bind(this, \"contextPopup\"));\n\t\t}\n\t\t\n\t\tif(def.clickPopup && !this.columnSubscribers.clickPopup){\n\t\t\tthis.columnSubscribers.clickPopup = this.loadPopupTableCellEvent.bind(this, \"clickPopup\");\n\t\t\tthis.subscribe(\"cell-click\", this.columnSubscribers.clickPopup);\n\t\t}\n\n\t\tif(def.dblClickPopup && !this.columnSubscribers.dblClickPopup){\n\t\t\tthis.columnSubscribers.dblClickPopup = this.loadPopupTableCellEvent.bind(this, \"dblClickPopup\");\n\t\t\tthis.subscribe(\"cell-click\", this.columnSubscribers.dblClickPopup);\n\t\t}\n\t}\n\t\n\tinitializeColumnHeaderPopup(column){\n\t\tvar icon = column.definition.headerPopupIcon,\n\t\theaderPopupEl;\n\t\t\n\t\theaderPopupEl = document.createElement(\"span\");\n\t\theaderPopupEl.classList.add(\"tabulator-header-popup-button\");\n\n\t\tif(icon){\n\t\t\tif(typeof icon === \"function\"){\n\t\t\t\ticon = icon(column.getComponent());\n\t\t\t}\n\n\t\t\tif(icon instanceof HTMLElement){\n\t\t\t\theaderPopupEl.appendChild(icon);\n\t\t\t}else {\n\t\t\t\theaderPopupEl.innerHTML = icon;\n\t\t\t}\n\t\t}else {\n\t\t\theaderPopupEl.innerHTML = \"&vellip;\";\n\t\t}\n\t\t\n\t\theaderPopupEl.addEventListener(\"click\", (e) => {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\t\n\t\t\tthis.loadPopupEvent(column.definition.headerPopup, e, column);\n\t\t});\n\t\t\n\t\tcolumn.titleElement.insertBefore(headerPopupEl, column.titleElement.firstChild);\n\t}\n\t\n\tloadPopupTableCellEvent(option, e, cell){\n\t\tif(cell._cell){\n\t\t\tcell = cell._cell;\n\t\t}\n\t\t\n\t\tif(cell.column.definition[option]){\n\t\t\tthis.loadPopupEvent(cell.column.definition[option], e, cell);\n\t\t}\n\t}\n\t\n\tloadPopupTableColumnEvent(option, e, column){\n\t\tif(column._column){\n\t\t\tcolumn = column._column;\n\t\t}\n\t\t\n\t\tif(column.definition[option]){\n\t\t\tthis.loadPopupEvent(column.definition[option], e, column);\n\t\t}\n\t}\n\t\n\tloadPopupEvent(contents, e, component, position){\n\t\tvar renderedCallback;\n\n\t\tfunction onRendered(callback){\n\t\t\trenderedCallback = callback;\n\t\t}\n\t\t\n\t\tif(component._group){\n\t\t\tcomponent = component._group;\n\t\t}else if(component._row){\n\t\t\tcomponent = component._row;\n\t\t}\n\t\t\n\t\tcontents = typeof contents == \"function\" ? contents.call(this.table, e, component.getComponent(),  onRendered) : contents;\n\t\t\n\t\tthis.loadPopup(e, component, contents, renderedCallback, position);\n\t}\n\t\n\tloadPopup(e, component, contents, renderedCallback, position){\n\t\tvar touch = !(e instanceof MouseEvent),\n\t\tcontentsEl, popup;\n\t\t\n\t\tif(contents instanceof HTMLElement){\n\t\t\tcontentsEl = contents;\n\t\t}else {\n\t\t\tcontentsEl = document.createElement(\"div\");\n\t\t\tcontentsEl.innerHTML = contents;\n\t\t}\n\t\t\n\t\tcontentsEl.classList.add(\"tabulator-popup\");\n\n\t\tcontentsEl.addEventListener(\"click\", (e) =>{\n\t\t\te.stopPropagation();\n\t\t});\n\n\t\tif(!touch){\n\t\t\te.preventDefault();\n\t\t}\n\t\t\n\t\tpopup = this.popup(contentsEl);\n\n\t\tif(typeof renderedCallback === \"function\"){\n\t\t\tpopup.renderCallback(renderedCallback);\n\t\t}\n\n\t\tif(e){\n\t\t\tpopup.show(e);\n\t\t}else {\n\t\t\tpopup.show(component.getElement(), position || \"center\");\n\t\t}\n\n\t\t\n\t\tpopup.hideOnBlur(() => {\n\t\t\tthis.dispatchExternal(\"popupClosed\", component.getComponent());\n\t\t});\n\n\n\n\t\tthis.dispatchExternal(\"popupOpened\", component.getComponent());\n\t}\n}\n\nPopup$1.moduleName = \"popup\";\n\nclass Print extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.element = false;\n\t\tthis.manualBlock = false;\n\t\tthis.beforeprintEventHandler = null;\n\t\tthis.afterprintEventHandler = null;\n\n\t\tthis.registerTableOption(\"printAsHtml\", false); //enable print as html\n\t\tthis.registerTableOption(\"printFormatter\", false); //printing page formatter\n\t\tthis.registerTableOption(\"printHeader\", false); //page header contents\n\t\tthis.registerTableOption(\"printFooter\", false); //page footer contents\n\t\tthis.registerTableOption(\"printStyled\", true); //enable print as html styling\n\t\tthis.registerTableOption(\"printRowRange\", \"visible\"); //restrict print to visible rows only\n\t\tthis.registerTableOption(\"printConfig\", {}); //print config options\n\n\t\tthis.registerColumnOption(\"print\");\n\t\tthis.registerColumnOption(\"titlePrint\");\n\t}\n\n\tinitialize(){\n\t\tif(this.table.options.printAsHtml){\n\t\t\tthis.beforeprintEventHandler = this.replaceTable.bind(this);\n\t\t\tthis.afterprintEventHandler = this.cleanup.bind(this);\n\n\t\t\twindow.addEventListener(\"beforeprint\", this.beforeprintEventHandler );\n\t\t\twindow.addEventListener(\"afterprint\", this.afterprintEventHandler);\n\t\t\tthis.subscribe(\"table-destroy\", this.destroy.bind(this));\n\t\t}\n\n\t\tthis.registerTableFunction(\"print\", this.printFullscreen.bind(this));\n\t}\n\n\tdestroy(){\n\t\tif(this.table.options.printAsHtml){\n\t\t\twindow.removeEventListener( \"beforeprint\", this.beforeprintEventHandler );\n\t\t\twindow.removeEventListener( \"afterprint\", this.afterprintEventHandler );\n\t\t}\n\t}\n\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\n\treplaceTable(){\n\t\tif(!this.manualBlock){\n\t\t\tthis.element = document.createElement(\"div\");\n\t\t\tthis.element.classList.add(\"tabulator-print-table\");\n\n\t\t\tthis.element.appendChild(this.table.modules.export.generateTable(this.table.options.printConfig, this.table.options.printStyled, this.table.options.printRowRange, \"print\"));\n\n\t\t\tthis.table.element.style.display = \"none\";\n\n\t\t\tthis.table.element.parentNode.insertBefore(this.element, this.table.element);\n\t\t}\n\t}\n\n\tcleanup(){\n\t\tdocument.body.classList.remove(\"tabulator-print-fullscreen-hide\");\n\n\t\tif(this.element && this.element.parentNode){\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t\tthis.table.element.style.display = \"\";\n\t\t}\n\t}\n\n\tprintFullscreen(visible, style, config){\n\t\tvar scrollX = window.scrollX,\n\t\tscrollY = window.scrollY,\n\t\theaderEl = document.createElement(\"div\"),\n\t\tfooterEl = document.createElement(\"div\"),\n\t\ttableEl = this.table.modules.export.generateTable(typeof config != \"undefined\" ? config : this.table.options.printConfig, typeof style != \"undefined\" ? style : this.table.options.printStyled, visible || this.table.options.printRowRange, \"print\"),\n\t\theaderContent, footerContent;\n\n\t\tthis.manualBlock = true;\n\n\t\tthis.element = document.createElement(\"div\");\n\t\tthis.element.classList.add(\"tabulator-print-fullscreen\");\n\n\t\tif(this.table.options.printHeader){\n\t\t\theaderEl.classList.add(\"tabulator-print-header\");\n\n\t\t\theaderContent = typeof this.table.options.printHeader == \"function\" ? this.table.options.printHeader.call(this.table) : this.table.options.printHeader;\n\n\t\t\tif(typeof headerContent == \"string\"){\n\t\t\t\theaderEl.innerHTML = headerContent;\n\t\t\t}else {\n\t\t\t\theaderEl.appendChild(headerContent);\n\t\t\t}\n\n\t\t\tthis.element.appendChild(headerEl);\n\t\t}\n\n\t\tthis.element.appendChild(tableEl);\n\n\t\tif(this.table.options.printFooter){\n\t\t\tfooterEl.classList.add(\"tabulator-print-footer\");\n\n\t\t\tfooterContent = typeof this.table.options.printFooter == \"function\" ? this.table.options.printFooter.call(this.table) : this.table.options.printFooter;\n\n\n\t\t\tif(typeof footerContent == \"string\"){\n\t\t\t\tfooterEl.innerHTML = footerContent;\n\t\t\t}else {\n\t\t\t\tfooterEl.appendChild(footerContent);\n\t\t\t}\n\n\t\t\tthis.element.appendChild(footerEl);\n\t\t}\n\n\t\tdocument.body.classList.add(\"tabulator-print-fullscreen-hide\");\n\t\tdocument.body.appendChild(this.element);\n\n\t\tif(this.table.options.printFormatter){\n\t\t\tthis.table.options.printFormatter(this.element, tableEl);\n\t\t}\n\n\t\twindow.print();\n\n\t\tthis.cleanup();\n\n\t\twindow.scrollTo(scrollX, scrollY);\n\n\t\tthis.manualBlock = false;\n\t}\n}\n\nPrint.moduleName = \"print\";\n\nclass ReactiveData extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.data = false;\n\t\tthis.blocked = false; //block reactivity while performing update\n\t\tthis.origFuncs = {}; // hold original data array functions to allow replacement after data is done with\n\t\tthis.currentVersion = 0;\n\t\t\n\t\tthis.registerTableOption(\"reactiveData\", false); //enable data reactivity\n\t}\n\t\n\tinitialize(){\n\t\tif(this.table.options.reactiveData){\n\t\t\tthis.subscribe(\"cell-value-save-before\", this.block.bind(this, \"cellsave\"));\n\t\t\tthis.subscribe(\"cell-value-save-after\", this.unblock.bind(this, \"cellsave\"));\n\t\t\tthis.subscribe(\"row-data-save-before\", this.block.bind(this, \"rowsave\"));\n\t\t\tthis.subscribe(\"row-data-save-after\", this.unblock.bind(this, \"rowsave\"));\n\t\t\tthis.subscribe(\"row-data-init-after\", this.watchRow.bind(this));\n\t\t\tthis.subscribe(\"data-processing\", this.watchData.bind(this));\n\t\t\tthis.subscribe(\"table-destroy\", this.unwatchData.bind(this));\n\t\t}\n\t}\n\t\n\twatchData(data){\n\t\tvar self = this,\n\t\tversion;\n\t\t\n\t\tthis.currentVersion ++;\n\t\t\n\t\tversion = this.currentVersion;\n\t\t\n\t\tthis.unwatchData();\n\t\t\n\t\tthis.data = data;\n\t\t\n\t\t//override array push function\n\t\tthis.origFuncs.push = data.push;\n\t\t\n\t\tObject.defineProperty(this.data, \"push\", {\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t\tvalue: function(){\n\t\t\t\tvar args = Array.from(arguments),\n\t\t\t\tresult;\n\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\t\n\t\t\t\t\tself.block(\"data-push\");\n\n\t\t\t\t\targs.forEach((arg) => {\n\t\t\t\t\t\tself.table.rowManager.addRowActual(arg, false);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tresult = self.origFuncs.push.apply(data, arguments);\n\t\t\t\t\t\n\t\t\t\t\tself.unblock(\"data-push\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn result;\n\t\t\t}\n\t\t});\n\t\t\n\t\t//override array unshift function\n\t\tthis.origFuncs.unshift = data.unshift;\n\t\t\n\t\tObject.defineProperty(this.data, \"unshift\", {\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t\tvalue: function(){\n\t\t\t\tvar args = Array.from(arguments),\n\t\t\t\tresult;\n\t\t\t\t\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\n\t\t\t\t\tself.block(\"data-unshift\");\n\t\t\t\t\t\n\t\t\t\t\targs.forEach((arg) => {\n\t\t\t\t\t\tself.table.rowManager.addRowActual(arg, true);\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tresult = self.origFuncs.unshift.apply(data, arguments);\n\t\t\t\t\t\n\t\t\t\t\tself.unblock(\"data-unshift\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn result;\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\t//override array shift function\n\t\tthis.origFuncs.shift = data.shift;\n\t\t\n\t\tObject.defineProperty(this.data, \"shift\", {\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t\tvalue: function(){\n\t\t\t\tvar row, result;\n\t\t\t\t\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\n\t\t\t\t\tself.block(\"data-shift\");\n\t\t\t\t\t\n\t\t\t\t\tif(self.data.length){\n\t\t\t\t\t\trow = self.table.rowManager.getRowFromDataObject(self.data[0]);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(row){\n\t\t\t\t\t\t\trow.deleteActual();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresult = self.origFuncs.shift.call(data);\n\n\t\t\t\t\tself.unblock(\"data-shift\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn result;\n\t\t\t}\n\t\t});\n\t\t\n\t\t//override array pop function\n\t\tthis.origFuncs.pop = data.pop;\n\t\t\n\t\tObject.defineProperty(this.data, \"pop\", {\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t\tvalue: function(){\n\t\t\t\tvar row, result;\n\t\t\t\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\n\t\t\t\t\tself.block(\"data-pop\");\n\t\t\t\t\t\n\t\t\t\t\tif(self.data.length){\n\t\t\t\t\t\trow = self.table.rowManager.getRowFromDataObject(self.data[self.data.length - 1]);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(row){\n\t\t\t\t\t\t\trow.deleteActual();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresult = self.origFuncs.pop.call(data);\n\t\t\t\t\t\n\t\t\t\t\tself.unblock(\"data-pop\");\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}\n\t\t});\n\t\t\n\t\t\n\t\t//override array splice function\n\t\tthis.origFuncs.splice = data.splice;\n\t\t\n\t\tObject.defineProperty(this.data, \"splice\", {\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t\tvalue: function(){\n\t\t\t\tvar args = Array.from(arguments),\n\t\t\t\tstart = args[0] < 0 ? data.length + args[0] : args[0],\n\t\t\t\tend = args[1],\n\t\t\t\tnewRows = args[2] ? args.slice(2) : false,\n\t\t\t\tstartRow, result;\n\t\t\t\t\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\n\t\t\t\t\tself.block(\"data-splice\");\n\t\t\t\t\t//add new rows\n\t\t\t\t\tif(newRows){\n\t\t\t\t\t\tstartRow = data[start] ? self.table.rowManager.getRowFromDataObject(data[start]) : false;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(startRow){\n\t\t\t\t\t\t\tnewRows.forEach((rowData) => {\n\t\t\t\t\t\t\t\tself.table.rowManager.addRowActual(rowData, true, startRow, true);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tnewRows = newRows.slice().reverse();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tnewRows.forEach((rowData) => {\n\t\t\t\t\t\t\t\tself.table.rowManager.addRowActual(rowData, true, false, true);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t//delete removed rows\n\t\t\t\t\tif(end !== 0){\n\t\t\t\t\t\tvar oldRows = data.slice(start, typeof args[1] === \"undefined\" ? args[1] : start + end);\n\t\t\t\t\t\t\n\t\t\t\t\t\toldRows.forEach((rowData, i) => {\n\t\t\t\t\t\t\tvar row = self.table.rowManager.getRowFromDataObject(rowData);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(row){\n\t\t\t\t\t\t\t\trow.deleteActual(i !== oldRows.length - 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif(newRows || end !== 0){\n\t\t\t\t\t\tself.table.rowManager.reRenderInPosition();\n\t\t\t\t\t}\n\n\t\t\t\t\tresult = self.origFuncs.splice.apply(data, arguments);\n\t\t\t\t\t\n\t\t\t\t\tself.unblock(\"data-splice\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn result ;\n\t\t\t}\n\t\t});\n\t}\n\t\n\tunwatchData(){\n\t\tif(this.data !== false){\n\t\t\tfor(var key in this.origFuncs){\n\t\t\t\tObject.defineProperty(this.data, key, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable:true,\n\t\t\t\t\twritable:true,\n\t\t\t\t\tvalue: this.origFuncs.key,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\t\n\twatchRow(row){\n\t\tvar data = row.getData();\n\t\t\n\t\tfor(var key in data){\n\t\t\tthis.watchKey(row, data, key);\n\t\t}\n\t\t\n\t\tif(this.table.options.dataTree){\n\t\t\tthis.watchTreeChildren(row);\n\t\t}\n\t}\n\t\n\twatchTreeChildren (row){\n\t\tvar self = this,\n\t\tchildField = row.getData()[this.table.options.dataTreeChildField],\n\t\torigFuncs = {};\n\t\t\n\t\tif(childField){\n\t\t\t\n\t\t\torigFuncs.push = childField.push;\n\t\t\t\n\t\t\tObject.defineProperty(childField, \"push\", {\n\t\t\t\tenumerable: false,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: () => {\n\t\t\t\t\tif(!self.blocked){\n\t\t\t\t\t\tself.block(\"tree-push\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar result = origFuncs.push.apply(childField, arguments);\n\t\t\t\t\t\tthis.rebuildTree(row);\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.unblock(\"tree-push\");\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\torigFuncs.unshift = childField.unshift;\n\t\t\t\n\t\t\tObject.defineProperty(childField, \"unshift\", {\n\t\t\t\tenumerable: false,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: () => {\n\t\t\t\t\tif(!self.blocked){\n\t\t\t\t\t\tself.block(\"tree-unshift\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar result =  origFuncs.unshift.apply(childField, arguments);\n\t\t\t\t\t\tthis.rebuildTree(row);\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.unblock(\"tree-unshift\");\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\torigFuncs.shift = childField.shift;\n\t\t\t\n\t\t\tObject.defineProperty(childField, \"shift\", {\n\t\t\t\tenumerable: false,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: () => {\n\t\t\t\t\tif(!self.blocked){\n\t\t\t\t\t\tself.block(\"tree-shift\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar result =  origFuncs.shift.call(childField);\n\t\t\t\t\t\tthis.rebuildTree(row);\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.unblock(\"tree-shift\");\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\torigFuncs.pop = childField.pop;\n\t\t\t\n\t\t\tObject.defineProperty(childField, \"pop\", {\n\t\t\t\tenumerable: false,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: () => {\n\t\t\t\t\tif(!self.blocked){\n\t\t\t\t\t\tself.block(\"tree-pop\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar result =  origFuncs.pop.call(childField);\n\t\t\t\t\t\tthis.rebuildTree(row);\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.unblock(\"tree-pop\");\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\torigFuncs.splice = childField.splice;\n\t\t\t\n\t\t\tObject.defineProperty(childField, \"splice\", {\n\t\t\t\tenumerable: false,\n\t\t\t\tconfigurable: true,\n\t\t\t\tvalue: () => {\n\t\t\t\t\tif(!self.blocked){\n\t\t\t\t\t\tself.block(\"tree-splice\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar result =  origFuncs.splice.apply(childField, arguments);\n\t\t\t\t\t\tthis.rebuildTree(row);\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.unblock(\"tree-splice\");\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\t\n\trebuildTree(row){\n\t\tthis.table.modules.dataTree.initializeRow(row);\n\t\tthis.table.modules.dataTree.layoutRow(row);\n\t\tthis.table.rowManager.refreshActiveData(\"tree\", false, true);\n\t}\n\t\n\twatchKey(row, data, key){\n\t\tvar self = this,\n\t\tprops = Object.getOwnPropertyDescriptor(data, key),\n\t\tvalue = data[key],\n\t\tversion = this.currentVersion;\n\t\t\n\t\tObject.defineProperty(data, key, {\n\t\t\tset: (newValue) => {\n\t\t\t\tvalue = newValue;\n\t\t\t\tif(!self.blocked && version === self.currentVersion){\n\t\t\t\t\tself.block(\"key\");\n\t\t\t\t\t\n\t\t\t\t\tvar update = {};\n\t\t\t\t\tupdate[key] = newValue;\n\t\t\t\t\trow.updateData(update);\n\t\t\t\t\t\n\t\t\t\t\tself.unblock(\"key\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(props.set){\n\t\t\t\t\tprops.set(newValue);\n\t\t\t\t}\n\t\t\t},\n\t\t\tget:() => {\n\t\t\t\t\n\t\t\t\tif(props.get){\n\t\t\t\t\tprops.get();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn value;\n\t\t\t}\n\t\t});\n\t}\n\t\n\tunwatchRow(row){\n\t\tvar data = row.getData();\n\t\t\n\t\tfor(var key in data){\n\t\t\tObject.defineProperty(data, key, {\n\t\t\t\tvalue:data[key],\n\t\t\t});\n\t\t}\n\t}\n\t\n\tblock(key){\n\t\tif(!this.blocked){\n\t\t\tthis.blocked = key;\n\t\t}\n\t}\n\t\n\tunblock(key){\n\t\tif(this.blocked === key){\n\t\t\tthis.blocked = false;\n\t\t}\n\t}\n}\n\nReactiveData.moduleName = \"reactiveData\";\n\nclass ResizeColumns extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.startColumn = false;\n\t\tthis.startX = false;\n\t\tthis.startWidth = false;\n\t\tthis.latestX = false;\n\t\tthis.handle = null;\n\t\tthis.initialNextColumn = null;\n\t\tthis.nextColumn = null;\n\t\t\n\t\tthis.initialized = false;\n\t\tthis.registerColumnOption(\"resizable\", true);\n\t\tthis.registerTableOption(\"resizableColumnFit\", false);\n\t}\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"column-rendered\", this.layoutColumnHeader.bind(this));\n\t}\n\t\n\tinitializeEventWatchers(){\n\t\tif(!this.initialized){\n\t\t\t\n\t\t\tthis.subscribe(\"cell-rendered\", this.layoutCellHandles.bind(this));\n\t\t\tthis.subscribe(\"cell-delete\", this.deInitializeComponent.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"cell-height\", this.resizeHandle.bind(this));\n\t\t\tthis.subscribe(\"column-moved\", this.columnLayoutUpdated.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"column-hide\", this.deInitializeColumn.bind(this));\n\t\t\tthis.subscribe(\"column-show\", this.columnLayoutUpdated.bind(this));\n\t\t\tthis.subscribe(\"column-width\", this.columnWidthUpdated.bind(this));\n\t\t\t\n\t\t\tthis.subscribe(\"column-delete\", this.deInitializeComponent.bind(this));\n\t\t\tthis.subscribe(\"column-height\", this.resizeHandle.bind(this));\n\t\t\t\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\t\n\t\n\tlayoutCellHandles(cell){\n\t\tif(cell.row.type === \"row\"){\n\t\t\tthis.deInitializeComponent(cell);\n\t\t\tthis.initializeColumn(\"cell\", cell, cell.column, cell.element);\n\t\t}\n\t}\n\t\n\tlayoutColumnHeader(column){\n\t\tif(column.definition.resizable){\n\t\t\tthis.initializeEventWatchers();\n\t\t\tthis.deInitializeComponent(column);\n\t\t\tthis.initializeColumn(\"header\", column, column, column.element);\n\t\t}\n\t}\n\t\n\tcolumnLayoutUpdated(column){\n\t\tvar prev = column.prevColumn();\n\t\t\n\t\tthis.reinitializeColumn(column);\n\t\t\n\t\tif(prev){\n\t\t\tthis.reinitializeColumn(prev);\n\t\t}\n\t}\n\t\n\tcolumnWidthUpdated(column){\n\t\tif(column.modules.frozen){\n\t\t\tif(this.table.modules.frozenColumns.leftColumns.includes(column)){\n\t\t\t\tthis.table.modules.frozenColumns.leftColumns.forEach((col) => {\n\t\t\t\t\tthis.reinitializeColumn(col);\n\t\t\t\t});\n\t\t\t}else if(this.table.modules.frozenColumns.rightColumns.includes(column)){\n\t\t\t\tthis.table.modules.frozenColumns.rightColumns.forEach((col) => {\n\t\t\t\t\tthis.reinitializeColumn(col);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfrozenColumnOffset(column){\n\t\tvar offset = false;\n\n\t\tif(column.modules.frozen){\n\t\t\toffset = column.modules.frozen.marginValue; \n\n\t\t\tif(column.modules.frozen.position === \"left\"){\n\t\t\t\toffset += column.getWidth() - 3;\n\t\t\t}else {\n\t\t\t\tif(offset){\n\t\t\t\t\toffset -= 3;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn offset !== false ? offset + \"px\" : false;\n\t}\n\t\n\treinitializeColumn(column){\n\t\tvar frozenOffset = this.frozenColumnOffset(column);\n\t\t\n\t\tcolumn.cells.forEach((cell) => {\n\t\t\tif(cell.modules.resize && cell.modules.resize.handleEl){\n\t\t\t\tif(frozenOffset){\n\t\t\t\t\tcell.modules.resize.handleEl.style[column.modules.frozen.position] = frozenOffset;\n\t\t\t\t\tcell.modules.resize.handleEl.style[\"z-index\"] = 11;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcell.element.after(cell.modules.resize.handleEl);\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(column.modules.resize && column.modules.resize.handleEl){\n\t\t\tif(frozenOffset){\n\t\t\t\tcolumn.modules.resize.handleEl.style[column.modules.frozen.position] = frozenOffset;\n\t\t\t}\n\t\t\t\n\t\t\tcolumn.element.after(column.modules.resize.handleEl);\n\t\t}\n\t}\n\t\n\tinitializeColumn(type, component, column, element){\n\t\tvar self = this,\n\t\tvariableHeight = false,\n\t\tmode = column.definition.resizable,\n\t\tconfig = {},\n\t\tnearestColumn = column.getLastColumn();\n\t\t\n\t\t//set column resize mode\n\t\tif(type === \"header\"){\n\t\t\tvariableHeight = column.definition.formatter == \"textarea\" || column.definition.variableHeight;\n\t\t\tconfig = {variableHeight:variableHeight};\n\t\t}\n\t\t\n\t\tif((mode === true || mode == type) && this._checkResizability(nearestColumn)){\n\t\t\t\n\t\t\tvar handle = document.createElement('span');\n\t\t\thandle.className = \"tabulator-col-resize-handle\";\n\t\t\t\n\t\t\thandle.addEventListener(\"click\", function(e){\n\t\t\t\te.stopPropagation();\n\t\t\t});\n\t\t\t\n\t\t\tvar handleDown = function(e){\n\t\t\t\tself.startColumn = column;\n\t\t\t\tself.initialNextColumn = self.nextColumn = nearestColumn.nextColumn();\n\t\t\t\tself._mouseDown(e, nearestColumn, handle);\n\t\t\t};\n\t\t\t\n\t\t\thandle.addEventListener(\"mousedown\", handleDown);\n\t\t\thandle.addEventListener(\"touchstart\", handleDown, {passive: true});\n\t\t\t\n\t\t\t//resize column on  double click\n\t\t\thandle.addEventListener(\"dblclick\", (e) => {\n\t\t\t\tvar oldWidth = nearestColumn.getWidth();\n\t\t\t\t\n\t\t\t\te.stopPropagation();\n\t\t\t\tnearestColumn.reinitializeWidth(true);\n\t\t\t\t\n\t\t\t\tif(oldWidth !== nearestColumn.getWidth()){\n\t\t\t\t\tself.dispatch(\"column-resized\", nearestColumn);\n\t\t\t\t\tself.table.externalEvents.dispatch(\"columnResized\", nearestColumn.getComponent());\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tif(column.modules.frozen){\n\t\t\t\thandle.style.position = \"sticky\";\n\t\t\t\thandle.style[column.modules.frozen.position] = this.frozenColumnOffset(column);\n\t\t\t}\n\t\t\t\n\t\t\tconfig.handleEl = handle;\n\t\t\t\n\t\t\tif(element.parentNode && column.visible){\n\t\t\t\telement.after(handle);\t\t\t\n\t\t\t}\n\t\t}\n\t\t\n\t\tcomponent.modules.resize = config;\n\t}\n\t\n\tdeInitializeColumn(column){\n\t\tthis.deInitializeComponent(column);\n\t\t\n\t\tcolumn.cells.forEach((cell) => {\n\t\t\tthis.deInitializeComponent(cell);\n\t\t});\n\t}\n\t\n\tdeInitializeComponent(component){\n\t\tvar handleEl;\n\t\t\n\t\tif(component.modules.resize){\n\t\t\thandleEl = component.modules.resize.handleEl;\n\t\t\t\n\t\t\tif(handleEl && handleEl.parentElement){\n\t\t\t\thandleEl.parentElement.removeChild(handleEl);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tresizeHandle(component, height){\n\t\tif(component.modules.resize && component.modules.resize.handleEl){\n\t\t\tcomponent.modules.resize.handleEl.style.height = height;\n\t\t}\n\t}\n\t\n\t_checkResizability(column){\n\t\treturn column.definition.resizable;\n\t}\n\t\n\t_mouseDown(e, column, handle){\n\t\tvar self = this;\n\t\t\n\t\tself.table.element.classList.add(\"tabulator-block-select\");\n\t\t\n\t\tfunction mouseMove(e){\n\t\t\tvar x = typeof e.screenX === \"undefined\" ? e.touches[0].screenX : e.screenX,\n\t\t\tstartDiff = x - self.startX,\n\t\t\tmoveDiff = x - self.latestX,\n\t\t\tblockedBefore, blockedAfter;\n\t\t\t\n\t\t\tself.latestX = x;\n\t\t\t\n\t\t\tif(self.table.rtl){\n\t\t\t\tstartDiff = -startDiff;\n\t\t\t\tmoveDiff = -moveDiff;\n\t\t\t}\n\t\t\t\n\t\t\tblockedBefore = column.width == column.minWidth || column.width == column.maxWidth;\n\t\t\t\n\t\t\tcolumn.setWidth(self.startWidth + startDiff);\n\t\t\t\n\t\t\tblockedAfter = column.width == column.minWidth || column.width == column.maxWidth;\n\t\t\t\n\t\t\tif(moveDiff < 0){\n\t\t\t\tself.nextColumn = self.initialNextColumn;\n\t\t\t}\n\t\t\t\n\t\t\tif(self.table.options.resizableColumnFit && self.nextColumn && !(blockedBefore && blockedAfter)){\n\t\t\t\tlet colWidth = self.nextColumn.getWidth();\n\t\t\t\t\n\t\t\t\tif(moveDiff > 0){\n\t\t\t\t\tif(colWidth <= self.nextColumn.minWidth){\n\t\t\t\t\t\tself.nextColumn = self.nextColumn.nextColumn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(self.nextColumn){\n\t\t\t\t\tself.nextColumn.setWidth(self.nextColumn.getWidth() - moveDiff);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tself.table.columnManager.rerenderColumns(true);\n\t\t\t\n\t\t\tif(!self.table.browserSlow && column.modules.resize && column.modules.resize.variableHeight){\n\t\t\t\tcolumn.checkCellHeights();\n\t\t\t}\n\t\t}\n\t\t\n\t\tfunction mouseUp(e){\n\t\t\t\n\t\t\t//block editor from taking action while resizing is taking place\n\t\t\tif(self.startColumn.modules.edit){\n\t\t\t\tself.startColumn.modules.edit.blocked = false;\n\t\t\t}\n\t\t\t\n\t\t\tif(self.table.browserSlow && column.modules.resize && column.modules.resize.variableHeight){\n\t\t\t\tcolumn.checkCellHeights();\n\t\t\t}\n\t\t\t\n\t\t\tdocument.body.removeEventListener(\"mouseup\", mouseUp);\n\t\t\tdocument.body.removeEventListener(\"mousemove\", mouseMove);\n\t\t\t\n\t\t\thandle.removeEventListener(\"touchmove\", mouseMove);\n\t\t\thandle.removeEventListener(\"touchend\", mouseUp);\n\t\t\t\n\t\t\tself.table.element.classList.remove(\"tabulator-block-select\");\n\t\t\t\n\t\t\tif(self.startWidth !== column.getWidth()){\n\t\t\t\tself.table.columnManager.verticalAlignHeaders();\n\n\t\t\t\tself.dispatch(\"column-resized\", column);\n\t\t\t\tself.table.externalEvents.dispatch(\"columnResized\", column.getComponent());\n\t\t\t}\n\t\t}\n\t\t\n\t\te.stopPropagation(); //prevent resize from interfering with movable columns\n\t\t\n\t\t//block editor from taking action while resizing is taking place\n\t\tif(self.startColumn.modules.edit){\n\t\t\tself.startColumn.modules.edit.blocked = true;\n\t\t}\n\t\t\n\t\tself.startX = typeof e.screenX === \"undefined\" ? e.touches[0].screenX : e.screenX;\n\t\tself.latestX = self.startX;\n\t\tself.startWidth = column.getWidth();\n\t\t\n\t\tdocument.body.addEventListener(\"mousemove\", mouseMove);\n\t\tdocument.body.addEventListener(\"mouseup\", mouseUp);\n\t\thandle.addEventListener(\"touchmove\", mouseMove, {passive: true});\n\t\thandle.addEventListener(\"touchend\", mouseUp);\n\t}\n}\n\nResizeColumns.moduleName = \"resizeColumns\";\n\nclass ResizeRows extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.startColumn = false;\n\t\tthis.startY = false;\n\t\tthis.startHeight = false;\n\t\tthis.handle = null;\n\t\tthis.prevHandle = null;\n\n\t\tthis.registerTableOption(\"resizableRows\", false); //resizable rows\n\t}\n\n\tinitialize(){\n\t\tif(this.table.options.resizableRows){\n\t\t\tthis.subscribe(\"row-layout-after\", this.initializeRow.bind(this));\n\t\t}\n\t}\n\n\tinitializeRow(row){\n\t\tvar self = this,\n\t\trowEl = row.getElement();\n\n\t\tvar handle = document.createElement('div');\n\t\thandle.className = \"tabulator-row-resize-handle\";\n\n\t\tvar prevHandle = document.createElement('div');\n\t\tprevHandle.className = \"tabulator-row-resize-handle prev\";\n\n\t\thandle.addEventListener(\"click\", function(e){\n\t\t\te.stopPropagation();\n\t\t});\n\n\t\tvar handleDown = function(e){\n\t\t\tself.startRow = row;\n\t\t\tself._mouseDown(e, row, handle);\n\t\t};\n\n\t\thandle.addEventListener(\"mousedown\", handleDown);\n\t\thandle.addEventListener(\"touchstart\", handleDown, {passive: true});\n\n\t\tprevHandle.addEventListener(\"click\", function(e){\n\t\t\te.stopPropagation();\n\t\t});\n\n\t\tvar prevHandleDown =  function(e){\n\t\t\tvar prevRow = self.table.rowManager.prevDisplayRow(row);\n\n\t\t\tif(prevRow){\n\t\t\t\tself.startRow = prevRow;\n\t\t\t\tself._mouseDown(e, prevRow, prevHandle);\n\t\t\t}\n\t\t};\n\n\t\tprevHandle.addEventListener(\"mousedown\",prevHandleDown);\n\t\tprevHandle.addEventListener(\"touchstart\",prevHandleDown, {passive: true});\n\n\t\trowEl.appendChild(handle);\n\t\trowEl.appendChild(prevHandle);\n\t}\n\n\t_mouseDown(e, row, handle){\n\t\tvar self = this;\n\n\t\tself.table.element.classList.add(\"tabulator-block-select\");\n\n\t\tfunction mouseMove(e){\n\t\t\trow.setHeight(self.startHeight + ((typeof e.screenY === \"undefined\" ? e.touches[0].screenY : e.screenY) - self.startY));\n\t\t}\n\n\t\tfunction mouseUp(e){\n\n\t\t\t// //block editor from taking action while resizing is taking place\n\t\t\t// if(self.startColumn.modules.edit){\n\t\t\t// \tself.startColumn.modules.edit.blocked = false;\n\t\t\t// }\n\n\t\t\tdocument.body.removeEventListener(\"mouseup\", mouseMove);\n\t\t\tdocument.body.removeEventListener(\"mousemove\", mouseMove);\n\n\t\t\thandle.removeEventListener(\"touchmove\", mouseMove);\n\t\t\thandle.removeEventListener(\"touchend\", mouseUp);\n\n\t\t\tself.table.element.classList.remove(\"tabulator-block-select\");\n\n\t\t\tself.dispatchExternal(\"rowResized\", row.getComponent());\n\t\t}\n\n\t\te.stopPropagation(); //prevent resize from interfering with movable columns\n\n\t\t//block editor from taking action while resizing is taking place\n\t\t// if(self.startColumn.modules.edit){\n\t\t// \tself.startColumn.modules.edit.blocked = true;\n\t\t// }\n\n\t\tself.startY = typeof e.screenY === \"undefined\" ? e.touches[0].screenY : e.screenY;\n\t\tself.startHeight = row.getHeight();\n\n\t\tdocument.body.addEventListener(\"mousemove\", mouseMove);\n\t\tdocument.body.addEventListener(\"mouseup\", mouseUp);\n\n\t\thandle.addEventListener(\"touchmove\", mouseMove, {passive: true});\n\t\thandle.addEventListener(\"touchend\", mouseUp);\n\t}\n}\n\nResizeRows.moduleName = \"resizeRows\";\n\nclass ResizeTable extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.binding = false;\n\t\tthis.visibilityObserver = false;\n\t\tthis.resizeObserver = false;\n\t\tthis.containerObserver = false;\n\t\t\n\t\tthis.tableHeight = 0;\n\t\tthis.tableWidth = 0;\n\t\tthis.containerHeight = 0;\n\t\tthis.containerWidth = 0;\n\t\t\n\t\tthis.autoResize = false;\n\t\t\n\t\tthis.visible = false;\n\t\t\n\t\tthis.initialized = false;\n\t\tthis.initialRedraw = false;\n\t\t\n\t\tthis.registerTableOption(\"autoResize\", true); //auto resize table\n\t}\n\t\n\tinitialize(){\n\t\tif(this.table.options.autoResize){\n\t\t\tvar table = this.table,\n\t\t\ttableStyle;\n\t\t\t\n\t\t\tthis.tableHeight = table.element.clientHeight;\n\t\t\tthis.tableWidth = table.element.clientWidth;\n\t\t\t\n\t\t\tif(table.element.parentNode){\n\t\t\t\tthis.containerHeight = table.element.parentNode.clientHeight;\n\t\t\t\tthis.containerWidth = table.element.parentNode.clientWidth;\n\t\t\t}\n\t\t\t\n\t\t\tif(typeof IntersectionObserver !== \"undefined\" && typeof ResizeObserver !== \"undefined\" && table.rowManager.getRenderMode() === \"virtual\"){\n\t\t\t\t\n\t\t\t\tthis.initializeVisibilityObserver();\n\t\t\t\t\n\t\t\t\tthis.autoResize = true;\n\t\t\t\t\n\t\t\t\tthis.resizeObserver = new ResizeObserver((entry) => {\n\t\t\t\t\tif(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar nodeHeight = Math.floor(entry[0].contentRect.height);\n\t\t\t\t\t\tvar nodeWidth = Math.floor(entry[0].contentRect.width);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(this.tableHeight != nodeHeight || this.tableWidth != nodeWidth){\n\t\t\t\t\t\t\tthis.tableHeight = nodeHeight;\n\t\t\t\t\t\t\tthis.tableWidth = nodeWidth;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(table.element.parentNode){\n\t\t\t\t\t\t\t\tthis.containerHeight = table.element.parentNode.clientHeight;\n\t\t\t\t\t\t\t\tthis.containerWidth = table.element.parentNode.clientWidth;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.redrawTable();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.resizeObserver.observe(table.element);\n\t\t\t\t\n\t\t\t\ttableStyle = window.getComputedStyle(table.element);\n\t\t\t\t\n\t\t\t\tif(this.table.element.parentNode && !this.table.rowManager.fixedHeight && (tableStyle.getPropertyValue(\"max-height\") || tableStyle.getPropertyValue(\"min-height\"))){\n\t\t\t\t\t\n\t\t\t\t\tthis.containerObserver = new ResizeObserver((entry) => {\n\t\t\t\t\t\tif(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar nodeHeight = Math.floor(entry[0].contentRect.height);\n\t\t\t\t\t\t\tvar nodeWidth = Math.floor(entry[0].contentRect.width);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(this.containerHeight != nodeHeight || this.containerWidth != nodeWidth){\n\t\t\t\t\t\t\t\tthis.containerHeight = nodeHeight;\n\t\t\t\t\t\t\t\tthis.containerWidth = nodeWidth;\n\t\t\t\t\t\t\t\tthis.tableHeight = table.element.clientHeight;\n\t\t\t\t\t\t\t\tthis.tableWidth = table.element.clientWidth;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.redrawTable();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.containerObserver.observe(this.table.element.parentNode);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.subscribe(\"table-resize\", this.tableResized.bind(this));\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tthis.binding = function(){\n\t\t\t\t\tif(!table.browserMobile || (table.browserMobile && (!table.modules.edit || (table.modules.edit && !table.modules.edit.currentCell)))){\n\t\t\t\t\t\ttable.columnManager.rerenderColumns(true);\n\t\t\t\t\t\ttable.redraw();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\twindow.addEventListener(\"resize\", this.binding);\n\t\t\t}\n\t\t\t\n\t\t\tthis.subscribe(\"table-destroy\", this.clearBindings.bind(this));\n\t\t}\n\t}\n\t\n\tinitializeVisibilityObserver(){\n\t\tthis.visibilityObserver = new IntersectionObserver((entries) => {\n\t\t\tthis.visible = entries[0].isIntersecting;\n\t\t\t\n\t\t\tif(!this.initialized){\n\t\t\t\tthis.initialized = true;\n\t\t\t\tthis.initialRedraw = !this.visible;\n\t\t\t}else {\n\t\t\t\tif(this.visible){\n\t\t\t\t\tthis.redrawTable(this.initialRedraw);\n\t\t\t\t\tthis.initialRedraw = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.visibilityObserver.observe(this.table.element);\n\t}\n\t\n\tredrawTable(force){\n\t\tif(this.initialized && this.visible){\n\t\t\tthis.table.columnManager.rerenderColumns(true);\n\t\t\tthis.table.redraw(force);\n\t\t}\n\t}\n\t\n\ttableResized(){\n\t\tthis.table.rowManager.redraw();\n\t}\n\t\n\tclearBindings(){\n\t\tif(this.binding){\n\t\t\twindow.removeEventListener(\"resize\", this.binding);\n\t\t}\n\t\t\n\t\tif(this.resizeObserver){\n\t\t\tthis.resizeObserver.unobserve(this.table.element);\n\t\t}\n\t\t\n\t\tif(this.visibilityObserver){\n\t\t\tthis.visibilityObserver.unobserve(this.table.element);\n\t\t}\n\t\t\n\t\tif(this.containerObserver){\n\t\t\tthis.containerObserver.unobserve(this.table.element.parentNode);\n\t\t}\n\t}\n}\n\nResizeTable.moduleName = \"resizeTable\";\n\nclass ResponsiveLayout extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.columns = [];\n\t\tthis.hiddenColumns = [];\n\t\tthis.mode = \"\";\n\t\tthis.index = 0;\n\t\tthis.collapseFormatter = [];\n\t\tthis.collapseStartOpen = true;\n\t\tthis.collapseHandleColumn = false;\n\n\t\tthis.registerTableOption(\"responsiveLayout\", false); //responsive layout flags\n\t\tthis.registerTableOption(\"responsiveLayoutCollapseStartOpen\", true); //start showing collapsed data\n\t\tthis.registerTableOption(\"responsiveLayoutCollapseUseFormatters\", true); //responsive layout collapse formatter\n\t\tthis.registerTableOption(\"responsiveLayoutCollapseFormatter\", false); //responsive layout collapse formatter\n\n\t\tthis.registerColumnOption(\"responsive\");\n\t}\n\n\t//generate responsive columns list\n\tinitialize(){\n\t\tif(this.table.options.responsiveLayout){\n\t\t\tthis.subscribe(\"column-layout\", this.initializeColumn.bind(this));\n\t\t\tthis.subscribe(\"column-show\", this.updateColumnVisibility.bind(this));\n\t\t\tthis.subscribe(\"column-hide\", this.updateColumnVisibility.bind(this));\n\t\t\tthis.subscribe(\"columns-loaded\", this.initializeResponsivity.bind(this));\n\t\t\tthis.subscribe(\"column-moved\", this.initializeResponsivity.bind(this));\n\t\t\tthis.subscribe(\"column-add\", this.initializeResponsivity.bind(this));\n\t\t\tthis.subscribe(\"column-delete\", this.initializeResponsivity.bind(this));\n\n\t\t\tthis.subscribe(\"table-redrawing\", this.tableRedraw.bind(this));\n\t\t\t\n\t\t\tif(this.table.options.responsiveLayout === \"collapse\"){\n\t\t\t\tthis.subscribe(\"row-data-changed\", this.generateCollapsedRowContent.bind(this));\n\t\t\t\tthis.subscribe(\"row-init\", this.initializeRow.bind(this));\n\t\t\t\tthis.subscribe(\"row-layout\", this.layoutRow.bind(this));\n\t\t\t}\n\t\t}\n\t}\n\n\ttableRedraw(force){\n\t\tif([\"fitColumns\", \"fitDataStretch\"].indexOf(this.layoutMode()) === -1){\n\t\t\tif(!force){\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t}\n\t}\n\n\tinitializeResponsivity(){\n\t\tvar columns = [];\n\n\t\tthis.mode = this.table.options.responsiveLayout;\n\t\tthis.collapseFormatter = this.table.options.responsiveLayoutCollapseFormatter || this.formatCollapsedData;\n\t\tthis.collapseStartOpen = this.table.options.responsiveLayoutCollapseStartOpen;\n\t\tthis.hiddenColumns = [];\n\n\t\t//determine level of responsivity for each column\n\t\tthis.table.columnManager.columnsByIndex.forEach((column, i) => {\n\t\t\tif(column.modules.responsive){\n\t\t\t\tif(column.modules.responsive.order && column.modules.responsive.visible){\n\t\t\t\t\tcolumn.modules.responsive.index = i;\n\t\t\t\t\tcolumns.push(column);\n\n\t\t\t\t\tif(!column.visible && this.mode === \"collapse\"){\n\t\t\t\t\t\tthis.hiddenColumns.push(column);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t//sort list by responsivity\n\t\tcolumns = columns.reverse();\n\t\tcolumns = columns.sort((a, b) => {\n\t\t\tvar diff = b.modules.responsive.order - a.modules.responsive.order;\n\t\t\treturn diff || (b.modules.responsive.index - a.modules.responsive.index);\n\t\t});\n\n\t\tthis.columns = columns;\n\n\t\tif(this.mode === \"collapse\"){\n\t\t\tthis.generateCollapsedContent();\n\t\t}\n\n\t\t//assign collapse column\n\t\tfor (let col of this.table.columnManager.columnsByIndex){\n\t\t\tif(col.definition.formatter == \"responsiveCollapse\"){\n\t\t\t\tthis.collapseHandleColumn = col;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(this.collapseHandleColumn){\n\t\t\tif(this.hiddenColumns.length){\n\t\t\t\tthis.collapseHandleColumn.show();\n\t\t\t}else {\n\t\t\t\tthis.collapseHandleColumn.hide();\n\t\t\t}\n\t\t}\n\t}\n\n\t//define layout information\n\tinitializeColumn(column){\n\t\tvar def = column.getDefinition();\n\n\t\tcolumn.modules.responsive = {order: typeof def.responsive === \"undefined\" ? 1 : def.responsive, visible:def.visible === false ? false : true};\n\t}\n\n\tinitializeRow(row){\n\t\tvar el;\n\n\t\tif(row.type !== \"calc\"){\n\t\t\tel = document.createElement(\"div\");\n\t\t\tel.classList.add(\"tabulator-responsive-collapse\");\n\n\t\t\trow.modules.responsiveLayout = {\n\t\t\t\telement:el,\n\t\t\t\topen:this.collapseStartOpen,\n\t\t\t};\n\n\t\t\tif(!this.collapseStartOpen){\n\t\t\t\tel.style.display = 'none';\n\t\t\t}\n\t\t}\n\t}\n\n\tlayoutRow(row){\n\t\tvar rowEl = row.getElement();\n\n\t\tif(row.modules.responsiveLayout){\n\t\t\trowEl.appendChild(row.modules.responsiveLayout.element);\n\t\t\tthis.generateCollapsedRowContent(row);\n\t\t}\n\t}\n\n\t//update column visibility\n\tupdateColumnVisibility(column, responsiveToggle){\n\t\tif(!responsiveToggle && column.modules.responsive){\n\t\t\tcolumn.modules.responsive.visible = column.visible;\n\t\t\tthis.initializeResponsivity();\n\t\t}\n\t}\n\n\thideColumn(column){\n\t\tvar colCount = this.hiddenColumns.length;\n\n\t\tcolumn.hide(false, true);\n\n\t\tif(this.mode === \"collapse\"){\n\t\t\tthis.hiddenColumns.unshift(column);\n\t\t\tthis.generateCollapsedContent();\n\n\t\t\tif(this.collapseHandleColumn && !colCount){\n\t\t\t\tthis.collapseHandleColumn.show();\n\t\t\t}\n\t\t}\n\t}\n\n\tshowColumn(column){\n\t\tvar index;\n\n\t\tcolumn.show(false, true);\n\t\t//set column width to prevent calculation loops on uninitialized columns\n\t\tcolumn.setWidth(column.getWidth());\n\n\t\tif(this.mode === \"collapse\"){\n\t\t\tindex = this.hiddenColumns.indexOf(column);\n\n\t\t\tif(index > -1){\n\t\t\t\tthis.hiddenColumns.splice(index, 1);\n\t\t\t}\n\n\t\t\tthis.generateCollapsedContent();\n\n\t\t\tif(this.collapseHandleColumn && !this.hiddenColumns.length){\n\t\t\t\tthis.collapseHandleColumn.hide();\n\t\t\t}\n\t\t}\n\t}\n\n\t//redraw columns to fit space\n\tupdate(){\n\t\tvar working = true;\n\n\t\twhile(working){\n\n\t\t\tlet width = this.table.modules.layout.getMode() == \"fitColumns\" ? this.table.columnManager.getFlexBaseWidth() : this.table.columnManager.getWidth();\n\n\t\t\tlet diff = (this.table.options.headerVisible ? this.table.columnManager.element.clientWidth : this.table.element.clientWidth) - width;\n\n\t\t\tif(diff < 0){\n\t\t\t\t//table is too wide\n\t\t\t\tlet column = this.columns[this.index];\n\n\t\t\t\tif(column){\n\t\t\t\t\tthis.hideColumn(column);\n\t\t\t\t\tthis.index ++;\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\n\t\t\t}else {\n\n\t\t\t\t//table has spare space\n\t\t\t\tlet column = this.columns[this.index -1];\n\n\t\t\t\tif(column){\n\t\t\t\t\tif(diff > 0){\n\t\t\t\t\t\tif(diff >= column.getWidth()){\n\t\t\t\t\t\t\tthis.showColumn(column);\n\t\t\t\t\t\t\tthis.index --;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tworking = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tworking = false;\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!this.table.rowManager.activeRowsCount){\n\t\t\t\tthis.table.rowManager.renderEmptyScroll();\n\t\t\t}\n\t\t}\n\t}\n\n\tgenerateCollapsedContent(){\n\t\tvar rows = this.table.rowManager.getDisplayRows();\n\n\t\trows.forEach((row) => {\n\t\t\tthis.generateCollapsedRowContent(row);\n\t\t});\n\t}\n\n\tgenerateCollapsedRowContent(row){\n\t\tvar el, contents;\n\n\t\tif(row.modules.responsiveLayout){\n\t\t\tel = row.modules.responsiveLayout.element;\n\n\t\t\twhile(el.firstChild) el.removeChild(el.firstChild);\n\n\t\t\tcontents = this.collapseFormatter(this.generateCollapsedRowData(row));\n\t\t\tif(contents){\n\t\t\t\tel.appendChild(contents);\n\t\t\t}\n\t\t}\n\t}\n\n\tgenerateCollapsedRowData(row){\n\t\tvar data = row.getData(),\n\t\toutput = [],\n\t\tmockCellComponent;\n\n\t\tthis.hiddenColumns.forEach((column) => {\n\t\t\tvar value = column.getFieldValue(data);\n\n\t\t\tif(column.definition.title && column.field){\n\t\t\t\tif(column.modules.format && this.table.options.responsiveLayoutCollapseUseFormatters){\n\n\t\t\t\t\tmockCellComponent = {\n\t\t\t\t\t\tvalue:false,\n\t\t\t\t\t\tdata:{},\n\t\t\t\t\t\tgetValue:function(){\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetData:function(){\n\t\t\t\t\t\t\treturn data;\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetType:function(){\n\t\t\t\t\t\t\treturn \"cell\";\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetElement:function(){\n\t\t\t\t\t\t\treturn document.createElement(\"div\");\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetRow:function(){\n\t\t\t\t\t\t\treturn row.getComponent();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetColumn:function(){\n\t\t\t\t\t\t\treturn column.getComponent();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetTable:() => {\n\t\t\t\t\t\t\treturn this.table;\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tfunction onRendered(callback){\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\tfield: column.field,\n\t\t\t\t\t\ttitle: column.definition.title,\n\t\t\t\t\t\tvalue: column.modules.format.formatter.call(this.table.modules.format, mockCellComponent, column.modules.format.params, onRendered)\n\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\tfield: column.field,\n\t\t\t\t\t\ttitle: column.definition.title,\n\t\t\t\t\t\tvalue: value\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t}\n\n\tformatCollapsedData(data){\n\t\tvar list = document.createElement(\"table\");\n\n\t\tdata.forEach(function(item){\n\t\t\tvar row = document.createElement(\"tr\");\n\t\t\tvar titleData = document.createElement(\"td\");\n\t\t\tvar valueData = document.createElement(\"td\");\n\t\t\tvar node_content;\n\n\t\t\tvar titleHighlight = document.createElement(\"strong\");\n\t\t\ttitleData.appendChild(titleHighlight);\n\t\t\tthis.langBind(\"columns|\" + item.field, function(text){\n\t\t\t\ttitleHighlight.innerHTML = text || item.title;\n\t\t\t});\n\n\t\t\tif(item.value instanceof Node){\n\t\t\t\tnode_content = document.createElement(\"div\");\n\t\t\t\tnode_content.appendChild(item.value);\n\t\t\t\tvalueData.appendChild(node_content);\n\t\t\t}else {\n\t\t\t\tvalueData.innerHTML = item.value;\n\t\t\t}\n\n\t\t\trow.appendChild(titleData);\n\t\t\trow.appendChild(valueData);\n\t\t\tlist.appendChild(row);\n\t\t}, this);\n\n\t\treturn Object.keys(data).length ? list : \"\";\n\t}\n}\n\nResponsiveLayout.moduleName = \"responsiveLayout\";\n\nclass SelectRow extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.selecting = false; //flag selecting in progress\n\t\tthis.lastClickedRow = false; //last clicked row\n\t\tthis.selectPrev = []; //hold previously selected element for drag drop selection\n\t\tthis.selectedRows = []; //hold selected rows\n\t\tthis.headerCheckboxElement = null; // hold header select element\n\t\t\n\t\tthis.registerTableOption(\"selectableRows\", \"highlight\"); //highlight rows on hover\n\t\tthis.registerTableOption(\"selectableRowsRangeMode\", \"drag\");  //highlight rows on hover\n\t\tthis.registerTableOption(\"selectableRowsRollingSelection\", true); //roll selection once maximum number of selectable rows is reached\n\t\tthis.registerTableOption(\"selectableRowsPersistence\", true); // maintain selection when table view is updated\n\t\tthis.registerTableOption(\"selectableRowsCheck\", function(data, row){return true;}); //check whether row is selectable\n\t\t\n\t\tthis.registerTableFunction(\"selectRow\", this.selectRows.bind(this));\n\t\tthis.registerTableFunction(\"deselectRow\", this.deselectRows.bind(this));\n\t\tthis.registerTableFunction(\"toggleSelectRow\", this.toggleRow.bind(this));\n\t\tthis.registerTableFunction(\"getSelectedRows\", this.getSelectedRows.bind(this));\n\t\tthis.registerTableFunction(\"getSelectedData\", this.getSelectedData.bind(this));\n\t\t\n\t\t//register component functions\n\t\tthis.registerComponentFunction(\"row\", \"select\", this.selectRows.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"deselect\", this.deselectRows.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"toggleSelect\", this.toggleRow.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"isSelected\", this.isRowSelected.bind(this));\n\t}\n\t\n\tinitialize(){\n\n\t\tthis.deprecatedOptionsCheck();\n\n\t\tif(this.table.options.selectableRows === \"highlight\" && this.table.options.selectableRange){\n\t\t\tthis.table.options.selectableRows = false;\n\t\t}\n\n\t\tif(this.table.options.selectableRows !== false){\n\t\t\tthis.subscribe(\"row-init\", this.initializeRow.bind(this));\n\t\t\tthis.subscribe(\"row-deleting\", this.rowDeleted.bind(this));\n\t\t\tthis.subscribe(\"rows-wipe\", this.clearSelectionData.bind(this));\n\t\t\tthis.subscribe(\"rows-retrieve\", this.rowRetrieve.bind(this));\n\t\t\t\n\t\t\tif(this.table.options.selectableRows && !this.table.options.selectableRowsPersistence){\n\t\t\t\tthis.subscribe(\"data-refreshing\", this.deselectRows.bind(this));\n\t\t\t}\n\t\t}\n\t}\n\n\tdeprecatedOptionsCheck(){\n\t\tthis.deprecationCheck(\"selectable\", \"selectableRows\", true);\n\t\tthis.deprecationCheck(\"selectableRollingSelection\", \"selectableRowsRollingSelection\", true);\n\t\tthis.deprecationCheck(\"selectableRangeMode\", \"selectableRowsRangeMode\", true);\n\t\tthis.deprecationCheck(\"selectablePersistence\", \"selectableRowsPersistence\", true);\n\t\tthis.deprecationCheck(\"selectableCheck\", \"selectableRowsCheck\", true);\n\t}\n\t\n\trowRetrieve(type, prevValue){\n\t\treturn type === \"selected\" ? this.selectedRows : prevValue;\n\t}\n\t\n\trowDeleted(row){\n\t\tthis._deselectRow(row, true);\n\t}\n\t\n\tclearSelectionData(silent){\n\t\tvar prevSelected = this.selectedRows.length;\n\n\t\tthis.selecting = false;\n\t\tthis.lastClickedRow = false;\n\t\tthis.selectPrev = [];\n\t\tthis.selectedRows = [];\n\t\t\n\t\tif(prevSelected && silent !== true){\n\t\t\tthis._rowSelectionChanged();\n\t\t}\n\t}\n\t\n\tinitializeRow(row){\n\t\tvar self = this,\n\t\tselectable = self.checkRowSelectability(row),\n\t\telement = row.getElement();\n\t\t\n\t\t// trigger end of row selection\n\t\tvar endSelect = function(){\n\t\t\t\n\t\t\tsetTimeout(function(){\n\t\t\t\tself.selecting = false;\n\t\t\t}, 50);\n\t\t\t\n\t\t\tdocument.body.removeEventListener(\"mouseup\", endSelect);\n\t\t};\n\t\t\n\t\trow.modules.select = {selected:false};\n\n\t\telement.classList.toggle(\"tabulator-selectable\", selectable);\n\t\telement.classList.toggle(\"tabulator-unselectable\", !selectable);\n\t\t\n\t\t//set row selection class\n\t\tif(self.checkRowSelectability(row)){\t\t\t\n\t\t\tif(self.table.options.selectableRows && self.table.options.selectableRows != \"highlight\"){\n\t\t\t\tif(self.table.options.selectableRowsRangeMode === \"click\"){\n\t\t\t\t\telement.addEventListener(\"click\", this.handleComplexRowClick.bind(this, row));\n\t\t\t\t}else {\n\t\t\t\t\telement.addEventListener(\"click\", function(e){\n\t\t\t\t\t\tif(!self.table.modExists(\"edit\") || !self.table.modules.edit.getCurrentCell()){\n\t\t\t\t\t\t\tself.table._clearSelection();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!self.selecting){\n\t\t\t\t\t\t\tself.toggleRow(row);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\telement.addEventListener(\"mousedown\", function(e){\n\t\t\t\t\t\tif(e.shiftKey){\n\t\t\t\t\t\t\tself.table._clearSelection();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tself.selecting = true;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tself.selectPrev = [];\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdocument.body.addEventListener(\"mouseup\", endSelect);\n\t\t\t\t\t\t\tdocument.body.addEventListener(\"keyup\", endSelect);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tself.toggleRow(row);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\telement.addEventListener(\"mouseenter\", function(e){\n\t\t\t\t\t\tif(self.selecting){\n\t\t\t\t\t\t\tself.table._clearSelection();\n\t\t\t\t\t\t\tself.toggleRow(row);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(self.selectPrev[1] == row){\n\t\t\t\t\t\t\t\tself.toggleRow(self.selectPrev[0]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\telement.addEventListener(\"mouseout\", function(e){\n\t\t\t\t\t\tif(self.selecting){\n\t\t\t\t\t\t\tself.table._clearSelection();\n\t\t\t\t\t\t\tself.selectPrev.unshift(row);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\thandleComplexRowClick(row, e){\n\t\tif(e.shiftKey){\n\t\t\tthis.table._clearSelection();\n\t\t\tthis.lastClickedRow = this.lastClickedRow || row;\n\t\t\t\n\t\t\tvar lastClickedRowIdx = this.table.rowManager.getDisplayRowIndex(this.lastClickedRow);\n\t\t\tvar rowIdx = this.table.rowManager.getDisplayRowIndex(row);\n\t\t\t\n\t\t\tvar fromRowIdx = lastClickedRowIdx <= rowIdx ? lastClickedRowIdx : rowIdx;\n\t\t\tvar toRowIdx = lastClickedRowIdx >= rowIdx ? lastClickedRowIdx : rowIdx;\n\t\t\t\n\t\t\tvar rows = this.table.rowManager.getDisplayRows().slice(0);\n\t\t\tvar toggledRows = rows.splice(fromRowIdx, toRowIdx - fromRowIdx + 1);\n\t\t\t\n\t\t\tif(e.ctrlKey || e.metaKey){\n\t\t\t\ttoggledRows.forEach((toggledRow)=>{\n\t\t\t\t\tif(toggledRow !== this.lastClickedRow){\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(this.table.options.selectableRows !== true && !this.isRowSelected(row)){\n\t\t\t\t\t\t\tif(this.selectedRows.length < this.table.options.selectableRows){\n\t\t\t\t\t\t\t\tthis.toggleRow(toggledRow);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tthis.toggleRow(toggledRow);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis.lastClickedRow = row;\n\t\t\t}else {\n\t\t\t\tthis.deselectRows(undefined, true);\n\t\t\t\t\n\t\t\t\tif(this.table.options.selectableRows !== true){\n\t\t\t\t\tif(toggledRows.length > this.table.options.selectableRows){\n\t\t\t\t\t\ttoggledRows = toggledRows.slice(0, this.table.options.selectableRows);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.selectRows(toggledRows);\n\t\t\t}\n\t\t\tthis.table._clearSelection();\n\t\t}\n\t\telse if(e.ctrlKey || e.metaKey){\n\t\t\tthis.toggleRow(row);\n\t\t\tthis.lastClickedRow = row;\n\t\t}else {\n\t\t\tthis.deselectRows(undefined, true);\n\t\t\tthis.selectRows(row);\n\t\t\tthis.lastClickedRow = row;\n\t\t}\n\t}\n\n\tcheckRowSelectability(row){\n\t\tif(row && row.type === \"row\"){\n\t\t\treturn this.table.options.selectableRowsCheck.call(this.table, row.getComponent());\n\t\t}\n\n\t\treturn false;\n\t}\n\t\n\t//toggle row selection\n\ttoggleRow(row){\n\t\tif(this.checkRowSelectability(row)){\n\t\t\tif(row.modules.select && row.modules.select.selected){\n\t\t\t\tthis._deselectRow(row);\n\t\t\t}else {\n\t\t\t\tthis._selectRow(row);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//select a number of rows\n\tselectRows(rows){\n\t\tvar changes = [], \n\t\trowMatch, change;\n\t\t\n\t\tswitch(typeof rows){\n\t\t\tcase \"undefined\":\n\t\t\t\trowMatch = this.table.rowManager.rows;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"number\":\n\t\t\t\trowMatch = this.table.rowManager.findRow(rows);\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase \"string\":\n\t\t\t\trowMatch = this.table.rowManager.findRow(rows);\n\t\t\t\n\t\t\t\tif(!rowMatch){\n\t\t\t\t\trowMatch = this.table.rowManager.getRows(rows);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\trowMatch = rows;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(Array.isArray(rowMatch)){\n\t\t\tif(rowMatch.length){\n\t\t\t\trowMatch.forEach((row) => {\n\t\t\t\t\tchange = this._selectRow(row, true, true);\n\n\t\t\t\t\tif(change){\n\t\t\t\t\t\tchanges.push(change);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tthis._rowSelectionChanged(false, changes);\n\t\t\t}\n\t\t}else {\n\t\t\tif(rowMatch){\n\t\t\t\tthis._selectRow(rowMatch, false, true);\n\t\t\t}\n\t\t}\t\n\t}\n\t\n\t//select an individual row\n\t_selectRow(rowInfo, silent, force){\n\t\t//handle max row count\n\t\tif(!isNaN(this.table.options.selectableRows) && this.table.options.selectableRows !== true && !force){\n\t\t\tif(this.selectedRows.length >= this.table.options.selectableRows){\n\t\t\t\tif(this.table.options.selectableRowsRollingSelection){\n\t\t\t\t\tthis._deselectRow(this.selectedRows[0]);\n\t\t\t\t}else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar row = this.table.rowManager.findRow(rowInfo);\n\t\t\n\t\tif(row){\n\t\t\tif(this.selectedRows.indexOf(row) == -1){\n\t\t\t\trow.getElement().classList.add(\"tabulator-selected\");\n\t\t\t\tif(!row.modules.select){\n\t\t\t\t\trow.modules.select = {};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\trow.modules.select.selected = true;\n\t\t\t\tif(row.modules.select.checkboxEl){\n\t\t\t\t\trow.modules.select.checkboxEl.checked = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.selectedRows.push(row);\n\t\t\t\t\n\t\t\t\tif(this.table.options.dataTreeSelectPropagate){\n\t\t\t\t\tthis.childRowSelection(row, true);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.dispatchExternal(\"rowSelected\", row.getComponent());\n\t\t\t\t\n\t\t\t\tthis._rowSelectionChanged(silent, row);\n\n\t\t\t\treturn row;\n\t\t\t}\n\t\t}else {\n\t\t\tif(!silent){\n\t\t\t\tconsole.warn(\"Selection Error - No such row found, ignoring selection:\" + rowInfo);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tisRowSelected(row){\n\t\treturn this.selectedRows.indexOf(row) !== -1;\n\t}\n\t\n\t//deselect a number of rows\n\tdeselectRows(rows, silent){\n\t\tvar changes = [], \n\t\trowMatch, change;\n\t\t\n\t\tswitch(typeof rows){\n\t\t\tcase \"undefined\":\n\t\t\t\trowMatch = Object.assign([], this.selectedRows);\n\t\t\t\tbreak;\n\n\t\t\tcase \"number\":\n\t\t\t\trowMatch = this.table.rowManager.findRow(rows);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"string\":\n\t\t\t\trowMatch = this.table.rowManager.findRow(rows);\n\t\t\t\n\t\t\t\tif(!rowMatch){\n\t\t\t\t\trowMatch = this.table.rowManager.getRows(rows);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\trowMatch = rows;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif(Array.isArray(rowMatch)){\n\t\t\tif(rowMatch.length){\n\t\t\t\trowMatch.forEach((row) => {\n\t\t\t\t\tchange = this._deselectRow(row, true, true);\n\n\t\t\t\t\tif(change){\n\t\t\t\t\t\tchanges.push(change);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tthis._rowSelectionChanged(silent, [], changes);\n\t\t\t}\n\t\t}else {\n\t\t\tif(rowMatch){\n\t\t\t\tthis._deselectRow(rowMatch, silent, true);\n\t\t\t}\n\t\t}\t\n\t}\n\t\n\t//deselect an individual row\n\t_deselectRow(rowInfo, silent){\n\t\tvar self = this,\n\t\trow = self.table.rowManager.findRow(rowInfo),\n\t\tindex, element;\n\t\t\n\t\tif(row){\n\t\t\tindex = self.selectedRows.findIndex(function(selectedRow){\n\t\t\t\treturn selectedRow == row;\n\t\t\t});\n\t\t\t\n\t\t\tif(index > -1){\n\n\t\t\t\telement = row.getElement();\n\t\t\t\t\n\t\t\t\tif(element){\n\t\t\t\t\telement.classList.remove(\"tabulator-selected\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(!row.modules.select){\n\t\t\t\t\trow.modules.select = {};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\trow.modules.select.selected = false;\n\t\t\t\tif(row.modules.select.checkboxEl){\n\t\t\t\t\trow.modules.select.checkboxEl.checked = false;\n\t\t\t\t}\n\t\t\t\tself.selectedRows.splice(index, 1);\n\t\t\t\t\n\t\t\t\tif(this.table.options.dataTreeSelectPropagate){\n\t\t\t\t\tthis.childRowSelection(row, false);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.dispatchExternal(\"rowDeselected\", row.getComponent());\n\t\t\t\t\n\t\t\t\tself._rowSelectionChanged(silent, undefined, row);\n\n\t\t\t\treturn row;\n\t\t\t}\n\t\t}else {\n\t\t\tif(!silent){\n\t\t\t\tconsole.warn(\"Deselection Error - No such row found, ignoring selection:\" + rowInfo);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tgetSelectedData(){\n\t\tvar data = [];\n\t\t\n\t\tthis.selectedRows.forEach(function(row){\n\t\t\tdata.push(row.getData());\n\t\t});\n\t\t\n\t\treturn data;\n\t}\n\t\n\tgetSelectedRows(){\n\t\tvar rows = [];\n\t\t\n\t\tthis.selectedRows.forEach(function(row){\n\t\t\trows.push(row.getComponent());\n\t\t});\n\t\t\n\t\treturn rows;\n\t}\n\t\n\t_rowSelectionChanged(silent, selected = [], deselected = []){\n\t\tif(this.headerCheckboxElement){\n\t\t\tif(this.selectedRows.length === 0){\n\t\t\t\tthis.headerCheckboxElement.checked = false;\n\t\t\t\tthis.headerCheckboxElement.indeterminate = false;\n\t\t\t} else if(this.table.rowManager.rows.length === this.selectedRows.length){\n\t\t\t\tthis.headerCheckboxElement.checked = true;\n\t\t\t\tthis.headerCheckboxElement.indeterminate = false;\n\t\t\t} else {\n\t\t\t\tthis.headerCheckboxElement.indeterminate = true;\n\t\t\t\tthis.headerCheckboxElement.checked = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(!silent){\n\t\t\tif(!Array.isArray(selected)){\n\t\t\t\tselected = [selected];\n\t\t\t}\n\n\t\t\tselected = selected.map(row => row.getComponent());\n\n\t\t\tif(!Array.isArray(deselected)){\n\t\t\t\tdeselected = [deselected];\n\t\t\t}\n\n\t\t\tdeselected = deselected.map(row => row.getComponent());\n\n\t\t\tthis.dispatchExternal(\"rowSelectionChanged\", this.getSelectedData(), this.getSelectedRows(), selected, deselected);\n\t\t}\n\t}\n\t\n\tregisterRowSelectCheckbox (row, element) {\n\t\tif(!row._row.modules.select){\n\t\t\trow._row.modules.select = {};\n\t\t}\n\t\t\n\t\trow._row.modules.select.checkboxEl = element;\n\t}\n\t\n\tregisterHeaderSelectCheckbox (element) {\n\t\tthis.headerCheckboxElement = element;\n\t}\n\t\n\tchildRowSelection(row, select){\n\t\tvar children = this.table.modules.dataTree.getChildren(row, true);\n\t\t\n\t\tif(select){\n\t\t\tfor(let child of children){\n\t\t\t\tthis._selectRow(child, true);\n\t\t\t}\n\t\t}else {\n\t\t\tfor(let child of children){\n\t\t\t\tthis._deselectRow(child, true);\n\t\t\t}\n\t\t}\n\t}\n}\n\nSelectRow.moduleName = \"selectRow\";\n\n//sort numbers\nfunction number$1(a, b, aRow, bRow, column, dir, params){\n\tvar alignEmptyValues = params.alignEmptyValues;\n\tvar decimal = params.decimalSeparator;\n\tvar thousand = params.thousandSeparator;\n\tvar emptyAlign = 0;\n\n\ta = String(a);\n\tb = String(b);\n\n\tif(thousand){\n\t\ta = a.split(thousand).join(\"\");\n\t\tb = b.split(thousand).join(\"\");\n\t}\n\n\tif(decimal){\n\t\ta = a.split(decimal).join(\".\");\n\t\tb = b.split(decimal).join(\".\");\n\t}\n\n\ta = parseFloat(a);\n\tb = parseFloat(b);\n\n\t//handle non numeric values\n\tif(isNaN(a)){\n\t\temptyAlign =  isNaN(b) ? 0 : -1;\n\t}else if(isNaN(b)){\n\t\temptyAlign =  1;\n\t}else {\n\t\t//compare valid values\n\t\treturn a - b;\n\t}\n\n\t//fix empty values in position\n\tif((alignEmptyValues === \"top\" && dir === \"desc\") || (alignEmptyValues === \"bottom\" && dir === \"asc\")){\n\t\temptyAlign *= -1;\n\t}\n\n\treturn emptyAlign;\n}\n\n//sort strings\nfunction string(a, b, aRow, bRow, column, dir, params){\n\tvar alignEmptyValues = params.alignEmptyValues;\n\tvar emptyAlign = 0;\n\tvar locale;\n\n\t//handle empty values\n\tif(!a){\n\t\temptyAlign =  !b ? 0 : -1;\n\t}else if(!b){\n\t\temptyAlign =  1;\n\t}else {\n\t\t//compare valid values\n\t\tswitch(typeof params.locale){\n\t\t\tcase \"boolean\":\n\t\t\t\tif(params.locale){\n\t\t\t\t\tlocale = this.langLocale();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"string\":\n\t\t\t\tlocale = params.locale;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn String(a).toLowerCase().localeCompare(String(b).toLowerCase(), locale);\n\t}\n\n\t//fix empty values in position\n\tif((alignEmptyValues === \"top\" && dir === \"desc\") || (alignEmptyValues === \"bottom\" && dir === \"asc\")){\n\t\temptyAlign *= -1;\n\t}\n\n\treturn emptyAlign;\n}\n\n//sort datetime\nfunction datetime$2(a, b, aRow, bRow, column, dir, params){\n\tvar DT = window.DateTime || luxon.DateTime;\n\tvar format = params.format || \"dd/MM/yyyy HH:mm:ss\",\n\talignEmptyValues = params.alignEmptyValues,\n\temptyAlign = 0;\n\n\tif(typeof DT != \"undefined\"){\n\t\tif(!DT.isDateTime(a)){\n\t\t\tif(format === \"iso\"){\n\t\t\t\ta = DT.fromISO(String(a));\n\t\t\t}else {\n\t\t\t\ta = DT.fromFormat(String(a), format);\n\t\t\t}\n\t\t}\n\n\t\tif(!DT.isDateTime(b)){\n\t\t\tif(format === \"iso\"){\n\t\t\t\tb = DT.fromISO(String(b));\n\t\t\t}else {\n\t\t\t\tb = DT.fromFormat(String(b), format);\n\t\t\t}\n\t\t}\n\n\t\tif(!a.isValid){\n\t\t\temptyAlign = !b.isValid ? 0 : -1;\n\t\t}else if(!b.isValid){\n\t\t\temptyAlign =  1;\n\t\t}else {\n\t\t\t//compare valid values\n\t\t\treturn a - b;\n\t\t}\n\n\t\t//fix empty values in position\n\t\tif((alignEmptyValues === \"top\" && dir === \"desc\") || (alignEmptyValues === \"bottom\" && dir === \"asc\")){\n\t\t\temptyAlign *= -1;\n\t\t}\n\n\t\treturn emptyAlign;\n\n\t}else {\n\t\tconsole.error(\"Sort Error - 'datetime' sorter is dependant on luxon.js\");\n\t}\n}\n\n//sort date\nfunction date$1(a, b, aRow, bRow, column, dir, params){\n\tif(!params.format){\n\t\tparams.format = \"dd/MM/yyyy\";\n\t}\n\n\treturn datetime$2.call(this, a, b, aRow, bRow, column, dir, params);\n}\n\n//sort times\nfunction time$1(a, b, aRow, bRow, column, dir, params){\n\tif(!params.format){\n\t\tparams.format = \"HH:mm\";\n\t}\n\n\treturn datetime$2.call(this, a, b, aRow, bRow, column, dir, params);\n}\n\n//sort booleans\nfunction boolean(a, b, aRow, bRow, column, dir, params){\n\tvar el1 = a === true || a === \"true\" || a === \"True\" || a === 1 ? 1 : 0;\n\tvar el2 = b === true || b === \"true\" || b === \"True\" || b === 1 ? 1 : 0;\n\n\treturn el1 - el2;\n}\n\n//sort if element contains any data\nfunction array(a, b, aRow, bRow, column, dir, params){\n\tvar type = params.type || \"length\",\n\talignEmptyValues = params.alignEmptyValues,\n\temptyAlign = 0;\n\n\tfunction calc(value){\n\t\tvar result;\n\n\t\tswitch(type){\n\t\t\tcase \"length\":\n\t\t\t\tresult = value.length;\n\t\t\t\tbreak;\n\n\t\t\tcase \"sum\":\n\t\t\t\tresult = value.reduce(function(c, d){\n\t\t\t\t\treturn c + d;\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"max\":\n\t\t\t\tresult = Math.max.apply(null, value) ;\n\t\t\t\tbreak;\n\n\t\t\tcase \"min\":\n\t\t\t\tresult = Math.min.apply(null, value) ;\n\t\t\t\tbreak;\n\n\t\t\tcase \"avg\":\n\t\t\t\tresult = value.reduce(function(c, d){\n\t\t\t\t\treturn c + d;\n\t\t\t\t}) / value.length;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//handle non array values\n\tif(!Array.isArray(a)){\n\t\temptyAlign = !Array.isArray(b) ? 0 : -1;\n\t}else if(!Array.isArray(b)){\n\t\temptyAlign = 1;\n\t}else {\n\t\treturn calc(b) - calc(a);\n\t}\n\n\t//fix empty values in position\n\tif((alignEmptyValues === \"top\" && dir === \"desc\") || (alignEmptyValues === \"bottom\" && dir === \"asc\")){\n\t\temptyAlign *= -1;\n\t}\n\n\treturn emptyAlign;\n}\n\n//sort if element contains any data\nfunction exists(a, b, aRow, bRow, column, dir, params){\n\tvar el1 = typeof a == \"undefined\" ? 0 : 1;\n\tvar el2 = typeof b == \"undefined\" ? 0 : 1;\n\n\treturn el1 - el2;\n}\n\n//sort alpha numeric strings\nfunction alphanum(as, bs, aRow, bRow, column, dir, params){\n\tvar a, b, a1, b1, i= 0, L, rx = /(\\d+)|(\\D+)/g, rd = /\\d/;\n\tvar alignEmptyValues = params.alignEmptyValues;\n\tvar emptyAlign = 0;\n\n\t//handle empty values\n\tif(!as && as!== 0){\n\t\temptyAlign =  !bs && bs!== 0 ? 0 : -1;\n\t}else if(!bs && bs!== 0){\n\t\temptyAlign =  1;\n\t}else {\n\n\t\tif(isFinite(as) && isFinite(bs)) return as - bs;\n\t\ta = String(as).toLowerCase();\n\t\tb = String(bs).toLowerCase();\n\t\tif(a === b) return 0;\n\t\tif(!(rd.test(a) && rd.test(b))) return a > b ? 1 : -1;\n\t\ta = a.match(rx);\n\t\tb = b.match(rx);\n\t\tL = a.length > b.length ? b.length : a.length;\n\t\twhile(i < L){\n\t\t\ta1= a[i];\n\t\t\tb1= b[i++];\n\t\t\tif(a1 !== b1){\n\t\t\t\tif(isFinite(a1) && isFinite(b1)){\n\t\t\t\t\tif(a1.charAt(0) === \"0\") a1 = \".\" + a1;\n\t\t\t\t\tif(b1.charAt(0) === \"0\") b1 = \".\" + b1;\n\t\t\t\t\treturn a1 - b1;\n\t\t\t\t}\n\t\t\t\telse return a1 > b1 ? 1 : -1;\n\t\t\t}\n\t\t}\n\n\t\treturn a.length > b.length;\n\t}\n\n\t//fix empty values in position\n\tif((alignEmptyValues === \"top\" && dir === \"desc\") || (alignEmptyValues === \"bottom\" && dir === \"asc\")){\n\t\temptyAlign *= -1;\n\t}\n\n\treturn emptyAlign;\n}\n\nvar defaultSorters = {\n\tnumber:number$1,\n\tstring:string,\n\tdate:date$1,\n\ttime:time$1,\n\tdatetime:datetime$2,\n\tboolean:boolean,\n\tarray:array,\n\texists:exists,\n\talphanum:alphanum\n};\n\nclass Sort extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.sortList = []; //holder current sort\n\t\tthis.changed = false; //has the sort changed since last render\n\t\t\n\t\tthis.registerTableOption(\"sortMode\", \"local\"); //local or remote sorting\n\t\t\n\t\tthis.registerTableOption(\"initialSort\", false); //initial sorting criteria\n\t\tthis.registerTableOption(\"columnHeaderSortMulti\", true); //multiple or single column sorting\n\t\tthis.registerTableOption(\"sortOrderReverse\", false); //reverse internal sort ordering\n\t\tthis.registerTableOption(\"headerSortElement\", \"<div class='tabulator-arrow'></div>\"); //header sort element\n\t\tthis.registerTableOption(\"headerSortClickElement\", \"header\"); //element which triggers sort when clicked\n\t\t\n\t\tthis.registerColumnOption(\"sorter\");\n\t\tthis.registerColumnOption(\"sorterParams\");\n\t\t\n\t\tthis.registerColumnOption(\"headerSort\", true);\n\t\tthis.registerColumnOption(\"headerSortStartingDir\");\n\t\tthis.registerColumnOption(\"headerSortTristate\");\n\t\t\n\t}\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"column-layout\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"table-built\", this.tableBuilt.bind(this));\n\t\tthis.registerDataHandler(this.sort.bind(this), 20);\n\t\t\n\t\tthis.registerTableFunction(\"setSort\", this.userSetSort.bind(this));\n\t\tthis.registerTableFunction(\"getSorters\", this.getSort.bind(this));\n\t\tthis.registerTableFunction(\"clearSort\", this.clearSort.bind(this));\n\t\t\n\t\tif(this.table.options.sortMode === \"remote\"){\n\t\t\tthis.subscribe(\"data-params\", this.remoteSortParams.bind(this));\n\t\t}\n\t}\n\t\n\ttableBuilt(){\n\t\tif(this.table.options.initialSort){\n\t\t\tthis.setSort(this.table.options.initialSort);\n\t\t}\n\t}\n\t\n\tremoteSortParams(data, config, silent, params){\n\t\tvar sorters = this.getSort();\n\t\t\n\t\tsorters.forEach((item) => {\n\t\t\tdelete item.column;\n\t\t});\n\t\t\n\t\tparams.sort = sorters;\n\t\t\n\t\treturn params;\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\t\n\tuserSetSort(sortList, dir){\n\t\tthis.setSort(sortList, dir);\n\t\t// this.table.rowManager.sorterRefresh();\n\t\tthis.refreshSort();\n\t}\n\t\n\tclearSort(){\n\t\tthis.clear();\n\t\t// this.table.rowManager.sorterRefresh();\n\t\tthis.refreshSort();\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\t//initialize column header for sorting\n\tinitializeColumn(column){\n\t\tvar sorter = false,\n\t\tcolEl,\n\t\tarrowEl;\n\t\t\n\t\tswitch(typeof column.definition.sorter){\n\t\t\tcase \"string\":\n\t\t\t\tif(Sort.sorters[column.definition.sorter]){\n\t\t\t\t\tsorter = Sort.sorters[column.definition.sorter];\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Sort Error - No such sorter found: \", column.definition.sorter);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"function\":\n\t\t\t\tsorter = column.definition.sorter;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcolumn.modules.sort = {\n\t\t\tsorter:sorter, dir:\"none\",\n\t\t\tparams:column.definition.sorterParams || {},\n\t\t\tstartingDir:column.definition.headerSortStartingDir || \"asc\",\n\t\t\ttristate: column.definition.headerSortTristate,\n\t\t};\n\t\t\n\t\tif(column.definition.headerSort !== false){\n\t\t\t\n\t\t\tcolEl = column.getElement();\n\t\t\t\n\t\t\tcolEl.classList.add(\"tabulator-sortable\");\n\t\t\t\n\t\t\tarrowEl = document.createElement(\"div\");\n\t\t\tarrowEl.classList.add(\"tabulator-col-sorter\");\n\t\t\t\n\t\t\tswitch(this.table.options.headerSortClickElement){\n\t\t\t\tcase \"icon\":\n\t\t\t\t\tarrowEl.classList.add(\"tabulator-col-sorter-element\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"header\":\n\t\t\t\t\tcolEl.classList.add(\"tabulator-col-sorter-element\");\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tcolEl.classList.add(\"tabulator-col-sorter-element\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tswitch(this.table.options.headerSortElement){\n\t\t\t\tcase \"function\":\n\t\t\t\t//do nothing\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase \"object\":\n\t\t\t\t\tarrowEl.appendChild(this.table.options.headerSortElement);\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tdefault:\n\t\t\t\t\tarrowEl.innerHTML = this.table.options.headerSortElement;\n\t\t\t}\n\t\t\t\n\t\t\t//create sorter arrow\n\t\t\tcolumn.titleHolderElement.appendChild(arrowEl);\n\t\t\t\n\t\t\tcolumn.modules.sort.element = arrowEl;\n\t\t\t\n\t\t\tthis.setColumnHeaderSortIcon(column, \"none\");\n\t\t\t\n\t\t\tif(this.table.options.headerSortClickElement === \"icon\"){\n\t\t\t\tarrowEl.addEventListener(\"mousedown\", (e) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\t//sort on click\n\t\t\t(this.table.options.headerSortClickElement === \"icon\" ? arrowEl : colEl).addEventListener(\"click\", (e) => {\n\t\t\t\tvar dir = \"\",\n\t\t\t\tsorters=[],\n\t\t\t\tmatch = false;\n\t\t\t\t\n\t\t\t\tif(column.modules.sort){\n\t\t\t\t\tif(column.modules.sort.tristate){\n\t\t\t\t\t\tif(column.modules.sort.dir == \"none\"){\n\t\t\t\t\t\t\tdir = column.modules.sort.startingDir;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif(column.modules.sort.dir == column.modules.sort.startingDir){\n\t\t\t\t\t\t\t\tdir = column.modules.sort.dir == \"asc\" ? \"desc\" : \"asc\";\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tdir = \"none\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tswitch(column.modules.sort.dir){\n\t\t\t\t\t\t\tcase \"asc\":\n\t\t\t\t\t\t\t\tdir = \"desc\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase \"desc\":\n\t\t\t\t\t\t\t\tdir = \"asc\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tdir = column.modules.sort.startingDir;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (this.table.options.columnHeaderSortMulti && (e.shiftKey || e.ctrlKey)) {\n\t\t\t\t\t\tsorters = this.getSort();\n\t\t\t\t\t\t\n\t\t\t\t\t\tmatch = sorters.findIndex((sorter) => {\n\t\t\t\t\t\t\treturn sorter.field === column.getField();\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(match > -1){\n\t\t\t\t\t\t\tsorters[match].dir = dir;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tmatch = sorters.splice(match, 1)[0];\n\t\t\t\t\t\t\tif(dir != \"none\"){\n\t\t\t\t\t\t\t\tsorters.push(match);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif(dir != \"none\"){\n\t\t\t\t\t\t\t\tsorters.push({column:column, dir:dir});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t//add to existing sort\n\t\t\t\t\t\tthis.setSort(sorters);\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(dir == \"none\"){\n\t\t\t\t\t\t\tthis.clear();\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t//sort by column only\n\t\t\t\t\t\t\tthis.setSort(column, dir);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// this.table.rowManager.sorterRefresh(!this.sortList.length);\n\t\t\t\t\tthis.refreshSort();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\t\n\trefreshSort(){\n\t\tif(this.table.options.sortMode === \"remote\"){\n\t\t\tthis.reloadData(null, false, false);\n\t\t}else {\n\t\t\tthis.refreshData(true);\n\t\t}\n\t\t\n\t\t//TODO - Persist left position of row manager\n\t\t// left = this.scrollLeft;\n\t\t// this.scrollHorizontal(left);\n\t}\n\t\n\t//check if the sorters have changed since last use\n\thasChanged(){\n\t\tvar changed = this.changed;\n\t\tthis.changed = false;\n\t\treturn changed;\n\t}\n\t\n\t//return current sorters\n\tgetSort(){\n\t\tvar self = this,\n\t\tsorters = [];\n\t\t\n\t\tself.sortList.forEach(function(item){\n\t\t\tif(item.column){\n\t\t\t\tsorters.push({column:item.column.getComponent(), field:item.column.getField(), dir:item.dir});\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn sorters;\n\t}\n\t\n\t//change sort list and trigger sort\n\tsetSort(sortList, dir){\n\t\tvar self = this,\n\t\tnewSortList = [];\n\t\t\n\t\tif(!Array.isArray(sortList)){\n\t\t\tsortList = [{column: sortList, dir:dir}];\n\t\t}\n\t\t\n\t\tsortList.forEach(function(item){\n\t\t\tvar column;\n\t\t\t\n\t\t\tcolumn = self.table.columnManager.findColumn(item.column);\n\t\t\t\n\t\t\tif(column){\n\t\t\t\titem.column = column;\n\t\t\t\tnewSortList.push(item);\n\t\t\t\tself.changed = true;\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Sort Warning - Sort field does not exist and is being ignored: \", item.column);\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\tself.sortList = newSortList;\n\t\t\n\t\tthis.dispatch(\"sort-changed\");\n\t}\n\t\n\t//clear sorters\n\tclear(){\n\t\tthis.setSort([]);\n\t}\n\t\n\t//find appropriate sorter for column\n\tfindSorter(column){\n\t\tvar row = this.table.rowManager.activeRows[0],\n\t\tsorter = \"string\",\n\t\tfield, value;\n\t\t\n\t\tif(row){\n\t\t\trow = row.getData();\n\t\t\tfield = column.getField();\n\t\t\t\n\t\t\tif(field){\n\t\t\t\t\n\t\t\t\tvalue = column.getFieldValue(row);\n\t\t\t\t\n\t\t\t\tswitch(typeof value){\n\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\tsorter = \"string\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"boolean\":\n\t\t\t\t\t\tsorter = \"boolean\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif(!isNaN(value) && value !== \"\"){\n\t\t\t\t\t\t\tsorter = \"number\";\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif(value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)){\n\t\t\t\t\t\t\t\tsorter = \"alphanum\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn Sort.sorters[sorter];\n\t}\n\t\n\t//work through sort list sorting data\n\tsort(data){\n\t\tvar self = this,\n\t\tsortList = this.table.options.sortOrderReverse ? self.sortList.slice().reverse() : self.sortList,\n\t\tsortListActual = [],\n\t\trowComponents = [];\n\t\t\n\t\tif(this.subscribedExternal(\"dataSorting\")){\n\t\t\tthis.dispatchExternal(\"dataSorting\", self.getSort());\n\t\t}\n\t\t\n\t\tself.clearColumnHeaders();\n\t\t\n\t\tif(this.table.options.sortMode !== \"remote\"){\n\t\t\t\n\t\t\t//build list of valid sorters and trigger column specific callbacks before sort begins\n\t\t\tsortList.forEach(function(item, i){\n\t\t\t\tvar sortObj;\n\t\t\t\t\n\t\t\t\tif(item.column){\n\t\t\t\t\tsortObj = item.column.modules.sort;\n\t\t\t\t\t\n\t\t\t\t\tif(sortObj){\n\t\t\t\t\t\t\n\t\t\t\t\t\t//if no sorter has been defined, take a guess\n\t\t\t\t\t\tif(!sortObj.sorter){\n\t\t\t\t\t\t\tsortObj.sorter = self.findSorter(item.column);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\titem.params = typeof sortObj.params === \"function\" ? sortObj.params(item.column.getComponent(), item.dir) : sortObj.params;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsortListActual.push(item);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tself.setColumnHeader(item.column, item.dir);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t//sort data\n\t\t\tif (sortListActual.length) {\n\t\t\t\tself._sortItems(data, sortListActual);\n\t\t\t}\n\t\t\t\n\t\t}else {\n\t\t\tsortList.forEach(function(item, i){\n\t\t\t\tself.setColumnHeader(item.column, item.dir);\n\t\t\t});\n\t\t}\n\t\t\n\t\tif(this.subscribedExternal(\"dataSorted\")){\n\t\t\tdata.forEach((row) => {\n\t\t\t\trowComponents.push(row.getComponent());\n\t\t\t});\n\t\t\t\n\t\t\tthis.dispatchExternal(\"dataSorted\", self.getSort(), rowComponents);\n\t\t}\n\t\t\n\t\treturn data;\n\t}\n\t\n\t//clear sort arrows on columns\n\tclearColumnHeaders(){\n\t\tthis.table.columnManager.getRealColumns().forEach((column) => {\n\t\t\tif(column.modules.sort){\n\t\t\t\tcolumn.modules.sort.dir = \"none\";\n\t\t\t\tcolumn.getElement().setAttribute(\"aria-sort\", \"none\");\n\t\t\t\tthis.setColumnHeaderSortIcon(column, \"none\");\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//set the column header sort direction\n\tsetColumnHeader(column, dir){\n\t\tcolumn.modules.sort.dir = dir;\n\t\tcolumn.getElement().setAttribute(\"aria-sort\", dir === \"asc\" ? \"ascending\" : \"descending\");\n\t\tthis.setColumnHeaderSortIcon(column, dir);\n\t}\n\t\n\tsetColumnHeaderSortIcon(column, dir){\n\t\tvar sortEl = column.modules.sort.element,\n\t\tarrowEl;\n\t\t\n\t\tif(column.definition.headerSort && typeof this.table.options.headerSortElement === \"function\"){\n\t\t\twhile(sortEl.firstChild) sortEl.removeChild(sortEl.firstChild);\n\t\t\t\n\t\t\tarrowEl = this.table.options.headerSortElement.call(this.table, column.getComponent(), dir);\n\t\t\t\n\t\t\tif(typeof arrowEl === \"object\"){\n\t\t\t\tsortEl.appendChild(arrowEl);\n\t\t\t}else {\n\t\t\t\tsortEl.innerHTML = arrowEl;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t//sort each item in sort list\n\t_sortItems(data, sortList){\n\t\tvar sorterCount = sortList.length - 1;\n\t\t\n\t\tdata.sort((a, b) => {\n\t\t\tvar result;\n\t\t\t\n\t\t\tfor(var i = sorterCount; i>= 0; i--){\n\t\t\t\tlet sortItem = sortList[i];\n\t\t\t\t\n\t\t\t\tresult = this._sortRow(a, b, sortItem.column, sortItem.dir, sortItem.params);\n\t\t\t\t\n\t\t\t\tif(result !== 0){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\treturn result;\n\t\t});\n\t}\n\t\n\t//process individual rows for a sort function on active data\n\t_sortRow(a, b, column, dir, params){\n\t\tvar el1Comp, el2Comp;\n\t\t\n\t\t//switch elements depending on search direction\n\t\tvar el1 = dir == \"asc\" ? a : b;\n\t\tvar el2 = dir == \"asc\" ? b : a;\n\t\t\n\t\ta = column.getFieldValue(el1.getData());\n\t\tb = column.getFieldValue(el2.getData());\n\t\t\n\t\ta = typeof a !== \"undefined\" ? a : \"\";\n\t\tb = typeof b !== \"undefined\" ? b : \"\";\n\t\t\n\t\tel1Comp = el1.getComponent();\n\t\tel2Comp = el2.getComponent();\n\t\t\n\t\treturn column.modules.sort.sorter.call(this, a, b, el1Comp, el2Comp, column.getComponent(), dir, params);\n\t}\n}\n\nSort.moduleName = \"sort\";\n\n//load defaults\nSort.sorters = defaultSorters;\n\nclass RangeComponent {\n\tconstructor(range) {\n\t\tthis._range = range;\n\n\t\treturn new Proxy(this, {\n\t\t\tget: function (target, name, receiver) {\n\t\t\t\tif (typeof target[name] !== \"undefined\") {\n\t\t\t\t\treturn target[name];\n\t\t\t\t} else {\n\t\t\t\t\treturn target._range.table.componentFunctionBinder.handle(\"range\", target._range, name);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\tgetElement() {\n\t\treturn this._range.element;\n\t}\n\n\tgetData() {\n\t\treturn this._range.getData();\n\t}\n\n\tgetCells() {\n\t\treturn this._range.getCells(true);\n\t}\n\n\tgetStructuredCells() {\n\t\treturn this._range.getStructuredCells();\n\t}\n\n\tgetRows() {\n\t\treturn this._range.getRows().map((row) => row.getComponent());\n\t}\n\n\tgetColumns() {\n\t\treturn this._range.getColumns().map((column) => column.getComponent());\n\t}\n\t\n\tgetBounds() {\n\t\treturn this._range.getBounds();\n\t}\n\n\tgetTopEdge() {\n\t\treturn this._range.top;\n\t}\n\n\tgetBottomEdge() {\n\t\treturn this._range.bottom;\n\t}\n\n\tgetLeftEdge() {\n\t\treturn this._range.left;\n\t}\n\n\tgetRightEdge() {\n\t\treturn this._range.right;\n\t}\n\n\tsetBounds(start, end){\n\t\tif(this._range.destroyedGuard(\"setBounds\")){\n\t\t\tthis._range.setBounds(start ? start._cell : start, end ? end._cell : end);\n\t\t}\n\t}\n\n\tsetStartBound(start){\n\t\tif(this._range.destroyedGuard(\"setStartBound\")){\n\t\t\tthis._range.setEndBound(start ? start._cell : start);\n\t\t\tthis._range.rangeManager.layoutElement();\n\t\t}\n\t}\n\n\tsetEndBound(end){\n\t\tif(this._range.destroyedGuard(\"setEndBound\")){\n\t\t\tthis._range.setEndBound(end ? end._cell : end);\n\t\t\tthis._range.rangeManager.layoutElement();\n\t\t}\n\t}\n\n\tclearValues(){\n\t\tif(this._range.destroyedGuard(\"clearValues\")){\n\t\t\tthis._range.clearValues();\n\t\t}\n\t}\n\n\tremove(){\n\t\tif(this._range.destroyedGuard(\"remove\")){\n\t\t\tthis._range.destroy(true);\n\t\t}\n\t}\n}\n\nclass Range extends CoreFeature{\n\tconstructor(table, rangeManager, start, end) {\n\t\tsuper(table);\n\t\t\n\t\tthis.rangeManager = rangeManager;\n\t\tthis.element = null;\n\t\tthis.initialized = false;\n\t\tthis.initializing = {\n\t\t\tstart:false,\n\t\t\tend:false,\n\t\t};\n\t\tthis.destroyed = false;\n\t\t\n\t\tthis.top = 0;\n\t\tthis.bottom = 0;\n\t\tthis.left = 0;\n\t\tthis.right = 0;\n\t\t\n\t\tthis.table = table;\n\t\tthis.start = {row:0, col:0};\n\t\tthis.end = {row:0, col:0};\n\n\t\tif(this.rangeManager.rowHeader){\n\t\t\tthis.left = 1;\n\t\t\tthis.right = 1;\n\t\t\tthis.start.col = 1;\n\t\t\tthis.end.col = 1;\n\t\t}\n\t\t\n\t\tthis.initElement();\n\t\t\n\t\tsetTimeout(() => {\n\t\t\tthis.initBounds(start, end);\n\t\t});\n\t}\n\t\n\tinitElement(){\n\t\tthis.element = document.createElement(\"div\");\n\t\tthis.element.classList.add(\"tabulator-range\");\n\t}\n\t\n\tinitBounds(start, end){\n\t\tthis._updateMinMax();\n\t\t\n\t\tif(start){\n\t\t\tthis.setBounds(start, end || start);\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t///////   Boundary Setup    ///////\n\t///////////////////////////////////\n\t\n\tsetStart(row, col) {\n\t\tif(this.start.row !== row || this.start.col !== col){\n\t\t\tthis.start.row = row;\n\t\t\tthis.start.col = col;\n\t\t\t\n\t\t\tthis.initializing.start = true;\n\t\t\tthis._updateMinMax();\n\t\t}\n\t}\n\t\n\tsetEnd(row, col) {\n\t\tif(this.end.row !== row || this.end.col !== col){\n\t\t\tthis.end.row = row;\n\t\t\tthis.end.col = col;\n\t\t\t\n\t\t\tthis.initializing.end = true;\n\t\t\tthis._updateMinMax();\n\t\t}\n\t}\n\t\n\tsetBounds(start, end, visibleRows){\n\t\tif(start){\n\t\t\tthis.setStartBound(start);\n\t\t}\n\t\t\n\t\tthis.setEndBound(end || start);\n\t\tthis.rangeManager.layoutElement(visibleRows);\n\t}\n\t\n\tsetStartBound(element){\n\t\tvar row, col;\n\t\t\n\t\tif (element.type === \"column\") {\n\t\t\tif(this.rangeManager.columnSelection){\n\t\t\t\tthis.setStart(0, element.getPosition() - 1);\n\t\t\t}\n\t\t}else {\n\t\t\trow = element.row.position - 1;\n\t\t\tcol = element.column.getPosition() - 1;\n\t\t\t\n\t\t\tif (element.column === this.rangeManager.rowHeader) {\n\t\t\t\tthis.setStart(row, 1);\n\t\t\t} else {\n\t\t\t\tthis.setStart(row, col);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tsetEndBound(element){\n\t\tvar rowsCount = this._getTableRows().length,\n\t\trow, col, isRowHeader;\n\t\t\n\t\tif (element.type === \"column\") {\n\t\t\tif(this.rangeManager.columnSelection){\n\t\t\t\tif (this.rangeManager.selecting === \"column\") {\n\t\t\t\t\tthis.setEnd(rowsCount - 1, element.getPosition() - 1);\n\t\t\t\t} else if (this.rangeManager.selecting === \"cell\") {\n\t\t\t\t\tthis.setEnd(0, element.getPosition() - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\trow = element.row.position - 1;\n\t\t\tcol = element.column.getPosition() - 1;\n\t\t\tisRowHeader = element.column === this.rangeManager.rowHeader;\n\t\t\t\n\t\t\tif (this.rangeManager.selecting === \"row\") {\n\t\t\t\tthis.setEnd(row, this._getTableColumns().length - 1);\n\t\t\t} else if (this.rangeManager.selecting !== \"row\" && isRowHeader) {\n\t\t\t\tthis.setEnd(row, 0);\n\t\t\t} else if (this.rangeManager.selecting === \"column\") {\n\t\t\t\tthis.setEnd(rowsCount - 1, col);\n\t\t\t} else {\n\t\t\t\tthis.setEnd(row, col);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_updateMinMax() {\n\t\tthis.top = Math.min(this.start.row, this.end.row);\n\t\tthis.bottom = Math.max(this.start.row, this.end.row);\n\t\tthis.left = Math.min(this.start.col, this.end.col);\n\t\tthis.right = Math.max(this.start.col, this.end.col);\n\t\t\n\t\tif(this.initialized){\n\t\t\tthis.dispatchExternal(\"rangeChanged\", this.getComponent());\n\t\t}else {\n\t\t\tif(this.initializing.start && this.initializing.end){\n\t\t\t\tthis.initialized = true;\n\t\t\t\tthis.dispatchExternal(\"rangeAdded\", this.getComponent());\n\t\t\t}\n\t\t}\n\t}\n\t\n\t_getTableColumns() {\n\t\treturn this.table.columnManager.getVisibleColumnsByIndex();\n\t}\n\t\n\t_getTableRows() {\n\t\treturn this.table.rowManager.getDisplayRows();\n\t}\n\t\n\t///////////////////////////////////\n\t///////      Rendering      ///////\n\t///////////////////////////////////\n\t\n\tlayout() {\n\t\tvar _vDomTop = this.table.rowManager.renderer.vDomTop,\n\t\t_vDomBottom = this.table.rowManager.renderer.vDomBottom,\n\t\t_vDomLeft = this.table.columnManager.renderer.leftCol,\n\t\t_vDomRight = this.table.columnManager.renderer.rightCol,\t\t\n\t\ttop, bottom, left, right, topLeftCell, bottomRightCell;\n\t\t\n\t\tif (_vDomTop == null) {\n\t\t\t_vDomTop = 0;\n\t\t}\n\t\t\n\t\tif (_vDomBottom == null) {\n\t\t\t_vDomBottom = Infinity;\n\t\t}\n\t\t\n\t\tif (_vDomLeft == null) {\n\t\t\t_vDomLeft = 0;\n\t\t}\n\t\t\n\t\tif (_vDomRight == null) {\n\t\t\t_vDomRight = Infinity;\n\t\t}\n\t\t\n\t\tif (this.overlaps(_vDomLeft, _vDomTop, _vDomRight, _vDomBottom)) {\n\t\t\ttop = Math.max(this.top, _vDomTop);\n\t\t\tbottom = Math.min(this.bottom, _vDomBottom);\n\t\t\tleft = Math.max(this.left, _vDomLeft);\n\t\t\tright = Math.min(this.right, _vDomRight);\n\t\t\t\n\t\t\ttopLeftCell = this.rangeManager.getCell(top, left);\n\t\t\tbottomRightCell = this.rangeManager.getCell(bottom, right);\n\t\t\t\n\t\t\tthis.element.classList.add(\"tabulator-range-active\");\n\t\t\t// this.element.classList.toggle(\"tabulator-range-active\", this === this.rangeManager.activeRange);\n\t\t\t\n\t\t\tthis.element.style.left = topLeftCell.row.getElement().offsetLeft + topLeftCell.getElement().offsetLeft + \"px\";\n\t\t\tthis.element.style.top = topLeftCell.row.getElement().offsetTop + \"px\";\n\t\t\tthis.element.style.width = bottomRightCell.getElement().offsetLeft + bottomRightCell.getElement().offsetWidth - topLeftCell.getElement().offsetLeft + \"px\";\n\t\t\tthis.element.style.height = bottomRightCell.row.getElement().offsetTop + bottomRightCell.row.getElement().offsetHeight - topLeftCell.row.getElement().offsetTop + \"px\";\n\t\t}\n\t}\n\t\n\tatTopLeft(cell) {\n\t\treturn cell.row.position - 1 === this.top && cell.column.getPosition() - 1 === this.left;\n\t}\n\t\n\tatBottomRight(cell) {\n\t\treturn cell.row.position - 1 === this.bottom && cell.column.getPosition() - 1 === this.right;\n\t}\n\t\n\toccupies(cell) {\n\t\treturn this.occupiesRow(cell.row) && this.occupiesColumn(cell.column);\n\t}\n\t\n\toccupiesRow(row) {\n\t\treturn this.top <= row.position - 1 && row.position - 1 <= this.bottom;\n\t}\n\t\n\toccupiesColumn(col) {\n\t\treturn this.left <= col.getPosition() - 1 && col.getPosition() - 1 <= this.right;\n\t}\n\t\n\toverlaps(left, top, right, bottom) {\n\t\tif ((this.left > right || left > this.right) || (this.top > bottom || top > this.bottom)){\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\n\tgetData() {\n\t\tvar data = [],\n\t\trows = this.getRows(),\n\t\tcolumns = this.getColumns();\n\t\t\n\t\trows.forEach((row) => {\n\t\t\tvar rowData = row.getData(),\n\t\t\tresult = {};\n\t\t\t\n\t\t\tcolumns.forEach((column) => {\n\t\t\t\tresult[column.field] = rowData[column.field];\n\t\t\t});\n\t\t\t\n\t\t\tdata.push(result);\n\t\t});\n\t\t\n\t\treturn data;\n\t}\n\t\n\tgetCells(structured, component) {\n\t\tvar cells = [],\n\t\trows = this.getRows(),\n\t\tcolumns = this.getColumns();\n\t\t\n\t\tif (structured) {\n\t\t\tcells = rows.map((row) => {\n\t\t\t\tvar arr = [];\n\t\t\t\t\n\t\t\t\trow.getCells().forEach((cell) => {\n\t\t\t\t\tif (columns.includes(cell.column)) {\n\t\t\t\t\t\tarr.push(component ? cell.getComponent() : cell);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\treturn arr;\n\t\t\t});\n\t\t} else {\n\t\t\trows.forEach((row) => {\n\t\t\t\trow.getCells().forEach((cell) => {\n\t\t\t\t\tif (columns.includes(cell.column)) {\n\t\t\t\t\t\tcells.push(component ? cell.getComponent() : cell);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn cells;\n\t}\n\t\n\tgetStructuredCells() {\n\t\treturn this.getCells(true, true);\n\t}\n\t\n\tgetRows() {\n\t\treturn this._getTableRows().slice(this.top, this.bottom + 1);\n\t}\n\t\n\tgetColumns() {\n\t\treturn this._getTableColumns().slice(this.left, this.right + 1);\n\t}\n\t\n\tclearValues(){\n\t\tvar cells = this.getCells();\n\t\tvar clearValue = this.table.options.selectableRangeClearCellsValue;\n\t\t\n\t\tthis.table.blockRedraw();\n\t\t\n\t\tcells.forEach((cell) => {\n\t\t\tcell.setValue(clearValue);\n\t\t});\n\t\t\n\t\tthis.table.restoreRedraw();\n\t\t\n\t}\n\t\n\tgetBounds(component){\n\t\tvar cells = this.getCells(false, component),\n\t\toutput = {\n\t\t\tstart:null,\n\t\t\tend:null,\n\t\t};\n\t\t\n\t\tif(cells.length){\n\t\t\toutput.start = cells[0];\n\t\t\toutput.end = cells[cells.length - 1];\n\t\t}else {\n\t\t\tconsole.warn(\"No bounds defined on range\");\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetComponent() {\n\t\tif (!this.component) {\n\t\t\tthis.component = new RangeComponent(this);\n\t\t}\n\t\treturn this.component;\n\t}\n\t\n\tdestroy(notify) {\n\t\tthis.destroyed = true;\n\t\t\n\t\tthis.element.remove();\n\t\t\n\t\tif(notify){\n\t\t\tthis.rangeManager.rangeRemoved(this);\n\t\t}\n\t\t\n\t\tif(this.initialized){\n\t\t\tthis.dispatchExternal(\"rangeRemoved\", this.getComponent());\n\t\t}\n\t}\n\t\n\tdestroyedGuard(func){\n\t\tif(this.destroyed){\n\t\t\tconsole.warn(\"You cannot call the \"  + func + \" function on a destroyed range\");\n\t\t}\n\t\t\n\t\treturn !this.destroyed;\n\t}\n}\n\nclass SelectRange extends Module {\n\tconstructor(table) {\n\t\tsuper(table);\n\t\t\n\t\tthis.selecting = \"cell\";\n\t\tthis.mousedown = false;\n\t\tthis.ranges = [];\n\t\tthis.overlay = null;\n\t\tthis.rowHeader = null;\n\t\tthis.layoutChangeTimeout = null;\n\t\tthis.columnSelection = false;\n\t\tthis.rowSelection = false;\n\t\tthis.maxRanges = 0;\n\t\tthis.activeRange = false;\n\t\tthis.blockKeydown = false;\n\t\t\n\t\tthis.keyDownEvent = this._handleKeyDown.bind(this);\n\t\tthis.mouseUpEvent = this._handleMouseUp.bind(this);\n\t\t\n\t\tthis.registerTableOption(\"selectableRange\", false); //enable selectable range\n\t\tthis.registerTableOption(\"selectableRangeColumns\", false); //enable selectable range\n\t\tthis.registerTableOption(\"selectableRangeRows\", false); //enable selectable range\n\t\tthis.registerTableOption(\"selectableRangeClearCells\", false); //allow clearing of active range\n\t\tthis.registerTableOption(\"selectableRangeClearCellsValue\", undefined); //value for cleared active range\n\n\t\tthis.registerTableFunction(\"getRangesData\", this.getRangesData.bind(this));\n\t\tthis.registerTableFunction(\"getRanges\", this.getRanges.bind(this));\n\t\tthis.registerTableFunction(\"addRange\", this.addRangeFromComponent.bind(this));\n\n\t\tthis.registerComponentFunction(\"cell\", \"getRanges\", this.cellGetRanges.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"getRanges\", this.rowGetRanges.bind(this));\n\t\tthis.registerComponentFunction(\"column\", \"getRanges\", this.colGetRanges.bind(this));\n\t}\n\t\n\t///////////////////////////////////\n\t///////    Initialization   ///////\n\t///////////////////////////////////\n\t\n\tinitialize() {\n\t\tif (this.options(\"selectableRange\")) {\t\t\n\t\t\tif(!this.options(\"selectableRows\")){\n\t\t\t\t\n\t\t\t\tthis.maxRanges = this.options(\"selectableRange\");\n\t\t\t\t\n\t\t\t\tthis.initializeTable();\n\t\t\t\tthis.initializeWatchers();\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"SelectRange functionality cannot be used in conjunction with row selection\");\n\t\t\t}\n\t\t}\n\t}\n\t\n\t\n\tinitializeTable() {\t\t\n\t\tthis.overlay = document.createElement(\"div\");\n\t\tthis.overlay.classList.add(\"tabulator-range-overlay\");\n\t\t\n\t\tthis.rangeContainer = document.createElement(\"div\");\n\t\tthis.rangeContainer.classList.add(\"tabulator-range-container\");\n\t\t\n\t\tthis.activeRangeCellElement = document.createElement(\"div\");\n\t\tthis.activeRangeCellElement.classList.add(\"tabulator-range-cell-active\");\n\t\t\n\t\tthis.overlay.appendChild(this.rangeContainer);\n\t\tthis.overlay.appendChild(this.activeRangeCellElement);\n\t\t\n\t\tthis.table.rowManager.element.addEventListener(\"keydown\", this.keyDownEvent);\n\t\t\n\t\tthis.resetRanges();\n\t\t\n\t\tthis.table.rowManager.element.appendChild(this.overlay);\n\t\tthis.table.columnManager.element.setAttribute(\"tabindex\", 0);\n\t\tthis.table.element.classList.add(\"tabulator-ranges\");\n\t}\n\t\n\tinitializeWatchers() {\n\t\tthis.columnSelection = this.options(\"selectableRangeColumns\");\n\t\tthis.rowSelection = this.options(\"selectableRangeRows\");\n\t\t\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t\tthis.subscribe(\"column-mousedown\", this.handleColumnMouseDown.bind(this));\n\t\tthis.subscribe(\"column-mousemove\", this.handleColumnMouseMove.bind(this));\n\t\tthis.subscribe(\"column-resized\", this.handleColumnResized.bind(this));\n\t\tthis.subscribe(\"column-width\", this.layoutChange.bind(this));\n\t\tthis.subscribe(\"column-height\", this.layoutChange.bind(this));\n\t\tthis.subscribe(\"column-resized\", this.layoutChange.bind(this));\n\t\tthis.subscribe(\"columns-loaded\", this.updateHeaderColumn.bind(this));\n\n\t\tthis.subscribe(\"cell-height\", this.layoutChange.bind(this));\n\t\tthis.subscribe(\"cell-rendered\", this.renderCell.bind(this));\n\t\tthis.subscribe(\"cell-mousedown\", this.handleCellMouseDown.bind(this));\n\t\tthis.subscribe(\"cell-mousemove\", this.handleCellMouseMove.bind(this));\n\t\tthis.subscribe(\"cell-click\", this.handleCellClick.bind(this));\n\t\tthis.subscribe(\"cell-editing\", this.handleEditingCell.bind(this));\n\t\t\n\t\tthis.subscribe(\"page-changed\", this.redraw.bind(this));\n\n\t\tthis.subscribe(\"scroll-vertical\", this.layoutChange.bind(this));\n\t\tthis.subscribe(\"scroll-horizontal\", this.layoutChange.bind(this));\n\t\t\n\t\tthis.subscribe(\"data-destroy\", this.tableDestroyed.bind(this));\n\t\tthis.subscribe(\"data-processed\", this.resetRanges.bind(this));\n\t\t\n\t\tthis.subscribe(\"table-layout\", this.layoutElement.bind(this));\n\t\tthis.subscribe(\"table-redraw\", this.redraw.bind(this));\n\t\tthis.subscribe(\"table-destroy\", this.tableDestroyed.bind(this));\n\t\t\n\t\tthis.subscribe(\"edit-editor-clear\", this.finishEditingCell.bind(this));\n\t\tthis.subscribe(\"edit-blur\", this.restoreFocus.bind(this));\n\t\t\n\t\tthis.subscribe(\"keybinding-nav-prev\", this.keyNavigate.bind(this, \"left\"));\n\t\tthis.subscribe(\"keybinding-nav-next\", this.keyNavigate.bind(this, \"right\"));\n\t\tthis.subscribe(\"keybinding-nav-left\", this.keyNavigate.bind(this, \"left\"));\n\t\tthis.subscribe(\"keybinding-nav-right\", this.keyNavigate.bind(this, \"right\"));\n\t\tthis.subscribe(\"keybinding-nav-up\", this.keyNavigate.bind(this, \"up\"));\n\t\tthis.subscribe(\"keybinding-nav-down\", this.keyNavigate.bind(this, \"down\"));\n\t\tthis.subscribe(\"keybinding-nav-range\", this.keyNavigateRange.bind(this));\n\t}\n\t\n\t\n\tinitializeColumn(column) {\n\t\tif(this.columnSelection && column.definition.headerSort && this.options(\"headerSortClickElement\") !== \"icon\"){\n\t\t\tconsole.warn(\"Using column headerSort with selectableRangeColumns option may result in unpredictable behavior. Consider using headerSortClickElement: 'icon'.\");\n\t\t}\n\t\t\n\t\tif (column.modules.edit) ;\n\t}\n\t\n\tupdateHeaderColumn(){\n\t\tif(this.rowSelection){\n\t\t\tthis.rowHeader = this.table.columnManager.getVisibleColumnsByIndex()[0];\n\t\t\t\n\t\t\tif(this.rowHeader){\n\t\t\t\tthis.rowHeader.definition.cssClass = this.rowHeader.definition.cssClass + \" tabulator-range-row-header\";\n\t\t\t\t\n\t\t\t\tif(this.rowHeader.definition.headerSort){\n\t\t\t\t\tconsole.warn(\"Using column headerSort with selectableRangeRows option may result in unpredictable behavior\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(this.rowHeader.definition.editor){\n\t\t\t\t\tconsole.warn(\"Using column editor with selectableRangeRows option may result in unpredictable behavior\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t///////   Table Functions   ///////\n\t///////////////////////////////////\n\t\n\tgetRanges(){\n\t\treturn this.ranges.map((range) => range.getComponent());\n\t}\n\t\n\tgetRangesData() {\n\t\treturn this.ranges.map((range) => range.getData());\n\t}\n\t\n\taddRangeFromComponent(start, end){\n\t\tstart = start ? start._cell : null;\n\t\tend = end ? end._cell : null;\n\t\t\n\t\treturn this.addRange(start, end);\n\t}\n\t\n\t///////////////////////////////////\n\t/////// Component Functions ///////\n\t///////////////////////////////////\n\t\n\tcellGetRanges(cell){\n\t\tvar ranges = [];\n\t\t\n\t\tif (cell.column === this.rowHeader) {\n\t\t\tranges = this.ranges.filter((range) => range.occupiesRow(cell.row));\n\t\t} else {\n\t\t\tranges = this.ranges.filter((range) => range.occupies(cell));\n\t\t}\n\t\t\n\t\treturn ranges.map((range) => range.getComponent());\n\t}\n\t\n\trowGetRanges(row){\n\t\tvar ranges = this.ranges.filter((range) => range.occupiesRow(row));\n\t\t\n\t\treturn ranges.map((range) => range.getComponent());\n\t}\n\t\n\tcolGetRanges(col){\n\t\tvar ranges = this.ranges.filter((range) => range.occupiesColumn(col));\n\t\t\n\t\treturn ranges.map((range) => range.getComponent());\n\t}\n\t\n\t///////////////////////////////////\n\t////////// Event Handlers /////////\n\t///////////////////////////////////\n\t\n\t_handleMouseUp(e){\n\t\tthis.mousedown = false;\n\t\tdocument.removeEventListener(\"mouseup\", this.mouseUpEvent);\n\t}\n\t\n\t_handleKeyDown(e) {\n\t\tif (!this.blockKeydown && (!this.table.modules.edit || (this.table.modules.edit && !this.table.modules.edit.currentCell))) {\n\t\t\tif (e.key === \"Enter\") {\n\t\t\t\t// is editing a cell?\n\t\t\t\tif (this.table.modules.edit && this.table.modules.edit.currentCell) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.table.modules.edit.editCell(this.getActiveCell());\n\t\t\t\t\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\tif ((e.key === \"Backspace\" || e.key === \"Delete\") && this.options(\"selectableRangeClearCells\")) {\n\t\t\t\tif(this.activeRange){\n\t\t\t\t\tthis.activeRange.clearValues();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tinitializeFocus(cell){\n\t\tvar range;\n\t\t\n\t\ttry{\n\t\t\tif (document.selection) { // IE\n\t\t\t\trange = document.body.createTextRange();\n\t\t\t\trange.moveToElementText(cell.getElement());\n\t\t\t\trange.select();\n\t\t\t} else if (window.getSelection) {\n\t\t\t\trange = document.createRange();\n\t\t\t\trange.selectNode(cell.getElement());\n\t\t\t\twindow.getSelection().removeAllRanges();\n\t\t\t\twindow.getSelection().addRange(range);\n\t\t\t}\n\t\t}catch(e){}\n\t}\n\t\n\trestoreFocus(element){\n\t\tthis.table.rowManager.element.focus();\n\t\t\n\t\treturn true;\n\t}\n\t\n\t///////////////////////////////////\n\t////// Column Functionality ///////\n\t///////////////////////////////////\n\t\n\thandleColumnResized(column) {\n\t\tvar selected;\n\t\t\n\t\tif (this.selecting !== \"column\" && this.selecting !== \"all\") {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tselected = this.ranges.some((range) => range.occupiesColumn(column));\n\t\t\n\t\tif (!selected) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.ranges.forEach((range) => {\n\t\t\tvar selectedColumns = range.getColumns(true);\n\t\t\t\n\t\t\tselectedColumns.forEach((selectedColumn) => {\n\t\t\t\tif (selectedColumn !== column) {\n\t\t\t\t\tselectedColumn.setWidth(column.width);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\t\n\thandleColumnMouseDown(event, column) {\n\t\tif (event.button === 2 && (this.selecting === \"column\" || this.selecting === \"all\") && this.activeRange.occupiesColumn(column)) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.mousedown = true;\n\t\t\n\t\tdocument.addEventListener(\"mouseup\", this.mouseUpEvent);\n\t\t\n\t\tthis.newSelection(event, column);\n\t}\n\t\n\thandleColumnMouseMove(e, column) {\n\t\tif (column === this.rowHeader || !this.mousedown || this.selecting === 'all') {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.activeRange.setBounds(false, column, true);\n\t}\n\t\n\t///////////////////////////////////\n\t//////// Cell Functionality ///////\n\t///////////////////////////////////\n\t\n\trenderCell(cell) {\n\t\tvar el = cell.getElement(),\n\t\trangeIdx = this.ranges.findIndex((range) => range.occupies(cell));\n\t\t\n\t\tel.classList.toggle(\"tabulator-range-selected\", rangeIdx !== -1);\n\t\tel.classList.toggle(\"tabulator-range-only-cell-selected\", this.ranges.length === 1 && this.ranges[0].atTopLeft(cell) &&\tthis.ranges[0].atBottomRight(cell));\n\t\t\n\t\tel.dataset.range = rangeIdx;\n\t}\n\t\n\thandleCellMouseDown(event, cell) {\n\t\tif (event.button === 2 && (this.activeRange.occupies(cell) || ((this.selecting === \"row\" || this.selecting === \"all\") && this.activeRange.occupiesRow(cell.row)))) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.mousedown = true;\n\t\t\n\t\tdocument.addEventListener(\"mouseup\", this.mouseUpEvent);\n\t\t\n\t\tthis.newSelection(event, cell);\n\t}\n\t\n\thandleCellMouseMove(e, cell) {\n\t\tif (!this.mousedown || this.selecting === \"all\") {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.activeRange.setBounds(false, cell, true);\n\t}\n\t\n\thandleCellClick(e, cell){\n\t\tthis.initializeFocus(cell);\n\t}\n\t\n\thandleEditingCell(cell) {\n\t\tif(this.activeRange){\n\t\t\tthis.activeRange.setBounds(cell);\n\t\t}\n\t}\n\t\n\tfinishEditingCell() {\n\t\tthis.blockKeydown = true;\n\t\tthis.table.rowManager.element.focus();\n\n\t\tsetTimeout(() => {\n\t\t\tthis.blockKeydown = false;\n\t\t}, 10);\n\t}\n\t\n\t///////////////////////////////////\n\t///////     Navigation      ///////\n\t///////////////////////////////////\n\t\n\tkeyNavigate(dir, e){\n\t\tif(this.navigate(false, false, dir)){\n\t\t\te.preventDefault();\n\t\t}\n\t}\n\t\n\tkeyNavigateRange(e, dir, jump, expand){\n\t\tif(this.navigate(jump, expand, dir)){\n\t\t\te.preventDefault();\n\t\t}\n\t}\n\t\n\tnavigate(jump, expand, dir) {\n\t\tvar moved = false,\n\t\trange, rangeEdge, nextRow, nextCol, row, column;\n\t\t\n\t\t// Don't navigate while editing\n\t\tif (this.table.modules.edit && this.table.modules.edit.currentCell) {\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// If there are more than 1 range, use the active range and destroy the others\n\t\tif (this.ranges.length > 1) {\n\t\t\tthis.ranges = this.ranges.filter((range) => {\n\t\t\t\tif (range === this.activeRange) {\n\t\t\t\t\trange.setEnd(range.start.row, range.start.col);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\trange.destroy();\n\t\t\t\treturn false;\n\t\t\t});\n\t\t}\n\t\t\n\t\trange = this.activeRange;\n\t\t\n\t\trangeEdge = expand ? range.end : range.start;\n\t\tnextRow = rangeEdge.row;\n\t\tnextCol = rangeEdge.col;\n\t\t\n\t\tif(jump){\n\t\t\tswitch(dir){\n\t\t\t\tcase \"left\":\n\t\t\t\t\tnextCol = this.findJumpCellLeft(range.start.row, rangeEdge.col);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\t\tnextCol = this.findJumpCellRight(range.start.row, rangeEdge.col);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"up\":\n\t\t\t\t\tnextRow = this.findJumpCellUp(rangeEdge.row, range.start.col);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"down\":\n\t\t\t\t\tnextRow = this.findJumpCellDown(rangeEdge.row, range.start.col);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}else {\n\t\t\tif(expand){\n\t\t\t\tif ((this.selecting === 'row' && (dir === 'left' || dir === 'right')) || (this.selecting === 'column' && (dir === 'up' || dir === 'down'))) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tswitch(dir){\n\t\t\t\tcase \"left\":\n\t\t\t\t\tnextCol = Math.max(nextCol - 1, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\t\tnextCol = Math.min(nextCol + 1, this.getTableColumns().length - 1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"up\":\n\t\t\t\t\tnextRow = Math.max(nextRow - 1, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"down\":\n\t\t\t\t\tnextRow = Math.min(nextRow + 1, this.getTableRows().length - 1);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tmoved = nextCol !== rangeEdge.col || nextRow !== rangeEdge.row;\n\t\t\n\t\tif(!expand){\n\t\t\trange.setStart(nextRow, nextCol);\n\t\t}\n\t\t\n\t\trange.setEnd(nextRow, nextCol);\n\t\t\n\t\tif(!expand){\n\t\t\tthis.selecting = \"cell\";\n\t\t}\n\t\t\n\t\tif (moved) {\n\t\t\trow = this.getRowByRangePos(range.end.row);\n\t\t\tcolumn = this.getColumnByRangePos(range.end.col);\n\t\t\t\n\t\t\tif ((dir === 'left' || dir === 'right') && column.getElement().parentNode === null) {\n\t\t\t\tcolumn.getComponent().scrollTo(undefined, false);\n\t\t\t} else if ((dir === 'up' || dir === 'down') && row.getElement().parentNode === null) {\n\t\t\t\trow.getComponent().scrollTo(undefined, false);\n\t\t\t} else {\n\t\t\t\t// Use faster autoScroll when the elements are on the DOM\n\t\t\t\tthis.autoScroll(range, row.getElement(), column.getElement());\n\t\t\t}\n\t\t\t\n\t\t\tthis.layoutElement();\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\trangeRemoved(removed){\n\t\tthis.ranges = this.ranges.filter((range) => range !== removed);\n\t\t\n\t\tif(this.activeRange === removed){\n\t\t\tif(this.ranges.length){\n\t\t\t\tthis.activeRange = this.ranges[this.ranges.length - 1];\n\t\t\t}else {\n\t\t\t\tthis.addRange();\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.layoutElement();\n\t}\n\t\n\tfindJumpCell(cells, reverse, emptyStart, emptySide){\n\t\tvar nextCell;\n\t\t\n\t\tif(reverse){\n\t\t\tcells = cells.reverse();\n\t\t}\n\t\t\n\t\tfor(let currentCell of cells){\n\t\t\tlet currentValue = currentCell.getValue();\n\t\t\t\n\t\t\tif(emptyStart){\n\t\t\t\tnextCell = currentCell;\n\t\t\t\tif(currentValue){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(emptySide){\n\t\t\t\t\tnextCell = currentCell;\n\t\t\t\t\t\n\t\t\t\t\tif(currentValue){\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tif(currentValue){\n\t\t\t\t\t\tnextCell = currentCell;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn nextCell;\n\t}\n\t\n\tfindJumpCellLeft(rowPos, colPos){\n\t\tvar row = this.getRowByRangePos(rowPos),\n\t\tcells = row.cells.filter((cell) => cell.column.visible),\n\t\tisStartingCellEmpty = !cells[colPos].getValue(),\n\t\tisLeftOfStartingCellEmpty = cells[colPos] ? !cells[colPos].getValue() : false,\n\t\tjumpCol = colPos,\n\t\ttargetCells = this.rowHeader ? cells.slice(1, colPos) : cells.slice(0, colPos),\n\t\tnextCell = this.findJumpCell(targetCells, true, isStartingCellEmpty, isLeftOfStartingCellEmpty);\n\t\t\n\t\tif(nextCell){\n\t\t\tjumpCol = nextCell.column.getPosition() - 1;\n\t\t}\n\t\t\n\t\treturn jumpCol;\n\t}\n\t\n\tfindJumpCellRight(rowPos, colPos){\n\t\tvar row = this.getRowByRangePos(rowPos),\n\t\tcells = row.cells.filter((cell) => cell.column.visible),\n\t\tisStartingCellEmpty = !cells[colPos].getValue(),\n\t\tisRightOfStartingCellEmpty = cells[colPos + 1] ? !cells[colPos + 1].getValue() : false,\n\t\tjumpCol = colPos,\n\t\tnextCell = this.findJumpCell(cells.slice(colPos + 1, cells.length), false, isStartingCellEmpty, isRightOfStartingCellEmpty);\n\t\t\n\t\tif(nextCell){\n\t\t\tjumpCol = nextCell.column.getPosition() - 1;\n\t\t}\n\t\t\n\t\treturn jumpCol;\n\t}\n\t\n\tfindJumpCellUp(rowPos, colPos) {\n\t\tvar column = this.getColumnByRangePos(colPos),\n\t\tcells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),\n\t\tisStartingCellEmpty = !cells[rowPos].getValue(),\n\t\tisTopOfStartingCellEmpty = cells[rowPos - 1] ? !cells[rowPos - 1].getValue() : false,\n\t\tjumpRow = rowPos,\n\t\tnextCell = this.findJumpCell(cells.slice(0, jumpRow), true, isStartingCellEmpty, isTopOfStartingCellEmpty);\n\t\t\n\t\tif(nextCell){\n\t\t\tjumpRow = nextCell.row.position - 1;\n\t\t}\n\t\t\n\t\treturn jumpRow;\n\t}\n\t\n\tfindJumpCellDown(rowPos, colPos) {\n\t\tvar column = this.getColumnByRangePos(colPos),\n\t\tcells = column.cells.filter((cell) => this.table.rowManager.activeRows.includes(cell.row)),\n\t\tisStartingCellEmpty = !cells[rowPos].getValue(),\n\t\tisBottomOfStartingCellEmpty = cells[rowPos + 1] ? !cells[rowPos + 1].getValue() : false,\n\t\tjumpRow = rowPos,\n\t\tnextCell = this.findJumpCell(cells.slice(jumpRow + 1, cells.length), false, isStartingCellEmpty, isBottomOfStartingCellEmpty);\n\t\t\n\t\tif(nextCell){\n\t\t\tjumpRow = nextCell.row.position - 1;\n\t\t}\n\t\t\n\t\treturn jumpRow;\n\t}\n\t\n\t///////////////////////////////////\n\t///////      Selection      ///////\n\t///////////////////////////////////\n\tnewSelection(event, element) {\n\t\tvar range;\n\t\t\n\t\tif (element.type === \"column\") {\n\t\t\tif(!this.columnSelection){\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tif (element === this.rowHeader) {\n\t\t\t\trange = this.resetRanges();\n\t\t\t\tthis.selecting = \"all\";\n\t\t\t\t\n\t\t\t\tvar topLeftCell, bottomRightCell = this.getCell(-1, -1);\n\n\t\t\t\tif(this.rowHeader){\n\t\t\t\t\ttopLeftCell = this.getCell(0, 1);\n\t\t\t\t}else {\n\t\t\t\t\ttopLeftCell = this.getCell(0, 0);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\trange.setBounds(topLeftCell, bottomRightCell);\t\t\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthis.selecting = \"column\";\n\t\t\t}\n\t\t} else if (element.column === this.rowHeader) {\n\t\t\tthis.selecting = \"row\";\n\t\t} else {\n\t\t\tthis.selecting = \"cell\";\n\t\t}\n\t\t\n\t\tif (event.shiftKey) {\n\t\t\tthis.activeRange.setBounds(false, element);\n\t\t} else if (event.ctrlKey) {\n\t\t\tthis.addRange().setBounds(element);\n\t\t} else {\n\t\t\tthis.resetRanges().setBounds(element);\n\t\t}\n\t}\n\t\n\tautoScroll(range, row, column) {\n\t\tvar tableHolder = this.table.rowManager.element,\n\t\trowHeader, rect, view, withinHorizontalView, withinVerticalView;\n\n\t\tif (typeof row === 'undefined') {\n\t\t\trow = this.getRowByRangePos(range.end.row).getElement();\n\t\t}\n\t\t\n\t\tif (typeof column === 'undefined') {\n\t\t\tcolumn = this.getColumnByRangePos(range.end.col).getElement();\n\t\t}\n\n\t\tif (this.rowHeader) {\n\t\t\trowHeader = this.rowHeader.getElement();\n\t\t}\n\t\t\n\t\trect = {\n\t\t\tleft: column.offsetLeft,\n\t\t\tright: column.offsetLeft + column.offsetWidth,\n\t\t\ttop: row.offsetTop,\n\t\t\tbottom: row.offsetTop + row.offsetHeight,\n\t\t};\n\t\t\n\t\tview = {\n\t\t\tleft: tableHolder.scrollLeft,\n\t\t\tright: Math.ceil(tableHolder.scrollLeft + tableHolder.clientWidth),\n\t\t\ttop: tableHolder.scrollTop,\n\t\t\tbottom:\ttableHolder.scrollTop +\ttableHolder.offsetHeight - this.table.rowManager.scrollbarWidth,\n\t\t};\n\n\t\tif (rowHeader) {\n\t\t\tview.left += rowHeader.offsetWidth;\n\t\t}\n\t\t\n\t\twithinHorizontalView = view.left < rect.left &&\trect.left < view.right && view.left < rect.right &&\trect.right < view.right;\n\t\t\n\t\twithinVerticalView = view.top < rect.top &&\trect.top < view.bottom && view.top < rect.bottom &&\trect.bottom < view.bottom;\n\t\t\n\t\tif (!withinHorizontalView) {\n\t\t\tif (rect.left < view.left) {\n\t\t\t\ttableHolder.scrollLeft = rect.left;\n\t\t\t\tif (rowHeader) {\n\t\t\t\t\ttableHolder.scrollLeft -= rowHeader.offsetWidth;\n\t\t\t\t}\n\t\t\t} else if (rect.right > view.right) {\n\t\t\t\ttableHolder.scrollLeft = rect.right - tableHolder.clientWidth;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (!withinVerticalView) {\n\t\t\tif (rect.top < view.top) {\n\t\t\t\ttableHolder.scrollTop = rect.top;\n\t\t\t} else if (rect.bottom > view.bottom) {\n\t\t\t\ttableHolder.scrollTop = rect.bottom - tableHolder.clientHeight;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////       Layout        ///////\n\t///////////////////////////////////\n\t\n\tlayoutChange(){\n\t\tthis.overlay.style.visibility = \"hidden\";\n\t\tclearTimeout(this.layoutChangeTimeout);\n\t\tthis.layoutChangeTimeout = setTimeout(this.layoutRanges.bind(this), 200);\n\t}\n\t\n\tredraw(force) {\n\t\tif (force) {\n\t\t\tthis.selecting = 'cell';\n\t\t\tthis.resetRanges();\n\t\t\tthis.layoutElement();\n\t\t}\n\t}\n\t\n\tlayoutElement(visibleRows) {\n\t\tvar rows;\n\t\t\n\t\tif (visibleRows) {\n\t\t\trows = this.table.rowManager.getVisibleRows(true);\n\t\t} else {\n\t\t\trows = this.table.rowManager.getRows();\n\t\t}\n\t\t\n\t\trows.forEach((row) => {\n\t\t\tif (row.type === \"row\") {\n\t\t\t\tthis.layoutRow(row);\n\t\t\t\trow.cells.forEach((cell) => this.renderCell(cell));\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.getTableColumns().forEach((column) => {\n\t\t\tthis.layoutColumn(column);\n\t\t});\n\t\t\n\t\tthis.layoutRanges();\n\t}\n\t\n\tlayoutRow(row) {\n\t\tvar el = row.getElement(),\n\t\tselected = false,\n\t\toccupied = this.ranges.some((range) => range.occupiesRow(row));\n\t\t\n\t\tif (this.selecting === \"row\") {\n\t\t\tselected = occupied;\n\t\t} else if (this.selecting === \"all\") {\n\t\t\tselected = true;\n\t\t}\n\t\t\n\t\tel.classList.toggle(\"tabulator-range-selected\", selected);\n\t\tel.classList.toggle(\"tabulator-range-highlight\", occupied);\n\t}\n\t\n\tlayoutColumn(column) {\n\t\tvar el = column.getElement(),\t\t\n\t\tselected = false,\n\t\toccupied = this.ranges.some((range) => range.occupiesColumn(column));\n\t\t\n\t\tif (this.selecting === \"column\") {\n\t\t\tselected = occupied;\n\t\t} else if (this.selecting === \"all\") {\n\t\t\tselected = true;\n\t\t}\n\t\t\n\t\tel.classList.toggle(\"tabulator-range-selected\", selected);\n\t\tel.classList.toggle(\"tabulator-range-highlight\", occupied);\n\t}\n\t\n\tlayoutRanges() {\n\t\tvar activeCell;\n\t\t\n\t\tif (!this.table.initialized) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tactiveCell = this.getActiveCell();\n\t\t\n\t\tif (!activeCell) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.activeRangeCellElement.style.left = activeCell.row.getElement().offsetLeft + activeCell.getElement().offsetLeft + \"px\";\n\t\tthis.activeRangeCellElement.style.top =\tactiveCell.row.getElement().offsetTop + \"px\";\n\t\tthis.activeRangeCellElement.style.width = activeCell.getElement().offsetLeft + activeCell.getElement().offsetWidth - activeCell.getElement().offsetLeft + \"px\";\n\t\tthis.activeRangeCellElement.style.height = activeCell.row.getElement().offsetTop + activeCell.row.getElement().offsetHeight - activeCell.row.getElement().offsetTop + \"px\";\n\t\t\n\t\tthis.ranges.forEach((range) => range.layout());\n\t\t\n\t\tthis.overlay.style.visibility = \"visible\";\n\t}\n\t\n\t\n\t///////////////////////////////////\n\t///////  Helper Functions   ///////\n\t///////////////////////////////////\t\n\t\n\tgetCell(rowIdx, colIdx) {\n\t\tvar row;\n\t\t\n\t\tif (colIdx < 0) {\n\t\t\tcolIdx = this.getTableColumns().length + colIdx;\n\t\t\tif (colIdx < 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (rowIdx < 0) {\n\t\t\trowIdx = this.getTableRows().length + rowIdx;\n\t\t}\n\t\t\n\t\trow = this.table.rowManager.getRowFromPosition(rowIdx + 1);\n\t\t\n\t\treturn row ? row.getCells(false, true).filter((cell) => cell.column.visible)[colIdx] : null;\n\t}\n\t\n\t\n\tgetActiveCell() {\n\t\treturn this.getCell(this.activeRange.start.row, this.activeRange.start.col);\n\t}\n\t\n\tgetRowByRangePos(pos) {\n\t\treturn this.getTableRows()[pos];\n\t}\n\t\n\tgetColumnByRangePos(pos) {\n\t\treturn this.getTableColumns()[pos];\n\t}\n\t\n\tgetTableRows() {\n\t\treturn this.table.rowManager.getDisplayRows();\n\t}\n\t\n\tgetTableColumns() {\n\t\treturn this.table.columnManager.getVisibleColumnsByIndex();\n\t}\n\t\n\taddRange(start, end) {\n\t\tvar  range;\n\t\t\n\t\tif(this.maxRanges !== true && this.ranges.length >= this.maxRanges){\n\t\t\tthis.ranges.shift().destroy();\n\t\t}\n\t\t\n\t\trange = new Range(this.table, this, start, end);\n\t\t\n\t\tthis.activeRange = range;\n\t\tthis.ranges.push(range);\n\t\tthis.rangeContainer.appendChild(range.element);\n\t\t\n\t\treturn range;\n\t}\n\t\n\tresetRanges() {\n\t\tvar range, cell;\n\t\t\n\t\tthis.ranges.forEach((range) => range.destroy());\n\t\tthis.ranges = [];\n\t\t\n\t\trange = this.addRange();\n\t\t\n\t\tif(this.table.rowManager.activeRows.length){\n\t\t\tcell = this.table.rowManager.activeRows[0].cells[this.rowHeader ? 1 : 0];\n\n\t\t\tif(cell){\n\t\t\t\trange.setBounds(cell);\n\t\t\t\tthis.initializeFocus(cell);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn range;\n\t}\n\t\n\ttableDestroyed(){\n\t\tdocument.removeEventListener(\"mouseup\", this.mouseUpEvent);\n\t\tthis.table.rowManager.element.removeEventListener(\"keydown\", this.keyDownEvent);\n\t}\n\t\n\tselectedRows(component) {\n\t\treturn component ? this.activeRange.getRows().map((row) => row.getComponent()) : this.activeRange.getRows();\n\t}\n\t\n\tselectedColumns(component) {\n\t\treturn component ? this.activeRange.getColumns().map((col) => col.getComponent()) : this.activeRange.getColumns();\n\t}\n}\n\nSelectRange.moduleName = \"selectRange\";\n\nclass Tooltip extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.tooltipSubscriber = null,\n\t\tthis.headerSubscriber = null,\n\t\t\n\t\tthis.timeout = null;\n\t\tthis.popupInstance = null;\n\t\t\n\t\tthis.registerTableOption(\"tooltipGenerationMode\", undefined);  //deprecated\n\t\tthis.registerTableOption(\"tooltipDelay\", 300); \n\t\t\n\t\tthis.registerColumnOption(\"tooltip\");\n\t\tthis.registerColumnOption(\"headerTooltip\");\n\t}\n\t\n\tinitialize(){\n\t\tthis.deprecatedOptionsCheck();\n\t\t\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t}\n\t\n\tdeprecatedOptionsCheck(){\n\t\tthis.deprecationCheckMsg(\"tooltipGenerationMode\", \"This option is no longer needed as tooltips are always generated on hover now\");\n\t}\t\n\t\n\tinitializeColumn(column){\n\t\tif(column.definition.headerTooltip && !this.headerSubscriber){\n\t\t\tthis.headerSubscriber = true;\n\t\t\t\n\t\t\tthis.subscribe(\"column-mousemove\", this.mousemoveCheck.bind(this, \"headerTooltip\"));\n\t\t\tthis.subscribe(\"column-mouseout\", this.mouseoutCheck.bind(this, \"headerTooltip\"));\n\t\t}\n\t\t\n\t\tif(column.definition.tooltip && !this.tooltipSubscriber){\n\t\t\tthis.tooltipSubscriber = true;\n\t\t\t\n\t\t\tthis.subscribe(\"cell-mousemove\", this.mousemoveCheck.bind(this, \"tooltip\"));\n\t\t\tthis.subscribe(\"cell-mouseout\", this.mouseoutCheck.bind(this, \"tooltip\"));\n\t\t}\n\t}\n\t\n\tmousemoveCheck(action, e, component){\n\t\tvar tooltip = action === \"tooltip\" ? component.column.definition.tooltip : component.definition.headerTooltip;\n\t\t\n\t\tif(tooltip){\n\t\t\tthis.clearPopup();\n\t\t\tthis.timeout = setTimeout(this.loadTooltip.bind(this, e, component, tooltip), this.table.options.tooltipDelay);\n\t\t}\n\t}\n\n\tmouseoutCheck(action, e, component){\n\t\tif(!this.popupInstance){\n\t\t\tthis.clearPopup();\n\t\t}\n\t}\n\t\n\tclearPopup(action, e, component){\n\t\tclearTimeout(this.timeout);\n\t\tthis.timeout = null;\n\t\t\n\t\tif(this.popupInstance){\n\t\t\tthis.popupInstance.hide();\n\t\t}\n\t}\n\t\n\tloadTooltip(e, component, tooltip){\n\t\tvar contentsEl, renderedCallback, coords;\n\n\t\tfunction onRendered(callback){\n\t\t\trenderedCallback = callback;\n\t\t}\n\t\t\n\t\tif(typeof tooltip === \"function\"){\n\t\t\ttooltip = tooltip(e, component.getComponent(), onRendered);\n\t\t}\n\t\t\n\t\tif(tooltip instanceof HTMLElement){\n\t\t\tcontentsEl = tooltip;\n\t\t}else {\n\t\t\tcontentsEl = document.createElement(\"div\");\n\t\t\t\n\t\t\tif(tooltip === true){\n\t\t\t\tif(component instanceof Cell){\n\t\t\t\t\ttooltip = component.value;\n\t\t\t\t}else {\n\t\t\t\t\tif(component.definition.field){\n\t\t\t\t\t\tthis.langBind(\"columns|\" + component.definition.field, (value) => {\n\t\t\t\t\t\t\tcontentsEl.innerHTML = tooltip = value || component.definition.title;\n\t\t\t\t\t\t});\n\t\t\t\t\t}else {\n\t\t\t\t\t\ttooltip = component.definition.title;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tcontentsEl.innerHTML = tooltip;\n\t\t}\n\t\t\n\t\tif(tooltip || tooltip === 0 || tooltip === false){\n\t\t\tcontentsEl.classList.add(\"tabulator-tooltip\");\n\n\t\t\tcontentsEl.addEventListener(\"mousemove\", e => e.preventDefault());\n\t\t\t\n\t\t\tthis.popupInstance = this.popup(contentsEl);\n\t\t\t\n\t\t\tif(typeof renderedCallback === \"function\"){\n\t\t\t\tthis.popupInstance.renderCallback(renderedCallback);\n\t\t\t}\n\n\t\t\tcoords = this.popupInstance.containerEventCoords(e);\n\t\t\t\n\t\t\tthis.popupInstance.show(coords.x + 15, coords.y + 15).hideOnBlur(() => {\n\t\t\t\tthis.dispatchExternal(\"TooltipClosed\", component.getComponent());\n\t\t\t\tthis.popupInstance = null;\n\t\t\t});\n\t\t\t\n\t\t\tthis.dispatchExternal(\"TooltipOpened\", component.getComponent());\n\t\t}\n\t}\n}\n\nTooltip.moduleName = \"tooltip\";\n\nvar defaultValidators = {\n\t//is integer\n\tinteger: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\n\t\tvalue = Number(value);\n\n\t\treturn !isNaN(value) && isFinite(value) && Math.floor(value) === value;\n\t},\n\n\t//is float\n\tfloat: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tvalue = Number(value);\n\n\t\treturn !isNaN(value) && isFinite(value) && value % 1 !== 0;\n\t},\n\n\t//must be a number\n\tnumeric: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn !isNaN(value);\n\t},\n\n\t//must be a string\n\tstring: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn isNaN(value);\n\t},\n\n\t//must be alphanumeric\n\talphanumeric: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\n\t\tvar reg = new RegExp(/^[a-z0-9]+$/i);\n\n\t\treturn reg.test(value);\n\t},\n\n\t//maximum value\n\tmax: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn parseFloat(value) <= parameters;\n\t},\n\n\t//minimum value\n\tmin: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn parseFloat(value) >= parameters;\n\t},\n\n\t//starts with  value\n\tstarts: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn String(value).toLowerCase().startsWith(String(parameters).toLowerCase());\n\t},\n\n\t//ends with  value\n\tends: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn String(value).toLowerCase().endsWith(String(parameters).toLowerCase());\n\t},\n\n\n\t//minimum string length\n\tminLength: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn String(value).length >= parameters;\n\t},\n\n\t//maximum string length\n\tmaxLength: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\treturn String(value).length <= parameters;\n\t},\n\n\t//in provided value list\n\tin: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\n\t\tif(typeof parameters == \"string\"){\n\t\t\tparameters = parameters.split(\"|\");\n\t\t}\n\n\t\treturn parameters.indexOf(value) > -1;\n\t},\n\n\t//must match provided regex\n\tregex: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\tvar reg = new RegExp(parameters);\n\n\t\treturn reg.test(value);\n\t},\n\n\t//value must be unique in this column\n\tunique: function(cell, value, parameters){\n\t\tif(value === \"\" || value === null || typeof value === \"undefined\"){\n\t\t\treturn true;\n\t\t}\n\t\tvar unique = true;\n\n\t\tvar cellData = cell.getData();\n\t\tvar column = cell.getColumn()._getSelf();\n\n\t\tthis.table.rowManager.rows.forEach(function(row){\n\t\t\tvar data = row.getData();\n\n\t\t\tif(data !== cellData){\n\t\t\t\tif(value == column.getFieldValue(data)){\n\t\t\t\t\tunique = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn unique;\n\t},\n\n\t//must have a value\n\trequired:function(cell, value, parameters){\n\t\treturn value !== \"\" && value !== null && typeof value !== \"undefined\";\n\t},\n};\n\nclass Validate extends Module{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.invalidCells = [];\n\t\t\n\t\tthis.registerTableOption(\"validationMode\", \"blocking\");\n\t\t\n\t\tthis.registerColumnOption(\"validator\");\n\t\t\n\t\tthis.registerTableFunction(\"getInvalidCells\", this.getInvalidCells.bind(this));\n\t\tthis.registerTableFunction(\"clearCellValidation\", this.userClearCellValidation.bind(this));\n\t\tthis.registerTableFunction(\"validate\", this.userValidate.bind(this));\n\t\t\n\t\tthis.registerComponentFunction(\"cell\", \"isValid\", this.cellIsValid.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"clearValidation\", this.clearValidation.bind(this));\n\t\tthis.registerComponentFunction(\"cell\", \"validate\", this.cellValidate.bind(this));\n\t\t\n\t\tthis.registerComponentFunction(\"column\", \"validate\", this.columnValidate.bind(this));\n\t\tthis.registerComponentFunction(\"row\", \"validate\", this.rowValidate.bind(this));\n\t}\n\t\n\t\n\tinitialize(){\n\t\tthis.subscribe(\"cell-delete\", this.clearValidation.bind(this));\n\t\tthis.subscribe(\"column-layout\", this.initializeColumnCheck.bind(this));\n\t\t\n\t\tthis.subscribe(\"edit-success\", this.editValidate.bind(this));\n\t\tthis.subscribe(\"edit-editor-clear\", this.editorClear.bind(this));\n\t\tthis.subscribe(\"edit-edited-clear\", this.editedClear.bind(this));\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Event Handling //////////\n\t///////////////////////////////////\n\t\n\teditValidate(cell, value, previousValue){\n\t\tvar valid = this.table.options.validationMode !== \"manual\" ? this.validate(cell.column.modules.validate, cell, value) : true;\n\t\t\n\t\t// allow time for editor to make render changes then style cell\n\t\tif(valid !== true){\n\t\t\tsetTimeout(() => {\n\t\t\t\tcell.getElement().classList.add(\"tabulator-validation-fail\");\n\t\t\t\tthis.dispatchExternal(\"validationFailed\", cell.getComponent(), value, valid);\n\t\t\t});\n\t\t}\n\t\t\n\t\treturn valid;\n\t}\n\t\n\teditorClear(cell, cancelled){\n\t\tif(cancelled){\n\t\t\tif(cell.column.modules.validate){\n\t\t\t\tthis.cellValidate(cell);\n\t\t\t}\n\t\t}\n\n\t\tcell.getElement().classList.remove(\"tabulator-validation-fail\");\n\t}\n\t\n\teditedClear(cell){\n\t\tif(cell.modules.validate){\n\t\t\tcell.modules.validate.invalid = false;\n\t\t}\n\t}\n\t\n\t///////////////////////////////////\n\t////////// Cell Functions /////////\n\t///////////////////////////////////\n\t\n\tcellIsValid(cell){\n\t\treturn cell.modules.validate ? (cell.modules.validate.invalid || true) : true;\n\t}\n\t\n\tcellValidate(cell){\n\t\treturn this.validate(cell.column.modules.validate, cell, cell.getValue());\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Column Functions ////////\n\t///////////////////////////////////\n\t\n\tcolumnValidate(column){\n\t\tvar invalid = [];\n\t\t\n\t\tcolumn.cells.forEach((cell) => {\n\t\t\tif(this.cellValidate(cell) !== true){\n\t\t\t\tinvalid.push(cell.getComponent());\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn invalid.length ? invalid : true;\n\t}\n\t\n\t///////////////////////////////////\n\t////////// Row Functions //////////\n\t///////////////////////////////////\n\t\n\trowValidate(row){\n\t\tvar invalid = [];\n\t\t\n\t\trow.cells.forEach((cell) => {\n\t\t\tif(this.cellValidate(cell) !== true){\n\t\t\t\tinvalid.push(cell.getComponent());\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn invalid.length ? invalid : true;\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Table Functions /////////\n\t///////////////////////////////////\n\t\n\t\n\tuserClearCellValidation(cells){\n\t\tif(!cells){\n\t\t\tcells = this.getInvalidCells();\n\t\t}\n\t\t\n\t\tif(!Array.isArray(cells)){\n\t\t\tcells = [cells];\n\t\t}\n\t\t\n\t\tcells.forEach((cell) => {\n\t\t\tthis.clearValidation(cell._getSelf());\n\t\t});\n\t}\n\t\n\tuserValidate(cells){\n\t\tvar output = [];\n\t\t\n\t\t//clear row data\n\t\tthis.table.rowManager.rows.forEach((row) => {\n\t\t\trow = row.getComponent();\n\t\t\t\n\t\t\tvar valid = row.validate();\n\t\t\t\n\t\t\tif(valid !== true){\n\t\t\t\toutput = output.concat(valid);\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn output.length ? output : true;\n\t}\n\t\n\t///////////////////////////////////\n\t///////// Internal Logic //////////\n\t///////////////////////////////////\n\t\n\tinitializeColumnCheck(column){\n\t\tif(typeof column.definition.validator !== \"undefined\"){\n\t\t\tthis.initializeColumn(column);\n\t\t}\n\t}\n\t\n\t//validate\n\tinitializeColumn(column){\n\t\tvar self = this,\n\t\tconfig = [],\n\t\tvalidator;\n\t\t\n\t\tif(column.definition.validator){\n\t\t\t\n\t\t\tif(Array.isArray(column.definition.validator)){\n\t\t\t\tcolumn.definition.validator.forEach((item) => {\n\t\t\t\t\tvalidator = self._extractValidator(item);\n\t\t\t\t\t\n\t\t\t\t\tif(validator){\n\t\t\t\t\t\tconfig.push(validator);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\tvalidator = this._extractValidator(column.definition.validator);\n\t\t\t\t\n\t\t\t\tif(validator){\n\t\t\t\t\tconfig.push(validator);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tcolumn.modules.validate = config.length ? config : false;\n\t\t}\n\t}\n\t\n\t_extractValidator(value){\n\t\tvar type, params, pos;\n\t\t\n\t\tswitch(typeof value){\n\t\t\tcase \"string\":\n\t\t\t\tpos = value.indexOf(':');\n\t\t\t\n\t\t\t\tif(pos > -1){\n\t\t\t\t\ttype = value.substring(0,pos);\n\t\t\t\t\tparams = value.substring(pos+1);\n\t\t\t\t}else {\n\t\t\t\t\ttype = value;\n\t\t\t\t}\n\t\t\t\n\t\t\t\treturn this._buildValidator(type, params);\n\t\t\t\n\t\t\tcase \"function\":\n\t\t\t\treturn this._buildValidator(value);\n\t\t\t\n\t\t\tcase \"object\":\n\t\t\t\treturn this._buildValidator(value.type, value.parameters);\n\t\t}\n\t}\n\t\n\t_buildValidator(type, params){\n\t\t\n\t\tvar func = typeof type == \"function\" ? type : Validate.validators[type];\n\t\t\n\t\tif(!func){\n\t\t\tconsole.warn(\"Validator Setup Error - No matching validator found:\", type);\n\t\t\treturn false;\n\t\t}else {\n\t\t\treturn {\n\t\t\t\ttype:typeof type == \"function\" ? \"function\" : type,\n\t\t\t\tfunc:func,\n\t\t\t\tparams:params,\n\t\t\t};\n\t\t}\n\t}\n\t\n\tvalidate(validators, cell, value){\n\t\tvar self = this,\n\t\tfailedValidators = [],\n\t\tinvalidIndex = this.invalidCells.indexOf(cell);\n\t\t\n\t\tif(validators){\n\t\t\tvalidators.forEach((item) => {\n\t\t\t\tif(!item.func.call(self, cell.getComponent(), value, item.params)){\n\t\t\t\t\tfailedValidators.push({\n\t\t\t\t\t\ttype:item.type,\n\t\t\t\t\t\tparameters:item.params\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tif(!cell.modules.validate){\n\t\t\tcell.modules.validate = {};\n\t\t}\n\t\t\n\t\tif(!failedValidators.length){\n\t\t\tcell.modules.validate.invalid = false;\n\t\t\tcell.getElement().classList.remove(\"tabulator-validation-fail\");\n\t\t\t\n\t\t\tif(invalidIndex > -1){\n\t\t\t\tthis.invalidCells.splice(invalidIndex, 1);\n\t\t\t}\n\t\t}else {\n\t\t\tcell.modules.validate.invalid = failedValidators;\n\t\t\t\n\t\t\tif(this.table.options.validationMode !== \"manual\"){\n\t\t\t\tcell.getElement().classList.add(\"tabulator-validation-fail\");\n\t\t\t}\n\t\t\t\n\t\t\tif(invalidIndex == -1){\n\t\t\t\tthis.invalidCells.push(cell);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn failedValidators.length ? failedValidators : true;\n\t}\n\t\n\tgetInvalidCells(){\n\t\tvar output = [];\n\t\t\n\t\tthis.invalidCells.forEach((cell) => {\n\t\t\toutput.push(cell.getComponent());\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tclearValidation(cell){\n\t\tvar invalidIndex;\n\t\t\n\t\tif(cell.modules.validate && cell.modules.validate.invalid){\n\t\t\t\n\t\t\tcell.getElement().classList.remove(\"tabulator-validation-fail\");\n\t\t\tcell.modules.validate.invalid = false;\n\t\t\t\n\t\t\tinvalidIndex = this.invalidCells.indexOf(cell);\n\t\t\t\n\t\t\tif(invalidIndex > -1){\n\t\t\t\tthis.invalidCells.splice(invalidIndex, 1);\n\t\t\t}\n\t\t}\n\t}\n}\n\nValidate.moduleName = \"validate\";\n\n//load defaults\nValidate.validators = defaultValidators;\n\nvar modules = /*#__PURE__*/Object.freeze({\n\t__proto__: null,\n\tAccessorModule: Accessor,\n\tAjaxModule: Ajax,\n\tClipboardModule: Clipboard,\n\tColumnCalcsModule: ColumnCalcs,\n\tDataTreeModule: DataTree,\n\tDownloadModule: Download,\n\tEditModule: Edit$1,\n\tExportModule: Export,\n\tFilterModule: Filter,\n\tFormatModule: Format,\n\tFrozenColumnsModule: FrozenColumns,\n\tFrozenRowsModule: FrozenRows,\n\tGroupRowsModule: GroupRows,\n\tHistoryModule: History,\n\tHtmlTableImportModule: HtmlTableImport,\n\tImportModule: Import,\n\tInteractionModule: Interaction,\n\tKeybindingsModule: Keybindings,\n\tMenuModule: Menu,\n\tMoveColumnsModule: MoveColumns,\n\tMoveRowsModule: MoveRows,\n\tMutatorModule: Mutator,\n\tPageModule: Page,\n\tPersistenceModule: Persistence,\n\tPopupModule: Popup$1,\n\tPrintModule: Print,\n\tReactiveDataModule: ReactiveData,\n\tResizeColumnsModule: ResizeColumns,\n\tResizeRowsModule: ResizeRows,\n\tResizeTableModule: ResizeTable,\n\tResponsiveLayoutModule: ResponsiveLayout,\n\tSelectRowModule: SelectRow,\n\tSortModule: Sort,\n\tSelectRangeModule: SelectRange,\n\tTooltipModule: Tooltip,\n\tValidateModule: Validate\n});\n\nvar defaultOptions = {\n\n\tdebugEventsExternal:false, //flag to console log events\n\tdebugEventsInternal:false, //flag to console log events\n\tdebugInvalidOptions:true, //allow toggling of invalid option warnings\n\tdebugInvalidComponentFuncs:true, //allow toggling of invalid component warnings\n\tdebugInitialization:true, //allow toggling of pre initialization function call warnings\n\tdebugDeprecation:true, //allow toggling of deprecation warnings\n\n\theight:false, //height of tabulator\n\tminHeight:false, //minimum height of tabulator\n\tmaxHeight:false, //maximum height of tabulator\n\n\tcolumnHeaderVertAlign:\"top\", //vertical alignment of column headers\n\n\tpopupContainer:false,\n\n\tcolumns:[],//store for colum header info\n\tcolumnDefaults:{}, //store column default props\n\n\tdata:false, //default starting data\n\n\tautoColumns:false, //build columns from data row structure\n\tautoColumnsDefinitions:false,\n\n\tnestedFieldSeparator:\".\", //separator for nested data\n\n\tfooterElement:false, //hold footer element\n\n\tindex:\"id\", //filed for row index\n\n\ttextDirection:\"auto\",\n\n\taddRowPos:\"bottom\", //position to insert blank rows, top|bottom\n\n\theaderVisible:true, //hide header\n\n\trenderVertical:\"virtual\",\n\trenderHorizontal:\"basic\",\n\trenderVerticalBuffer:0, // set virtual DOM buffer size\n\n\tscrollToRowPosition:\"top\",\n\tscrollToRowIfVisible:true,\n\n\tscrollToColumnPosition:\"left\",\n\tscrollToColumnIfVisible:true,\n\n\trowFormatter:false,\n\trowFormatterPrint:null,\n\trowFormatterClipboard:null,\n\trowFormatterHtmlOutput:null,\n\n\trowHeight:null,\n\n\tplaceholder:false,\n\n\tdataLoader:true,\n\tdataLoaderLoading:false,\n\tdataLoaderError:false,\n\tdataLoaderErrorTimeout:3000,\n\n\tdataSendParams:{},\n\n\tdataReceiveParams:{},\n};\n\nclass OptionsList {\n\tconstructor(table, msgType, defaults = {}){\n\t\tthis.table = table;\n\t\tthis.msgType = msgType;\n\t\tthis.registeredDefaults = Object.assign({}, defaults);\n\t}\n\t\n\tregister(option, value){\n\t\tthis.registeredDefaults[option] = value;\n\t}\n\t\n\tgenerate(defaultOptions, userOptions = {}){\n\t\tvar output = Object.assign({}, this.registeredDefaults),\n\t\twarn = this.table.options.debugInvalidOptions || userOptions.debugInvalidOptions === true;\n\t\t\n\t\tObject.assign(output, defaultOptions);\n\t\t\n\t\tfor (let key in userOptions){\n\t\t\tif(!output.hasOwnProperty(key)){\n\t\t\t\tif(warn){\n\t\t\t\t\tconsole.warn(\"Invalid \" + this.msgType + \" option:\", key);\n\t\t\t\t}\n\n\t\t\t\toutput[key] = userOptions.key;\n\t\t\t}\n\t\t}\n\t\n\t\t\n\t\tfor (let key in output){\n\t\t\tif(key in userOptions){\n\t\t\t\toutput[key] = userOptions[key];\n\t\t\t}else {\n\t\t\t\tif(Array.isArray(output[key])){\n\t\t\t\t\toutput[key] = Object.assign([], output[key]);\n\t\t\t\t}else if(typeof output[key] === \"object\" && output[key] !== null){\n\t\t\t\t\toutput[key] = Object.assign({}, output[key]);\n\t\t\t\t}else if (typeof output[key] === \"undefined\"){\n\t\t\t\t\tdelete output[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n}\n\nclass Renderer extends CoreFeature{\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.elementVertical = table.rowManager.element;\n\t\tthis.elementHorizontal = table.columnManager.element;\n\t\tthis.tableElement =  table.rowManager.tableElement;\n\n\t\tthis.verticalFillMode = \"fit\"; // used by row manager to determine how to size the render area (\"fit\" - fits container to the contents, \"fill\" - fills the container without resizing it)\n\t}\n\n\n\t///////////////////////////////////\n\t/////// Internal Bindings /////////\n\t///////////////////////////////////\n\n\tinitialize(){\n\t\t//initialize core functionality\n\t}\n\n\tclearRows(){\n\t\t//clear down existing rows layout\n\t}\n\n\tclearColumns(){\n\t\t//clear down existing columns layout\n\t}\n\n\n\treinitializeColumnWidths(columns){\n\t\t//resize columns to fit data\n\t}\n\n\n\trenderRows(){\n\t\t//render rows from a clean slate\n\t}\n\n\trenderColumns(){\n\t\t//render columns from a clean slate\n\t}\n\n\trerenderRows(callback){\n\t\t// rerender rows and keep position\n\t\tif(callback){\n\t\t\tcallback();\n\t\t}\n\t}\n\n\trerenderColumns(update, blockRedraw){\n\t\t//rerender columns\n\t}\n\n\trenderRowCells(row){\n\t\t//render the cells in a row\n\t}\n\n\trerenderRowCells(row, force){\n\t\t//rerender the cells in a row\n\t}\n\n\tscrollColumns(left, dir){\n\t\t//handle horizontal scrolling\n\t}\n\n\tscrollRows(top, dir){\n\t\t//handle vertical scrolling\n\t}\n\n\tresize(){\n\t\t//container has resized, carry out any needed recalculations (DO NOT RERENDER IN THIS FUNCTION)\n\t}\n\n\tscrollToRow(row){\n\t\t//scroll to a specific row\n\t}\n\n\tscrollToRowNearestTop(row){\n\t\t//determine weather the row is nearest the top or bottom of the table, return true for top or false for bottom\n\t}\n\n\tvisibleRows(includingBuffer){\n\t\t//return the visible rows\n\t\treturn [];\n\t}\n\n\t///////////////////////////////////\n\t//////// Helper Functions /////////\n\t///////////////////////////////////\n\n\trows(){\n\t\treturn this.table.rowManager.getDisplayRows();\n\t}\n\n\tstyleRow(row, index){\n\t\tvar rowEl = row.getElement();\n\n\t\tif(index % 2){\n\t\t\trowEl.classList.add(\"tabulator-row-even\");\n\t\t\trowEl.classList.remove(\"tabulator-row-odd\");\n\t\t}else {\n\t\t\trowEl.classList.add(\"tabulator-row-odd\");\n\t\t\trowEl.classList.remove(\"tabulator-row-even\");\n\t\t}\n\t}\n\n\t///////////////////////////////////\n\t/////// External Triggers /////////\n\t/////// (DO NOT OVERRIDE) /////////\n\t///////////////////////////////////\n\n\tclear(){\n\t\t//clear down existing layout\n\t\tthis.clearRows();\n\t\tthis.clearColumns();\n\t}\n\n\trender(){\n\t\t//render from a clean slate\n\t\tthis.renderRows();\n\t\tthis.renderColumns();\n\t}\n\n\trerender(callback){\n\t\t// rerender and keep position\n\t\tthis.rerenderRows();\n\t\tthis.rerenderColumns();\n\t}\n\n\tscrollToRowPosition(row, position, ifVisible){\n\t\tvar rowIndex = this.rows().indexOf(row),\n\t\trowEl = row.getElement(),\n\t\toffset = 0;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif(rowIndex > -1){\n\n\t\t\t\tif(typeof ifVisible === \"undefined\"){\n\t\t\t\t\tifVisible = this.table.options.scrollToRowIfVisible;\n\t\t\t\t}\n\n\t\t\t\t//check row visibility\n\t\t\t\tif(!ifVisible){\n\t\t\t\t\tif(Helpers.elVisible(rowEl)){\n\t\t\t\t\t\toffset = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(offset > 0 && offset < this.elementVertical.clientHeight - rowEl.offsetHeight){\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(typeof position === \"undefined\"){\n\t\t\t\t\tposition = this.table.options.scrollToRowPosition;\n\t\t\t\t}\n\n\t\t\t\tif(position === \"nearest\"){\n\t\t\t\t\tposition = this.scrollToRowNearestTop(row) ? \"top\" : \"bottom\";\n\t\t\t\t}\n\n\t\t\t\t//scroll to row\n\t\t\t\tthis.scrollToRow(row);\n\n\t\t\t\t//align to correct position\n\t\t\t\tswitch(position){\n\t\t\t\t\tcase \"middle\":\n\t\t\t\t\tcase \"center\":\n\n\t\t\t\t\t\tif(this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight){\n\t\t\t\t\t\t\tthis.elementVertical.scrollTop = this.elementVertical.scrollTop + (rowEl.offsetTop - this.elementVertical.scrollTop) - ((this.elementVertical.scrollHeight - rowEl.offsetTop) / 2);\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tthis.elementVertical.scrollTop = this.elementVertical.scrollTop - (this.elementVertical.clientHeight / 2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"bottom\":\n\n\t\t\t\t\t\tif(this.elementVertical.scrollHeight - this.elementVertical.scrollTop == this.elementVertical.clientHeight){\n\t\t\t\t\t\t\tthis.elementVertical.scrollTop = this.elementVertical.scrollTop - (this.elementVertical.scrollHeight - rowEl.offsetTop) + rowEl.offsetHeight;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tthis.elementVertical.scrollTop = this.elementVertical.scrollTop - this.elementVertical.clientHeight + rowEl.offsetHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"top\":\n\t\t\t\t\t\tthis.elementVertical.scrollTop = rowEl.offsetTop;\t\t\t\t\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Scroll Error - Row not visible\");\n\t\t\t\treject(\"Scroll Error - Row not visible\");\n\t\t\t}\n\t\t});\n\t}\n}\n\nclass BasicHorizontal extends Renderer{\n\tconstructor(table){\n\t\tsuper(table);\n\t}\n\t\n\trenderRowCells(row, inFragment) {\n\t\tconst rowFrag = document.createDocumentFragment();\n\t\trow.cells.forEach((cell) => {\n\t\t\trowFrag.appendChild(cell.getElement());\n\t\t});\n\t\trow.element.appendChild(rowFrag);\n\t\t\n\t\tif(!inFragment){\n\t\t\trow.cells.forEach((cell) => {\n\t\t\t\tcell.cellRendered();\n\t\t\t});\n\t\t}\n\t}\n\t\n\treinitializeColumnWidths(columns){\n\t\tcolumns.forEach(function(column){\n\t\t\tcolumn.reinitializeWidth();\n\t\t});\n\t}\n}\n\nclass VirtualDomHorizontal extends Renderer{\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.leftCol = 0;\n\t\tthis.rightCol = 0;\n\t\tthis.scrollLeft = 0;\n\t\t\n\t\tthis.vDomScrollPosLeft = 0;\n\t\tthis.vDomScrollPosRight = 0;\n\t\t\n\t\tthis.vDomPadLeft = 0;\n\t\tthis.vDomPadRight = 0;\n\t\t\n\t\tthis.fitDataColAvg = 0;\n\t\t\n\t\tthis.windowBuffer = 200; //pixel margin to make column visible before it is shown on screen\n\t\t\n\t\tthis.visibleRows = null;\n\t\t\n\t\tthis.initialized = false;\n\t\tthis.isFitData = false;\n\t\t\n\t\tthis.columns = [];\n\t}\n\t\n\tinitialize(){\n\t\tthis.compatibilityCheck();\n\t\tthis.layoutCheck();\n\t\tthis.vertScrollListen();\n\t}\n\t\n\tcompatibilityCheck(){\t\t\n\t\tif(this.options(\"layout\") == \"fitDataTable\"){\n\t\t\tconsole.warn(\"Horizontal Virtual DOM is not compatible with fitDataTable layout mode\");\n\t\t}\n\t\t\n\t\tif(this.options(\"responsiveLayout\")){\n\t\t\tconsole.warn(\"Horizontal Virtual DOM is not compatible with responsive columns\");\n\t\t}\n\t\t\n\t\tif(this.options(\"rtl\")){\n\t\t\tconsole.warn(\"Horizontal Virtual DOM is not currently compatible with RTL text direction\");\n\t\t}\n\t}\n\t\n\tlayoutCheck(){\n\t\tthis.isFitData = this.options(\"layout\").startsWith('fitData');\n\t}\n\t\n\tvertScrollListen(){\n\t\tthis.subscribe(\"scroll-vertical\", this.clearVisRowCache.bind(this));\n\t\tthis.subscribe(\"data-refreshed\", this.clearVisRowCache.bind(this));\n\t}\n\t\n\tclearVisRowCache(){\n\t\tthis.visibleRows = null;\n\t}\n\t\n\t//////////////////////////////////////\n\t///////// Public Functions ///////////\n\t//////////////////////////////////////\n\t\n\trenderColumns(row, force){\n\t\tthis.dataChange();\n\t}\n\t\n\t\n\tscrollColumns(left, dir){\n\t\tif(this.scrollLeft != left){\n\t\t\tthis.scrollLeft = left;\n\t\t\t\n\t\t\tthis.scroll(left - (this.vDomScrollPosLeft + this.windowBuffer));\n\t\t}\n\t}\n\t\n\tcalcWindowBuffer(){\n\t\tvar buffer = this.elementVertical.clientWidth;\n\t\t\n\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\tif(column.visible){\n\t\t\t\tvar width = column.getWidth();\n\t\t\t\t\n\t\t\t\tif(width > buffer){\n\t\t\t\t\tbuffer = width;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.windowBuffer = buffer * 2;\n\t}\n\t\n\trerenderColumns(update, blockRedraw){\t\t\n\t\tvar old = {\n\t\t\tcols:this.columns,\n\t\t\tleftCol:this.leftCol,\n\t\t\trightCol:this.rightCol,\n\t\t},\n\t\tcolPos = 0;\n\t\t\n\t\tif(update && !this.initialized){\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.clear();\n\t\t\n\t\tthis.calcWindowBuffer();\n\t\t\n\t\tthis.scrollLeft = this.elementVertical.scrollLeft;\n\t\t\n\t\tthis.vDomScrollPosLeft = this.scrollLeft - this.windowBuffer;\n\t\tthis.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;\n\t\t\n\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\tvar config = {},\n\t\t\twidth;\n\t\t\t\n\t\t\tif(column.visible){\n\t\t\t\tif(!column.modules.frozen){\t\t\t\n\t\t\t\t\twidth = column.getWidth();\n\n\t\t\t\t\tconfig.leftPos = colPos;\n\t\t\t\t\tconfig.rightPos = colPos + width;\n\t\t\t\t\t\n\t\t\t\t\tconfig.width = width;\n\t\t\t\t\t\n\t\t\t\t\tif (this.isFitData) {\n\t\t\t\t\t\tconfig.fitDataCheck = column.modules.vdomHoz ? column.modules.vdomHoz.fitDataCheck : true;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif((colPos + width > this.vDomScrollPosLeft) && (colPos < this.vDomScrollPosRight)){\n\t\t\t\t\t\t//column is visible\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(this.leftCol == -1){\n\t\t\t\t\t\t\tthis.leftCol = this.columns.length;\n\t\t\t\t\t\t\tthis.vDomPadLeft = colPos;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.rightCol = this.columns.length;\n\t\t\t\t\t}else {\n\t\t\t\t\t\t// column is hidden\n\t\t\t\t\t\tif(this.leftCol !== -1){\n\t\t\t\t\t\t\tthis.vDomPadRight += width;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthis.columns.push(column);\n\t\t\t\t\t\n\t\t\t\t\tcolumn.modules.vdomHoz = config;\n\t\t\t\t\t\n\t\t\t\t\tcolPos += width;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tthis.tableElement.style.paddingLeft = this.vDomPadLeft + \"px\";\n\t\tthis.tableElement.style.paddingRight = this.vDomPadRight + \"px\";\n\t\t\n\t\tthis.initialized = true;\n\t\t\n\t\tif(!blockRedraw){\n\t\t\tif(!update || this.reinitChanged(old)){\n\t\t\t\tthis.reinitializeRows();\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.elementVertical.scrollLeft = this.scrollLeft;\n\t}\n\t\n\trenderRowCells(row){\n\t\tif(this.initialized){\n\t\t\tthis.initializeRow(row);\n\t\t}else {\n\t\t\tconst rowFrag = document.createDocumentFragment();\n\t\t\trow.cells.forEach((cell) => {\n\t\t\t\trowFrag.appendChild(cell.getElement());\n\t\t\t});\n\t\t\trow.element.appendChild(rowFrag);\n\n\t\t\trow.cells.forEach((cell) => {\n\t\t\t\tcell.cellRendered();\n\t\t\t});\n\t\t}\n\t}\n\t\n\trerenderRowCells(row, force){\n\t\tthis.reinitializeRow(row, force);\n\t}\n\t\n\treinitializeColumnWidths(columns){\n\t\tfor(let i = this.leftCol; i <= this.rightCol; i++){\n\t\t\tthis.columns[i].reinitializeWidth();\n\t\t}\n\t}\n\t\n\t//////////////////////////////////////\n\t//////// Internal Rendering //////////\n\t//////////////////////////////////////\n\t\n\tdeinitialize(){\n\t\tthis.initialized = false;\n\t}\n\t\n\tclear(){\n\t\tthis.columns = [];\n\t\t\n\t\tthis.leftCol = -1;\n\t\tthis.rightCol = 0;\n\t\t\n\t\tthis.vDomScrollPosLeft = 0;\n\t\tthis.vDomScrollPosRight = 0;\n\t\tthis.vDomPadLeft = 0;\n\t\tthis.vDomPadRight = 0;\n\t}\n\t\n\tdataChange(){\n\t\tvar change = false,\n\t\trow, rowEl;\n\t\t\n\t\tif(this.isFitData){\n\t\t\tthis.table.columnManager.columnsByIndex.forEach((column) => {\n\t\t\t\tif(!column.definition.width && column.visible){\n\t\t\t\t\tchange = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tif(change && this.table.rowManager.getDisplayRows().length){\n\t\t\t\tthis.vDomScrollPosRight = this.scrollLeft + this.elementVertical.clientWidth + this.windowBuffer;\n\t\t\t\t\n\t\t\t\trow = this.chain(\"rows-sample\", [1], [], () => {\n\t\t\t\t\treturn this.table.rowManager.getDisplayRows();\n\t\t\t\t})[0];\n\t\t\t\t\n\t\t\t\tif(row){\n\t\t\t\t\trowEl = row.getElement();\n\t\t\t\t\t\n\t\t\t\t\trow.generateCells();\n\t\t\t\t\t\n\t\t\t\t\tthis.tableElement.appendChild(rowEl);\n\t\t\t\t\t\n\t\t\t\t\tfor(let colEnd = 0; colEnd < row.cells.length; colEnd++){\n\t\t\t\t\t\tlet cell = row.cells[colEnd];\n\t\t\t\t\t\trowEl.appendChild(cell.getElement());\n\t\t\t\t\t\t\n\t\t\t\t\t\tcell.column.reinitializeWidth();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\trowEl.parentNode.removeChild(rowEl);\n\t\t\t\t\t\n\t\t\t\t\tthis.rerenderColumns(false, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tif(this.options(\"layout\") === \"fitColumns\"){\n\t\t\t\tthis.layoutRefresh();\n\t\t\t\tthis.rerenderColumns(false, true);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treinitChanged(old){\n\t\tvar match = true;\n\t\t\n\t\tif(old.cols.length !== this.columns.length || old.leftCol !== this.leftCol || old.rightCol !== this.rightCol){\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\told.cols.forEach((col, i) => {\n\t\t\tif(col !== this.columns[i]){\n\t\t\t\tmatch = false;\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn !match;\n\t}\n\t\n\treinitializeRows(){\n\t\tvar visibleRows = this.getVisibleRows(),\n\t\totherRows = this.table.rowManager.getRows().filter(row => !visibleRows.includes(row));\n\n\t\tvisibleRows.forEach((row) => {\n\t\t\tthis.reinitializeRow(row, true);\n\t\t});\n\n\t\totherRows.forEach((row) =>{\n\t\t\trow.deinitialize();\n\t\t});\n\t}\n\t\n\tgetVisibleRows(){\n\t\tif (!this.visibleRows){\n\t\t\tthis.visibleRows = this.table.rowManager.getVisibleRows();\n\t\t}\n\t\t\n\t\treturn this.visibleRows;\t\n\t}\n\t\n\tscroll(diff){\n\t\tthis.vDomScrollPosLeft += diff;\n\t\tthis.vDomScrollPosRight += diff;\n\t\t\n\t\tif(Math.abs(diff) > (this.windowBuffer / 2)){\n\t\t\tthis.rerenderColumns();\n\t\t}else {\n\t\t\tif(diff > 0){\n\t\t\t\t//scroll right\n\t\t\t\tthis.addColRight();\n\t\t\t\tthis.removeColLeft();\n\t\t\t}else {\n\t\t\t\t//scroll left\n\t\t\t\tthis.addColLeft();\n\t\t\t\tthis.removeColRight();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tcolPositionAdjust (start, end, diff){\n\t\tfor(let i = start; i < end; i++){\n\t\t\tlet column = this.columns[i];\n\t\t\t\n\t\t\tcolumn.modules.vdomHoz.leftPos += diff;\n\t\t\tcolumn.modules.vdomHoz.rightPos += diff;\n\t\t}\n\t}\n\t\n\taddColRight(){\n\t\tvar changes = false,\n\t\tworking = true;\n\t\t\n\t\twhile(working){\n\n\t\t\tlet column = this.columns[this.rightCol + 1];\n\t\t\t\n\t\t\tif(column){\n\t\t\t\tif(column.modules.vdomHoz.leftPos <= this.vDomScrollPosRight){\n\t\t\t\t\tchanges = true;\n\t\t\t\t\t\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\tvar cell = row.getCell(column);\n\t\t\t\t\t\t\trow.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.rightCol]).getElement().nextSibling);\n\t\t\t\t\t\t\tcell.cellRendered();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.fitDataColActualWidthCheck(column);\n\t\t\t\t\t\n\t\t\t\t\tthis.rightCol++; // Don't move this below the >= check below\n\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\trow.modules.vdomHoz.rightCol = this.rightCol;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif(this.rightCol >= (this.columns.length - 1)){\n\t\t\t\t\t\tthis.vDomPadRight = 0;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.vDomPadRight -= column.getWidth();\n\t\t\t\t\t}\t\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(changes){\n\t\t\tthis.tableElement.style.paddingRight = this.vDomPadRight + \"px\";\n\t\t}\n\t}\n\t\n\taddColLeft(){\n\t\tvar changes = false,\n\t\tworking = true;\n\t\t\n\t\twhile(working){\n\t\t\tlet column = this.columns[this.leftCol - 1];\n\t\t\t\n\t\t\tif(column){\n\t\t\t\tif(column.modules.vdomHoz.rightPos >= this.vDomScrollPosLeft){\n\t\t\t\t\tchanges = true;\n\t\t\t\t\t\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\tvar cell = row.getCell(column);\n\t\t\t\t\t\t\trow.getElement().insertBefore(cell.getElement(), row.getCell(this.columns[this.leftCol]).getElement());\n\t\t\t\t\t\t\tcell.cellRendered();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.leftCol--; // don't move this below the <= check below\n\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\trow.modules.vdomHoz.leftCol = this.leftCol;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif(this.leftCol <= 0){ // replicating logic in addColRight\n\t\t\t\t\t\tthis.vDomPadLeft = 0;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.vDomPadLeft -= column.getWidth();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tlet diff = this.fitDataColActualWidthCheck(column);\n\t\t\t\t\t\n\t\t\t\t\tif(diff){\n\t\t\t\t\t\tthis.scrollLeft = this.elementVertical.scrollLeft = this.elementVertical.scrollLeft + diff;\n\t\t\t\t\t\tthis.vDomPadRight -= diff;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(changes){\n\t\t\tthis.tableElement.style.paddingLeft = this.vDomPadLeft + \"px\";\n\t\t}\n\t}\n\t\n\tremoveColRight(){\n\t\tvar changes = false,\n\t\tworking = true;\n\t\t\n\t\twhile(working){\n\t\t\tlet column = this.columns[this.rightCol];\n\t\t\t\n\t\t\tif(column){\n\t\t\t\tif(column.modules.vdomHoz.leftPos > this.vDomScrollPosRight){\n\t\t\t\t\tchanges = true;\n\t\t\t\t\t\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\tvar cell = row.getCell(column);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\trow.getElement().removeChild(cell.getElement());\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\tconsole.warn(\"Could not removeColRight\", ex.message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.vDomPadRight += column.getWidth();\n\t\t\t\t\tthis.rightCol --;\n\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\trow.modules.vdomHoz.rightCol = this.rightCol;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(changes){\n\t\t\tthis.tableElement.style.paddingRight = this.vDomPadRight + \"px\";\n\t\t}\n\t}\n\t\n\tremoveColLeft(){\n\t\tvar changes = false,\n\t\tworking = true;\n\n\t\twhile(working){\n\t\t\tlet column = this.columns[this.leftCol];\n\t\t\t\n\t\t\tif(column){\n\t\t\t\tif(column.modules.vdomHoz.rightPos < this.vDomScrollPosLeft){\n\t\t\t\t\tchanges = true;\n\t\t\t\t\t\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\t\t\t\t\t\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\tvar cell = row.getCell(column);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\trow.getElement().removeChild(cell.getElement());\n\t\t\t\t\t\t\t} catch (ex) {\n\t\t\t\t\t\t\t\tconsole.warn(\"Could not removeColLeft\", ex.message);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tthis.vDomPadLeft += column.getWidth();\n\t\t\t\t\tthis.leftCol ++;\n\n\t\t\t\t\tthis.getVisibleRows().forEach((row) => {\n\t\t\t\t\t\tif(row.type !== \"group\"){\n\t\t\t\t\t\t\trow.modules.vdomHoz.leftCol = this.leftCol;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(changes){\n\t\t\tthis.tableElement.style.paddingLeft = this.vDomPadLeft + \"px\";\n\t\t}\n\t}\n\t\n\tfitDataColActualWidthCheck(column){\n\t\tvar newWidth, widthDiff;\n\t\t\n\t\tif(column.modules.vdomHoz.fitDataCheck){\n\t\t\tcolumn.reinitializeWidth();\n\t\t\t\n\t\t\tnewWidth = column.getWidth();\n\t\t\twidthDiff = newWidth - column.modules.vdomHoz.width;\n\t\t\t\n\t\t\tif(widthDiff){\n\t\t\t\tcolumn.modules.vdomHoz.rightPos += widthDiff;\n\t\t\t\tcolumn.modules.vdomHoz.width = newWidth;\n\t\t\t\tthis.colPositionAdjust(this.columns.indexOf(column) + 1, this.columns.length, widthDiff);\n\t\t\t}\n\t\t\t\n\t\t\tcolumn.modules.vdomHoz.fitDataCheck = false;\n\t\t}\n\t\t\n\t\treturn widthDiff;\n\t}\n\t\n\tinitializeRow(row){\n\t\tif(row.type !== \"group\"){\n\t\t\trow.modules.vdomHoz = {\n\t\t\t\tleftCol:this.leftCol,\n\t\t\t\trightCol:this.rightCol,\n\t\t\t};\n\n\t\t\tif(this.table.modules.frozenColumns){\n\t\t\t\tthis.table.modules.frozenColumns.leftColumns.forEach((column) => {\n\t\t\t\t\tthis.appendCell(row, column);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor(let i = this.leftCol; i <= this.rightCol; i++){\n\t\t\t\tthis.appendCell(row, this.columns[i]);\n\t\t\t}\n\n\t\t\tif(this.table.modules.frozenColumns){\n\t\t\t\tthis.table.modules.frozenColumns.rightColumns.forEach((column) => {\n\t\t\t\t\tthis.appendCell(row, column);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\t\n\tappendCell(row, column){\n\t\tif(column && column.visible){\n\t\t\tlet cell = row.getCell(column);\n\t\t\t\n\t\t\trow.getElement().appendChild(cell.getElement());\n\t\t\tcell.cellRendered();\n\t\t}\n\t}\n\t\n\treinitializeRow(row, force){\n\t\tif(row.type !== \"group\"){\n\t\t\tif(force || !row.modules.vdomHoz || row.modules.vdomHoz.leftCol !== this.leftCol || row.modules.vdomHoz.rightCol !== this.rightCol){\n\t\t\t\t\n\t\t\t\tvar rowEl = row.getElement();\n\t\t\t\twhile(rowEl.firstChild) rowEl.removeChild(rowEl.firstChild);\n\n\t\t\t\tthis.initializeRow(row);\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass ColumnManager extends CoreFeature {\n\t\n\tconstructor (table){\n\t\tsuper(table);\n\t\t\n\t\tthis.blockHozScrollEvent = false;\n\t\tthis.headersElement = null;\n\t\tthis.contentsElement = null;\n\t\tthis.element = null ; //containing element\n\t\tthis.columns = []; // column definition object\n\t\tthis.columnsByIndex = []; //columns by index\n\t\tthis.columnsByField = {}; //columns by field\n\t\tthis.scrollLeft = 0;\n\t\tthis.optionsList = new OptionsList(this.table, \"column definition\", defaultColumnOptions);\n\t\t\n\t\tthis.redrawBlock = false; //prevent redraws to allow multiple data manipulations before continuing\n\t\tthis.redrawBlockUpdate = null; //store latest redraw update only status\n\t\t\n\t\tthis.renderer = null;\n\t}\n\t\n\t////////////// Setup Functions /////////////////\n\t\n\tinitialize(){\n\t\tthis.initializeRenderer();\n\t\t\n\t\tthis.headersElement = this.createHeadersElement();\n\t\tthis.contentsElement = this.createHeaderContentsElement();\n\t\tthis.element = this.createHeaderElement();\n\t\t\n\t\tthis.contentsElement.insertBefore(this.headersElement, this.contentsElement.firstChild);\n\t\tthis.element.insertBefore(this.contentsElement, this.element.firstChild);\n\n\t\tthis.initializeScrollWheelWatcher();\n\t\t\n\t\tthis.subscribe(\"scroll-horizontal\", this.scrollHorizontal.bind(this));\n\t\tthis.subscribe(\"scrollbar-vertical\", this.padVerticalScrollbar.bind(this));\n\t}\n\n\tpadVerticalScrollbar(width){\n\t\tif(this.table.rtl){\n\t\t\tthis.headersElement.style.marginLeft = width + \"px\";\n\t\t}else {\n\t\t\tthis.headersElement.style.marginRight = width + \"px\";\n\t\t}\n\t}\n\t\n\tinitializeRenderer(){\n\t\tvar renderClass;\n\t\t\n\t\tvar renderers = {\n\t\t\t\"virtual\": VirtualDomHorizontal,\n\t\t\t\"basic\": BasicHorizontal,\n\t\t};\n\t\t\n\t\tif(typeof this.table.options.renderHorizontal === \"string\"){\n\t\t\trenderClass = renderers[this.table.options.renderHorizontal];\n\t\t}else {\n\t\t\trenderClass = this.table.options.renderHorizontal;\n\t\t}\n\t\t\n\t\tif(renderClass){\n\t\t\tthis.renderer = new renderClass(this.table, this.element, this.tableElement);\n\t\t\tthis.renderer.initialize();\n\t\t}else {\n\t\t\tconsole.error(\"Unable to find matching renderer:\", this.table.options.renderHorizontal);\n\t\t}\n\t}\n\t\n\t\n\tcreateHeadersElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-headers\");\n\t\tel.setAttribute(\"role\", \"row\");\n\t\t\n\t\treturn el;\n\t}\n\n\tcreateHeaderContentsElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-header-contents\");\n\t\tel.setAttribute(\"role\", \"rowgroup\");\n\t\t\n\t\treturn el;\n\t}\n\t\n\tcreateHeaderElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-header\");\n\t\tel.setAttribute(\"role\", \"rowgroup\");\n\t\t\n\t\tif(!this.table.options.headerVisible){\n\t\t\tel.classList.add(\"tabulator-header-hidden\");\n\t\t}\n\t\t\n\t\treturn el;\n\t}\n\t\n\t//return containing element\n\tgetElement(){\n\t\treturn this.element;\n\t}\n\n\t//return containing contents element\n\tgetContentsElement(){\n\t\treturn this.contentsElement;\n\t}\n\t\n\t\n\t//return header containing element\n\tgetHeadersElement(){\n\t\treturn this.headersElement;\n\t}\n\t\n\t//scroll horizontally to match table body\n\tscrollHorizontal(left){\n\t\tthis.contentsElement.scrollLeft = left;\n\n\t\tthis.scrollLeft = left;\n\t\t\n\t\tthis.renderer.scrollColumns(left);\n\t}\n\n\tinitializeScrollWheelWatcher(){\n\t\tthis.contentsElement.addEventListener(\"wheel\", (e) => {\n\t\t\tvar left;\n\n\t\t\tif(e.deltaX){\n\t\t\t\tleft = this.contentsElement.scrollLeft + e.deltaX;\n\n\t\t\t\tthis.table.rowManager.scrollHorizontal(left);\n\t\t\t\tthis.table.columnManager.scrollHorizontal(left);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t///////////// Column Setup Functions /////////////\n\tgenerateColumnsFromRowData(data){\n\t\tvar cols = [],\n\t\tdefinitions = this.table.options.autoColumnsDefinitions,\n\t\trow, sorter;\n\t\t\n\t\tif(data && data.length){\n\t\t\t\n\t\t\trow = data[0];\n\t\t\t\n\t\t\tfor(var key in row){\n\t\t\t\tlet col = {\n\t\t\t\t\tfield:key,\n\t\t\t\t\ttitle:key,\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tlet value = row[key];\n\t\t\t\t\n\t\t\t\tswitch(typeof value){\n\t\t\t\t\tcase \"undefined\":\n\t\t\t\t\t\tsorter = \"string\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"boolean\":\n\t\t\t\t\t\tsorter = \"boolean\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\tif(Array.isArray(value)){\n\t\t\t\t\t\t\tsorter = \"array\";\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tsorter = \"string\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif(!isNaN(value) && value !== \"\"){\n\t\t\t\t\t\t\tsorter = \"number\";\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tif(value.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)){\n\t\t\t\t\t\t\t\tsorter = \"alphanum\";\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tsorter = \"string\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcol.sorter = sorter;\n\t\t\t\t\n\t\t\t\tcols.push(col);\n\t\t\t}\n\t\t\t\n\t\t\tif(definitions){\n\t\t\t\t\n\t\t\t\tswitch(typeof definitions){\n\t\t\t\t\tcase \"function\":\n\t\t\t\t\t\tthis.table.options.columns = definitions.call(this.table, cols);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"object\":\n\t\t\t\t\t\tif(Array.isArray(definitions)){\n\t\t\t\t\t\t\tcols.forEach((col) => {\n\t\t\t\t\t\t\t\tvar match = definitions.find((def) => {\n\t\t\t\t\t\t\t\t\treturn def.field === col.field;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif(match){\n\t\t\t\t\t\t\t\t\tObject.assign(col, match);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tcols.forEach((col) => {\n\t\t\t\t\t\t\t\tif(definitions[col.field]){\n\t\t\t\t\t\t\t\t\tObject.assign(col, definitions[col.field]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.table.options.columns = cols;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis.table.options.columns = cols;\n\t\t\t}\n\t\t\t\n\t\t\tthis.setColumns(this.table.options.columns);\n\t\t}\n\t}\n\t\n\tsetColumns(cols, row){\n\t\twhile(this.headersElement.firstChild) this.headersElement.removeChild(this.headersElement.firstChild);\n\t\t\n\t\tthis.columns = [];\n\t\tthis.columnsByIndex = [];\n\t\tthis.columnsByField = {};\n\t\t\n\t\tthis.dispatch(\"columns-loading\");\n\t\t\n\t\tcols.forEach((def, i) => {\n\t\t\tthis._addColumn(def);\n\t\t});\n\t\t\n\t\tthis._reIndexColumns();\n\t\t\n\t\tthis.dispatch(\"columns-loaded\");\n\t\t\n\t\tthis.rerenderColumns(false, true);\n\t\t\n\t\tthis.redraw(true);\n\t}\n\t\n\t_addColumn(definition, before, nextToColumn){\n\t\tvar column = new Column(definition, this),\n\t\tcolEl = column.getElement(),\n\t\tindex = nextToColumn ? this.findColumnIndex(nextToColumn) : nextToColumn;\n\t\t\n\t\tif(nextToColumn && index > -1){\n\t\t\tvar topColumn = nextToColumn.getTopColumn();\n\t\t\tvar parentIndex = this.columns.indexOf(topColumn);\n\t\t\tvar nextEl = topColumn.getElement();\n\t\t\t\n\t\t\tif(before){\n\t\t\t\tthis.columns.splice(parentIndex, 0, column);\n\t\t\t\tnextEl.parentNode.insertBefore(colEl, nextEl);\n\t\t\t}else {\n\t\t\t\tthis.columns.splice(parentIndex + 1, 0, column);\n\t\t\t\tnextEl.parentNode.insertBefore(colEl, nextEl.nextSibling);\n\t\t\t}\n\t\t}else {\n\t\t\tif(before){\n\t\t\t\tthis.columns.unshift(column);\n\t\t\t\tthis.headersElement.insertBefore(column.getElement(), this.headersElement.firstChild);\n\t\t\t}else {\n\t\t\t\tthis.columns.push(column);\n\t\t\t\tthis.headersElement.appendChild(column.getElement());\n\t\t\t}\n\t\t}\n\t\t\n\t\tcolumn.columnRendered();\n\t\t\n\t\treturn column;\n\t}\n\t\n\tregisterColumnField(col){\n\t\tif(col.definition.field){\n\t\t\tthis.columnsByField[col.definition.field] = col;\n\t\t}\n\t}\n\t\n\tregisterColumnPosition(col){\n\t\tthis.columnsByIndex.push(col);\n\t}\n\t\n\t_reIndexColumns(){\n\t\tthis.columnsByIndex = [];\n\t\t\n\t\tthis.columns.forEach(function(column){\n\t\t\tcolumn.reRegisterPosition();\n\t\t});\n\t}\n\t\n\t//ensure column headers take up the correct amount of space in column groups\n\tverticalAlignHeaders(){\n\t\tvar minHeight = 0;\n\t\t\n\t\tif(!this.redrawBlock){\n\n\t\t\tthis.headersElement.style.height=\"\";\n\t\t\t\n\t\t\tthis.columns.forEach((column) => {\n\t\t\t\tcolumn.clearVerticalAlign();\n\t\t\t});\n\t\t\t\n\t\t\tthis.columns.forEach((column) => {\n\t\t\t\tvar height = column.getHeight();\n\t\t\t\t\n\t\t\t\tif(height > minHeight){\n\t\t\t\t\tminHeight = height;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.headersElement.style.height = minHeight + \"px\";\n\n\t\t\tthis.columns.forEach((column) => {\n\t\t\t\tcolumn.verticalAlign(this.table.options.columnHeaderVertAlign, minHeight);\n\t\t\t});\n\t\t\t\n\t\t\tthis.table.rowManager.adjustTableSize();\n\t\t}\n\t}\n\t\n\t//////////////// Column Details /////////////////\n\tfindColumn(subject){\n\t\tvar columns;\n\n\t\tif(typeof subject == \"object\"){\n\t\t\t\n\t\t\tif(subject instanceof Column){\n\t\t\t\t//subject is column element\n\t\t\t\treturn subject;\n\t\t\t}else if(subject instanceof ColumnComponent){\n\t\t\t\t//subject is public column component\n\t\t\t\treturn subject._getSelf() || false;\n\t\t\t}else if(typeof HTMLElement !== \"undefined\" && subject instanceof HTMLElement){\n\n\t\t\t\tcolumns = [];\n\n\t\t\t\tthis.columns.forEach((column) => {\n\t\t\t\t\tcolumns.push(column);\n\t\t\t\t\tcolumns = columns.concat(column.getColumns(true));\n\t\t\t\t});\n\n\t\t\t\t//subject is a HTML element of the column header\n\t\t\t\tlet match = columns.find((column) => {\n\t\t\t\t\treturn column.element === subject;\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\treturn match || false;\n\t\t\t}\n\t\t\t\n\t\t}else {\n\t\t\t//subject should be treated as the field name of the column\n\t\t\treturn this.columnsByField[subject] || false;\n\t\t}\n\t\t\n\t\t//catch all for any other type of input\n\t\treturn false;\n\t}\n\t\n\tgetColumnByField(field){\n\t\treturn this.columnsByField[field];\n\t}\n\t\n\tgetColumnsByFieldRoot(root){\n\t\tvar matches = [];\n\t\t\n\t\tObject.keys(this.columnsByField).forEach((field) => {\n\t\t\tvar fieldRoot = this.table.options.nestedFieldSeparator ? field.split(this.table.options.nestedFieldSeparator)[0] : field;\n\t\t\tif(fieldRoot === root){\n\t\t\t\tmatches.push(this.columnsByField[field]);\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn matches;\n\t}\n\t\n\tgetColumnByIndex(index){\n\t\treturn this.columnsByIndex[index];\n\t}\n\t\n\tgetFirstVisibleColumn(){\n\t\tvar index = this.columnsByIndex.findIndex((col) => {\n\t\t\treturn col.visible;\n\t\t});\n\t\t\n\t\treturn index > -1 ? this.columnsByIndex[index] : false;\n\t}\n\n\tgetVisibleColumnsByIndex() {\n\t\treturn this.columnsByIndex.filter((col) => col.visible);\n\t}\n\t\n\tgetColumns(){\n\t\treturn this.columns;\n\t}\n\t\n\tfindColumnIndex(column){\n\t\treturn this.columnsByIndex.findIndex((col) => {\n\t\t\treturn column === col;\n\t\t});\n\t}\n\t\n\t//return all columns that are not groups\n\tgetRealColumns(){\n\t\treturn this.columnsByIndex;\n\t}\n\t\n\t//traverse across columns and call action\n\ttraverse(callback){\n\t\tthis.columnsByIndex.forEach((column,i) =>{\n\t\t\tcallback(column, i);\n\t\t});\n\t}\n\t\n\t//get definitions of actual columns\n\tgetDefinitions(active){\n\t\tvar output = [];\n\t\t\n\t\tthis.columnsByIndex.forEach((column) => {\n\t\t\tif(!active || (active && column.visible)){\n\t\t\t\toutput.push(column.getDefinition());\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\t//get full nested definition tree\n\tgetDefinitionTree(){\n\t\tvar output = [];\n\t\t\n\t\tthis.columns.forEach((column) => {\n\t\t\toutput.push(column.getDefinition(true));\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetComponents(structured){\n\t\tvar output = [],\n\t\tcolumns = structured ? this.columns : this.columnsByIndex;\n\t\t\n\t\tcolumns.forEach((column) => {\n\t\t\toutput.push(column.getComponent());\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetWidth(){\n\t\tvar width = 0;\n\t\t\n\t\tthis.columnsByIndex.forEach((column) => {\n\t\t\tif(column.visible){\n\t\t\t\twidth += column.getWidth();\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn width;\n\t}\n\t\n\tmoveColumn(from, to, after){\n\t\tto.element.parentNode.insertBefore(from.element, to.element);\n\t\t\n\t\tif(after){\n\t\t\tto.element.parentNode.insertBefore(to.element, from.element);\n\t\t}\n\t\t\n\t\tthis.moveColumnActual(from, to, after);\n\n\t\tthis.verticalAlignHeaders();\n\t\t\n\t\tthis.table.rowManager.reinitialize();\n\t}\n\t\n\tmoveColumnActual(from, to, after){\n\t\tif(from.parent.isGroup){\n\t\t\tthis._moveColumnInArray(from.parent.columns, from, to, after);\n\t\t}else {\n\t\t\tthis._moveColumnInArray(this.columns, from, to, after);\n\t\t}\n\t\t\n\t\tthis._moveColumnInArray(this.columnsByIndex, from, to, after, true);\n\t\t\n\t\tthis.rerenderColumns(true);\n\t\t\n\t\tthis.dispatch(\"column-moved\", from, to, after);\n\t\t\n\t\tif(this.subscribedExternal(\"columnMoved\")){\n\t\t\tthis.dispatchExternal(\"columnMoved\", from.getComponent(), this.table.columnManager.getComponents());\n\t\t}\n\t}\n\t\n\t_moveColumnInArray(columns, from, to, after, updateRows){\n\t\tvar\tfromIndex = columns.indexOf(from),\n\t\ttoIndex, rows = [];\n\t\t\n\t\tif (fromIndex > -1) {\n\t\t\t\n\t\t\tcolumns.splice(fromIndex, 1);\n\t\t\t\n\t\t\ttoIndex = columns.indexOf(to);\n\t\t\t\n\t\t\tif (toIndex > -1) {\n\t\t\t\t\n\t\t\t\tif(after){\n\t\t\t\t\ttoIndex = toIndex+1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}else {\n\t\t\t\ttoIndex = fromIndex;\n\t\t\t}\n\t\t\t\n\t\t\tcolumns.splice(toIndex, 0, from);\n\t\t\t\n\t\t\tif(updateRows){\n\t\t\t\t\n\t\t\t\trows = this.chain(\"column-moving-rows\", [from, to, after], null, []) || [];\n\t\t\t\t\n\t\t\t\trows = rows.concat(this.table.rowManager.rows);\n\t\t\t\t\n\t\t\t\trows.forEach(function(row){\n\t\t\t\t\tif(row.cells.length){\n\t\t\t\t\t\tvar cell = row.cells.splice(fromIndex, 1)[0];\n\t\t\t\t\t\trow.cells.splice(toIndex, 0, cell);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t}\n\t\n\tscrollToColumn(column, position, ifVisible){\n\t\tvar left = 0,\n\t\toffset = column.getLeftOffset(),\n\t\tadjust = 0,\n\t\tcolEl = column.getElement();\n\t\t\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tif(typeof position === \"undefined\"){\n\t\t\t\tposition = this.table.options.scrollToColumnPosition;\n\t\t\t}\n\t\t\t\n\t\t\tif(typeof ifVisible === \"undefined\"){\n\t\t\t\tifVisible = this.table.options.scrollToColumnIfVisible;\n\t\t\t}\n\t\t\t\n\t\t\tif(column.visible){\n\t\t\t\t\n\t\t\t\t//align to correct position\n\t\t\t\tswitch(position){\n\t\t\t\t\tcase \"middle\":\n\t\t\t\t\tcase \"center\":\n\t\t\t\t\t\tadjust = -this.element.clientWidth / 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tadjust = colEl.clientWidth - this.headersElement.clientWidth;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//check column visibility\n\t\t\t\tif(!ifVisible){\n\t\t\t\t\tif(offset > 0 && offset + colEl.offsetWidth < this.element.clientWidth){\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//calculate scroll position\n\t\t\t\tleft = offset + adjust;\n\t\t\t\t\n\t\t\t\tleft = Math.max(Math.min(left, this.table.rowManager.element.scrollWidth - this.table.rowManager.element.clientWidth),0);\n\t\t\t\t\n\t\t\t\tthis.table.rowManager.scrollHorizontal(left);\n\t\t\t\tthis.scrollHorizontal(left);\n\t\t\t\t\n\t\t\t\tresolve();\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Scroll Error - Column not visible\");\n\t\t\t\treject(\"Scroll Error - Column not visible\");\n\t\t\t}\n\t\t\t\n\t\t});\n\t}\n\t\n\t//////////////// Cell Management /////////////////\n\tgenerateCells(row){\n\t\tvar cells = [];\n\t\t\n\t\tthis.columnsByIndex.forEach((column) => {\n\t\t\tcells.push(column.generateCell(row));\n\t\t});\n\t\t\n\t\treturn cells;\n\t}\n\t\n\t//////////////// Column Management /////////////////\n\tgetFlexBaseWidth(){\n\t\tvar totalWidth = this.table.element.clientWidth, //table element width\n\t\tfixedWidth = 0;\n\t\t\n\t\t//adjust for vertical scrollbar if present\n\t\tif(this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight){\n\t\t\ttotalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth;\n\t\t}\n\t\t\n\t\tthis.columnsByIndex.forEach(function(column){\n\t\t\tvar width, minWidth, colWidth;\n\t\t\t\n\t\t\tif(column.visible){\n\t\t\t\t\n\t\t\t\twidth = column.definition.width || 0;\n\t\t\t\t\n\t\t\t\tminWidth = parseInt(column.minWidth);\n\t\t\t\t\n\t\t\t\tif(typeof(width) == \"string\"){\n\t\t\t\t\tif(width.indexOf(\"%\") > -1){\n\t\t\t\t\t\tcolWidth = (totalWidth / 100) * parseInt(width) ;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tcolWidth = parseInt(width);\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tcolWidth = width;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfixedWidth += colWidth > minWidth ? colWidth : minWidth;\n\t\t\t\t\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn fixedWidth;\n\t}\n\t\n\taddColumn(definition, before, nextToColumn){\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tvar column = this._addColumn(definition, before, nextToColumn);\n\t\t\t\n\t\t\tthis._reIndexColumns();\n\t\t\t\n\t\t\tthis.dispatch(\"column-add\", definition, before, nextToColumn);\n\t\t\t\n\t\t\tif(this.layoutMode() != \"fitColumns\"){\n\t\t\t\tcolumn.reinitializeWidth();\n\t\t\t}\n\t\t\t\n\t\t\tthis.redraw(true);\n\t\t\t\n\t\t\tthis.table.rowManager.reinitialize();\n\t\t\t\n\t\t\tthis.rerenderColumns();\n\t\t\t\n\t\t\tresolve(column);\n\t\t});\n\t}\n\t\n\t//remove column from system\n\tderegisterColumn(column){\n\t\tvar field = column.getField(),\n\t\tindex;\n\t\t\n\t\t//remove from field list\n\t\tif(field){\n\t\t\tdelete this.columnsByField[field];\n\t\t}\n\t\t\n\t\t//remove from index list\n\t\tindex = this.columnsByIndex.indexOf(column);\n\t\t\n\t\tif(index > -1){\n\t\t\tthis.columnsByIndex.splice(index, 1);\n\t\t}\n\t\t\n\t\t//remove from column list\n\t\tindex = this.columns.indexOf(column);\n\t\t\n\t\tif(index > -1){\n\t\t\tthis.columns.splice(index, 1);\n\t\t}\n\t\t\n\t\tthis.verticalAlignHeaders();\n\t\t\n\t\tthis.redraw();\n\t}\n\t\n\trerenderColumns(update, silent){\n\t\tif(!this.redrawBlock){\n\t\t\tthis.renderer.rerenderColumns(update, silent);\n\t\t}else {\n\t\t\tif(update === false || (update === true && this.redrawBlockUpdate === null)){\n\t\t\t\tthis.redrawBlockUpdate = update;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tblockRedraw(){\n\t\tthis.redrawBlock = true;\n\t\tthis.redrawBlockUpdate = null;\n\t}\n\t\n\trestoreRedraw(){\n\t\tthis.redrawBlock = false;\n\t\tthis.verticalAlignHeaders();\n\t\tthis.renderer.rerenderColumns(this.redrawBlockUpdate);\n\t\t\n\t}\n\t\n\t//redraw columns\n\tredraw(force){\n\t\tif(Helpers.elVisible(this.element)){\n\t\t\tthis.verticalAlignHeaders();\n\t\t}\n\t\t\n\t\tif(force){\n\t\t\tthis.table.rowManager.resetScroll();\n\t\t\tthis.table.rowManager.reinitialize();\n\t\t}\n\t\t\n\t\tif(!this.confirm(\"table-redrawing\", force)){\n\t\t\tthis.layoutRefresh(force);\n\t\t}\n\t\t\n\t\tthis.dispatch(\"table-redraw\", force);\n\t\t\n\t\tthis.table.footerManager.redraw();\n\t}\n}\n\nclass BasicVertical extends Renderer{\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.verticalFillMode = \"fill\";\n\t\t\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\t\t\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\t}\n\t\n\tclearRows(){\n\t\tvar element = this.tableElement;\n\t\t\n\t\t// element.children.detach();\n\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\t\t\n\t\telement.scrollTop = 0;\n\t\telement.scrollLeft = 0;\n\t\t\n\t\telement.style.minWidth = \"\";\n\t\telement.style.minHeight = \"\";\n\t\telement.style.display = \"\";\n\t\telement.style.visibility = \"\";\n\t}\n\t\n\trenderRows() {\n\t\tvar element = this.tableElement,\n\t\tonlyGroupHeaders = true,\n\t\ttableFrag = document.createDocumentFragment(),\n\t\trows = this.rows();\n\t\t\n\t\trows.forEach((row, index) => {\n\t\t\tthis.styleRow(row, index);\n\t\t\trow.initialize(false, true);\n\t\t\t\n\t\t\tif (row.type !== \"group\") {\n\t\t\t\tonlyGroupHeaders = false;\n\t\t\t}\n\t\t\t\n\t\t\ttableFrag.appendChild(row.getElement());\n\t\t});\n\t\t\n\t\telement.appendChild(tableFrag);\n\t\t\n\t\trows.forEach((row) => {\n\t\t\trow.rendered();\n\t\t\t\n\t\t\tif(!row.heightInitialized) {\n\t\t\t\trow.calcHeight(true);\n\t\t\t}\n\t\t});\n\t\t\n\t\trows.forEach((row) => {\n\t\t\tif(!row.heightInitialized) {\n\t\t\t\trow.setCellHeight();\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(onlyGroupHeaders){\n\t\t\telement.style.minWidth = this.table.columnManager.getWidth() + \"px\";\n\t\t}else {\n\t\t\telement.style.minWidth = \"\";\n\t\t}\n\t}\n\t\n\t\n\trerenderRows(callback){\t\n\t\tthis.clearRows();\n\t\t\n\t\tif(callback){\n\t\t\tcallback();\n\t\t}\n\t\t\n\t\tthis.renderRows();\n\n\t\tif(!this.rows().length){\n\t\t\tthis.table.rowManager.tableEmpty();\n\t\t}\n\t}\n\t\n\tscrollToRowNearestTop(row){\n\t\tvar rowTop = Helpers.elOffset(row.getElement()).top;\n\t\t\n\t\treturn !(Math.abs(this.elementVertical.scrollTop - rowTop) > Math.abs(this.elementVertical.scrollTop + this.elementVertical.clientHeight - rowTop));\n\t}\n\t\n\tscrollToRow(row){\n\t\tvar rowEl = row.getElement();\n\t\t\n\t\tthis.elementVertical.scrollTop = Helpers.elOffset(rowEl).top - Helpers.elOffset(this.elementVertical).top + this.elementVertical.scrollTop;\n\t}\n\t\n\tvisibleRows(includingBuffer){\n\t\treturn this.rows();\n\t}\n\t\n}\n\nclass VirtualDomVertical extends Renderer{\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.verticalFillMode = \"fill\";\n\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\n\t\tthis.vDomRowHeight = 20; //approximation of row heights for padding\n\n\t\tthis.vDomTop = 0; //hold position for first rendered row in the virtual DOM\n\t\tthis.vDomBottom = 0; //hold position for last rendered row in the virtual DOM\n\n\t\tthis.vDomScrollPosTop = 0; //last scroll position of the vDom top;\n\t\tthis.vDomScrollPosBottom = 0; //last scroll position of the vDom bottom;\n\n\t\tthis.vDomTopPad = 0; //hold value of padding for top of virtual DOM\n\t\tthis.vDomBottomPad = 0; //hold value of padding for bottom of virtual DOM\n\n\t\tthis.vDomMaxRenderChain = 90; //the maximum number of dom elements that can be rendered in 1 go\n\n\t\tthis.vDomWindowBuffer = 0; //window row buffer before removing elements, to smooth scrolling\n\n\t\tthis.vDomWindowMinTotalRows = 20; //minimum number of rows to be generated in virtual dom (prevent buffering issues on tables with tall rows)\n\t\tthis.vDomWindowMinMarginRows = 5; //minimum number of rows to be generated in virtual dom margin\n\n\t\tthis.vDomTopNewRows = []; //rows to normalize after appending to optimize render speed\n\t\tthis.vDomBottomNewRows = []; //rows to normalize after appending to optimize render speed\n\t}\n\n\t//////////////////////////////////////\n\t///////// Public Functions ///////////\n\t//////////////////////////////////////\n\n\tclearRows(){\n\t\tvar element = this.tableElement;\n\n\t\t// element.children.detach();\n\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\n\t\telement.style.paddingTop = \"\";\n\t\telement.style.paddingBottom = \"\";\n\t\telement.style.minHeight = \"\";\n\t\telement.style.display = \"\";\n\t\telement.style.visibility = \"\";\n\n\t\tthis.elementVertical.scrollTop = 0;\n\t\tthis.elementVertical.scrollLeft = 0;\n\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\n\t\tthis.vDomTop = 0;\n\t\tthis.vDomBottom = 0;\n\t\tthis.vDomTopPad = 0;\n\t\tthis.vDomBottomPad = 0;\n\t\tthis.vDomScrollPosTop = 0;\n\t\tthis.vDomScrollPosBottom = 0;\n\t}\n\n\trenderRows(){\n\t\tthis._virtualRenderFill();\n\t}\n\n\trerenderRows(callback){\n\t\tvar scrollTop = this.elementVertical.scrollTop;\n\t\tvar topRow = false;\n\t\tvar topOffset = false;\n\n\t\tvar left = this.table.rowManager.scrollLeft;\n\n\t\tvar rows = this.rows();\n\n\t\tfor(var i = this.vDomTop; i <= this.vDomBottom; i++){\n\n\t\t\tif(rows[i]){\n\t\t\t\tvar diff = scrollTop - rows[i].getElement().offsetTop;\n\n\t\t\t\tif(topOffset === false || Math.abs(diff) < topOffset){\n\t\t\t\t\ttopOffset = diff;\n\t\t\t\t\ttopRow = i;\n\t\t\t\t}else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trows.forEach((row) => {\n\t\t\trow.deinitializeHeight();\n\t\t});\n\n\t\tif(callback){\n\t\t\tcallback();\n\t\t}\n\n\t\tif(this.rows().length){\n\t\t\tthis._virtualRenderFill((topRow === false ? this.rows.length - 1 : topRow), true, topOffset || 0);\n\t\t}else {\n\t\t\tthis.clear();\n\t\t\tthis.table.rowManager.tableEmpty();\n\t\t}\n\n\t\tthis.scrollColumns(left);\n\t}\n\n\tscrollColumns(left){\n\t\tthis.table.rowManager.scrollHorizontal(left);\n\t}\n\n\tscrollRows(top, dir){\n\t\tvar topDiff = top - this.vDomScrollPosTop;\n\t\tvar bottomDiff = top - this.vDomScrollPosBottom;\n\t\tvar margin = this.vDomWindowBuffer * 2;\n\t\tvar rows = this.rows();\n\n\t\tthis.scrollTop = top;\n\n\t\tif(-topDiff > margin || bottomDiff > margin){\n\t\t\t//if big scroll redraw table;\n\t\t\tvar left = this.table.rowManager.scrollLeft;\n\t\t\tthis._virtualRenderFill(Math.floor((this.elementVertical.scrollTop / this.elementVertical.scrollHeight) * rows.length));\n\t\t\tthis.scrollColumns(left);\n\t\t}else {\n\n\t\t\tif(dir){\n\t\t\t\t//scrolling up\n\t\t\t\tif(topDiff < 0){\n\t\t\t\t\tthis._addTopRow(rows, -topDiff);\n\t\t\t\t}\n\n\t\t\t\tif(bottomDiff < 0){\n\t\t\t\t\t//hide bottom row if needed\n\t\t\t\t\tif(this.vDomScrollHeight - this.scrollTop > this.vDomWindowBuffer){\n\t\t\t\t\t\tthis._removeBottomRow(rows, -bottomDiff);\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.vDomScrollPosBottom = this.scrollTop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else {\n\n\t\t\t\tif(bottomDiff >= 0){\n\t\t\t\t\tthis._addBottomRow(rows, bottomDiff);\n\t\t\t\t}\n\n\t\t\t\t//scrolling down\n\t\t\t\tif(topDiff >= 0){\n\t\t\t\t\t//hide top row if needed\n\t\t\t\t\tif(this.scrollTop > this.vDomWindowBuffer){\n\t\t\t\t\t\tthis._removeTopRow(rows, topDiff);\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.vDomScrollPosTop = this.scrollTop;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tresize(){\n\t\tthis.vDomWindowBuffer = this.table.options.renderVerticalBuffer || this.elementVertical.clientHeight;\n\t}\n\n\tscrollToRowNearestTop(row){\n\t\tvar rowIndex = this.rows().indexOf(row);\n\n\t\treturn !(Math.abs(this.vDomTop - rowIndex) > Math.abs(this.vDomBottom - rowIndex));\n\t}\n\n\tscrollToRow(row){\n\t\tvar index = this.rows().indexOf(row);\n\n\t\tif(index > -1){\n\t\t\tthis._virtualRenderFill(index, true);\n\t\t}\n\t}\n\n\tvisibleRows(includingBuffer){\n\t\tvar topEdge = this.elementVertical.scrollTop,\n\t\tbottomEdge = this.elementVertical.clientHeight + topEdge,\n\t\ttopFound = false,\n\t\ttopRow = 0,\n\t\tbottomRow = 0,\n\t\trows = this.rows();\n\n\t\tif(includingBuffer){\n\t\t\ttopRow = this.vDomTop;\n\t\t\tbottomRow = this.vDomBottom;\n\t\t}else {\n\t\t\tfor(var i = this.vDomTop; i <= this.vDomBottom; i++){\n\t\t\t\tif(rows[i]){\n\t\t\t\t\tif(!topFound){\n\t\t\t\t\t\tif((topEdge - rows[i].getElement().offsetTop) >= 0){\n\t\t\t\t\t\t\ttopRow = i;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\ttopFound = true;\n\n\t\t\t\t\t\t\tif(bottomEdge - rows[i].getElement().offsetTop >= 0){\n\t\t\t\t\t\t\t\tbottomRow = i;\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tif(bottomEdge - rows[i].getElement().offsetTop >= 0){\n\t\t\t\t\t\t\tbottomRow = i;\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn rows.slice(topRow, bottomRow + 1);\n\t}\n\n\t//////////////////////////////////////\n\t//////// Internal Rendering //////////\n\t//////////////////////////////////////\n\n\t//full virtual render\n\t_virtualRenderFill(position, forceMove, offset) {\n\t\tvar\telement = this.tableElement,\n\t\tholder = this.elementVertical,\n\t\ttopPad = 0,\n\t\trowsHeight = 0,\n\t\trowHeight = 0,\n\t\theightOccupied = 0,\n\t\ttopPadHeight = 0,\n\t\ti = 0,\n\t\trows = this.rows(),\n\t\trowsCount = rows.length,\n\t\tindex = 0,\n\t\trow,\n\t\trowFragment,\n\t\trenderedRows = [],\n\t\ttotalRowsRendered = 0,\n\t\trowsToRender = 0,\n\t\tfixedHeight = this.table.rowManager.fixedHeight,\n\t\tcontainerHeight = this.elementVertical.clientHeight, \n\t\tavgRowHeight = this.table.options.rowHeight, \n\t\tresized = true;\n\n\t\tposition = position || 0;\n\n\t\toffset = offset || 0;\n\n\t\tif(!position){\n\t\t\tthis.clear();\n\t\t}else {\n\t\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\n\t\t\t//check if position is too close to bottom of table\n\t\t\theightOccupied = (rowsCount - position + 1) * this.vDomRowHeight;\n\n\t\t\tif(heightOccupied < containerHeight){\n\t\t\t\tposition -= Math.ceil((containerHeight - heightOccupied) / this.vDomRowHeight);\n\t\t\t\tif(position < 0){\n\t\t\t\t\tposition = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//calculate initial pad\n\t\t\ttopPad = Math.min(Math.max(Math.floor(this.vDomWindowBuffer / this.vDomRowHeight),  this.vDomWindowMinMarginRows), position);\n\t\t\tposition -= topPad;\n\t\t}\n\n\t\tif(rowsCount && Helpers.elVisible(this.elementVertical)){\n\t\t\tthis.vDomTop = position;\n\t\t\tthis.vDomBottom = position -1;\n\n\t\t\tif(fixedHeight || this.table.options.maxHeight) {\n\t\t\t\tif(avgRowHeight) {\n\t\t\t\t\trowsToRender = (containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight);\n\t\t\t\t}\n\t\t\t\trowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil(rowsToRender));\n\t\t\t}\n\t\t\telse {\n\t\t\t\trowsToRender = rowsCount;\n\t\t\t}\n\n\t\t\twhile(((rowsToRender == rowsCount || rowsHeight <= containerHeight + this.vDomWindowBuffer) || totalRowsRendered < this.vDomWindowMinTotalRows) && this.vDomBottom < rowsCount -1) {\n\t\t\t\trenderedRows = [];\n\t\t\t\trowFragment = document.createDocumentFragment();\n\n\t\t\t\ti = 0;\n\n\t\t\t\twhile ((i < rowsToRender) && this.vDomBottom < rowsCount -1) {\t\n\t\t\t\t\tindex = this.vDomBottom + 1,\n\t\t\t\t\trow = rows[index];\n\n\t\t\t\t\tthis.styleRow(row, index);\n\n\t\t\t\t\trow.initialize(false, true);\n\t\t\t\t\tif(!row.heightInitialized && !this.table.options.rowHeight){\n\t\t\t\t\t\trow.clearCellHeight();\n\t\t\t\t\t}\n\n\t\t\t\t\trowFragment.appendChild(row.getElement());\n\t\t\t\t\trenderedRows.push(row);\n\t\t\t\t\tthis.vDomBottom ++;\n\t\t\t\t\ti++;\n\t\t\t\t}\n\n\t\t\t\tif(!renderedRows.length){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telement.appendChild(rowFragment);\n\t\t\t\t\n\t\t\t\t// NOTE: The next 3 loops are separate on purpose\n\t\t\t\t// This is to batch up the dom writes and reads which drastically improves performance \n\n\t\t\t\trenderedRows.forEach((row) => {\n\t\t\t\t\trow.rendered();\n\n\t\t\t\t\tif(!row.heightInitialized) {\n\t\t\t\t\t\trow.calcHeight(true);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\trenderedRows.forEach((row) => {\n\t\t\t\t\tif(!row.heightInitialized) {\n\t\t\t\t\t\trow.setCellHeight();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\trenderedRows.forEach((row) => {\n\t\t\t\t\trowHeight = row.getHeight();\n\t\t\t\t\t\n\t\t\t\t\tif(totalRowsRendered < topPad){\n\t\t\t\t\t\ttopPadHeight += rowHeight;\n\t\t\t\t\t}else {\n\t\t\t\t\t\trowsHeight += rowHeight;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(rowHeight > this.vDomWindowBuffer){\n\t\t\t\t\t\tthis.vDomWindowBuffer = rowHeight * 2;\n\t\t\t\t\t}\n\t\t\t\t\ttotalRowsRendered++;\n\t\t\t\t});\n\n\t\t\t\tresized = this.table.rowManager.adjustTableSize();\n\t\t\t\tcontainerHeight = this.elementVertical.clientHeight;\n\t\t\t\tif(resized && (fixedHeight || this.table.options.maxHeight))\n\t\t\t\t{\n\t\t\t\t\tavgRowHeight = rowsHeight / totalRowsRendered;\n\t\t\t\t\trowsToRender = Math.max(this.vDomWindowMinTotalRows, Math.ceil((containerHeight / avgRowHeight) + (this.vDomWindowBuffer / avgRowHeight)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!position){\n\t\t\t\tthis.vDomTopPad = 0;\n\t\t\t\t//adjust row height to match average of rendered elements\n\t\t\t\tthis.vDomRowHeight = Math.floor((rowsHeight + topPadHeight) / totalRowsRendered);\n\t\t\t\tthis.vDomBottomPad = this.vDomRowHeight * (rowsCount - this.vDomBottom -1);\n\n\t\t\t\tthis.vDomScrollHeight = topPadHeight + rowsHeight + this.vDomBottomPad - containerHeight;\n\t\t\t}else {\n\t\t\t\tthis.vDomTopPad = !forceMove ? this.scrollTop - topPadHeight : (this.vDomRowHeight * this.vDomTop) + offset;\n\t\t\t\tthis.vDomBottomPad = this.vDomBottom == rowsCount-1 ? 0 : Math.max(this.vDomScrollHeight - this.vDomTopPad - rowsHeight - topPadHeight, 0);\n\t\t\t}\n\t\t\t\n\t\t\telement.style.paddingTop = this.vDomTopPad+\"px\";\n\t\t\telement.style.paddingBottom = this.vDomBottomPad+\"px\";\n\n\t\t\tif(forceMove){\n\t\t\t\tthis.scrollTop = this.vDomTopPad + (topPadHeight) + offset - (this.elementVertical.scrollWidth > this.elementVertical.clientWidth ? this.elementVertical.offsetHeight - containerHeight : 0);\n\t\t\t}\n\n\t\t\tthis.scrollTop = Math.min(this.scrollTop, this.elementVertical.scrollHeight - containerHeight);\n\n\t\t\t//adjust for horizontal scrollbar if present (and not at top of table)\n\t\t\tif(this.elementVertical.scrollWidth > this.elementVertical.clientWidth && forceMove){\n\t\t\t\tthis.scrollTop += this.elementVertical.offsetHeight - containerHeight;\n\t\t\t}\n\n\t\t\tthis.vDomScrollPosTop = this.scrollTop;\n\t\t\tthis.vDomScrollPosBottom = this.scrollTop;\n\n\t\t\tholder.scrollTop = this.scrollTop;\n\n\t\t\tthis.dispatch(\"render-virtual-fill\");\n\t\t}\n\t}\n\n\t_addTopRow(rows, fillableSpace){\n\t\tvar table = this.tableElement,\n\t\taddedRows = [],\n\t\tpaddingAdjust = 0,\n\t\tindex = this.vDomTop -1,\n\t\ti = 0,\n\t\tworking = true;\n\n\t\twhile(working){\n\t\t\tif(this.vDomTop){\n\t\t\t\tlet row = rows[index],\n\t\t\t\trowHeight, initialized;\n\n\t\t\t\tif(row && i < this.vDomMaxRenderChain){\n\t\t\t\t\trowHeight = row.getHeight() || this.vDomRowHeight;\n\t\t\t\t\tinitialized = row.initialized;\n\n\t\t\t\t\tif(fillableSpace >= rowHeight){\n\n\t\t\t\t\t\tthis.styleRow(row, index);\n\t\t\t\t\t\ttable.insertBefore(row.getElement(), table.firstChild);\n\n\t\t\t\t\t\tif(!row.initialized || !row.heightInitialized){\n\t\t\t\t\t\t\taddedRows.push(row);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\trow.initialize();\n\n\t\t\t\t\t\tif(!initialized){\n\t\t\t\t\t\t\trowHeight = row.getElement().offsetHeight;\n\n\t\t\t\t\t\t\tif(rowHeight > this.vDomWindowBuffer){\n\t\t\t\t\t\t\t\tthis.vDomWindowBuffer = rowHeight * 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfillableSpace -= rowHeight;\n\t\t\t\t\t\tpaddingAdjust += rowHeight;\n\n\t\t\t\t\t\tthis.vDomTop--;\n\t\t\t\t\t\tindex--;\n\t\t\t\t\t\ti++;\n\n\t\t\t\t\t}else {\n\t\t\t\t\t\tworking = false;\n\t\t\t\t\t}\n\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let row of addedRows){\n\t\t\trow.clearCellHeight();\n\t\t}\n\n\t\tthis._quickNormalizeRowHeight(addedRows);\n\n\t\tif(paddingAdjust){\n\t\t\tthis.vDomTopPad -= paddingAdjust;\n\n\t\t\tif(this.vDomTopPad < 0){\n\t\t\t\tthis.vDomTopPad = index * this.vDomRowHeight;\n\t\t\t}\n\n\t\t\tif(index < 1){\n\t\t\t\tthis.vDomTopPad = 0;\n\t\t\t}\n\n\t\t\ttable.style.paddingTop = this.vDomTopPad + \"px\";\n\t\t\tthis.vDomScrollPosTop -= paddingAdjust;\n\t\t}\n\t}\n\n\t_removeTopRow(rows, fillableSpace){\n\t\tvar removableRows = [],\n\t\tpaddingAdjust = 0,\n\t\ti = 0,\n\t\tworking = true;\n\n\t\twhile(working){\n\t\t\tlet row = rows[this.vDomTop],\n\t\t\trowHeight;\n\n\t\t\tif(row && i < this.vDomMaxRenderChain){\n\t\t\t\trowHeight = row.getHeight() || this.vDomRowHeight;\n\n\t\t\t\tif(fillableSpace >= rowHeight){\n\t\t\t\t\tthis.vDomTop++;\n\n\t\t\t\t\tfillableSpace -= rowHeight;\n\t\t\t\t\tpaddingAdjust += rowHeight;\n\n\t\t\t\t\tremovableRows.push(row);\n\t\t\t\t\ti++;\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let row of removableRows){\n\t\t\tlet rowEl = row.getElement();\n\n\t\t\tif(rowEl.parentNode){\n\t\t\t\trowEl.parentNode.removeChild(rowEl);\n\t\t\t}\n\t\t}\n\n\t\tif(paddingAdjust){\n\t\t\tthis.vDomTopPad += paddingAdjust;\n\t\t\tthis.tableElement.style.paddingTop = this.vDomTopPad + \"px\";\n\t\t\tthis.vDomScrollPosTop += this.vDomTop ? paddingAdjust : paddingAdjust + this.vDomWindowBuffer;\n\t\t}\n\t}\n\n\t_addBottomRow(rows, fillableSpace){\n\t\tvar table = this.tableElement,\n\t\taddedRows = [],\n\t\tpaddingAdjust = 0,\n\t\tindex = this.vDomBottom + 1,\n\t\ti = 0,\n\t\tworking = true;\n\n\t\twhile(working){\n\t\t\tlet row = rows[index],\n\t\t\trowHeight, initialized;\n\n\t\t\tif(row && i < this.vDomMaxRenderChain){\n\t\t\t\trowHeight = row.getHeight() || this.vDomRowHeight;\n\t\t\t\tinitialized = row.initialized;\n\n\t\t\t\tif(fillableSpace >= rowHeight){\n\n\t\t\t\t\tthis.styleRow(row, index);\n\t\t\t\t\ttable.appendChild(row.getElement());\n\n\t\t\t\t\tif(!row.initialized || !row.heightInitialized){\n\t\t\t\t\t\taddedRows.push(row);\n\t\t\t\t\t}\n\n\t\t\t\t\trow.initialize();\n\n\t\t\t\t\tif(!initialized){\n\t\t\t\t\t\trowHeight = row.getElement().offsetHeight;\n\n\t\t\t\t\t\tif(rowHeight > this.vDomWindowBuffer){\n\t\t\t\t\t\t\tthis.vDomWindowBuffer = rowHeight * 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfillableSpace -= rowHeight;\n\t\t\t\t\tpaddingAdjust += rowHeight;\n\n\t\t\t\t\tthis.vDomBottom++;\n\t\t\t\t\tindex++;\n\t\t\t\t\ti++;\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let row of addedRows){\n\t\t\trow.clearCellHeight();\n\t\t}\n\n\t\tthis._quickNormalizeRowHeight(addedRows);\n\n\t\tif(paddingAdjust){\n\t\t\tthis.vDomBottomPad -= paddingAdjust;\n\n\t\t\tif(this.vDomBottomPad < 0 || index == rows.length -1){\n\t\t\t\tthis.vDomBottomPad = 0;\n\t\t\t}\n\n\t\t\ttable.style.paddingBottom = this.vDomBottomPad + \"px\";\n\t\t\tthis.vDomScrollPosBottom += paddingAdjust;\n\t\t}\n\t}\n\n\t_removeBottomRow(rows, fillableSpace){\n\t\tvar removableRows = [],\n\t\tpaddingAdjust = 0,\n\t\ti = 0,\n\t\tworking = true;\n\n\t\twhile(working){\n\t\t\tlet row = rows[this.vDomBottom],\n\t\t\trowHeight;\n\n\t\t\tif(row && i < this.vDomMaxRenderChain){\n\t\t\t\trowHeight = row.getHeight() || this.vDomRowHeight;\n\n\t\t\t\tif(fillableSpace >= rowHeight){\n\t\t\t\t\tthis.vDomBottom --;\n\n\t\t\t\t\tfillableSpace -= rowHeight;\n\t\t\t\t\tpaddingAdjust += rowHeight;\n\n\t\t\t\t\tremovableRows.push(row);\n\t\t\t\t\ti++;\n\t\t\t\t}else {\n\t\t\t\t\tworking = false;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tworking = false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let row of removableRows){\n\t\t\tlet rowEl = row.getElement();\n\n\t\t\tif(rowEl.parentNode){\n\t\t\t\trowEl.parentNode.removeChild(rowEl);\n\t\t\t}\n\t\t}\n\n\t\tif(paddingAdjust){\n\t\t\tthis.vDomBottomPad += paddingAdjust;\n\n\t\t\tif(this.vDomBottomPad < 0){\n\t\t\t\tthis.vDomBottomPad = 0;\n\t\t\t}\n\n\t\t\tthis.tableElement.style.paddingBottom = this.vDomBottomPad + \"px\";\n\t\t\tthis.vDomScrollPosBottom -= paddingAdjust;\n\t\t}\n\t}\n\n\t_quickNormalizeRowHeight(rows){\n\t\tfor(let row of rows){\n\t\t\trow.calcHeight();\n\t\t}\n\n\t\tfor(let row of rows){\n\t\t\trow.setCellHeight();\n\t\t}\n\t}\n}\n\nclass RowManager extends CoreFeature{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.element = this.createHolderElement(); //containing element\n\t\tthis.tableElement = this.createTableElement(); //table element\n\t\tthis.heightFixer = this.createTableElement(); //table element\n\t\tthis.placeholder = null; //placeholder element\n\t\tthis.placeholderContents = null; //placeholder element\n\t\t\n\t\tthis.firstRender = false; //handle first render\n\t\tthis.renderMode = \"virtual\"; //current rendering mode\n\t\tthis.fixedHeight = false; //current rendering mode\n\t\t\n\t\tthis.rows = []; //hold row data objects\n\t\tthis.activeRowsPipeline = []; //hold calculation of active rows\n\t\tthis.activeRows = []; //rows currently available to on display in the table\n\t\tthis.activeRowsCount = 0; //count of active rows\n\t\t\n\t\tthis.displayRows = []; //rows currently on display in the table\n\t\tthis.displayRowsCount = 0; //count of display rows\n\t\t\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\t\t\n\t\tthis.redrawBlock = false; //prevent redraws to allow multiple data manipulations before continuing\n\t\tthis.redrawBlockRestoreConfig = false; //store latest redraw function calls for when redraw is needed\n\t\tthis.redrawBlockRenderInPosition = false; //store latest redraw function calls for when redraw is needed\n\t\t\n\t\tthis.dataPipeline = []; //hold data pipeline tasks\n\t\tthis.displayPipeline = []; //hold data display pipeline tasks\n\t\t\n\t\tthis.scrollbarWidth = 0;\n\t\t\n\t\tthis.renderer = null;\n\t}\n\t\n\t//////////////// Setup Functions /////////////////\n\t\n\tcreateHolderElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-tableholder\");\n\t\tel.setAttribute(\"tabindex\", 0);\n\t\t// el.setAttribute(\"role\", \"rowgroup\");\n\t\t\n\t\treturn el;\n\t}\n\t\n\tcreateTableElement (){\n\t\tvar el = document.createElement(\"div\");\n\t\t\n\t\tel.classList.add(\"tabulator-table\");\n\t\tel.setAttribute(\"role\", \"rowgroup\");\n\t\t\n\t\treturn el;\n\t}\n\t\n\tinitializePlaceholder(){\n\t\tvar placeholder = this.table.options.placeholder;\n\t\t\n\t\tif(typeof placeholder === \"function\"){\n\t\t\tplaceholder = placeholder.call(this.table);\n\t\t}\n\t\t\n\t\tplaceholder = this.chain(\"placeholder\", [placeholder], placeholder, placeholder) || placeholder;\n\t\t\n\t\t//configure placeholder element\n\t\tif(placeholder){\t\n\t\t\tlet el = document.createElement(\"div\");\n\t\t\tel.classList.add(\"tabulator-placeholder\");\n\t\t\t\n\t\t\tif(typeof placeholder == \"string\"){\n\t\t\t\tlet contents = document.createElement(\"div\");\n\t\t\t\tcontents.classList.add(\"tabulator-placeholder-contents\");\n\t\t\t\tcontents.innerHTML = placeholder;\n\t\t\t\t\n\t\t\t\tel.appendChild(contents);\n\t\t\t\t\n\t\t\t\tthis.placeholderContents = contents;\n\t\t\t\t\n\t\t\t}else if(typeof HTMLElement !== \"undefined\" && placeholder instanceof HTMLElement){\n\t\t\t\t\n\t\t\t\tel.appendChild(placeholder);\n\t\t\t\tthis.placeholderContents = placeholder;\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Invalid placeholder provided, must be string or HTML Element\", placeholder);\n\t\t\t\t\n\t\t\t\tthis.el = null;\n\t\t\t}\n\t\t\t\n\t\t\tthis.placeholder = el;\n\t\t}\n\t}\n\t\n\t//return containing element\n\tgetElement(){\n\t\treturn this.element;\n\t}\n\t\n\t//return table element\n\tgetTableElement(){\n\t\treturn this.tableElement;\n\t}\n\t\n\tinitialize(){\n\t\tthis.initializePlaceholder();\n\t\tthis.initializeRenderer();\n\t\t\n\t\t//initialize manager\n\t\tthis.element.appendChild(this.tableElement);\n\t\t\n\t\tthis.firstRender = true;\n\t\t\n\t\t//scroll header along with table body\n\t\tthis.element.addEventListener(\"scroll\", () => {\n\t\t\tvar left = this.element.scrollLeft,\n\t\t\tleftDir = this.scrollLeft > left,\n\t\t\ttop = this.element.scrollTop,\n\t\t\ttopDir = this.scrollTop > top;\n\t\t\t\n\t\t\t//handle horizontal scrolling\n\t\t\tif(this.scrollLeft != left){\n\t\t\t\tthis.scrollLeft = left;\n\t\t\t\t\n\t\t\t\tthis.dispatch(\"scroll-horizontal\", left, leftDir);\n\t\t\t\tthis.dispatchExternal(\"scrollHorizontal\", left, leftDir);\n\t\t\t\t\n\t\t\t\tthis._positionPlaceholder();\n\t\t\t}\n\t\t\t\n\t\t\t//handle vertical scrolling\n\t\t\tif(this.scrollTop != top){\n\t\t\t\tthis.scrollTop = top;\n\t\t\t\t\n\t\t\t\tthis.renderer.scrollRows(top, topDir);\n\t\t\t\t\n\t\t\t\tthis.dispatch(\"scroll-vertical\", top, topDir);\n\t\t\t\tthis.dispatchExternal(\"scrollVertical\", top, topDir);\n\t\t\t}\n\t\t});\n\t}\n\t\n\t////////////////// Row Manipulation //////////////////\n\tfindRow(subject){\n\t\tif(typeof subject == \"object\"){\n\t\t\tif(subject instanceof Row){\n\t\t\t\t//subject is row element\n\t\t\t\treturn subject;\n\t\t\t}else if(subject instanceof RowComponent){\n\t\t\t\t//subject is public row component\n\t\t\t\treturn subject._getSelf() || false;\n\t\t\t}else if(typeof HTMLElement !== \"undefined\" && subject instanceof HTMLElement){\n\t\t\t\t//subject is a HTML element of the row\n\t\t\t\tlet match = this.rows.find((row) => {\n\t\t\t\t\treturn row.getElement() === subject;\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\treturn match || false;\n\t\t\t}else if(subject === null){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}else if(typeof subject == \"undefined\"){\n\t\t\treturn false;\n\t\t}else {\n\t\t\t//subject should be treated as the index of the row\n\t\t\tlet match = this.rows.find((row) => {\n\t\t\t\treturn row.data[this.table.options.index] == subject;\n\t\t\t});\n\t\t\t\n\t\t\treturn match || false;\n\t\t}\n\t\t\n\t\t//catch all for any other type of input\n\t\treturn false;\n\t}\n\t\n\tgetRowFromDataObject(data){\n\t\tvar match = this.rows.find((row) => {\n\t\t\treturn row.data === data;\n\t\t});\n\t\t\n\t\treturn match || false;\n\t}\n\t\n\tgetRowFromPosition(position){\n\t\treturn this.getDisplayRows().find((row) => {\n\t\t\treturn row.getPosition() === position && row.isDisplayed();\n\t\t});\n\t}\n\t\n\tscrollToRow(row, position, ifVisible){\n\t\treturn this.renderer.scrollToRowPosition(row, position, ifVisible);\n\t}\n\t\n\t////////////////// Data Handling //////////////////\n\tsetData(data, renderInPosition, columnsChanged){\n\t\treturn new Promise((resolve, reject)=>{\n\t\t\tif(renderInPosition && this.getDisplayRows().length){\n\t\t\t\tif(this.table.options.pagination){\n\t\t\t\t\tthis._setDataActual(data, true);\n\t\t\t\t}else {\n\t\t\t\t\tthis.reRenderInPosition(() => {\n\t\t\t\t\t\tthis._setDataActual(data);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(this.table.options.autoColumns && columnsChanged && this.table.initialized){\n\t\t\t\t\tthis.table.columnManager.generateColumnsFromRowData(data);\n\t\t\t\t}\n\t\t\t\tthis.resetScroll();\n\t\t\t\t\n\t\t\t\tthis._setDataActual(data);\n\t\t\t}\n\t\t\t\n\t\t\tresolve();\n\t\t});\n\t}\n\t\n\t_setDataActual(data, renderInPosition){\n\t\tthis.dispatchExternal(\"dataProcessing\", data);\n\t\t\n\t\tthis._wipeElements();\n\t\t\n\t\tif(Array.isArray(data)){\n\t\t\tthis.dispatch(\"data-processing\", data);\n\t\t\t\n\t\t\tdata.forEach((def, i) => {\n\t\t\t\tif(def && typeof def === \"object\"){\n\t\t\t\t\tvar row = new Row(def, this);\n\t\t\t\t\tthis.rows.push(row);\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Data Loading Warning - Invalid row data detected and ignored, expecting object but received:\", def);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tthis.refreshActiveData(false, false, renderInPosition);\n\t\t\t\n\t\t\tthis.dispatch(\"data-processed\", data);\n\t\t\tthis.dispatchExternal(\"dataProcessed\", data);\n\t\t}else {\n\t\t\tconsole.error(\"Data Loading Error - Unable to process data due to invalid data type \\nExpecting: array \\nReceived: \", typeof data, \"\\nData:     \", data);\n\t\t}\n\t}\n\t\n\t_wipeElements(){\n\t\tthis.dispatch(\"rows-wipe\");\n\t\t\n\t\tthis.destroy();\n\t\t\n\t\tthis.adjustTableSize();\n\t\t\n\t\tthis.dispatch(\"rows-wiped\");\n\t}\n\t\n\tdestroy(){\n\t\tthis.rows.forEach((row) => {\n\t\t\trow.wipe();\n\t\t});\n\t\t\n\t\tthis.rows = [];\n\t\tthis.activeRows = [];\n\t\tthis.activeRowsPipeline = [];\n\t\tthis.activeRowsCount = 0;\n\t\tthis.displayRows = [];\n\t\tthis.displayRowsCount = 0;\n\t}\n\t\n\tdeleteRow(row, blockRedraw){\n\t\tvar allIndex = this.rows.indexOf(row),\n\t\tactiveIndex = this.activeRows.indexOf(row);\n\t\t\n\t\tif(activeIndex > -1){\n\t\t\tthis.activeRows.splice(activeIndex, 1);\n\t\t}\n\t\t\n\t\tif(allIndex > -1){\n\t\t\tthis.rows.splice(allIndex, 1);\n\t\t}\n\t\t\n\t\tthis.setActiveRows(this.activeRows);\n\t\t\n\t\tthis.displayRowIterator((rows) => {\n\t\t\tvar displayIndex = rows.indexOf(row);\n\t\t\t\n\t\t\tif(displayIndex > -1){\n\t\t\t\trows.splice(displayIndex, 1);\n\t\t\t}\n\t\t});\n\t\t\n\t\tif(!blockRedraw){\n\t\t\tthis.reRenderInPosition();\n\t\t}\n\t\t\n\t\tthis.regenerateRowPositions();\n\t\t\n\t\tthis.dispatchExternal(\"rowDeleted\", row.getComponent());\n\t\t\n\t\tif(!this.displayRowsCount){\n\t\t\tthis.tableEmpty();\n\t\t}\n\t\t\n\t\tif(this.subscribedExternal(\"dataChanged\")){\n\t\t\tthis.dispatchExternal(\"dataChanged\", this.getData());\n\t\t}\n\t}\n\t\n\taddRow(data, pos, index, blockRedraw){\n\t\tvar row = this.addRowActual(data, pos, index, blockRedraw);\n\t\treturn row;\n\t}\n\t\n\t//add multiple rows\n\taddRows(data, pos, index, refreshDisplayOnly){\n\t\tvar rows = [];\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tpos = this.findAddRowPos(pos);\n\t\t\t\n\t\t\tif(!Array.isArray(data)){\n\t\t\t\tdata = [data];\n\t\t\t}\n\t\t\t\n\t\t\tif((typeof index == \"undefined\" && pos) || (typeof index !== \"undefined\" && !pos)){\n\t\t\t\tdata.reverse();\n\t\t\t}\n\t\t\t\n\t\t\tdata.forEach((item, i) => {\n\t\t\t\tvar row = this.addRow(item, pos, index, true);\n\t\t\t\trows.push(row);\n\t\t\t\tthis.dispatch(\"row-added\", row, item, pos, index);\n\t\t\t});\n\t\t\t\n\t\t\tthis.refreshActiveData(refreshDisplayOnly ? \"displayPipeline\" : false, false, true);\n\t\t\t\n\t\t\tthis.regenerateRowPositions();\n\t\t\t\n\t\t\tif(this.displayRowsCount){\n\t\t\t\tthis._clearPlaceholder();\n\t\t\t}\n\t\t\t\n\t\t\tresolve(rows);\n\t\t});\n\t}\n\t\n\tfindAddRowPos(pos){\n\t\tif(typeof pos === \"undefined\"){\n\t\t\tpos = this.table.options.addRowPos;\n\t\t}\n\t\t\n\t\tif(pos === \"pos\"){\n\t\t\tpos = true;\n\t\t}\n\t\t\n\t\tif(pos === \"bottom\"){\n\t\t\tpos = false;\n\t\t}\n\t\t\n\t\treturn pos;\n\t}\n\t\n\taddRowActual(data, pos, index, blockRedraw){\n\t\tvar row = data instanceof Row ? data : new Row(data || {}, this),\n\t\ttop = this.findAddRowPos(pos),\n\t\tallIndex = -1,\n\t\tactiveIndex, chainResult;\n\t\t\n\t\tif(!index){\n\t\t\tchainResult = this.chain(\"row-adding-position\", [row, top], null, {index, top});\n\t\t\t\n\t\t\tindex = chainResult.index;\n\t\t\ttop = chainResult.top;\n\t\t}\n\t\t\n\t\tif(typeof index !== \"undefined\"){\n\t\t\tindex = this.findRow(index);\n\t\t}\n\t\t\n\t\tindex = this.chain(\"row-adding-index\", [row, index, top], null, index);\n\t\t\n\t\tif(index){\n\t\t\tallIndex = this.rows.indexOf(index);\n\t\t}\n\t\t\n\t\tif(index && allIndex > -1){\n\t\t\tactiveIndex = this.activeRows.indexOf(index);\n\t\t\t\n\t\t\tthis.displayRowIterator(function(rows){\n\t\t\t\tvar displayIndex = rows.indexOf(index);\n\t\t\t\t\n\t\t\t\tif(displayIndex > -1){\n\t\t\t\t\trows.splice((top ? displayIndex : displayIndex + 1), 0, row);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tif(activeIndex > -1){\n\t\t\t\tthis.activeRows.splice((top ? activeIndex : activeIndex + 1), 0, row);\n\t\t\t}\n\t\t\t\n\t\t\tthis.rows.splice((top ? allIndex : allIndex + 1), 0, row);\n\t\t\t\n\t\t}else {\n\t\t\t\n\t\t\tif(top){\n\t\t\t\t\n\t\t\t\tthis.displayRowIterator(function(rows){\n\t\t\t\t\trows.unshift(row);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.activeRows.unshift(row);\n\t\t\t\tthis.rows.unshift(row);\n\t\t\t}else {\n\t\t\t\tthis.displayRowIterator(function(rows){\n\t\t\t\t\trows.push(row);\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tthis.activeRows.push(row);\n\t\t\t\tthis.rows.push(row);\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.setActiveRows(this.activeRows);\n\t\t\n\t\tthis.dispatchExternal(\"rowAdded\", row.getComponent());\n\t\t\n\t\tif(this.subscribedExternal(\"dataChanged\")){\n\t\t\tthis.dispatchExternal(\"dataChanged\", this.table.rowManager.getData());\n\t\t}\n\t\t\n\t\tif(!blockRedraw){\n\t\t\tthis.reRenderInPosition();\n\t\t}\n\t\t\n\t\treturn row;\n\t}\n\t\n\tmoveRow(from, to, after){\n\t\tthis.dispatch(\"row-move\", from, to, after);\n\t\t\n\t\tthis.moveRowActual(from, to, after);\n\t\t\n\t\tthis.regenerateRowPositions();\n\t\t\n\t\tthis.dispatch(\"row-moved\", from, to, after);\n\t\tthis.dispatchExternal(\"rowMoved\", from.getComponent());\n\t}\n\t\n\tmoveRowActual(from, to, after){\n\t\tthis.moveRowInArray(this.rows, from, to, after);\n\t\tthis.moveRowInArray(this.activeRows, from, to, after);\n\t\t\n\t\tthis.displayRowIterator((rows) => {\n\t\t\tthis.moveRowInArray(rows, from, to, after);\n\t\t});\n\t\t\n\t\tthis.dispatch(\"row-moving\", from, to, after);\n\t}\n\t\n\tmoveRowInArray(rows, from, to, after){\n\t\tvar\tfromIndex, toIndex, start, end;\n\t\t\n\t\tif(from !== to){\n\t\t\t\n\t\t\tfromIndex = rows.indexOf(from);\n\t\t\t\n\t\t\tif (fromIndex > -1) {\n\t\t\t\t\n\t\t\t\trows.splice(fromIndex, 1);\n\t\t\t\t\n\t\t\t\ttoIndex = rows.indexOf(to);\n\t\t\t\t\n\t\t\t\tif (toIndex > -1) {\n\t\t\t\t\t\n\t\t\t\t\tif(after){\n\t\t\t\t\t\trows.splice(toIndex+1, 0, from);\n\t\t\t\t\t}else {\n\t\t\t\t\t\trows.splice(toIndex, 0, from);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}else {\n\t\t\t\t\trows.splice(fromIndex, 0, from);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t//restyle rows\n\t\t\tif(rows === this.getDisplayRows()){\n\t\t\t\t\n\t\t\t\tstart = fromIndex < toIndex ? fromIndex : toIndex;\n\t\t\t\tend = toIndex > fromIndex ? toIndex : fromIndex +1;\n\t\t\t\t\n\t\t\t\tfor(let i = start; i <= end; i++){\n\t\t\t\t\tif(rows[i]){\n\t\t\t\t\t\tthis.styleRow(rows[i], i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tclearData(){\n\t\tthis.setData([]);\n\t}\n\t\n\tgetRowIndex(row){\n\t\treturn this.findRowIndex(row, this.rows);\n\t}\n\t\n\tgetDisplayRowIndex(row){\n\t\tvar index = this.getDisplayRows().indexOf(row);\n\t\treturn index > -1 ? index : false;\n\t}\n\t\n\tnextDisplayRow(row, rowOnly){\n\t\tvar index = this.getDisplayRowIndex(row),\n\t\tnextRow = false;\n\t\t\n\t\t\n\t\tif(index !== false && index < this.displayRowsCount -1){\n\t\t\tnextRow = this.getDisplayRows()[index+1];\n\t\t}\n\t\t\n\t\tif(nextRow && (!(nextRow instanceof Row) || nextRow.type != \"row\")){\n\t\t\treturn this.nextDisplayRow(nextRow, rowOnly);\n\t\t}\n\t\t\n\t\treturn nextRow;\n\t}\n\t\n\tprevDisplayRow(row, rowOnly){\n\t\tvar index = this.getDisplayRowIndex(row),\n\t\tprevRow = false;\n\t\t\n\t\tif(index){\n\t\t\tprevRow = this.getDisplayRows()[index-1];\n\t\t}\n\t\t\n\t\tif(rowOnly && prevRow && (!(prevRow instanceof Row) || prevRow.type != \"row\")){\n\t\t\treturn this.prevDisplayRow(prevRow, rowOnly);\n\t\t}\n\t\t\n\t\treturn prevRow;\n\t}\n\t\n\tfindRowIndex(row, list){\n\t\tvar rowIndex;\n\t\t\n\t\trow = this.findRow(row);\n\t\t\n\t\tif(row){\n\t\t\trowIndex = list.indexOf(row);\n\t\t\t\n\t\t\tif(rowIndex > -1){\n\t\t\t\treturn rowIndex;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tgetData(active, transform){\n\t\tvar output = [],\n\t\trows = this.getRows(active);\n\t\t\n\t\trows.forEach(function(row){\n\t\t\tif(row.type == \"row\"){\n\t\t\t\toutput.push(row.getData(transform || \"data\"));\n\t\t\t}\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetComponents(active){\n\t\tvar\toutput = [],\n\t\trows = this.getRows(active);\n\t\t\n\t\trows.forEach(function(row){\n\t\t\toutput.push(row.getComponent());\n\t\t});\n\t\t\n\t\treturn output;\n\t}\n\t\n\tgetDataCount(active){\n\t\tvar rows = this.getRows(active);\n\t\t\n\t\treturn rows.length;\n\t}\n\t\n\tscrollHorizontal(left){\n\t\tthis.scrollLeft = left;\n\t\tthis.element.scrollLeft = left;\n\t\t\n\t\tthis.dispatch(\"scroll-horizontal\", left);\n\t}\n\t\n\tregisterDataPipelineHandler(handler, priority){\n\t\tif(typeof priority !== \"undefined\"){\n\t\t\tthis.dataPipeline.push({handler, priority});\n\t\t\tthis.dataPipeline.sort((a, b) => {\n\t\t\t\treturn a.priority - b.priority;\n\t\t\t});\n\t\t}else {\n\t\t\tconsole.error(\"Data pipeline handlers must have a priority in order to be registered\");\n\t\t}\n\t}\n\t\n\tregisterDisplayPipelineHandler(handler, priority){\n\t\tif(typeof priority !== \"undefined\"){\n\t\t\tthis.displayPipeline.push({handler, priority});\n\t\t\tthis.displayPipeline.sort((a, b) => {\n\t\t\t\treturn a.priority - b.priority;\n\t\t\t});\n\t\t}else {\n\t\t\tconsole.error(\"Display pipeline handlers must have a priority in order to be registered\");\n\t\t}\n\t}\n\t\n\t//set active data set\n\trefreshActiveData(handler, skipStage, renderInPosition){\n\t\tvar table = this.table,\n\t\tstage = \"\",\n\t\tindex = 0,\n\t\tcascadeOrder = [\"all\", \"dataPipeline\", \"display\", \"displayPipeline\", \"end\"];\n\t\t\n\t\tif(!this.table.destroyed){\n\t\t\tif(typeof handler === \"function\"){\n\t\t\t\tindex = this.dataPipeline.findIndex((item) => {\n\t\t\t\t\treturn item.handler === handler;\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif(index > -1){\n\t\t\t\t\tstage = \"dataPipeline\";\n\t\t\t\t\t\n\t\t\t\t\tif(skipStage){\n\t\t\t\t\t\tif(index == this.dataPipeline.length - 1){\n\t\t\t\t\t\t\tstage = \"display\";\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\tindex++;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tindex = this.displayPipeline.findIndex((item) => {\n\t\t\t\t\t\treturn item.handler === handler;\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tif(index > -1){\n\t\t\t\t\t\tstage = \"displayPipeline\";\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(skipStage){\n\t\t\t\t\t\t\tif(index == this.displayPipeline.length - 1){\n\t\t\t\t\t\t\t\tstage = \"end\";\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tindex++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.error(\"Unable to refresh data, invalid handler provided\", handler);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tstage = handler || \"all\";\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\t\n\t\t\tif(this.redrawBlock){\n\t\t\t\tif(!this.redrawBlockRestoreConfig || (this.redrawBlockRestoreConfig && ((this.redrawBlockRestoreConfig.stage === stage && index < this.redrawBlockRestoreConfig.index) || (cascadeOrder.indexOf(stage) < cascadeOrder.indexOf(this.redrawBlockRestoreConfig.stage))))){\n\t\t\t\t\tthis.redrawBlockRestoreConfig = {\n\t\t\t\t\t\thandler: handler,\n\t\t\t\t\t\tskipStage: skipStage,\n\t\t\t\t\t\trenderInPosition: renderInPosition,\n\t\t\t\t\t\tstage:stage,\n\t\t\t\t\t\tindex:index,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn;\n\t\t\t}else {\n\t\t\t\tif(Helpers.elVisible(this.element)){\n\t\t\t\t\tif(renderInPosition){\n\t\t\t\t\t\tthis.reRenderInPosition(this.refreshPipelines.bind(this, handler, stage, index, renderInPosition));\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.refreshPipelines(handler, stage, index, renderInPosition);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(!handler){\n\t\t\t\t\t\t\tthis.table.columnManager.renderer.renderColumns();\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis.renderTable();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(table.options.layoutColumnsOnNewData){\n\t\t\t\t\t\t\tthis.table.columnManager.redraw(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tthis.refreshPipelines(handler, stage, index, renderInPosition);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.dispatch(\"data-refreshed\");\n\t\t\t}\n\t\t}\n\t}\n\t\n\trefreshPipelines(handler, stage, index, renderInPosition){\n\t\tthis.dispatch(\"data-refreshing\");\n\t\t\n\t\tif(!handler || !this.activeRowsPipeline[0]){\n\t\t\tthis.activeRowsPipeline[0] = this.rows.slice(0);\n\t\t}\n\t\t\n\t\t//cascade through data refresh stages\n\t\tswitch(stage){\n\t\t\tcase \"all\":\n\t\t\t//handle case where all data needs refreshing\n\t\t\t\n\t\t\tcase \"dataPipeline\":\n\t\t\t\tfor(let i = index; i < this.dataPipeline.length; i++){\n\t\t\t\t\tlet result = this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0));\n\t\t\t\t\n\t\t\t\t\tthis.activeRowsPipeline[i + 1] = result || this.activeRowsPipeline[i].slice(0);\n\t\t\t\t}\n\t\t\t\n\t\t\t\tthis.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]);\n\t\t\t\n\t\t\tcase \"display\":\n\t\t\t\tindex = 0;\n\t\t\t\tthis.resetDisplayRows();\n\t\t\t\n\t\t\tcase \"displayPipeline\":\n\t\t\t\tfor(let i = index; i < this.displayPipeline.length; i++){\n\t\t\t\t\tlet result = this.displayPipeline[i].handler((i ? this.getDisplayRows(i - 1) : this.activeRows).slice(0), renderInPosition);\n\t\t\t\t\n\t\t\t\t\tthis.setDisplayRows(result || this.getDisplayRows(i - 1).slice(0), i);\n\t\t\t\t}\n\t\t\t\n\t\t\tcase \"end\":\n\t\t\t//case to handle scenario when trying to skip past end stage\n\t\t\t\tthis.regenerateRowPositions();\n\t\t}\n\t\t\n\t\tif(this.getDisplayRows().length){\n\t\t\tthis._clearPlaceholder();\n\t\t}\n\t}\n\t\n\t//regenerate row positions\n\tregenerateRowPositions(){\n\t\tvar rows = this.getDisplayRows();\n\t\tvar index = 1;\n\t\t\n\t\trows.forEach((row) => {\n\t\t\tif (row.type === \"row\"){\n\t\t\t\trow.setPosition(index);\n\t\t\t\tindex++;\n\t\t\t}\n\t\t});\n\t}\n\t\n\tsetActiveRows(activeRows){\n\t\tthis.activeRows = this.activeRows = Object.assign([], activeRows);\n\t\tthis.activeRowsCount = this.activeRows.length;\n\t}\n\t\n\t//reset display rows array\n\tresetDisplayRows(){\n\t\tthis.displayRows = [];\n\t\t\n\t\tthis.displayRows.push(this.activeRows.slice(0));\n\t\t\n\t\tthis.displayRowsCount = this.displayRows[0].length;\n\t}\n\t\n\t//set display row pipeline data\n\tsetDisplayRows(displayRows, index){\n\t\tthis.displayRows[index] = displayRows;\n\t\t\n\t\tif(index == this.displayRows.length -1){\n\t\t\tthis.displayRowsCount = this.displayRows[this.displayRows.length -1].length;\n\t\t}\n\t}\n\t\n\tgetDisplayRows(index){\n\t\tif(typeof index == \"undefined\"){\n\t\t\treturn this.displayRows.length ? this.displayRows[this.displayRows.length -1] : [];\n\t\t}else {\n\t\t\treturn this.displayRows[index] || [];\n\t\t}\n\t}\n\t\n\tgetVisibleRows(chain, viewable){\n\t\tvar rows =  Object.assign([], this.renderer.visibleRows(!viewable));\n\t\t\n\t\tif(chain){\n\t\t\trows = this.chain(\"rows-visible\", [viewable], rows, rows);\n\t\t}\n\t\t\n\t\treturn rows;\n\t}\n\t\n\t//repeat action across display rows\n\tdisplayRowIterator(callback){\n\t\tthis.activeRowsPipeline.forEach(callback);\n\t\tthis.displayRows.forEach(callback);\n\t\t\n\t\tthis.displayRowsCount = this.displayRows[this.displayRows.length -1].length;\n\t}\n\t\n\t//return only actual rows (not group headers etc)\n\tgetRows(type){\n\t\tvar rows = [];\n\t\t\n\t\tswitch(type){\n\t\t\tcase \"active\":\n\t\t\t\trows = this.activeRows;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"display\":\n\t\t\t\trows = this.table.rowManager.getDisplayRows();\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"visible\":\n\t\t\t\trows = this.getVisibleRows(false, true);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tdefault:\n\t\t\t\trows = this.chain(\"rows-retrieve\", type, null, this.rows) || this.rows;\n\t\t}\n\t\t\n\t\treturn rows;\n\t}\n\t\n\t///////////////// Table Rendering /////////////////\n\t//trigger rerender of table in current position\n\treRenderInPosition(callback){\n\t\tif(this.redrawBlock){\n\t\t\tif(callback){\n\t\t\t\tcallback();\n\t\t\t}else {\n\t\t\t\tthis.redrawBlockRenderInPosition = true;\n\t\t\t}\n\t\t}else {\n\t\t\tthis.dispatchExternal(\"renderStarted\");\n\t\t\t\n\t\t\tthis.renderer.rerenderRows(callback);\n\t\t\t\n\t\t\tif(!this.fixedHeight){\n\t\t\t\tthis.adjustTableSize();\n\t\t\t}\n\t\t\t\n\t\t\tthis.scrollBarCheck();\n\t\t\t\n\t\t\tthis.dispatchExternal(\"renderComplete\");\n\t\t}\n\t}\n\t\n\tscrollBarCheck(){\n\t\tvar scrollbarWidth = 0;\n\t\t\n\t\t//adjust for vertical scrollbar moving table when present\n\t\tif(this.element.scrollHeight > this.element.clientHeight){\n\t\t\tscrollbarWidth = this.element.offsetWidth - this.element.clientWidth;\n\t\t}\n\t\t\n\t\tif(scrollbarWidth !== this.scrollbarWidth){\n\t\t\tthis.scrollbarWidth = scrollbarWidth;\n\t\t\tthis.dispatch(\"scrollbar-vertical\", scrollbarWidth);\n\t\t}\n\t}\n\t\n\tinitializeRenderer(){\n\t\tvar renderClass;\n\t\t\n\t\tvar renderers = {\n\t\t\t\"virtual\": VirtualDomVertical,\n\t\t\t\"basic\": BasicVertical,\n\t\t};\n\t\t\n\t\tif(typeof this.table.options.renderVertical === \"string\"){\n\t\t\trenderClass = renderers[this.table.options.renderVertical];\n\t\t}else {\n\t\t\trenderClass = this.table.options.renderVertical;\n\t\t}\n\t\t\n\t\tif(renderClass){\n\t\t\tthis.renderMode = this.table.options.renderVertical;\n\t\t\t\n\t\t\tthis.renderer = new renderClass(this.table, this.element, this.tableElement);\n\t\t\tthis.renderer.initialize();\n\t\t\t\n\t\t\tif((this.table.element.clientHeight || this.table.options.height) && !(this.table.options.minHeight && this.table.options.maxHeight)){\n\t\t\t\tthis.fixedHeight = true;\n\t\t\t}else {\n\t\t\t\tthis.fixedHeight = false;\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.error(\"Unable to find matching renderer:\", this.table.options.renderVertical);\n\t\t}\n\t}\n\t\n\tgetRenderMode(){\n\t\treturn this.renderMode;\n\t}\n\t\n\trenderTable(){\n\t\tthis.dispatchExternal(\"renderStarted\");\n\t\t\n\t\tthis.element.scrollTop = 0;\n\t\t\n\t\tthis._clearTable();\n\t\t\n\t\tif(this.displayRowsCount){\n\t\t\tthis.renderer.renderRows();\n\t\t\t\n\t\t\tif(this.firstRender){\n\t\t\t\tthis.firstRender = false;\n\t\t\t\t\n\t\t\t\tif(!this.fixedHeight){\n\t\t\t\t\tthis.adjustTableSize();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.layoutRefresh(true);\n\t\t\t}\n\t\t}else {\n\t\t\tthis.renderEmptyScroll();\n\t\t}\n\t\t\n\t\tif(!this.fixedHeight){\n\t\t\tthis.adjustTableSize();\n\t\t}\n\t\t\n\t\tthis.dispatch(\"table-layout\");\n\t\t\n\t\tif(!this.displayRowsCount){\n\t\t\tthis._showPlaceholder();\n\t\t}\n\t\t\n\t\tthis.scrollBarCheck();\n\t\t\n\t\tthis.dispatchExternal(\"renderComplete\");\n\t}\n\t\n\t//show scrollbars on empty table div\n\trenderEmptyScroll(){\n\t\tif(this.placeholder){\n\t\t\tthis.tableElement.style.display = \"none\";\n\t\t}else {\n\t\t\tthis.tableElement.style.minWidth = this.table.columnManager.getWidth() + \"px\";\n\t\t\t// this.tableElement.style.minHeight = \"1px\";\n\t\t\t// this.tableElement.style.visibility = \"hidden\";\n\t\t}\n\t}\n\t\n\t_clearTable(){\t\n\t\tthis._clearPlaceholder();\n\t\t\n\t\tthis.scrollTop = 0;\n\t\tthis.scrollLeft = 0;\n\t\t\n\t\tthis.renderer.clearRows();\n\t}\n\t\n\ttableEmpty(){\n\t\tthis.renderEmptyScroll();\n\t\tthis._showPlaceholder();\n\t}\n\n\tcheckPlaceholder(){\n\t\tif(this.displayRowsCount){\n\t\t\tthis._clearPlaceholder();\n\t\t}else {\n\t\t\tthis.tableEmpty();\n\t\t}\n\t}\n\t\n\t_showPlaceholder(){\n\t\tif(this.placeholder){\n\t\t\tif(this.placeholder && this.placeholder.parentNode){\n\t\t\t\tthis.placeholder.parentNode.removeChild(this.placeholder);\n\t\t\t}\n\t\t\t\n\t\t\tthis.initializePlaceholder();\n\t\t\t\n\t\t\tthis.placeholder.setAttribute(\"tabulator-render-mode\", this.renderMode);\n\t\t\t\n\t\t\tthis.getElement().appendChild(this.placeholder);\n\t\t\tthis._positionPlaceholder();\n\n\t\t\tthis.adjustTableSize();\n\t\t}\n\t}\n\t\n\t_clearPlaceholder(){\n\t\tif(this.placeholder && this.placeholder.parentNode){\n\t\t\tthis.placeholder.parentNode.removeChild(this.placeholder);\n\t\t}\n\t\t\n\t\t// clear empty table placeholder min\n\t\tthis.tableElement.style.minWidth = \"\";\n\t\tthis.tableElement.style.display = \"\";\n\t}\n\t\n\t_positionPlaceholder(){\n\t\tif(this.placeholder && this.placeholder.parentNode){\n\t\t\tthis.placeholder.style.width = this.table.columnManager.getWidth() + \"px\";\n\t\t\tthis.placeholderContents.style.width = this.table.rowManager.element.clientWidth + \"px\";\n\t\t\tthis.placeholderContents.style.marginLeft = this.scrollLeft + \"px\";\n\t\t}\n\t}\n\t\n\tstyleRow(row, index){\n\t\tvar rowEl = row.getElement();\n\t\t\n\t\tif(index % 2){\n\t\t\trowEl.classList.add(\"tabulator-row-even\");\n\t\t\trowEl.classList.remove(\"tabulator-row-odd\");\n\t\t}else {\n\t\t\trowEl.classList.add(\"tabulator-row-odd\");\n\t\t\trowEl.classList.remove(\"tabulator-row-even\");\n\t\t}\n\t}\n\t\n\t//normalize height of active rows\n\tnormalizeHeight(){\n\t\tthis.activeRows.forEach(function(row){\n\t\t\trow.normalizeHeight();\n\t\t});\n\t}\n\t\n\t//adjust the height of the table holder to fit in the Tabulator element\n\tadjustTableSize(){\n\t\tlet initialHeight = this.element.clientHeight, minHeight;\n\t\tlet resized = false;\n\t\t\n\t\tif(this.renderer.verticalFillMode === \"fill\"){\n\t\t\tlet otherHeight =  Math.floor(this.table.columnManager.getElement().getBoundingClientRect().height + (this.table.footerManager && this.table.footerManager.active && !this.table.footerManager.external ? this.table.footerManager.getElement().getBoundingClientRect().height : 0));\n\t\t\t\n\t\t\tif(this.fixedHeight){\n\t\t\t\tminHeight = isNaN(this.table.options.minHeight) ? this.table.options.minHeight : this.table.options.minHeight + \"px\";\n\t\t\t\t\n\t\t\t\tconst height = \"calc(100% - \" + otherHeight + \"px)\";\n\t\t\t\tthis.element.style.minHeight = minHeight || \"calc(100% - \" + otherHeight + \"px)\";\n\t\t\t\tthis.element.style.height = height;\n\t\t\t\tthis.element.style.maxHeight = height;\n\t\t\t} else {\n\t\t\t\tthis.element.style.height = \"\";\n\t\t\t\tthis.element.style.height =\n\t\t\t\tthis.table.element.clientHeight - otherHeight + \"px\";\n\t\t\t\tthis.element.scrollTop = this.scrollTop;\n\t\t\t}\n\t\t\t\n\t\t\tthis.renderer.resize();\n\t\t\t\n\t\t\t//check if the table has changed size when dealing with variable height tables\n\t\t\tif(!this.fixedHeight && initialHeight != this.element.clientHeight){\n\t\t\t\tresized = true;\n\t\t\t\tif(this.subscribed(\"table-resize\")){\n\t\t\t\t\tthis.dispatch(\"table-resize\");\n\t\t\t\t}else {\n\t\t\t\t\tthis.redraw();\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tthis.scrollBarCheck();\n\t\t}\n\t\t\n\t\tthis._positionPlaceholder();\n\t\treturn resized;\n\t}\n\t\n\t//reinitialize all rows\n\treinitialize(){\n\t\tthis.rows.forEach(function(row){\n\t\t\trow.reinitialize(true);\n\t\t});\n\t}\n\t\n\t//prevent table from being redrawn\n\tblockRedraw (){\n\t\tthis.redrawBlock = true;\n\t\tthis.redrawBlockRestoreConfig = false;\n\t}\n\t\n\t//restore table redrawing\n\trestoreRedraw (){\n\t\tthis.redrawBlock = false;\n\t\t\n\t\tif(this.redrawBlockRestoreConfig){\n\t\t\tthis.refreshActiveData(this.redrawBlockRestoreConfig.handler, this.redrawBlockRestoreConfig.skipStage, this.redrawBlockRestoreConfig.renderInPosition);\n\t\t\t\n\t\t\tthis.redrawBlockRestoreConfig = false;\n\t\t}else {\n\t\t\tif(this.redrawBlockRenderInPosition){\n\t\t\t\tthis.reRenderInPosition();\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.redrawBlockRenderInPosition = false;\n\t}\n\t\n\t//redraw table\n\tredraw (force){\n\t\tthis.adjustTableSize();\n\t\tthis.table.tableWidth = this.table.element.clientWidth;\n\t\t\n\t\tif(!force){\t\n\t\t\tthis.reRenderInPosition();\n\t\t\tthis.scrollHorizontal(this.scrollLeft);\n\t\t}else {\n\t\t\tthis.renderTable();\n\t\t}\n\t}\n\t\n\tresetScroll(){\n\t\tthis.element.scrollLeft = 0;\n\t\tthis.element.scrollTop = 0;\n\t\t\n\t\tif(this.table.browser === \"ie\"){\n\t\t\tvar event = document.createEvent(\"Event\");\n\t\t\tevent.initEvent(\"scroll\", false, true);\n\t\t\tthis.element.dispatchEvent(event);\n\t\t}else {\n\t\t\tthis.element.dispatchEvent(new Event('scroll'));\n\t\t}\n\t}\n}\n\nclass FooterManager extends CoreFeature{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.active = false;\n\t\tthis.element = this.createElement(); //containing element\n\t\tthis.containerElement = this.createContainerElement(); //containing element\n\t\tthis.external = false;\n\t}\n\n\tinitialize(){\n\t\tthis.initializeElement();\n\t}\n\n\tcreateElement(){\n\t\tvar el = document.createElement(\"div\");\n\n\t\tel.classList.add(\"tabulator-footer\");\n\n\t\treturn el;\n\t}\n\n\t\n\tcreateContainerElement(){\n\t\tvar el = document.createElement(\"div\");\n\n\t\tel.classList.add(\"tabulator-footer-contents\");\n\n\t\tthis.element.appendChild(el);\n\n\t\treturn el;\n\t}\n\n\tinitializeElement(){\n\t\tif(this.table.options.footerElement){\n\n\t\t\tswitch(typeof this.table.options.footerElement){\n\t\t\t\tcase \"string\":\n\t\t\t\t\tif(this.table.options.footerElement[0] === \"<\"){\n\t\t\t\t\t\tthis.containerElement.innerHTML = this.table.options.footerElement;\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.external = true;\n\t\t\t\t\t\tthis.containerElement = document.querySelector(this.table.options.footerElement);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tthis.element = this.table.options.footerElement;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tgetElement(){\n\t\treturn this.element;\n\t}\n\n\tappend(element){\n\t\tthis.activate();\n\n\t\tthis.containerElement.appendChild(element);\n\t\tthis.table.rowManager.adjustTableSize();\n\t}\n\n\tprepend(element){\n\t\tthis.activate();\n\n\t\tthis.element.insertBefore(element, this.element.firstChild);\n\t\tthis.table.rowManager.adjustTableSize();\n\t}\n\n\tremove(element){\n\t\telement.parentNode.removeChild(element);\n\t\tthis.deactivate();\n\t}\n\n\tdeactivate(force){\n\t\tif(!this.element.firstChild || force){\n\t\t\tif(!this.external){\n\t\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t\t}\n\t\t\tthis.active = false;\n\t\t}\n\t}\n\n\tactivate(){\n\t\tif(!this.active){\n\t\t\tthis.active = true;\n\t\t\tif(!this.external){\n\t\t\t\tthis.table.element.appendChild(this.getElement());\n\t\t\t\tthis.table.element.style.display = '';\n\t\t\t}\n\t\t}\n\t}\n\n\tredraw(){\n\t\tthis.dispatch(\"footer-redraw\");\n\t}\n}\n\nclass InteractionManager extends CoreFeature {\n\t\n\tconstructor (table){\n\t\tsuper(table);\n\t\t\n\t\tthis.el = null;\n\t\t\n\t\tthis.abortClasses = [\"tabulator-headers\", \"tabulator-table\"];\n\t\t\n\t\tthis.previousTargets = {};\n\t\t\n\t\tthis.listeners = [\n\t\t\t\"click\",\n\t\t\t\"dblclick\",\n\t\t\t\"contextmenu\",\n\t\t\t\"mouseenter\",\n\t\t\t\"mouseleave\",\n\t\t\t\"mouseover\",\n\t\t\t\"mouseout\",\n\t\t\t\"mousemove\",\n\t\t\t\"mouseup\",\n\t\t\t\"mousedown\",\n\t\t\t\"touchstart\",\n\t\t\t\"touchend\",\n\t\t];\n\t\t\n\t\tthis.componentMap = {\n\t\t\t\"tabulator-cell\":\"cell\",\n\t\t\t\"tabulator-row\":\"row\",\n\t\t\t\"tabulator-group\":\"group\",\n\t\t\t\"tabulator-col\":\"column\",\n\t\t};\n\t\t\n\t\tthis.pseudoTrackers = {\n\t\t\t\"row\":{\n\t\t\t\tsubscriber:null,\n\t\t\t\ttarget:null,\n\t\t\t},\n\t\t\t\"cell\":{\n\t\t\t\tsubscriber:null,\n\t\t\t\ttarget:null,\n\t\t\t},\n\t\t\t\"group\":{\n\t\t\t\tsubscriber:null,\n\t\t\t\ttarget:null,\n\t\t\t},\n\t\t\t\"column\":{\n\t\t\t\tsubscriber:null,\n\t\t\t\ttarget:null,\n\t\t\t},\n\t\t};\n\t\t\n\t\tthis.pseudoTracking = false;\n\t}\n\t\n\tinitialize(){\n\t\tthis.el = this.table.element;\n\t\t\n\t\tthis.buildListenerMap();\n\t\tthis.bindSubscriptionWatchers();\n\t}\n\t\n\tbuildListenerMap(){\n\t\tvar listenerMap = {};\n\t\t\n\t\tthis.listeners.forEach((listener) => {\n\t\t\tlistenerMap[listener] = {\n\t\t\t\thandler:null,\n\t\t\t\tcomponents:[],\n\t\t\t};\n\t\t});\n\t\t\n\t\tthis.listeners = listenerMap;\n\t}\n\t\n\tbindPseudoEvents(){\n\t\tObject.keys(this.pseudoTrackers).forEach((key) => {\n\t\t\tthis.pseudoTrackers[key].subscriber = this.pseudoMouseEnter.bind(this, key);\n\t\t\tthis.subscribe(key + \"-mouseover\", this.pseudoTrackers[key].subscriber);\n\t\t});\n\t\t\n\t\tthis.pseudoTracking = true;\n\t}\n\t\n\tpseudoMouseEnter(key, e, target){\n\t\tif(this.pseudoTrackers[key].target !== target){\n\t\t\t\n\t\t\tif(this.pseudoTrackers[key].target){\n\t\t\t\tthis.dispatch(key + \"-mouseleave\", e, this.pseudoTrackers[key].target);\n\t\t\t}\n\t\t\t\n\t\t\tthis.pseudoMouseLeave(key, e);\n\t\t\t\n\t\t\tthis.pseudoTrackers[key].target = target;\n\t\t\t\n\t\t\tthis.dispatch(key + \"-mouseenter\", e, target);\n\t\t}\n\t}\n\t\n\tpseudoMouseLeave(key, e){\n\t\tvar leaveList = Object.keys(this.pseudoTrackers),\n\t\tlinkedKeys = {\n\t\t\t\"row\":[\"cell\"],\n\t\t\t\"cell\":[\"row\"],\n\t\t};\n\t\t\n\t\tleaveList = leaveList.filter((item) => {\n\t\t\tvar links = linkedKeys[key];\n\t\t\treturn item !== key && (!links || (links && !links.includes(item)));\n\t\t});\n\t\t\n\t\t\n\t\tleaveList.forEach((key) => {\n\t\t\tvar target = this.pseudoTrackers[key].target;\n\t\t\t\n\t\t\tif(this.pseudoTrackers[key].target){\n\t\t\t\tthis.dispatch(key + \"-mouseleave\", e, target);\n\t\t\t\t\n\t\t\t\tthis.pseudoTrackers[key].target = null;\n\t\t\t}\n\t\t});\n\t}\n\t\n\t\n\tbindSubscriptionWatchers(){\n\t\tvar listeners = Object.keys(this.listeners),\n\t\tcomponents = Object.values(this.componentMap);\n\t\t\n\t\tfor(let comp of components){\n\t\t\tfor(let listener of listeners){\n\t\t\t\tlet key = comp + \"-\" + listener;\n\t\t\t\t\n\t\t\t\tthis.subscriptionChange(key, this.subscriptionChanged.bind(this, comp, listener));\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.subscribe(\"table-destroy\", this.clearWatchers.bind(this));\n\t}\n\t\n\tsubscriptionChanged(component, key, added){\n\t\tvar listener = this.listeners[key].components,\n\t\tindex = listener.indexOf(component),\n\t\tchanged = false;\n\t\t\n\t\tif(added){\n\t\t\tif(index === -1){\n\t\t\t\tlistener.push(component);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}else {\n\t\t\tif(!this.subscribed(component + \"-\" + key)){\n\t\t\t\tif(index > -1){\n\t\t\t\t\tlistener.splice(index, 1);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif((key === \"mouseenter\" || key === \"mouseleave\") && !this.pseudoTracking){\n\t\t\tthis.bindPseudoEvents();\n\t\t}\n\t\t\n\t\tif(changed){\n\t\t\tthis.updateEventListeners();\n\t\t}\n\t}\n\t\n\tupdateEventListeners(){\n\t\tfor(let key in this.listeners){\n\t\t\tlet listener = this.listeners[key];\n\t\t\t\n\t\t\tif(listener.components.length){\n\t\t\t\tif(!listener.handler){\n\t\t\t\t\tlistener.handler = this.track.bind(this, key);\n\t\t\t\t\tthis.el.addEventListener(key, listener.handler);\n\t\t\t\t\t// this.el.addEventListener(key, listener.handler, {passive: true})\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tif(listener.handler){\n\t\t\t\t\tthis.el.removeEventListener(key, listener.handler);\n\t\t\t\t\tlistener.handler = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\ttrack(type, e){\n\t\tvar path = (e.composedPath && e.composedPath()) || e.path;\n\t\t\n\t\tvar targets = this.findTargets(path);\n\t\ttargets = this.bindComponents(type, targets);\n\t\t\n\t\tthis.triggerEvents(type, e, targets);\n\t\t\n\t\tif(this.pseudoTracking && (type == \"mouseover\" || type == \"mouseleave\") && !Object.keys(targets).length){\n\t\t\tthis.pseudoMouseLeave(\"none\", e);\n\t\t}\n\t}\n\t\n\tfindTargets(path){\n\t\tvar targets = {};\n\t\t\n\t\tlet componentMap = Object.keys(this.componentMap);\n\t\t\n\t\tfor (let el of path) {\n\t\t\tlet classList = el.classList ? [...el.classList] : [];\n\t\t\t\n\t\t\tlet abort = classList.filter((item) => {\n\t\t\t\treturn this.abortClasses.includes(item);\n\t\t\t});\n\t\t\t\n\t\t\tif(abort.length){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tlet elTargets = classList.filter((item) => {\n\t\t\t\treturn componentMap.includes(item);\n\t\t\t});\n\t\t\t\n\t\t\tfor (let target of elTargets) {\n\t\t\t\tif(!targets[this.componentMap[target]]){\n\t\t\t\t\ttargets[this.componentMap[target]] = el;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(targets.group && targets.group === targets.row){\n\t\t\tdelete targets.row;\n\t\t}\n\n\t\treturn targets;\n\t}\n\t\n\tbindComponents(type, targets){\n\t\t//ensure row component is looked up before cell\n\t\tvar keys = Object.keys(targets).reverse(),\n\t\tlistener = this.listeners[type],\n\t\tmatches = {},\n\t\ttargetMatches = {};\n\t\t\n\t\tfor(let key of keys){\n\t\t\tlet component,\n\t\t\ttarget = targets[key],\n\t\t\tpreviousTarget = this.previousTargets[key];\n\t\t\t\n\t\t\tif(previousTarget && previousTarget.target === target){\n\t\t\t\tcomponent = previousTarget.component;\n\t\t\t}else {\n\t\t\t\tswitch(key){\n\t\t\t\t\tcase \"row\":\n\t\t\t\t\tcase \"group\":\n\t\t\t\t\t\tif(listener.components.includes(\"row\") || listener.components.includes(\"cell\") || listener.components.includes(\"group\")){\n\t\t\t\t\t\t\tlet rows = this.table.rowManager.getVisibleRows(true);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tcomponent = rows.find((row) => {\n\t\t\t\t\t\t\t\treturn row.getElement() === target;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(targets[\"row\"] && targets[\"row\"].parentNode && targets[\"row\"].parentNode.closest(\".tabulator-row\")){\n\t\t\t\t\t\t\t\ttargets[key] = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"column\":\n\t\t\t\t\t\tif(listener.components.includes(\"column\")){\n\t\t\t\t\t\t\tcomponent = this.table.columnManager.findColumn(target);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tcase \"cell\":\n\t\t\t\t\t\tif(listener.components.includes(\"cell\")){\n\t\t\t\t\t\t\tif(matches[\"row\"] instanceof Row){\n\t\t\t\t\t\t\t\tcomponent = matches[\"row\"].findCell(target);\n\t\t\t\t\t\t\t}else {\t\n\t\t\t\t\t\t\t\tif(targets[\"row\"]){\n\t\t\t\t\t\t\t\t\tconsole.warn(\"Event Target Lookup Error - The row this cell is attached to cannot be found, has the table been reinitialized without being destroyed first?\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif(component){\n\t\t\t\tmatches[key] = component;\n\t\t\t\ttargetMatches[key] = {\n\t\t\t\t\ttarget:target,\n\t\t\t\t\tcomponent:component,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.previousTargets = targetMatches;\n\t\t\n\t\treturn matches;\n\t}\n\t\n\ttriggerEvents(type, e, targets){\n\t\tvar listener = this.listeners[type];\n\n\t\tfor(let key in targets){\n\t\t\tif(targets[key] && listener.components.includes(key)){\n\t\t\t\tthis.dispatch(key + \"-\" + type, e, targets[key]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tclearWatchers(){\n\t\tfor(let key in this.listeners){\n\t\t\tlet listener = this.listeners[key];\n\t\t\t\n\t\t\tif(listener.handler){\n\t\t\t\tthis.el.removeEventListener(key, listener.handler);\n\t\t\t\tlistener.handler = null;\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass ComponentFunctionBinder{\n\n\tconstructor(table){\n\t\tthis.table = table;\n\n\t\tthis.bindings = {};\n\t}\n\n\tbind(type, funcName, handler){\n\t\tif(!this.bindings[type]){\n\t\t\tthis.bindings[type] = {};\n\t\t}\n\n\t\tif(this.bindings[type][funcName]){\n\t\t\tconsole.warn(\"Unable to bind component handler, a matching function name is already bound\", type, funcName, handler);\n\t\t}else {\n\t\t\tthis.bindings[type][funcName] = handler;\n\t\t}\n\t}\n\n\thandle(type, component, name){\n\t\tif(this.bindings[type] && this.bindings[type][name] && typeof this.bindings[type][name].bind === 'function'){\n\t\t\treturn this.bindings[type][name].bind(null, component);\n\t\t}else {\n\t\t\tif(name !== \"then\" && typeof name === \"string\" && !name.startsWith(\"_\")){\n\t\t\t\tif(this.table.options.debugInvalidComponentFuncs){\n\t\t\t\t\tconsole.error(\"The \" + type + \" component does not have a \" + name + \" function, have you checked that you have the correct Tabulator module installed?\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass DataLoader extends CoreFeature{\n\tconstructor(table){\n\t\tsuper(table);\n\t\t\n\t\tthis.requestOrder = 0; //prevent requests coming out of sequence if overridden by another load request\n\t\tthis.loading = false;\n\t}\n\t\n\tinitialize(){}\n\t\n\tload(data, params, config, replace, silent, columnsChanged){\n\t\tvar requestNo = ++this.requestOrder;\n\n\t\tif(this.table.destroyed){\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t\n\t\tthis.dispatchExternal(\"dataLoading\", data);\n\t\t\n\t\t//parse json data to array\n\t\tif (data && (data.indexOf(\"{\") == 0 || data.indexOf(\"[\") == 0)){\n\t\t\tdata = JSON.parse(data);\n\t\t}\n\t\t\n\t\tif(this.confirm(\"data-loading\", [data, params, config, silent])){\n\t\t\tthis.loading = true;\n\t\t\t\n\t\t\tif(!silent){\n\t\t\t\tthis.alertLoader();\n\t\t\t}\n\t\t\t\n\t\t\t//get params for request\n\t\t\tparams = this.chain(\"data-params\", [data, config, silent], params || {}, params || {});\n\t\t\t\n\t\t\tparams = this.mapParams(params, this.table.options.dataSendParams);\n\t\t\t\n\t\t\tvar result = this.chain(\"data-load\", [data, params, config, silent], false, Promise.resolve([]));\n\t\t\t\n\t\t\treturn result.then((response) => {\n\t\t\t\tif(!this.table.destroyed){\n\t\t\t\t\tif(!Array.isArray(response) && typeof response == \"object\"){\n\t\t\t\t\t\tresponse = this.mapParams(response, this.objectInvert(this.table.options.dataReceiveParams));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar rowData = this.chain(\"data-loaded\", response, null, response);\n\t\t\t\t\t\n\t\t\t\t\tif(requestNo == this.requestOrder){\n\t\t\t\t\t\tthis.clearAlert();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif(rowData !== false){\n\t\t\t\t\t\t\tthis.dispatchExternal(\"dataLoaded\", rowData);\n\t\t\t\t\t\t\tthis.table.rowManager.setData(rowData,  replace, typeof columnsChanged === \"undefined\" ? !replace : columnsChanged);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made\");\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Data Load Response Blocked - Table has been destroyed\");\n\t\t\t\t}\n\t\t\t}).catch((error) => {\n\t\t\t\tconsole.error(\"Data Load Error: \", error);\n\t\t\t\tthis.dispatchExternal(\"dataLoadError\", error);\n\t\t\t\t\n\t\t\t\tif(!silent){\n\t\t\t\t\tthis.alertError();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.clearAlert();\n\t\t\t\t}, this.table.options.dataLoaderErrorTimeout);\n\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tthis.loading = false;\n\t\t\t\t});\n\t\t}else {\n\t\t\tthis.dispatchExternal(\"dataLoaded\", data);\n\t\t\t\n\t\t\tif(!data){\n\t\t\t\tdata = [];\n\t\t\t}\n\t\t\t\n\t\t\tthis.table.rowManager.setData(data, replace, typeof columnsChanged === \"undefined\" ? !replace : columnsChanged);\n\t\t\treturn Promise.resolve();\n\t\t}\n\t}\n\t\n\tmapParams(params, map){\n\t\tvar output = {};\n\t\t\n\t\tfor(let key in params){\n\t\t\toutput[map.hasOwnProperty(key) ? map[key] : key] = params[key];\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tobjectInvert(obj){\n\t\tvar output = {};\n\t\t\n\t\tfor(let key in obj){\n\t\t\toutput[obj[key]] = key;\n\t\t}\n\t\t\n\t\treturn output;\n\t}\n\t\n\tblockActiveLoad(){\n\t\tthis.requestOrder++;\n\t}\n\t\n\talertLoader(){\n\t\tvar shouldLoad = typeof this.table.options.dataLoader === \"function\" ? this.table.options.dataLoader() : this.table.options.dataLoader;\n\t\t\n\t\tif(shouldLoad){\n\t\t\tthis.table.alertManager.alert(this.table.options.dataLoaderLoading || this.langText(\"data|loading\"));\n\t\t}\n\t}\n\t\n\talertError(){\n\t\tthis.table.alertManager.alert(this.table.options.dataLoaderError || this.langText(\"data|error\"), \"error\");\n\t}\n\t\n\tclearAlert(){\n\t\tthis.table.alertManager.clear();\n\t}\n}\n\nclass ExternalEventBus {\n\n\tconstructor(table, optionsList, debug){\n\t\tthis.table = table;\n\t\tthis.events = {};\n\t\tthis.optionsList = optionsList || {};\n\t\tthis.subscriptionNotifiers = {};\n\n\t\tthis.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this);\n\t\tthis.debug = debug;\n\t}\n\n\tsubscriptionChange(key, callback){\n\t\tif(!this.subscriptionNotifiers[key]){\n\t\t\tthis.subscriptionNotifiers[key] = [];\n\t\t}\n\n\t\tthis.subscriptionNotifiers[key].push(callback);\n\n\t\tif(this.subscribed(key)){\n\t\t\tthis._notifySubscriptionChange(key, true);\n\t\t}\n\t}\n\n\tsubscribe(key, callback){\n\t\tif(!this.events[key]){\n\t\t\tthis.events[key] = [];\n\t\t}\n\n\t\tthis.events[key].push(callback);\n\n\t\tthis._notifySubscriptionChange(key, true);\n\t}\n\n\tunsubscribe(key, callback){\n\t\tvar index;\n\n\t\tif(this.events[key]){\n\t\t\tif(callback){\n\t\t\t\tindex = this.events[key].findIndex((item) => {\n\t\t\t\t\treturn item === callback;\n\t\t\t\t});\n\n\t\t\t\tif(index > -1){\n\t\t\t\t\tthis.events[key].splice(index, 1);\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Cannot remove event, no matching event found:\", key, callback);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tdelete this.events[key];\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.warn(\"Cannot remove event, no events set on:\", key);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._notifySubscriptionChange(key, false);\n\t}\n\n\tsubscribed(key){\n\t\treturn this.events[key] && this.events[key].length;\n\t}\n\n\t_notifySubscriptionChange(key, subscribed){\n\t\tvar notifiers = this.subscriptionNotifiers[key];\n\n\t\tif(notifiers){\n\t\t\tnotifiers.forEach((callback)=>{\n\t\t\t\tcallback(subscribed);\n\t\t\t});\n\t\t}\n\t}\n\n\t_dispatch(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args.shift(),\n\t\tresult;\n\n\t\tif(this.events[key]){\n\t\t\tthis.events[key].forEach((callback, i) => {\n\t\t\t\tlet callResult = callback.apply(this.table, args);\n\n\t\t\t\tif(!i){\n\t\t\t\t\tresult = callResult;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t_debugDispatch(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args[0];\n\n\t\targs[0] = \"ExternalEvent:\" + args[0];\n\n\t\tif(this.debug === true || this.debug.includes(key)){\n\t\t\tconsole.log(...args);\n\t\t}\n\n\t\treturn this._dispatch(...arguments);\n\t}\n}\n\nclass InternalEventBus {\n\n\tconstructor(debug){\n\t\tthis.events = {};\n\t\tthis.subscriptionNotifiers = {};\n\n\t\tthis.dispatch = debug ? this._debugDispatch.bind(this) : this._dispatch.bind(this);\n\t\tthis.chain = debug ? this._debugChain.bind(this) : this._chain.bind(this);\n\t\tthis.confirm = debug ? this._debugConfirm.bind(this) : this._confirm.bind(this);\n\t\tthis.debug = debug;\n\t}\n\n\tsubscriptionChange(key, callback){\n\t\tif(!this.subscriptionNotifiers[key]){\n\t\t\tthis.subscriptionNotifiers[key] = [];\n\t\t}\n\n\t\tthis.subscriptionNotifiers[key].push(callback);\n\n\t\tif(this.subscribed(key)){\n\t\t\tthis._notifySubscriptionChange(key, true);\n\t\t}\n\t}\n\n\tsubscribe(key, callback, priority = 10000){\n\t\tif(!this.events[key]){\n\t\t\tthis.events[key] = [];\n\t\t}\n\n\t\tthis.events[key].push({callback, priority});\n\n\t\tthis.events[key].sort((a, b) => {\n\t\t\treturn a.priority - b.priority;\n\t\t});\n\n\t\tthis._notifySubscriptionChange(key, true);\n\t}\n\n\tunsubscribe(key, callback){\n\t\tvar index;\n\n\t\tif(this.events[key]){\n\t\t\tif(callback){\n\t\t\t\tindex = this.events[key].findIndex((item) => {\n\t\t\t\t\treturn item.callback === callback;\n\t\t\t\t});\n\n\t\t\t\tif(index > -1){\n\t\t\t\t\tthis.events[key].splice(index, 1);\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Cannot remove event, no matching event found:\", key, callback);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.warn(\"Cannot remove event, no events set on:\", key);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._notifySubscriptionChange(key, false);\n\t}\n\n\tsubscribed(key){\n\t\treturn this.events[key] && this.events[key].length;\n\t}\n\n\t_chain(key, args, initialValue, fallback){\n\t\tvar value = initialValue;\n\n\t\tif(!Array.isArray(args)){\n\t\t\targs = [args];\n\t\t}\n\n\t\tif(this.subscribed(key)){\n\t\t\tthis.events[key].forEach((subscriber, i) => {\n\t\t\t\tvalue = subscriber.callback.apply(this, args.concat([value]));\n\t\t\t});\n\n\t\t\treturn value;\n\t\t}else {\n\t\t\treturn typeof fallback === \"function\" ? fallback() : fallback;\n\t\t}\n\t}\n\n\t_confirm(key, args){\n\t\tvar confirmed = false;\n\n\t\tif(!Array.isArray(args)){\n\t\t\targs = [args];\n\t\t}\n\n\t\tif(this.subscribed(key)){\n\t\t\tthis.events[key].forEach((subscriber, i) => {\n\t\t\t\tif(subscriber.callback.apply(this, args)){\n\t\t\t\t\tconfirmed = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn confirmed;\n\t}\n\n\t_notifySubscriptionChange(key, subscribed){\n\t\tvar notifiers = this.subscriptionNotifiers[key];\n\n\t\tif(notifiers){\n\t\t\tnotifiers.forEach((callback)=>{\n\t\t\t\tcallback(subscribed);\n\t\t\t});\n\t\t}\n\t}\n\n\t_dispatch(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args.shift();\n\n\t\tif(this.events[key]){\n\t\t\tthis.events[key].forEach((subscriber) => {\n\t\t\t\tsubscriber.callback.apply(this, args);\n\t\t\t});\n\t\t}\n\t}\n\n\t_debugDispatch(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args[0];\n\n\t\targs[0] = \"InternalEvent:\" + key;\n\n\t\tif(this.debug === true || this.debug.includes(key)){\n\t\t\tconsole.log(...args);\n\t\t}\n\n\t\treturn this._dispatch(...arguments);\n\t}\n\n\t_debugChain(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args[0];\n\n\t\targs[0] = \"InternalEvent:\" + key;\n\n\t\tif(this.debug === true || this.debug.includes(key)){\n\t\t\tconsole.log(...args);\n\t\t}\n\n\t\treturn this._chain(...arguments);\n\t}\n\n\t_debugConfirm(){\n\t\tvar args = Array.from(arguments),\n\t\tkey = args[0];\n\n\t\targs[0] = \"InternalEvent:\" + key;\n\n\t\tif(this.debug === true || this.debug.includes(key)){\n\t\t\tconsole.log(...args);\n\t\t}\n\n\t\treturn this._confirm(...arguments);\n\t}\n}\n\nclass DeprecationAdvisor extends CoreFeature{\n\t\n\tconstructor(table){\n\t\tsuper(table);\n\t}\n\t\n\t_warnUser(){\n\t\tif(this.options(\"debugDeprecation\")){\n\t\t\tconsole.warn(...arguments);\n\t\t}\n\t}\n\t\n\tcheck(oldOption, newOption, convert){\n\t\tvar msg = \"\";\n\t\t\n\t\tif(typeof this.options(oldOption) !== \"undefined\"){\n\t\t\tmsg = \"Deprecated Setup Option - Use of the %c\" + oldOption + \"%c option is now deprecated\";\n\t\t\t\n\t\t\tif(newOption){\n\t\t\t\tmsg = msg + \", Please use the %c\" + newOption + \"%c option instead\";\n\t\t\t\tthis._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;');\n\n\t\t\t\tif(convert){\n\t\t\t\t\tthis.table.options[newOption] = this.table.options[oldOption];\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tthis._warnUser(msg, 'font-weight: bold;', 'font-weight: normal;');\n\t\t\t}\n\t\t\t\n\t\t\treturn false;\n\t\t}else {\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\tcheckMsg(oldOption, msg){\n\t\tif(typeof this.options(oldOption) !== \"undefined\"){\n\t\t\tthis._warnUser(\"%cDeprecated Setup Option - Use of the %c\" + oldOption + \" %c option is now deprecated, \" + msg, 'font-weight: normal;', 'font-weight: bold;', 'font-weight: normal;');\n\t\t\t\n\t\t\treturn false;\n\t\t}else {\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\tmsg(msg){\n\t\tthis._warnUser(msg);\n\t}\n}\n\nclass TableRegistry {\n\n\tstatic register(table){\n\t\tTableRegistry.tables.push(table);\n\t}\n\n\tstatic deregister(table){\n\t\tvar index = TableRegistry.tables.indexOf(table);\n\n\t\tif(index > -1){\n\t\t\tTableRegistry.tables.splice(index, 1);\n\t\t}\n\t}\n\n\tstatic lookupTable(query, silent){\n\t\tvar results = [],\n\t\tmatches, match;\n\n\t\tif(typeof query === \"string\"){\n\t\t\tmatches = document.querySelectorAll(query);\n\n\t\t\tif(matches.length){\n\t\t\t\tfor(var i = 0; i < matches.length; i++){\n\t\t\t\t\tmatch = TableRegistry.matchElement(matches[i]);\n\n\t\t\t\t\tif(match){\n\t\t\t\t\t\tresults.push(match);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}else if((typeof HTMLElement !== \"undefined\" && query instanceof HTMLElement) || query instanceof Tabulator){\n\t\t\tmatch = TableRegistry.matchElement(query);\n\n\t\t\tif(match){\n\t\t\t\tresults.push(match);\n\t\t\t}\n\t\t}else if(Array.isArray(query)){\n\t\t\tquery.forEach(function(item){\n\t\t\t\tresults = results.concat(TableRegistry.lookupTable(item));\n\t\t\t});\n\t\t}else {\n\t\t\tif(!silent){\n\t\t\t\tconsole.warn(\"Table Connection Error - Invalid Selector\", query);\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tstatic matchElement(element){\n\t\treturn TableRegistry.tables.find(function(table){\n\t\t\treturn element instanceof Tabulator ? table === element : table.element === element;\n\t\t});\n\t}\n}\n\nTableRegistry.tables = [];\n\n//resize columns to fit data they contain\nfunction fitData(columns, forced){\n\tif(forced){\n\t\tthis.table.columnManager.renderer.reinitializeColumnWidths(columns);\n\t}\n\t\n\tif(this.table.options.responsiveLayout && this.table.modExists(\"responsiveLayout\", true)){\n\t\tthis.table.modules.responsiveLayout.update();\n\t}\n}\n\n//resize columns to fit data they contain and stretch row to fill table, also used for fitDataTable\nfunction fitDataGeneral(columns, forced){\n\tcolumns.forEach(function(column){\n\t\tcolumn.reinitializeWidth();\n\t});\n\n\tif(this.table.options.responsiveLayout && this.table.modExists(\"responsiveLayout\", true)){\n\t\tthis.table.modules.responsiveLayout.update();\n\t}\n}\n\n//resize columns to fit data the contain and stretch last column to fill table\nfunction fitDataStretch(columns, forced){\n\tvar colsWidth = 0,\n\ttableWidth = this.table.rowManager.element.clientWidth,\n\tgap = 0,\n\tlastCol = false;\n\n\tcolumns.forEach((column, i) => {\n\t\tif(!column.widthFixed){\n\t\t\tcolumn.reinitializeWidth();\n\t\t}\n\n\t\tif(this.table.options.responsiveLayout ? column.modules.responsive.visible : column.visible){\n\t\t\tlastCol = column;\n\t\t}\n\n\t\tif(column.visible){\n\t\t\tcolsWidth += column.getWidth();\n\t\t}\n\t});\n\n\tif(lastCol){\n\t\tgap = tableWidth - colsWidth + lastCol.getWidth();\n\n\t\tif(this.table.options.responsiveLayout && this.table.modExists(\"responsiveLayout\", true)){\n\t\t\tlastCol.setWidth(0);\n\t\t\tthis.table.modules.responsiveLayout.update();\n\t\t}\n\n\t\tif(gap > 0){\n\t\t\tlastCol.setWidth(gap);\n\t\t}else {\n\t\t\tlastCol.reinitializeWidth();\n\t\t}\n\t}else {\n\t\tif(this.table.options.responsiveLayout && this.table.modExists(\"responsiveLayout\", true)){\n\t\t\tthis.table.modules.responsiveLayout.update();\n\t\t}\n\t}\n}\n\n//resize columns to fit\nfunction fitColumns(columns, forced){\n\tvar totalWidth = this.table.rowManager.element.getBoundingClientRect().width; //table element width\n\tvar fixedWidth = 0; //total width of columns with a defined width\n\tvar flexWidth = 0; //total width available to flexible columns\n\tvar flexGrowUnits = 0; //total number of widthGrow blocks across all columns\n\tvar flexColWidth = 0; //desired width of flexible columns\n\tvar flexColumns = []; //array of flexible width columns\n\tvar fixedShrinkColumns = []; //array of fixed width columns that can shrink\n\tvar flexShrinkUnits = 0; //total number of widthShrink blocks across all columns\n\tvar overflowWidth = 0; //horizontal overflow width\n\tvar gapFill = 0; //number of pixels to be added to final column to close and half pixel gaps\n\n\tfunction calcWidth(width){\n\t\tvar colWidth;\n\n\t\tif(typeof(width) == \"string\"){\n\t\t\tif(width.indexOf(\"%\") > -1){\n\t\t\t\tcolWidth = (totalWidth / 100) * parseInt(width);\n\t\t\t}else {\n\t\t\t\tcolWidth = parseInt(width);\n\t\t\t}\n\t\t}else {\n\t\t\tcolWidth = width;\n\t\t}\n\n\t\treturn colWidth;\n\t}\n\n\t//ensure columns resize to take up the correct amount of space\n\tfunction scaleColumns(columns, freeSpace, colWidth, shrinkCols){\n\t\tvar oversizeCols = [],\n\t\toversizeSpace = 0,\n\t\tremainingSpace = 0,\n\t\tnextColWidth = 0,\n\t\tremainingFlexGrowUnits = flexGrowUnits,\n\t\tgap = 0,\n\t\tchangeUnits = 0,\n\t\tundersizeCols = [];\n\n\t\tfunction calcGrow(col){\n\t\t\treturn (colWidth * (col.column.definition.widthGrow || 1));\n\t\t}\n\n\t\tfunction calcShrink(col){\n\t\t\treturn  (calcWidth(col.width) - (colWidth * (col.column.definition.widthShrink || 0)));\n\t\t}\n\n\t\tcolumns.forEach(function(col, i){\n\t\t\tvar width = shrinkCols ? calcShrink(col) : calcGrow(col);\n\t\t\tif(col.column.minWidth >= width){\n\t\t\t\toversizeCols.push(col);\n\t\t\t}else {\n\t\t\t\tif(col.column.maxWidth && col.column.maxWidth < width){\n\t\t\t\t\tcol.width = col.column.maxWidth;\n\t\t\t\t\tfreeSpace -= col.column.maxWidth;\n\n\t\t\t\t\tremainingFlexGrowUnits -= shrinkCols ? (col.column.definition.widthShrink || 1) : (col.column.definition.widthGrow || 1);\n\n\t\t\t\t\tif(remainingFlexGrowUnits){\n\t\t\t\t\t\tcolWidth = Math.floor(freeSpace/remainingFlexGrowUnits);\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tundersizeCols.push(col);\n\t\t\t\t\tchangeUnits += shrinkCols ? (col.column.definition.widthShrink || 1) : (col.column.definition.widthGrow || 1);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif(oversizeCols.length){\n\t\t\toversizeCols.forEach(function(col){\n\t\t\t\toversizeSpace += shrinkCols ?  col.width - col.column.minWidth : col.column.minWidth;\n\t\t\t\tcol.width = col.column.minWidth;\n\t\t\t});\n\n\t\t\tremainingSpace = freeSpace - oversizeSpace;\n\n\t\t\tnextColWidth = changeUnits ? Math.floor(remainingSpace/changeUnits) : remainingSpace;\n\n\t\t\tgap = scaleColumns(undersizeCols, remainingSpace, nextColWidth, shrinkCols);\n\t\t}else {\n\t\t\tgap = changeUnits ? freeSpace - (Math.floor(freeSpace/changeUnits) * changeUnits) : freeSpace;\n\n\t\t\tundersizeCols.forEach(function(column){\n\t\t\t\tcolumn.width = shrinkCols ? calcShrink(column) : calcGrow(column);\n\t\t\t});\n\t\t}\n\n\t\treturn gap;\n\t}\n\n\tif(this.table.options.responsiveLayout && this.table.modExists(\"responsiveLayout\", true)){\n\t\tthis.table.modules.responsiveLayout.update();\n\t}\n\n\t//adjust for vertical scrollbar if present\n\tif(this.table.rowManager.element.scrollHeight > this.table.rowManager.element.clientHeight){\n\t\ttotalWidth -= this.table.rowManager.element.offsetWidth - this.table.rowManager.element.clientWidth;\n\t}\n\n\tcolumns.forEach(function(column){\n\t\tvar width, minWidth, colWidth;\n\n\t\tif(column.visible){\n\n\t\t\twidth = column.definition.width;\n\t\t\tminWidth =  parseInt(column.minWidth);\n\n\t\t\tif(width){\n\n\t\t\t\tcolWidth = calcWidth(width);\n\n\t\t\t\tfixedWidth += colWidth > minWidth ? colWidth : minWidth;\n\n\t\t\t\tif(column.definition.widthShrink){\n\t\t\t\t\tfixedShrinkColumns.push({\n\t\t\t\t\t\tcolumn:column,\n\t\t\t\t\t\twidth:colWidth > minWidth ? colWidth : minWidth\n\t\t\t\t\t});\n\t\t\t\t\tflexShrinkUnits += column.definition.widthShrink;\n\t\t\t\t}\n\n\t\t\t}else {\n\t\t\t\tflexColumns.push({\n\t\t\t\t\tcolumn:column,\n\t\t\t\t\twidth:0,\n\t\t\t\t});\n\t\t\t\tflexGrowUnits += column.definition.widthGrow || 1;\n\t\t\t}\n\t\t}\n\t});\n\n\t//calculate available space\n\tflexWidth = totalWidth - fixedWidth;\n\n\t//calculate correct column size\n\tflexColWidth = Math.floor(flexWidth / flexGrowUnits);\n\n\t//generate column widths\n\tgapFill = scaleColumns(flexColumns, flexWidth, flexColWidth, false);\n\n\t//increase width of last column to account for rounding errors\n\tif(flexColumns.length && gapFill > 0){\n\t\tflexColumns[flexColumns.length-1].width += gapFill;\n\t}\n\n\t//calculate space for columns to be shrunk into\n\tflexColumns.forEach(function(col){\n\t\tflexWidth -= col.width;\n\t});\n\n\toverflowWidth = Math.abs(gapFill) + flexWidth;\n\n\t//shrink oversize columns if there is no available space\n\tif(overflowWidth > 0 && flexShrinkUnits){\n\t\tgapFill = scaleColumns(fixedShrinkColumns, overflowWidth, Math.floor(overflowWidth / flexShrinkUnits), true);\n\t}\n\n\t//decrease width of last column to account for rounding errors\n\tif(gapFill && fixedShrinkColumns.length){\n\t\tfixedShrinkColumns[fixedShrinkColumns.length-1].width -= gapFill;\n\t}\n\n\tflexColumns.forEach(function(col){\n\t\tcol.column.setWidth(col.width);\n\t});\n\n\tfixedShrinkColumns.forEach(function(col){\n\t\tcol.column.setWidth(col.width);\n\t});\n}\n\nvar defaultModes = {\n\tfitData:fitData,\n\tfitDataFill:fitDataGeneral,\n\tfitDataTable:fitDataGeneral,\n\tfitDataStretch:fitDataStretch,\n\tfitColumns:fitColumns ,\n};\n\nclass Layout extends Module{\n\n\tconstructor(table){\n\t\tsuper(table, \"layout\");\n\n\t\tthis.mode = null;\n\n\t\tthis.registerTableOption(\"layout\", \"fitData\"); //layout type\n\t\tthis.registerTableOption(\"layoutColumnsOnNewData\", false); //update column widths on setData\n\n\t\tthis.registerColumnOption(\"widthGrow\");\n\t\tthis.registerColumnOption(\"widthShrink\");\n\t}\n\n\t//initialize layout system\n\tinitialize(){\n\t\tvar layout = this.table.options.layout;\n\n\t\tif(Layout.modes[layout]){\n\t\t\tthis.mode = layout;\n\t\t}else {\n\t\t\tconsole.warn(\"Layout Error - invalid mode set, defaulting to 'fitData' : \" + layout);\n\t\t\tthis.mode = 'fitData';\n\t\t}\n\n\t\tthis.table.element.setAttribute(\"tabulator-layout\", this.mode);\n\t\tthis.subscribe(\"column-init\", this.initializeColumn.bind(this));\n\t}\n\n\tinitializeColumn(column){\n\t\tif(column.definition.widthGrow){\n\t\t\tcolumn.definition.widthGrow = Number(column.definition.widthGrow);\n\t\t}\n\t\tif(column.definition.widthShrink){\n\t\t\tcolumn.definition.widthShrink = Number(column.definition.widthShrink);\n\t\t}\n\t}\n\n\tgetMode(){\n\t\treturn this.mode;\n\t}\n\n\t//trigger table layout\n\tlayout(dataChanged){\n\t\tthis.dispatch(\"layout-refreshing\");\n\t\tLayout.modes[this.mode].call(this, this.table.columnManager.columnsByIndex, dataChanged);\n\t\tthis.dispatch(\"layout-refreshed\");\n\t}\n}\n\nLayout.moduleName = \"layout\";\n\n//load defaults\nLayout.modes = defaultModes;\n\nvar defaultLangs = {\n\t\"default\":{ //hold default locale text\n\t\t\"groups\":{\n\t\t\t\"item\":\"item\",\n\t\t\t\"items\":\"items\",\n\t\t},\n\t\t\"columns\":{\n\t\t},\n\t\t\"data\":{\n\t\t\t\"loading\":\"Loading\",\n\t\t\t\"error\":\"Error\",\n\t\t},\n\t\t\"pagination\":{\n\t\t\t\"page_size\":\"Page Size\",\n\t\t\t\"page_title\":\"Show Page\",\n\t\t\t\"first\":\"First\",\n\t\t\t\"first_title\":\"First Page\",\n\t\t\t\"last\":\"Last\",\n\t\t\t\"last_title\":\"Last Page\",\n\t\t\t\"prev\":\"Prev\",\n\t\t\t\"prev_title\":\"Prev Page\",\n\t\t\t\"next\":\"Next\",\n\t\t\t\"next_title\":\"Next Page\",\n\t\t\t\"all\":\"All\",\n\t\t\t\"counter\":{\n\t\t\t\t\"showing\": \"Showing\",\n\t\t\t\t\"of\": \"of\",\n\t\t\t\t\"rows\": \"rows\",\n\t\t\t\t\"pages\": \"pages\",\n\t\t\t}\n\t\t},\n\t\t\"headerFilters\":{\n\t\t\t\"default\":\"filter column...\",\n\t\t\t\"columns\":{}\n\t\t}\n\t},\n};\n\nclass Localize extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\n\t\tthis.locale = \"default\"; //current locale\n\t\tthis.lang = false; //current language\n\t\tthis.bindings = {}; //update events to call when locale is changed\n\t\tthis.langList = {};\n\n\t\tthis.registerTableOption(\"locale\", false); //current system language\n\t\tthis.registerTableOption(\"langs\", {});\n\t}\n\n\tinitialize(){\n\t\tthis.langList = Helpers.deepClone(Localize.langs);\n\n\t\tif(this.table.options.columnDefaults.headerFilterPlaceholder !== false){\n\t\t\tthis.setHeaderFilterPlaceholder(this.table.options.columnDefaults.headerFilterPlaceholder);\n\t\t}\n\n\t\tfor(let locale in this.table.options.langs){\n\t\t\tthis.installLang(locale, this.table.options.langs[locale]);\n\t\t}\n\n\t\tthis.setLocale(this.table.options.locale);\n\n\t\tthis.registerTableFunction(\"setLocale\", this.setLocale.bind(this));\n\t\tthis.registerTableFunction(\"getLocale\", this.getLocale.bind(this));\n\t\tthis.registerTableFunction(\"getLang\", this.getLang.bind(this));\n\t}\n\n\t//set header placeholder\n\tsetHeaderFilterPlaceholder(placeholder){\n\t\tthis.langList.default.headerFilters.default = placeholder;\n\t}\n\n\t//setup a lang description object\n\tinstallLang(locale, lang){\n\t\tif(this.langList[locale]){\n\t\t\tthis._setLangProp(this.langList[locale], lang);\n\t\t}else {\n\t\t\tthis.langList[locale] = lang;\n\t\t}\n\t}\n\n\t_setLangProp(lang, values){\n\t\tfor(let key in values){\n\t\t\tif(lang[key] && typeof lang[key] == \"object\"){\n\t\t\t\tthis._setLangProp(lang[key], values[key]);\n\t\t\t}else {\n\t\t\t\tlang[key] = values[key];\n\t\t\t}\n\t\t}\n\t}\n\n\t//set current locale\n\tsetLocale(desiredLocale){\n\t\tdesiredLocale = desiredLocale || \"default\";\n\n\t\t//fill in any matching language values\n\t\tfunction traverseLang(trans, path){\n\t\t\tfor(var prop in trans){\n\t\t\t\tif(typeof trans[prop] == \"object\"){\n\t\t\t\t\tif(!path[prop]){\n\t\t\t\t\t\tpath[prop] = {};\n\t\t\t\t\t}\n\t\t\t\t\ttraverseLang(trans[prop], path[prop]);\n\t\t\t\t}else {\n\t\t\t\t\tpath[prop] = trans[prop];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//determining correct locale to load\n\t\tif(desiredLocale === true && navigator.language){\n\t\t\t//get local from system\n\t\t\tdesiredLocale = navigator.language.toLowerCase();\n\t\t}\n\n\t\tif(desiredLocale){\n\t\t\t//if locale is not set, check for matching top level locale else use default\n\t\t\tif(!this.langList[desiredLocale]){\n\t\t\t\tlet prefix = desiredLocale.split(\"-\")[0];\n\n\t\t\t\tif(this.langList[prefix]){\n\t\t\t\t\tconsole.warn(\"Localization Error - Exact matching locale not found, using closest match: \", desiredLocale, prefix);\n\t\t\t\t\tdesiredLocale = prefix;\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Localization Error - Matching locale not found, using default: \", desiredLocale);\n\t\t\t\t\tdesiredLocale = \"default\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.locale = desiredLocale;\n\n\t\t//load default lang template\n\t\tthis.lang = Helpers.deepClone(this.langList.default || {});\n\n\t\tif(desiredLocale != \"default\"){\n\t\t\ttraverseLang(this.langList[desiredLocale], this.lang);\n\t\t}\n\n\t\tthis.dispatchExternal(\"localized\", this.locale, this.lang);\n\n\t\tthis._executeBindings();\n\t}\n\n\t//get current locale\n\tgetLocale(locale){\n\t\treturn this.locale;\n\t}\n\n\t//get lang object for given local or current if none provided\n\tgetLang(locale){\n\t\treturn locale ? this.langList[locale] : this.lang;\n\t}\n\n\t//get text for current locale\n\tgetText(path, value){\n\t\tvar fillPath = value ? path + \"|\" + value : path,\n\t\tpathArray = fillPath.split(\"|\"),\n\t\ttext = this._getLangElement(pathArray, this.locale);\n\n\t\t// if(text === false){\n\t\t// \tconsole.warn(\"Localization Error - Matching localized text not found for given path: \", path);\n\t\t// }\n\n\t\treturn text || \"\";\n\t}\n\n\t//traverse langs object and find localized copy\n\t_getLangElement(path, locale){\n\t\tvar root = this.lang;\n\n\t\tpath.forEach(function(level){\n\t\t\tvar rootPath;\n\n\t\t\tif(root){\n\t\t\t\trootPath = root[level];\n\n\t\t\t\tif(typeof rootPath != \"undefined\"){\n\t\t\t\t\troot = rootPath;\n\t\t\t\t}else {\n\t\t\t\t\troot = false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn root;\n\t}\n\n\t//set update binding\n\tbind(path, callback){\n\t\tif(!this.bindings[path]){\n\t\t\tthis.bindings[path] = [];\n\t\t}\n\n\t\tthis.bindings[path].push(callback);\n\n\t\tcallback(this.getText(path), this.lang);\n\t}\n\n\t//iterate through bindings and trigger updates\n\t_executeBindings(){\n\t\tfor(let path in this.bindings){\n\t\t\tthis.bindings[path].forEach((binding) => {\n\t\t\t\tbinding(this.getText(path), this.lang);\n\t\t\t});\n\t\t}\n\t}\n}\n\nLocalize.moduleName = \"localize\";\n\n//load defaults\nLocalize.langs = defaultLangs;\n\nclass Comms extends Module{\n\n\tconstructor(table){\n\t\tsuper(table);\n\t}\n\n\tinitialize(){\n\t\tthis.registerTableFunction(\"tableComms\", this.receive.bind(this));\n\t}\n\n\tgetConnections(selectors){\n\t\tvar connections = [],\n\t\tconnection;\n\n\t\tconnection = TableRegistry.lookupTable(selectors);\n\n\t\tconnection.forEach((con) =>{\n\t\t\tif(this.table !== con){\n\t\t\t\tconnections.push(con);\n\t\t\t}\n\t\t});\n\n\t\treturn connections;\n\t}\n\n\tsend(selectors, module, action, data){\n\t\tvar connections = this.getConnections(selectors);\n\n\t\tconnections.forEach((connection) => {\n\t\t\tconnection.tableComms(this.table.element, module, action, data);\n\t\t});\n\n\t\tif(!connections.length && selectors){\n\t\t\tconsole.warn(\"Table Connection Error - No tables matching selector found\", selectors);\n\t\t}\n\t}\n\n\treceive(table, module, action, data){\n\t\tif(this.table.modExists(module)){\n\t\t\treturn this.table.modules[module].commsReceived(table, action, data);\n\t\t}else {\n\t\t\tconsole.warn(\"Inter-table Comms Error - no such module:\", module);\n\t\t}\n\t}\n}\n\nComms.moduleName = \"comms\";\n\nvar coreModules = /*#__PURE__*/Object.freeze({\n\t__proto__: null,\n\tLayoutModule: Layout,\n\tLocalizeModule: Localize,\n\tCommsModule: Comms\n});\n\nclass ModuleBinder {\n\t\n\tconstructor(tabulator, modules){\n\t\tthis.bindStaticFunctionality(tabulator);\n\t\tthis.bindModules(tabulator, coreModules, true);\n\t\t\n\t\tif(modules){\n\t\t\tthis.bindModules(tabulator, modules);\n\t\t}\n\t}\n\t\n\tbindStaticFunctionality(tabulator){\n\t\ttabulator.moduleBindings = {};\n\t\t\n\t\ttabulator.extendModule = function(name, property, values){\n\t\t\tif(tabulator.moduleBindings[name]){\n\t\t\t\tvar source = tabulator.moduleBindings[name][property];\n\t\t\t\t\n\t\t\t\tif(source){\n\t\t\t\t\tif(typeof values == \"object\"){\n\t\t\t\t\t\tfor(let key in values){\n\t\t\t\t\t\t\tsource[key] = values[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}else {\n\t\t\t\t\t\tconsole.warn(\"Module Error - Invalid value type, it must be an object\");\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tconsole.warn(\"Module Error - property does not exist:\", property);\n\t\t\t\t}\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Module Error - module does not exist:\", name);\n\t\t\t}\n\t\t};\n\t\t\n\t\ttabulator.registerModule = function(modules){\n\t\t\tif(!Array.isArray(modules)){\n\t\t\t\tmodules = [modules];\n\t\t\t}\n\t\t\t\n\t\t\tmodules.forEach((mod) => {\n\t\t\t\ttabulator.registerModuleBinding(mod);\n\t\t\t});\n\t\t};\n\t\t\n\t\ttabulator.registerModuleBinding = function(mod){\n\t\t\ttabulator.moduleBindings[mod.moduleName] = mod;\n\t\t};\n\t\t\n\t\ttabulator.findTable = function(query){\n\t\t\tvar results = TableRegistry.lookupTable(query, true);\n\t\t\treturn Array.isArray(results) && !results.length ? false : results;\n\t\t};\n\t\t\n\t\t//ensure that module are bound to instantiated function\n\t\ttabulator.prototype.bindModules = function(){\n\t\t\tvar orderedStartMods = [],\n\t\t\torderedEndMods = [],\n\t\t\tunOrderedMods = [];\n\t\t\t\n\t\t\tthis.modules = {};\n\t\t\t\n\t\t\tfor(var name in tabulator.moduleBindings){\n\t\t\t\tlet mod = tabulator.moduleBindings[name];\n\t\t\t\tlet module = new mod(this);\n\t\t\t\t\n\t\t\t\tthis.modules[name] = module;\n\t\t\t\t\n\t\t\t\tif(mod.prototype.moduleCore){\n\t\t\t\t\tthis.modulesCore.push(module);\n\t\t\t\t}else {\n\t\t\t\t\tif(mod.moduleInitOrder){\n\t\t\t\t\t\tif(mod.moduleInitOrder < 0){\n\t\t\t\t\t\t\torderedStartMods.push(module);\n\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\torderedEndMods.push(module);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t}else {\n\t\t\t\t\t\tunOrderedMods.push(module);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\torderedStartMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1);\n\t\t\torderedEndMods.sort((a, b) => a.moduleInitOrder > b.moduleInitOrder ? 1 : -1);\n\t\t\t\n\t\t\tthis.modulesRegular = orderedStartMods.concat(unOrderedMods.concat(orderedEndMods));\n\t\t};\n\t}\n\t\n\tbindModules(tabulator, modules, core){\n\t\tvar mods = Object.values(modules);\n\t\t\n\t\tif(core){\n\t\t\tmods.forEach((mod) => {\n\t\t\t\tmod.prototype.moduleCore = true;\n\t\t\t});\n\t\t}\n\t\t\n\t\ttabulator.registerModule(mods);\n\t}\n}\n\nclass Alert extends CoreFeature{\n\tconstructor(table){\n\t\tsuper(table);\n        \n\t\tthis.element = this._createAlertElement();\n\t\tthis.msgElement = this._createMsgElement();\n\t\tthis.type = null;\n        \n\t\tthis.element.appendChild(this.msgElement);\n\t}\n    \n\t_createAlertElement(){\n\t\tvar el = document.createElement(\"div\");\n\t\tel.classList.add(\"tabulator-alert\");\n\t\treturn el;\n\t}\n    \n\t_createMsgElement(){\n\t\tvar el = document.createElement(\"div\");\n\t\tel.classList.add(\"tabulator-alert-msg\");\n\t\tel.setAttribute(\"role\", \"alert\");\n\t\treturn el;\n\t}\n    \n\t_typeClass(){\n\t\treturn \"tabulator-alert-state-\" + this.type;\n\t}\n    \n\talert(content, type = \"msg\"){\n\t\tif(content){\n\t\t\tthis.clear();\n\n\t\t\tthis.dispatch(\"alert-show\", type);\n            \n\t\t\tthis.type = type;\n            \n\t\t\twhile(this.msgElement.firstChild) this.msgElement.removeChild(this.msgElement.firstChild);\n            \n\t\t\tthis.msgElement.classList.add(this._typeClass());\n            \n\t\t\tif(typeof content === \"function\"){\n\t\t\t\tcontent = content();\n\t\t\t}\n            \n\t\t\tif(content instanceof HTMLElement){\n\t\t\t\tthis.msgElement.appendChild(content);\n\t\t\t}else {\n\t\t\t\tthis.msgElement.innerHTML = content;\n\t\t\t}\n            \n\t\t\tthis.table.element.appendChild(this.element);\n\t\t}\n\t}\n    \n\tclear(){\n\t\tthis.dispatch(\"alert-hide\", this.type);\n\n\t\tif(this.element.parentNode){\n\t\t\tthis.element.parentNode.removeChild(this.element);\n\t\t}\n        \n\t\tthis.msgElement.classList.remove(this._typeClass());\n\t}\n}\n\nclass Tabulator {\n\t\n\tconstructor(element, options){\n\t\t\n\t\tthis.options = {};\n\t\t\n\t\tthis.columnManager = null; // hold Column Manager\n\t\tthis.rowManager = null; //hold Row Manager\n\t\tthis.footerManager = null; //holder Footer Manager\n\t\tthis.alertManager = null; //hold Alert Manager\n\t\tthis.vdomHoz  = null; //holder horizontal virtual dom\n\t\tthis.externalEvents = null; //handle external event messaging\n\t\tthis.eventBus = null; //handle internal event messaging\n\t\tthis.interactionMonitor = false; //track user interaction\n\t\tthis.browser = \"\"; //hold current browser type\n\t\tthis.browserSlow = false; //handle reduced functionality for slower browsers\n\t\tthis.browserMobile = false; //check if running on mobile, prevent resize cancelling edit on keyboard appearance\n\t\tthis.rtl = false; //check if the table is in RTL mode\n\t\tthis.originalElement = null; //hold original table element if it has been replaced\n\t\t\n\t\tthis.componentFunctionBinder = new ComponentFunctionBinder(this); //bind component functions\n\t\tthis.dataLoader = false; //bind component functions\n\t\t\n\t\tthis.modules = {}; //hold all modules bound to this table\n\t\tthis.modulesCore = []; //hold core modules bound to this table (for initialization purposes)\n\t\tthis.modulesRegular = []; //hold regular modules bound to this table (for initialization purposes)\n\t\t\n\t\tthis.deprecationAdvisor = new DeprecationAdvisor(this);\n\t\tthis.optionsList = new OptionsList(this, \"table constructor\");\n\t\t\n\t\tthis.initialized = false;\n\t\tthis.destroyed = false;\n\t\t\n\t\tif(this.initializeElement(element)){\n\t\t\t\n\t\t\tthis.initializeCoreSystems(options);\n\t\t\t\n\t\t\t//delay table creation to allow event bindings immediately after the constructor\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis._create();\n\t\t\t});\n\t\t}\n\t\t\n\t\tTableRegistry.register(this); //register table for inter-device communication\n\t}\n\t\n\tinitializeElement(element){\n\t\tif(typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement){\n\t\t\tthis.element = element;\n\t\t\treturn true;\n\t\t}else if(typeof element === \"string\"){\n\t\t\tthis.element = document.querySelector(element);\n\t\t\t\n\t\t\tif(this.element){\n\t\t\t\treturn true;\n\t\t\t}else {\n\t\t\t\tconsole.error(\"Tabulator Creation Error - no element found matching selector: \", element);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.error(\"Tabulator Creation Error - Invalid element provided:\", element);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tinitializeCoreSystems(options){\n\t\tthis.columnManager = new ColumnManager(this);\n\t\tthis.rowManager = new RowManager(this);\n\t\tthis.footerManager = new FooterManager(this);\n\t\tthis.dataLoader = new DataLoader(this);\n\t\tthis.alertManager = new Alert(this);\n\t\t\n\t\tthis.bindModules();\n\t\t\n\t\tthis.options = this.optionsList.generate(Tabulator.defaultOptions, options);\n\t\t\n\t\tthis._clearObjectPointers();\n\t\t\n\t\tthis._mapDeprecatedFunctionality();\n\t\t\n\t\tthis.externalEvents = new ExternalEventBus(this, this.options, this.options.debugEventsExternal);\n\t\tthis.eventBus = new InternalEventBus(this.options.debugEventsInternal);\n\t\t\n\t\tthis.interactionMonitor = new InteractionManager(this);\n\t\t\n\t\tthis.dataLoader.initialize();\n\t\t// this.columnManager.initialize();\n\t\t// this.rowManager.initialize();\n\t\tthis.footerManager.initialize();\n\t}\n\t\n\t//convert deprecated functionality to new functions\n\t_mapDeprecatedFunctionality(){\n\t\t//all previously deprecated functionality removed in the 5.0 release\n\t}\n\t\n\t_clearSelection(){\n\t\t\n\t\tthis.element.classList.add(\"tabulator-block-select\");\n\t\t\n\t\tif (window.getSelection) {\n\t\t\tif (window.getSelection().empty) {  // Chrome\n\t\t\t\twindow.getSelection().empty();\n\t\t\t} else if (window.getSelection().removeAllRanges) {  // Firefox\n\t\t\t\twindow.getSelection().removeAllRanges();\n\t\t\t}\n\t\t} else if (document.selection) {  // IE?\n\t\t\tdocument.selection.empty();\n\t\t}\n\t\t\n\t\tthis.element.classList.remove(\"tabulator-block-select\");\n\t}\n\t\n\t//create table\n\t_create(){\n\t\tthis.externalEvents.dispatch(\"tableBuilding\");\n\t\tthis.eventBus.dispatch(\"table-building\");\n\t\t\n\t\tthis._rtlCheck();\n\t\t\n\t\tthis._buildElement();\n\t\t\n\t\tthis._initializeTable();\n\t\t\n\t\tthis._loadInitialData();\n\t\t\n\t\tthis.initialized = true;\n\t\t\n\t\tthis.externalEvents.dispatch(\"tableBuilt\");\n\t}\n\t\n\t_rtlCheck(){\n\t\tvar style = window.getComputedStyle(this.element);\n\t\t\n\t\tswitch(this.options.textDirection){\n\t\t\tcase\"auto\":\n\t\t\t\tif(style.direction !== \"rtl\"){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\n\t\t\tcase \"rtl\":\n\t\t\t\tthis.element.classList.add(\"tabulator-rtl\");\n\t\t\t\tthis.rtl = true;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase \"ltr\":\n\t\t\t\tthis.element.classList.add(\"tabulator-ltr\");\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthis.rtl = false;\n\t\t}\n\t}\n\t\n\t//clear pointers to objects in default config object\n\t_clearObjectPointers(){\n\t\tthis.options.columns = this.options.columns.slice(0);\n\t\t\n\t\tif(Array.isArray(this.options.data) && !this.options.reactiveData){\n\t\t\tthis.options.data = this.options.data.slice(0);\n\t\t}\n\t}\n\t\n\t//build tabulator element\n\t_buildElement(){\n\t\tvar element = this.element,\n\t\toptions = this.options,\n\t\tnewElement;\n\t\t\n\t\tif(element.tagName === \"TABLE\"){\n\t\t\tthis.originalElement = this.element;\n\t\t\tnewElement = document.createElement(\"div\");\n\t\t\t\n\t\t\t//transfer attributes to new element\n\t\t\tvar attributes = element.attributes;\n\t\t\t\n\t\t\t// loop through attributes and apply them on div\n\t\t\tfor(var i in attributes){\n\t\t\t\tif(typeof attributes[i] == \"object\"){\n\t\t\t\t\tnewElement.setAttribute(attributes[i].name, attributes[i].value);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// replace table with div element\n\t\t\telement.parentNode.replaceChild(newElement, element);\n\t\t\t\n\t\t\tthis.element = element = newElement;\n\t\t}\n\t\t\n\t\telement.classList.add(\"tabulator\");\n\t\telement.setAttribute(\"role\", \"grid\");\n\t\t\n\t\t//empty element\n\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\t\t\n\t\t//set table height\n\t\tif(options.height){\n\t\t\toptions.height = isNaN(options.height) ? options.height : options.height + \"px\";\n\t\t\telement.style.height = options.height;\n\t\t}\n\t\t\n\t\t//set table min height\n\t\tif(options.minHeight !== false){\n\t\t\toptions.minHeight = isNaN(options.minHeight) ? options.minHeight : options.minHeight + \"px\";\n\t\t\telement.style.minHeight = options.minHeight;\n\t\t}\n\t\t\n\t\t//set table maxHeight\n\t\tif(options.maxHeight !== false){\n\t\t\toptions.maxHeight = isNaN(options.maxHeight) ? options.maxHeight : options.maxHeight + \"px\";\n\t\t\telement.style.maxHeight = options.maxHeight;\n\t\t}\n\t}\n\t\n\t//initialize core systems and modules\n\t_initializeTable(){\n\t\tvar element = this.element,\n\t\toptions = this.options;\n\t\t\n\t\tthis.interactionMonitor.initialize();\n\t\t\n\t\tthis.columnManager.initialize();\n\t\tthis.rowManager.initialize();\n\t\t\n\t\tthis._detectBrowser();\n\t\t\n\t\t//initialize core modules\n\t\tthis.modulesCore.forEach((mod) => {\n\t\t\tmod.initialize();\n\t\t});\n\t\t\n\t\t//build table elements\n\t\telement.appendChild(this.columnManager.getElement());\n\t\telement.appendChild(this.rowManager.getElement());\n\t\t\n\t\tif(options.footerElement){\n\t\t\tthis.footerManager.activate();\n\t\t}\n\t\t\n\t\tif(options.autoColumns && options.data){\n\t\t\t\n\t\t\tthis.columnManager.generateColumnsFromRowData(this.options.data);\n\t\t}\n\t\t\n\t\t//initialize regular modules\n\t\tthis.modulesRegular.forEach((mod) => {\n\t\t\tmod.initialize();\n\t\t});\n\t\t\n\t\tthis.columnManager.setColumns(options.columns);\n\t\t\n\t\tthis.eventBus.dispatch(\"table-built\");\n\t}\n\t\n\t_loadInitialData(){\n\t\tthis.dataLoader.load(this.options.data);\n\t\tthis.columnManager.verticalAlignHeaders();\n\t}\n\t\n\t//deconstructor\n\tdestroy(){\n\t\tvar element = this.element;\n\t\t\n\t\tthis.destroyed = true;\n\t\t\n\t\tTableRegistry.deregister(this); //deregister table from inter-device communication\n\t\t\n\t\tthis.eventBus.dispatch(\"table-destroy\");\n\t\t\n\t\t//clear row data\n\t\tthis.rowManager.destroy();\n\t\t\n\t\t//clear DOM\n\t\twhile(element.firstChild) element.removeChild(element.firstChild);\n\t\telement.classList.remove(\"tabulator\");\n\n\t\tthis.externalEvents.dispatch(\"tableDestroyed\");\n\t}\n\t\n\t_detectBrowser(){\n\t\tvar ua = navigator.userAgent||navigator.vendor||window.opera;\n\t\t\n\t\tif(ua.indexOf(\"Trident\") > -1){\n\t\t\tthis.browser = \"ie\";\n\t\t\tthis.browserSlow = true;\n\t\t}else if(ua.indexOf(\"Edge\") > -1){\n\t\t\tthis.browser = \"edge\";\n\t\t\tthis.browserSlow = true;\n\t\t}else if(ua.indexOf(\"Firefox\") > -1){\n\t\t\tthis.browser = \"firefox\";\n\t\t\tthis.browserSlow = false;\n\t\t}else if(ua.indexOf(\"Mac OS\") > -1){\n\t\t\tthis.browser = \"safari\";\n\t\t\tthis.browserSlow = false;\n\t\t}else {\n\t\t\tthis.browser = \"other\";\n\t\t\tthis.browserSlow = false;\n\t\t}\n\t\t\n\t\tthis.browserMobile = /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(ua)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(ua.slice(0,4));\n\t}\n\t\n\tinitGuard(func, msg){\n\t\tvar stack, line;\n\t\t\n\t\tif(this.options.debugInitialization && !this.initialized){\n\t\t\tif(!func){\n\t\t\t\tstack = new Error().stack.split(\"\\n\");\n\t\t\t\t\n\t\t\t\tline = stack[0] == \"Error\" ? stack[2] : stack[1];\n\t\t\t\t\n\t\t\t\tif(line[0] == \" \"){\n\t\t\t\t\tfunc = line.trim().split(\" \")[1].split(\".\")[1];\n\t\t\t\t}else {\n\t\t\t\t\tfunc = line.trim().split(\"@\")[0];\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tconsole.warn(\"Table Not Initialized - Calling the \" + func + \" function before the table is initialized may result in inconsistent behavior, Please wait for the `tableBuilt` event before calling this function.\" + (msg ? \" \" + msg : \"\"));\n\t\t}\n\t\t\n\t\treturn this.initialized;\n\t}\n\t\n\t////////////////// Data Handling //////////////////\n\t//block table redrawing\n\tblockRedraw(){\n\t\tthis.initGuard();\n\n\t\tthis.eventBus.dispatch(\"redraw-blocking\");\n\t\t\n\t\tthis.rowManager.blockRedraw();\n\t\tthis.columnManager.blockRedraw();\n\n\t\tthis.eventBus.dispatch(\"redraw-blocked\");\n\t}\n\t\n\t//restore table redrawing\n\trestoreRedraw(){\n\t\tthis.initGuard();\n\n\t\tthis.eventBus.dispatch(\"redraw-restoring\");\n\n\t\tthis.rowManager.restoreRedraw();\n\t\tthis.columnManager.restoreRedraw();\n\n\t\tthis.eventBus.dispatch(\"redraw-restored\");\n\t}\n\t\n\t//load data\n\tsetData(data, params, config){\n\t\tthis.initGuard(false, \"To set initial data please use the 'data' property in the table constructor.\");\n\t\t\n\t\treturn this.dataLoader.load(data, params, config, false);\n\t}\n\t\n\t//clear data\n\tclearData(){\n\t\tthis.initGuard();\n\t\t\n\t\tthis.dataLoader.blockActiveLoad();\n\t\tthis.rowManager.clearData();\n\t}\n\t\n\t//get table data array\n\tgetData(active){\n\t\treturn this.rowManager.getData(active);\n\t}\n\t\n\t//get table data array count\n\tgetDataCount(active){\n\t\treturn this.rowManager.getDataCount(active);\n\t}\n\t\n\t//replace data, keeping table in position with same sort\n\treplaceData(data, params, config){\n\t\tthis.initGuard();\n\t\t\n\t\treturn this.dataLoader.load(data, params, config, true, true);\n\t}\n\t\n\t//update table data\n\tupdateData(data){\n\t\tvar responses = 0;\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.dataLoader.blockActiveLoad();\n\t\t\t\n\t\t\tif(typeof data === \"string\"){\n\t\t\t\tdata = JSON.parse(data);\n\t\t\t}\n\t\t\t\n\t\t\tif(data && data.length > 0){\n\t\t\t\tdata.forEach((item) => {\n\t\t\t\t\tvar row = this.rowManager.findRow(item[this.options.index]);\n\t\t\t\t\t\n\t\t\t\t\tif(row){\n\t\t\t\t\t\tresponses++;\n\t\t\t\t\t\t\n\t\t\t\t\t\trow.updateData(item)\n\t\t\t\t\t\t\t.then(()=>{\n\t\t\t\t\t\t\t\tresponses--;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif(!responses){\n\t\t\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\t\treject(\"Update Error - Unable to update row\", item, e);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}else {\n\t\t\t\t\t\treject(\"Update Error - Unable to find row\", item);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Update Error - No data provided\");\n\t\t\t\treject(\"Update Error - No data provided\");\n\t\t\t}\n\t\t});\n\t}\n\t\n\taddData(data, pos, index){\n\t\tthis.initGuard();\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.dataLoader.blockActiveLoad();\n\t\t\t\n\t\t\tif(typeof data === \"string\"){\n\t\t\t\tdata = JSON.parse(data);\n\t\t\t}\n\t\t\t\n\t\t\tif(data){\n\t\t\t\tthis.rowManager.addRows(data, pos, index)\n\t\t\t\t\t.then((rows) => {\n\t\t\t\t\t\tvar output = [];\n\t\t\t\t\t\n\t\t\t\t\t\trows.forEach(function(row){\n\t\t\t\t\t\t\toutput.push(row.getComponent());\n\t\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t\tresolve(output);\n\t\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Update Error - No data provided\");\n\t\t\t\treject(\"Update Error - No data provided\");\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//update table data\n\tupdateOrAddData(data){\n\t\tvar rows = [],\n\t\tresponses = 0;\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.dataLoader.blockActiveLoad();\n\t\t\t\n\t\t\tif(typeof data === \"string\"){\n\t\t\t\tdata = JSON.parse(data);\n\t\t\t}\n\t\t\t\n\t\t\tif(data && data.length > 0){\n\t\t\t\tdata.forEach((item) => {\n\t\t\t\t\tvar row = this.rowManager.findRow(item[this.options.index]);\n\t\t\t\t\t\n\t\t\t\t\tresponses++;\n\t\t\t\t\t\n\t\t\t\t\tif(row){\n\t\t\t\t\t\trow.updateData(item)\n\t\t\t\t\t\t\t.then(()=>{\n\t\t\t\t\t\t\t\tresponses--;\n\t\t\t\t\t\t\t\trows.push(row.getComponent());\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif(!responses){\n\t\t\t\t\t\t\t\t\tresolve(rows);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}else {\n\t\t\t\t\t\tthis.rowManager.addRows(item)\n\t\t\t\t\t\t\t.then((newRows)=>{\n\t\t\t\t\t\t\t\tresponses--;\n\t\t\t\t\t\t\t\trows.push(newRows[0].getComponent());\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif(!responses){\n\t\t\t\t\t\t\t\t\tresolve(rows);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Update Error - No data provided\");\n\t\t\t\treject(\"Update Error - No data provided\");\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//get row object\n\tgetRow(index){\n\t\tvar row = this.rowManager.findRow(index);\n\t\t\n\t\tif(row){\n\t\t\treturn row.getComponent();\n\t\t}else {\n\t\t\tconsole.warn(\"Find Error - No matching row found:\", index);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t//get row object\n\tgetRowFromPosition(position){\n\t\tvar row = this.rowManager.getRowFromPosition(position);\n\t\t\n\t\tif(row){\n\t\t\treturn row.getComponent();\n\t\t}else {\n\t\t\tconsole.warn(\"Find Error - No matching row found:\", position);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t//delete row from table\n\tdeleteRow(index){\n\t\tvar foundRows = [];\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(!Array.isArray(index)){\n\t\t\tindex = [index];\n\t\t}\n\t\t\n\t\t//find matching rows\n\t\tfor(let item of index){\n\t\t\tlet row = this.rowManager.findRow(item, true);\n\t\t\t\n\t\t\tif(row){\n\t\t\t\tfoundRows.push(row);\n\t\t\t}else {\n\t\t\t\tconsole.error(\"Delete Error - No matching row found:\", item);\n\t\t\t\treturn Promise.reject(\"Delete Error - No matching row found\");\n\t\t\t}\n\t\t}\n\t\t\n\t\t//sort rows into correct order to ensure smooth delete from table\n\t\tfoundRows.sort((a, b) => {\n\t\t\treturn this.rowManager.rows.indexOf(a) > this.rowManager.rows.indexOf(b) ? 1 : -1;\n\t\t});\n\t\t\n\t\t//delete rows\n\t\tfoundRows.forEach((row) =>{\n\t\t\trow.delete();\n\t\t});\n\t\t\n\t\tthis.rowManager.reRenderInPosition();\n\t\t\n\t\treturn Promise.resolve();\n\t}\n\t\n\t//add row to table\n\taddRow(data, pos, index){\n\t\tthis.initGuard();\n\t\t\n\t\tif(typeof data === \"string\"){\n\t\t\tdata = JSON.parse(data);\n\t\t}\n\t\t\n\t\treturn this.rowManager.addRows(data, pos, index, true)\n\t\t\t.then((rows)=>{\n\t\t\t\treturn rows[0].getComponent();\n\t\t\t});\n\t}\n\t\n\t//update a row if it exists otherwise create it\n\tupdateOrAddRow(index, data){\n\t\tvar row = this.rowManager.findRow(index);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(typeof data === \"string\"){\n\t\t\tdata = JSON.parse(data);\n\t\t}\n\t\t\n\t\tif(row){\n\t\t\treturn row.updateData(data)\n\t\t\t\t.then(()=>{\n\t\t\t\t\treturn row.getComponent();\n\t\t\t\t});\n\t\t}else {\n\t\t\treturn this.rowManager.addRows(data)\n\t\t\t\t.then((rows)=>{\n\t\t\t\t\treturn rows[0].getComponent();\n\t\t\t\t});\n\t\t}\n\t}\n\t\n\t//update row data\n\tupdateRow(index, data){\n\t\tvar row = this.rowManager.findRow(index);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(typeof data === \"string\"){\n\t\t\tdata = JSON.parse(data);\n\t\t}\n\t\t\n\t\tif(row){\n\t\t\treturn row.updateData(data)\n\t\t\t\t.then(()=>{\n\t\t\t\t\treturn Promise.resolve(row.getComponent());\n\t\t\t\t});\n\t\t}else {\n\t\t\tconsole.warn(\"Update Error - No matching row found:\", index);\n\t\t\treturn Promise.reject(\"Update Error - No matching row found\");\n\t\t}\n\t}\n\t\n\t//scroll to row in DOM\n\tscrollToRow(index, position, ifVisible){\n\t\tvar row = this.rowManager.findRow(index);\n\t\t\n\t\tif(row){\n\t\t\treturn this.rowManager.scrollToRow(row, position, ifVisible);\n\t\t}else {\n\t\t\tconsole.warn(\"Scroll Error - No matching row found:\", index);\n\t\t\treturn Promise.reject(\"Scroll Error - No matching row found\");\n\t\t}\n\t}\n\t\n\tmoveRow(from, to, after){\n\t\tvar fromRow = this.rowManager.findRow(from);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(fromRow){\n\t\t\tfromRow.moveToRow(to, after);\n\t\t}else {\n\t\t\tconsole.warn(\"Move Error - No matching row found:\", from);\n\t\t}\n\t}\n\t\n\tgetRows(active){\n\t\treturn this.rowManager.getComponents(active);\t\n\t}\n\t\n\t//get position of row in table\n\tgetRowPosition(index){\n\t\tvar row = this.rowManager.findRow(index);\n\t\t\n\t\tif(row){\n\t\t\treturn row.getPosition();\n\t\t}else {\n\t\t\tconsole.warn(\"Position Error - No matching row found:\", index);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t/////////////// Column Functions  ///////////////\n\tsetColumns(definition){\n\t\tthis.initGuard(false, \"To set initial columns please use the 'columns' property in the table constructor\");\n\t\t\n\t\tthis.columnManager.setColumns(definition);\n\t}\n\t\n\tgetColumns(structured){\n\t\treturn this.columnManager.getComponents(structured);\n\t}\n\t\n\tgetColumn(field){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tif(column){\n\t\t\treturn column.getComponent();\n\t\t}else {\n\t\t\tconsole.warn(\"Find Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tgetColumnDefinitions(){\n\t\treturn this.columnManager.getDefinitionTree();\n\t}\n\t\n\tshowColumn(field){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(column){\n\t\t\tcolumn.show();\n\t\t}else {\n\t\t\tconsole.warn(\"Column Show Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\thideColumn(field){\n\t\tvar column = this.columnManager.findColumn(field); \n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(column){\n\t\t\tcolumn.hide();\n\t\t}else {\n\t\t\tconsole.warn(\"Column Hide Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\ttoggleColumn(field){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(column){\n\t\t\tif(column.visible){\n\t\t\t\tcolumn.hide();\n\t\t\t}else {\n\t\t\t\tcolumn.show();\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.warn(\"Column Visibility Toggle Error - No matching column found:\", field);\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\taddColumn(definition, before, field){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\treturn this.columnManager.addColumn(definition, before, column)\n\t\t\t.then((column) => {\n\t\t\t\treturn column.getComponent();\n\t\t\t});\n\t}\n\t\n\tdeleteColumn(field){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(column){\n\t\t\treturn column.delete();\n\t\t}else {\n\t\t\tconsole.warn(\"Column Delete Error - No matching column found:\", field);\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\tupdateColumnDefinition(field, definition){\n\t\tvar column = this.columnManager.findColumn(field);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(column){\n\t\t\treturn column.updateDefinition(definition);\n\t\t}else {\n\t\t\tconsole.warn(\"Column Update Error - No matching column found:\", field);\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\t\n\tmoveColumn(from, to, after){\n\t\tvar fromColumn = this.columnManager.findColumn(from),\n\t\ttoColumn = this.columnManager.findColumn(to);\n\t\t\n\t\tthis.initGuard();\n\t\t\n\t\tif(fromColumn){\n\t\t\tif(toColumn){\n\t\t\t\tthis.columnManager.moveColumn(fromColumn, toColumn, after);\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Move Error - No matching column found:\", toColumn);\n\t\t\t}\n\t\t}else {\n\t\t\tconsole.warn(\"Move Error - No matching column found:\", from);\n\t\t}\n\t}\n\t\n\t//scroll to column in DOM\n\tscrollToColumn(field, position, ifVisible){\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tvar column = this.columnManager.findColumn(field);\n\t\t\t\n\t\t\tif(column){\n\t\t\t\treturn this.columnManager.scrollToColumn(column, position, ifVisible);\n\t\t\t}else {\n\t\t\t\tconsole.warn(\"Scroll Error - No matching column found:\", field);\n\t\t\t\treturn Promise.reject(\"Scroll Error - No matching column found\");\n\t\t\t}\n\t\t});\n\t}\n\t\n\t//////////// General Public Functions ////////////\n\t//redraw list without updating data\n\tredraw(force){\n\t\tthis.initGuard();\n\n\t\tthis.columnManager.redraw(force);\n\t\tthis.rowManager.redraw(force);\n\t}\n\t\n\tsetHeight(height){\n\t\tthis.options.height = isNaN(height) ? height : height + \"px\";\n\t\tthis.element.style.height = this.options.height;\n\t\tthis.rowManager.initializeRenderer();\n\t\tthis.rowManager.redraw(true);\n\t}\n\t\n\t//////////////////// Event Bus ///////////////////\n\t\n\ton(key, callback){\n\t\tthis.externalEvents.subscribe(key, callback);\n\t}\n\t\n\toff(key, callback){\n\t\tthis.externalEvents.unsubscribe(key, callback);\n\t}\n\t\n\tdispatchEvent(){\n\t\tvar args = Array.from(arguments);\n\t\targs.shift();\n\t\t\n\t\tthis.externalEvents.dispatch(...arguments);\n\t}\n\n\t//////////////////// Alerts ///////////////////\n\n\talert(contents, type){\n\t\tthis.initGuard();\n\n\t\tthis.alertManager.alert(contents, type);\n\t}\n\n\tclearAlert(){\n\t\tthis.initGuard();\n\n\t\tthis.alertManager.clear();\n\t}\n\t\n\t////////////// Extension Management //////////////\n\tmodExists(plugin, required){\n\t\tif(this.modules[plugin]){\n\t\t\treturn true;\n\t\t}else {\n\t\t\tif(required){\n\t\t\t\tconsole.error(\"Tabulator Module Not Installed: \" + plugin);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tmodule(key){\n\t\tvar mod = this.modules[key];\n\t\t\n\t\tif(!mod){\n\t\t\tconsole.error(\"Tabulator module not installed: \" + key);\n\t\t}\n\t\t\n\t\treturn mod;\n\t}\n}\n\n//default setup options\nTabulator.defaultOptions = defaultOptions;\n\n//bind modules and static functionality\nnew ModuleBinder(Tabulator);\n\n//tabulator with all modules installed\n\nclass TabulatorFull extends Tabulator {}\n\n//bind modules and static functionality\nnew ModuleBinder(TabulatorFull, modules);\n\nclass PseudoRow {\n\n\tconstructor (type){\n\t\tthis.type = type;\n\t\tthis.element = this._createElement();\n\t}\n\n\t_createElement(){\n\t\tvar el = document.createElement(\"div\");\n\t\tel.classList.add(\"tabulator-row\");\n\t\treturn el;\n\t}\n\n\tgetElement(){\n\t\treturn this.element;\n\t}\n\n\tgetComponent(){\n\t\treturn false;\n\t}\n\n\tgetData(){\n\t\treturn {};\n\t}\n\n\tgetHeight(){\n\t\treturn this.element.outerHeight;\n\t}\n\n\tinitialize(){}\n\n\treinitialize(){}\n\n\tnormalizeHeight(){}\n\n\tgenerateCells(){}\n\n\treinitializeHeight(){}\n\n\tcalcHeight(){}\n\n\tsetCellHeight(){}\n\n\tclearCellHeight(){}\n\n\trendered(){}\n}\n\nexport { Accessor as AccessorModule, Ajax as AjaxModule, CalcComponent, CellComponent, Clipboard as ClipboardModule, ColumnCalcs as ColumnCalcsModule, ColumnComponent, DataTree as DataTreeModule, Download as DownloadModule, Edit$1 as EditModule, Export as ExportModule, Filter as FilterModule, Format as FormatModule, FrozenColumns as FrozenColumnsModule, FrozenRows as FrozenRowsModule, GroupComponent, GroupRows as GroupRowsModule, History as HistoryModule, HtmlTableImport as HtmlTableImportModule, Import as ImportModule, Interaction as InteractionModule, Keybindings as KeybindingsModule, Menu as MenuModule, Module, MoveColumns as MoveColumnsModule, MoveRows as MoveRowsModule, Mutator as MutatorModule, Page as PageModule, Persistence as PersistenceModule, Popup$1 as PopupModule, Print as PrintModule, PseudoRow, ReactiveData as ReactiveDataModule, Renderer, ResizeColumns as ResizeColumnsModule, ResizeRows as ResizeRowsModule, ResizeTable as ResizeTableModule, ResponsiveLayout as ResponsiveLayoutModule, RowComponent, SelectRange as SelectRangeModule, SelectRow as SelectRowModule, Sort as SortModule, Tabulator, TabulatorFull, Tooltip as TooltipModule, Validate as ValidateModule };\n//# sourceMappingURL=tabulator_esm.js.map\n","import angular from \"angular\";\r\nimport { ApiImportStatus, Dates, Numeric, EnumerationsLogic, Configs, ApiValidation, DataMapper, ApiValidationErrorType, OpenAPIV3, Occupations, Translations } from \"@salaxy/core\";\r\nimport { TabulatorFull as Tabulator } from \"tabulator-tables\";\r\nimport { JsonSchemaService } from \"../../../services\";\r\n\r\n\r\nlet XLSX = null;\r\n\r\n/**\r\n * Controller for data imports.\r\n */\r\nexport abstract class DataImportControllerBase<TSource, TTarget> implements angular.IController {\r\n\r\n  /** Tabular source row data. */\r\n  public sourceData: Array<TSource & { validation?: ApiValidation, importStatus?: ApiImportStatus }>;\r\n\r\n  /** Target objects mapped from source data, and which should be imported */\r\n  public targetData:  Array<TTarget & { validation?: ApiValidation, result?: {status?: ApiImportStatus}}>;\r\n\r\n  /** Table control*/\r\n  public table: any;\r\n\r\n  /** Current action */\r\n  public action: \"upload\" | \"validate\" | \"import\" = \"upload\";\r\n\r\n  /** Current import count */\r\n  public importCurrent = 0;\r\n\r\n  /** Total import count */\r\n  public importTotal = 0;\r\n\r\n  /** Flag for import in progress. */\r\n  public isImporting = false;\r\n\r\n  /** Flag for cancel. */\r\n  public isCanceled = false;\r\n\r\n  /** Data mapper */\r\n  protected mapper: DataMapper<TSource, TTarget>;\r\n\r\n  /**\r\n   * Creates a new DataImportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    /** JsonSchemaService */\r\n    protected jsonSchemaService: JsonSchemaService,\r\n    /** Angular timeout service */\r\n    protected $timeout: angular.ITimeoutService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public async $onInit(){\r\n    // Support both esm and umd builds...\r\n    XLSX = await Promise.resolve(Configs.global.XLSX);\r\n    this.init();\r\n  }\r\n\r\n  /**\r\n   * Download data or template\r\n   * @param helpData Help data in the form or array of arrays\r\n   */\r\n  public async download(helpData = null) {\r\n    // Take copy\r\n    const copied = angular.copy(this.sourceData);\r\n    if (copied.length < 1) {\r\n      const emptyRow: any = { };\r\n      this.mapper.source.keys.forEach((key) => {\r\n        emptyRow[key] = null;\r\n      });\r\n      copied.push(emptyRow);\r\n    }\r\n     // remove validation\r\n     for(const row of copied) {\r\n      delete row.validation;\r\n    }\r\n    const sheet = XLSX.utils.json_to_sheet(copied);\r\n    const workbook = XLSX.utils.book_new();\r\n    XLSX.utils.book_append_sheet(workbook, sheet, \"data\");\r\n    if (helpData){\r\n      const helpSheet = XLSX.utils.aoa_to_sheet(helpData);\r\n      XLSX.utils.book_append_sheet(workbook, helpSheet, \"help\");\r\n    }\r\n    XLSX.writeFile(workbook, \"import.xlsx\");\r\n  }\r\n\r\n  /** Upload rows to table */\r\n  public async upload(files: any[]) {\r\n    if (files && files.length) {\r\n      this.reset();\r\n      const file = files[0];\r\n      const fileData = await file.arrayBuffer();\r\n      /* data is an ArrayBuffer */\r\n      const workbook = XLSX.read(fileData);\r\n      if (workbook?.SheetNames?.length > 0) {\r\n        const sheet = workbook.Sheets[workbook.SheetNames[0]];\r\n        const sheetData = XLSX.utils.sheet_to_json(sheet);\r\n        this.sourceData = [];\r\n        sheetData.forEach( (sheetRow) => {\r\n          if (this.hasData(sheetRow)) {\r\n            const row: any = { validation: {}};\r\n            this.mapper.source.keys.forEach((key) => {\r\n              this.setFieldValue(row,key,sheetRow[key] ?? null);\r\n            });\r\n            this.sourceData.push(row);\r\n          }\r\n        });\r\n      }\r\n      this.table.setData(this.sourceData);\r\n      await this.$timeout();\r\n    }\r\n  }\r\n\r\n  /** Reset data */\r\n  public reset(setData = false) {\r\n    this.importTotal = 0;\r\n    this.importCurrent = 0;\r\n    this.isImporting = false;\r\n    this.isCanceled = false;\r\n    this.sourceData = [];\r\n    this.targetData = null;\r\n    if (this.table && setData) {\r\n      this.table.setData(this.sourceData);\r\n      this.$timeout();\r\n    }\r\n  }\r\n\r\n  /** Paste data */\r\n  public async paste() {\r\n    const text = await (navigator as any).clipboard.readText();\r\n    if (text) {\r\n\t\t\tconst rowData =  this.table.modules.clipboard.pasteParser(text);\r\n\t\t\tif(rowData){\r\n\t\t\t\tthis.table.modules.clipboard.pasteAction(rowData);\r\n      }\r\n      await this.$timeout();\r\n    }\r\n  }\r\n\r\n  /** Map and validate data */\r\n  public async validate() {\r\n    this.importTotal = 0;\r\n    let isValid = true;\r\n    for(const row of this.sourceData) {\r\n      let isValidRow = true;\r\n      row.importStatus = ApiImportStatus.Ignored;\r\n      row.validation = null;\r\n      for(const field of this.mapper.source.keys) {\r\n        if (!this.validateField(field, row[field])) {\r\n          if (isValidRow) {\r\n            isValidRow = false;\r\n            isValid = false;\r\n            row.validation = {\r\n              isValid: false,\r\n              errors: [\r\n               {\r\n                 type: ApiValidationErrorType.General,\r\n                 msg: `${Translations.get(\"SALAXY.NG1.DataImport.messageInvalid\")} ${this.getFieldTitle(field)}`\r\n               }\r\n              ]\r\n            };\r\n          }\r\n        }\r\n      }\r\n      if (isValidRow) {\r\n        row.validation = {\r\n          isValid : true,\r\n          errors: [],\r\n        };\r\n      }\r\n    }\r\n    if (isValid) {\r\n      this.targetData = this.mapper.doMap(this.sourceData);\r\n    }\r\n    else\r\n    {\r\n      this.targetData = null;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n  }\r\n\r\n  /** Returns extra validator */\r\n  public getExtraValidators(): Array<{ validate: () => void, buttonLabel: string }> {\r\n    return [];\r\n  }\r\n\r\n  /** Enrichs data */\r\n  public getDataEnrichers(): Array<{ enrich: () => void, buttonLabel: string }> {\r\n    return [];\r\n  }\r\n\r\n  /** Cancel import */\r\n  public cancel() {\r\n    this.isCanceled = true;\r\n  }\r\n\r\n  /** Import data */\r\n  public abstract import();\r\n\r\n  /** Help */\r\n  public abstract help();\r\n\r\n  /** Returns number of undefined validation rows */\r\n  public get validationUndoneRows() {\r\n    return this.sourceData.filter( (r) => !r.validation?.isValid &&  r.validation?.isValid !== false).length;\r\n  }\r\n\r\n  /** Returns number of success rows */\r\n  public get validationSuccessRows() {\r\n    return this.sourceData.filter( (r) => r.validation?.isValid === true).length;\r\n  }\r\n\r\n  /** Returns number of error rows */\r\n  public get validationErrorRows() {\r\n    return this.sourceData.filter( (r) => r.validation?.isValid === false).length;\r\n  }\r\n\r\n  /** Returns number of success rows */\r\n  public get importSuccessRows() {\r\n    return this.getImportStatusRows(ApiImportStatus.Success);\r\n  }\r\n\r\n  /** Returns number of error rows */\r\n  public get importErrorRows() {\r\n    return this.getImportStatusRows(ApiImportStatus.Error);\r\n  }\r\n\r\n  /** Returns number of warning rows */\r\n  public get importWarningRows() {\r\n    return this.getImportStatusRows(ApiImportStatus.Warning);\r\n  }\r\n\r\n  /** Returns number of success rows */\r\n  public get importIgnoredRows() {\r\n    return this.getImportStatusRows(ApiImportStatus.Ignored);\r\n  }\r\n\r\n  protected getFieldTitle(field: string): string {\r\n    return field;\r\n  }\r\n\r\n  protected getEditor(field: string): any {\r\n    // OpenAPIV3.NonArraySchemaObjectType \"string\" | \"number\" | \"boolean\" | \"object\" | \"integer\"\r\n    const fieldSchema = this.mapper.source.schema.properties[field] as OpenAPIV3.SchemaObject;\r\n\r\n\r\n    switch (fieldSchema?.type) {\r\n      case \"string\":\r\n      {\r\n        switch ( fieldSchema.format ) {\r\n          case \"date\":\r\n            return { editor: \"date\" };\r\n          case \"date-time\":\r\n            return { editor: \"datetime\" };\r\n          case \"multiline\":\r\n            return { editor: \"textarea\" };\r\n        }\r\n        if (fieldSchema.format == \"Occupation\") {\r\n          const occupations = Occupations.getAll();\r\n          return {\r\n            editor: \"list\",\r\n            editorParams: {\r\n             values: occupations.map( (e) =>  ({value: e.code, label: e.label})),\r\n             autocomplete: true,\r\n            }\r\n          };\r\n        } else if (fieldSchema.format && fieldSchema.enum?.length > 0) {\r\n          const enumMetadata = EnumerationsLogic.getEnumMetadata(fieldSchema.format);\r\n          return {\r\n            editor: \"list\",\r\n            formatter:function(cell, /*formatterParams, onRendered */){\r\n              //cell - the cell component\r\n              //formatterParams - parameters set for the column\r\n              //onRendered - function to call when the formatter has been rendered\r\n              const value = cell.getValue();\r\n              if (!value) {\r\n                return null;\r\n              }\r\n              return enumMetadata.values.find( (e) => e.name == value)?.label ?? value;\r\n            },\r\n            editorParams: {\r\n             values: enumMetadata.values.map( (e) =>  ({value: e.name, label: e.label})),\r\n            }\r\n          };\r\n        }\r\n        break;\r\n      }\r\n      case \"number\":\r\n      case \"integer\":\r\n          return { editor: \"number\" };\r\n      case \"boolean\":\r\n          return { editor: \"tickCross\" };\r\n    }\r\n    return { editor: \"input\" };\r\n  }\r\n\r\n  protected validateField(field: string, value: any): boolean {\r\n    if (!field) {\r\n      return true;\r\n    }\r\n    const fieldSchema = this.mapper.source.schema.properties[field] as OpenAPIV3.SchemaObject;\r\n    switch (fieldSchema?.type) {\r\n      case \"string\":{\r\n          if (!value) {\r\n            return true;\r\n          }\r\n          if ( typeof value !== \"string\" ) {\r\n            return false;\r\n          }\r\n          switch ( fieldSchema.format ) {\r\n            case \"date\":\r\n            case \"date-time\":\r\n            {\r\n              return Dates.isValidDateTime(value);\r\n            }\r\n          }\r\n          if (fieldSchema.format == \"Occupation\") {\r\n            const occupations = Occupations.getAll();\r\n            return occupations.some( (o) => o.code === value);\r\n          } else if (fieldSchema.format && fieldSchema.enum?.length > 0) {\r\n            const enumMetadata = EnumerationsLogic.getEnumMetadata(fieldSchema.format);\r\n            return enumMetadata.values.some( (e) => e.name === value);\r\n          }\r\n          return true;\r\n        }\r\n      case \"number\":\r\n      case \"integer\": {\r\n          if (value == null || value == undefined) {\r\n            return true;\r\n          }\r\n          return typeof value === \"number\" || typeof value === \"bigint\";\r\n        }\r\n      case \"boolean\": {\r\n          if (value == null || value == undefined) {\r\n            return true;\r\n          }\r\n          return typeof value === \"boolean\";\r\n        }\r\n      default: {\r\n          if (value == null || value == undefined) {\r\n            return true;\r\n          }\r\n          return typeof value === \"string\";\r\n        }\r\n      }\r\n  }\r\n\r\n  /** Default help data for columns. */\r\n  protected getDefaultHelpDataForColumns() {\r\n    return [\r\n      [Translations.get(\"SALAXY.NG1.DataImport.help.fields.title\")],\r\n      [Translations.get(\"SALAXY.NG1.DataImport.help.fields.id\"), Translations.get(\"SALAXY.NG1.DataImport.help.fields.type\"), Translations.get(\"SALAXY.NG1.DataImport.help.fields.name\"), Translations.get(\"SALAXY.NG1.DataImport.help.fields.description\")],\r\n      ...(this.mapper.source.keys.map((f) =>\r\n      [\r\n        f,\r\n        (this.mapper.source.schema.properties[f] as any)?.format ||  (this.mapper.source.schema.properties[f] as any)?.type || \"string\",\r\n        Translations.getWithDefault((this.mapper.source.schema.properties[f] ?? {})[\"x-salaxy-title\"],\"\"),\r\n        Translations.getWithDefault((this.mapper.source.schema.properties[f] ?? {})[\"x-salaxy-description\"],\"\")\r\n      ])),\r\n      [\"\"],\r\n      [Translations.get(\"SALAXY.NG1.DataImport.help.values.title\")],\r\n      [Translations.get(\"SALAXY.NG1.DataImport.help.values.type\"),Translations.get(\"SALAXY.NG1.DataImport.help.values.value\"), Translations.get(\"SALAXY.NG1.DataImport.help.values.description\")],\r\n      ...(this.mapper.source.keys.filter((f) => this.getEditor(f)?.editor === \"list\").flatMap((f) =>\r\n        this.getEditor(f)?.editorParams.values.map( (v) => [(this.mapper.source.schema.properties[f] as any).format, v.value, v.label] as any)\r\n      ))\r\n    ];\r\n  }\r\n\r\n  private setFieldValue(row: any, field: string, value: any) {\r\n    const fieldSchema = this.mapper?.source.schema.properties ? this.mapper.source.schema.properties[field] as OpenAPIV3.SchemaObject : undefined;\r\n    switch (fieldSchema?.type) {\r\n      case \"string\": {\r\n        if ( value != null && value != undefined) {\r\n          if (fieldSchema.format == \"date\" || fieldSchema.format == \"date-time\") {\r\n            if (typeof value === \"number\") {\r\n              const y1900 = Dates.getDate(1900,1,1);\r\n              value = Dates.add(y1900, value - 2, \"day\");\r\n            }\r\n          }\r\n          else if (fieldSchema.format && (fieldSchema.enum?.length ?? -1) > 0) {\r\n            const enumMetadata = EnumerationsLogic.getEnumMetadata(fieldSchema.format);\r\n            const lowerValue = value.toLowerCase();\r\n            const candidate = enumMetadata.values.find( (e) => e.name.toLowerCase() === lowerValue);\r\n            if (candidate) {\r\n              value = candidate.name;\r\n            }\r\n          }\r\n          else {\r\n            if (typeof value === \"number\" || typeof value === \"bigint\" || typeof value === \"boolean\" ) {\r\n              value = `${value}`;\r\n            }\r\n          }\r\n        }\r\n        break;\r\n      }\r\n      case \"number\": {\r\n        if ( value != null && value != undefined && typeof value === \"string\") {\r\n          value = Numeric.parseNumber(value);\r\n        }\r\n        break;\r\n      }\r\n      case \"integer\": {\r\n        if ( value != null && value != undefined && typeof value === \"string\") {\r\n          value = Numeric.round(Numeric.parseNumber(value),0);\r\n        }\r\n        break;\r\n      }\r\n      case \"boolean\": {\r\n        if ( value != null && value != undefined && typeof value === \"string\") {\r\n          value = ( value.toLowerCase() == \"TRUE\" );\r\n        }\r\n        break;\r\n      }\r\n      default:\r\n        break;\r\n    }\r\n    row[field] = value;\r\n  }\r\n\r\n  /** Returns the import mapper */\r\n  protected abstract getImportMapper(): Promise<DataMapper<TSource, TTarget>>;\r\n\r\n\r\n  private getImportStatusRows(status: ApiImportStatus) {\r\n    return this.sourceData.filter( (r) => r.importStatus == status).length;\r\n  }\r\n\r\n  private async init() {\r\n\r\n    this.mapper = await this.getImportMapper();\r\n    this.reset();\r\n    this.table = new Tabulator(\"#import-table\", {\r\n      height: \"calc(100vh - 500px)\", // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)\r\n      data: this.sourceData, //assign data to table\r\n      layout: \"fitColumns\", //fit columns to width of table (optional)\r\n      clipboard: true,\r\n      clipboardPasteAction: ((sheetData: any) => {\r\n        this.reset();\r\n        sheetData.forEach( (sheetRow) => {\r\n          if (this.hasData(sheetRow)) {\r\n            const row = { validation: {}} as any;\r\n            this.mapper.source.keys.forEach((key) => {\r\n              this.setFieldValue(row,key,sheetRow[key] ?? null);\r\n            });\r\n            this.sourceData.push(row);\r\n          }\r\n        });\r\n        this.table.setData(this.sourceData);\r\n        return this.sourceData;\r\n      }) as any,\r\n      columns: [\r\n        {\r\n          title: Translations.get(\"SALAXY.NG1.DataImport.columnImportStatus\"),\r\n          field: \"importStatus\",\r\n          formatter:function(cell, /*formatterParams, onRendered */){\r\n            //cell - the cell component\r\n            //formatterParams - parameters set for the column\r\n            //onRendered - function to call when the formatter has been rendered\r\n\r\n            const status = cell.getValue() ?? ApiImportStatus.Ignored;\r\n            switch (status) {\r\n              case ApiImportStatus.Ignored:\r\n                return `<span class=\"text-default\">${Translations.get(\"SALAXY.NG1.DataImport.ignoredLabel\")}</span>`;\r\n              case ApiImportStatus.Success:\r\n                return `<span class=\"text-success\" >${Translations.get(\"SALAXY.NG1.DataImport.successLabel\")}</span>`;\r\n              case ApiImportStatus.Error:\r\n                return `<span class=\"text-danger\" >${Translations.get(\"SALAXY.NG1.DataImport.errorLabel\")}</span>`;\r\n              case ApiImportStatus.Warning:\r\n                return `<span class=\"text-warning\" >${Translations.get(\"SALAXY.NG1.DataImport.warningLabel\")}</span>`;\r\n            }\r\n            return null;\r\n          },\r\n          headerSort:false,\r\n        },\r\n        {\r\n          title: Translations.get(\"SALAXY.NG1.DataImport.columnValidation\"),\r\n          field: \"validation\",\r\n          formatter:function(cell, /*formatterParams, onRendered */){\r\n            //cell - the cell component\r\n            //formatterParams - parameters set for the column\r\n            //onRendered - function to call when the formatter has been rendered\r\n\r\n            const validation: ApiValidation = cell.getValue();\r\n            if (!validation) {\r\n              return null;\r\n            }\r\n\r\n            // null or undefined\r\n            if (!validation.isValid && validation.isValid !== false ) {\r\n              if (validation.errors?.length > 0) {\r\n                return `<span class=\"text-warning\">${(validation.errors ?? []).map( (e) => e.msg).join(\"<br>\")}</span>`;\r\n              }\r\n              return null;\r\n            }\r\n\r\n            if (validation.isValid !== false) {\r\n              if (validation.errors?.length > 0) {\r\n                return `<span class=\"text-success\">${(validation.errors ?? []).map( (e) => e.msg).join(\"<br>\")}</span>`;\r\n              }\r\n              return `<span class=\"text-success\">Ok</span>`;\r\n            }\r\n            else {\r\n              return `<span class=\"text-danger\" >${(validation.errors ?? []).map( (e) => e.msg).join(\"<br>\")}</span>`;\r\n            }\r\n          },\r\n          headerSort:false,\r\n        },\r\n        ... this.mapper.source.keys.map((x) => ({\r\n          title: this.getFieldTitle(x),\r\n          field: x,\r\n          ... this.getEditor(x),\r\n          headerSort:false,\r\n          headerVertical:\"flip\",\r\n        }))\r\n      ]\r\n    });\r\n\r\n    //trigger an alert message when the row is clicked\r\n    this.table.on(\"cellEdited\", async () => {\r\n      await this.$timeout();\r\n    });\r\n\r\n    await this.$timeout();\r\n  }\r\n\r\n  private hasData(sheetRow: any): boolean {\r\n    if (!sheetRow) {\r\n      return false;\r\n    }\r\n    let dataOk = false;\r\n    for(const key of Object.keys(sheetRow)) {\r\n      dataOk = dataOk || (sheetRow[key] != null && sheetRow[key] != undefined &&\r\n          !(typeof sheetRow[key] === \"string\" && sheetRow[key].trim().length == 0));\r\n      if (dataOk) {\r\n        return dataOk;\r\n      }\r\n    }\r\n    return dataOk;\r\n  }\r\n}","import angular from \"angular\";\r\nimport { ApiImportStatus, Imports, DataMapper, CompanyImportRow,CompanyImport, ApiValidationErrorType, Translations, EInvoiceAddress } from \"@salaxy/core\";\r\n\r\nimport { DataImportControllerBase } from \"./DataImportControllerBase\";\r\n\r\nimport { EditDialogKnownActions, JsonSchemaService, UiHelpers } from \"../../../services\";\r\n\r\n\r\n/**\r\n * Controller for company imports.\r\n */\r\nexport class CompanyImportController extends DataImportControllerBase<CompanyImportRow, CompanyImport> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Imports\", \"JsonSchemaService\", \"$timeout\", \"UiHelpers\"];\r\n\r\n  private dataEnricher = {\r\n    enrich: () => this.enrichEInvoiceAddresses(),\r\n    buttonLabel: Translations.get(\"SALAXY.NG1.CompanyImport.enrichEInvoiceAddressesButton\")\r\n  };\r\n\r\n  /**\r\n   * Creates a new WorkerImportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private importsApi: Imports,\r\n    jsonSchemaService: JsonSchemaService,\r\n    $timeout: angular.ITimeoutService,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    super(jsonSchemaService, $timeout);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public async $onInit(){\r\n    super.$onInit();\r\n  }\r\n\r\n\r\n  /** Enrichs data */\r\n  public getDataEnrichers(): Array<{ enrich: () => void, buttonLabel: string }> {\r\n    return [this.dataEnricher];\r\n  }\r\n\r\n\r\n  /** Import data */\r\n  public async import() {\r\n\r\n    if (this.isImporting) {\r\n      return;\r\n    }\r\n\r\n    await this.validate();\r\n    if (!this.targetData) {\r\n      return;\r\n    }\r\n\r\n    this.isImporting = true;\r\n    this.isCanceled = false;\r\n\r\n    for(const sourceRow of this.sourceData) {\r\n      sourceRow.validation = null;\r\n      sourceRow.importStatus = ApiImportStatus.Ignored;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n\r\n    const getTargetKey = (x: CompanyImport) => `${x.item.officialId}`.toLowerCase();\r\n    const getSourceKey = (x: CompanyImportRow) => `${x.officialId}`.toLowerCase();\r\n\r\n    this.importTotal = this.targetData.length;\r\n    this.importCurrent = 0;\r\n\r\n    const chunkSize = 10;\r\n    const chunks: CompanyImport[][] = [];\r\n    for (let i = 0; i < this.targetData.length; i += chunkSize) {\r\n        chunks.push(this.targetData.slice(i, i + chunkSize));\r\n    }\r\n\r\n    let index = 0;\r\n    for(const chunk of chunks) {\r\n      try {\r\n        if (this.isCanceled) {\r\n          break;\r\n        }\r\n        chunk.splice(0, chunk.length, ... await this.importsApi.importCompanies(chunk));\r\n      } catch (error) {\r\n        for( const importObj of chunk) {\r\n          importObj.result = importObj.result ?? {};\r\n          importObj.result.status = ApiImportStatus.Error,\r\n          importObj.validation = {\r\n            isValid: false,\r\n            errors: [{\r\n              key: null,\r\n              type: ApiValidationErrorType.General,\r\n              code: \"Server error\",\r\n              msg: error?.data?.messageHtml || JSON.stringify(error?.data, Object.getOwnPropertyNames(error?.data)),\r\n            }],\r\n          };\r\n        }\r\n      }\r\n      for(const result of chunk) {\r\n        const sourceRows = this.sourceData.filter((x) => getSourceKey(x) == getTargetKey(result));\r\n        for(const sourceRow of sourceRows) {\r\n          sourceRow.validation = {\r\n            isValid: result.validation?.isValid,\r\n            errors: result.validation?.errors\r\n          };\r\n          sourceRow.importStatus = result.result?.status;\r\n        }\r\n        index += sourceRows.length;\r\n        this.importCurrent = index;\r\n\r\n        this.table.setData(this.sourceData);\r\n        await this.$timeout();\r\n      }\r\n    }\r\n    this.isImporting = false;\r\n    await this.$timeout();\r\n  }\r\n\r\n  /** Help */\r\n  public async help() {\r\n    const helpData = [\r\n      [Translations.get(\"SALAXY.NG1.CompanyImport.help.title\")],\r\n      [\"\"],\r\n      [Translations.get(\"SALAXY.NG1.CompanyImport.help.overview.title\")],\r\n      [Translations.get(\"SALAXY.NG1.CompanyImport.help.overview.row1\")],\r\n      [Translations.get(\"SALAXY.NG1.CompanyImport.help.overview.row2\")],\r\n      [\"\"],\r\n       ...this.getDefaultHelpDataForColumns(),\r\n    ];\r\n    await this.download(helpData);\r\n  }\r\n\r\n  protected async getImportMapper() {\r\n    const mapper = new DataMapper<CompanyImportRow, CompanyImport>(\"NG1/CompanyImportController\", \"Asiakkaat\");\r\n    const map = {\r\n      officialId: \"item.officialId\",\r\n      partnerAccountId: \"item.partnerAccountId\",\r\n      email: \"item.email\",\r\n      telephone: \"item.telephone\",\r\n      contactFirstName: \"item.contactFirstName\",\r\n      contactLastname: \"item.contactLastName\",\r\n      proxyPartner: \"item.proxyPartner\",\r\n      language: \"item.language\",\r\n      eInvoiceReceiver: \"parameters.settings.payments.invoice.eInvoiceReceiver\",\r\n      eInvoiceIntermediator: \"parameters.settings.payments.invoice.eInvoiceIntermediator\",\r\n    };\r\n    await mapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"CompanyImport\", \"target\");\r\n    mapper.setPaths(map);\r\n    mapper.generateSchema(\"CompanyImportRow\", \"source\");\r\n    return mapper;\r\n  }\r\n\r\n  private async enrichEInvoiceAddresses() {\r\n    if (!this.sourceData || this.sourceData.length == 0) {\r\n      return;\r\n    }\r\n    const dialog = this.uiHelpers.showLoading(\"SALAXY.NG1.CompanyImport.enrichEInvoiceAddressesMessage\", \"\");\r\n    for (const row of this.sourceData) {\r\n      if (row.eInvoiceReceiver && row.eInvoiceIntermediator) {\r\n        continue;\r\n      }\r\n      dialog.setText(row.officialId);\r\n      const addresses = await this.importsApi.queryEInvoiceAddress(row.officialId);\r\n      if (addresses.length == 0) {\r\n        continue;\r\n      }\r\n      if (addresses.length ==  1) {\r\n        row.eInvoiceReceiver = addresses[0].receiver;\r\n        row.eInvoiceIntermediator = addresses[0].intermediator;\r\n        await this.validate();\r\n        continue;\r\n      }\r\n      const currentSelection: EInvoiceAddress = null;\r\n      const selectionDialog = await this.uiHelpers.openEditDialog(\"salaxy-components/helpers/import/EInvoiceAddressSelect.html\", { selection: currentSelection }, { addresses, select: (current, row, close) => { current.selection = row; close(EditDialogKnownActions.Ok); } });\r\n      if (selectionDialog.result == EditDialogKnownActions.Ok && selectionDialog.item.selection?.receiver && selectionDialog.item.selection?.intermediator) {\r\n          row.eInvoiceReceiver = selectionDialog.item.selection?.receiver;\r\n          row.eInvoiceIntermediator = selectionDialog.item.selection?.intermediator;\r\n          await this.validate();\r\n          continue;\r\n      }\r\n    }\r\n    dialog.dismiss();\r\n  }\r\n}","import angular from \"angular\";\r\nimport { ApiCheckStatus, ApiValidationErrorType, ApiImportStatus, Dates, Arrays, UserDefinedRow, Imports, DataMapper, DataMapperSelector, CalculationImportRow, CalculationImport, WorkerCheck, Translations } from \"@salaxy/core\";\r\n\r\nimport { DataImportControllerBase } from \"./DataImportControllerBase\";\r\n\r\nimport { JsonSchemaService } from \"../../../services\";\r\n\r\n/**\r\n * Controller for calculation imports.\r\n */\r\nexport class CalcImportController extends DataImportControllerBase<CalculationImportRow, CalculationImport> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Imports\", \"JsonSchemaService\", \"$timeout\"];\r\n\r\n  /** Boolean indicating if the worker validation is in progress. */\r\n  public isValidating = false;\r\n\r\n  // check SalaryDate, should not be changed in server\r\n  private getTargetKey = (x: CalculationImport) => `${x.officialId}_${x.item.worker.paymentData.socialSecurityNumber}_${Dates.asDate(x.item.workflow.salaryDate)}_${x.parameters.payroll.input.title}`.toLowerCase();\r\n  private getSourceKey = (x: CalculationImportRow) => `${x.companyOfficialId}_${x.personalId}_${Dates.asDate(x.salaryDate)}_${x.payrollTitle}`.toLowerCase();\r\n  private getCheckTargetKey = (x: WorkerCheck) => `${x.officialId}_${x.id}`.toLowerCase();\r\n  private getCheckSourceKey = (x: CalculationImportRow) => `${x.companyOfficialId}_${x.employmentId || x.personalId}`.toLowerCase();\r\n\r\n  private extraValidator = {\r\n    validate: () => this.validateWorkers(),\r\n    buttonLabel: Translations.get(\"SALAXY.NG1.CalcImport.validateWorkersButton\")\r\n  };\r\n\r\n  /**\r\n   * Creates a new WorkerImportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private importsApi: Imports,\r\n    jsonSchemaService: JsonSchemaService,\r\n    $timeout: angular.ITimeoutService\r\n  ) {\r\n    super(jsonSchemaService, $timeout);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public async $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Import data */\r\n  public async import() {\r\n\r\n    if (this.isImporting) {\r\n      return;\r\n    }\r\n\r\n    await this.validate();\r\n    if (!this.targetData) {\r\n      return;\r\n    }\r\n\r\n    this.isImporting = true;\r\n    this.isCanceled = false;\r\n\r\n    for(const sourceRow of this.sourceData) {\r\n      sourceRow.validation = null;\r\n      sourceRow.importStatus = ApiImportStatus.Ignored;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n\r\n    this.importTotal = this.targetData.length;\r\n    this.importCurrent = 0;\r\n\r\n    // compose calculations\r\n    // group by officialId, personalId and salaryDate\r\n    const groups = Arrays.groupBy(this.targetData, this.getTargetKey);\r\n    const imports = [];\r\n    for(const key in groups) {\r\n      const groupCalcs = groups[key];\r\n      const firstCalc = groupCalcs.splice(0,1)[0];\r\n      for(const calc of groupCalcs) {\r\n        firstCalc.item.rows.push(... calc.item.rows);\r\n      }\r\n      imports.push(firstCalc);\r\n    }\r\n\r\n    const chunkSize = 10;\r\n    const chunks: CalculationImport[][] = [];\r\n    for (let i = 0; i < imports.length; i += chunkSize) {\r\n        chunks.push(imports.slice(i, i + chunkSize));\r\n    }\r\n\r\n    let index = 0;\r\n    for(const chunk of chunks) {\r\n      try {\r\n        if (this.isCanceled) {\r\n          break;\r\n        }\r\n        chunk.splice(0, chunk.length, ... await this.importsApi.importCalculations(chunk));\r\n      } catch (error) {\r\n        for( const importObj of chunk) {\r\n          importObj.result = importObj.result ?? {};\r\n          importObj.result.status = ApiImportStatus.Error,\r\n          importObj.validation = {\r\n            isValid: false,\r\n            errors: [{\r\n              key: null,\r\n              type: ApiValidationErrorType.General,\r\n              code: \"Server error\",\r\n              msg: error?.data?.messageHtml || JSON.stringify(error?.data, Object.getOwnPropertyNames(error?.data)),\r\n            }],\r\n          };\r\n        }\r\n      }\r\n      for(const result of chunk) {\r\n        const sourceRows = this.sourceData.filter((x) => this.getSourceKey(x) == this.getTargetKey(result));\r\n        for(const sourceRow of sourceRows) {\r\n          sourceRow.validation = {\r\n            isValid: result.validation?.isValid,\r\n            errors: result.validation?.errors\r\n          };\r\n          sourceRow.importStatus = result.result?.status;\r\n        }\r\n        index += sourceRows.length;\r\n        this.importCurrent = index;\r\n\r\n        this.table.setData(this.sourceData);\r\n        await this.$timeout();\r\n      }\r\n    }\r\n\r\n    this.isImporting = false;\r\n    await this.$timeout();\r\n  }\r\n\r\n  /** Help */\r\n  public async help() {\r\n    const helpData = [\r\n        [Translations.get(\"SALAXY.NG1.CalcImport.help.title\")],\r\n        [\"\"],\r\n        [Translations.get(\"SALAXY.NG1.CalcImport.help.overview.title\")],\r\n        [Translations.get(\"SALAXY.NG1.CalcImport.help.overview.row1\")],\r\n        [Translations.get(\"SALAXY.NG1.CalcImport.help.overview.row2\")],\r\n        [\"\"],\r\n        ...this.getDefaultHelpDataForColumns(),\r\n      ];\r\n\r\n    await this.download(helpData);\r\n  }\r\n\r\n  /** Returns extra validator */\r\n  public getExtraValidators(): Array<{ validate: () => void, buttonLabel: string }> {\r\n    return [this.extraValidator];\r\n  }\r\n\r\n  protected async getImportMapper() {\r\n\r\n    const rowMap = {\r\n      rowType: \"rowType\",\r\n      message: \"message\",\r\n      kind: \"data.kind\",\r\n      count: \"count\",\r\n      price: \"price\",\r\n      rowSourceId: \"sourceId\",\r\n      vatPercent: \"accounting.vatPercent\",\r\n    };\r\n\r\n    const rowMapper = new DataMapper<CalculationImportRow, UserDefinedRow>(\"NG1/CalcImporController\", \"Palkkalaskelmat\");\r\n    await rowMapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"UserDefinedRow\", \"target\");\r\n    rowMapper.setPaths(rowMap);\r\n    rowMapper.generateSchema(\"CalculationImportRow\", \"source\");\r\n\r\n    const rowSelector = new DataMapperSelector<CalculationImportRow, CalculationImport>(null, \"item.rows\",\r\n      (source) => {\r\n        if (source.rowType && source.price > 0) {\r\n          return rowMapper.doMap([source]);\r\n        }\r\n        return [];\r\n      });\r\n\r\n    const mapper = new DataMapper<CalculationImportRow, CalculationImport>(\"NG1/CalcImportController\", \"Palkkalaskelmat\");\r\n    const map = {\r\n      companyOfficialId: \"officialId\",\r\n      personalId: \"item.worker.paymentData.socialSecurityNumber\",\r\n      employmentId: \"item.worker.employmentId\",\r\n      occupationCode: \"item.info.occupationCode\",\r\n      periodStart: \"item.info.workStartDate\",\r\n      periodEnd: \"item.info.workEndDate\",\r\n      workDescription: \"item.info.workDescription\",\r\n      salarySlipMessage: \"item.info.salarySlipMessage\",\r\n      salaryDate: \"item.workflow.salaryDate\",\r\n      paymentChannel: \"item.info.paymentChannel\",\r\n      payrollTitle: \"parameters.payroll.input.title\",\r\n      payrollSourceId: \"parameters.payroll.input.sourceId\",\r\n      sourceId: \"item.info.sourceId\",\r\n      fixedTaxAmount: \"item.worker.tax.fixedTaxAmount\",\r\n      rowType: rowSelector,\r\n    };\r\n    await mapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"CalculationImport\", \"target\");\r\n    mapper.setPaths(map);\r\n    mapper.generateSchema(\"CalculationImportRow\", \"source\");\r\n\r\n    mapper.source.schema.properties.occupationCode[\"format\"] =\"Occupation\";\r\n    for(const property in rowMapper.source.schema.properties) {\r\n      mapper.source.schema.properties[property] = rowMapper.source.schema.properties[property];\r\n    }\r\n\r\n    return mapper;\r\n  }\r\n\r\n  /** Import data */\r\n  private async validateWorkers() {\r\n\r\n    if (this.isValidating) {\r\n      return;\r\n    }\r\n\r\n    await this.validate();\r\n    if (!this.targetData) {\r\n      return;\r\n    }\r\n\r\n    this.isValidating = true;\r\n\r\n    for(const sourceRow of this.sourceData) {\r\n      sourceRow.validation = null;\r\n      sourceRow.validation = {\r\n        isValid: null, // null on purpose\r\n        errors: [{\r\n          type: ApiValidationErrorType.General,\r\n          msg: Translations.get(\"SALAXY.UI_Terms.wait\"),\r\n        }],\r\n      };\r\n      sourceRow.importStatus = ApiImportStatus.Ignored;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n\r\n    const workerGroups = Arrays.groupBy(this.sourceData, this.getCheckSourceKey);\r\n    const workerChecks: WorkerCheck[] = [];\r\n    for(const workerGroupKey in workerGroups) {\r\n      workerChecks.push( {\r\n        officialId: workerGroups[workerGroupKey][0].companyOfficialId,\r\n        id: workerGroups[workerGroupKey][0].employmentId || workerGroups[workerGroupKey][0].personalId,\r\n      });\r\n    }\r\n\r\n    const chunkSize = 10;\r\n    const chunks: WorkerCheck[][] = [];\r\n    for (let i = 0; i < workerChecks.length; i += chunkSize) {\r\n        chunks.push(workerChecks.slice(i, i + chunkSize));\r\n    }\r\n\r\n    for(const chunk of chunks) {\r\n      try {\r\n        chunk.splice(0, chunk.length, ... await this.importsApi.checkWorkers(chunk));\r\n      } catch (error) {\r\n        for( const checkObj of chunk) {\r\n          checkObj.result = checkObj.result ?? {};\r\n          checkObj.result.status = ApiCheckStatus.Error,\r\n          checkObj.validation = {\r\n            isValid: false,\r\n            errors: [{\r\n              key: null,\r\n              type: ApiValidationErrorType.General,\r\n              code: \"Server error\",\r\n              msg: error?.data?.messageHtml || JSON.stringify(error?.data, Object.getOwnPropertyNames(error?.data)),\r\n            }],\r\n          };\r\n        }\r\n      }\r\n      for(const result of chunk) {\r\n        const sourceRows = this.sourceData.filter((x) => this.getCheckSourceKey(x) == this.getCheckTargetKey(result));\r\n        for(const sourceRow of sourceRows) {\r\n          sourceRow.validation = {\r\n            isValid: result.validation.isValid && result.result.item.length == 1 ,\r\n            errors: result.validation.isValid ? (\r\n                    (result.result.item == null || result.result.item.length == 0) ? [ {msg: Translations.get(\"SALAXY.NG1.CalcImport.messageMissingEmployment\"), type: ApiValidationErrorType.General,}] :\r\n                    (result.result.item.length == 1) ? [ {msg: Translations.get(\"SALAXY.NG1.CalcImport.messageExistingEmployment\"), type: ApiValidationErrorType.General,}] :\r\n                    (result.result.item.length > 1) ? [ {msg: Translations.get(\"SALAXY.NG1.CalcImport.messageSeveralEmployments\"), type: ApiValidationErrorType.General,}] : result.validation.errors) :\r\n                    result.validation.errors\r\n          };\r\n        }\r\n\r\n        this.table.setData(this.sourceData);\r\n        await this.$timeout();\r\n      }\r\n    }\r\n    this.isValidating = false;\r\n    await this.$timeout();\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { Ajax, OData, Payrolls4, Translations, WorktimeApiConnector } from \"@salaxy/core\";\r\nimport type { calcReportType, CalculationListItem, ODataQueryOptions, PayrollDetails, WorktimeImport, WorktimeImportInStagingListItem, WorktimeImportPreviewMetadata, WorktimeImportRow } from \"@salaxy/core\";\r\nimport { ReportsService, SessionService, UiHelpers, UserSettingsService } from \"../../../services\";\r\n\r\n/** Controller that connects to the Import Staging area */\r\nexport class ImportStagingController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\", \"$timeout\", \"UserSettingsService\", \"Payrolls4\", \"$sce\", \"SessionService\", \"UiHelpers\", \"ReportsService\"];\r\n\r\n  /** Currently selected Payroll: This is set when in Payroll details view (one payroll, not general staging view) */\r\n  public payroll: PayrollDetails | undefined = undefined;\r\n\r\n  /**\r\n   * If provided by the parent (payroll controller), contains the list off calculations commit into the Payroll\r\n   * TODO: Consider including this to WorktimeImport wihtin the commit stage (also some other meta data)?\r\n   */\r\n  public payrollCalcs: CalculationListItem[] = [];\r\n\r\n  /** API methods for the Worktime Service. */\r\n  public worktimeApi: WorktimeApiConnector;\r\n\r\n  /** Itsems to show in the salary slips list. */\r\n  public salarySlipListType: \"preview\" | \"committed\" | \"all\" | \"distinct\" = \"all\";\r\n\r\n  constructor(\r\n    private ajax: Ajax,\r\n    private $timeout: angular.ITimeoutService,\r\n    private userSettingsService: UserSettingsService,\r\n    private payrollsApi: Payrolls4,\r\n    private $sce: angular.ISCEService,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n    private reportsService: ReportsService,\r\n  ) {\r\n  }\r\n\r\n  $onInit(): void {\r\n    if (!this.isSupported) {\r\n      return;\r\n    }\r\n    this.worktimeApi = new WorktimeApiConnector(this.serverUrl + \"/api/v01/worktime\", this.ajax);\r\n    this.worktimeApi.reloadList();\r\n    if (this.payroll) {\r\n      this.worktimeApi.setPayroll(this.payroll);\r\n    } else {\r\n      OData.getAllPages((options: ODataQueryOptions) => {\r\n        return this.payrollsApi.getOData(options);\r\n      }, {}).then((payrolls) => {\r\n        this.worktimeApi.payrolls = payrolls.items;\r\n        this.$timeout();\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * If supported for the company or partner, this URL is the integration server used in for the imports.\r\n   */\r\n  public get serverUrl(): string | undefined {\r\n    return this.sessionService.session.settings.integration.serverUrl || undefined;\r\n  }\r\n\r\n  /**\r\n   * Gets the user-specific setting (service), stored in the local storage.\r\n   */\r\n  public get userSettings() {\r\n    return this.userSettingsService;\r\n  }\r\n\r\n  /** If true, the staginc server is supported for the partner. */\r\n  public get isSupported(): boolean {\r\n    return !!this.serverUrl;\r\n  }\r\n\r\n  /** Gets the calculations / salary slips for the employment. */\r\n  public get currentEmploymentCalcs(): CalculationListItem[] {\r\n    if (!this.worktimeApi.current?.preview?.employments?.length) {\r\n      return [];\r\n    }\r\n    const personalId = this.worktimeApi.current.preview.employments[0].identity.personalId;\r\n    if (this.salarySlipCache.personalId !== personalId || this.salarySlipCache.type !== this.salarySlipListType) {\r\n      this.salarySlipCache.personalId = personalId;\r\n      this.salarySlipCache.calcList = undefined;\r\n      this.salarySlipCache.type = this.salarySlipListType;\r\n      this.ajax.getJSON(this.serverUrl + `/api/v01/worktime/employment/${personalId}/calculations?type=${this.salarySlipListType}`)\r\n        .then((result: any) => {\r\n          this.salarySlipCache.calcList = result.value;\r\n        });\r\n    }\r\n    return this.salarySlipCache.calcList;\r\n  }\r\n\r\n  /**\r\n   * Commits the current payroll.\r\n   */\r\n  public async commitPayroll(scope: \"payroll\" | \"employment\") {\r\n    const commitSingle = async (payrollId: string, employmentId: string) => {\r\n      await this.ajax.postJSON(this.serverUrl + `/api/v01/worktime/commit-payroll/${payrollId}/${employmentId}`, undefined);\r\n    };\r\n\r\n    if (scope == \"payroll\") {\r\n      const list = this.worktimeApi.filteredList;\r\n      const columns = [\r\n        { title: Translations.get(\"SALAXY.UI_Terms.name\"), field: \"sortableName\" },\r\n        { title: Translations.get(\"SALAXY.UI_Terms.personalId\"), field: \"personalId\" },\r\n      ];\r\n      await this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.ImportStagingComponent.dialog.commitPayroll\"), list, async (item, _data) => {\r\n        if (Array.isArray(item)) {\r\n          throw new Error(\"Batch processing not supported for payroll commit.\");\r\n        }\r\n        await commitSingle(this.payroll.id, item.id);\r\n        return [{\r\n          message: \"\",\r\n          result: undefined,\r\n        }];\r\n      }, undefined, {}, columns, undefined, true);\r\n      this.$timeout(() => {\r\n        this.reloadUi();\r\n      });\r\n      return;\r\n    }\r\n\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.ImportStagingComponent.dialog.commitPayroll\"));\r\n    await commitSingle(this.worktimeApi.currentCalc.info.payrollId, this.worktimeApi.current.id);\r\n    loader.dismiss();\r\n    this.reloadUi();\r\n  }\r\n\r\n  /** Reloads the current user interface: Especially the payroll if we are in the Payroll view. */\r\n  public reloadUi() {\r\n    this.sessionService.refreshUi();\r\n  }\r\n\r\n  /**\r\n   * Selects a payroll and fetches the calculations for it.\r\n   * @param payrollId - The ID of the payroll to select.\r\n   */\r\n  public selectPayroll(payrollId: string) {\r\n    if (!payrollId) {\r\n      this.payroll = undefined;\r\n      this.worktimeApi.setPayroll(undefined);\r\n      return;\r\n    }\r\n    this.payrollsApi.getSingle(payrollId).then((payroll) => {\r\n      this.payroll = payroll;\r\n      this.worktimeApi.setPayroll(this.payroll);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the totals for the selected payroll or the entire history if no payroll is selected.\r\n   * @param row - The row for which to get the totals.\r\n   */\r\n  public getTotals(row: WorktimeImportInStagingListItem | \"all\"): WorktimeImportPreviewMetadata {\r\n    if (row == \"all\") {\r\n      let rows: WorktimeImportPreviewMetadata[] = [];\r\n      if (this.worktimeApi?.list) {\r\n        rows = this.worktimeApi.payrollId\r\n          ? this.worktimeApi.list.map((item) => item.payrolls[this.worktimeApi.payrollId]).filter((item) => item)\r\n          : this.worktimeApi.list.map((item) => item.totals);\r\n      }\r\n      return this.uiHelpers.cache(this, \"allTotals\", () => {\r\n        return rows.reduce((acc: WorktimeImportPreviewMetadata, cur: WorktimeImportPreviewMetadata) => {\r\n          return {\r\n            calcs: {\r\n              count: acc.calcs.count + cur.calcs.count,\r\n            },\r\n            period: cur.period, // Add min/max if necessary\r\n            rows: {\r\n              committed: acc.rows.committed + cur.rows.committed,\r\n              count: acc.rows.count + cur.rows.count,\r\n              deleted: acc.rows.deleted + cur.rows.deleted,\r\n              edited: acc.rows.edited + cur.rows.edited,\r\n              error: acc.rows.error + cur.rows.error,\r\n              ignored: acc.rows.ignored + cur.rows.ignored,\r\n              new: acc.rows.new + cur.rows.new,\r\n              preview: acc.rows.preview + cur.rows.preview,\r\n            },\r\n            salaryDate: cur.salaryDate, // Add min/max if necessary\r\n          };\r\n        }, {\r\n          calcs: {\r\n            count: 0,\r\n          },\r\n          rows: {\r\n            committed: 0,\r\n            count: 0,\r\n            deleted: 0,\r\n            edited: 0,\r\n            error: 0,\r\n            ignored: 0,\r\n            new: 0,\r\n            preview: 0,\r\n          }\r\n        } as any);\r\n      }, /** Add upadated at to WorktimeImportPreviewMetadata for quicker cache  */);\r\n    }\r\n    if (this.worktimeApi.payrollId) {\r\n      const totals = row.payrolls[this.worktimeApi.payrollId];\r\n      if (this.payrollCalcs && totals && !(totals as any).committed) {\r\n        const committedCalc = this.payrollCalcs.find((calc) => calc.data.employmentId == row.id);\r\n        if (committedCalc) {\r\n          (totals as any).committed = {\r\n            gross: committedCalc.grossSalary,\r\n            net: committedCalc.data.workerPayment,\r\n          };\r\n        }\r\n      }\r\n      return totals;\r\n    }\r\n    return row.totals;\r\n  }\r\n\r\n  /**\r\n   * Recalculates the current worktime (if selected).\r\n   */\r\n  public async recalculateWorktime() {\r\n    const id = this.worktimeApi.current?.id;\r\n    this.showDetails(undefined);\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.ImportStagingComponent.dialog.recalculating\"));\r\n    await this.worktimeApi.recalculateWorktime(id);\r\n    this.showDetails(id);\r\n    loader.dismiss();\r\n  }\r\n\r\n  /**\r\n   * Saves the manual rows to the server and refreshes the view.\r\n   * @returns The updated worktime import.\r\n   */\r\n  public async saveManualRows(): Promise<void> {\r\n    await this.worktimeApi.saveManualRows();\r\n    await this.recalculateWorktime();\r\n  }\r\n\r\n  /** Deletes the current worktime (with are you sure) */\r\n  public async deleteWorktime() {\r\n    if (!this.worktimeApi.current) {\r\n      return;\r\n    }\r\n    this.uiHelpers.showConfirm(\"SALAXY.NG1.ApiCrudObjectComponent.deleteDialog\").then((result: boolean) => {\r\n      if (result) {\r\n        const id = this.worktimeApi.current.id;\r\n        this.showDetails(undefined);\r\n        this.worktimeApi.delete(id);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Recalculates all the worktimes in the list.\r\n   */\r\n  public async recalculateAllWorktimes() {\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.ImportStagingComponent.dialog.recalculating\"));\r\n    const list = this.worktimeApi.filteredList;\r\n    for (let i = 0; i < list.length; i++) {\r\n      const item = list[i];\r\n      loader.setText(`Recalculating ${item.sortableName} ${i + 1}/${list.length}...`);\r\n      await this.worktimeApi.recalculateWorktime(item.id);\r\n    }\r\n    loader.dismiss();\r\n  }\r\n\r\n  /**\r\n   * Shows a report for the current calculation using a modal dialog.\r\n   * @param calculationId - Identifier of the calculation to show.\r\n   * @param reportType - Type of report to show\r\n   */\r\n  public showReportDialog(calculationId: string, reportType: calcReportType = \"salarySlip\") {\r\n    // TODO: Add support for all report types view\r\n    const isPreview = calculationId.startsWith(\"preview-\");\r\n    if (isPreview) {\r\n      const calc = this.worktimeApi.current.preview.calculations.find((calc) => calc.id == calculationId);\r\n      if (calc) {\r\n        this.reportsService.showReportModalForCalc(reportType, calc, \"page1\", true);\r\n        return;\r\n      }\r\n      throw new Error(`Calculation ${calculationId} not found in preview.`);\r\n    }\r\n    const url = `${this.serverUrl}/api/v01/worktime/calculations/${calculationId}`;\r\n    this.ajax.getJSON(url).then((calc) => {\r\n      this.reportsService.showReportModalForCalc(reportType, calc, \"page1\", false);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the salary slip PDF in the IFrame UI.\r\n   * Sets the currentEmploymentPdf to the PDF of the salary slip (Base64 resource URI).\r\n   * @param calculationId Identifier of the calculation for which the PDF is shown.\r\n   */\r\n  public showSalarySlipPdf(calculationId: string | undefined) {\r\n    this.currentEmploymentPdf = \"loading\";\r\n    if (!calculationId) {\r\n      this.currentEmploymentPdf = undefined;\r\n      return;\r\n    }\r\n    this.ajax.getHTML(this.serverUrl + `/api/v01/worktime/calculations/${calculationId}/pdf`).then((pdf) => {\r\n      this.currentEmploymentPdf = this.$sce.trustAsResourceUrl(`data:application/pdf;base64, ${encodeURI(pdf)}`);\r\n      this.$timeout();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the salary slip HTML in the IFrame UI.\r\n   * @param calculationId Identifier of the calculation for which the HTML is shown.\r\n   */\r\n  public showSalarySlipHtml(calculationId: string | undefined): void {\r\n    this.currentEmploymentPdf = this.$sce.trustAsResourceUrl(this.serverUrl + `/api/v01/worktime/calculations/${calculationId}/html?access_token=` + this.ajax.getCurrentToken());\r\n  }\r\n\r\n  private salarySlipCache = {\r\n    /** Employment ID for which the data has been fetched. */\r\n    personalId: undefined as string | undefined,\r\n    /** List of calculations for the employment ID */\r\n    calcList: undefined as CalculationListItem[] | undefined,\r\n    /** Type of the list (filtering of the items on server-side) */\r\n    type: undefined as string | undefined,\r\n  };\r\n\r\n  /**\r\n   * Shows (hides) an item in the details view\r\n   * @param id - The ID of the item to show. If undefined, hides the details view.\r\n   */\r\n  public showDetails(id: string | undefined) {\r\n    if (id) {\r\n      this.worktimeApi.showDetails(id);\r\n    } else {\r\n      this.worktimeApi.setCurrent(undefined);\r\n    }\r\n  }\r\n\r\n  /** Returns true if the offcanvas (dialog) should be shown. */\r\n  public get showOffcanvas(): boolean {\r\n    return !!this.worktimeApi.current;\r\n  }\r\n\r\n  /** PDF salary slip that was last fetched for the current employment */\r\n  public currentEmploymentPdf: string | undefined = undefined;\r\n\r\n  /**\r\n   * Uploads a JSON file for testing purposes.\r\n   * Should be added to a form submit event.\r\n   * @param event - The change event that triggered by the file upload\r\n   * @example\r\n   * ```html\r\n   * <form ng-submit=\"$ctrl.uploadTestFile($event)\">\r\n   *   <input type=\"file\" class=\"form-control\" />\r\n   *   <button type=\"submit\" class=\"btn btn-default\">Upload</button>\r\n   * </form>\r\n   * ```\r\n   */\r\n  public async uploadTestFile(event?: Event) {\r\n    const form = event?.target as HTMLFormElement;\r\n    if (!form.tagName || form.tagName.toLowerCase() !== \"form\") {\r\n      throw new Error(`Method uploadTestFile should be connected to submit event of a form, e.g. <form ng-submit=\"$ctrl.uploadTestFile($event)\">.`);\r\n    }\r\n    const ipt = form.querySelector(\"input[type=file]\") as HTMLInputElement;\r\n    if (!ipt) {\r\n      throw new Error(\"No file input found in the form.\");\r\n    }\r\n    const file = ipt.files?.[0];\r\n    if (!file) {\r\n      return;\r\n    }\r\n    const text = await file.text();\r\n    const data = JSON.parse(text);\r\n    let result: WorktimeImport;\r\n    try {\r\n      result = await this.worktimeApi.callUpdateWorktime(data);\r\n    } catch (error) {\r\n      this.uploadResults = error;\r\n      this.$timeout();\r\n      throw error;\r\n    }\r\n\r\n    const validationErrors = (result.rows ?? []).concat(result.employments ?? [])\r\n      .filter((row) => !row.validation.isValid);\r\n    if (validationErrors.length) {\r\n      console.error(\"Validation errors\", validationErrors);\r\n      this.uploadResults = validationErrors;\r\n      alert(\"Validation errors found, see console for details.\");\r\n    } else {\r\n      console.debug(\"Result\", result);\r\n      this.uploadResults = result;\r\n      alert(\"Updates have been saved and validated.\");\r\n    }\r\n    this.$timeout();\r\n  }\r\n\r\n  public uploadResults: any = undefined;\r\n\r\n  /**\r\n   * Marks the selected rows with given state.\r\n   * @param rows - The rows to mark.\r\n   * @param status - The status to set.\r\n   * Status \"new\" is essentially reverting the state from \"ignored\" => final state may be \"preview\", \"new\" or \"error\" depending on other properties of the row.\r\n   */\r\n  public setStatus(rows: WorktimeImportRow[], status: \"ignored\" | \"new\") {\r\n    const loader = this.uiHelpers.showLoading();\r\n    this.worktimeApi.setStatus(rows, status).then((result: WorktimeImport) => {\r\n      // TODO: Instead of row-replace, we should do full Worktime refresh here (the asme way as in recalculate).\r\n      rows.forEach(row => {\r\n        const incoming = result.rows.find((r) => r.sourceId == row.sourceId);\r\n        if (incoming) {\r\n          row.status = incoming.status;\r\n        } else {\r\n          console.error(\"Row not found in result, defaulting to status: \" + status, row);\r\n        }\r\n        delete (row.data.isSelected);\r\n      });\r\n      loader.dismiss();\r\n      this.$timeout();\r\n    });\r\n  }\r\n\r\n}","import angular from \"angular\";\r\nimport { ApiImportStatus, ApiCheckStatus, Arrays, UserDefinedRow, Imports, DataMapper, DataMapperSelector, WorkerCheck, WorkerImportRow, WorkerImport, ApiValidationErrorType, Translations} from \"@salaxy/core\";\r\n\r\nimport { DataImportControllerBase } from \"./DataImportControllerBase\";\r\n\r\nimport { JsonSchemaService } from \"../../../services\";\r\n\r\n\r\n/**\r\n * Controller for worker imports.\r\n */\r\nexport class WorkerImportController extends DataImportControllerBase<WorkerImportRow, WorkerImport> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Imports\", \"JsonSchemaService\", \"$timeout\"];\r\n\r\n  /**\r\n   * Boolean indicating if the worker validation is in progress.\r\n   */\r\n  public isValidating = false;\r\n\r\n  private getTargetKey = (x: WorkerImport) => `${x.officialId}_${x.item.officialPersonId}`.toLowerCase();\r\n  private getSourceKey = (x: WorkerImportRow) => `${x.companyOfficialId}_${x.personalId}`.toLowerCase();\r\n  private getCheckTargetKey = (x: WorkerCheck) => `${x.officialId}_${x.id}`.toLowerCase();\r\n  private getCheckSourceKey = (x: WorkerImportRow) => `${x.companyOfficialId}_${x.personalId}`.toLowerCase();\r\n\r\n  private extraValidator = {\r\n    validate: () => this.validateWorkers(),\r\n    buttonLabel: Translations.get(\"SALAXY.NG1.WorkerImport.validateWorkersButton\")\r\n  };\r\n\r\n  /**\r\n   * Creates a new WorkerImportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private importsApi: Imports,\r\n    jsonSchemaService: JsonSchemaService,\r\n    $timeout: angular.ITimeoutService\r\n  ) {\r\n    super(jsonSchemaService, $timeout);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public async $onInit(){\r\n    super.$onInit();\r\n  }\r\n  /** Import data */\r\n  public async import() {\r\n\r\n    if (this.isImporting) {\r\n      return;\r\n    }\r\n\r\n    await this.validate();\r\n    if (!this.targetData) {\r\n      return;\r\n    }\r\n\r\n    this.isImporting = true;\r\n    this.isCanceled = false;\r\n\r\n    for(const sourceRow of this.sourceData) {\r\n      sourceRow.validation = null;\r\n      sourceRow.importStatus = ApiImportStatus.Ignored;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n\r\n    this.importTotal = this.targetData.length;\r\n    this.importCurrent = 0;\r\n\r\n    const chunkSize = 10;\r\n    const chunks: WorkerImport[][] = [];\r\n    for (let i = 0; i < this.targetData.length; i += chunkSize) {\r\n        chunks.push(this.targetData.slice(i, i + chunkSize));\r\n    }\r\n\r\n    let index = 0;\r\n    for(const chunk of chunks) {\r\n      try {\r\n        if (this.isCanceled) {\r\n          break;\r\n        }\r\n        chunk.splice(0, chunk.length, ... await this.importsApi.importWorkers(chunk));\r\n      } catch (error) {\r\n        for( const importObj of chunk) {\r\n          importObj.result = importObj.result ?? {};\r\n          importObj.result.status = ApiImportStatus.Error,\r\n          importObj.validation = {\r\n            isValid: false,\r\n            errors: [{\r\n              key: null,\r\n              type: ApiValidationErrorType.General,\r\n              code: \"Server error\",\r\n              msg: error?.data?.messageHtml || JSON.stringify(error?.data, Object.getOwnPropertyNames(error?.data)),\r\n            }],\r\n          };\r\n        }\r\n      }\r\n      for(const result of chunk) {\r\n        const sourceRows = this.sourceData.filter((x) => this.getSourceKey(x) == this.getTargetKey(result));\r\n        for(const sourceRow of sourceRows) {\r\n          sourceRow.validation = {\r\n            isValid: result.validation?.isValid,\r\n            errors: result.validation?.errors\r\n          };\r\n          sourceRow.importStatus = result.result?.status;\r\n        }\r\n        index += sourceRows.length;\r\n        this.importCurrent = index;\r\n\r\n        this.table.setData(this.sourceData);\r\n        await this.$timeout();\r\n      }\r\n    }\r\n    this.isImporting = false;\r\n    await this.$timeout();\r\n  }\r\n\r\n  /** Help */\r\n  public async help() {\r\n    const helpData = [\r\n      [Translations.get(\"SALAXY.NG1.WorkerImport.help.title\")],\r\n      [\"\"],\r\n      [Translations.get(\"SALAXY.NG1.WorkerImport.help.overview.title\")],\r\n      [Translations.get(\"SALAXY.NG1.WorkerImport.help.overview.row1\")],\r\n      [Translations.get(\"SALAXY.NG1.WorkerImport.help.overview.row2\")],\r\n      [\"\"],\r\n      ...this.getDefaultHelpDataForColumns(),\r\n    ];\r\n    await this.download(helpData);\r\n  }\r\n\r\n  /** Returns extra validator */\r\n  public getExtraValidators(): Array<{ validate: () => void, buttonLabel: string }> {\r\n      return [this.extraValidator];\r\n  }\r\n\r\n  protected async getImportMapper() {\r\n\r\n    const rowMap = {\r\n      defaultRowType: \"rowType\",\r\n      defaultRowKind: \"data.kind\",\r\n      defaultSalary: \"price\",\r\n    };\r\n\r\n    const rowMapper = new DataMapper<WorkerImportRow, UserDefinedRow>(\"NG1/WorkerImporController\", \"Työntekijät\");\r\n    await rowMapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"UserDefinedRow\", \"target\");\r\n    rowMapper.setPaths(rowMap);\r\n    rowMapper.generateSchema(\"WorkerImportRow\", \"source\");\r\n\r\n\r\n    const salaryDefaultSelector = new DataMapperSelector<WorkerImportRow, WorkerImport>(null,\"item.employment.work.salaryDefaults\",\r\n    (source) => {\r\n      if (source.defaultRowType && source.defaultSalary > 0) {\r\n        return rowMapper.doMap([source]);\r\n      }\r\n      return [];\r\n    });\r\n\r\n    const mapper = new DataMapper<WorkerImportRow, WorkerImport>(\"NG1/WorkerImportController\", \"Työntekijät\");\r\n    const map = {\r\n      companyOfficialId: \"officialId\",\r\n      personalId: \"item.officialPersonId\",\r\n      sourceId: \"item.employment.sourceId\",\r\n      firstName: \"item.avatar.firstName\",\r\n      lastName: \"item.avatar.lastName\",\r\n      email: \"item.contact.email\",\r\n      telephone: \"item.contact.telephone\",\r\n      ibanNumber: \"item.ibanNumber\",\r\n      street: \"item.contact.street\",\r\n      postalCode: \"item.contact.postalCode\",\r\n      city: \"item.contact.city\",\r\n      countryCode: \"item.contact.countryCode\",\r\n      startDate: \"item.employment.startDate\",\r\n      employmentType: \"item.employment.type\",\r\n      pensionCalculation: \"item.employment.pensionCalculation\",\r\n      description: \"item.employment.work.description\",\r\n      occupationCode: \"item.employment.work.occupationCode\",\r\n      taxcard: \"item.employment.taxcard\",\r\n      defaultRowType: salaryDefaultSelector,\r\n    };\r\n    await mapper.setSchemaFromCache(this.jsonSchemaService.getCache(), \"salaxy-secure/schemas/v02.json\", \"WorkerImport\", \"target\");\r\n    mapper.setPaths(map);\r\n    mapper.generateSchema(\"WorkerImportRow\", \"source\");\r\n\r\n    mapper.source.schema.properties.occupationCode[\"format\"] =\"Occupation\";\r\n    for(const property in rowMapper.source.schema.properties) {\r\n      mapper.source.schema.properties[property] = rowMapper.source.schema.properties[property];\r\n    }\r\n    return mapper;\r\n  }\r\n\r\n  /** Import data */\r\n  private async validateWorkers() {\r\n\r\n    if (this.isValidating) {\r\n      return;\r\n    }\r\n\r\n    await this.validate();\r\n    if (!this.targetData) {\r\n      return;\r\n    }\r\n\r\n    this.isValidating = true;\r\n\r\n    for(const sourceRow of this.sourceData) {\r\n      sourceRow.validation = null;\r\n      sourceRow.validation = {\r\n        isValid: null, // null on purpose\r\n        errors: [{\r\n          type: ApiValidationErrorType.General,\r\n          msg: Translations.get(\"SALAXY.UI_Terms.wait\"),\r\n        }],\r\n      };\r\n      sourceRow.importStatus = ApiImportStatus.Ignored;\r\n    }\r\n    this.table.setData(this.sourceData);\r\n    await this.$timeout();\r\n\r\n    const workerGroups = Arrays.groupBy(this.sourceData, this.getCheckSourceKey);\r\n    const workerChecks: WorkerCheck[] = [];\r\n    for(const workerGroupKey in workerGroups) {\r\n      workerChecks.push( {\r\n        officialId: workerGroups[workerGroupKey][0].companyOfficialId,\r\n        id: workerGroups[workerGroupKey][0].personalId,\r\n      });\r\n    }\r\n\r\n    const chunkSize = 10;\r\n    const chunks: WorkerCheck[][] = [];\r\n    for (let i = 0; i < workerChecks.length; i += chunkSize) {\r\n        chunks.push(workerChecks.slice(i, i + chunkSize));\r\n    }\r\n\r\n    for(const chunk of chunks) {\r\n      try {\r\n        chunk.splice(0, chunk.length, ... await this.importsApi.checkWorkers(chunk));\r\n      } catch (error) {\r\n        for( const checkObj of chunk) {\r\n          checkObj.result = checkObj.result ?? {};\r\n          checkObj.result.status = ApiCheckStatus.Error,\r\n          checkObj.validation = {\r\n            isValid: false,\r\n            errors: [{\r\n              key: null,\r\n              type: ApiValidationErrorType.General,\r\n              code: \"Server error\",\r\n              msg: error?.data?.messageHtml || JSON.stringify(error?.data, Object.getOwnPropertyNames(error?.data)),\r\n            }],\r\n          };\r\n        }\r\n      }\r\n      for(const result of chunk) {\r\n        const sourceRows = this.sourceData.filter((x) => this.getCheckSourceKey(x) == this.getCheckTargetKey(result));\r\n        for(const sourceRow of sourceRows) {\r\n          sourceRow.validation = {\r\n            isValid: result.validation.isValid,\r\n            errors: result.validation.isValid ? (\r\n                    (result.result.item == null || result.result.item.length == 0) ? [ {msg: Translations.get(\"SALAXY.NG1.WorkerImport.messageMissingEmployment\"), type: ApiValidationErrorType.General,}] :\r\n                    (result.result.item.length == 1) ? [ {msg: Translations.get(\"SALAXY.NG1.WorkerImport.messageExistingEmployment\"), type: ApiValidationErrorType.General,}] :\r\n                    (result.result.item.length > 1) ? [ {msg: Translations.get(\"SALAXY.NG1.WorkerImport.messageSeveralEmployments\"), type: ApiValidationErrorType.General,}] : result.validation.errors) :\r\n                    result.validation.errors\r\n          };\r\n        }\r\n\r\n        this.table.setData(this.sourceData);\r\n        await this.$timeout();\r\n      }\r\n    }\r\n    this.isValidating = false;\r\n    await this.$timeout();\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { CustomerInvoice, CustomerInvoiceListItem, CustomerInvoices } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Controller for listing and browsing Customer Usecases.\r\n * NOTE: Access save / modify methods is very restricted by design as invoces are created by Palkkaus and cannot be modified by the Customer.\r\n * Typically, you will not be able to save / delete / modify customer invoices in the production environment.\r\n */\r\nexport class CustomerInvoiceCrudController extends ApiCrudObjectController<CustomerInvoice, CustomerInvoiceListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"CustomerInvoices\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n  ];\r\n\r\n  /**\r\n   * Creates a new DatasetsCrudController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    fullApi: CustomerInvoices,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n  ) {\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Controller initialization\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/customer-invoices/\",\r\n      detailsUrl: this.detailsUrl || \"/customer-invoices/details/\",\r\n      // TODO: Add a custom listing\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/CustomerInvoices.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { Ajax, Calculations, Configs, Dates, InputEnumOption, Invoice, InvoiceListItem, Invoices, InvoiceStatus, InvoiceType, PaymentChannel, Payrolls, Translations } from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Provides read access for authenticated user to access his/her own invoices\r\n * and write access to create new salary and related payments based on calculations.\r\n */\r\nexport class InvoiceCrudController extends ApiCrudObjectController<Invoice, InvoiceListItem> {\r\n  private _reportCalcs = [];\r\n  private _calcOrPayrollId = [];\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Invoices\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"InvoicesService\",\r\n    \"AjaxNg1\",\r\n    \"Calculations\",\r\n    \"Payrolls\"\r\n  ];\r\n\r\n  /** For list component, defines the layout / functionality of the list. */\r\n  public mode: \"default\" | \"panel\" | \"person\";\r\n\r\n  /** Data reader for selected items. */\r\n  public selectionDataReader = {\r\n    /** Function to read data into given array */\r\n    read: (arr: Invoice[], message: string): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n      const promises = this.odataController.selectedItems.map(x => this.api.getSingle(x.id));\r\n      return Promise.all(promises).then( (data) => {\r\n        arr.push(...data.filter(d => !!d));\r\n        return;\r\n      });\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: Translations.get(\"SALAXY.NG1.AccountingReportToolsComponent.exportLabel\"),\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.odataController.selectedItems || this.odataController.selectedItems.length === 0,\r\n  };\r\n\r\n  /** Data reader for selected items. */\r\n  public selectionDataReaderPerson = {\r\n    /** Function to read data into given array */\r\n    read: (arr: Invoice[], message: string): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n      const promises = this.odataController.selectedItems.map(x => this.api.getSingle(x.id));\r\n      return Promise.all(promises).then( (data) => {\r\n        data = data.filter(x => x.header.type === InvoiceType.Net || x.header.type === InvoiceType.Tax);\r\n        arr.push(...data.filter(d => !!d));\r\n        return;\r\n      });\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: Translations.get(\"SALAXY.NG1.AccountingReportToolsComponent.exportLabel\"),\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.odataController.selectedItems || this.odataController.selectedItems.length === 0,\r\n  };\r\n\r\n  /** Status filters for lists: Groups statuses to logical groups. */\r\n  public statusFilters: InputEnumOption[] = [\r\n    {\r\n      value: \"all\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusAll\"),\r\n      ui: \"\",\r\n    }, {\r\n      value: \"waitingConfirmation\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusWaitingConfirmation\"),\r\n      ui: \"status eq 'unread' or status eq 'read' or status eq 'waitingConfirmation'\",\r\n    }, {\r\n      value: \"paid\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusPaid\"),\r\n      ui: \"status eq 'paid' or status eq 'paymentStarted' or status eq 'canceled'\",\r\n    }, {\r\n      value: \"forecast\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusForecast\"),\r\n      ui: \"status eq 'forecast' or status eq 'preview'\",\r\n    },\r\n  ];\r\n\r\n  constructor(\r\n    protected invoicesApi: Invoices,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private invoicesService: InvoicesService,\r\n    private ajax: Ajax,\r\n  ) { // Dependency injection\r\n    super(invoicesApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Gets the default channel for the current account. */\r\n  public get defaultChannel(): PaymentChannel {\r\n    return this.invoicesService.defaultChannel;\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"invoices\",\r\n      detailsUrl: this.detailsUrl || \"/invoices/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/InvoicesPanel.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Gets the type of the due date vs. the current date and status for display purposes. */\r\n  public getDueDateType(listItem: InvoiceListItem): \"default\" | \"estimation\" | \"canceled\" | \"overdue\" | \"future\"| \"unknown\" {\r\n    if (listItem.entityType === \"unemployment\" ) {\r\n      return \"estimation\";\r\n    }\r\n\r\n    switch (listItem.status) {\r\n      case InvoiceStatus.Canceled:\r\n        return \"canceled\";\r\n      case InvoiceStatus.Forecast:\r\n      case InvoiceStatus.Preview:\r\n        if (listItem.endAt > Dates.getToday()) {\r\n          return \"future\";\r\n        }\r\n        return \"default\";\r\n      case InvoiceStatus.Undefined:\r\n      case InvoiceStatus.Unread:\r\n        if (listItem.endAt < Dates.getToday()) {\r\n          return \"overdue\";\r\n        }\r\n        return \"default\";\r\n      case InvoiceStatus.Read:\r\n      case InvoiceStatus.WaitingConfirmation:\r\n      case InvoiceStatus.WaitingPalkkaus:\r\n      case InvoiceStatus.Paid:\r\n      case InvoiceStatus.PaymentStarted:\r\n        return \"default\";\r\n    }\r\n    return \"default\";\r\n  }\r\n\r\n  /** For list components, gets the OData query options. */\r\n  public getListOptions() {\r\n    return this.uiHelpers.cache(this, \"listOptions\", () => {\r\n      if (this.mode === \"panel\") {\r\n        return {\r\n          $filter: \"\",\r\n          $top: 5,\r\n          $orderby: \"endAt desc\",\r\n        };\r\n      } else {\r\n        // Add logic and e.g. if needed\r\n        return {\r\n          $orderby: \"endAt desc\",\r\n        };\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Returns content url for the invoice. */\r\n  public getContentUrl(id: string, inline = false): string {\r\n    return this.invoicesApi.getContentUrl(id, inline);\r\n  }\r\n\r\n  /**\r\n   * Request the status update for the invoice.\r\n   * @param status Status data. If not set, uses the requestedStatus property of the controller.\r\n   */\r\n  public requestStatusUpdate(status: InvoiceStatus = null): any {\r\n    status = status || this.requestedStatus;\r\n\r\n    if ( status === InvoiceStatus.Paid && (\r\n      this.current.header.channel === PaymentChannel.Test ||\r\n      this.current.header.channel === PaymentChannel.Procountor ||\r\n      this.current.header.channel === PaymentChannel.VismaNetvisor)) {\r\n\r\n      const loader = this.uiHelpers.showLoading(\"Maksuikkuna avattu...\");\r\n      let url = \"\";\r\n      switch ( this.current.header.channel) {\r\n        case PaymentChannel.Test:\r\n          url =\r\n          Configs.current.isTestData ?\r\n          \"https://test-integrations.salaxy.com/test#/dialogs/invoice\" :\r\n          \"https://integrations.salaxy.com/test#/dialogs/invoice\";\r\n          break;\r\n        case PaymentChannel.Procountor:\r\n          url =\r\n          Configs.current.isTestData ?\r\n          \"http://localhost:93/procountor/invoice.html\" :\r\n          \"https://integrations.salaxy.com/procountor/invoice.html\";\r\n          break;\r\n        case PaymentChannel.VismaNetvisor:\r\n         url =\r\n         Configs.current.isTestData ?\r\n          \"http://localhost:93/vismanetvisor/invoice.html\" :\r\n          \"https://integrations.salaxy.com/vismanetvisor/invoice.html\";\r\n        break;\r\n      }\r\n      url += \"?invoiceIds=\" + this.currentId + \"&token=\" + this.ajax.getCurrentToken();\r\n      return this.uiHelpers.showExternalDialog(\"invoiceCreation\", url, {})\r\n        .then(() => {\r\n          loader.dismiss();\r\n          return this.setStatus(this.api.getSingle(this.current.id)).then((invoice) => {\r\n            if (invoice) {\r\n              this.setCurrent(invoice);\r\n            }\r\n            return invoice;\r\n          });\r\n        });\r\n    } else {\r\n\r\n      return this.setStatus(this.invoicesApi.requestStatusUpdate(this.currentId, status)\r\n        .then((invoice) => {\r\n          if (invoice) {\r\n            this.setCurrent(invoice);\r\n          }\r\n          return invoice;\r\n        }));\r\n    }\r\n  }\r\n\r\n  /** Requested status for binding */\r\n  public get requestedStatus(): InvoiceStatus {\r\n    if (this.current) {\r\n      return (this.current.header as any).requestedStatus || this.current.header.status;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Requested status for binding */\r\n  public set requestedStatus(value: InvoiceStatus) {\r\n    (this.current.header as any).requestedStatus = value;\r\n  }\r\n\r\n  /**\r\n   * Delete invoice and related business objects (calculations and payrolls)\r\n   * @param item  - Invoice to delete.\r\n   * @param confirmMessage - Optional message for confirm popup\r\n   */\r\n  public deleteWithBusinessObjects(item?: Invoice, confirmMessage?: string): Promise<boolean> {\r\n    item = item || this.current;\r\n    return this.uiHelpers.showConfirm(confirmMessage || \"Haluatko varmasti poistaa tämän laskun ja siihen liittyvät laskelmat ja palkkalistat?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          return this.ajax.remove(`/accounts/invoice?ids=${item.id}`).then(() => {\r\n            if (this.current === item) {\r\n              this.setCurrent(null);\r\n            }\r\n            if (this.odataController) {\r\n              this.odataController.reload();\r\n            } else {\r\n              this.$location.url(this.getDefaults().listUrl);\r\n            }\r\n            return true;\r\n          });\r\n        } else {\r\n          return Promise.resolve(false);\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Data reader for one item.\r\n   * TODO: Should add interface for the reader.\r\n   */\r\n  public getItemDataReader = (item: {\r\n    /** List item id */\r\n    id: string,\r\n    /** List item owner */\r\n    owner: string,\r\n  }) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (arr: Invoice[], message: string): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n        (item as any).isReading = true;\r\n        return this.api.getSingle(item.id).then((data) => {\r\n          /*\r\n          const wfEvent = {\r\n            type: \"PartnerMessageClosed\",\r\n            ui: \"success\" as any,\r\n            message,\r\n          };\r\n          return this.filesApi.saveWorkflowEvent(item, wfEvent).then(() => {\r\n            this.setWorkflowEvent(item as any, wfEvent);\r\n          */\r\n          if (data) {\r\n            arr.push(data);\r\n          }\r\n          (item as any).isReading = false;\r\n          return Promise.resolve();\r\n          /* });*/\r\n        });\r\n      },\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n    };\r\n  };\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n    if (this.odataController.selectedItems) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n    }\r\n  }\r\n\r\n  /** Select all */\r\n  public selectAll() {\r\n    if (this.odataController.selectedItems && this.odataController.items) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n      this.odataController.selectedItems.push(...this.odataController.items);\r\n    }\r\n  }\r\n\r\n  /** Open PaymentDialog for selected row */\r\n  public showPaymentDialog(row: InvoiceListItem) {\r\n    this.invoicesService.showPaymentDialogForCalculation(row);\r\n  }\r\n\r\n  /** Get invoices calculation by id */\r\n  public getReportCalcs() {\r\n    const id = this.current.header.businessObjects[0];\r\n    if (!this._calcOrPayrollId.includes(id)) {\r\n      this._calcOrPayrollId.push(id);\r\n      const calculations = new Calculations(this.ajax);\r\n      calculations.getSingle(id).then(calc => {\r\n        if (calc) {\r\n          this._reportCalcs.splice(0,this._reportCalcs.length);\r\n          this._reportCalcs.push(calc);\r\n        } else if(this.current.header.type === InvoiceType.Gross) {\r\n          const payrolls = new Payrolls(this.ajax);\r\n          payrolls.getOData({$filter: `id eq '${this.current.header.businessObjects[0]}'`}).then(result => {\r\n            if(result.items[0] && result.items[0].businessObjects.length) {\r\n              const calculations = new Calculations(this.ajax);\r\n              calculations.getMulti(result.items[0].businessObjects).then(calcs => {\r\n                this._reportCalcs.splice(0,this._reportCalcs.length);\r\n                this._reportCalcs.push(...calcs);\r\n              });\r\n            }\r\n          });\r\n        }\r\n      });\r\n    }\r\n    return this._reportCalcs;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport {\r\n  Ajax, Calculation, Calculations, Configs, InputEnumOption,\r\n  Invoice, Invoices, InvoicesLogic, InvoicePreview, InvoiceStatus, InvoiceType,\r\n  PaymentChannel, PayrollDetails, PayrollStatus, InvoicePaymentType, SalaryDateKind, Translations, CalculationListItem, PayrollListItem, Payrolls4\r\n} from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, SessionService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { CalculationCrudController, PayrollCrudController } from \"../calc\";\r\nimport { } from \"../../components\";\r\n\r\n/**\r\n * Controller for the new Payment button and other functionality:\r\n * Creating (recreating) Invoices based on Calculations and Payrolls.\r\n */\r\nexport class InvoicesCreateController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Invoices\", \"InvoicesService\", \"Calculations\", \"SessionService\", \"UiHelpers\", \"$location\", \"AjaxNg1\"];\r\n\r\n  /**\r\n   * Defines the binding mode of the component.\r\n   * Currently, only \"model\" is supported (Calculation or PayrollDetails),\r\n   * but we might support e.g. id in the future.\r\n   */\r\n  public bindingMode: \"model\" | \"null\";\r\n\r\n  /**\r\n   * Collection of invoices if the channel and model have been set.\r\n   * Null if the collection is being fetched.\r\n   */\r\n  public invoices: InvoicePreview[] = [];\r\n\r\n  /** User canceled the process. */\r\n  public userCanceled = false;\r\n\r\n  private _current: Calculation | PayrollDetails;\r\n\r\n  private _model: any;\r\n\r\n  private _primaryCalcNetInvoicePreview: InvoicePreview = null;\r\n\r\n  private _primaryCalcTaxInvoicePreview: InvoicePreview = null;\r\n\r\n  constructor(\r\n    private invoicesApi: Invoices,\r\n    private invoicesService: InvoicesService,\r\n    private calculationsApi: Calculations,\r\n    private sessionService: SessionService,\r\n    protected uiHelpers: UiHelpers,\r\n    private $location: angular.ILocationService,\r\n    private ajax: Ajax,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController by providing onInit method.\r\n   * We currently do nothing here, but if you override this function,\r\n   * you should call this method in base class for future compatibility.\r\n   */\r\n  public $onInit() {\r\n    this.bindingMode = this.bindingMode || \"null\";\r\n  }\r\n\r\n  /**\r\n   * Set the Current selected item (the model).\r\n   * Currently, only Calculation or PayrollDetails is supported,\r\n   * but we will probably support controller and url in the future.\r\n   */\r\n  public set model(value: Calculation | PayrollDetails | \"url\" | string | ApiCrudObjectController<Calculation, CalculationListItem> | ApiCrudObjectController<PayrollDetails, PayrollListItem>) {\r\n    this._model = value;\r\n    if (InvoicesLogic.isCalculation(value) || InvoicesLogic.isPayroll(value)) {\r\n      this._current = value;\r\n      this.bindingMode = \"model\";\r\n    } else {\r\n      throw new Error(\"Not implemented: Only Calculation or PayrollDetails is currently supported.\");\r\n    }\r\n    this.reload();\r\n  }\r\n  /** Gets the Current selected item (the model). */\r\n  public get model(): Calculation | PayrollDetails | \"url\" | string | ApiCrudObjectController<Calculation, CalculationListItem> | ApiCrudObjectController<PayrollDetails, PayrollListItem> {\r\n    return this._model;\r\n  }\r\n\r\n  /** Changes the channel */\r\n  public set channel(value: PaymentChannel) {\r\n    if (InvoicesLogic.isCalculation(this.current)) {\r\n      this.current.info.paymentChannel = value;\r\n    } else {\r\n      this.current.input.paymentChannel = value;\r\n    }\r\n    this.reload();\r\n  }\r\n  /** The current payment channel for user interface purposes. */\r\n  public get channel(): PaymentChannel {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    const channel = InvoicesLogic.isCalculation(this.current)\r\n      ? this.current.info.paymentChannel\r\n      : this.current.input.paymentChannel;\r\n    return channel || this.invoicesService.defaultChannel;\r\n  }\r\n\r\n  /** Gets the enabled channels. */\r\n  public get allChannels() {\r\n    return this.invoicesService.channelEnumOptions;\r\n  }\r\n\r\n  /** Gets the text for the Primary submit button. Null for hiding the button. */\r\n  public getOkBtn(): string {\r\n    if (this.userCanceled) {\r\n      return null;\r\n    }\r\n    if (!this.isValid) {\r\n      return null;\r\n    }\r\n    switch (this.paymentStatus) {\r\n\r\n      case \"paid\":\r\n      case \"exceptions\":\r\n      case \"canceled\":\r\n      case \"unknown\":\r\n        return null;\r\n      case \"preview\":\r\n        if (this.channel === PaymentChannel.PalkkausManual && this.salaryDateKind == SalaryDateKind.InPast) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.createAndMarkPaid\");\r\n        }\r\n        if (this.channel === PaymentChannel.PalkkausManual || this.channel === PaymentChannel.PalkkausWS || this.channel === PaymentChannel.FinagoSolo || this.channel === PaymentChannel.AccountorGo) {\r\n          // for Accountor Go service users\r\n          if(this.sessionService.isInRole(\"accountorService\")){\r\n            return null;\r\n          }\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.createPayments\");\r\n        }\r\n        if (this.channel == PaymentChannel.PalkkausInvoices || this.channel == PaymentChannel.Kitsas) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.createInvoices\");\r\n        }\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.sendForPayment\");\r\n      case \"inProgress\":\r\n        if (this.channel === PaymentChannel.Procountor || this.channel === PaymentChannel.VismaNetvisor || this.channel === PaymentChannel.Test) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.checkPayment\");\r\n        }\r\n        return null;\r\n      default:\r\n        if (!this.channel || this.channel === PaymentChannel.Undefined) {\r\n          return null;\r\n        }\r\n        if (this.channel == PaymentChannel.PalkkausInvoices || this.channel == PaymentChannel.Kitsas) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.createInvoices\");\r\n        }\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.sendForPayment\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Intro text for the dialog.\r\n   */\r\n  public get intro(): string {\r\n    if (this.channel == PaymentChannel.PalkkausManual && this.salaryDateKind == SalaryDateKind.InPast) {\r\n      return Translations.get(`SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManualAndFixed.intro`);\r\n    }\r\n    return Translations.get(`SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.${this.channel}.intro`);\r\n  }\r\n  /** Title for the dialog */\r\n  public get title(): string {\r\n    switch (this.channel) {\r\n      case PaymentChannel.PalkkausManual:\r\n        return this.salaryDateKind == SalaryDateKind.InPast ?\r\n          Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManualAndFixed.heading\") :\r\n          Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManual.heading\");\r\n      case PaymentChannel.PalkkausWS:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausWS.heading\");\r\n      case PaymentChannel.PalkkausInvoices:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausInvoices.heading\");\r\n      case PaymentChannel.Kitsas:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kitsas.heading\");\r\n      case PaymentChannel.FinagoSolo:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.finagoSolo.heading\");\r\n      case PaymentChannel.AccountorGo:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.accountorGo.heading\");\r\n      case PaymentChannel.Askelma:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.askelma.heading\");\r\n      case PaymentChannel.Briox:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.briox.heading\");\r\n      case PaymentChannel.Lemonaid:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.lemonaid.heading\");\r\n      case PaymentChannel.Laskupiste:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.laskupiste.heading\");\r\n      case PaymentChannel.PasseliMerit:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.passeliMerit.heading\");\r\n      case PaymentChannel.Odoo:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.odoo.heading\");\r\n      case PaymentChannel.Ecom:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.ecom.heading\");\r\n      case PaymentChannel.Kompassi:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kompassi.heading\");\r\n      case PaymentChannel.Domus:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.domus.heading\");\r\n      case PaymentChannel.Holvi:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.holvi.heading\");\r\n      case PaymentChannel.TalenomOnline:\r\n        return Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.talenomOnline.heading\");\r\n      case PaymentChannel.PalkkausPersonal:\r\n      default:\r\n        return Translations.get(\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.loadingPayment\");\r\n    }\r\n  }\r\n\r\n  /** Gets the Current selected item. */\r\n  public get current(): Calculation | PayrollDetails {\r\n    return this._current;\r\n  }\r\n\r\n  /**\r\n   * Returns true if the invoices have been created => the payment process has been started.\r\n   * It may have been completed (paid), canceled or rejected.\r\n   */\r\n  public get isStarted(): boolean {\r\n    if (InvoicesLogic.isPayroll(this.current) && this.current.info.status !== PayrollStatus.Draft) {\r\n      return true;\r\n    } else if (InvoicesLogic.isCalculation(this.current) && this.current.isReadOnly) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Gets the payment status of the invoices.\r\n   *\r\n   * - unknown: The invoices have not been loaded from the server yet.\r\n   * - preview: The invoices have not yet been created\r\n   * - inProgress: Any of the invoices is in progress (WaitingPalkkaus,Unread, Read, WaitingConfirmation, PaymentStarted)\r\n   * OR some invoices have been paid, some not (default state).\r\n   * - canceled: One of the invoices is canceled.\r\n   * - exceptions: Any of the invoices have exceptions (Undefined, Error)\r\n   * - paid: All the invoices have been paid\r\n   *\r\n   * This is ready only after the invoices have been loaded by Preview (may be already created invoices).\r\n   */\r\n  public get paymentStatus(): \"unknown\" | \"preview\" | \"inProgress\" | \"exceptions\" | \"canceled\" | \"paid\" {\r\n    if (!this.invoices || this.invoices.length === 0) {\r\n      return \"unknown\";\r\n    }\r\n    if (this.invoices.every((x) => !x.exists)) {\r\n      return \"preview\";\r\n    }\r\n\r\n    const paidNet = this.invoices.find((x) => x.invoice.status == InvoiceStatus.Paid && x.invoice.entityType == \"net\");\r\n    if (paidNet?.invoice.data.channel == PaymentChannel.PalkkausPersonal) {\r\n      // HACK: As of writing PalkkausPersonal only sets Net payment as paid (not the tax).\r\n      return \"paid\";\r\n    }\r\n\r\n    const inProgress = [InvoiceStatus.WaitingPalkkaus, InvoiceStatus.Unread, InvoiceStatus.Read, InvoiceStatus.WaitingConfirmation, InvoiceStatus.PaymentStarted];\r\n    if (this.invoices.find((x) => inProgress.indexOf(x.invoice.status) >= 0)) {\r\n      return \"inProgress\";\r\n    }\r\n    if (this.invoices.find((x) => x.invoice.status === InvoiceStatus.Canceled)) {\r\n      return \"canceled\";\r\n    }\r\n    const exceptions = [InvoiceStatus.Undefined, InvoiceStatus.Error];\r\n    if (this.invoices.find((x) => exceptions.indexOf(x.invoice.status) >= 0)) {\r\n      return \"exceptions\";\r\n    }\r\n    const paid = [InvoiceStatus.Paid, InvoiceStatus.Forecast, InvoiceStatus.Preview];\r\n    if (this.invoices.every((x) => paid.indexOf(x.invoice.status) >= 0)) {\r\n      return \"paid\";\r\n    }\r\n    return \"inProgress\";\r\n  }\r\n\r\n  /** Gets the type of current. */\r\n  public get currentType(): \"Calculation\" | \"PayrollDetails\" | null {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (InvoicesLogic.isPayroll(this.current)) {\r\n      return \"PayrollDetails\";\r\n    }\r\n    if (InvoicesLogic.isCalculation(this.current)) {\r\n      return \"Calculation\";\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Returns true if the calculations are valid for payment. */\r\n  public get isValid(): boolean {\r\n    if (InvoicesLogic.isPayroll(this.current)) {\r\n      // return this.current.validations.every((x) => x.isValid);\r\n      return this.current.info &&\r\n        this.current.info.isReadyForPayment;\r\n    }\r\n    if (InvoicesLogic.isCalculation(this.current)) {\r\n      return this.current.result &&\r\n        // this.current.result.validation?.isValid &&\r\n        !(this.current.result.validation?.errors ?? []).find((e) => (e.type !== \"warning\")) &&\r\n        this.current.worker &&\r\n        this.current.worker.tax.isValid;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets and avatar image for a payment channel */\r\n  public getChannelAvatar(option: InputEnumOption) {\r\n    const channel = option.value || PaymentChannel.Undefined;\r\n    return InvoicesLogic.getChannelAvatar(channel as PaymentChannel);\r\n  }\r\n\r\n  /** Reloads the preview invoices from the server. */\r\n  public reload() {\r\n    if (!this.channel || this.channel === PaymentChannel.Undefined || !this.isValid) {\r\n      return; // Cannot start reload\r\n    }\r\n    if (this.bindingMode == null) {\r\n      return;\r\n    }\r\n    if (this.bindingMode !== \"model\") {\r\n      throw new Error(\"Not implemented: Only Calculation or PayrollDetails is currently supported.\");\r\n    }\r\n    this.invoices = null;\r\n    if (InvoicesLogic.isPayroll(this.current)) {\r\n\r\n      if (this.current.calcs?.length > 0) {\r\n        // old\r\n        this.invoicesApi.previewInvoices(this.channel, { payrollIds: [this.current.id] }).then((result) => {\r\n          this.invoices = result;\r\n        });\r\n      }\r\n      else {\r\n        // new\r\n        const payrolls4Api = new Payrolls4(this.ajax);\r\n        payrolls4Api.getCalcsOData(this.current.id, null).then((listItemResult) => {\r\n          const calcs = listItemResult.items;\r\n          const data: any = {};\r\n          data.listItemType = \"CalculationListItem\";\r\n          const columns = undefined;\r\n          const paramsTemplate = undefined;\r\n          const action = (items, data) => {\r\n            const itemIds = items.map((x) => x.id);\r\n            const remainingAfterThis =  data.dialogList.filter((x) => !x.processed).length;\r\n            const excludePeriodic = remainingAfterThis == 0 ? false:  true;\r\n            return payrolls4Api.previewInvoices(this.current.id, itemIds, excludePeriodic).then((result) => {\r\n              const results = items.map(() => ( {message: \"\", result: []}));\r\n              if (results.length > 0) {\r\n                results[0].result = result;\r\n              }\r\n              return results;\r\n            });\r\n          };\r\n          this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.uiStatusLoading\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n            if (dialogResult.done) {\r\n              this.invoices = [];\r\n              dialogResult.results.forEach( (result) => {\r\n                this.invoices.push(...result.result);\r\n              });\r\n            }\r\n            else\r\n            {\r\n              this.userCanceled = true;\r\n              this.invoices = [];\r\n            }\r\n          });\r\n        });\r\n      }\r\n    }\r\n    else if (InvoicesLogic.isCalculation(this.current)) {\r\n      this.invoicesApi.previewInvoices(this.channel, { calcs: [this.current] }).then((result) => {\r\n        this.invoices = result;\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Gets the part of the UI that should be visible. */\r\n  public get uiStatus(): \"invalid\" | \"loading\" | \"created\" | \"supportedChannel\" | \"unsupported\" | \"userCanceled\" | \"undefined\" {\r\n    if (this.userCanceled) {\r\n      return \"userCanceled\"; // User canceled the process\r\n    }\r\n    if (!this.isValid) {\r\n      return \"invalid\"; // Show validation errors\r\n    }\r\n    if (this.paymentStatus === \"unknown\") {\r\n      return \"loading\"; // this.invoices is still loading => Show spinner\r\n    }\r\n    if (this.paymentStatus === \"exceptions\"\r\n      || this.paymentStatus === \"canceled\"\r\n      || this.paymentStatus === \"inProgress\"\r\n      || this.paymentStatus === \"paid\"\r\n    ) {\r\n      return \"created\"; // Invoices have already been created (no swithching channel).\r\n    }\r\n    if (!this.channel || this.channel === PaymentChannel.Undefined) {\r\n      return \"undefined\"; // Choose channel\r\n    }\r\n    const supportedChannels = [\r\n      PaymentChannel.AccountorGo,\r\n      PaymentChannel.FinagoSolo,\r\n      PaymentChannel.Kevytyrittaja,\r\n      PaymentChannel.Askelma,\r\n      PaymentChannel.Briox,\r\n      PaymentChannel.Lemonaid,\r\n      PaymentChannel.Laskupiste,\r\n      PaymentChannel.PasseliMerit,\r\n      PaymentChannel.Odoo,\r\n      PaymentChannel.Ecom,\r\n      PaymentChannel.Kompassi,\r\n      PaymentChannel.Domus,\r\n      PaymentChannel.Holvi,\r\n      PaymentChannel.PalkkausManual,\r\n      PaymentChannel.PalkkausWS,\r\n      PaymentChannel.PalkkausPersonal,\r\n      PaymentChannel.PalkkausInvoices,\r\n      PaymentChannel.Kitsas,\r\n      PaymentChannel.Test,\r\n      PaymentChannel.ZeroPayment,\r\n      PaymentChannel.TalenomOnline,\r\n      PaymentChannel.VismaNetvisor,\r\n      PaymentChannel.Procountor\r\n    ];\r\n    if (supportedChannels.find((x) => x === this.channel)) {\r\n      return \"supportedChannel\"; // Supported channel\r\n    }\r\n    return \"unsupported\";\r\n  }\r\n\r\n  /** Returns current salary date kind */\r\n  public get salaryDateKind(): SalaryDateKind {\r\n    let salaryDateKind: SalaryDateKind = undefined;\r\n    if (InvoicesLogic.isPayroll(this.current)) {\r\n      salaryDateKind = this.current.input.salaryDateKind;\r\n    }\r\n    else if (InvoicesLogic.isCalculation(this.current)) {\r\n      salaryDateKind = this.current.workflow.salaryDateKind;\r\n    }\r\n    return salaryDateKind ?? SalaryDateKind.Default;\r\n  }\r\n\r\n  /**\r\n   * Starts the invoices creation process from the current channel and model.\r\n   * This method is used when controller is used first as previe and then creating invoices.\r\n   */\r\n  public createInvoices(closeFunc?: (action) => any) {\r\n    if (!this.channel || this.channel === PaymentChannel.Undefined || !this.isValid) {\r\n      throw new Error(\"Cannot start invoices creation\");\r\n    }\r\n\r\n    if (!this.invoicesService.checkAccountVerificationForPayment()) {\r\n      this.invoicesService.showMissingSignatureAlert();\r\n      return;\r\n    }\r\n\r\n    if (!this.invoicesService.checkChangedSalaryDate(this.current)) {\r\n      this.invoicesService.showChangedSalaryDateAlert();\r\n      return;\r\n    }\r\n\r\n    if(InvoicesLogic.isEcfa(this.channel)) {\r\n      if(!this.invoicesService.checkKycForPayment()) {\r\n        this.invoicesService.showMissingKycAlert();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const inProgress = [InvoiceStatus.WaitingPalkkaus, InvoiceStatus.Read, InvoiceStatus.WaitingConfirmation, InvoiceStatus.PaymentStarted];\r\n\r\n    // TODO: We should allow redirection for payroll payments to TalenomOnline and Procountor, like with InvoicesLogic.isCalculation.\r\n    if (InvoicesLogic.isPayroll(this.current)) {\r\n      if (this.channel === PaymentChannel.Test ||\r\n        this.channel === PaymentChannel.VismaNetvisor ||\r\n        this.channel === PaymentChannel.Procountor) {\r\n\r\n        if (this.paymentStatus === \"inProgress\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.paymentDialogOpened\");\r\n          const idsToPay = this.invoices.filter((x) => inProgress.indexOf(x.invoice.status) >= 0).map((x) => x.invoice.id);\r\n          let url = \"\";\r\n          switch (this.channel) {\r\n            case PaymentChannel.Test:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"https://test-integrations.salaxy.com/test#/dialogs/payment\" :\r\n                  \"https://integrations.salaxy.com/test#/dialogs/payment\";\r\n              break;\r\n            case PaymentChannel.Procountor:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"http://localhost:93/procountor/payment.html\" :\r\n                  \"https://integrations.salaxy.com/procountor/payment.html\";\r\n              break;\r\n            case PaymentChannel.VismaNetvisor:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"http://localhost:93/vismanetvisor/payment.html\" :\r\n                  \"https://integrations.salaxy.com/vismanetvisor/payment.html\";\r\n              break;\r\n          }\r\n          url += \"?invoiceIds=\" + idsToPay + \"&token=\" + this.ajax.getCurrentToken();\r\n          this.uiHelpers.showExternalDialog(\"payrollPayment\", url, {})\r\n            .then(() => {\r\n              loader.dismiss();\r\n              // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n              this.$location.path(\"/payroll/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n              if (closeFunc) {\r\n                closeFunc(\"ok\");\r\n              }\r\n            });\r\n        } else {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n          this.invoicesApi.createInvoicesForPayroll(this.channel, this.current.id).then((result) => {\r\n            loader.setHeading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.paymentDialogOpened\");\r\n            const idsToPay = result.filter((x) => x.header.status === InvoiceStatus.Unread).map((x) => x.id);\r\n            let url = \"\";\r\n            switch (this.channel) {\r\n              case PaymentChannel.Test:\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"https://test-integrations.salaxy.com/test#/dialogs/payment\" :\r\n                    \"https://integrations.salaxy.com/test#/dialogs/payment\";\r\n                break;\r\n              case PaymentChannel.Procountor:\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"http://localhost:93/procountor/payment.html\" :\r\n                    \"https://integrations.salaxy.com/procountor/payment.html\";\r\n                break;\r\n              case PaymentChannel.VismaNetvisor:\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"http://localhost:93/vismanetvisor/payment.html\" :\r\n                    \"https://integrations.salaxy.com/vismanetvisor/payment.html\";\r\n                break;\r\n            }\r\n            url += \"?invoiceIds=\" + idsToPay + \"&token=\" + this.ajax.getCurrentToken();\r\n            this.uiHelpers.showExternalDialog(\"payrollPayment\", url, {})\r\n              .then(() => {\r\n                loader.dismiss();\r\n                // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n                this.$location.path(\"/payroll/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n                if (closeFunc) {\r\n                  closeFunc(\"ok\");\r\n                }\r\n              });\r\n          });\r\n        }\r\n      } else {\r\n        if (this.current.calcs?.length > 0) {\r\n          // old\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n          this.invoicesApi.createInvoicesForPayroll(this.channel, this.current.id).then(() => {\r\n            loader.dismiss();\r\n            // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n            this.$location.path(\"/payroll/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n            this.showInvoiceSuccessAlert(this.channel);\r\n            if (closeFunc) {\r\n              closeFunc(\"ok\");\r\n            }\r\n          });\r\n        }\r\n        else\r\n        {\r\n          // new\r\n          const payrolls4Api = new Payrolls4(this.ajax);\r\n          payrolls4Api.getCalcsOData(this.current.id, null).then((listItemResult) => {\r\n            const calcs = listItemResult.items;\r\n            const data: any = {};\r\n            data.listItemType = \"CalculationListItem\";\r\n            const columns = undefined;\r\n            const paramsTemplate = undefined;\r\n            const action = (items, data) => {\r\n              const itemIds = items.map((x) => x.id);\r\n              const remainingAfterThis =  data.dialogList.filter((x) => !x.processed).length;\r\n              const excludePeriodic = remainingAfterThis == 0 ? false:  true;\r\n              return payrolls4Api.createInvoices(this.current.id, itemIds, excludePeriodic).then((result) => {\r\n                const results = items.map(() => ( {message: \"\", result: []}));\r\n                if (results.length > 0) {\r\n                  results[0].result = result;\r\n                }\r\n                return results;\r\n              });\r\n            };\r\n            this.uiHelpers.showBatchProcessDialog(Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\"), calcs, action, paramsTemplate, data, columns, 20, true, true, true).then((dialogResult) => {\r\n              if (dialogResult.done) {\r\n                // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n                this.$location.path(\"/payroll/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n                this.showInvoiceSuccessAlert(this.channel);\r\n                if (closeFunc) {\r\n                  closeFunc(\"ok\");\r\n                }\r\n              }\r\n              else\r\n              {\r\n                this.userCanceled = true;\r\n              }\r\n            });\r\n          });\r\n        }\r\n      }\r\n    } else if (InvoicesLogic.isCalculation(this.current)) {\r\n\r\n      const refreshCurrentCalculation = (invoices: Invoice[]): Promise<Calculation> => {\r\n        if (invoices) {\r\n          const calcId = (invoices.find((x) => x.header.type === InvoiceType.Net || x.header.type === InvoiceType.Gross))?.header.businessObjects[0];\r\n          if (calcId) {\r\n            return this.calculationsApi.getSingle(calcId).then((calculation) => {\r\n              angular.copy(calculation, this.current);\r\n              return this.current;\r\n            });\r\n          }\r\n        }\r\n        return Promise.resolve(this.current);\r\n      };\r\n      if (this.channel === PaymentChannel.Test ||\r\n        this.channel === PaymentChannel.VismaNetvisor ||\r\n        this.channel === PaymentChannel.Procountor) {\r\n\r\n        if (this.paymentStatus === \"inProgress\") {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.paymentDialogOpened\");\r\n          const idsToPay = this.invoices.filter((x) => inProgress.indexOf(x.invoice.status) >= 0).map((x) => x.invoice.id);\r\n          let url = \"\";\r\n          switch (this.channel) {\r\n            case PaymentChannel.Test:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"https://test-integrations.salaxy.com/test#/dialogs/payment\" :\r\n                  \"https://integrations.salaxy.com/test#/dialogs/payment\";\r\n              break;\r\n            case PaymentChannel.Procountor:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"http://localhost:93/procountor/payment.html\" :\r\n                  \"https://integrations.salaxy.com/procountor/payment.html\";\r\n              break;\r\n            case PaymentChannel.VismaNetvisor:\r\n              url =\r\n                Configs.current.isTestData ?\r\n                  \"http://localhost:93/vismanetvisor/payment.html\" :\r\n                  \"https://integrations.salaxy.com/vismanetvisor/payment.html\";\r\n              break;\r\n          }\r\n          url += \"?invoiceIds=\" + idsToPay + \"&token=\" + this.ajax.getCurrentToken();\r\n          this.uiHelpers.showExternalDialog(\"calcPayment\", url, {})\r\n            .then(() => {\r\n              refreshCurrentCalculation(null).then(() => {\r\n                loader.dismiss();\r\n                // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n                this.$location.path(\"/calc/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n              });\r\n              if (closeFunc) {\r\n                closeFunc(\"ok\");\r\n              }\r\n            });\r\n        }\r\n        else {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n          this.invoicesApi.createInvoices(this.current, this.channel).then((result) => {\r\n            loader.setHeading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.paymentDialogOpened\");\r\n            let idsToPay = result.filter((x) => x.header.status === InvoiceStatus.Unread).map((x) => x.id);\r\n            let url = \"\";\r\n            switch (this.channel) {\r\n              case PaymentChannel.Test:\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"https://test-integrations.salaxy.com/test#/dialogs/payment\" :\r\n                    \"https://integrations.salaxy.com/test#/dialogs/payment\";\r\n                break;\r\n              case PaymentChannel.Procountor:\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"http://localhost:93/procountor/payment.html\" :\r\n                    \"https://integrations.salaxy.com/procountor/payment.html\";\r\n                break;\r\n              case PaymentChannel.VismaNetvisor:\r\n                idsToPay = result\r\n                  .filter(v => v.header.paymentType === InvoicePaymentType.Salary && v.header.status === InvoiceStatus.Unread)\r\n                  .map(v => v.id);\r\n                url =\r\n                  Configs.current.isTestData ?\r\n                    \"http://localhost:93/vismanetvisor/payment.html\" :\r\n                    \"https://integrations.salaxy.com/vismanetvisor/payment.html\";\r\n                break;\r\n            }\r\n            url += \"?invoiceIds=\" + idsToPay + \"&token=\" + this.ajax.getCurrentToken();\r\n            this.uiHelpers.showExternalDialog(\"calcPayment\", url, {})\r\n              .then(() => {\r\n                refreshCurrentCalculation(result).then(() => {\r\n                  loader.dismiss();\r\n                  // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n                  this.$location.path(\"/calc/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n                });\r\n                if (closeFunc) {\r\n                  closeFunc(\"ok\");\r\n                }\r\n              });\r\n          });\r\n        }\r\n      } else {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n        this.invoicesApi.createInvoices(this.current, this.channel).then((result) => {\r\n          refreshCurrentCalculation(result).then(() => {\r\n            loader.dismiss();\r\n            // HACK: Need a way to configure the URL and potentially raise an event for reload.\r\n            this.$location.path(\"/calc/details/\" + this.current.id + \"&refresh=\" + new Date().getTime());\r\n            this.showInvoiceSuccessAlert(this.channel);\r\n          });\r\n          if (closeFunc) {\r\n            closeFunc(\"ok\");\r\n          }\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Create invoices for calculation: Immediate execution without preview. Used in PRO and other advanced UI.\r\n   * Shows a loader dialog, saves changes if necessary, creates invoices and reloads the controller.\r\n   * @param calcController Controller that contains the calculation that should be paid. May have save changes.\r\n   * @param channel Payment channel that is used for payment.\r\n   */\r\n  public createInvoicesForCalculation(calcController: CalculationCrudController, channel: PaymentChannel): Promise<Invoice[]> {\r\n    if (!this.invoicesService.checkAccountVerificationForPayment()) {\r\n      this.invoicesService.showMissingSignatureAlert();\r\n      return;\r\n    }\r\n\r\n    if (!this.invoicesService.checkChangedSalaryDate(calcController.current)) {\r\n      this.invoicesService.showChangedSalaryDateAlert();\r\n      return;\r\n    }\r\n\r\n    if(InvoicesLogic.isEcfa(channel)) {\r\n      if(!this.invoicesService.checkKycForPayment()) {\r\n        this.invoicesService.showMissingKycAlert();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n    return this.invoicesApi.createInvoices(calcController.current, channel).then((result) => {\r\n      calcController.reload();\r\n      loader.dismiss();\r\n      this.showInvoiceSuccessAlert(channel);\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Create invoices for payroll: Immediate execution without preview. Used in PRO and other advanced UI.\r\n   * Shows a loader dialog, saves changes if necessary, creates invoices and reloads the controller.\r\n   * @param payrollController Controller that contains the calculation that should be paid. May have save changes.\r\n   * @param channel Payment channel that is used for payment.\r\n   */\r\n  public createInvoicesForPayroll(payrollController: PayrollCrudController, channel: PaymentChannel): Promise<Invoice[]> {\r\n    if (!this.invoicesService.checkAccountVerificationForPayment()) {\r\n      this.invoicesService.showMissingSignatureAlert();\r\n      return;\r\n    }\r\n\r\n    if (!this.invoicesService.checkChangedSalaryDate(payrollController.current)) {\r\n      this.invoicesService.showChangedSalaryDateAlert();\r\n      return;\r\n    }\r\n\r\n    if(InvoicesLogic.isEcfa(channel)) {\r\n      if(!this.invoicesService.checkKycForPayment()) {\r\n        this.invoicesService.showMissingKycAlert();\r\n        return;\r\n      }\r\n    }\r\n\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.creatingInvoices\");\r\n\r\n    const invoiceCreate = () => {\r\n      return this.invoicesApi.createInvoicesForPayroll(channel, payrollController.current.id).then((result) => {\r\n        payrollController.reload();\r\n        loader.dismiss();\r\n        this.showInvoiceSuccessAlert(channel);\r\n        return result;\r\n      });\r\n    };\r\n\r\n    if (payrollController.hasChanges || payrollController.isNew()) {\r\n      return payrollController.save().then(() => {\r\n        return invoiceCreate();\r\n      });\r\n    } else {\r\n      return invoiceCreate();\r\n    }\r\n  }\r\n\r\n  /** Gets text for preview invoice */\r\n  public getPreviewText(item: InvoicePreview): string {\r\n    if( (item.invoice.data.channel == PaymentChannel.PalkkausInvoices ||  item.invoice.data.channel == PaymentChannel.Kitsas) && (item.invoice.entityType == InvoiceType.Tax || item.invoice.entityType == InvoiceType.Union || item.invoice.entityType == InvoiceType.Payroll)) {\r\n      return Translations.get(\"SALAXY.NG1.InvoicesCreateTableComponent.PalkkausInvoicesTaxPreviewText\");\r\n    }\r\n    return Translations.get(\"SALAXY.NG1.InvoicesCreateTableComponent.dueDateTypePreview\");\r\n  }\r\n\r\n  /** Gets text for estimation invoice */\r\n  public getEstimationText(item: InvoicePreview): string {\r\n    return `${item.invoice.otherPartyInfo.avatar.sortableName} ${Translations.get(\"SALAXY.NG1.InvoicesCreateTableComponent.sendsInvoice\")}`;\r\n  }\r\n\r\n  /** Gets the type of the calculation for display purposes. */\r\n  public getDueDateType(item: InvoicePreview): \"default\" | \"estimation\" | \"forecast\" | \"preview\" | \"zero\" | \"unknown\" | \"paid\" {\r\n    if (item.invoice.entityType === \"unemployment\") {\r\n      return \"estimation\";\r\n    }\r\n\r\n    if (item.invoice.status === InvoiceStatus.Forecast) {\r\n      return \"forecast\";\r\n    }\r\n\r\n    if (item.invoice.status === InvoiceStatus.Preview) {\r\n      return \"preview\";\r\n    }\r\n\r\n    if (item.invoice.data.channel === PaymentChannel.ZeroPayment) {\r\n      return \"zero\";\r\n    }\r\n\r\n    if (item.invoice.status === InvoiceStatus.Paid && item.invoice.payment === 0) {\r\n      return \"zero\";\r\n    }\r\n\r\n    if (!item.invoice.otherId && item.invoice.data.channel === PaymentChannel.VismaNetvisor) {\r\n      return \"preview\";\r\n    }\r\n\r\n    if (item.invoice.status === InvoiceStatus.Paid) {\r\n      return \"paid\";\r\n    }\r\n\r\n    if (item.invoice.data.channel === PaymentChannel.PalkkausManual && (item.invoice.entityType === InvoiceType.Net || item.invoice.entityType === InvoiceType.Foreclosure) && this.salaryDateKind === SalaryDateKind.InPast) {\r\n      return \"paid\";\r\n    }\r\n\r\n    if (( item.invoice.data.channel === PaymentChannel.PalkkausInvoices ||  item.invoice.data.channel === PaymentChannel.Kitsas ) && (item.invoice.entityType === InvoiceType.Net || item.invoice.entityType === InvoiceType.Foreclosure) && this.salaryDateKind === SalaryDateKind.InPast) {\r\n      return \"paid\";\r\n    }\r\n\r\n    if( (item.invoice.data.channel == PaymentChannel.PalkkausInvoices ||  item.invoice.data.channel == PaymentChannel.Kitsas) &&\r\n    (item.invoice.entityType == InvoiceType.Tax || item.invoice.entityType == InvoiceType.Union || item.invoice.entityType == InvoiceType.Payroll))\r\n    {\r\n      return \"preview\";\r\n    }\r\n\r\n    return \"default\";\r\n  }\r\n\r\n  /**\r\n   * Returns the net invoice preview for current calculation.\r\n   */\r\n  public get primaryCalcNetInvoicePreview(): InvoicePreview {\r\n    if (!this._primaryCalcNetInvoicePreview && this.invoices && this.invoices.length > 0) {\r\n      const preview = this.invoices.find((x) => x.invoice.entityType === InvoiceType.Net && x.invoice.status !== InvoiceStatus.Canceled && x.invoice.status !== InvoiceStatus.Error);\r\n      if (preview) {\r\n        this._primaryCalcNetInvoicePreview = preview;\r\n      }\r\n    }\r\n    return this._primaryCalcNetInvoicePreview;\r\n  }\r\n\r\n  /**\r\n   * Returns the ysc invoice preview for current calculation.\r\n   */\r\n  public get primaryCalcTaxInvoicePreview(): InvoicePreview {\r\n    if (!this._primaryCalcTaxInvoicePreview && this.invoices && this.invoices.length > 0) {\r\n      const preview = this.invoices.find((x) => x.invoice.entityType === InvoiceType.Tax && x.invoice.status !== InvoiceStatus.Canceled && x.invoice.status !== InvoiceStatus.Error);\r\n      if (preview) {\r\n        this._primaryCalcTaxInvoicePreview = preview;\r\n      }\r\n    }\r\n    return this._primaryCalcTaxInvoicePreview;\r\n  }\r\n\r\n  private getNetInvoiceId(invoices: Invoice[]): string {\r\n    if (!invoices || invoices.length === 0) {\r\n      return null;\r\n    }\r\n    return (invoices.find((x) => x.header.type === InvoiceType.Net) || {}).id;\r\n  }\r\n\r\n  private showInvoiceSuccessAlert(channel: PaymentChannel) {\r\n    if (channel === PaymentChannel.ZeroPayment) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.zeroPayment.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.zeroPayment.successAlertText\");\r\n    } else if (channel === PaymentChannel.AccountorGo) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.accountorGo.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.accountorGo.successAlertText\");\r\n    } else if (channel === PaymentChannel.FinagoSolo) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.finagoSolo.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.finagoSolo.successAlertText\");\r\n    } else if (channel === PaymentChannel.Kevytyrittaja) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kevytyrittaja.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kevytyrittaja.successAlertText\");\r\n    } else if (channel === PaymentChannel.Askelma) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.askelma.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.askelma.successAlertText\");\r\n    } else if (channel === PaymentChannel.Briox) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.briox.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.briox.successAlertText\");\r\n    } else if (channel === PaymentChannel.Lemonaid) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.lemonaid.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.lemonaid.successAlertText\");\r\n    } else if (channel === PaymentChannel.Laskupiste) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.laskupiste.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.laskupiste.successAlertText\");\r\n    } else if (channel === PaymentChannel.PasseliMerit) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.passeliMerit.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.passeliMerit.successAlertText\");\r\n    } else if (channel === PaymentChannel.Odoo) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.odoo.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.odoo.successAlertText\");\r\n    } else if (channel === PaymentChannel.Ecom) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.ecom.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.ecom.successAlertText\");\r\n    } else if (channel === PaymentChannel.Kompassi) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kompassi.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kompassi.successAlertText\");\r\n    } else if (channel === PaymentChannel.Domus) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.domus.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.domus.successAlertText\")\r\n      .then(() => {\r\n        window.parent.postMessage({ \"salaxyEvent\": \"InvoiceSuccessAlert\" }, \"*\");\r\n        console.debug(\"Domus\",\"InvoiceSuccessAlert posted with postMessage\");\r\n      });\r\n    } else if (channel === PaymentChannel.Holvi) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.holvi.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.holvi.successAlertText\");\r\n    } else if (channel === PaymentChannel.TalenomOnline) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.talenomOnline.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.talenomOnline.successAlertText\");\r\n    } else if (channel === PaymentChannel.PalkkausManual) {\r\n      if (this.salaryDateKind == SalaryDateKind.InPast) {\r\n        this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManualAndFixed.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManualAndFixed.successAlertText\");\r\n      }\r\n      else {\r\n        this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManual.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausManual.successAlertText\");\r\n      }\r\n    } else if (channel === PaymentChannel.PalkkausWS) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausWS.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausWS.successAlertText\");\r\n    } else if (channel === PaymentChannel.PalkkausPersonal) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausPersonal.successAlertHeading\", \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausPersonal.successAlertText\");\r\n    } else if (channel === PaymentChannel.PalkkausInvoices) {\r\n      this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausInvoices.successAlertHeading\",\r\n        null,\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausInvoices.successAlertOk\",\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausInvoices.successAlertCancel\",\r\n        Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.palkkausInvoices.successAlertText\"),\r\n      ).then((x) => {\r\n        if (x) {\r\n          this.$location.path(\"/invoices/company\");\r\n        } else {\r\n          // TODO: Now this only closes, should there be a redirect here?\r\n        }\r\n      });\r\n    }\r\n    else if (channel === PaymentChannel.Kitsas) {\r\n      this.uiHelpers.showConfirm(\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kitsas.successAlertHeading\",\r\n        null,\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kitsas.successAlertOk\",\r\n        \"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kitsas.successAlertCancel\",\r\n        Translations.get(\"SALAXY.NG1.InvoicesCreateComponent.PaymentChannel.kitsas.successAlertText\"),\r\n      ).then((x) => {\r\n        if (x) {\r\n          this.$location.path(\"/invoices/company\");\r\n        } else {\r\n          // TODO: Now this only closes, should there be a redirect here?\r\n        }\r\n      });\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, Invoice, InvoiceListItem, InvoicesLogic, InvoiceStatusNotification, PaymentChannel, PaymentChannelApi, Translations } from \"@salaxy/core\";\r\n\r\nimport { AjaxNg1 } from \"../../ajax\";\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Provides access for a payment channel to access invoices\r\n * that were sent to that channel and also the calculations etc. related to those invoices.\r\n * Only a Partner with registered Payment Channel can use this Controller.\r\n * Please contact Palkkaus.fi support for more information.\r\n */\r\nexport class PaymentChannelController extends ApiCrudObjectController<Invoice, InvoiceListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AjaxNg1\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"SessionService\",\r\n    \"$scope\",\r\n  ];\r\n\r\n  /** Status notification data for UI binding to update status. */\r\n  public statusData: InvoiceStatusNotification;\r\n\r\n  private _channel: PaymentChannel;\r\n\r\n  private _initialOwner: string;\r\n\r\n  private unread: Invoice[];\r\n\r\n  constructor(\r\n    private ajax: AjaxNg1,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private sessionService: SessionService,\r\n    private $scope: angular.IScope,\r\n  ) { // Dependency injection\r\n    super(new PaymentChannelApi(null, ajax), uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    const setChannel = () => {\r\n\r\n      if (this.sessionService.isSessionChecked && this.sessionService.isAuthenticated) {\r\n        const owner = this.sessionService.session.currentAccount.owner;\r\n        if (this._initialOwner != owner){\r\n          this._initialOwner = owner;\r\n          this.channel = this.sessionService.getOwnedPaymentChannel();\r\n          this.reload();\r\n          this.unread = null;\r\n          if (this.odataController) {\r\n            this.odataController.refreshClearAll();\r\n          }\r\n        }\r\n      } else {\r\n        this._initialOwner = null;\r\n        this.channel = null;\r\n        this.api = null;\r\n        this.unread = null;\r\n          if (this.odataController) {\r\n            this.odataController.refreshClearAll();\r\n          }\r\n      }\r\n    };\r\n\r\n    setChannel();\r\n\r\n    this.sessionService.subscribe(this.$scope, () => {\r\n      setChannel();\r\n    });\r\n\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Name/key of the channel on which the controller operates. */\r\n  public get channel(): PaymentChannel {\r\n    return this._channel;\r\n  }\r\n  public set channel(value: PaymentChannel) {\r\n    this._channel = value;\r\n    if (value) {\r\n      this.api = new PaymentChannelApi(value, this.ajax);\r\n    }\r\n  }\r\n\r\n  /** Gets the full items for unread objects. */\r\n  public get unreadInvoices(): Invoice[] {\r\n    if (!this.unread) {\r\n      this.unread = [];\r\n      this.paymentChannelApi.getInvoicesByStatus().then((items) => {\r\n        this.unread = items;\r\n      });\r\n    }\r\n    return this.unread;\r\n  }\r\n\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"payment-channel\",\r\n      detailsUrl: this.detailsUrl || \"/payment-channel/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/InvoicesPanel.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Returns content url for the invoice. */\r\n  public getContentUrl(id: string, inline = false): string {\r\n    return this.paymentChannelApi.getContentUrl(id, inline);\r\n  }\r\n\r\n  /**\r\n   * Updates the status of the invoice.\r\n   * @param data Status data. If not set, uses the statusData property of the controller.\r\n   */\r\n  public updateStatus(data: InvoiceStatusNotification = null): Promise<Invoice> {\r\n    const loading = this.uiHelpers.showLoading();\r\n    data = data || this.statusData;\r\n    return this.setStatus(this.paymentChannelApi.updateStatus([data])\r\n      .then((invoices) => {\r\n        loading.dismiss();\r\n        this.setCurrent(invoices[0]);\r\n        this.resetStatusData();\r\n        return invoices[0];\r\n      }));\r\n  }\r\n\r\n  /** Resets the status data according to current Invoice. */\r\n  public resetStatusData() {\r\n    if (!this.current) {\r\n      this.statusData = null;\r\n      return;\r\n    }\r\n    this.statusData = {\r\n      id: this.current.id,\r\n      externalId: this.current.header.externalId,\r\n      date: Dates.getToday(),\r\n      status: this.current.header.status,\r\n      amount: this.current.header.total,\r\n    };\r\n  }\r\n\r\n  /** Gets and avatar image for a payment channel */\r\n  public getChannelAvatar() {\r\n    return InvoicesLogic.getChannelAvatar(this.channel);\r\n  }\r\n\r\n  /** Data reader for selected items. */\r\n  public selectionDataReader = {\r\n    /** Function to read data into given array */\r\n    read: (arr: Invoice[], message: string): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n      const promises = this.odataController.selectedItems.map(x => this.api.getSingle(x.id));\r\n      return Promise.all(promises).then((data) => {\r\n        arr.push(...data.filter(d => !!d));\r\n        return;\r\n      });\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: Translations.get(\"SALAXY.NG1.AccountingReportToolsComponent.exportLabel\"),\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.odataController.selectedItems || this.odataController.selectedItems.length === 0,\r\n  };\r\n\r\n  /**\r\n   * Data reader for one item.\r\n   * TODO: Should add interface for the reader.\r\n   */\r\n  public getItemDataReader = (item: {\r\n    /** List item id */\r\n    id: string,\r\n    /** List item owner */\r\n    owner: string,\r\n  }) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (arr: Invoice[], message: string): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n        (item as any).isReading = true;\r\n        return this.api.getSingle(item.id).then((data) => {\r\n          /*\r\n          const wfEvent = {\r\n            type: \"PartnerMessageClosed\",\r\n            ui: \"success\" as any,\r\n            message,\r\n          };\r\n          return this.filesApi.saveWorkflowEvent(item, wfEvent).then(() => {\r\n            this.setWorkflowEvent(item as any, wfEvent);\r\n          */\r\n          if (data) {\r\n            arr.push(data);\r\n          }\r\n          (item as any).isReading = false;\r\n          return Promise.resolve();\r\n          /* });*/\r\n        });\r\n      },\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n    };\r\n  };\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n    if (this.odataController.selectedItems) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n    }\r\n  }\r\n\r\n  /** Select all */\r\n  public selectAll() {\r\n    if (this.odataController.selectedItems && this.odataController.items) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n      this.odataController.selectedItems.push(...this.odataController.items);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates the invoice. Only valid in the test environment.\r\n   */\r\n  public save(): Promise<Invoice> {\r\n    const loading = this.uiHelpers.showLoading();\r\n    return this.ajax.postJSON( `/v03/api/payment-channel/${this.channel}`, this.current)\r\n      .then((invoice) => {\r\n        loading.dismiss();\r\n        this.setCurrent(invoice);\r\n        return invoice;\r\n      });\r\n  }\r\n\r\n  private get paymentChannelApi() {\r\n    return this.api as PaymentChannelApi;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport JSZip from \"@progress/jszip-esm\";\r\n\r\nimport * as FileSaver from \"file-saver\";\r\n\r\nimport { Ajax, Dates, Invoice, InvoiceType, PaymentChannel, Texts, Translations } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/** File type id */\r\nenum FileTypeId {\r\n  SepaFile = \"sepaFile\",\r\n  SepaCopy = \"sepaCopy\",\r\n  PdfFile = \"pdfFile\",\r\n  FinvoiceFile = \"finvoiceFile\"\r\n}\r\n\r\n/**\r\n * Provides functionality to export invoices in various formats.\r\n */\r\nexport class InvoiceToolsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AjaxNg1\",\r\n    \"$http\",\r\n    \"UiHelpers\"\r\n  ];\r\n\r\n  /** Export format */\r\n  public fileTypeId: string = FileTypeId.PdfFile;\r\n\r\n  /** Supported export formats */\r\n  public fileTypes: {\r\n    /** File type id */\r\n    id: string,\r\n    /** File type label */\r\n    label: string,\r\n    /** Workflow message after export */\r\n    workflowMessage,\r\n    /** Icon */\r\n    icon: string,\r\n  }[] = [\r\n      {\r\n        id: FileTypeId.PdfFile,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.filePdf.label\"),\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.filePdf.label\"),\r\n        icon: \"fa-file-pdf-o\",\r\n      },\r\n      {\r\n        id: FileTypeId.SepaFile,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.fileSepa.label\"),\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.fileSepa.workflowMessage\"),\r\n        icon: \"fa-file-code-o\",\r\n      },\r\n      {\r\n        id: FileTypeId.SepaCopy,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.copySepa.label\"),\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.copySepa.workflowMessage\"),\r\n        icon: \"fa-clipboard\",\r\n      },\r\n      {\r\n        id: FileTypeId.FinvoiceFile,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.finvoiceFile.label\"),\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.finvoiceFile.workflowMessage\"),\r\n        icon: \"fa-file-code-o\",\r\n      },\r\n    ];\r\n\r\n\r\n  /** Filetype Enum Options for filetype select element*/\r\n  public get fileTypeOptions() {\r\n    if (!this._fileTypeOptions) {\r\n      this._fileTypeOptions = this.fileTypes.map((x) => ({ value: x.id, text: x.label }));\r\n    }\r\n    return this._fileTypeOptions;\r\n  }\r\n  /**\r\n   * Object with read function to call for retrieving the invoice data.\r\n   * Function has the following argument:  arr, which is an array of invoices into which the result will be appended.\r\n   */\r\n  public reader: {\r\n    /** Function for reading invoices into given array. */\r\n    read: (\r\n      /** Array for invoices */\r\n      arr: Invoice[],\r\n      /** Message for workflow (loading) */\r\n      message: string,\r\n    ) => Promise<void>,\r\n    /** Function for getting sepa data for invoices */\r\n    getSepaData?: (\r\n      /** Array for invoices */\r\n      arr: Invoice[],\r\n    ) => Promise<string>,\r\n    /** Function for getting finvoice data for invoices */\r\n    getFinvoiceData?: (\r\n      /** Array for invoices */\r\n      arr: Invoice[],\r\n    ) => Promise<Blob[]>,\r\n    /** Function for getting pdf data for invoices */\r\n    getPdfData?: (\r\n      /** Array for invoices */\r\n      arr: Invoice[],\r\n    ) => Promise<Blob[]>,\r\n    /** Optional label for data export */\r\n    exportLabel?: string,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => boolean,\r\n  };\r\n\r\n  private _fileTypeOptions = null;\r\n  constructor(\r\n    private ajax: Ajax,\r\n    private $http: angular.IHttpService,\r\n    private uiHelpers: UiHelpers\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    // Nothing here\r\n  }\r\n\r\n  /** Set visible filetypes. Sets the first file type as default. */\r\n  public setFileTypes(fileTypes: string[]) {\r\n    if (fileTypes && fileTypes.length > 0) {\r\n      const fts = [];\r\n      fileTypes.forEach((x) => {\r\n        const ft = this.fileTypes.find((f) => f.id === x);\r\n        if (ft) {\r\n          fts.push(ft);\r\n        }\r\n      });\r\n      this.fileTypes.splice(0);\r\n      this.fileTypes.push(...fts);\r\n      this.fileTypeId = fileTypes[0];\r\n    }\r\n  }\r\n\r\n  /** Exports data in defined format. */\r\n  public export(\r\n    reader: {\r\n      /** Function for reading data into given array. */\r\n      read: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n        /** Workflow loading message */\r\n        message: string,\r\n      ) => Promise<void>,\r\n      /** Function for getting sepa data for invoices */\r\n      getSepaData?: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ) => Promise<string>,\r\n      /** Function for getting finvoice data for invoices */\r\n      getFinvoiceData?: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ) => Promise<Blob[]>,\r\n      /** Function for getting pdf data for invoices */\r\n      getPdfData?: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ) => Promise<Blob[]>,\r\n      /** Optional label for data export */\r\n      exportLabel?: string,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => boolean,\r\n    } = null,\r\n    /** If true, does not show loading indicator. Default is false. */\r\n    hideLoading = false,\r\n    /** If true, does not return any content. */\r\n    withoutContent = false,\r\n  ): Promise<void> {\r\n    if (!reader) {\r\n      reader = this.reader;\r\n    }\r\n    if (!reader) {\r\n      console.error(\"No reader for invoices.\");\r\n      return Promise.resolve();\r\n    }\r\n    const loading = hideLoading ? { dismiss: () => null } : this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n\r\n    const arr: Invoice[] = [];\r\n    return reader.read(arr, this.getWorkflowMessage()).then(() => {\r\n      if (arr.length === 0) {\r\n        loading.dismiss();\r\n        return Promise.resolve();\r\n      }\r\n      if (withoutContent) {\r\n        return;\r\n      }\r\n      switch (this.fileTypeId) {\r\n        case FileTypeId.PdfFile:\r\n          return (reader.getPdfData ?? ((x) => this.getPdfData(x)))(arr).then((pdfArr) => {\r\n            if (pdfArr.length === 1) {\r\n              FileSaver.saveAs(pdfArr[0], `${this.getFileName(arr[0])}.pdf`);\r\n              loading.dismiss();\r\n              return;\r\n            } else {\r\n              let counter = 0;\r\n              const zip = new JSZip();\r\n              const next = () => {\r\n                if (counter === pdfArr.length) {\r\n                  return;\r\n                }\r\n                zip.file(`${this.getFileName(arr[counter])}.pdf`, pdfArr[counter]);\r\n                counter++;\r\n                next();\r\n              };\r\n\r\n              next();\r\n              return zip.generateAsync({\r\n                type: \"blob\",\r\n                mimeType:\r\n                  \"application/zip\",\r\n              }).then((blob) => {\r\n                FileSaver.saveAs(blob, `${this.getZipFileName(arr)}.zip`);\r\n                loading.dismiss();\r\n                return;\r\n              });\r\n            }\r\n          });\r\n          break;\r\n        case FileTypeId.SepaFile:\r\n          return (reader.getSepaData ?? ((x) => this.getSepaData(x)))(arr).then((sepaData) => {\r\n            FileSaver.saveAs(new Blob([sepaData], { type: \"text/xml;charset=utf-8\" }), arr.length === 1 ? `${this.getFileName(arr[0])}.xml` : `${this.getZipFileName(arr)}.xml`);\r\n            loading.dismiss();\r\n            return;\r\n          });\r\n          break;\r\n        case FileTypeId.SepaCopy:\r\n          return (reader.getSepaData ?? ((x) => this.getSepaData(x)))(arr).then((sepaData) => {\r\n            (navigator as any).clipboard.writeText(sepaData);\r\n            loading.dismiss();\r\n            return;\r\n          });\r\n        case FileTypeId.FinvoiceFile:\r\n          return (reader.getFinvoiceData ?? ((x) => this.getFinvoiceData(x)))(arr).then((finvoiceArr) => {\r\n            if (finvoiceArr.length === 1) {\r\n              FileSaver.saveAs(finvoiceArr[0], `${this.getFileName(arr[0])}.xml`);\r\n              loading.dismiss();\r\n              return;\r\n            } else {\r\n              let counter = 0;\r\n              const zip = new JSZip();\r\n              const next = () => {\r\n                if (counter === finvoiceArr.length) {\r\n                  return;\r\n                }\r\n                zip.file(`${this.getFileName(arr[counter])}.xml`, finvoiceArr[counter]);\r\n                counter++;\r\n                next();\r\n              };\r\n\r\n              next();\r\n              return zip.generateAsync({\r\n                type: \"blob\",\r\n                mimeType:\r\n                  \"application/zip\",\r\n              }).then((blob) => {\r\n                FileSaver.saveAs(blob, `${this.getZipFileName(arr)}.zip`);\r\n                loading.dismiss();\r\n                return;\r\n              });\r\n            }\r\n          });\r\n          break;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Create single invoice.\r\n   * @param channel Payment channel.\r\n   * @param invoiceType Invoice type.\r\n   * @returns New/updated invoice.\r\n   */\r\n  public createSingleInvoice(channel: PaymentChannel, invoiceType: InvoiceType): Promise<Invoice> {\r\n    const loading = this.uiHelpers.showLoading();\r\n    return this.ajax.postJSON(`/v03/api/invoices/create/${channel}/${invoiceType}?month=${Dates.format(new Date(),\"YYYY-MM-01\")}`, null).then((invoice) => {\r\n      loading.dismiss();\r\n      return this.uiHelpers.showAlert(\"Lasku luotu\",\"Päivitä lista.\").then(() => invoice);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns the file type definition\r\n   * @param fileTypeId File type id.\r\n   */\r\n  public getFileType(fileTypeId: string) {\r\n    return this.fileTypes.find((x) => x.id === fileTypeId);\r\n  }\r\n\r\n\r\n  private getFileName(invoice: Invoice) {\r\n    return Texts.escapeFileName(`${Translations.get(\"SALAXY.UI_Terms.downLoadableMaterialTypes.payment\")}_${invoice.payer.avatar.displayName}_${invoice.id}`);\r\n  }\r\n\r\n  private getZipFileName(invoices: Invoice[]) {\r\n    return Texts.escapeFileName(`${Translations.get(\"SALAXY.UI_Terms.downLoadableMaterialTypes.payments\")}${invoices[0].payer.avatar.displayName}_${Dates.format(\"today\",\"YYYYMMDD\")}`);\r\n  }\r\n\r\n  private getWorkflowMessage() {\r\n    const fileType = this.getFileType(this.fileTypeId);\r\n    if (fileType) {\r\n      return fileType.workflowMessage;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private getPdfData(invoices: Invoice[]): Promise<Blob[]> {\r\n    const promises = invoices.map(x => this.download(\"/v03/api/invoices/content\", x, \"blob\"));\r\n    return Promise.all(promises);\r\n  }\r\n\r\n  private getFinvoiceData(invoices: Invoice[]): Promise<Blob[]> {\r\n    const promises = invoices.map(x => this.download(\"/v03/api/invoices/finvoice\", x, \"blob\"));\r\n    return Promise.all(promises);\r\n  }\r\n\r\n  private getSepaData(invoices: Invoice[], payerIbanNumber: string = null): Promise<string> {\r\n    const method = `/v03/api/invoices/sepa${payerIbanNumber ? \"?payerIbanNumber=\" + encodeURIComponent(payerIbanNumber) : \"\"}`;\r\n    return this.download(method, invoices, \"text\");\r\n  }\r\n  private download(method: string, data: any, responseType: string): Promise<any> {\r\n\r\n    const request: any = {}; // angular.IRequestConfig\r\n\r\n    const token: string = this.ajax.getCurrentToken();\r\n    if (token) {\r\n      request.headers = { Authorization: \"Bearer \" + token };\r\n    }\r\n\r\n    request.url = this.ajax.getServerAddress() + method;\r\n    request.method = \"POST\";\r\n    request.data = data;\r\n    request.responseType = responseType;\r\n    request.withCredentials = (token) ? false : this.ajax.useCredentials;\r\n\r\n    return (this.$http(request).then(\r\n      (response) => response.data,\r\n      (error: any) => {\r\n        return null;\r\n      }) as any\r\n    );\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountInIndex, Ajax, Avatar, Barcodes, Dates, Invoice, InvoiceListItem, Invoices, InvoicesLogic, InvoiceStatus, InvoiceType, Numeric, PaymentChannel, SystemRole, ODataQueryOptions,Translations, Promises, QrCodes, BicHelper } from \"@salaxy/core\";\r\nimport { InvoicesService, SessionService, UiHelpers } from \"../../services\";\r\nimport { InvoiceCrudController } from \"./InvoiceCrudController\";\r\n/**\r\n * Extends the InvoiceCrudController to provide\r\n * SEPA payment management functionality.\r\n */\r\nexport class InvoiceSepaController extends InvoiceCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   */\r\n  public static $inject = [\r\n    \"Invoices\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"InvoicesService\",\r\n    \"AjaxNg1\",\r\n    \"SessionService\",\r\n    \"$http\",\r\n    \"$timeout\",\r\n    \"$sce\"\r\n  ];\r\n\r\n    /** URL for the OData list service, null for preventing automatic initial load */\r\n    public get odataServiceUrl(): string {\r\n      return null;\r\n    }\r\n\r\n  /** List items grouped by owner, invoiceType, status and dueDate */\r\n  public groupedItems: Array<{\r\n    /** Group identifier / key */\r\n    id: string,\r\n    /** Owner (employer) info */\r\n    ownerInfo: AccountInIndex,\r\n    /** Invoice type */\r\n    invoiceType: InvoiceType,\r\n    /** Status of the payments */\r\n    status: InvoiceStatus,\r\n    /** Due date of the payments */\r\n    dueDate: string,\r\n    /** Total payment for the group */\r\n    payment: number,\r\n    /** Payment channel for the group. */\r\n    channel: string,\r\n    /** Key data of the invoices */\r\n    invoices: any[],\r\n  }>;\r\n\r\n  /** Year for invoices query */\r\n  public queryYear = Dates.getToday();\r\n\r\n  /** Status filters for invoices */\r\n  public invoiceEntityTypes = [\r\n    { label: Translations.get(\"SALAXY.NG1.InvoicesComponent.all\"), value: \"all\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.net.label\"), value: \"net\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.pension.label\"), value: \"pension\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.tax.label\"), value: \"tax\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.unemployment.label\"), value: \"unemployment\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.union.label\"), value: \"union\" },\r\n    { label: Translations.get(\"SALAXY.ENUM.InvoiceType.payroll.label\"), value: \"payroll\" },\r\n  ];\r\n\r\n  /** Invoice entity type used in filtering */\r\n  public invoiceEntityType = this.invoiceEntityTypes.find((x) => x.value === \"all\");\r\n\r\n  /** The current status filter. \"waitingConfirmation\" is the default. */\r\n  public statusFilter = this.statusFilters.find((x) => x.value === \"waitingConfirmation\");\r\n\r\n  /** Default sepa channel */\r\n  public sepaChannel:PaymentChannel = PaymentChannel.PalkkausManual;\r\n\r\n  private _allChannels: Avatar[] = null;\r\n\r\n  private qrCodesCache: { [key: string]: string } = {};\r\n\r\n  constructor(\r\n    invoicesFullApi: Invoices,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private invService: InvoicesService,\r\n    private sepaAjax: Ajax,\r\n    private session: SessionService,\r\n    private $http: angular.IHttpService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $sce: angular.ISCEService\r\n  ) {\r\n    // Dependency injection\r\n    super(invoicesFullApi, uiHelpers, $location, $routeParams, invService, sepaAjax);\r\n  }\r\n\r\n  /** Intitializes the controller */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    this.loadData();\r\n  }\r\n\r\n  /**\r\n   * Loads the data for the controller.\r\n   */\r\n  public loadData() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    this.loadAllInvoices().then((items) => {\r\n      this.updateGroupedItems(items);\r\n      loading.dismiss();\r\n      this.$timeout();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Loads all invoices from the server.\r\n   * @returns Promise of all invoices\r\n   */\r\n  public async loadAllInvoices(): Promise<InvoiceListItem[]> {\r\n    const items: any[] = [];\r\n    const sepaChannel = this.sepaChannel || PaymentChannel.PalkkausManual;\r\n    const loadItems = (nextPageLink: string = null): Promise<string> => {\r\n      let options: ODataQueryOptions = {$filter: `data/channel eq '${sepaChannel}' and endAt ge ${Dates.getYear(this.queryYear)}-01-01 and endAt le ${Dates.getYear(this.queryYear)}-12-31`, $orderby: \"endAt desc\"};\r\n      const queryString = nextPageLink?.indexOf(\"?\") ?? -1;\r\n      if (queryString >= 0) {\r\n        const searchParams = new URLSearchParams(nextPageLink.substr(queryString));\r\n        if (searchParams.get(\"$skip\")) {\r\n          options = { $skip:  Number(searchParams.get(\"$skip\")), $filter: `data/channel eq '${sepaChannel}' and endAt ge ${Dates.getYear(this.queryYear)}-01-01 and endAt le ${Dates.getYear(this.queryYear)}-12-31`, $orderby: \"endAt desc\"};\r\n        }\r\n      }\r\n      return this.invoicesApi.getOData(options).then((data) => {\r\n        items.push(...data.items);\r\n        return data.nextPageLink ? loadItems(data.nextPageLink) : null;\r\n      });\r\n    };\r\n\r\n    return loadItems().then(() => {\r\n      return items;\r\n    });\r\n\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for a group of invoices.\r\n   * @param group Group of invoices as defined in groupedItems.\r\n   */\r\n  public showGroupDialog(group: any) {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/invoices/invoice-group-dialog.html\", group, { parent: this }, \"lg\");\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for a single invoice.\r\n   * @param item Invoice item.\r\n   */\r\n  public showInvoiceDialog(item: InvoiceListItem) {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/invoices/invoice-dialog.html\", item, { parent: this }, \"lg\");\r\n  }\r\n\r\n  /** Filter function for angularjs filter used in template */\r\n  public invoiceFilter = (value: InvoiceListItem | any) => {\r\n    if(this.statusFilter.value === \"all\" && this.invoiceEntityType.value === \"all\") {\r\n      return true;\r\n    }\r\n\r\n    if(this.invoiceEntityType.value !== \"all\" && value.invoiceType !== this.invoiceEntityType.value) {\r\n      return false;\r\n    }\r\n\r\n    const statuses = {\r\n      waitingConfirmation: [InvoiceStatus.Unread, InvoiceStatus.Read, InvoiceStatus.WaitingConfirmation],\r\n      paid: [InvoiceStatus.Paid, InvoiceStatus.PaymentStarted, InvoiceStatus.Canceled],\r\n      forecast: [InvoiceStatus.Forecast, InvoiceStatus.Preview]\r\n    };\r\n\r\n    if (statuses[this.statusFilter.value]?.indexOf(value.status) === -1) {\r\n      return false;\r\n    }\r\n\r\n    return true;\r\n  };\r\n\r\n  /** Gets the grouped items, creating them if necessary. */\r\n  public getGroupedItems() {\r\n    return this.groupedItems;\r\n  }\r\n\r\n  /** Updates the grouped items based on the ODataQueryController.  */\r\n  public updateGroupedItems(items: InvoiceListItem[]) {\r\n    this.groupedItems = [];\r\n    items.forEach((l) => {\r\n      const id = l.ownerId + l.entityType + l.status + l.data.dueDate + l.data.channel;\r\n      let group = this.groupedItems.find((x) => x.id === id);\r\n      if (!group) {\r\n        group = {\r\n          id: id,\r\n          ownerInfo: l.ownerInfo,\r\n          invoiceType: l.entityType as InvoiceType,\r\n          status: l.status,\r\n          dueDate: l.data.dueDate,\r\n          payment: 0,\r\n          channel: l.data.channel,\r\n          invoices: [],\r\n        };\r\n        this.groupedItems.push(group);\r\n      }\r\n      group.payment += l.payment;\r\n      group.invoices.push(l);\r\n    });\r\n  }\r\n\r\n  /** Data reader for one item. */\r\n  public getGroupDataReader = (\r\n    group:\r\n      {\r\n        /** invoices */\r\n        invoices: InvoiceListItem[],\r\n      },\r\n    status: InvoiceStatus) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (arr: Invoice[], message: string): Promise<void> => {\r\n        const showConfirmation = (): Promise<boolean> => {\r\n          const warning = this.getEprWarning(group.invoices, status);\r\n          if (warning) {\r\n            return this.uiHelpers.showConfirm(\"Huomioi palkkatietoilmoitukset!\", warning);\r\n          }\r\n          return Promise.resolve(true);\r\n        };\r\n        return showConfirmation().then((result) => {\r\n          if (result) {\r\n            (group as any)[\"isReading\" + (status || \"\")] = true;\r\n            const promises = group.invoices.map((x) => () => this.getInvoice(x, message, status));\r\n            return Promises.sequence(promises).then( (invoices) => {\r\n              arr.push(...invoices.filter(i => !!i));\r\n              (group as any)[\"isReading\" + (status || \"\")] = false;\r\n              if (status) {\r\n                (group as any).status = status;\r\n              }\r\n              return;\r\n            });\r\n          } else {\r\n            return;\r\n          }\r\n        });\r\n      },\r\n      getSepaData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<string> => this.getSepaData(arr),\r\n      getFinvoiceData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<Blob[]> => this.getFinvoiceData(arr),\r\n      getPdfData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<Blob[]> => this.getPdfData(arr),\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n    };\r\n  };\r\n\r\n  /** Data reader for one item. */\r\n  public getGroupItemDataReader = (item: InvoiceListItem, status: InvoiceStatus) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (arr: Invoice[], message: string): Promise<void> => {\r\n        const showConfirmation = (): Promise<boolean> => {\r\n          const warning = this.getEprWarning([item], status);\r\n          if (warning) {\r\n            return this.uiHelpers.showConfirm(\"Huomioi palkkatietoilmoitukset!\", warning);\r\n          }\r\n          return Promise.resolve(true);\r\n        };\r\n        return showConfirmation().then((result) => {\r\n          if (result) {\r\n            (item as any)[\"isReading\" + (status || \"\")] = true;\r\n            return this.getInvoice(item, message, status).then((data) => {\r\n              if (data) {\r\n                arr.push(data);\r\n              }\r\n              (item as any)[\"isReading\" + (status || \"\")] = false;\r\n              return;\r\n            });\r\n          } else {\r\n            return;\r\n          }\r\n        });\r\n      },\r\n      getSepaData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<string> => this.getSepaData(arr),\r\n      getFinvoiceData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<Blob[]> => this.getFinvoiceData(arr),\r\n      getPdfData: (\r\n        /** Array for invoices */\r\n        arr: Invoice[],\r\n      ): Promise<Blob[]> => this.getPdfData(arr),\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n    };\r\n  };\r\n\r\n  /**\r\n   * Returns PDF url for a single invoice.\r\n   * @param item Invoice list item.\r\n   */\r\n  public getPdfUrl(item: InvoiceListItem): string {\r\n    if (!(item as any).pdfUrl) {\r\n        (item as any).pdfUrl = (this.api as Invoices).getContentUrl(item.id, false);\r\n    }\r\n    return (item as any).pdfUrl;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the QR code for the specified invoice item.\r\n   * If the QR code is not already cached, it generates the QR code and caches it for future use.\r\n   * @param item - The invoice item for which to retrieve the QR code.\r\n   * @returns The QR code string.\r\n   */\r\n  public getQrCode(item: InvoiceListItem): string {\r\n    if(!this.qrCodesCache[item.id]) {\r\n      this.qrCodesCache[item.id] = \"loading\";\r\n      this.generateQrCodeSvgForInvoice(item).then((qrCode) => {\r\n        if(!qrCode) {\r\n          this.qrCodesCache[item.id] = \"error\";\r\n          this.$timeout();\r\n          return this.qrCodesCache[item.id];\r\n        } else {\r\n          this.qrCodesCache[item.id] = qrCode;\r\n          this.$timeout();\r\n          return this.$sce.trustAsHtml(this.qrCodesCache[item.id]);\r\n        }\r\n      });\r\n    }\r\n    if(this.qrCodesCache[item.id] === \"error\") {\r\n      return this.qrCodesCache[item.id];\r\n    }\r\n    return this.$sce.trustAsHtml(this.qrCodesCache[item.id]);\r\n  }\r\n\r\n  /**\r\n   * Calculates barcode value for the invoice item.\r\n   * @param item Invoice list item.\r\n   */\r\n  public getBarcodeValue(item: InvoiceListItem): string {\r\n    return Barcodes.getValue(\r\n      item.otherPartyInfo.ibanNumber || \"\",\r\n      (item as any).reference || \"\",\r\n      Dates.asDate(item.data.dueDate),\r\n      Numeric.round(item.payment * 100, 0));\r\n  }\r\n\r\n  /**\r\n   * Retrieves the barcode for the invoice recipient's IBAN.\r\n   * If the IBAN does not start with \"fi\" or is not provided, an empty string is returned.\r\n   * The barcode is generated using the Barcodes.createBarcode function.\r\n   * @returns The barcode as a string, wrapped in an HTML trust object.\r\n   */\r\n  public getBarcode(item: InvoiceListItem): string {\r\n    if (!item.otherPartyInfo.ibanNumber || !item.otherPartyInfo.ibanNumber.toLowerCase().trim().startsWith(\"fi\")) {\r\n      return \"\";\r\n    }\r\n    const getDocumentAndSvgNode = () => {\r\n      return {document, svgNode: document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")};\r\n    };\r\n\r\n    const result = Barcodes.createBarcode(\r\n      getDocumentAndSvgNode,\r\n      item.otherPartyInfo.ibanNumber || \"\",\r\n      (item as any).reference || \"\",\r\n      Dates.asDate(item.data.dueDate),\r\n      Numeric.round(item.payment * 100, 0),\r\n      {\r\n        width: 1.8,\r\n        height: 32,\r\n        displayValue: true,\r\n        fontSize: 15\r\n      }\r\n    );\r\n    if(!result) {\r\n      return \"\";\r\n    }\r\n    return this.$sce.trustAsHtml(new XMLSerializer().serializeToString(result as any));\r\n  }\r\n\r\n  /** Hides bar code for forecast and preview invoice statuses*/\r\n  public hideBarCode(item: InvoiceListItem): boolean {\r\n    if(item.status === InvoiceStatus.Forecast || item.status === InvoiceStatus.Preview) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Copies the barcode to clipboard.\r\n   * @param item Invoice list item.\r\n   */\r\n  public copyBarcode(item: InvoiceListItem) {\r\n    (navigator as any).clipboard.writeText(this.getBarcodeValue(item));\r\n  }\r\n\r\n  /** Gets and avatar image for a payment channel */\r\n  public getChannelAvatar(channel: PaymentChannel) {\r\n    return InvoicesLogic.getChannelAvatar(channel);\r\n  }\r\n\r\n  /** Update status of invoices in group using the group data reader. */\r\n  public updateInvoiceGroupStatus(\r\n    group:\r\n      {\r\n        /** invoices */\r\n        invoices: InvoiceListItem[],\r\n      },\r\n    status: InvoiceStatus) {\r\n    const loading = this.uiHelpers.showLoading(\"Odota...\");\r\n    const reader = this.getGroupDataReader(group, status);\r\n    reader.read([], null).then(() => {\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Update status of single invoice using the group data reader. */\r\n  public updateInvoiceGroupItemStatus(item: InvoiceListItem, status: InvoiceStatus) {\r\n    const loading = this.uiHelpers.showLoading(\"Odota...\");\r\n    const reader = this.getGroupItemDataReader(item, status);\r\n    reader.read([], null).then(() => {\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets all channels as avatars for drop-down.\r\n   */\r\n  public getAllChannels(): Avatar[] {\r\n    if (this.session.getSession() && this._allChannels === null) {\r\n      const settings = this.session.getSession().settings;\r\n      let available = (settings.paymentChannels || []);\r\n      if (settings.defaultPaymentChannel) {\r\n        available = available.filter((x) => x !== settings.defaultPaymentChannel);\r\n        available.unshift(settings.defaultPaymentChannel);\r\n      }\r\n      if (available.indexOf(PaymentChannel.ZeroPayment) < 0) {\r\n        available.push(PaymentChannel.ZeroPayment);\r\n      }\r\n      this._allChannels = available\r\n        .map((x) => InvoicesLogic.getChannelAvatar(x));\r\n    }\r\n    return this._allChannels;\r\n  }\r\n\r\n  /**\r\n   * Summs payment fields of InvoiceListImte array\r\n   * @returns summed values\r\n   */\r\n  public sumInvoicePayments(invoices: Array<InvoiceListItem>) {\r\n    let sum = 0;\r\n    invoices.forEach(invoice => {\r\n      sum += invoice.payment;\r\n    });\r\n    return sum;\r\n  }\r\n\r\n  private getInvoice(item: InvoiceListItem, message: any, status: InvoiceStatus = null): Promise<Invoice> {\r\n\r\n    const updateInvoiceStatus = (invoice: Invoice, status: InvoiceStatus): Promise<Invoice> => {\r\n      if (invoice.header.status === status) {\r\n        return Promise.resolve(invoice);\r\n      }\r\n      return (this.api as Invoices).requestStatusUpdate(item.id, status);\r\n    };\r\n\r\n    return this.api.getSingle(item.id)\r\n      .then((readInvoice: Invoice) => {\r\n        if (status) {\r\n          return updateInvoiceStatus(readInvoice, status).then((updatedInvoice) => {\r\n            item.status = updatedInvoice.header.status;\r\n            return updatedInvoice;\r\n          });\r\n        } else {\r\n          return readInvoice;\r\n        }\r\n      });\r\n  }\r\n\r\n  private async getPdfData(invoices: Invoice[]): Promise<Blob[]> {\r\n    const blobs: Blob[] = [];\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    for (const [index, invoice] of invoices.entries()) {\r\n      const blob = await this.download(\"/v03/api/invoices/content\", invoice, \"blob\");\r\n      loader.setText(`${index}/${invoices.length}`);\r\n      blobs.push(blob);\r\n    }\r\n    loader.dismiss();\r\n    return blobs;\r\n  }\r\n\r\n  private async getFinvoiceData(invoices: Invoice[]): Promise<Blob[]> {\r\n    const blobs: Blob[] = [];\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    for (const [index, invoice] of invoices.entries()) {\r\n      const blob = await this.download(\"/v03/api/invoices/finvoice\", invoice, \"blob\");\r\n      loader.setText(`${index}/${invoices.length}`);\r\n      blobs.push(blob);\r\n    }\r\n    loader.dismiss();\r\n    return blobs;\r\n  }\r\n\r\n  private getSepaData(invoices: Invoice[], payerIbanNumber: string = null): Promise<string> {\r\n    const method = `/v03/api/invoices/sepa${payerIbanNumber ? \"?payerIbanNumber=\" + encodeURIComponent(payerIbanNumber) : \"\"}`;\r\n    return this.download(method, invoices, \"text\");\r\n  }\r\n  private download(method: string, data: any, responseType: string): Promise<any> {\r\n\r\n    const request: any = {}; // angular.IRequestConfig\r\n\r\n    const token: string = this.sepaAjax.getCurrentToken();\r\n    if (token) {\r\n      request.headers = { Authorization: \"Bearer \" + token };\r\n    }\r\n\r\n    request.url = this.sepaAjax.getServerAddress() + method;\r\n    request.method = \"POST\";\r\n    request.data = data;\r\n    request.responseType = responseType;\r\n    request.withCredentials = (token) ? false : this.sepaAjax.useCredentials;\r\n\r\n    return (this.$http(request).then(\r\n      (response) => response.data,\r\n      (error: any) => {\r\n        return null;\r\n      }) as any\r\n    );\r\n  }\r\n\r\n\r\n  private getEprWarning(items: InvoiceListItem[], status: InvoiceStatus): string {\r\n    if (status === InvoiceStatus.Canceled) {\r\n      for (const item of items) {\r\n        if (item.status === InvoiceStatus.Paid &&\r\n          item.entityType == InvoiceType.Net &&\r\n          this.isDelayed(item.logicalDate)) {\r\n          return \"Palkanmaksusta tehdyt tulorekisteri-ilmoitukset perutaan automaattisesti.\\n\\nJos maksat palkan uudestaan samalle palkkapäivälle, ota huomioon, että uudesta palkkatietoilmoituksesta saattaa seurata myöhästymismaksu. Haluatko varmasti perua maksut?\";\r\n        }\r\n      }\r\n    } else if (status === InvoiceStatus.Paid) {\r\n      for (const item of items) {\r\n        if (item.status !== InvoiceStatus.Paid &&\r\n          item.entityType == InvoiceType.Net &&\r\n          this.isDelayed(item.logicalDate)) {\r\n          return \"Annetulle palkkapäivälle tehtävä palkkatietoilmoitus myöhästyy, koska ilmoitus pitää tehdä 5 päivän kuluessa palkkapäivästä. Ota huomioon, että tästä saattaa seurata myöhästymismaksu. Haluatko varmasti merkitä palkan maksetuiksi?\";\r\n        }\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Checks if the Epr report is delayed. */\r\n  private isDelayed(salaryDate?: string): boolean {\r\n    if (this.session.isInRole(SystemRole.Test)) {\r\n      const officialDate = Dates.add((salaryDate ?? \"today\"),5, \"day\");\r\n      const expiresAt = Dates.addWorkdays(officialDate, 0);\r\n      const today = Dates.asDate(\"today\");\r\n      return today>expiresAt;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  private async generateQrCodeSvgForInvoice(item: InvoiceListItem): Promise<string> {\r\n    const svg = await QrCodes.getValue(\r\n     BicHelper.getBicForIban(item.otherPartyInfo.ibanNumber.replace(/\\s+/g, \"\")),\r\n     item.otherPartyInfo.avatar.displayName,\r\n     item.otherPartyInfo?.ibanNumber,\r\n     item.reference,\r\n     null,\r\n     item.payment,\r\n     item.endAt\r\n   );\r\n   return svg;\r\n }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Language,\r\n  Translations,\r\n  Invoice,\r\n  InvoiceType,\r\n  InvoiceStatus\r\n} from \"@salaxy/core\";\r\nimport { SessionService } from \"../../services\";\r\nimport {\r\n  InvoiceMapper,\r\n  ReportData,\r\n  ReportOptions,\r\n  Templates,\r\n  MappedInvoice\r\n} from \"@salaxy/reports\";\r\n\r\n\r\n/**\r\n * Renders a invoice report for the given invoice.\r\n * Uses Handlebars templates (@salaxy/reports).\r\n */\r\nexport class InvoiceReportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Templates\",\r\n    \"$sce\",\r\n    \"$timeout\",\r\n    \"SessionService\",\r\n  ];\r\n\r\n  /** Invoice for the report */\r\n  public invoice: Invoice;\r\n  /** If true applies table-html classes and uses only invoice table */\r\n  public applySiteStyles: boolean;\r\n\r\n  /** Boolean indicating if the refresh is in progress. */\r\n  public refreshInprogress: boolean;\r\n\r\n  /**Selected report language */\r\n  public lang: Language;\r\n\r\n  private renderedInvoice: Invoice;\r\n\r\n  private renderedLang: string;\r\n\r\n  private renderedApplySiteStyles: boolean;\r\n\r\n  private htmlData: any;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private reportData: ReportData<MappedInvoice> = {\r\n    headerFooter: {},\r\n    layout: {},\r\n    report: {},\r\n  };\r\n\r\n  /**\r\n   * Creates a new InvoiceReportController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private templates: Templates,\r\n    private $sce: angular.ISCEService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private sessionService: SessionService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    // no initializations\r\n  }\r\n\r\n  /** Bindable and trusted html. */\r\n  public get html(): any {\r\n    if (!this.invoice) {\r\n      this.renderedInvoice = null;\r\n      this.renderedLang = null;\r\n      this.renderedApplySiteStyles = null;\r\n    } else {\r\n      const invoice = angular.copy(this.invoice);\r\n\r\n      if (!this.renderedInvoice ||\r\n        !angular.equals(invoice, this.renderedInvoice) ||\r\n        this.renderedLang !== this.lang ||\r\n        this.applySiteStyles !== this.renderedApplySiteStyles) {\r\n        this.renderedApplySiteStyles = this.applySiteStyles;\r\n        this.renderedInvoice = angular.copy(invoice);\r\n        this.renderedLang = this.lang;\r\n        this.getDefaultLanguage(this.lang).then((lang) => {\r\n          this.lang = lang;\r\n          this.renderedLang = this.lang;\r\n          this.refresh();\r\n        });\r\n      }\r\n    }\r\n    return this.htmlData;\r\n  }\r\n\r\n  /** Checks if invoice is preview */\r\n  public isPreviewInvoice(): boolean {\r\n    return (\r\n      [InvoiceType.Pension, InvoiceType.Unemployment].includes(\r\n        this.invoice.header.type\r\n      ) &&\r\n      [InvoiceStatus.Preview, InvoiceStatus.Forecast].includes(\r\n        this.invoice.header.status\r\n      )\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Refresh invoice report data.\r\n   */\r\n  private async refresh() {\r\n    if (this.refreshInprogress) {\r\n      return;\r\n    }\r\n    this.refreshInprogress = true;\r\n    const renderingLang = this.lang ?? Language.Fi;\r\n    await Translations.loadLanguage(renderingLang);\r\n    this.reportData.report = await InvoiceMapper.getInvoice(this.invoice, this.getDocumentAndSvgNode);\r\n    if(this.reportData.report.barcode) {\r\n      this.reportData.report.barcode = new XMLSerializer().serializeToString(this.reportData.report.barcode as any);\r\n    }\r\n    this.reportOptions = InvoiceMapper.loadReportOptions(angular.copy(this.invoice));\r\n    this.reportData.headerFooter = InvoiceMapper.getHeaderFooter(this.invoice, this.reportOptions, renderingLang);\r\n    this.reportData.layout = InvoiceMapper.loadReportLayout(false);\r\n    const css = \"\";\r\n    this.reportData.layout.hasCustomCss = false;\r\n    this.reportData.layout.customCss = (css || \"\");\r\n    this.reportData.layout.margin = {\r\n      top: this.reportOptions.margin.top,\r\n      right: this.reportOptions.margin.right,\r\n      bottom: this.reportOptions.margin.bottom,\r\n      left: this.reportOptions.margin.left\r\n    };\r\n    const templates = new Templates();\r\n    this.reportData.headerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.headerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n    this.reportData.footerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.footerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n    this.htmlData = this.$sce.trustAsHtml(this.templates.getHtml(this.applySiteStyles ? \"invoiceTable\" : \"invoice\", this.reportData, renderingLang));\r\n    this.refreshInprogress = false;\r\n    this.$timeout();\r\n  }\r\n\r\n  private getDocumentAndSvgNode() {\r\n    return {document, svgNode: document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")};\r\n  }\r\n\r\n  private async getDefaultLanguage(lang: Language): Promise<Language> {\r\n    if (!lang) {\r\n      return this.sessionService.getReportLang();\r\n    }\r\n    return Promise.resolve(lang);\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Ajax,\r\n  Barcodes,\r\n  Dates,\r\n  InputEnumOption,\r\n  Invoice,\r\n  InvoiceListItem,\r\n  Invoices,\r\n  InvoiceStatus,\r\n  InvoiceType,\r\n  Numeric,\r\n  PaymentChannel,\r\n  SystemRole,\r\n  Translations,\r\n  QrCodes,\r\n  BicHelper,\r\n  Configs,\r\n} from \"@salaxy/core\";\r\nimport { InvoicesService, SessionService, UiHelpers } from \"../../services\";\r\nimport { InvoiceCrudController } from \"./InvoiceCrudController\";\r\n/**\r\n * Extends the InvoiceCrudController to provide\r\n * company invoices handling functionality.\r\n */\r\nexport class CompanyInvoicesController extends InvoiceCrudController {\r\n  /**\r\n   * For NG-dependency injection\r\n   */\r\n  public static $inject = [\r\n    \"Invoices\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"InvoicesService\",\r\n    \"AjaxNg1\",\r\n    \"SessionService\",\r\n    \"$http\",\r\n    \"$timeout\",\r\n    \"$sce\",\r\n  ];\r\n\r\n  /** Default channel for payments */\r\n  public channel: PaymentChannel;\r\n\r\n  /** Month for invoices query */\r\n  private queryMonth = Dates.format(Dates.getToday(), \"YYYY-MM-01\");\r\n\r\n  /** Queries for lists: Groups statuses to logical groups. */\r\n  public queryOptions: InputEnumOption[] = [\r\n    {\r\n      value: \"unpaid\",\r\n      text: Translations.get(\r\n        \"SALAXY.NG1.InvoicesComponent.statusWaitingConfirmation\"\r\n      ),\r\n      ui: () => ({\r\n        $filter: `data/channel eq '${this.channel}' and (entityType eq '${InvoiceType.Net}' or entityType eq '${InvoiceType.Foreclosure}' or entityType eq '${InvoiceType.Tax}' or  entityType eq '${InvoiceType.Union}' or  entityType eq '${InvoiceType.Payroll}') and ( status eq '${InvoiceStatus.Preview}' or status eq '${InvoiceStatus.Unread}' or status eq '${InvoiceStatus.Read}' or status eq '${InvoiceStatus.WaitingConfirmation}')`,\r\n        $top: undefined,\r\n        $orderby: \"endAt asc\",\r\n      }),\r\n    },\r\n    {\r\n      value: \"paid\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusPaid\"),\r\n      ui: () => ({\r\n        $filter: `${\r\n          this.dateFilterQueryOption.ui().dateFilter\r\n        }data/channel eq '${\r\n          this.channel\r\n        }' and (entityType eq '${InvoiceType.Net}' or entityType eq '${\r\n          InvoiceType.Foreclosure\r\n        }' or entityType eq '${InvoiceType.Tax}' or  entityType eq '${\r\n          InvoiceType.Union\r\n        }' or  entityType eq '${InvoiceType.Payroll}') and ( status eq '${\r\n          InvoiceStatus.Paid\r\n        }' or status eq '${InvoiceStatus.PaymentStarted}' or status eq '${\r\n          InvoiceStatus.Canceled\r\n        }')`,\r\n        $top: undefined,\r\n        $orderby: \"endAt asc\",\r\n      }),\r\n    },\r\n    {\r\n      value: \"all\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesComponent.statusAll\"),\r\n      ui: () => ({\r\n        $filter: `${\r\n          this.dateFilterQueryOption.ui().dateFilter\r\n        }data/channel eq '${\r\n          this.channel\r\n        }' and (entityType eq '${InvoiceType.Net}' or entityType eq '${\r\n          InvoiceType.Foreclosure\r\n        }' or entityType eq '${InvoiceType.Tax}' or  entityType eq '${\r\n          InvoiceType.Union\r\n        }' or  entityType eq '${InvoiceType.Payroll}') `,\r\n        $top: undefined,\r\n        $orderby: \"endAt asc\",\r\n      }),\r\n    },\r\n  ];\r\n\r\n  public queryDateFilterOptions: InputEnumOption[] = [\r\n    {\r\n      value: \"default\",\r\n      text: `${Dates.getMonth(Dates.add(this.queryMonth, -1, \"month\"))}-${Dates.getMonth(Dates.add(this.queryMonth, 1, \"month\"))}/${Dates.getYear(this.queryMonth)}`,\r\n      ui: () => ({\r\n        dateFilter: `endAt ge ${Dates.add(\r\n          this.queryMonth,\r\n          -1,\r\n          \"month\"\r\n        )} and endAt le ${Dates.startEnd(\r\n          Dates.add(this.queryMonth, 1, \"month\"),\r\n          \"end-month\"\r\n        )} and `,\r\n      }),\r\n    },\r\n    {\r\n      value: \"fromStartOfYear\",\r\n      text: `${Translations.get(\"SALAXY.UI_Terms.year\")} ${Dates.getYear(this.queryMonth)}`,\r\n      ui: () => ({\r\n        dateFilter: `endAt ge ${Dates.startEnd(\r\n          this.queryMonth,\r\n          \"start-year\"\r\n        )} and endAt le ${Dates.startEnd(\r\n          this.queryMonth,\r\n          \"end-year\"\r\n        )} and `,\r\n      }),\r\n    },\r\n    {\r\n      value: \"all\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesCompany.queryFilterDateAll\"),\r\n      ui: () => ({\r\n        dateFilter: ``,\r\n      }),\r\n    },\r\n    {\r\n      value: \"other\",\r\n      text: Translations.get(\"SALAXY.NG1.InvoicesCompany.queryFilterDateOther\"),\r\n      ui: () => ({\r\n        dateFilter: ``,\r\n      }),\r\n    },\r\n  ];\r\n\r\n  /** The current query */\r\n  public queryOption: InputEnumOption = this.queryOptions[0];\r\n  public dateFilterQueryOption: InputEnumOption =\r\n    this.queryDateFilterOptions[0];\r\n\r\n  private qrCodesCache: { [key: string]: string } = {};\r\n\r\n  constructor(\r\n    invoicesApi: Invoices,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    invoiceService: InvoicesService,\r\n    private companyAjax: Ajax,\r\n    private session: SessionService,\r\n    private $http: angular.IHttpService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $sce: angular.ISCEService\r\n  ) {\r\n    // Dependency injection\r\n    super(\r\n      invoicesApi,\r\n      uiHelpers,\r\n      $location,\r\n      $routeParams,\r\n      invoiceService,\r\n      companyAjax\r\n    );\r\n  }\r\n\r\n  /** Intitializes the controller */\r\n  public $onInit() {\r\n    this.channel ||= PaymentChannel.PalkkausInvoices;\r\n    super.$onInit();\r\n  }\r\n\r\n  /** For list components, gets the OData query options. */\r\n  public getListOptions() {\r\n    return this.uiHelpers.cache(this, \"listOptions\", () => {\r\n      return this.queryOption.ui();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the date filter query option.\r\n   * @param option - The input enum option.\r\n   */\r\n  public setDateFilterQueryOption(option: InputEnumOption) {\r\n    const oldDateFilterQueryOption = this.dateFilterQueryOption;\r\n    this.dateFilterQueryOption = option;\r\n    if (this.dateFilterQueryOption.value !== \"other\") {\r\n      this.doQuery();\r\n    } else {\r\n      const logic = {\r\n        startDate: Dates.add(this.queryMonth, -1, \"month\"),\r\n        endDate: Dates.add(this.queryMonth, 1, \"month\"),\r\n      };\r\n      this.uiHelpers\r\n        .openEditDialog(\r\n          \"salaxy-components/modals/invoices/company-invoices-date-filter-dialog.html\",\r\n          null,\r\n          logic\r\n        )\r\n        .then((result) => {\r\n          if (result.action === \"ok\") {\r\n            this.dateFilterQueryOption.ui = () => ({\r\n              dateFilter: `endAt ge ${result.logic.startDate} and endAt le ${result.logic.endDate} and `,\r\n            });\r\n            this.dateFilterQueryOption.text = `Muu ${result.logic.startDate} - ${result.logic.endDate}`;\r\n            this.doQuery();\r\n          } else {\r\n            this.dateFilterQueryOption = oldDateFilterQueryOption;\r\n          }\r\n        });\r\n    }\r\n  }\r\n\r\n  /** Refreshes query */\r\n  public doQuery() {\r\n    this.odataController.setQueryOptions(this.queryOption.ui());\r\n    this.odataController.refresh();\r\n  }\r\n\r\n  /** Dropdown options for marking invoice as paid */\r\n  public getMarkAsPaidOptions(items: InvoiceListItem[]): InputEnumOption[] {\r\n    return this.uiHelpers.cache(\r\n      this,\r\n      \"markAsPaidOptions\",\r\n      () => {\r\n        const result: InputEnumOption[] = [];\r\n        const filterInvoices = (type: InvoiceType) =>\r\n          items.filter(\r\n            (item) =>\r\n              item.entityType === type &&\r\n              item.status !== InvoiceStatus.Paid &&\r\n              item.status !== InvoiceStatus.Canceled\r\n          );\r\n\r\n        const netInvoices = filterInvoices(InvoiceType.Net);\r\n        const taxInvoices = filterInvoices(InvoiceType.Tax);\r\n        const unionInvoices = filterInvoices(InvoiceType.Union);\r\n        const foreclosureInvoices = filterInvoices(InvoiceType.Foreclosure);\r\n        result.push({\r\n          value: \"all\",\r\n          text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.all\"),\r\n        });\r\n        if (netInvoices.length > 0) {\r\n          result.push({\r\n            value: InvoiceType.Net,\r\n            text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.netInvoices\"),\r\n          });\r\n        }\r\n\r\n        if (taxInvoices.length > 0) {\r\n          result.push({\r\n            value: InvoiceType.Tax,\r\n            text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.taxInvoices\"),\r\n          });\r\n        }\r\n\r\n        if (unionInvoices.length > 0) {\r\n          result.push({\r\n            value: InvoiceType.Union,\r\n            text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.unionInvoices\"),\r\n          });\r\n        }\r\n\r\n        if (foreclosureInvoices.length > 0) {\r\n          result.push({\r\n            value: InvoiceType.Foreclosure,\r\n            text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.foreclosureInvoices\"),\r\n          });\r\n        }\r\n        result.push({\r\n          value: \"removeAll\",\r\n          text: Translations.get(\"SALAXY.NG1.InvoicesCompany.markAsPaidOptions.removeAll\"),\r\n        });\r\n        return result;\r\n      },\r\n      () => items.map((item) => item.id)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Selects invoices of a specific type and marks them as selected.\r\n   * @param action - The type of invoices to select.\r\n   */\r\n  public selectInvoicesByType(action: InvoiceType | \"all\" | \"removeAll\") {\r\n    if(action === \"removeAll\") {\r\n      this.odataController.unselectAll();\r\n      return;\r\n    }\r\n\r\n    if(action === \"all\") {\r\n      this.odataController.selectAll();\r\n      return;\r\n    }\r\n\r\n    const invoices = this.odataController.items.filter(\r\n      (x) =>\r\n        x.entityType === action &&\r\n        x.status !== InvoiceStatus.Paid &&\r\n        x.status !== InvoiceStatus.Canceled\r\n    );\r\n    for (const invoice of invoices) {\r\n      this.odataController.setSelected(invoice, true);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Determines whether to show the \"Mark as Paid\" button for a given invoice.\r\n   * @param invoice - The invoice to check.\r\n   * @returns A boolean indicating whether to show the button.\r\n   */\r\n  public showMarkAsPaidButton(invoice: InvoiceListItem): boolean {\r\n    return (\r\n      invoice.status === InvoiceStatus.Preview ||\r\n      invoice.status === InvoiceStatus.Unread\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Determines whether to show the \"Mark as Canceled\" button for a given invoice.\r\n   * @param invoice - The invoice to check.\r\n   * @returns A boolean indicating whether to show the button.\r\n   */\r\n  public showMarkAsCanceledButton(invoice: InvoiceListItem): boolean {\r\n    return (\r\n      invoice.status === InvoiceStatus.Paid ||\r\n      invoice.status === InvoiceStatus.Unread ||\r\n      invoice.status === InvoiceStatus.Preview\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Determines whether to show the IR cancel information text for a given invoice.\r\n   * @param invoice - The invoice item to check.\r\n   * @returns `true` if the invoice entity type is `Net` and the status is `Paid`, otherwise `false`.\r\n   */\r\n  public showIrCancelInfoText(invoice: InvoiceListItem): boolean {\r\n    return invoice.entityType === InvoiceType.Net && invoice.status === InvoiceStatus.Paid;\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for a single invoice.\r\n   * @param item Invoice item.\r\n   */\r\n  public showInvoiceDialog(item: InvoiceListItem) {\r\n    this.uiHelpers\r\n      .openEditDialog(\r\n        \"salaxy-components/modals/invoices/company-invoice-dialog.html\",\r\n        item,\r\n        { parent: this },\r\n        \"lg\"\r\n      )\r\n      .then((response: any) => {\r\n        if (response.action === \"ok\") {\r\n          this.getInvoice(item, null, null).then((result) => {\r\n            (item.data as any).statusAt = (result.header as any).statusAt;\r\n            item.status = result.header.status;\r\n            this.refreshPeriodicInvoices();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Marks selected invoices as paid.\r\n   * This method filters the selected invoices to exclude those that are already paid or canceled.\r\n   * It then shows a loading indicator and processes each invoice by marking it as paid.\r\n   * After processing all invoices, it refreshes the periodic invoices and dismisses the loading indicator.\r\n   * @returns A promise that resolves when the operation is complete.\r\n   */\r\n  public async markInvoicesAsPaid() {\r\n    const invoices = this.odataController.selectedItems.filter(\r\n      (item) =>\r\n        item.status != InvoiceStatus.Paid &&\r\n        item.status != InvoiceStatus.Canceled\r\n    );\r\n    const loader = this.uiHelpers.showLoading(\r\n      \"SALAXY.NG1.InvoicesCompany.markingAsPaid\"\r\n    );\r\n    for (const [index, invoice] of invoices.entries()) {\r\n      const reader = this.getInvoiceReader(invoice, InvoiceStatus.Paid, false);\r\n      loader.setText(`${index + 1}/${invoices.length}`);\r\n      await reader.read([], null);\r\n    }\r\n    await this.refreshPeriodicInvoices();\r\n    loader.dismiss();\r\n  }\r\n\r\n  /** Update status of single invoice. */\r\n  public updateInvoiceStatus(item: InvoiceListItem, status: InvoiceStatus) {\r\n    const loading = this.uiHelpers.showLoading(\r\n      status === InvoiceStatus.Paid\r\n        ? \"SALAXY.NG1.InvoicesCompany.markingAsPaid\"\r\n        : \"SALAXY.NG1.InvoicesCompany.markingAsCanceled\"\r\n    );\r\n    const reader = this.getInvoiceReader(item, status);\r\n    reader.read([], null).then(() => {\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Data reader for one item. */\r\n  public getInvoiceReader = (\r\n    item: InvoiceListItem,\r\n    status: InvoiceStatus,\r\n    updatePeriodicInvoices = true\r\n  ) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (arr: Invoice[], message: string): Promise<void> => {\r\n        const showConfirmation = (): Promise<boolean> => {\r\n          const warning = this.getEprWarning([item], status);\r\n          if (warning) {\r\n            return this.uiHelpers.showConfirm(\r\n              Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.eprWarningHeading\"),\r\n              warning\r\n            );\r\n          } else {\r\n            if(status === InvoiceStatus.Canceled) {\r\n              const getConfirmText = (item: InvoiceListItem): string => {\r\n                if(item.entityType === \"net\" && item.status === InvoiceStatus.Unread) {\r\n                  return Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.cancellationTexts.invoiceCancelingNetInvoiceText\");\r\n                }\r\n                if(item.entityType === \"tax\" && item.status !== InvoiceStatus.Paid) {\r\n                  return Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.cancellationTexts.invoiceCancelingTax\");\r\n                }\r\n                return Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.cancellationTexts.invoiceCancelingInvoiceText\");\r\n              };\r\n\r\n              return this.uiHelpers.showConfirm(\r\n                Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.cancellationTexts.invoiceCancelingHeading\"),\r\n                getConfirmText(item),\r\n                Translations.get(\"SALAXY.NG1.InvoicesCompany.companyInvoiceDialog.buttons.save\"),\r\n                Translations.get(\"SALAXY.NG1.InvoicesCompany.companyInvoiceDialog.buttons.cancel\")\r\n              );\r\n            }\r\n          }\r\n          return Promise.resolve(true);\r\n        };\r\n        return showConfirmation().then((result) => {\r\n          if (result) {\r\n            (item as any)[\"isReading\" + (status || \"\")] = true;\r\n            return this.getInvoice(item, message, status).then((data) => {\r\n              if (data) {\r\n                // Update list item, does not need to refresh list\r\n                (item.data as any).statusAt = (data.header as any).statusAt;\r\n                item.status = data.header.status;\r\n                if (updatePeriodicInvoices) {\r\n                  this.refreshPeriodicInvoices().then(() => {\r\n                    arr.push(data);\r\n                  });\r\n                } else {\r\n                  arr.push(data);\r\n                }\r\n              }\r\n              (item as any)[\"isReading\" + (status || \"\")] = false;\r\n              return;\r\n            });\r\n          } else {\r\n            return;\r\n          }\r\n        });\r\n      },\r\n      getSepaData: (\r\n        /** Array for invoices */\r\n        _arr: Invoice[]\r\n      ): Promise<string> => undefined,\r\n      getFinvoiceData: (\r\n        /** Array for invoices */\r\n        _arr: Invoice[]\r\n      ): Promise<Blob[]> => undefined,\r\n      getPdfData: (\r\n        /** Array for invoices */\r\n        _arr: Invoice[]\r\n      ): Promise<Blob[]> => undefined,\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n    };\r\n  };\r\n\r\n  /**\r\n   * Returns PDF url for a single invoice.\r\n   * @param item Invoice list item.\r\n   */\r\n  public getPdfUrl(item: InvoiceListItem): string {\r\n    if (!(item as any).pdfUrl) {\r\n      (item as any).pdfUrl = this.getContentUrl(item.id, false);\r\n    }\r\n    return (item as any).pdfUrl;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the QR code for the specified invoice item.\r\n   * If the QR code is not already cached, it generates the QR code and caches it for future use.\r\n   * @param item - The invoice item for which to retrieve the QR code.\r\n   * @returns The QR code string.\r\n   */\r\n  public getQrCode(item: InvoiceListItem): string {\r\n    if (!this.qrCodesCache[item.id]) {\r\n      this.qrCodesCache[item.id] = \"loading\";\r\n      this.generateQrCodeSvgForInvoice(item).then((qrCode) => {\r\n        if (!qrCode) {\r\n          this.qrCodesCache[item.id] = \"error\";\r\n          this.$timeout();\r\n          return this.qrCodesCache[item.id];\r\n        } else {\r\n          this.qrCodesCache[item.id] = qrCode;\r\n          this.$timeout();\r\n          return this.$sce.trustAsHtml(this.qrCodesCache[item.id]);\r\n        }\r\n      });\r\n    }\r\n    if (this.qrCodesCache[item.id] === \"error\") {\r\n      return this.qrCodesCache[item.id];\r\n    }\r\n    return this.$sce.trustAsHtml(this.qrCodesCache[item.id]);\r\n  }\r\n\r\n  /**\r\n   * Calculates barcode value for the invoice item.\r\n   * @param item Invoice list item.\r\n   */\r\n  public getBarcodeValue(item: InvoiceListItem): string {\r\n    return Barcodes.getValue(\r\n      item.otherPartyInfo.ibanNumber || \"\",\r\n      item.entityType === \"net\" ? \"\" : item.reference,\r\n      Dates.asDate(item.data.dueDate),\r\n      Numeric.round(this.getInvoicePayment(item) * 100, 0)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Calculates the invoice payment amount for a given invoice item.\r\n   * If the invoice item is of type \"tax\" or \"union\" and the total paid amount\r\n   * is different from the payment amount, it returns the rounded difference\r\n   * between the payment amount and the total paid amount.\r\n   * Otherwise, it returns the payment amount.\r\n   * @param {InvoiceListItem} item - The invoice item to calculate the payment for.\r\n   * @returns {number} - The calculated payment amount.\r\n   */\r\n  public getInvoicePayment(item: InvoiceListItem): number {\r\n    if (\r\n      (item.entityType == \"tax\" || item.entityType == \"union\") &&\r\n      (item.data as any)?.totalPaid &&\r\n      (item.data as any).totalPaid != item.payment\r\n    ) {\r\n      return Numeric.round(item.payment - (item.data as any).totalPaid);\r\n    }\r\n    return item.payment;\r\n  }\r\n\r\n  /**\r\n   * Retrieves the barcode for the invoice recipient's IBAN.\r\n   * If the IBAN does not start with \"fi\" or is not provided, an empty string is returned.\r\n   * The barcode is generated using the Barcodes.createBarcode function.\r\n   * @returns The barcode as a string, wrapped in an HTML trust object.\r\n   */\r\n  public getBarcode(item: InvoiceListItem): string {\r\n    if (\r\n      !item.otherPartyInfo.ibanNumber ||\r\n      !item.otherPartyInfo.ibanNumber.toLowerCase().trim().startsWith(\"fi\")\r\n    ) {\r\n      return \"\";\r\n    }\r\n    const getDocumentAndSvgNode = () => {\r\n      return {\r\n        document,\r\n        svgNode: document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\"),\r\n      };\r\n    };\r\n\r\n    const result = Barcodes.createBarcode(\r\n      getDocumentAndSvgNode,\r\n      item.otherPartyInfo.ibanNumber || \"\",\r\n      item.entityType === \"net\" ? \"\" : item.reference || \"\",\r\n      Dates.asDate(item.data.dueDate),\r\n      Numeric.round(this.getInvoicePayment(item) * 100, 0),\r\n      {\r\n        width: 1.8,\r\n        height: 32,\r\n        displayValue: true,\r\n        fontSize: 15,\r\n      }\r\n    );\r\n    if (!result) {\r\n      return \"\";\r\n    }\r\n    return this.$sce.trustAsHtml(\r\n      new XMLSerializer().serializeToString(result as any)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Copies the barcode to clipboard.\r\n   * @param item Invoice list item.\r\n   */\r\n  public copyBarcode(item: InvoiceListItem) {\r\n    (navigator as any).clipboard.writeText(this.getBarcodeValue(item));\r\n  }\r\n\r\n  /**\r\n   * Displays the PDF for the given invoice items.\r\n   * @param items - The list of invoice items.\r\n   */\r\n  public showloadPfd(items: InvoiceListItem[]) {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    const url = `${\r\n      Configs.current.reportServer\r\n    }/pdf?id=&reportType=${encodeURIComponent(\r\n      \"invoiceList\"\r\n    )}&template=${encodeURIComponent(\r\n      \"invoiceList\"\r\n    )}&language=${encodeURIComponent(\r\n      Translations.getLanguage()\r\n    )}&disposition=inline&access_token=${this.companyAjax.getCurrentToken()}`;\r\n    this.handlePdfRequest(url, false, { object: items }, loading);\r\n  }\r\n\r\n  /**\r\n   * Generates a URL for the calculation details of an invoice item.\r\n   * @param item - The invoice item for which to generate the URL.\r\n   * @returns A string representing the URL for the calculation details.\r\n   */\r\n  public calculationHref(item: InvoiceListItem): string {\r\n    //TODO: Nice to have for periodic invoices implement list for viewing invoice rows\r\n    if(item.status == InvoiceStatus.Canceled &&\r\n      (item.entityType == InvoiceType.Net || item.entityType == InvoiceType.Foreclosure) &&\r\n      item.businessObjects.length == 1\r\n    ){\r\n      return `#/calc/details/${item.businessObjects[0]}`;\r\n    }\r\n    return \"\";\r\n  }\r\n\r\n  private getEprWarning(\r\n    items: InvoiceListItem[],\r\n    status: InvoiceStatus\r\n  ): string {\r\n    if (status === InvoiceStatus.Canceled) {\r\n      for (const item of items) {\r\n        if (\r\n          item.status === InvoiceStatus.Paid &&\r\n          item.entityType == InvoiceType.Net &&\r\n          this.isDelayed(item.logicalDate)\r\n        ) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.eprWarningTextCanceled\");\r\n        }\r\n      }\r\n    } else if (status === InvoiceStatus.Paid) {\r\n      for (const item of items) {\r\n        if (\r\n          item.status !== InvoiceStatus.Paid &&\r\n          item.entityType == InvoiceType.Net &&\r\n          this.isDelayed(item.logicalDate)\r\n        ) {\r\n          return Translations.get(\"SALAXY.NG1.InvoicesCompany.invoiceReader.eprWarningTextPaid\");\r\n        }\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n  /** Checks if the Epr report is delayed. */\r\n  private isDelayed(salaryDate?: string): boolean {\r\n    if (this.session.isInRole(SystemRole.Test)) {\r\n      const officialDate = Dates.add(salaryDate ?? \"today\", 5, \"day\");\r\n      const expiresAt = Dates.addWorkdays(officialDate, 0);\r\n      const today = Dates.asDate(\"today\");\r\n      return today > expiresAt;\r\n    }\r\n    return false;\r\n  }\r\n  private getInvoice(\r\n    item: InvoiceListItem,\r\n    message: any,\r\n    status: InvoiceStatus = null\r\n  ): Promise<Invoice> {\r\n    const updateInvoiceStatus = (\r\n      invoice: Invoice,\r\n      status: InvoiceStatus\r\n    ): Promise<Invoice> => {\r\n      if (invoice.header.status === status) {\r\n        return Promise.resolve(invoice);\r\n      }\r\n      return this.invoicesApi.requestStatusUpdate(item.id, status);\r\n    };\r\n\r\n    return this.api.getSingle(item.id).then((readInvoice: Invoice) => {\r\n      if (status) {\r\n        return updateInvoiceStatus(readInvoice, status).then(\r\n          (updatedInvoice) => {\r\n            item.status = updatedInvoice.header.status;\r\n            return updatedInvoice;\r\n          }\r\n        );\r\n      } else {\r\n        return readInvoice;\r\n      }\r\n    });\r\n  }\r\n\r\n  private async generateQrCodeSvgForInvoice(\r\n    item: InvoiceListItem\r\n  ): Promise<string> {\r\n    const svg = await QrCodes.getValue(\r\n      BicHelper.getBicForIban(\r\n        item.otherPartyInfo.ibanNumber.replace(/\\s+/g, \"\")\r\n      ),\r\n      item.otherPartyInfo.avatar.displayName,\r\n      item.otherPartyInfo?.ibanNumber,\r\n      item.entityType === \"net\" ? null : item.reference,\r\n      item.entityType === \"net\"\r\n        ? `${Translations.get(\r\n            `SALAXY.ENUM.InvoiceType.${item.entityType}.label`\r\n          )} ${Dates.getFormattedRange(\r\n            item.data.periodStart,\r\n            item.data.periodEnd\r\n          )}`\r\n        : null,\r\n      this.getInvoicePayment(item),\r\n      item.endAt\r\n    );\r\n    return svg;\r\n  }\r\n\r\n  private async handlePdfRequest(\r\n    url: string,\r\n    inline: boolean,\r\n    payload: any,\r\n    loading: any\r\n  ): Promise<void> {\r\n    try {\r\n      await this.fetchPdf(url, payload, inline);\r\n    } catch (error) {\r\n      //HACK: Implement failover functionality to cloud (azure)\r\n      if (\r\n        url.includes(Configs.current.reportServer) &&\r\n        Configs.current.getEnv() === \"prod\"\r\n      ) {\r\n        url = url.replace(\r\n          Configs.current.reportServer,\r\n          \"https://failover-reports.salaxy.com\"\r\n        );\r\n        try {\r\n          await this.fetchPdf(url, payload, inline);\r\n        } catch (error) {\r\n          console.error(error);\r\n        }\r\n      } else {\r\n        console.error(error);\r\n      }\r\n    }\r\n    if (loading) {\r\n      loading.dismiss();\r\n    }\r\n  }\r\n\r\n  private async fetchPdf(\r\n    url: string,\r\n    payload: any,\r\n    inline: boolean\r\n  ): Promise<void> {\r\n    let response: any;\r\n    if (payload) {\r\n      response = await this.$http.post(url, payload, { responseType: \"blob\" });\r\n    } else {\r\n      response = await this.$http.get(url, { responseType: \"blob\" });\r\n    }\r\n    if (response.data) {\r\n      if (inline) {\r\n        this.uiHelpers.openFile(response.data as any);\r\n      } else {\r\n        this.uiHelpers.downloadFile(\r\n          response.data as any,\r\n          decodeURIComponent(response.headers(\"content-disposition\")).match(\r\n            /filename\\s*=\\s*\"?(?<file>.*?)(?:\\s*;|\"|\\s*$)/\r\n          )?.groups?.file\r\n        );\r\n      }\r\n    }\r\n  }\r\n\r\n  private async refreshPeriodicInvoices(): Promise<any[]> {\r\n    const periodicInvoices = this.odataController.items.filter(\r\n      (x) =>\r\n        x.entityType === InvoiceType.Tax ||\r\n        x.entityType === InvoiceType.Union ||\r\n        x.entityType === InvoiceType.Payroll ||\r\n        x.entityType === InvoiceType.Foreclosure\r\n    );\r\n    if (periodicInvoices.length === 0) {\r\n      return Promise.resolve([]);\r\n    }\r\n    const $filter = periodicInvoices.map((x) => `id eq '${x.id}'`).join(\" or \");\r\n    const loading = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.InvoicesCompany.gettingsInvoices\"));\r\n    const delay = (ms: number) =>\r\n      new Promise((resolve) => setTimeout(resolve, ms));\r\n    await delay(3000);\r\n    return this.odataController\r\n      .getApi()\r\n      .getOData({ $filter })\r\n      .then((result) => {\r\n        const toBeRemoved = [];\r\n        for (const periodicInvoice of periodicInvoices) {\r\n          const item = result.items.find((x) => x.id === periodicInvoice.id);\r\n          if (item) {\r\n            angular.copy(item, periodicInvoice);\r\n          } else {\r\n            toBeRemoved.push(periodicInvoice);\r\n          }\r\n        }\r\n        toBeRemoved.forEach((x) => {\r\n          const index = this.odataController.items.indexOf(x);\r\n          if (index > -1) {\r\n            this.odataController.items.splice(index, 1);\r\n          }\r\n        });\r\n        loading.dismiss();\r\n        return periodicInvoices;\r\n      })\r\n      .catch((error) => {\r\n        loading.dismiss();\r\n        console.error(error);\r\n        return periodicInvoices;\r\n      });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { PaymentChannel, Dates, Calculations, CalculationListItem, Translations, ODataResult, OData, Ajax } from \"@salaxy/core\";\r\n\r\n\r\n/**\r\n * The `InvoiceAlertsController` class is responsible for managing invoice alerts within the application.\r\n */\r\nexport class InvoiceAlertsController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"AjaxNg1\"];\r\n\r\n  /** Payment channels for OData query. */\r\n  public paymentChannels: PaymentChannel[];\r\n\r\n  /** Indicates if used in pro. */\r\n  public isPro: boolean;\r\n\r\n  public groupedPaymentChannelResult: string[] = [];\r\n\r\n  /** Start date for filtering list of calculations with status \"PaymentStarted\". Displayed on front page */\r\n  private paymentStartedWarningStartDate = Dates.getToday() + \"Z\";\r\n\r\n  /** End date for filtering list of calculations with status \"PaymentStarted\". Displayed on front page */\r\n  private paymentStartedWarningEndDate =  Dates.add(Dates.getToday(), -6, \"month\") + \"Z\";\r\n\r\n  private result: ODataResult<CalculationListItem>;\r\n\r\n  constructor(\r\n    private calculationsApi: Calculations,\r\n    private ajax: Ajax\r\n  ) {}\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.getOData().then(result => {\r\n      this.groupResultsByPaymentChannel(result);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Groups the results by payment channel and stores the unique payment channels.\r\n   */\r\n  public groupResultsByPaymentChannel(results: CalculationListItem[]): void {\r\n    const paymentChannels = results.reduce((acc, item) => {\r\n      if (!acc.includes(item.data.paymentChannel)) {\r\n        acc.push(item.data.paymentChannel);\r\n      }\r\n      return acc;\r\n    }, [] as string[]);\r\n    this.groupedPaymentChannelResult = paymentChannels;\r\n  }\r\n\r\n  /**\r\n   * Retrieves a list of calculation items based on OData filters\r\n   * This method fetches data from the calculations API or a specific OData endpoint depending on the value of the `isPro` property. It applies filters to retrieve items with a status of 'paymentStarted' and within a specified salary date range.\r\n   */\r\n  public async getOData(): Promise<CalculationListItem[]> {\r\n    if(!this.isPro) {\r\n      this.result = await this.calculationsApi.getOData({\r\n        $filter: `status eq 'paymentStarted' and ${this.getPaymentChannelFilter()} and salaryDate lt ${this.paymentStartedWarningStartDate} and salaryDate gt ${this.paymentStartedWarningEndDate}`\r\n      });\r\n      return this.result.items ?? [];\r\n    }\r\n    this.result = await OData.getOData(\"/v01/api/pro/calculations/readonly\", {$filter: `status eq 'paymentStarted' and ${this.getPaymentChannelFilter()} and salaryDate lt ${this.paymentStartedWarningStartDate} and salaryDate gt ${this.paymentStartedWarningEndDate}`}, this.ajax);\r\n    return this.result.items ?? [];\r\n  }\r\n\r\n\r\n  /**\r\n   * Generates an HTML string containing payment channel information.\r\n   * The generated HTML includes:\r\n   * - A header with the payment channel label.\r\n   * - A description paragraph.\r\n   * - Instruction text specific to the payment channel.\r\n   * - Links related to the payment channel, including calculation and payroll links if applicable.\r\n   * - A help link to an external article.\r\n   */\r\n  public getpaymentChannelInfoHtml(paymentChannel: PaymentChannel): string {\r\n    const paymentChannelItems = this.result.items.filter(item => item.data.paymentChannel === paymentChannel);\r\n      const getInstructionText = () => {\r\n        return Translations.get(`SALAXY.NG1.InvoiceAlertsComponent.${paymentChannel}.instructionText.html`);\r\n      };\r\n\r\n      const getLinks = () => {\r\n        if (paymentChannel === PaymentChannel.PalkkausManual) {\r\n          const urls = this.getUrls();\r\n          let link = Translations.get(`SALAXY.NG1.InvoiceAlertsComponent.calculationLink.html`, { calculationUrl: urls.calculationUrl });\r\n          if (paymentChannelItems.some(item => item.data.payrollId)) {\r\n            link += Translations.get(`SALAXY.NG1.InvoiceAlertsComponent.payrollLink.html`, { payrollUrl: urls.payrollUrl });\r\n          }\r\n          return link;\r\n        } else {\r\n          let link = Translations.get(`SALAXY.NG1.InvoiceAlertsComponent.calculationLink.html`, { calculationUrl: \"#/calc/paid/\" });\r\n          if (paymentChannelItems.some(item => item.data.payrollId)) {\r\n            link += Translations.get(`SALAXY.NG1.InvoiceAlertsComponent.payrollLink.html`, { calculationUrl: \"#/payroll/\" });\r\n          }\r\n          return link;\r\n        }\r\n      };\r\n      return `\r\n      <div class=\"row\">\r\n          <div class=\"col-12\">\r\n            <p class=\"lead lead-with-text\">${Translations.get(\"SALAXY.NG1.InvoiceAlertsComponent.header\", {channel: Translations.get(`SALAXY.ENUM.PaymentChannel.${paymentChannel}.label`)})}</p>\r\n            <p>${Translations.get(\"SALAXY.NG1.InvoiceAlertsComponent.description\")} ${getInstructionText()} ${getLinks()}</p>\r\n          </div>\r\n          <div class=\"col-12\">\r\n            <a href=\"https://help.palkkaus.fi/hc/fi/articles/23187345878557-Sinulla-on-keskeneräisiä-palkkalaskelmia-ilmoitus\" target=\"_blank\">${Translations.get(\"SALAXY.NG1.InvoiceAlertsComponent.openHelp\")}</a>\r\n          </div>\r\n      </div>\r\n    `;\r\n  }\r\n\r\n  private getUrls() {\r\n    const href = window.location.href;\r\n    //Local ng1\r\n    if (href.includes(\"localhost\") && href.includes(\"/ng1/\")) {\r\n      return { calculationUrl: `#/calc/paid`, payrollUrl: `#/payroll` };\r\n    }\r\n    //Local pro\r\n    if (href.includes(\":9001\")) {\r\n      return { calculationUrl: `#/pro/calc-paid`, payrollUrl: `#/pro/payroll-paid` };\r\n    }\r\n    if (href.includes(\"pro.palkkaus.fi\")) {\r\n      return { calculationUrl: `#/pro/calc-paid`, payrollUrl: `#/pro/payroll-paid` };\r\n    }\r\n    if (href.includes(\"palkkaus.fi/company\")) {\r\n      return { calculationUrl: `#/calc/paid`, payrollUrl: `#/payroll` };\r\n    }\r\n    if (href.includes(\"yritys.palkkaus.fi\")) {\r\n      return { calculationUrl: `#/calc/paid`, payrollUrl: `#/payroll` };\r\n    }\r\n    return { calculationUrl: \"\", payrollUrl: \"\" };\r\n  }\r\n\r\n  private getPaymentChannelFilter(): string {\r\n    return `(${this.paymentChannels.map(channel => `data/paymentChannel eq '${channel}'`).join(\" or \")})`;\r\n  }\r\n}\r\n","import { EditDialogParameters } from \"../../services\";\r\n\r\n/**\r\n * Controller for Item edit dialogs.\r\n */\r\nexport class EditDialogController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"EditDialogParameters\"];\r\n\r\n    /**\r\n     * The item that is being edited.\r\n     * This a copy of the original item to allow cancel / reset and other change tracking.\r\n     */\r\n    public current: any;\r\n\r\n    /** Additional logic: Helper functions, metadata etc. that view can use to contruct the UI. */\r\n    public logic: any;\r\n\r\n    constructor(public editDialogParams: EditDialogParameters<any>) {\r\n\r\n    }\r\n    /**\r\n     * Implement IController\r\n     */\r\n    public $onInit = () => {\r\n      // initialization\r\n      if (!this.editDialogParams) {\r\n        throw new Error(\"No editDialogParams coming in.\");\r\n      }\r\n      this.current = this.editDialogParams.current;\r\n      this.logic = this.editDialogParams.logic;\r\n    };\r\n}\r\n","\r\n/**\r\n * Controller for alert, confirm and loading dialogs.\r\n */\r\nexport class ModalGenericDialogController {\r\n\r\n    /**\r\n     * For NG-dependency injection\r\n     * @ignore\r\n     */\r\n    public static $inject = [\"data\"];\r\n\r\n    constructor(\r\n        public data: any,\r\n    ) {\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiListItem,\r\n  Calculation,\r\n  Calculations,\r\n  Employments,\r\n  ODataQueryOptions,\r\n  ODataResult,\r\n  SharingUriType,\r\n  Taxcards,\r\n  Translations\r\n} from \"@salaxy/core\";\r\n\r\nimport { CalculationCrudController } from \"../calc/CalculationCrudController\";\r\n\r\nimport {\r\n  InvoicesService, OnboardingService, ReportsService, SessionService, UiHelpers,\r\n} from \"../../services\";\r\n\r\n/**\r\n * Controller for sharing the calculation between worker and employer.\r\n */\r\nexport class CalcSharingController extends CalculationCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"ReportsService\", \"UiHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"InvoicesService\", \"Employments\", \"OnboardingService\", \"Taxcards\"];\r\n\r\n  /** Employing relations for the current account */\r\n  public employingRelations: ApiListItem[] = [];\r\n\r\n  /** True, if the current link has been copied to the clipboard */\r\n  public uriCopied = false;\r\n\r\n  /** If true, template shows option to share direct link to the calculation. Currently used only in Rakennusliitto site. */\r\n  public showLinkSharing: boolean;\r\n\r\n  /** Web sharing targets */\r\n  public webSharingTargets = {\r\n    email: {\r\n      title: Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingTargets.email\"),\r\n      icon: \"fa-envelope-o\",\r\n      action: () => this.showEmailSharing(),\r\n    },\r\n    whatsApp: {\r\n      title: \"WhatsApp\",\r\n      icon: \"fa-whatsapp\",\r\n      getUrl: () => this.getWhatsAppUrl(),\r\n    },\r\n    telegram: {\r\n      title: \"Telegram\",\r\n      icon: \"fa-telegram\",\r\n      getUrl: () => this.getTelegramUrl(),\r\n    },\r\n  };\r\n\r\n  /** Web sharing targets */\r\n  public mobileSharingTargets = {\r\n    email: {\r\n      title: Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingTargets.email\"),\r\n      icon: \"fa-envelope-o\",\r\n      action: () => this.showEmailSharing(),\r\n\r\n    },\r\n    device: {\r\n      title: Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingTargets.device\"),\r\n      icon: \"fa-share\",\r\n      action: () => this.shareInMobile(),\r\n    },\r\n  };\r\n\r\n  /** Loading indicator. */\r\n  public isSharingType: string = null;\r\n\r\n  /**\r\n   * Creates a new CalcSharingController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private sharingCalculationsApi: Calculations,\r\n    reportsService: ReportsService,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    invoicesService: InvoicesService,\r\n    private employmentsApi: Employments,\r\n    private onboardingService: OnboardingService,\r\n    private taxcards: Taxcards,\r\n  ) {\r\n    super(sharingCalculationsApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    this.loadEmployingRelations();\r\n  }\r\n\r\n  /** Show sharing page for the current calculation. */\r\n  public showSharing(action: string = null): Promise<angular.ILocationService> {\r\n    const savePending = (): Promise<Calculation> => {\r\n      if ((!action || action === \"default\")) {\r\n        if (!this.current.isReadOnly) {\r\n          return this.save();\r\n        }\r\n      }\r\n      return Promise.resolve(this.current);\r\n    };\r\n    return savePending().then((calculation: Calculation) => {\r\n      return this.$location.url(`/calc/sharing/${calculation.id}${action ? \"/\" + action : \"\"}`);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shares the current calculation.\r\n   * @param type Type of the sharing action or link.\r\n   * @param employer List item for employer to share the calculation with. Mandatory in Direct share.\r\n   * @returns Sharing object of the calculation.\r\n   */\r\n  public share(type: SharingUriType = SharingUriType.Undefined, employer: ApiListItem = null): Promise<angular.ILocationService> {\r\n\r\n    if (type !== SharingUriType.Undefined) {\r\n      if (!this.sessionService.checkAccountVerification()) {\r\n        this.showMissingSignatureAlert();\r\n        return Promise.resolve(null);\r\n      }\r\n    }\r\n\r\n    const createSharingMessageForEmployer = (): Promise<{ to: string, cc: string, message: string }> => {\r\n      if (type !== SharingUriType.Employer) {\r\n        return Promise.resolve(null);\r\n      }\r\n      return this.createSharingMessage(employer);\r\n    };\r\n\r\n    this.isSharingType = `${type}${employer?.ownerId ? employer.ownerId : \"\"}`;\r\n    return createSharingMessageForEmployer().then( (item) => {\r\n      if (type === SharingUriType.Employer) {\r\n        if (!item) {\r\n          this.isSharingType = null;\r\n          return null;\r\n        }\r\n      }\r\n      return this.sharingCalculationsApi.share(this.currentId, type, employer?.ownerId, item?.to, item?.cc, item?.message).then(() => {\r\n        if (type === SharingUriType.Employer) {\r\n          this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.CalcSharingComponent.emailSent\")+ \".\");\r\n        }\r\n        return this.reload().then(() => {\r\n          this.isSharingType = null;\r\n          return this.showDetails(this.current);\r\n        });\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Loads employing relations of the existing employers for the current account.\r\n   * @param options OData query options.\r\n   */\r\n  public loadEmployingRelations(options: ODataQueryOptions = null): Promise<ApiListItem[]> {\r\n    return this.employmentsApi.getODataForEmployingRelations(options).then((result: ODataResult<ApiListItem>) => {\r\n\r\n      // filter out duplicates, default sort is updatedAt desc\r\n      const distinctItems: ApiListItem[] = [];\r\n      result.items.forEach((x) => {\r\n        if (distinctItems.findIndex((d) => d.ownerId === x.ownerId) === -1) {\r\n          distinctItems.push(x);\r\n        }\r\n      });\r\n      this.employingRelations = distinctItems;\r\n      return this.employingRelations;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns validation for current calculation or empty validation object if the calculation has not been recalculated (validated).\r\n   */\r\n  public get validation() {\r\n    return this.current?.result?.validation || { errors: [], hasAllRequiredFields: true, isValid: true };\r\n  }\r\n\r\n  /** Returns the employer for the given id using employing employers as a source */\r\n  public get employer(): any {\r\n    if (this.current && this.current.sharing.type === SharingUriType.Employer && this.employingRelations) {\r\n      return this.employingRelations.find((x) => x.ownerId === (this.current.sharing.uri));\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Returns email address for current accoount */\r\n  public get cc(): string {\r\n    if (this.sessionService.session) {\r\n      return this.sessionService.session.currentAccount.contact.email;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Copies link to clipboard */\r\n  public copyUri() {\r\n    (navigator as any).clipboard.writeText(this.current.sharing.uri);\r\n    this.uriCopied = true;\r\n  }\r\n\r\n  /** Returns true if the given typing is just processing sharing */\r\n  public isSharing(type: string): boolean {\r\n    return type === this.isSharingType;\r\n  }\r\n\r\n  /** Returns true if the navigator.share -function exists. */\r\n  public get isMobileSharingEnabled() {\r\n    return !!(navigator as any).share;\r\n  }\r\n\r\n  /** Whatsapp-link */\r\n  private getWhatsAppUrl(): string {\r\n    if (!this.current) {\r\n      return \"\";\r\n    }\r\n    return `https://wa.me/?text=${encodeURIComponent(this.getSharingMessage() + \"\\n\" + this.current.sharing.uri)}`;\r\n  }\r\n\r\n  /** Telegram-link */\r\n  private getTelegramUrl(): string {\r\n    if (!this.current) {\r\n      return \"\";\r\n    }\r\n    return `https://telegram.me/share/url?url=${encodeURIComponent(this.current.sharing.uri)}&text=${encodeURIComponent(this.getSharingMessage())}`;\r\n  }\r\n\r\n  /** Mobile sharing */\r\n  private shareInMobile(): Promise<any> {\r\n    const data = {\r\n      url: this.current.sharing.uri,\r\n      title: this.getSharingTitle(),\r\n      text: this.getSharingMessage(),\r\n    };\r\n    return (navigator as any).share(data);\r\n  }\r\n\r\n  private showEmailSharing(): void {\r\n    this.createSharingMessage().then( (item) => {\r\n      if (item) {\r\n        this.sendSharingEmail(item.to, item.cc, item.message);\r\n      }\r\n    });\r\n  }\r\n\r\n  private createSharingMessage(employer?: ApiListItem ): Promise<{ to: string, cc: string, message: string }> {\r\n    const item = {\r\n      to: employer?.ownerInfo?.email || \"\",\r\n      cc: this.cc,\r\n      message: \"\",\r\n    };\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/modals/calc/EmailSharing.html\", item, null)\r\n      .then((dialog) => {\r\n        if (dialog.result === \"ok\") {\r\n          return dialog.item;\r\n        } else {\r\n          return null;\r\n        }\r\n      });\r\n  }\r\n\r\n  private sendSharingEmail(to: string, cc: string, message: string): Promise<boolean> {\r\n    this.isSharingType = \"notification\";\r\n    return this.sharingCalculationsApi.notifySharing(this.currentId, to, cc, message).then((result) => {\r\n      this.isSharingType = null;\r\n      if (result === true) {\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.CalcSharingComponent.emailSendSuccess\")+ \".\");\r\n      } else {\r\n        this.uiHelpers.showAlert(Translations.get(\"SALAXY.NG1.CalcSharingComponent.emailSent\")+ \".\");\r\n      }\r\n      return this.reload().then( () => {\r\n        return result;\r\n      });\r\n    });\r\n  }\r\n\r\n  private getSharingMessage(): string {\r\n    return `${Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingMessage.calculationSent\")}. \\n ${Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingMessage.login\")}!`;\r\n  }\r\n\r\n  private getSharingTitle(): string {\r\n    return Translations.get(\"SALAXY.NG1.CalcSharingComponent.sharingTitle\");\r\n  }\r\n\r\n  /**\r\n   * Shows an alert if the signature is missing.\r\n   */\r\n  private showMissingSignatureAlert() {\r\n    this.uiHelpers.showConfirm(Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.missingSignature\"),\r\n    `${Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.finishAccountCreation\")}\\n ${Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.signAuthorization\")} \\n\\n ${Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.continueToSigning\")}`,\r\n    Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.continue\"), Translations.get(\"SALAXY.NG1.CalcSharingComponent.missingSignatureAlert.close\")).then((ok: boolean) => {\r\n        if (ok) {\r\n          this.onboardingService.launchWorkerOnboarding();\r\n        }\r\n      });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\nimport {\r\n  ApiListItem,\r\n  Employments,\r\n  ODataQueryOptions,\r\n  ODataResult,\r\n\r\n} from \"@salaxy/core\";\r\n\r\n\r\n\r\n/**\r\n * List of employers\r\n */\r\nexport class EmployerListController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Employments\", \"UiHelpers\"];\r\n\r\n  /** Employing relations for the current account */\r\n  public employingRelations: ApiListItem[] = [];\r\n\r\n  public employerId: string;\r\n\r\n  /** Items once loaded from the server. This is an empty array when the loading starts. */\r\n  public items: any[];\r\n\r\n  /** Selected search items */\r\n  public selectedItems: any[];\r\n\r\n  /** True if no employer is selected */\r\n  public showFullEmployerList: boolean;\r\n\r\n  /**\r\n   * Creates a new EmployerSelectController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private employmentsApi: Employments,\r\n    protected uiHelpers: UiHelpers\r\n  ) {\r\n\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.loadEmployingRelations();\r\n    this.selectedItems = this.selectedItems || [];\r\n    this.items = this.items || [];\r\n  }\r\n\r\n\r\n  /**\r\n   * Loads employing relations of the existing employers for the current account.\r\n   * @param options OData query options.\r\n   */\r\n  public loadEmployingRelations(options: ODataQueryOptions = null): Promise<ApiListItem[]> {\r\n\r\n    return this.employmentsApi.getODataForEmployingRelations(options).then((result: ODataResult<ApiListItem>) => {\r\n\r\n      // filter out duplicates, default sort is updatedAt desc\r\n      const distinctItems: ApiListItem[] = [];\r\n      result.items.forEach((x) => {\r\n        if (distinctItems.findIndex((d) => d.ownerId === x.ownerId) === -1) {\r\n          distinctItems.push(x);\r\n        }\r\n      });\r\n      this.employingRelations = distinctItems;\r\n\r\n      return this.employingRelations;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Function that is called when user selects an employer in the list.\r\n   * Function has the following locals: value: true/false, item: the last selected/unselected item.\r\n   * @example <salaxy-employer-select on-employer-select=\"$ctrl.onEmployerSelect($ctrl.current, value, item)\"></salaxy-employer-select>\r\n   */\r\n  public onEmployerSelect: (params: {\r\n\r\n    /** In multi-select mode, the value may be true (selected) or false (unselected). */\r\n    value: true | false,\r\n    /** Item that was last selected / deselected. */\r\n    item: any,\r\n\r\n    /** All items that are currently selected. */\r\n    allItems: any[],\r\n\r\n  }) => void;\r\n\r\n\r\n  /**\r\n   * Sets an item as selected.\r\n   * @param item Item to set as selected\r\n   * @param value Selected true / false or \"toggle\" to toggle to other value.\r\n   */\r\n  public setEmployerSelected(item: any, value: true | false | \"toggle\" = true) {\r\n    // TODO: This now only supports items with id. Add other identifiers if necessary.\r\n    const ix = this.selectedItems.findIndex((x) => x.ownerId === item.ownerId);\r\n    const exists = ix >= 0;\r\n    if (exists) {\r\n\r\n      this.selectedItems.splice(ix, 1);\r\n    }\r\n    switch (value) {\r\n      case true:\r\n        this.selectedItems.push(item);\r\n        break;\r\n      case false:\r\n        // Already done\r\n        break;\r\n      case \"toggle\":\r\n        if (!exists) {\r\n          this.selectedItems.push(item);\r\n        }\r\n        break;\r\n    }\r\n    this.onEmployerSelect({\r\n      value: value === \"toggle\" ? !exists : value,\r\n      item,\r\n      /** All items that are currently selected. */\r\n      allItems: this.selectedItems,\r\n    });\r\n    this.selectEmployer(item.ownerId);\r\n  }\r\n\r\n\r\n  /**\r\n   * Returns true if the item is selected.\r\n   * @param item Item to check for selected value.\r\n   */\r\n  public isEmployerSelected(item: any) {\r\n    return this.selectedItems.findIndex((x) => x.ownerId === item.ownerId) >= 0;\r\n  }\r\n\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n\r\n    if (this.selectedItems) {\r\n      this.selectedItems.splice(0, this.selectedItems.length);\r\n      this.showFullEmployerList = true;\r\n    }\r\n  }\r\n\r\n  /** Selects employer */\r\n\r\n  public selectEmployer(employerId:string){\r\n    this.employerId = employerId;\r\n  }\r\n\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax } from \"@salaxy/core\";\r\n\r\n/**\r\n * Employer report.\r\n */\r\nexport class EmployerReportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\"];\r\n\r\n  // TODO: Implement an algorithm that craetes the year options, so that it is always up to date.\r\n  /** Year options for the year select control. */\r\n  public yearOptions = [\r\n    { value: \"2023\", name: \"2023\" },\r\n    { value: \"2022\", name: \"2022\" },\r\n    { value: \"2021\", name: \"2021\" },\r\n    { value: \"2020\", name: \"2020\" },\r\n    { value: \"2019\", name: \"2019\" },\r\n    { value: \"2018\", name: \"2018\" },\r\n    { value: \"2017\", name: \"2017\" },\r\n    { value: \"2016\", name: \"2016\" },\r\n    { value: \"2015\", name: \"2015\" },\r\n    { value: \"2014\", name: \"2014\" },\r\n  ];\r\n\r\n  private _currentReport: any = null;\r\n  private _selectedYear: any = null;\r\n  private _employers14BGroups: any = null;\r\n\r\n\r\n  constructor(private ajax: Ajax) { }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    this.refreshData();\r\n  };\r\n\r\n  /**\r\n   * Returns the currently loaded report data.\r\n   */\r\n  public get currentReport(): any {\r\n    return this._currentReport;\r\n  }\r\n\r\n  /**\r\n   * Returns the currently selected year.\r\n   */\r\n  public get selectedYear(): any {\r\n    if (!this._selectedYear) {\r\n      // Defaults to current year (given that the yearOptions is up to date)\r\n      this._selectedYear = this.yearOptions[0];\r\n    }\r\n    return this._selectedYear;\r\n  }\r\n\r\n  /**\r\n   * Sets the currently selected year and reloads the data.\r\n   */\r\n  public set selectedYear(year) {\r\n    this._selectedYear = year;\r\n    this.refreshData();\r\n  }\r\n\r\n  /**\r\n   * Returns employer ids and names in groups of two as in the 14B form (14B Kotitalousvähennys –\r\n   * työntekijälle maksettu palkka (3026))\r\n   */\r\n  public get employers14BGroups(): any {\r\n    return this._employers14BGroups;\r\n  }\r\n\r\n/**\r\n * Returns the employer id from the current report data if available otherwise undefined.\r\n */\r\n  public get employerId(): string {\r\n    return this._currentReport?.employerReports?.[0]?.employerId;\r\n  }\r\n\r\n  /**\r\n   * Returns the salary amount for TVR (Työttömyysvakuutusrahasto).\r\n   */\r\n  public get tvrSalaryAmount(): number {\r\n    // TODO: Arrays helperiä vois käyttää\r\n    return this._currentReport.employerReports.reduce((acc, cur) => acc + cur.totalSocialSecurityBase, 0);\r\n  }\r\n\r\n  /**\r\n   * Returns avatar data based on the given url.\r\n   * @param url Avatar url.\r\n   * @returns Avatar data.\r\n   */\r\n  public avatarFrom(url: string): any {\r\n    if (url.toLowerCase().startsWith(\"/person/icon/\")) {\r\n      return this.avatarDataFromIcon(url);\r\n    }\r\n    if (url.toLowerCase().startsWith(\"http\")) {\r\n      return this.avatarDataFromUrl(url);\r\n    }\r\n    return {\r\n      color: \"pink\",\r\n      initials: \"#?\"\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Returns the worker email address from a report object otherwise null or undefined.\r\n   * @param report The report object to search for worker email.\r\n   * @returns Returns the email address or null/undefined.\r\n   */\r\n  public workerEmailFrom(report: any): string {\r\n    return report?.worker.contact.email || report?.worker.identity.email;\r\n  }\r\n\r\n  /**\r\n   * Checks if the selected reporting year is before incomes registry was established and/or\r\n   * implemented.\r\n   * @returns Returns true if selected year is before and false otherwise.\r\n   */\r\n  public get isSelectedYearBeforeIncomesRegistry(): boolean {\r\n    return this.selectedYear.value < 2019;\r\n  }\r\n\r\n  /**\r\n   * Returns the authorization token for the current user.\r\n   */\r\n  public get token(): string {\r\n    return this.ajax.getCurrentToken();\r\n  }\r\n\r\n  /**\r\n   * Returns the api server address.\r\n   */\r\n  public get apiServerAddress(): string {\r\n    return this.ajax.getServerAddress();\r\n  }\r\n\r\n  private avatarDataFromIcon(url: string) {\r\n    const iconComponents = url.substring(url.lastIndexOf(\"/\") + 1);\r\n    const initials = iconComponents.substring(0, iconComponents.indexOf(\"?color=\")) || \"#?\";\r\n    const color = iconComponents.substring(iconComponents.indexOf(\"?color=\") + \"?color=\".length) || \"pink\";\r\n    const baseIcon = \"fa-user\";\r\n    return {\r\n      initials,\r\n      color,\r\n      baseIcon,\r\n    };\r\n  }\r\n\r\n  private avatarDataFromUrl(url: string): any {\r\n    return {\r\n      url: url.trim().replace(\"https://az724081.vo.msecnd.net\", \"https://cdn.salaxy.com\"),\r\n    };\r\n  }\r\n\r\n  private refreshData() {\r\n    this.ajax.getJSON(`/v03-rc/api/yearly/employer-report/${this.selectedYear.value}`).then((data) => {\r\n      this._currentReport = data;\r\n      this._employers14BGroups = this.extractEmployer14BGroups();\r\n    });\r\n  }\r\n\r\n  private extractEmployer14BGroups(): any {\r\n    const filtered = this._currentReport.employerReports.filter(v => v.isHouseholdDeductionWork);\r\n    return filtered.reduce((acc, cur, indx) => {\r\n      if (indx % 2 === 0) {\r\n        const id1 = cur.worker.identity.socialSecurityNumberValid;\r\n        const id2 = filtered?.[indx + 1]?.worker.identity.socialSecurityNumberValid || \"\";\r\n        const names = cur.worker.fullName + (filtered?.[indx + 1] ? \" ja \" + filtered[indx + 1].worker.fullName : \"\");\r\n        acc.push({ id1, id2, names, });\r\n      }\r\n      return acc;\r\n    }, []);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiListItem,\r\n  Employments,\r\n  ODataQueryOptions,\r\n  ODataResult,\r\n\r\n} from \"@salaxy/core\";\r\n\r\n\r\n\r\n/**\r\n * Controller handles Employer selection\r\n */\r\nexport class EmployerSelectController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Employments\"];\r\n\r\n  /** Employing relations for the current account */\r\n  public employingRelations: ApiListItem[] = [];\r\n\r\n\r\n  /** Items once loaded from the server. This is an empty array when the loading starts. */\r\n  public items: any[];\r\n\r\n  /** Selected search items */\r\n  public selectedItems: any[];\r\n\r\n  /** True if any employer is selected */\r\n  public showFullEmployerList: boolean;\r\n\r\n  /**\r\n   * Creates a new EmployerSelectController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private employmentsApi: Employments\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.loadEmployingRelations();\r\n    this.selectedItems = this.selectedItems || [];\r\n    this.items = this.items || [];\r\n  }\r\n\r\n\r\n  /**\r\n   * Loads employing relations of the existing employers for the current account.\r\n   * @param options OData query options.\r\n   */\r\n  public loadEmployingRelations(options: ODataQueryOptions = null): Promise<ApiListItem[]> {\r\n\r\n    return this.employmentsApi.getODataForEmployingRelations(options).then((result: ODataResult<ApiListItem>) => {\r\n\r\n      // filter out duplicates, default sort is updatedAt desc\r\n      const distinctItems: ApiListItem[] = [];\r\n      result.items.forEach((x) => {\r\n        if (distinctItems.findIndex((d) => d.ownerId === x.ownerId) === -1) {\r\n          distinctItems.push(x);\r\n        }\r\n      });\r\n      this.employingRelations = distinctItems;\r\n      if (this.employingRelations.length == 1) {\r\n        this.setEmployerSelected(this.employingRelations[0], true);\r\n      }\r\n\r\n      return this.employingRelations;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Function that is called when user selects an employer in the list.\r\n   * Function has the following locals: value: true/false, item: the last selected/unselected item.\r\n   * @example <salaxy-employer-select on-employer-select=\"$ctrl.onEmployerSelect($ctrl.current, value, item)\"></salaxy-employer-select>\r\n   */\r\n  public onEmployerSelect: (params: {\r\n\r\n    /** In multi-select mode, the value may be true (selected) or false (unselected). */\r\n    value: true | false,\r\n    /** Item that was last selected / deselected. */\r\n    item: any,\r\n\r\n    /** All items that are currently selected. */\r\n    allItems: any[],\r\n\r\n  }) => void;\r\n\r\n\r\n  /**\r\n   * Sets an item as selected.\r\n   * @param item Item to set as selected\r\n   * @param value Selected true / false or \"toggle\" to toggle to other value.\r\n   */\r\n  public setEmployerSelected(item: any, value: true | false | \"toggle\" = true) {\r\n    // TODO: This now only supports items with id. Add other identifiers if necessary.\r\n    const ix = this.selectedItems.findIndex((x) => x.ownerId === item.ownerId);\r\n    const exists = ix >= 0;\r\n    if (exists) {\r\n\r\n      this.selectedItems.splice(ix, 1);\r\n    }\r\n    switch (value) {\r\n      case true:\r\n        this.selectedItems.push(item);\r\n        break;\r\n      case false:\r\n        // Already done\r\n        break;\r\n      case \"toggle\":\r\n        if (!exists) {\r\n          this.selectedItems.push(item);\r\n        }\r\n        break;\r\n    }\r\n    this.onEmployerSelect({\r\n      value: value === \"toggle\" ? !exists : value,\r\n      item,\r\n      /** All items that are currently selected. */\r\n      allItems: this.selectedItems,\r\n    });\r\n  }\r\n\r\n\r\n  /**\r\n   * Returns true if the item is selected.\r\n   * @param item Item to check for selected value.\r\n   */\r\n  public isEmployerSelected(item: any) {\r\n    return this.selectedItems.findIndex((x) => x.ownerId === item.ownerId) >= 0;\r\n  }\r\n\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n\r\n    if (this.selectedItems) {\r\n      this.selectedItems.splice(0, this.selectedItems.length);\r\n      this.showFullEmployerList = true;\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, Dates } from \"@salaxy/core\";\r\n\r\n/**\r\n * Employer report.\r\n */\r\nexport class HouseholdDeductionReportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\"];\r\n\r\n  // TODO: Implement an algorithm that craetes the year options, so that it is always up to date.\r\n  /** Year options for the year select control. */\r\n  public yearOptions = [\r\n    { value: \"2020\", name: \"2020\" },\r\n    { value: \"2019\", name: \"2019\" },\r\n    { value: \"2018\", name: \"2018\" },\r\n    { value: \"2017\", name: \"2017\" },\r\n    { value: \"2016\", name: \"2016\" },\r\n    { value: \"2015\", name: \"2015\" },\r\n  ];\r\n\r\n  private _currentReport: any = null;\r\n  private _selectedYear: any = null;\r\n\r\n  private _yearlyDeductionMaxAmounts = {\r\n    \"2020\": 2250,\r\n    \"2019\": 2400,\r\n    \"2018\": 2400,\r\n    \"2017\": 2400,\r\n    \"2016\": 2400,\r\n    \"2015\": 2400,\r\n  };\r\n\r\n  constructor(private ajax: Ajax) { }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    this.refreshData();\r\n  };\r\n\r\n  /**\r\n   * Returns the currently loaded report data.\r\n   */\r\n  public get currentReport(): any {\r\n    return this._currentReport;\r\n  }\r\n\r\n  /**\r\n   * Returns the currently selected year. Defaults to current year minus one.\r\n   */\r\n  public get selectedYear(): any {\r\n    if (!this._selectedYear) {\r\n      // Defaults to current year (given that the yearOptions is up to date)\r\n      this._selectedYear = this.yearOptions[0];\r\n    }\r\n    return this._selectedYear;\r\n  }\r\n\r\n  /**\r\n   * Sets the currently selected year and reloads the data.\r\n   */\r\n  public set selectedYear(year) {\r\n    this._selectedYear = year;\r\n    this.refreshData();\r\n  }\r\n\r\n  /**\r\n   * Returns the employer id from the current report data if available otherwise undefined.\r\n   */\r\n  public get employerId(): string {\r\n    return this._currentReport?.employerReports?.[0]?.employerId;\r\n  }\r\n\r\n  /**\r\n   * Returns the total deduction amount from a given employer report.\r\n   * @param employerReport The employer report for which the amount is calculated for.\r\n   * @returns The total deduction amount from a given employer report.\r\n   */\r\n  public employerDeductionsTotalAmount(employerReport: any): string {\r\n    return this.formatNumber(\r\n      employerReport.totalTaxableDeduction +\r\n      employerReport.totalMandatorySideCosts +\r\n      employerReport.deductionInsuranceEtc\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Returns the total deduction amount for a 14B form of a given year end report.\r\n   */\r\n  public yearlyForm14BTotalAmount(yearlyReport: any): string {\r\n    return this.formatNumber(\r\n      yearlyReport.employerReports\r\n        .reduce((acc, cur) => acc + cur.deduction14BFormTotal, 0)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Returns the total house hold deduction amount of a given year end report.\r\n   * @param yearlyReport The year end report for which the amount is calculated for.\r\n   */\r\n  public yearlyDeductionsTotalAmount(yearlyReport: any): string {\r\n    return this.formatNumber(this.calculateYearlyDeductionsTotalAmount(yearlyReport));\r\n  }\r\n\r\n  /**\r\n   * Returns the total deduction amount for a given reports with maximum and deductible amount taken\r\n   * into account.\r\n   * @param yearlyReport The year end report for which the amount is calculated for.\r\n   * @param deductibleAmount The deductible amount (can change in the future?)\r\n   * @returns The total deduction amount with maximum and deductible amount taken into account.\r\n   */\r\n  public yearlyDeductionTotal(yearlyReport: any, deductibleAmount = 100): string {\r\n    return this.formatNumber(\r\n      Math.min(\r\n        Math.max(\r\n          this.calculateYearlyDeductionsTotalAmount(yearlyReport) - deductibleAmount,\r\n          0),\r\n        this.deductionMaxAmount,\r\n      )\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Returns...\r\n   */\r\n  public get deductionMaxAmount(): number {\r\n    return this._yearlyDeductionMaxAmounts[this.selectedYear.value];\r\n  }\r\n\r\n  /**\r\n   * Return the given amount formatted as a currency string.\r\n   * @param amount The amount to be formatted.\r\n   * @returns The amount formatted as currency.\r\n   */\r\n  public formatNumber(amount: number): string {\r\n    return new Intl.NumberFormat(\r\n      \"fi-FI\",\r\n      {\r\n        maximumFractionDigits: 2,\r\n        minimumFractionDigits: 2,\r\n      }\r\n    ).format(amount);\r\n  }\r\n\r\n  /**\r\n   * Formats the given start and end datetimes to an optimized datarange string.\r\n   * @param start The start datetime of the date range.\r\n   * @param end The end datetime of the date range.\r\n   * @returns Returns the daterange as an optimized date range string.\r\n   */\r\n  public formatDateRange(start: string, end: string): string {\r\n    return Dates.getFormattedRange(start, end);\r\n  }\r\n\r\n  /**\r\n   * Returns an avatar.\r\n   * @param url Avatart url.\r\n   * @returns Avatar.\r\n   */\r\n  public avatarFrom(url: string): any {\r\n    if (url.toLowerCase().startsWith(\"/person/icon/\")) {\r\n      return this.avatarDataFromIcon(url);\r\n    }\r\n    if (url.toLowerCase().startsWith(\"http\")) {\r\n      return this.avatarDataFromUrl(url);\r\n    }\r\n    return {\r\n      color: \"pink\",\r\n      initials: \"#?\"\r\n    };\r\n  }\r\n\r\n  private calculateYearlyDeductionsTotalAmount(yearlyReport: any): number {\r\n    return yearlyReport.employerReports.reduce((acc, cur) => {\r\n      return acc +\r\n        cur.totalTaxableDeduction +\r\n        cur.totalMandatorySideCosts +\r\n        cur.deductionInsuranceEtc;\r\n    }, 0);\r\n  }\r\n\r\n  private avatarDataFromIcon(url: string) {\r\n    const iconComponents = url.substring(url.lastIndexOf(\"/\") + 1);\r\n    const initials = iconComponents.substring(0, iconComponents.indexOf(\"?color=\")) || \"#?\";\r\n    const color = iconComponents.substring(iconComponents.indexOf(\"?color=\") + \"?color=\".length) || \"pink\";\r\n    const baseIcon = \"fa-user\";\r\n    return {\r\n      initials,\r\n      color,\r\n      baseIcon,\r\n    };\r\n  }\r\n\r\n  private avatarDataFromUrl(url: string): any {\r\n    return {\r\n      url: url.trim().replace(\"https://az724081.vo.msecnd.net\", \"https://cdn.salaxy.com\"),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Returns the worker email address from a report object otherwise null or undefined.\r\n   * @param report The report object to search for worker email.\r\n   * @returns Returns the email address or null/undefined.\r\n   */\r\n  public workerEmailFrom(report: any): string {\r\n    return report?.worker.contact.email || report?.worker.identity.email;\r\n  }\r\n\r\n  private refreshData() {\r\n    this.ajax.getJSON(`/v03/api/yearly/tax-household-deduction-report/${this.selectedYear.value}`).then((data) => {\r\n      this._currentReport = data;\r\n    });\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport JSZip from \"@progress/jszip-esm\";\r\n\r\nimport * as FileSaver from \"file-saver\";\r\n\r\nimport { ApiListItem, Calculation, CalcWorker, Dates, HouseholdYear, HouseholdYears, HouseholdYearProcessingStatus, ODataResult, ReportType, Texts, Years, YearlySideCosts, TaxDeductionWorkCategories, HouseholdYearListItem } from \"@salaxy/core\";\r\n\r\nimport { ReportsService, SessionService, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Provides CRUD access to household yearly deductions.\r\n */\r\nexport class HouseholdYearCrudController extends ApiCrudObjectController<HouseholdYear, HouseholdYearListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"HouseholdYears\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"ReportsService\",\r\n    \"SessionService\",\r\n  ];\r\n\r\n  private _yearlyCalculations: {\r\n     year: number,\r\n     calculations: Calculation[],\r\n     modifiedCalculations: Calculation[]\r\n     status: \"loading\" | \"loaded\",\r\n     workers: Array<{\r\n       worker: CalcWorker,\r\n       mandatorySideCosts: number,\r\n       totalTaxable: number,\r\n       calculations: Calculation[],\r\n      }>\r\n  } = { year: null, calculations: [], modifiedCalculations: [], status: \"loaded\", workers: [] };\r\n\r\n  constructor(\r\n    private householdYearsApi: HouseholdYears,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private reportsService: ReportsService,\r\n    private sessionService: SessionService,\r\n  ) {\r\n    super(householdYearsApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/household-years\",\r\n      detailsUrl: this.detailsUrl || \"/household-years/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/HouseholdYears.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Save changes to the current item */\r\n  public async save(): Promise<HouseholdYear> {\r\n    for (const calc of this.yearlyCalculations.modifiedCalculations) {\r\n      const updatedCalc = await this.householdYearsApi.updateCalculation(calc);\r\n      const i = this.yearlyCalculations.calculations.indexOf(calc);\r\n      if (i >= 0) {\r\n          angular.copy(updatedCalc,this.yearlyCalculations.calculations[i]);\r\n      }\r\n    }\r\n    this.yearlyCalculations.modifiedCalculations.splice(0,  this.yearlyCalculations.modifiedCalculations.length);\r\n    return super.save();\r\n  }\r\n\r\n  /** Returns all paid calculations for the household year */\r\n  public get yearlyCalculations(): {year: number, calculations: Calculation[], modifiedCalculations: Calculation[], status: \"loading\" | \"loaded\",  workers: Array<{\r\n    worker: CalcWorker,\r\n    mandatorySideCosts: number,\r\n    totalTaxable: number,\r\n    calculations: Calculation[],\r\n   }>} {\r\n    if (!this.current || !this.current.year) {\r\n      this._yearlyCalculations.year = null;\r\n      this._yearlyCalculations.status = \"loaded\";\r\n      this._yearlyCalculations.calculations.splice(0,  this._yearlyCalculations.calculations.length);\r\n      this._yearlyCalculations.modifiedCalculations.splice(0,  this._yearlyCalculations.modifiedCalculations.length);\r\n      this._yearlyCalculations.workers.splice(0,  this._yearlyCalculations.calculations.length);\r\n    } else {\r\n      if (this._yearlyCalculations.year !== this.current.year &&  this._yearlyCalculations.status !== \"loading\") {\r\n        this._yearlyCalculations.year = this.current.year;\r\n        this._yearlyCalculations.status = \"loading\";\r\n        this.householdYearsApi.getCalculationsForYear(this._yearlyCalculations.year).then( (calculations) => {\r\n          this._yearlyCalculations.calculations = [];\r\n          this._yearlyCalculations.modifiedCalculations = [];\r\n          this._yearlyCalculations.workers = [];\r\n          this._yearlyCalculations.calculations.push(...calculations);\r\n\r\n          for(const calc of this._yearlyCalculations.calculations) {\r\n            let item = this._yearlyCalculations.workers.find( (x) => x.worker.paymentData.socialSecurityNumberValid == calc.worker.paymentData.socialSecurityNumberValid);\r\n            if (!item) {\r\n              item = { worker: calc.worker, totalTaxable: 0, mandatorySideCosts:0, calculations: [] };\r\n              this._yearlyCalculations.workers.push(item);\r\n            }\r\n            item.calculations.push(calc);\r\n            item.mandatorySideCosts += calc.result.employerCalc.mandatorySideCosts;\r\n            item.totalTaxable += calc.result.totals.totalTaxable;\r\n          }\r\n          this._yearlyCalculations.status = \"loaded\";\r\n        });\r\n      }\r\n    }\r\n    return this._yearlyCalculations;\r\n  }\r\n\r\n    /** Returns true if the feedback is active */\r\n    public get isOpen(): boolean {\r\n      if (!this.current) {\r\n        return false;\r\n      }\r\n\r\n      return this.sessionService.isInSomeRole([\"pro\", \"admin\"]) ||\r\n             !this.current.processingStatus || this.current.processingStatus === HouseholdYearProcessingStatus.Open;\r\n    }\r\n\r\n\r\n  /** Calculates the household tax deduction total */\r\n  public getTaxDeductionTotal() {\r\n    let deductibleTotal = 0;\r\n    const calcs = this.yearlyCalculations.calculations;\r\n\r\n    for (const calc of calcs) {\r\n      if (calc.usecase?.data?.isHouseholdDeductible && !this.isHouseholdDeductionExtended(calc)) {\r\n        deductibleTotal += calc.result.employerCalc.mandatorySideCosts;\r\n        deductibleTotal += ( calc.result.totals.totalTaxable * this.getHouseholdDeduction(calc) );\r\n      }\r\n    }\r\n    return deductibleTotal;\r\n  }\r\n\r\n   /** Calculates the household tax deduction total */\r\n   public getTaxDeductionTotalExtended() {\r\n    let deductibleTotal = 0;\r\n    const calcs = this.yearlyCalculations.calculations;\r\n\r\n    for (const calc of calcs) {\r\n      if (calc.usecase?.data?.isHouseholdDeductible && this.isHouseholdDeductionExtended(calc)) {\r\n        deductibleTotal += calc.result.employerCalc.mandatorySideCosts;\r\n        deductibleTotal += ( calc.result.totals.totalTaxable * this.getHouseholdDeduction(calc) );\r\n      }\r\n    }\r\n    return deductibleTotal;\r\n  }\r\n\r\n  /** Returns true if the deduction should be split between spouses */\r\n  public canSplitWithSpouse() {\r\n    return this.getSplittableMaxAmount() > 0;\r\n  }\r\n\r\n  /** Returns current deduction max amount */\r\n  public getSplittableMaxAmount() {\r\n    let maxAmount = 0;\r\n    if ((this.getTaxDeductionTotal() + (this.current.insuranceAmount ?? 0)) > (this.getHouseholdDeductionMaxAmount() + this.getHouseholdDeductionDeductible())) {\r\n      maxAmount = this.getHouseholdDeductionMaxAmount();\r\n    }\r\n    if ( (Math.min(this.getTaxDeductionTotal(), this.getHouseholdDeductionMaxAmount() + this.getHouseholdDeductionDeductible()) + this.getTaxDeductionTotalExtended() + (this.current.insuranceAmount ?? 0)) > (this.getHouseholdDeductionMaxAmountExtended() + this.getHouseholdDeductionDeductible())) {\r\n      maxAmount = this.getHouseholdDeductionMaxAmountExtended();\r\n    }\r\n    return maxAmount;\r\n  }\r\n\r\n  /** Returns household deduction for calculation */\r\n  public getHouseholdDeduction(calc: Calculation) {\r\n    const category = this.getTaxDeductionWorkCategories(calc);\r\n    const sideCosts = this.getYearlySideCosts();\r\n\r\n    if (this.getHouseholdDeductionCategoriesExtended().includes(category)) {\r\n      return sideCosts.householdDeductionExtended;\r\n    }\r\n    return sideCosts.householdDeduction;\r\n  }\r\n\r\n  /** Returns deduction deductible */\r\n  public getHouseholdDeductionDeductible() {\r\n    const sideCosts = this.getYearlySideCosts();\r\n    return sideCosts.householdDeductionDeductible;\r\n  }\r\n\r\n  /**\r\n   * Gets a link URL for a yearly report. This is a full link with token and absolute URL.\r\n   * @param type - Type of the report must be one of the yearly reports\r\n   * @param year - Year for the report\r\n   * @param id - Worker ID for those reports that are specific to one Worker.\r\n   * @param id2 - Second Worker ID for those reports that have two Workers in one report\r\n   */\r\n   public getYearlyReport(type: ReportType, year: number, id?: string, id2?: string) {\r\n    return this.reportsService.getYearlyReportUrl(type, year, id, id2);\r\n  }\r\n\r\n  /** Set calculation modified */\r\n  public calculationUpdated(calc: Calculation) {\r\n    const existingCalc = this.yearlyCalculations.modifiedCalculations.find( (x) => x.id === calc.id);\r\n    if (!existingCalc) {\r\n      const newCalc = this.yearlyCalculations.calculations.find( (x) => x.id == calc.id);\r\n      if (newCalc) {\r\n        this.yearlyCalculations.modifiedCalculations.push(newCalc);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sets the active year to the controller.\r\n   */\r\n  public setActiveYear() {\r\n    const now = new Date();\r\n    const year = now.getMonth() >= 2 ? now.getFullYear() : now.getFullYear()  - 1;\r\n\r\n    this.householdYearsApi.getAll().then( (result) => {\r\n      const odata = result as any as ODataResult<ApiListItem>;\r\n      const logicalDate = `${year}-01-01T00:00:00Z`;\r\n      const report = odata.items.find( (x) => x.logicalDate == logicalDate);\r\n      if (report) {\r\n        this.householdYearsApi.getSingle(report.id).then( (yearReport) => {\r\n          this.model = yearReport;\r\n        });\r\n      }\r\n      else\r\n      {\r\n        const newModel = this.api.getBlank();\r\n        newModel.year = year;\r\n        this.model = newModel;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Export pdf for the given deductions */\r\n  public async export() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\", \"Ladataan PDF-tiedostoja...\");\r\n    const results =  await this.downloadReportsForHousehold();\r\n    if (results.length === 0) {\r\n      loading.dismiss();\r\n    } else {\r\n      if (results.length === 1) {\r\n        this.uiHelpers.downloadFile(results[0].blob, results[0].fileName);\r\n        loading.dismiss();\r\n      } else {\r\n        loading.setText(`Muodostetaan pakattu tiedosto`);\r\n        const zip = new JSZip();\r\n        results.forEach(item => {\r\n          zip.file(`${item.fileName}`, item.blob);\r\n        });\r\n        const blob =  await zip.generateAsync({\r\n          type: \"blob\",\r\n          mimeType:\r\n            \"application/zip\",\r\n        });\r\n        FileSaver.saveAs(blob, `${Texts.escapeFileName(`14B_${Dates.format(\"today\",\"YYYYMMDD\")}`)}.zip`);\r\n        loading.dismiss();\r\n      }\r\n    }\r\n  }\r\n\r\n  private async downloadReportsForHousehold(): Promise<Array<{blob: Blob, fileName: string}>> {\r\n    if (!this.current?.id) {\r\n      return Promise.resolve([]);\r\n    }\r\n    const results = [];\r\n    const pdfs = await this.householdYearsApi.downloadPdfs(this.current.id);\r\n    for(const pdf of pdfs) {\r\n      results.push( {\r\n        fileName: pdf.fileName,\r\n        blob: this.uiHelpers.bytes2Blob(pdf.bytes,\"application/pdf\"),\r\n      });\r\n    }\r\n    return results;\r\n  }\r\n\r\n   private  getYearlySideCosts(): YearlySideCosts {\r\n    if (!this.current || !this.current.year) {\r\n      return Years.getYearlyChangingNumbers(Dates.getToday()).sideCosts;\r\n    }\r\n    return Years.getYearlyChangingNumbers(`${this.current.year}-01-01`).sideCosts;\r\n  }\r\n\r\n  private getHouseholdDeductionMaxAmount() {\r\n    const sideCosts = this.getYearlySideCosts();\r\n    return sideCosts.householdDeductionMaxAmount;\r\n  }\r\n\r\n  private getHouseholdDeductionMaxAmountExtended() {\r\n    const sideCosts = this.getYearlySideCosts();\r\n    return sideCosts.householdDeductionMaxAmountExtended;\r\n  }\r\n\r\n  private getTaxDeductionWorkCategories(calc: Calculation) : TaxDeductionWorkCategories {\r\n    return calc.usecase?.data?.taxDeductionCategories ?? TaxDeductionWorkCategories.None;\r\n  }\r\n\r\n  private getHouseholdDeductionCategoriesExtended(): TaxDeductionWorkCategories[] {\r\n    const sideCosts = this.getYearlySideCosts();\r\n    return sideCosts.householdDeductionCategoriesExtended ?? [];\r\n  }\r\n\r\n  private isHouseholdDeductionExtended(calc: Calculation): boolean {\r\n    const category = this.getTaxDeductionWorkCategories(calc);\r\n    return this.getHouseholdDeductionCategoriesExtended().includes(category);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Accounts, Avatar, AvatarPictureType, PersonAccount, WorkflowEvent, Years } from \"@salaxy/core\";\r\n\r\nimport { GravatarHelpers, SessionService, UiHelpers, UploadService } from \"../../services\";\r\n\r\n/** Controller for editing contact, avatar etc. information on Person accounts (Worker or Household). */\r\nexport class PersonAccountController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Accounts\", \"SessionService\", \"UploadService\", \"UiHelpers\", \"$location\"];\r\n\r\n  /** Yearly sidecosts */\r\n  public sideCosts = Years.getYearlyChangingNumbers(new Date()).sideCosts;\r\n\r\n  /** Current person account being edited. */\r\n  public current: PersonAccount;\r\n\r\n  /** Current tab in initialization. If not set, will be fetched from url hash. */\r\n  private _currentTab = null;\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    private accounts: Accounts,\r\n\r\n    private sessionService: SessionService,\r\n    private uploadService: UploadService,\r\n    private uiHelpers: UiHelpers,\r\n    private $location: angular.ILocationService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    if (!this.current && this.sessionService.getCurrentToken()) {\r\n      this.accounts.getPerson().then((person) => {\r\n        this.current = person;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Switches the current web site usage role between household and worker.\r\n   * TODO: This functionality will be removed\r\n   * @param role - household or worker.\r\n   * @returns A Promise with result data (new role as string)\r\n   */\r\n  public switchRole(role: \"worker\" | \"household\"): Promise<\"household\" | \"worker\"> {\r\n    return this.sessionService.switchRole(role).then((resultRole) => {\r\n      if (role === \"worker\") {\r\n        window.location.href = \"/Worker#/\";\r\n      } else {\r\n        window.location.href = \"/Household#/\";\r\n      }\r\n      return resultRole;\r\n    });\r\n  }\r\n\r\n  /** Updates the person */\r\n  public saveCurrent = (): Promise<PersonAccount> => {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return this.accounts.savePerson(this.current).then((person: PersonAccount) => {\r\n      this.current = person;\r\n      return this.sessionService.checkSession().then(() => {\r\n        loading.dismiss();\r\n        return this.current;\r\n      });\r\n    });\r\n  };\r\n\r\n  /** Gets the language of the user (person) */\r\n  public getAccountLanguage() {\r\n    return this.current?.language;\r\n  }\r\n\r\n/**\r\n * Uploads avatar image file to the server.\r\n * @param avatar - selected file\r\n */\r\n  public uploadAvatarImage(avatar: any) {\r\n    if (!avatar) {\r\n      return;\r\n    }\r\n    this.uploadService.upload<Avatar>(this.accounts.getAvatarUploadUrl(), { avatar })\r\n      .then((resp) => {\r\n        this.current.avatar.url = resp.url;\r\n        this.current.avatar.pictureType = resp.pictureType;\r\n      });\r\n  }\r\n\r\n  /** Called when avatar changes */\r\n  public emailForAvatarChanged() {\r\n    if (!this.current || !this.current.avatar) {\r\n      return;\r\n    }\r\n    if (this.current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      this.current.avatar.url = GravatarHelpers.getGravatarUrl(this.current.contact.email);\r\n    }\r\n  }\r\n  /** Called when avatar changes */\r\n  public typeForAvatarChanged() {\r\n    if (!this.current || !this.current.avatar) {\r\n      return;\r\n    }\r\n    if (this.current.avatar.pictureType === AvatarPictureType.Gravatar) {\r\n      this.current.avatar.url = GravatarHelpers.getGravatarUrl(this.current.contact.email);\r\n    } else {\r\n      if (GravatarHelpers.isGravatarUrl(this.current.avatar.url)) {\r\n        this.current.avatar.url = null;\r\n      }\r\n      if (this.current.avatar.pictureType === AvatarPictureType.Uploaded) {\r\n        const originalAvatar = (this.sessionService.getPersonAccount() || {}).avatar;\r\n        if (!this.current.avatar.url && originalAvatar && originalAvatar.url) {\r\n          if (originalAvatar.pictureType === AvatarPictureType.Uploaded &&\r\n            !GravatarHelpers.isGravatarUrl(originalAvatar.url)) {\r\n            this.current.avatar.url = originalAvatar.url;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * For the tab UI control, returns the current tab, if defined in the path\r\n   * or set explicitly. Defaults to \"default\".\r\n   */\r\n\r\n  public get currentTab(): \"default\" | \"contact\" | \"avatar\" | \"insurance\" | \"identity\" | \"taxcard\" {\r\n    if (this._currentTab) {\r\n      return this._currentTab;\r\n    }\r\n    const supportedHashes = [\"default\", \"contact\", \"avatar\", \"insurance\", \"identity\", \"taxcard\"];\r\n    const hash = (this.$location ? this.$location.hash() || \"\" : \"\").trim().toLowerCase();\r\n    return supportedHashes.indexOf(hash) > -1 ? hash as any : \"default\";\r\n  }\r\n  public set currentTab(value: \"default\" | \"contact\" | \"avatar\" | \"insurance\" | \"identity\" | \"taxcard\") {\r\n    this._currentTab = value;\r\n  }\r\n\r\n  /**\r\n   * Adds/updates the workflow event for the current using API.\r\n   * @param wfEvent - Workflow event to add/update.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public saveWorkflowEvent(wfEvent: WorkflowEvent): Promise<void | PersonAccount> {\r\n    return this.accounts.saveWorkflowEvent(this.current, wfEvent).then(() => {\r\n      return this.accounts.getPerson().then((person) => {\r\n        this.current = person;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes the given event or all events with given type using API.\r\n   * @param wfIdOrType Id or type of the workflow event.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public deleteWorkflowEvent(wfIdOrType: string): Promise<void | PersonAccount> {\r\n    return this.accounts.deleteWorkflowEvent(this.current, wfIdOrType).then(() => {\r\n      return this.accounts.getPerson().then((person) => {\r\n        this.current = person;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a single workflow event for the item.\r\n   * @param wfId Id the workflow event.\r\n   * @returns - Workflow event.\r\n   */\r\n  public getWorkflowEvent(wfId: string): Promise<WorkflowEvent> {\r\n    return this.accounts.getWorkflowEvent(this.current, wfId);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax } from \"@salaxy/core\";\r\n\r\n/**\r\n * Employer report.\r\n */\r\nexport class WorkerReportController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\"];\r\n\r\n  private _yearOptions = null;\r\n\r\n  private _currentReport: any = null;\r\n  private _selectedYear: any = null;\r\n\r\n  constructor(private ajax: Ajax) { }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    this.refreshData();\r\n  };\r\n\r\n  /** Return year options for the year select control. */\r\n  public get yearOptions() {\r\n    if (!this._yearOptions) {\r\n      const startYear = 2014;\r\n      const endYear = new Date().getFullYear();\r\n      this._yearOptions = [];\r\n      for(let year = startYear; year <= endYear; year++) {\r\n        this._yearOptions.unshift({value: \"\" + year, name: \"\" + year});\r\n      }\r\n    }\r\n    return this._yearOptions;\r\n  }\r\n\r\n  /**\r\n   * Returns the currently loaded report data.\r\n   */\r\n  public get currentReport(): any {\r\n    return this._currentReport;\r\n  }\r\n\r\n  /**\r\n   * Returns the currently selected reporting year.\r\n   */\r\n  public get selectedYear(): any {\r\n    if (!this._selectedYear) {\r\n      // Defaults to current year (given that the yearOptions is up to date)\r\n      this._selectedYear = this.yearOptions[0];\r\n    }\r\n    return this._selectedYear;\r\n  }\r\n\r\n  /**\r\n   * Sets the currently selected reporting year and reloads the data.\r\n   */\r\n  public set selectedYear(year) {\r\n    this._selectedYear = year;\r\n    this.refreshData();\r\n  }\r\n\r\n  /**\r\n   * Returns the worker email address from a report object otherwise null or undefined.\r\n   * @param report The report object to search for worker email.\r\n   * @returns Returns the email address or null/undefined.\r\n   */\r\n  public employerEmailFrom(report: any): string {\r\n    return report?.employer.contact.email || report?.employer.identity.email;\r\n  }\r\n\r\n  /**\r\n   * Checks if the selected reporting year is before incomes registry was established and/or\r\n   * implemented.\r\n   * @returns Returns true if selected year is before and false otherwise.\r\n   */\r\n  public get isSelectedYearBeforeIncomesRegistry(): boolean {\r\n    return this.selectedYear.value < 2019;\r\n  }\r\n\r\n  /**\r\n   * Returns avatar data based on the given url.\r\n   * @param url Avatar url.\r\n   * @returns Avatar data.\r\n   */\r\n  public avatarFrom(url: string): any {\r\n    if (url.toLowerCase().startsWith(\"/person/icon/\")) {\r\n      return this.avatarDataFromIcon(url);\r\n    }\r\n    if (url.toLowerCase().startsWith(\"http\")) {\r\n      return this.avatarDataFromUrl(url);\r\n    }\r\n    return {\r\n      color: \"pink\",\r\n      initials: \"#?\"\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Returns the authorization token for the current user.\r\n   */\r\n  public get token(): string {\r\n    return this.ajax.getCurrentToken();\r\n  }\r\n\r\n  /**\r\n   * Returns the api server address.\r\n   */\r\n  public get apiServerAddress(): string {\r\n    return this.ajax.getServerAddress();\r\n  }\r\n\r\n  private avatarDataFromIcon(url: string) {\r\n    const iconComponents = url.substring(url.lastIndexOf(\"/\") + 1);\r\n    const initials = iconComponents.substring(0, iconComponents.indexOf(\"?color=\")) || \"#?\";\r\n    const color = iconComponents.substring(iconComponents.indexOf(\"?color=\") + \"?color=\".length) || \"pink\";\r\n    const baseIcon = \"fa-user\";\r\n    return {\r\n      initials,\r\n      color,\r\n      baseIcon,\r\n    };\r\n  }\r\n\r\n  private avatarDataFromUrl(url: string): any {\r\n    return {\r\n      url: url.trim().replace(\"https://az724081.vo.msecnd.net\", \"https://cdn.salaxy.com\"),\r\n    };\r\n  }\r\n\r\n  private refreshData() {\r\n    this.ajax.getJSON(`/v03-rc/api/yearly/worker-report/${this.selectedYear.value}`).then((data) => {\r\n      this._currentReport = data;\r\n    });\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { Arrays, Calculations, MessageThreads, Payrolls} from \"@salaxy/core\";\r\n\r\nimport { MessageThreadCrudController } from \"../communications\";\r\n\r\nimport { SessionService, UiHelpers, UploadService } from \"../../services\";\r\n\r\n/** DEMO / PROTO ONLY: UI prototype for worker side of new Timesheet and usecases functionality. */\r\nexport class TimesheetWorkerDemoController extends MessageThreadCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"MessageThreads\", \"UiHelpers\", \"UploadService\", \"$location\", \"$routeParams\", \"$anchorScroll\", \"$timeout\", \"SessionService\", \"$interval\", \"Calculations\", \"Payrolls\"];\r\n\r\n  /** List of entries: This should be stored in local storage. */\r\n  public entries = [];\r\n\r\n  /** Current entry in the entry or editable entry */\r\n  public currentEntry: {\r\n    start: Date,\r\n    end?: Date,\r\n    total: Date,\r\n    project?: string,\r\n    comment?: string,\r\n    isStarted: boolean,\r\n  } = null;\r\n\r\n  public projects = {\r\n    \"1234\": \"Projekti 1\",\r\n    \"2345\": \"Toinen projekti\",\r\n    \"1345\": \"Joku muu projekti\",\r\n  };\r\n\r\n  private timer: angular.IPromise<void>;\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    private msgApi: MessageThreads,\r\n    uiHelpers: UiHelpers,\r\n    uploadService: UploadService,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    $anchorScroll: angular.IAnchorScrollService,\r\n    $timeout: angular.ITimeoutService,\r\n\r\n    sessionService: SessionService,\r\n    calculations: Calculations,\r\n    payrolls: Payrolls,\r\n    private $interval: angular.IIntervalService,\r\n  ) {\r\n    super(msgApi, uiHelpers, uploadService, $location, $routeParams, $anchorScroll, $timeout, sessionService, calculations, payrolls);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.resetTimer();\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Called when controller is destroyed */\r\n  public $onDestroy = () => {\r\n    this.stopTechnicalTimer();\r\n  };\r\n\r\n  /** Resets the timer to zero value */\r\n  public resetTimer() {\r\n    this.stopTechnicalTimer();\r\n    this.currentEntry = {\r\n      isStarted: false,\r\n      start: this.roundDate(),\r\n      total: new Date(0),\r\n    };\r\n  }\r\n\r\n  /** Starts the timer. */\r\n  public startTimer()\r\n  {\r\n    this.stopTechnicalTimer();\r\n    this.currentEntry.start = this.roundDate();\r\n    this.currentEntry.isStarted = true;\r\n    this.timer = this.$interval(() => {\r\n      this.currentEntry.total = new Date(this.roundDate().getTime() - this.currentEntry.start.getTime());\r\n    }, 1000);\r\n  }\r\n\r\n  /** Starts the timer. */\r\n  public stopTimer()\r\n  {\r\n    this.currentEntry.end = this.roundDate();\r\n    this.currentEntry.total = new Date(this.currentEntry.end.getTime() - this.currentEntry.start.getTime());\r\n    this.entries.push(this.currentEntry);\r\n    this.resetTimer();\r\n  }\r\n\r\n  /** Gets the project text for a project */\r\n  public getProjectText(key: string): string {\r\n    if (!key) {\r\n      return \"Ei projektia\";\r\n    }\r\n    return this.projects[key] || (\"Ei projektia \" + key) ;\r\n  }\r\n\r\n  /** Gets the total of the timesheets logged today */\r\n  public getTotal() {\r\n    return new Date(Arrays.sum(this.entries, (x) => x.total.getTime()));\r\n  }\r\n\r\n  private roundDate(time: Date = null): Date {\r\n    if (!time) {\r\n      time = new Date();\r\n    }\r\n    time.setMilliseconds(0);\r\n    // time.setSeconds(0);\r\n    return time;\r\n  }\r\n\r\n  private stopTechnicalTimer() {\r\n    if (this.timer) {\r\n      this.$interval.cancel(this.timer);\r\n    }\r\n  }\r\n\r\n\r\n  public calendarDemoData = [\r\n    {\r\n      day: \"ma\",\r\n      date: \"2.5.\",\r\n      hours: \"7:30 h\",\r\n    },{\r\n      day: \"ti\",\r\n      date: \"3.5.\",\r\n      hours: \"7:30 h\",\r\n    },{\r\n      day: \"ke\",\r\n      date: \"4.5.\",\r\n      hours: null,\r\n    },{\r\n      day: \"to\",\r\n      date: \"5.5.\",\r\n      hours: null,\r\n    },{\r\n      day: \"pe\",\r\n      date: \"6.5.\",\r\n      hours: null,\r\n    },{\r\n      day: \"la\",\r\n      date: \"7.5.\",\r\n      hours: null,\r\n      isHoliday: true,\r\n    },{\r\n      day: \"su\",\r\n      date: \"8.5.\",\r\n      hours: null,\r\n      isHoliday: true,\r\n    },\r\n  ];\r\n\r\n  /** Sets the usecase to a new message thread */\r\n  public setUsecase(newUsecase: any) {\r\n    (this.current as any).usecase = {\r\n      uri: \"palkkaus.fi/testing/messages-proto/\" + newUsecase.id,\r\n      label: newUsecase.title,\r\n      description: newUsecase.descr,\r\n      data: {\r\n        protoId: newUsecase.id,\r\n      },\r\n    };\r\n  }\r\n\r\n  /** Gets the usecases available for the current Worker-Employer combination. */\r\n  public getUsecases(): {\r\n    id: string,\r\n    icon?: string,\r\n    pic?: string,\r\n    title: string,\r\n    descr: string,\r\n  }[] {\r\n    return this.uiHelpers.cache(this, \"usecases\", () => {\r\n      return [\r\n        {\r\n          id: \"default\",\r\n          icon: \"fa-envelope\",\r\n          title: \"Viesti\",\r\n          descr: \"Lähetä viesti turvapostilla.\",\r\n        },\r\n        {\r\n          id: \"timer\",\r\n          icon: \"fa-clock-o\",\r\n          title: \"Kellokortti\",\r\n          descr: \"Leimaa sisään digitaalisella kellokorttisovelluksella.\",\r\n        },\r\n        {\r\n          id: \"timesheet\",\r\n          icon: \"fa-calendar\",\r\n          title: \"Kirjaa tunteja\",\r\n          descr: \"Kirjaa / muokkaa jo tapahtuneita tunteja.\",\r\n        },\r\n        {\r\n          id: \"timesheet\",\r\n          icon: \"fa-calendar\",\r\n          title: \"Kirjaa työaikoja\",\r\n          descr: \"Kirjaa / muokkaa jo tehtyjä työaikoja (myös kellonajat).\",\r\n        },\r\n        {\r\n          id: \"timesheet\",\r\n          icon: \"fa-sun-o\",\r\n          title: \"Lomakalenteri\",\r\n          descr: \"Lähetä lomapyyntö\",\r\n        },\r\n        {\r\n          id: \"timesheet\",\r\n          icon: \"fa-ambulance\",\r\n          title: \"Poissaolot\",\r\n          descr: \"Ilmoita poissaolosta\",\r\n        },\r\n        {\r\n          id: \"travel\",\r\n          icon: \"fa-suitcase\",\r\n          title: \"Matkalaskut\",\r\n          descr: \"Kilometrikorvaukset, päivärahat ja kulukorvaukset matkoista.\",\r\n        },\r\n        {\r\n          id: \"expenses\",\r\n          icon: \"fa-shopping-cart\",\r\n          title: \"Kulukorvaukset\",\r\n          descr: \"Kulukorvaukset kuittien perusteella mukaan lukien kilometrikorvaukset.\",\r\n        },\r\n        {\r\n          id: \"calc\",\r\n          pic: \"https://salaxypublic.blob.core.windows.net/salaxy-wordpress/2019/03/palkkaennakko_palkkalaskuri_palkkalaskelma.png\",\r\n          title: \"Palkkalaskuri\",\r\n          descr: \"Palkkaus.fi perinteinen palkkalaskuri, jolla voit lähettää minkä tahansa palkkapyynnön.\",\r\n        }\r\n      ];\r\n    });\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\nimport { ApiValidationErrorType, Arrays, Dates, DateTimes, Message, MessageThread, Numeric, ThreadedMessageType, MessageFrom, TimesheetInput, TimesheetInputModification } from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\nimport { ListControllerBase } from \"../bases\";\r\n\r\n\r\n/** Controller handles Timer usecases */\r\nexport class WorkerTimerController extends ListControllerBase<MessageThread, Message> {\r\n  /** Binded crud controller */\r\n  public crudController: any;\r\n\r\n  /** User interface mode: \"mini\" is the front page card UI without the list and \"edit\" is just the editable list of entries.  */\r\n  public timerMode: \"mini\" | \"edit\" | \"\";\r\n\r\n  private timer: angular.IPromise<void>;\r\n\r\n  private _newTimerMessage: Message;\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$interval\", \"UiHelpers\", \"SessionService\"];\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    private $interval: angular.IIntervalService,\r\n    uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n  ) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit(){\r\n    if (this.isTimerOn) {\r\n      this.startTechnicalTimer(this.getTimerMessage());\r\n    }\r\n    this.validateEntries();\r\n    this.onCommit = () => {\r\n      this.validateEntries();\r\n      if (this.isTimerOn) {\r\n        this.startTechnicalTimer(this.getTimerMessage());\r\n      }\r\n    };\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Stop timer on destroy\r\n   */\r\n  public $onDestoy() {\r\n    this.stopTechnicalTimer();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the message indicates that the timer should be on.\r\n   */\r\n  public get isTimerOn() {\r\n    const timerMessage = this.getTimerMessage();\r\n    return timerMessage.contentData.startTime && !timerMessage.contentData.endTime;\r\n  }\r\n\r\n  /**\r\n   * Returns true if the message indicates that the timer should be on.\r\n   */\r\n    public get isTimerOnFromDayBefore() {\r\n      const timerMessage = this.getTimerMessage();\r\n      return this.isTimerOn && Dates.isBefore(timerMessage.contentData.period.start, Dates.getToday());\r\n    }\r\n\r\n  /**\r\n   * Ensure that atleast one message exists\r\n   */\r\n  public getTimerMessage() {\r\n    const messageIndex = this.list.findIndex(x => x.type === ThreadedMessageType.Timer &&\r\n      (\r\n        (!x.contentData.startTime && !x.contentData.endTime) ||\r\n        (x.contentData.startTime && !x.contentData.endTime)\r\n      )\r\n    );\r\n\r\n    if (messageIndex >= 0) {\r\n      this._newTimerMessage = null;\r\n      return this.list[messageIndex];\r\n    }\r\n\r\n    if (!this._newTimerMessage) {\r\n      this._newTimerMessage = this.getBlank();\r\n    }\r\n    return this._newTimerMessage;\r\n  }\r\n\r\n\r\n  /**\r\n   * List of items\r\n   */\r\n  public get list(): Message[] {\r\n    if (!this.parent) {\r\n      return null;\r\n    }\r\n    return this.parent.messages;\r\n  }\r\n\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl(): string {\r\n    return \"salaxy-components/worker/TimerEditDialog.html\";\r\n  }\r\n\r\n  /**\r\n   * Creating of a new item\r\n   */\r\n  public getBlank(): Message {\r\n\r\n    const contentData: TimesheetInput = {\r\n      modification: TimesheetInputModification.CREATE,\r\n      period: {\r\n        start: Dates.getToday()\r\n      }\r\n    };\r\n\r\n    return {\r\n      type: ThreadedMessageType.Timer,\r\n      content: \"Kellokorttikirjaus\",\r\n      contentData,\r\n      fromParty: MessageFrom.OtherParty,\r\n    };\r\n  }\r\n\r\n  /** Starts the timer. */\r\n  public startTimer() {\r\n    this.stopTechnicalTimer();\r\n    let timerMessage = this.getTimerMessage();\r\n    if (this.list.indexOf(timerMessage) < 0) {\r\n      this.list.push(timerMessage);\r\n    }\r\n    const now = new Date();\r\n    timerMessage.contentData.period.start = Dates.asDate(now);\r\n    timerMessage.contentData.startTime = DateTimes.asTime(now);\r\n    timerMessage.contentData.totalTime = 0;\r\n    timerMessage.contentData.totalTimeInSeconds = 0;\r\n    this.crudController.save().then((thread: MessageThread) => {\r\n      this.parent = thread;\r\n      timerMessage = this.getTimerMessage();\r\n      this.startTechnicalTimer(timerMessage);\r\n    });\r\n  }\r\n\r\n  /** Stops the timer. */\r\n  public stopTimer() {\r\n    this.stopTechnicalTimer();\r\n    const timerMessage = this.getTimerMessage();\r\n    const now = new Date();\r\n    timerMessage.contentData.period.end = Dates.asDate(now);\r\n    timerMessage.contentData.endTime = DateTimes.asTime(now);\r\n    this.calculateAndSetTotals(timerMessage);\r\n    this.crudController.save().then((thread) => {\r\n      this.parent = thread;\r\n      this.validateEntries();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Formats time as minutes or seconds.\r\n   * TODO: implement this as filter.\r\n   * @param total Total number of minutes or seconds\r\n   * @param unit Unit: seconds or minutes\r\n   * @returns Formatted time\r\n   */\r\n  public formatTime(total: number, unit: \"minutes\" | \"seconds\" = \"minutes\"): string {\r\n    const padTo2Digits = (num) => {\r\n      return num.toString().padStart(2, \"0\");\r\n    };\r\n    total = Numeric.isNumber(total) ? total : 0;\r\n    switch( unit ) {\r\n      case \"minutes\": {\r\n        const hours = Math.floor(total / 60);\r\n        const minutes = total % 60;\r\n        return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}`;\r\n      }\r\n      case \"seconds\": {\r\n        const hours = Math.floor(total / 3600);\r\n        const minutes =  Math.floor((total % 3600) / 60);\r\n        const seconds = total % 60;\r\n        return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}:${padTo2Digits(seconds)}`;\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the total of the timesheets logged in messageThread.\r\n   */\r\n  public getAndFormatTotal(): string {\r\n    return this.formatTime(Arrays.sum(this.list, (x) => x.contentData.totalTime));\r\n  }\r\n\r\n  /**\r\n   * Override for ListControllerBase showEditDialog\r\n   * @param item Item to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: Message | \"new\", isNew = false) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    if (item === \"new\") {\r\n      isNew = true;\r\n      item = this.getBlank();\r\n    }\r\n\r\n    const lk1 = ( this.crudController?.employingRelation?.settings?.costAccounting?.dimensions ||\r\n      this.sessionService.session.settings?.costAccounting?.dimensions || undefined)\r\n      .find((x) => x.name = \"lk1\");\r\n\r\n\r\n    const costAccountingSettings = lk1 ?\r\n      {\r\n        options: lk1.options,\r\n        label: lk1.label,\r\n      } : null;\r\n\r\n    this.uiHelpers.openEditDialog(this.getEditDialogTemplateUrl(), item, { ...this.getEditDialogLogic(), costAccountingSettings }).then((result) => {\r\n      if (result.action === \"ok\" || result.action === \"ok-no-save\") {\r\n        this.calculateAndSetTotals(result.item);\r\n\r\n        if (isNew) {\r\n          this.list.push(result.item);\r\n        }\r\n        if ((isNew || result.hasChanges) && result.action !== \"ok-no-save\") {\r\n          this.commit();\r\n        }\r\n      } else if (result.action === \"delete\" || result.action === \"delete-no-save\") {\r\n        if (!isNew) {\r\n          this.delete(item as Message);\r\n          if (result.action !== \"delete-no-save\") {\r\n            this.commit();\r\n          }\r\n        }\r\n      } else {\r\n        // No changes, cancel\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Gets the project text for a project */\r\n  public getDimensionOptionText(value: string): string {\r\n    if (value) {\r\n      const lk1 = ( this.crudController?.employingRelation?.settings?.costAccounting?.dimensions ||\r\n        this.sessionService.session.settings?.costAccounting?.dimensions || undefined )\r\n      .find((x) => x.name = \"lk1\");\r\n      if (lk1) {\r\n          return lk1.options.find( (x) => x.value === value)?.text ?? \"\";\r\n      }\r\n    }\r\n    return \"\";\r\n  }\r\n\r\n\r\n  private startTechnicalTimer(timerMessage: Message) {\r\n    this.stopTechnicalTimer();\r\n    this.timer = this.$interval((msg) => {\r\n      this.calculateAndSetTotals(msg, new Date());\r\n    }, 1000, 0, true, timerMessage);\r\n  }\r\n\r\n  private calculateAndSetTotals(timerMessage: Message, endTime: Date = null) {\r\n    const now = new Date();\r\n    const startTime = new Date(`${timerMessage.contentData.period.start ?? Dates.asDate(now) }T${timerMessage.contentData.startTime ?? DateTimes.asTime(now)}:00`);\r\n    endTime = endTime ?? new Date(`${timerMessage.contentData.period.end ?? Dates.asDate(now)}T${timerMessage.contentData.endTime ?? DateTimes.asTime(now)}:00`);\r\n    const ms = endTime.getTime() - startTime.getTime();\r\n    timerMessage.contentData.totalTimeInSeconds = Math.floor(ms / 1000);\r\n    timerMessage.contentData.totalTime = Math.floor(ms / 60000);\r\n  }\r\n  private stopTechnicalTimer(): void {\r\n    if (this.timer) {\r\n      this.$interval.cancel(this.timer);\r\n    }\r\n  }\r\n\r\n  /** Overlapping timer log entries validation */\r\n  private validateEntries(): void {\r\n    for (const entry of this.list) {\r\n      entry.validation = null;\r\n    }\r\n    for (const entry of this.list) {\r\n      if (entry.contentData.period.start &&\r\n        entry.contentData.startTime &&\r\n        entry.contentData.period.end &&\r\n        entry.contentData.endTime) {\r\n\r\n        const entryStartTime = new Date(`${entry.contentData.period.start}T${entry.contentData.startTime}:00`);\r\n        const entryEndTime = new Date(`${entry.contentData.period.end}T${entry.contentData.endTime}:00`);\r\n\r\n        const isOverlapping = this.list.find((x) => {\r\n\r\n          if (x.contentData.period.start &&\r\n            x.contentData.startTime &&\r\n            x.contentData.period.end &&\r\n            x.contentData.endTime) {\r\n\r\n            const xStartTime = new Date(`${x.contentData.period.start}T${x.contentData.startTime}:00`);\r\n            const xEndTime = new Date(`${x.contentData.period.end}T${x.contentData.endTime}:00`);\r\n\r\n            return entry != x &&\r\n              (\r\n                // endTime not inside entry's range\r\n                (Dates.isSameOrAfter(xEndTime, entryStartTime, \"minutes\") && Dates.isSameOrBefore(xEndTime, entryEndTime, \"minutes\")) ||\r\n                // startTime not inside entry's range\r\n                (Dates.isSameOrAfter(xStartTime, entryStartTime, \"minutes\") && Dates.isBefore(xStartTime, entryEndTime, \"minutes\")) ||\r\n                // another range covers entry's range\r\n                (Dates.isSameOrBefore(xStartTime, entryStartTime, \"minutes\") && Dates.isSameOrAfter(xEndTime, entryEndTime, \"minutes\"))\r\n              );\r\n          }\r\n          else {\r\n            return false;\r\n          }\r\n        });\r\n        if (isOverlapping) {\r\n          entry.validation = {\r\n            errors: [{\r\n              type: \"invalid\" as ApiValidationErrorType,\r\n              msg: \"Päällekkäisiä kirjauksia\",\r\n              code: \"TimeSheetInput.isOverlapping\"\r\n            }],\r\n            isValid: false,\r\n            hasAllRequiredFields: true\r\n          };\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n","import { Dates, Message, ThreadedMessageType, MessageThread, MessageFrom, TimesheetInput, TimesheetInputModification } from \"@salaxy/core\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\nimport { UiHelpers, SessionService } from \"../../services\";\r\n\r\ninterface Weekday {\r\n  dayName: string,\r\n  date: string,\r\n  displayDate: string,\r\n  isCollapsed: boolean\r\n}\r\n\r\nclass WorkerHourlyReportControllerBindings extends ListControllerBaseBindings {\r\n   /** Type of the timesheet. Options are hourlyReport and timeReport */\r\n   public reportType =  \"<\";\r\n   /**\r\n    * CRUD controller that typically defines the values for url template and\r\n    */\r\n    public crudController =  \"<\";\r\n}\r\n\r\n/** Controller handles timebased usecases (timer, hourlyreport) */\r\nexport class WorkerHourlyReportController extends ListControllerBase<MessageThread, Message> {\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new WorkerHourlyReportControllerBindings();\r\n  /** Binded crud controller */\r\n  public crudController: any;\r\n  /** Date of today */\r\n  public currentDate: string;\r\n  public firstDayOfCurrentWeekFormatted: string;\r\n  /** Last day of current week, formatted to MM/dd/YYYY - format */\r\n  public lastDayOfCurrentWeekFormatted: string;\r\n  /** first of current week, used to determine week range */\r\n  public firstDayOfCurrentWeek: string;\r\n  /** Lastday of current week, used to determine week range */\r\n  public lastDayOfCurrentWeek: string;\r\n  /** Currentweek dataset */\r\n  public currentWeek: Weekday[] = [];\r\n  /** Currently supported Report type, mostly affects to ui */\r\n  public reportType: ThreadedMessageType.HourlyReport | ThreadedMessageType.TimeReport;\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"SessionService\"];\r\n\r\n  /** Constructor for dependency injection */\r\n  constructor(\r\n    uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n  ) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.currentDate = Dates.getToday();\r\n    this.setCurrentWeek();\r\n  }\r\n\r\n  /**\r\n   * List of items\r\n   */\r\n  public get list(): Message[] {\r\n    if (!this.parent) {\r\n      return null;\r\n    }\r\n    return this.parent.messages;\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl(): string {\r\n    if (this.reportType == ThreadedMessageType.HourlyReport) {\r\n      return \"salaxy-components/worker/HourlyReportEditDialog.html\";\r\n    }\r\n\r\n    if (this.reportType == ThreadedMessageType.TimeReport) {\r\n      return \"salaxy-components/worker/TimeReportEditDialog.html\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creating of a new item\r\n   */\r\n  public getBlank(): Message {\r\n    if (this.reportType === ThreadedMessageType.HourlyReport) {\r\n      const contentData: TimesheetInput = {\r\n        modification: TimesheetInputModification.CREATE,\r\n        project: \"\",\r\n        projectText: \"\",\r\n        period: {\r\n          start: this.currentDate\r\n        },\r\n        totalTime: 450\r\n      };\r\n      return {\r\n        type: ThreadedMessageType.HourlyReport,\r\n        content: \"Tuntikirjaus\",\r\n        contentData,\r\n        fromParty: MessageFrom.OtherParty,\r\n      };\r\n    }\r\n    if (this.reportType === ThreadedMessageType.TimeReport) {\r\n      const contentData: TimesheetInput = {\r\n        modification: TimesheetInputModification.CREATE,\r\n        project: \"\",\r\n        projectText: \"\",\r\n        period: {\r\n          start: this.currentDate\r\n        }\r\n      };\r\n      return {\r\n        type: ThreadedMessageType.TimeReport,\r\n        content: \"Työaikakirjaus\",\r\n        contentData,\r\n        fromParty: MessageFrom.OtherParty,\r\n      };\r\n    }\r\n  }\r\n\r\n  /** Logic used in ListControlerBase showEditDialog */\r\n  public getEditDialogLogic(): any {\r\n    return {};\r\n  }\r\n\r\n  /** Sums daily total time */\r\n  public countDailyHours(date: string): number {\r\n    let total = 0;\r\n    const dailyMessages = this.list.filter(x => Dates.getFormattedDate(x.contentData.period.start) === Dates.getFormattedDate(date));\r\n    dailyMessages.forEach(message => {\r\n      total = total + message.contentData.totalTime;\r\n    });\r\n    if (total === 0 ) {\r\n      return 0;\r\n    }\r\n    return total;\r\n  }\r\n\r\n  /** Sum weekly totalTime */\r\n  public get weeklyHours(): number {\r\n    let total = 0;\r\n    const dailyMessages = this.list.filter(x => Dates.isSameOrAfter(x.contentData.period.start, this.firstDayOfCurrentWeek) && Dates.isSameOrBefore(x.contentData.period.start, this.lastDayOfCurrentWeek));\r\n    dailyMessages.forEach(message => {\r\n      total = total + message.contentData.totalTime;\r\n    });\r\n    if (total === 0 ) {\r\n      return 0;\r\n    }\r\n    return total;\r\n  }\r\n\r\n\r\n  /** Sets current week for ui */\r\n  public setCurrentWeek(): void {\r\n    this.firstDayOfCurrentWeekFormatted = Dates.getFormattedDate(Dates.startEnd(this.currentDate, \"start-week\"));\r\n    this.lastDayOfCurrentWeekFormatted = Dates.getFormattedDate(Dates.startEnd(this.currentDate, \"end-week\"));\r\n    this.firstDayOfCurrentWeek = Dates.startEnd(this.currentDate, \"start-week\");\r\n    this.lastDayOfCurrentWeek = Dates.startEnd(this.currentDate, \"end-week\");\r\n    this.currentWeek = [\r\n      {\r\n        dayName: \"Ma\",\r\n        date: Dates.format(this.firstDayOfCurrentWeek, \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(this.firstDayOfCurrentWeek, \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"Ti\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 1, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 1, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"Ke\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 2, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 2, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"To\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 3, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 3, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"Pe\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 4, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 4, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"La\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 5, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 5, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      },\r\n      {\r\n        dayName: \"Su\",\r\n        date: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 6, \"day\"), \"YYYY-MM-DD\"),\r\n        displayDate: Dates.format(Dates.add(this.firstDayOfCurrentWeek, 6, \"day\"), \"DD.MM\"),\r\n        isCollapsed: true\r\n      }\r\n    ];\r\n  }\r\n\r\n  /** Gets the project text for a project */\r\n  public getDimensionOptionText(value: string): string {\r\n    if (value) {\r\n      const lk1 = (this.crudController?.employingRelation?.settings?.costAccounting?.dimensions ||\r\n        this.sessionService.session.settings?.costAccounting?.dimensions || undefined)\r\n      .find((x) => x.name = \"lk1\");\r\n      if (lk1) {\r\n          return lk1.options.find( (x) => x.value === value)?.text ?? \"\";\r\n      }\r\n    }\r\n    return \"\";\r\n  }\r\n\r\n\r\n  /**\r\n   * Controlls visibility of dates messages\r\n   * @param date Used to find correct date from currentWeek\r\n   */\r\n  public setHourlyRecordsVisible(date: string): void {\r\n    const targetDate = this.currentWeek.find(x => x.date === date);\r\n    targetDate.isCollapsed = !targetDate.isCollapsed;\r\n  }\r\n\r\n  /** Change current week and reload week data */\r\n  public changeWeek(next: boolean): void {\r\n    if (next) {\r\n      this.currentDate = Dates.add(this.currentDate, 7, \"day\");\r\n    } else {\r\n      this.currentDate = Dates.add(this.currentDate, -7, \"day\");\r\n    }\r\n    this.setCurrentWeek();\r\n  }\r\n\r\n  /** Get current weeknumber */\r\n  public get currentWeekNumber(): number {\r\n    return Dates.getWeekNumber(this.currentDate);\r\n  }\r\n\r\n  /**\r\n   * Check if provided date is saturday or sunday or not workday\r\n   * @param date Used date to determine if saturday or sunday\r\n   * @returns Boolean if date is saturday or sunday\r\n   */\r\n  public isHoliday(date: string): boolean {\r\n    return !Dates.isWorkday(date) || Dates.isHoliday(date);\r\n  }\r\n\r\n  /**\r\n   * Checks if expand button should be visible\r\n   * @param date used to search correct objects\r\n   * @returns Boolean that indicates if expand chevron should be visible\r\n   */\r\n  public showExpandButton(date: string): boolean {\r\n      const messages = this.list.filter(x => Dates.getFormattedDate(x.contentData.period.start) === Dates.getFormattedDate(date));\r\n      return messages.length > 0;\r\n  }\r\n\r\n  /**\r\n   * Get blank message object for edit dialog\r\n   * @param date is used to create start date\r\n   * @returns Blank message object\r\n   */\r\n  public getEditDialogItem(date: string): Message {\r\n    if (this.reportType === ThreadedMessageType.HourlyReport) {\r\n      return {\r\n        type: this.reportType,\r\n        content: \"Tuntikirjaus\",\r\n        fromParty: MessageFrom.OtherParty,\r\n        contentData: {\r\n          modification: TimesheetInputModification.CREATE,\r\n          project: \"\",\r\n          projectText: \"\",\r\n          period: {\r\n            start: date\r\n          },\r\n          totalTime: 450\r\n        }\r\n      };\r\n    }\r\n\r\n    if (this.reportType === ThreadedMessageType.TimeReport) {\r\n      return {\r\n        type: this.reportType,\r\n        content: \"Työaikakirjaus\",\r\n        fromParty: MessageFrom.OtherParty,\r\n        contentData: {\r\n          modification: TimesheetInputModification.CREATE,\r\n          project: \"\",\r\n          projectText: \"\",\r\n          period: {\r\n            start: date\r\n          },\r\n          totalTime: 450\r\n        }\r\n      };\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Get button style for date. Handles dirrerent styles for workday, today, holiday\r\n   * @param date Day used to figure date\r\n   * @returns button class as string\r\n   */\r\n  public getDateStyle(date: string) {\r\n    if (date === Dates.getToday()) {\r\n      return \"bg-info\";\r\n    }\r\n\r\n    if (!Dates.isWorkday(date) || Dates.isHoliday(date)) {\r\n      return \"bg-primary\";\r\n    }\r\n\r\n    return \"btn btn-default\";\r\n  }\r\n\r\n  /**\r\n   * Override for ListControllerBase showEditDialog\r\n   * @param item Item to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: Message | \"new\", isNew = false) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    if (item === \"new\") {\r\n      isNew = true;\r\n      item = this.getBlank();\r\n    }\r\n\r\n    const lk1 = (this.crudController?.employingRelation?.settings?.costAccounting?.dimensions ||\r\n      this.sessionService.session.settings?.costAccounting?.dimensions || undefined)\r\n    .find((x) => x.name = \"lk1\");\r\n\r\n    const costAccountingSettings = lk1 ?\r\n      {\r\n        options: lk1.options,\r\n        label: lk1.label,\r\n      } : null;\r\n\r\n    this.uiHelpers.openEditDialog(this.getEditDialogTemplateUrl(), item, {...this.getEditDialogLogic(), costAccountingSettings}).then((result) => {\r\n      if (result.action === \"ok\" || result.action === \"ok-no-save\" ) {\r\n        if (result.item.type === ThreadedMessageType.TimeReport) {\r\n          const startTime = new Date(`${Dates.getToday()}T${result.item.contentData.startTime}:00`);\r\n          const endTime = new Date(`${Dates.getToday()}T${result.item.contentData.endTime}:00`);\r\n          result.item.contentData.totalTime = Math.floor((endTime.getTime() - startTime.getTime()) / 60000);\r\n        }\r\n        if (isNew) {\r\n          this.list.push(result.item);\r\n        }\r\n        if (( isNew || result.hasChanges) && result.action !== \"ok-no-save\") {\r\n          this.commit();\r\n        }\r\n      } else if (result.action === \"delete\" || result.action === \"delete-no-save\") {\r\n        if (!isNew) {\r\n          this.delete(item as Message);\r\n          if (result.action !== \"delete-no-save\" ) {\r\n            this.commit();\r\n          }\r\n        }\r\n      } else {\r\n        // No changes, cancel\r\n      }\r\n      });\r\n  }\r\n\r\n}\r\n","import { Message, ThreadedMessageType, MessageThread } from \"@salaxy/core\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\nclass WorkerExpenseReportControllerBindings extends ListControllerBaseBindings {\r\n  /** Type of the timesheet. Options are hourlyReport and timeReport */\r\n  public reportType =  \"<\";\r\n  /**\r\n   * CRUD controller that typically defines the values for url template and\r\n   */\r\n  public crudController =  \"<\";\r\n}\r\n\r\n/** Controller handles expense usecases*/\r\nexport class WorkerExpenseReportController extends ListControllerBase<MessageThread, Message> {\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new WorkerExpenseReportControllerBindings();\r\n\r\n  /** Type of the timesheet. Options are hourlyReport and timeReport */\r\n  public reportType: \"expense\" | \"travel\";\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n   public static $inject = [\"UiHelpers\"];\r\n\r\n   private _rowTypes = [\"expenses\", \"milageDaily\", \"milageOther\", \"milageOwnCar\", \"dailyAllowance\"];\r\n\r\n   /** Constructor for dependency injection */\r\n   constructor(\r\n     uiHelpers: UiHelpers\r\n   ) {\r\n     super(uiHelpers);\r\n   }\r\n\r\n   /** Template for edit UI that is shown in a modal dialog. */\r\n   public getEditDialogTemplateUrl(): string {\r\n    throw new Error(\"Method not implemented.\");\r\n  }\r\n\r\n  /**\r\n   * Creating of a new item\r\n   */\r\n  public getBlank(): Message {\r\n    throw new Error(\"Method not implemented.\");\r\n  }\r\n\r\n  /**\r\n   * List of items\r\n   */\r\n  public get list(): Message[] {\r\n    if (!this.parent) {\r\n      return null;\r\n    }\r\n    return this.parent.messages;\r\n  }\r\n\r\n  /**\r\n   * Ensure that atleast one message exists\r\n   */\r\n   public getCalcRowMessage() {\r\n    const messageIndex = this.list.findIndex(x => x.type === ThreadedMessageType.CalcRow);\r\n    if (messageIndex >= 0) {\r\n      return this.list[messageIndex];\r\n    }\r\n\r\n    this.list.unshift({type: ThreadedMessageType.CalcRow, contentData: {rows: []}});\r\n    return this.list[0];\r\n  }\r\n\r\n  /**\r\n   * Get rowTypes based on report type\r\n   */\r\n  public getRowTypes() {\r\n    // TODO: implement dirrerent row types\r\n    if (this.reportType === \"expense\") {\r\n      return this._rowTypes;\r\n    }\r\n    if (this.reportType === \"travel\") {\r\n      return this._rowTypes;\r\n    }\r\n  }\r\n\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Attachment, Records, Record, Translations, WorkflowEvent, RecordListItem } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, UploadService, WorkflowService } from \"../../services\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases/ApiCrudObjectController\";\r\n\r\n\r\n/**\r\n * Base controller for records management.\r\n */\r\nexport class RecordsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Records\",\r\n    \"UiHelpers\",\r\n    \"UploadService\",\r\n    \"WorkflowService\"\r\n  ];\r\n\r\n  /** Current records. */\r\n  public records: Record[];\r\n\r\n  /** Readonly binding */\r\n  public readOnly: boolean;\r\n\r\n  /** API CRUD controller for the workflow object.*/\r\n  public apiCtrl: ApiCrudObjectController<Record, RecordListItem>;\r\n\r\n  /** Entity type */\r\n  public entityType: string;\r\n\r\n  /** Loding indicator */\r\n  public isLoading: boolean;\r\n\r\n  private _wfType = \"EmployerMessageRecord\";\r\n  private _events: WorkflowEvent[] = [];\r\n\r\n  constructor(\r\n    protected api: Records,\r\n    protected uiHelpers: UiHelpers,\r\n    protected uploadService: UploadService,\r\n    protected workflowService: WorkflowService,\r\n  ) { }\r\n\r\n  /**\r\n   * Loads the records for the entity.\r\n   */\r\n  public $onInit() {\r\n    this.reload();\r\n  }\r\n\r\n  /**\r\n   * Reloads data\r\n   */\r\n  public reload() {\r\n    this.isLoading = true;\r\n    this.api.getForEntity(this.entityType, this.entityId).then((data) => {\r\n      this.records = data;\r\n      this.isLoading = false;\r\n    });\r\n  }\r\n\r\n  /** Returns events for the record. */\r\n  public getEvents(item: Record) {\r\n    return this.events.filter((x) => x.record && x.record === item.id);\r\n  }\r\n\r\n  /** Returns single event for the record. */\r\n  public getSingleEvent(item: Record): WorkflowEvent {\r\n    const wfEvents = this.getEvents(item);\r\n    return wfEvents.length > 0 ? wfEvents[0] : {};\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog.\r\n   * @param item Item to edit or to create.\r\n   * @param index Current index. -1 for new.\r\n   */\r\n  public showEditRecord(item: Record, index = -1) {\r\n    const logic = {\r\n      title: index < 0 ? Translations.get(\"SALAXY.UI_Terms.add\") : this.readOnly ? Translations.get(\"SALAXY.UI_Terms.show\") : Translations.get(\"SALAXY.UI_Terms.edit\"),\r\n      showDelete: index > -1 && !this.readOnly,\r\n      readOnly: this.readOnly,\r\n      recordTypes: [],\r\n      getAttachmentDownloadUrl: (attachment) => this.getAttachmentDownloadUrl(attachment),\r\n      getAttachmentIcon: (attachment) => this.getAttachmentIcon(attachment),\r\n      uploadAttachments: (files, attachments) => this.uploadAttachments(files, attachments),\r\n    };\r\n\r\n    item.entityType = this.entityType;\r\n    item.entityId = this.entityId;\r\n    const recordAndEvent = { record: item, wfEvent: this.getSingleEvent(item)};\r\n\r\n    logic.recordTypes.push(... this.records.map(x => x.recordType).filter((v, i, a) => a.indexOf(v) === i));\r\n    logic.recordTypes.sort();\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/records/Record.html\", recordAndEvent, logic).then((result) => {\r\n      if (result.action === \"ok\") {\r\n        if (index === -1) {\r\n          // Add\r\n          this.api.save(result.item.record).then((data) => {\r\n            this.records.push(data);\r\n            this.saveWorkflowEvent(data, result.item.wfEvent);\r\n          });\r\n        } else {\r\n          // Modify\r\n          this.api.save(result.item.record).then((data) => {\r\n            angular.copy(data, this.records[index]);\r\n            this.saveWorkflowEvent(this.records[index], result.item.wfEvent);\r\n          });\r\n        }\r\n      } else if (result.action === \"delete\") {\r\n        this.deleteRecord(result.item.record, index);\r\n        this.deleteWorkflowEvent(result.item.wfEvent);\r\n      }\r\n    });\r\n    this.api.getRecordTypes().then((serverRecordTypes) => {\r\n      logic.recordTypes.push(... (serverRecordTypes ?? []));\r\n      logic.recordTypes.splice(0, logic.recordTypes.length, ...logic.recordTypes.filter((v, i, a) => a.indexOf(v) === i));\r\n      logic.recordTypes.sort();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes one record\r\n   * @param item Item to delete.\r\n   * @param index Current index.\r\n   */\r\n  public deleteRecord(item: Record, index = -1) {\r\n    if (index > -1) {\r\n      // Delete\r\n      const wfItem = this.getSingleEvent(item);\r\n      return this.api.delete(item.id).then(() => {\r\n        this.records.splice(index, 1);\r\n        return this.deleteWorkflowEvent(wfItem);\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Returns file icon for the attachment. */\r\n  public getAttachmentIcon(attachment: Attachment): string {\r\n    return this.uploadService.getFileIcon(attachment?.fileName);\r\n  }\r\n\r\n  /** Returns download url for the attachment. */\r\n  public getAttachmentDownloadUrl(attachment: Attachment): string {\r\n    return this.uploadService.getFileUrl(attachment?.contentId);\r\n  }\r\n\r\n  /** Returns the upload url for the attachment */\r\n  public getAttachmentUploadUrl(): string {\r\n    return this.api.getRecordUploadUrl(this.entityType, this.entityId);\r\n  }\r\n\r\n  /**\r\n   * Uploads the attachments to the server, and adds them to the attchment collection.\r\n   * @param files The files collection from the upload component\r\n   * @param attachments The attachment collection for the results.\r\n   */\r\n  private uploadAttachments(files: any[], attachments: Attachment[]): any {\r\n    if (files && files.length) {\r\n      const uploadUrl = this.getAttachmentUploadUrl();\r\n      const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.MessageThreadComponent.uploadFilesSaving\");\r\n      return this.uploadService.upload<Attachment[]>(\r\n        uploadUrl, { files }).then((data) => {\r\n          if (data) {\r\n            attachments.push(...data);\r\n          }\r\n          loader.dismiss();\r\n          return data;\r\n        }).catch((response) => {\r\n          loader.dismiss();\r\n          this.uiHelpers.showAlert(\"SALAXY.UI_Terms.error\", \"SALAXY.NG1.MessageThreadComponent.uploadFilesError\");\r\n          throw new Error(response);\r\n        });\r\n    }\r\n  }\r\n\r\n  private deleteWorkflowEvent(wfEvent: WorkflowEvent): Promise<any> {\r\n    return this.cleanWorkflowEvents().then( () => {\r\n      if (wfEvent.id) {\r\n        return this.workflowService.deleteWorkflowEvent(this.apiCtrl, wfEvent.id);\r\n      }\r\n      return Promise.resolve(this.apiCtrl.current);\r\n    });\r\n  }\r\n\r\n  private saveWorkflowEvent(item: Record, wfEvent: WorkflowEvent): Promise<any> {\r\n    if (wfEvent.message) {\r\n      return this.cleanWorkflowEvents().then( () => {\r\n        // add or update\r\n        wfEvent.record = item.id;\r\n        wfEvent.type = this._wfType;\r\n        return this.workflowService.saveWorkflowEvent(this.apiCtrl, wfEvent);\r\n      });\r\n    }\r\n    else\r\n    {\r\n      // delete\r\n      return this.deleteWorkflowEvent(wfEvent);\r\n    }\r\n  }\r\n\r\n  private async cleanWorkflowEvents():Promise<any> {\r\n    // All events with no record, or with record and no matching record.id\r\n    const orphans = this.events.filter( (x) => x.id && (!x.record || (x.record && !this.records.some( (r) => x.record === r.id))));\r\n    // delete all orphans in sequence, otherwise the events are not deleted correctly\r\n    for(const orphan of orphans) {\r\n      await this.workflowService.deleteWorkflowEvent(this.apiCtrl, orphan.id);\r\n    }\r\n    return this.apiCtrl.current;\r\n  }\r\n\r\n  private get entityId(): string {\r\n    return this.entityType == \"employment\" ?\r\n     // Support old worker based cruds (not sure if this hack is needed anymore)\r\n    (this.apiCtrl.getApi().getBaseUrl() === \"/accounts/workers\" ? (this.apiCtrl.current as any).employmentId : this.apiCtrl.current.id) :\r\n    this.entityType == \"account\" ? null : this.apiCtrl.current.id;\r\n  }\r\n\r\n  private get events(): WorkflowEvent[] {\r\n    const eventsOfType = ((this.apiCtrl.current as any)?.workflowData?.events ?? []).filter((x) => x.type == this._wfType);\r\n    this.modifyArray(eventsOfType, this._events);\r\n    return this._events;\r\n  }\r\n\r\n  private modifyArray(\r\n    source: any[],\r\n    target: any[]) {\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    target.splice(0, target.length);\r\n    target.push(...source);\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingData, BlobFile, Dates, FileListItem, Files, Reports, Translations } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * The new ApiCrudObject type of CRUD controller for the BlobFile of the accounting report.\r\n */\r\nexport class AccountingReportCrudController extends ApiCrudObjectController<BlobFile, FileListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Files\",\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"$timeout\",\r\n  ];\r\n\r\n  /** Default query options for panel */\r\n  public panelQueryOptions = {\r\n    $filter: \"entityType eq 'MonthlyReport.MonthlyAccounting'\",\r\n    $orderby: \"logicalDate desc\",\r\n    $top: 5,\r\n  };\r\n\r\n  /** Data reader for selected items. */\r\n  public selectionDataReader = {\r\n    /** Function to read data into given array */\r\n    read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n      const items = this.odataController.selectedItems;\r\n      let counter = 0;\r\n      const next = (): Promise<void> => {\r\n        if (counter === items.length) {\r\n          return Promise.resolve();\r\n        }\r\n        const item = items[counter++];\r\n        return this.reportsApi.getAccountingData(item.id, target, ruleSet).then((data) => {\r\n          if (message) {\r\n            const wfEvent = {\r\n              type: \"PartnerMessageClosed\",\r\n              ui: \"success\" as any,\r\n              message,\r\n            };\r\n            return this.filesApi.saveWorkflowEvent(item, wfEvent).then(() => {\r\n              this.setWorkflowEvent(item, wfEvent);\r\n              if (data) {\r\n                arr.push(data);\r\n              }\r\n              return next();\r\n            });\r\n          }\r\n          else {\r\n            if (data) {\r\n              arr.push(data);\r\n            }\r\n            return next();\r\n          }\r\n        });\r\n      };\r\n      return next().then(() => {\r\n        return Promise.resolve();\r\n      });\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: Translations.get(\"SALAXY.NG1.AccountingReportToolsComponent.exportLabel\"),\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.odataController.selectedItems || this.odataController.selectedItems.length === 0,\r\n    /* Indicates if row is expandable */\r\n    showExpand: false,\r\n    /* Indicates if rows exists*/\r\n    hasRows: () => !this.odataController.selectedItems || this.odataController.selectedItems.length === 0,\r\n  };\r\n\r\n  /** Data reader for the current loaded data. */\r\n  public currentDataReader = {\r\n    /** Function to read data into given array */\r\n    read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n      if (this.currentData) {\r\n        if (message) {\r\n          const wfEvent = {\r\n            type: \"PartnerMessageClosed\",\r\n            ui: \"success\" as any,\r\n            message,\r\n          };\r\n          return this.filesApi.saveWorkflowEvent(this.current, wfEvent).then(() => {\r\n            arr.push(this.currentData);\r\n            return this.reload().then(() => {\r\n              return Promise.resolve();\r\n            });\r\n          });\r\n        }\r\n        else {\r\n          arr.push(this.currentData);\r\n          return Promise.resolve();\r\n        }\r\n      }\r\n      else {\r\n        return Promise.resolve();\r\n      }\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: null,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.currentData,\r\n    /* Indicates if row is expandable */\r\n    showExpand: true,\r\n    /* Indicates if rows exists*/\r\n    hasRows: () => !this.currentData?.ledgerAccounts\r\n  };\r\n\r\n  /** Status for current data . */\r\n  private currentDataStatus: \"initial\" | \"loading\" | string = \"initial\";\r\n\r\n  private _currentData: AccountingData;\r\n\r\n  private logicalDate: string;\r\n\r\n  constructor(\r\n    private filesApi: Files,\r\n    private reportsApi: Reports,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n  ) { // Dependency injection\r\n    super(filesApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n\r\n    if (Dates.getMonth(\"today\") === 1) {\r\n      this.logicalDate = Dates.format(Dates.add(\"today\",-1, \"year\"),\"YYYY-01-01\");\r\n    } else {\r\n      this.logicalDate = Dates.format(\"today\",\"YYYY-01-01\");\r\n    }\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/accounting\",\r\n      detailsUrl: this.detailsUrl || \"/accounting/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/ApiCrudObject.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Returns OData filter. */\r\n  public getODataFilter = (): string => {\r\n    const logicalDateExcluding = Dates.format(Dates.add(this.logicalDate,1, \"year\"),\"YYYY-01-01\");\r\n    return `entityType eq 'MonthlyReport.MonthlyAccounting' and logicalDate ge ${this.logicalDate} and logicalDate lt ${logicalDateExcluding}`;\r\n  };\r\n\r\n  /** Data reader for one item. */\r\n  public getItemDataReader = (item: {\r\n    /** List item id */\r\n    id: string,\r\n    /** List item owner */\r\n    owner: string,\r\n  }) => {\r\n    return {\r\n      /** Function to read data into given array */\r\n      read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n        (item as any).isReading = true;\r\n        return this.reportsApi.getAccountingData(item.id, target, ruleSet).then((data) => {\r\n          if (message) {\r\n            const wfEvent = {\r\n              type: \"PartnerMessageClosed\",\r\n              ui: \"success\" as any,\r\n              message,\r\n            };\r\n            return this.filesApi.saveWorkflowEvent(item, wfEvent).then(() => {\r\n              this.setWorkflowEvent(item as any, wfEvent);\r\n              if (data) {\r\n                arr.push(data);\r\n              }\r\n              (item as any).isReading = false;\r\n              return Promise.resolve();\r\n            });\r\n          }\r\n          else {\r\n            if (data) {\r\n              arr.push(data);\r\n            }\r\n            (item as any).isReading = false;\r\n            return Promise.resolve();\r\n          }\r\n        });\r\n      },\r\n      /** Optional label for data export */\r\n      exportLabel: null,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => false,\r\n      /* Indicates if row is expandable */\r\n      showExpand: true,\r\n      /* Indicates if rows exists*/\r\n      hasRows: true\r\n    };\r\n  };\r\n\r\n  /** Event handler for logical date. */\r\n  public logicalDateChanged() {\r\n    if (this.odataController.selectedItems) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n    }\r\n    this.odataController.options.$filter = this.getODataFilter();\r\n    this.odataController.refresh();\r\n  }\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n    if (this.odataController.selectedItems) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n    }\r\n  }\r\n\r\n  /** Select all */\r\n  public selectAll() {\r\n    if (this.odataController.selectedItems && this.odataController.items) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n      this.odataController.selectedItems.push(...this.odataController.items);\r\n    }\r\n  }\r\n\r\n  /** Accounting data of the current item. */\r\n  public get currentData() {\r\n    if (this.currentId) {\r\n      this.loadCurrentData();\r\n    } else {\r\n      // No id, reset data.\r\n      this._currentData = null;\r\n      this.currentDataStatus = \"initial\";\r\n    }\r\n    return this._currentData;\r\n  }\r\n\r\n  /** Load current data */\r\n  public loadCurrentData(targetId: string = null) {\r\n    if (targetId == null) {\r\n      if (this.currentDataStatus === \"initial\") {\r\n        targetId = \"default\";\r\n      } else if (this.currentDataStatus === \"loading\") {\r\n        return;\r\n      } else {\r\n        targetId = this.currentDataStatus.split(\".\")[1];\r\n      }\r\n    }\r\n    const currentLoadingId = `${this.currentId}.${targetId}`;\r\n    if (this.currentDataStatus !== currentLoadingId && this.currentDataStatus !== \"loading\") {\r\n      // Start downloading for the new id\r\n      this.currentDataStatus = \"loading\";\r\n      const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n      this.reportsApi.getAccountingData(this.currentId, targetId, null).then((data) => {\r\n        if (data) {\r\n          this._currentData = data;\r\n        }\r\n        this.currentDataStatus = currentLoadingId;\r\n        loading.dismiss();\r\n      });\r\n    }\r\n  }\r\n\r\n  private setWorkflowEvent(\r\n    item: {\r\n      /** List item id */\r\n      flags: string[],\r\n      /** List item owner */\r\n      messages: string[],\r\n    },\r\n    wfEvent: {\r\n      /** workflow type */\r\n      type: string,\r\n      /** ui type */\r\n      ui: string,\r\n      /** message */\r\n      message: string,\r\n    }) {\r\n    item.flags = (item.flags || []).filter((x) => x !== wfEvent.type);\r\n    item.messages = (item.messages || []).filter((x) => !x.startsWith(wfEvent.type));\r\n\r\n    item.flags.push(wfEvent.type);\r\n    item.messages.push(`${wfEvent.type} (Ui${wfEvent.ui}): ${wfEvent.message} ()`);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingData, Calculation, CalculationListItem, Dates, PeriodDateKind, PeriodType, Reports } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Provides functionality for building ad hoc accounting reports.\r\n */\r\nexport class AccountingReportQueryController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  /**\r\n   * Report view table only (partial) or pdf preview (full)\r\n   * Defaults to 'partial'\r\n   */\r\n  public view: \"partial\" | \"full\";\r\n  /** Query type: Query period or set of id's from database or calcs to specify the calculations. */\r\n  public queryType: \"periodQuery\" | \"selectionQuery\" | \"calcs\" = \"periodQuery\";\r\n\r\n  /** Period type for the query. */\r\n  public periodType: PeriodType = PeriodType.Month;\r\n\r\n  /** Period date kind for the query. */\r\n  public periodDateKind: PeriodDateKind = PeriodDateKind.PaidAtDate;\r\n\r\n  /** Ref date for the period. */\r\n  public refDate?: string;\r\n\r\n  /** End date for the custom period. */\r\n  public endDate?: string;\r\n\r\n  /** Accounting data */\r\n  public data: AccountingData;\r\n\r\n  /**Selected report language */\r\n  public lang: string;\r\n\r\n  /**\r\n   * Calculations that are selected by used to show be fetched and shown in reports.\r\n   * Only the ID is really used: the rest of the calculation data is fetched from database.\r\n   */\r\n  public calculations: CalculationListItem[] = [];\r\n\r\n  /**\r\n   * Calculations that are shown in the database directly.\r\n   * If set, will hide the query interface and set queryType accordingly (only in init).\r\n   */\r\n  public calcs: Calculation[];\r\n\r\n  /** Data reader for the control. */\r\n  public dataReader = {\r\n  /**\r\n   * Function to read data into given array\r\n   * TODO: Should make interface for this or otherwise go-through.\r\n   */\r\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n   read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n      if (this.data) {\r\n        arr.push(this.data);\r\n      }\r\n      return Promise.resolve();\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: null,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.data,\r\n    /* Indicates if row is expandable */\r\n    showExpand: true,\r\n    /* Indicates if rows exists*/\r\n    hasRows: () => !this.data?.ledgerAccounts\r\n  };\r\n\r\n  constructor(\r\n    private reportsApi: Reports,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    this.view = this.view || \"partial\";\r\n    this.refDate = Dates.format(Dates.add(\"today\",-1, \"month\"),\"YYYY-MM-01\");\r\n    if (this.calcs?.length > 0) {\r\n      this.queryType = \"calcs\";\r\n      this.queryData();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens the list of calculations into a dialog window for selection and then adds them to the selected calculations\r\n   * @param category Either \"paid\" or \"draft\".\r\n   */\r\n  public addCalcs(category: \"paid\" | \"draft\" = \"draft\") {\r\n    const selectedCalculations: CalculationListItem[] = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/CalcList.html\",\r\n      selectedCalculations,\r\n      {\r\n        title: (category === \"paid\" ? \"Valitse maksetut palkat\" : \"Valitse luonnokset\"),\r\n        category,\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && result.item.length > 0) {\r\n          for (const selectedCalculation of result.item) {\r\n            if (!this.calculations.some((x) => x.id === selectedCalculation.id)) {\r\n              this.calculations.push(selectedCalculation);\r\n            }\r\n          }\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Removes the selected calculation from the calculations list. */\r\n  public removeCalc(calculation: any) {\r\n    this.calculations = this.calculations.filter((x) => x.id !== calculation.id);\r\n  }\r\n\r\n  /** Queries the report data. */\r\n  public queryData(target = \"default\") {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    switch (this.queryType) {\r\n      case \"periodQuery\":\r\n        this.reportsApi.getAccountingDataForPeriod(this.refDate, target, this.periodType, this.endDate, this.periodDateKind)\r\n          .then((result) => {\r\n            this.data = result;\r\n            loading.dismiss();\r\n          });\r\n        break;\r\n      case \"selectionQuery\": {\r\n        const calcIds = this.calculations.map((x) => x.id);\r\n        this.reportsApi.getAccountingDataForCalculationIds(calcIds, target)\r\n          .then((result) => {\r\n            this.data = result;\r\n            loading.dismiss();\r\n          });\r\n        break;\r\n      }\r\n      case \"calcs\":\r\n        this.reportsApi.getAccountingDataForCalculations(this.calcs, target)\r\n          .then((result) => {\r\n            this.data = result;\r\n            loading.dismiss();\r\n          });\r\n        break;\r\n      default:\r\n        loading.dismiss();\r\n        throw new Error(\"Unknown queryType: \" + this.queryType);\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingData, Numeric } from \"@salaxy/core\";\r\nimport { SettingsService } from \"../../services\";\r\nimport {\r\n  Templates,\r\n  AccountingMapper,\r\n  ReportOptions,\r\n  ReportData\r\n} from \"@salaxy/reports\";\r\n\r\n/**\r\n * Provides functionality to show report rows.\r\n */\r\nexport class AccountingReportRowsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Templates\", \"$sce\", \"SettingsService\"];\r\n\r\n  /**\r\n   * Report view table only (partial) or pdf preview (full)\r\n   * Defaults to 'partial'\r\n   */\r\n  public view: \"partial\" | \"full\";\r\n\r\n  /** Accounting data */\r\n  public data: AccountingData;\r\n\r\n  /** Boolean indicating if the refresh is in progress. */\r\n  public refreshInprogress: boolean;\r\n\r\n  /**Selected report language */\r\n  public lang: string;\r\n\r\n  /** Trusted language used in html */\r\n  public calcLang: string;\r\n\r\n  private renderedData: AccountingData;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private renderedLang: string;\r\n\r\n  private reportData: ReportData<AccountingData> = {\r\n    headerFooter: {},\r\n    layout: {},\r\n    report: {},\r\n  };\r\n\r\n  private htmlData: any;\r\n\r\n  constructor(\r\n    private templates: Templates,\r\n    private $sce: angular.ISCEService,\r\n    private settingsService: SettingsService\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    this.view = this.view || \"partial\";\r\n    this.reportData.layout = AccountingMapper.getReportLayout(false);\r\n  }\r\n\r\n  /** Expand/close all nodes */\r\n  public expand(close = false) {\r\n    if (this.data) {\r\n      for (const ledgerAccount of this.data.ledgerAccounts) {\r\n        (ledgerAccount as any).rowToggle = !close;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Returns true if at least one account is toggled */\r\n  public get anyExpanded(): boolean {\r\n    if (this.data) {\r\n      for (const ledgerAccount of this.data.ledgerAccounts) {\r\n        if ((ledgerAccount as any).rowToggle) {\r\n          return true;\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Bindable and trusted html. */\r\n  public get html(): any {\r\n    this.calcLang = this.lang === \"default\" ? \"fi\" : this.lang;\r\n    if (!this.data) {\r\n      this.renderedData = null;\r\n      this.renderedLang = null;\r\n    } else {\r\n      const data = angular.copy(this.data);\r\n\r\n      if (!this.renderedData || !angular.equals(data, this.renderedData)\r\n        || this.renderedLang !== this.calcLang) {\r\n        this.renderedData = data;\r\n        this.renderedLang = this.calcLang;\r\n        this.refresh();\r\n      }\r\n    }\r\n    return this.htmlData;\r\n  }\r\n\r\n  /**\r\n   * Refresh calculation report data.\r\n   */\r\n  private refresh() {\r\n    if (this.refreshInprogress) {\r\n      return;\r\n    }\r\n    this.refreshInprogress = true;\r\n    this.settingsService.getReportOptions().then((options) => {\r\n      this.reportOptions = options;\r\n      const reportOptions = this.getDefaultReportOptions(angular.copy(this.reportOptions));\r\n      this.reportData.headerFooter = AccountingMapper.getHeaderFooter(this.data, this.reportOptions, this.calcLang);\r\n      const css = \"\";\r\n      this.reportData.layout.hasCustomCss = false;\r\n      this.reportData.layout.customCss = (css || \"\");\r\n      this.reportData.layout.margin = {\r\n        top: reportOptions.margin.top,\r\n        right: reportOptions.margin.right,\r\n        bottom: reportOptions.margin.bottom,\r\n        left: reportOptions.margin.left\r\n      };\r\n      const templates = new Templates();\r\n      this.reportData.headerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.headerTemplate, this.reportData.headerFooter, this.calcLang) : \"\";\r\n      this.reportData.footerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.footerTemplate, this.reportData.headerFooter, this.calcLang) : \"\";\r\n      this.reportData.report = AccountingMapper.getAccountingReport(this.data);\r\n      this.htmlData = this.$sce.trustAsHtml(this.templates.getHtml(\"accountingReport\", this.reportData, this.calcLang));\r\n      this.refreshInprogress = false;\r\n    });\r\n\r\n  }\r\n\r\n  private getDefaultReportOptions(optionsInput?: ReportOptions): ReportOptions {\r\n    optionsInput = optionsInput || {};\r\n    optionsInput.margin = optionsInput.margin || {};\r\n    optionsInput.margin.top = Numeric.parseNumber(optionsInput.margin.top) || 30;\r\n    optionsInput.margin.right = Numeric.parseNumber(optionsInput.margin.right) || 10;\r\n    optionsInput.margin.bottom = Numeric.parseNumber(optionsInput.margin.bottom) || 40;\r\n    optionsInput.margin.left = Numeric.parseNumber(optionsInput.margin.left) || 10;\r\n    return optionsInput;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport JSZip from \"@progress/jszip-esm\";\r\nimport * as FileSaver from \"file-saver\";\r\nimport { AccountingData, AccountingTargetLogic, CompanyAccountSettings, Dates, ExportMethod, Texts, Configs, Ajax, AccountingTargetSettings, AccountingChannel, Translations } from \"@salaxy/core\";\r\nimport { ExcelHelpers, SessionService, SettingsService, UiHelpers } from \"../../services\";\r\n\r\n/** Locale id */\r\nenum LocaleId {\r\n  Fi = \"fi\",\r\n  En = \"en\",\r\n}\r\n\r\n/** TargetOption */\r\ninterface TargetOptions {\r\n  [key: string]: TargetOption;\r\n}\r\n\r\n/** TargetOption */\r\ninterface TargetOption {\r\n  /** Export function */\r\n  getExportData?: (accountingData: AccountingData, schemeId?: string) => any[];\r\n  /** List of supported schemes */\r\n  schemes?: { id: string, label: string }[],\r\n  /** Default export method */\r\n  defaultExportMethod?: string;\r\n  /** Boolean indicating if the csv export should contain quoted strings */\r\n  noCsvQuotedStrings?: boolean;\r\n\r\n  /** Boolean indicating if the csv export should contain byte order mark */\r\n  noCsvBom?: boolean;\r\n\r\n  /** Format data as text*/\r\n  formatAsText?: (data: any[], isFinnish: boolean) => string;\r\n}\r\n\r\n/**\r\n * Provides functionality to export accounting data in various formats.\r\n */\r\nexport class AccountingReportToolsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"$timeout\",\r\n    \"SettingsService\",\r\n    \"SessionService\",\r\n    \"$location\",\r\n    \"$http\",\r\n    \"AjaxNg1\"\r\n  ];\r\n\r\n  /** Locale for exports */\r\n  public localeId: string = LocaleId.Fi;\r\n\r\n  /**\r\n   * Supported locales for exports\r\n   * TODO: This could be replaced with Culture enum directly in the UI.\r\n   */\r\n  public locales: {\r\n    /** Locale id */\r\n    id: string,\r\n    /** Locale label */\r\n    label: string,\r\n    /** Local description */\r\n    description: string,\r\n  }[] = [\r\n      {\r\n        id: LocaleId.Fi,\r\n        label: Translations.get(\"SALAXY.ENUM.Culture.fi.label\"),\r\n        description: Translations.get(\"SALAXY.ENUM.Culture.fi.description\"),\r\n      },\r\n      {\r\n        id: LocaleId.En,\r\n        label: Translations.get(\"SALAXY.ENUM.Culture.en.label\"),\r\n        description: Translations.get(\"SALAXY.ENUM.Culture.en.description\"),\r\n      },\r\n    ];\r\n\r\n  /** Size of the data export */\r\n  public schemeId: string;\r\n\r\n  /** Export format */\r\n  public exportMethod: string = ExportMethod.FileExcel;\r\n\r\n  /** Supported export formats */\r\n  private _exportMethods: {\r\n    /** File type id */\r\n    id: string,\r\n    /** File type label */\r\n    label: string,\r\n    /** Boolean indicating if the file type supports different locales */\r\n    hasLocales: boolean,\r\n    /** Workflow message after export */\r\n    workflowMessage,\r\n  }[] = [\r\n      {\r\n        id: ExportMethod.FilePdf,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.filePdf.label\"),\r\n        hasLocales: false,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.filePdf.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.FileExcel,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.fileExcel.label\"),\r\n        hasLocales: false,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.fileExcel.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.CopyExcel,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.copyExcel.label\"),\r\n        hasLocales: true,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.copyExcel.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.FileCsv,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.fileCsv.label\"),\r\n        hasLocales: true,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.fileCsv.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.CopyCsv,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.copyCsv.label\"),\r\n        hasLocales: true,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.copyCsv.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.FileText,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.fileText.label\"),\r\n        hasLocales: true,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.fileText.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.CopyText,\r\n        label: Translations.get(\"SALAXY.ENUM.ExportMethod.copyText.label\"),\r\n        hasLocales: true,\r\n        workflowMessage: Translations.get(\"SALAXY.ENUM.ExportMethod.copyText.workflowMessage\"),\r\n      },\r\n      {\r\n        id: ExportMethod.Api,\r\n        label: \"API integraatio\",\r\n        hasLocales: false,\r\n        workflowMessage: \"\",\r\n      }\r\n    ];\r\n\r\n  /** Export target */\r\n  public targetId = \"default\";\r\n\r\n  /** Targets */\r\n  public targets: any[] = [];\r\n\r\n  /**\r\n   * Object with read function to call for retrieving the accounting data.\r\n   * Function has the following argument:  arr, which is an array of accounting data into which the result will be appended.\r\n   */\r\n  public reader: {\r\n    /** Function for reading data into given array. */\r\n    read: (\r\n      /** Target for accounting data */\r\n      target: string,\r\n      /** RuleSet for accounting data */\r\n      ruleSet: string,\r\n      /** Array for accounting data read results */\r\n      arr: AccountingData[],\r\n      /** Message for workflow (loading) */\r\n      message: string,\r\n    ) => Promise<void>,\r\n    /** Optional label for data export */\r\n    exportLabel?: string,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => boolean,\r\n    /* Indicates if row is expandable */\r\n    showExpand: boolean,\r\n    /* Indicates if rows exists*/\r\n    hasRows: boolean\r\n  };\r\n\r\n  /**\r\n   * Indicator for any expanded row\r\n   */\r\n  public anyExpanded: boolean;\r\n\r\n  /**\r\n   * Report view table only (partial) or pdf preview (full)\r\n   * Defaults to 'partial'\r\n   */\r\n  public view: \"partial\" | \"full\";\r\n\r\n  /**\r\n   * Function that is called when the target has been changed\r\n   * Function has the following locals:  targetId: the selected accounting target id.\r\n   */\r\n  public onTargetChange: (params: {\r\n    /** Selected target id */\r\n    targetId: any,\r\n  }) => void;\r\n\r\n  /**\r\n   * Function that is called when row expand change\r\n   */\r\n  public onExpandChange: (params: {\r\n    /** Selected target id */\r\n    close: boolean,\r\n  }) => void;\r\n\r\n  /** Supported targets */\r\n  private targetOptions: TargetOptions = AccountingTargetLogic.getSupportedTargets();\r\n\r\n  private defaultOption: TargetOption = {\r\n    // Palkkaus.fi\r\n    getExportData: (accountingData: AccountingData) => {\r\n      return this.targetOptions[\"36dff2e2-e181-4f0d-9004-0e4aa92f5e17\"].getExportData(accountingData);\r\n    },\r\n    defaultExportMethod: ExportMethod.FileExcel,\r\n    noCsvBom: false\r\n  };\r\n\r\n  private static channelBasePaths = {\r\n    [AccountingChannel.Procountor]: \"procountor\",\r\n    [AccountingChannel.VismaNetvisor]: \"vismanetvisor\",\r\n    [AccountingChannel.VismaFivaldi]: \"vismafivaldi\",\r\n  };\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private $timeout: angular.ITimeoutService,\r\n    private settingsService: SettingsService,\r\n    private sessionService: SessionService,\r\n    private $location: angular.ILocationService,\r\n    private $http: angular.IHttpService,\r\n    private ajax: Ajax,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    // Get accounting targets\r\n    const getSettings = (): Promise<CompanyAccountSettings> => {\r\n      return new Promise((resolve) => {\r\n        const check = () => {\r\n          if (this.settingsService.current) {\r\n            return resolve(this.settingsService.current);\r\n          }\r\n          this.$timeout(() => check(), 50);\r\n        };\r\n\r\n        check();\r\n      });\r\n    };\r\n    getSettings().then((settings) => {\r\n      this.targets = settings.accounting.targets;\r\n      for (const target of this.targets) {\r\n        const targetOption = this.targetOptions[target.id] || this.targetOptions[target.format] || this.defaultOption;\r\n        target.getExportData = targetOption.getExportData;\r\n        target.schemes = targetOption.schemes ?? [];\r\n        target.defaultExportMethod = targetOption.defaultExportMethod;\r\n        target.noCsvQuotedStrings = targetOption.noCsvQuotedStrings;\r\n        target.noCsvBom = targetOption.noCsvBom;\r\n        target.formatAsText = targetOption.formatAsText;\r\n      }\r\n      if (settings.accounting.defaultTargetId) {\r\n        this.targetId = settings.accounting.defaultTargetId;\r\n        this.setExportMethod(settings.accounting.defaultTargetId);\r\n      }\r\n    });\r\n    this.view = this.view || \"partial\";\r\n  }\r\n\r\n  /** Exports data in defined format. */\r\n  public export(\r\n    reader: {\r\n      /** Function for reading data into given array. */\r\n      read: (\r\n        /** Target for accounting data */\r\n        target: string,\r\n        /** RuleSet for accounting data */\r\n        ruleSet: string,\r\n        /** Array for accounting data read results */\r\n        arr: AccountingData[],\r\n        /** Workflow loading message */\r\n        message: string,\r\n      ) => Promise<void>,\r\n      /** Optional label for data export */\r\n      exportLabel?: string,\r\n      /** Indicates if the export is not possible */\r\n      disabled: () => boolean,\r\n      /* Indicates if row is expandable */\r\n      showExpand: boolean,\r\n      /* Indicates if rows exists*/\r\n      hasRows: boolean\r\n    } = null,\r\n    /** If true, does not show loading indicator. Default is false. */\r\n    hideLoading = false,\r\n  ): Promise<void> {\r\n    if (!reader) {\r\n      reader = this.reader;\r\n    }\r\n    if (!reader) {\r\n      console.error(\"No data reader for accounting data.\");\r\n      return Promise.resolve();\r\n    }\r\n    const loading = hideLoading ? { dismiss: () => null } : this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n\r\n    const target = this.getTarget(this.targetId);\r\n    const arr: AccountingData[] = [];\r\n    return reader.read(this.targetId, null, arr, this.getWorkflowMessage()).then(() => {\r\n      if (arr.length === 0) {\r\n        loading.dismiss();\r\n        return Promise.resolve();\r\n      }\r\n      switch (this.exportMethod) {\r\n        case ExportMethod.Api:\r\n          loading.dismiss();\r\n          this.sendToApi(target, arr);\r\n          return;\r\n        case ExportMethod.FilePdf:\r\n          if (arr.length === 1) {\r\n            return this.getPdf(arr[0]).then(result => {\r\n              this.uiHelpers.downloadFile(result.blob, result.fileName);\r\n              loading.dismiss();\r\n              return;\r\n            });\r\n          } else {\r\n            const zip = new JSZip();\r\n            const getAllBlobs = (items) => {\r\n              const promises: Array<Promise<{ blob: Blob, fileName: string }>> = [];\r\n              for (const item of items) {\r\n                promises.push(this.getPdf(item));\r\n              }\r\n              return Promise.all(promises).then((results) => {\r\n                let counter = 0;\r\n                results.forEach(item => {\r\n                  counter++;\r\n                  zip.file(`${counter}_ ${item.fileName}`, item.blob);\r\n                });\r\n                return;\r\n              });\r\n            };\r\n\r\n            return getAllBlobs(arr).then(() => {\r\n              zip.generateAsync({\r\n                type: \"blob\",\r\n                mimeType:\r\n                  \"application/zip\",\r\n              }).then((blob) => {\r\n                FileSaver.saveAs(blob, `${this.getZipName(arr)}.zip`);\r\n                loading.dismiss();\r\n                return;\r\n              });\r\n            });\r\n\r\n          }\r\n          break;\r\n        case ExportMethod.FileCsv:\r\n          if (arr.length === 1) {\r\n            const data = arr[0];\r\n            FileSaver.saveAs(new Blob([this.getCsv(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, !target.noCsvBom, !target.noCsvQuotedStrings)], { type: \"application/octet-stream;charset=utf-8\" }), `${this.getFileName(data)}.csv`);\r\n            loading.dismiss();\r\n            return;\r\n          } else {\r\n            let counter = 0;\r\n            const zip = new JSZip();\r\n            const next = () => {\r\n              if (counter === arr.length) {\r\n                return;\r\n              }\r\n              const data = arr[counter++];\r\n              const blob = new Blob([this.getCsv(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, !target.noCsvBom, !target.noCsvQuotedStrings)], { type: \"application/octet-stream;charset=utf-8\" });\r\n              zip.file(`${this.getFileName(data)}.csv`, blob);\r\n              next();\r\n            };\r\n\r\n            next();\r\n            zip.generateAsync({\r\n              type: \"blob\",\r\n              mimeType:\r\n                \"application/zip\",\r\n            }).then((blob) => {\r\n              FileSaver.saveAs(blob, `${this.getZipName(arr)}.zip`);\r\n              loading.dismiss();\r\n              return;\r\n            });\r\n          }\r\n          break;\r\n        case ExportMethod.FileExcel:\r\n          if (arr.length === 1) {\r\n            const data = arr[0];\r\n            ExcelHelpers.export(target.getExportData(data, this.schemeId), this.getFileName(data)).then(() => {\r\n              loading.dismiss();\r\n              return;\r\n            });\r\n          } else if (arr.length > 1) {\r\n            const tablesData = [];\r\n            const next = () => {\r\n              if (tablesData.length === arr.length) {\r\n                return;\r\n              }\r\n              const data = arr[tablesData.length];\r\n              tablesData.push({\r\n                tableData: target.getExportData(data, this.schemeId),\r\n                fileName: this.getFileName(data),\r\n              });\r\n              next();\r\n            };\r\n\r\n            next();\r\n            ExcelHelpers.exportMany(tablesData, this.getZipName(arr)).then(() => {\r\n              loading.dismiss();\r\n              return;\r\n            });\r\n          }\r\n          break;\r\n          case ExportMethod.FileText:\r\n            if (arr.length === 1) {\r\n              const data = arr[0];\r\n              FileSaver.saveAs(new Blob([this.getText(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, target.formatAsText)], { type: \"application/octet-stream;charset=utf-8\" }), `${this.getFileName(data)}.txt`);\r\n              loading.dismiss();\r\n              return;\r\n            } else {\r\n              let counter = 0;\r\n              const zip = new JSZip();\r\n              const next = () => {\r\n                if (counter === arr.length) {\r\n                  return;\r\n                }\r\n                const data = arr[counter++];\r\n                const blob = new Blob([this.getText(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, target.formatAsText)], { type: \"application/octet-stream;charset=utf-8\" });\r\n                zip.file(`${this.getFileName(data)}.txt`, blob);\r\n                next();\r\n              };\r\n              next();\r\n              zip.generateAsync({\r\n                type: \"blob\",\r\n                mimeType:\r\n                  \"application/zip\",\r\n              }).then((blob) => {\r\n                FileSaver.saveAs(blob, `${this.getZipName(arr)}.zip`);\r\n                loading.dismiss();\r\n                return;\r\n              });\r\n            }\r\n            break;\r\n        case ExportMethod.CopyCsv:\r\n          if (arr.length === 1) {\r\n            const data = arr[0];\r\n            this.copyToClipboard(this.getCsv(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, !target.noCsvBom, !target.noCsvQuotedStrings));\r\n            loading.dismiss();\r\n            return;\r\n          } else if (arr.length > 1) {\r\n            let counter = 0;\r\n            let csv = !target.noCsvBom ? \"\\uFEFF\" : \"\";\r\n            const next = () => {\r\n              if (counter === arr.length) {\r\n                return;\r\n              }\r\n              const data = arr[counter++];\r\n              csv += `${this.getFileName(data)}\\r\\n`;\r\n              csv += this.getCsv(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, false, !target.noCsvQuotedStrings) + (counter < arr.length ? \"\\r\\n\" : \"\");\r\n              next();\r\n            };\r\n            next();\r\n            this.copyToClipboard(csv);\r\n            loading.dismiss();\r\n            return;\r\n          }\r\n          break;\r\n        case ExportMethod.CopyExcel:\r\n          if (arr.length === 1) {\r\n            const data = arr[0];\r\n            this.copyToClipboard(this.getTabbed(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En));\r\n            loading.dismiss();\r\n            return;\r\n          } else if (arr.length > 1) {\r\n            let counter = 0;\r\n            let tabbed = \"\";\r\n            const next = () => {\r\n              if (counter === arr.length) {\r\n                return;\r\n              }\r\n              const data = arr[counter++];\r\n              tabbed += `${this.getFileName(data)}\\r\\n`;\r\n              tabbed += this.getTabbed(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En) + (counter < arr.length ? \"\\n\" : \"\");\r\n              next();\r\n            };\r\n            next();\r\n            this.copyToClipboard(tabbed);\r\n            loading.dismiss();\r\n            return;\r\n          }\r\n          break;\r\n          case ExportMethod.CopyText:\r\n            if (arr.length === 1) {\r\n              const data = arr[0];\r\n              this.copyToClipboard(this.getText(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, target.formatAsText));\r\n              loading.dismiss();\r\n              return;\r\n            } else if (arr.length > 1) {\r\n              let counter = 0;\r\n              let txt = \"\";\r\n              const next = () => {\r\n                if (counter === arr.length) {\r\n                  return;\r\n                }\r\n                const data = arr[counter++];\r\n                txt += `${this.getFileName(data)}\\r\\n`;\r\n                txt += this.getText(target.getExportData(data, this.schemeId), this.localeId !== LocaleId.En, target.formatAsText) + (counter < arr.length ? \"\\r\\n\" : \"\");\r\n                next();\r\n              };\r\n              next();\r\n              this.copyToClipboard(txt);\r\n              loading.dismiss();\r\n              return;\r\n            }\r\n            break;\r\n        default:\r\n          loading.dismiss();\r\n          this.uiHelpers.showAlert(\"Ei vielä toteutettu\", \"Tätä tiedostotyyppiä ei ole toteutettu.\");\r\n          return;\r\n      }\r\n      loading.dismiss();\r\n      return;\r\n    });\r\n  }\r\n\r\n  /** Navigates to given path and closes possible open modal dialogs. */\r\n  public navigate(path: string) {\r\n    this.$location.path(path);\r\n    this.uiHelpers.dismissAllModals();\r\n  }\r\n\r\n  /**\r\n   * Change target and call event handler.\r\n   * @param targetId - New target id.\r\n   */\r\n  public changeTarget(targetId: string) {\r\n    this.setExportMethod(targetId);\r\n    this.targetId = targetId;\r\n    this.onTargetChange({ targetId });\r\n  }\r\n\r\n  /**\r\n   * Returns the export methods that are available for the accounting target.\r\n   */\r\n  public get exportMethods() {\r\n    // If an accounting target from company settings is selected...\r\n    const target = this.getTarget(this.targetId);\r\n    // ...and available methods for the target are configured\r\n    const availableMethods = [];\r\n    if (target?.availableMethods?.length > 0) {\r\n      // Filter the possible export methods according to the available methods configured for the target.\r\n      availableMethods.push(...target.availableMethods);\r\n    } else {\r\n      // Defaults only\r\n      availableMethods.push(...\r\n        [\r\n          ExportMethod.FilePdf,\r\n          ExportMethod.FileExcel,\r\n          ExportMethod.CopyExcel,\r\n          ExportMethod.FileCsv,\r\n          ExportMethod.CopyCsv\r\n        ]);\r\n    }\r\n    return this._exportMethods.filter(v => availableMethods.indexOf(v.id as ExportMethod) > -1);\r\n  }\r\n\r\n  /**\r\n   * Returns the export method type definition\r\n   * @param exportMethodId export method id\r\n   */\r\n  public getExportMethod(exportMethodId: string) {\r\n    return this.exportMethods.find((x) => x.id === exportMethodId);\r\n  }\r\n\r\n  /**\r\n   * Returns the target definition\r\n   * @param targetId Target id.\r\n   */\r\n  public getTarget(targetId: string) {\r\n    return this.targets.find((x) => x.id === targetId);\r\n  }\r\n\r\n  /**\r\n   * Returns the locale definition\r\n   * @param localeId Locale id.\r\n   */\r\n  public getLocale(localeId: string) {\r\n    return this.locales.find((x) => x.id === localeId);\r\n  }\r\n\r\n  /**\r\n   * Returns the scheme definition.\r\n   * @param schemeId Scheme id.\r\n   */\r\n  public getScheme(schemeId: string) {\r\n    return this.getTarget(this.targetId)?.schemes.find(x => x.id === schemeId);\r\n  }\r\n  private setExportMethod(targetId: string) {\r\n\r\n    // First check if the targetId is one of the \"default\" target options\r\n    if (this.targetOptions[targetId]) {\r\n      this.exportMethod = this.targetOptions[targetId].defaultExportMethod;\r\n      this.schemeId = this.targetOptions[targetId].schemes?.length ? this.targetOptions[targetId].schemes[0].id : null;\r\n      return;\r\n    }\r\n\r\n    const target = this.getTarget(targetId);\r\n    this.schemeId = target.schemes?.length ? target.schemes[0].id : null;\r\n    this.exportMethod = (target.method && target.method !== \"undefined\") ? target.method : target.defaultExportMethod;\r\n  }\r\n\r\n  /**\r\n   * Method for calling onExpandChange event\r\n   * @param close If true, closes the expanding component.\r\n   */\r\n  public expand(close = false) {\r\n    this.onExpandChange({ close });\r\n  }\r\n\r\n  private getFileName(data: AccountingData) {\r\n    return Texts.escapeFileName(`${Translations.get(\"SALAXY.UI_Terms.downLoadableMaterialTypes.accounting\")}_${data.employer.displayName}_${Dates.format((data.period.start ?? \"today\"),\"YYYY_MM\")}`);\r\n  }\r\n\r\n  private getZipName(all: AccountingData[]) { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n    return Texts.escapeFileName(`${Translations.get(\"SALAXY.UI_Terms.downLoadableMaterialTypes.accounting\")}_${Dates.format(\"today\",\"YYYYMMDD\")}`);\r\n  }\r\n\r\n  private getWorkflowMessage() {\r\n    const exportMethod = this.getExportMethod(this.exportMethod);\r\n    if (exportMethod) {\r\n      return exportMethod.workflowMessage;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  private getCsv(data: any[], isFinnish = true, addPrefix: boolean, addQuotes: boolean) {\r\n    const separator = (isFinnish ? \";\" : \",\");\r\n    const rowMapper = this.formatRow(isFinnish, separator, addQuotes);\r\n    const rows = data.map(rowMapper);\r\n    return (addPrefix ? \"\\uFEFF\" : \"\") + rows.join(\"\\r\\n\");\r\n  }\r\n\r\n  private getText(data: any[], isFinnish = true, formatAsText: (data: any[], isFinnish: boolean) => string) {\r\n    if (formatAsText == null) {\r\n      const rowMapper = this.formatRow(isFinnish, \"\\t\", false);\r\n      const rows = data.map(rowMapper);\r\n      return rows.join(\"\\r\\n\");\r\n    }\r\n    else {\r\n      return formatAsText(data, isFinnish);\r\n    }\r\n  }\r\n\r\n  private getPdf(obj): Promise<{ blob: Blob, fileName: string }> {\r\n    const url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(\"accountingReport\")}&template=${encodeURIComponent(\"accountingReport\")}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n    return (this.$http.post(url, { object: obj }, { responseType: \"blob\" }) as Promise<any>).then((response) => {\r\n      if (response.data) {\r\n        return Promise.resolve({ blob: response.data, fileName: response.headers(\"content-disposition\").split(\";\")[1].split(\"filename\")[1].split(\"=\")[1].trim().replace(/\"/g, \"\") });\r\n      }\r\n    }, (error) => {\r\n      console.error(error);\r\n      return Promise.reject(error);\r\n    });\r\n  }\r\n  private getTabbed(data: any[], isFinnish = true) {\r\n    const rowMapper = this.formatRow(isFinnish, \"\\t\");\r\n    const rows = data.map(rowMapper);\r\n    return rows.join(\"\\n\");\r\n  }\r\n\r\n  private formatRow(isFinnish: boolean, separator: string, addQuotes = true) {\r\n    const fieldMapper = this.formatField(isFinnish, addQuotes);\r\n    return (row) => {\r\n      return row.map(fieldMapper).join(separator);\r\n    };\r\n  }\r\n\r\n  private formatField(isFinnish: boolean, addQuotes = true) {\r\n    return (value) => {\r\n      if (value == null) { // we want to catch anything null-ish, hence just == not ===\r\n        return \"\";\r\n      }\r\n      if (typeof (value) === \"number\") {\r\n        if (isFinnish) {\r\n          return value.toString().replace(\".\", \",\");\r\n        }\r\n        return value;\r\n      }\r\n      if (typeof (value) === \"boolean\") {\r\n        return (value ? \"TRUE\" : \"FALSE\");\r\n      }\r\n      if (typeof (value) === \"string\") {\r\n        if (addQuotes) {\r\n          return \"\\\"\" + value.replace(/\"/g, \"\\\"\\\"\") + \"\\\"\";\r\n        }\r\n        return value;\r\n      }\r\n      if (typeof (value) === \"object\") {\r\n        if (value instanceof Date) {\r\n          if (isFinnish) {\r\n            return Dates.format(value,\"D.M.YYYY\");\r\n          } else {\r\n            return Dates.format(value,\"YYYY-MM-DD\");\r\n          }\r\n        } else {\r\n          if (addQuotes) {\r\n            return \"\\\"\" + JSON.stringify(value).replace(/\"/g, \"\\\"\\\"\") + \"\\\"\";\r\n          }\r\n          return JSON.stringify(value);\r\n        }\r\n      }\r\n      return JSON.stringify(value);\r\n    };\r\n  }\r\n\r\n  private copyToClipboard(data: string) {\r\n    (navigator as any).clipboard.writeText(data);\r\n  }\r\n\r\n  private async sendToApi(target: AccountingTargetSettings, arr: any[]): Promise<void> {\r\n    if(!target.channel || target.channel === \"undefined\") {\r\n      return;\r\n    }\r\n\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const items = [];\r\n    for(const accountingData of arr) {\r\n      items.push( {\r\n        accountingData,\r\n        preview: (await this.$http.post(this.getAccountingDataUrl(target, \"accountingPreview\"), accountingData, { responseType: \"json\", }))?.data,\r\n        result: \"\",\r\n        error: \"\",\r\n      });\r\n    }\r\n\r\n    loading.dismiss();\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/report/modals/PostAccountingData.html\", items,{\r\n      postData: (item) => {\r\n        item.isPosting = true;\r\n        this.$http.post(this.getAccountingDataUrl(target, \"accounting\"), item.accountingData, { responseType: \"json\", })\r\n          .then((result) => {\r\n            item.isPosting = false;\r\n            item.error = \"\";\r\n            item.result = this.getAccountingDataResult(target, result);\r\n          })\r\n          .catch( (err) => {\r\n            item.isPosting = false;\r\n            item.error =  this.getAccountingDataError(target, err);\r\n            item.result = \"\";\r\n          });\r\n      },\r\n      previewTemplateUrl: this.getAccountingDataPreviewTemplate(target),\r\n    },\"lg\");\r\n  }\r\n\r\n  private getAccountingDataUrl(target: AccountingTargetSettings, path: string): string {\r\n    const accessToken = this.ajax.getCurrentToken();\r\n    const url = `${Configs.current.integrationsServer}/${AccountingReportToolsController.channelBasePaths[target.channel]}/${path}`;\r\n    return `${url}?accessToken=${accessToken}&accountingTargetId=${target.id}`;\r\n  }\r\n\r\n  private getAccountingDataError(target: AccountingTargetSettings, error: any) {\r\n    if (error?.data?.detail) {\r\n      return Translations.get(\"SALAXY.UI_Terms.error\") +\", \" + error.data.detail;\r\n    }\r\n    if (error.data) {\r\n      return  Translations.get(\"SALAXY.UI_Terms.error\") + \", \" + error.data.status + \"-\" + error.data.title;\r\n    }\r\n    return Translations.get(\"SALAXY.UI_Terms.error\");\r\n  }\r\n\r\n  private getAccountingDataResult(target: AccountingTargetSettings, result: any) {\r\n    switch(target.channel) {\r\n      case AccountingChannel.VismaFivaldi:\r\n        return Translations.get(\"SALAXY.UI_Terms.ok\") + \", VismaFivaldi: \" + result.data.fivaldiVoucherNumber;\r\n      default:\r\n        return Translations.get(\"SALAXY.UI_Terms.ok\");\r\n    }\r\n  }\r\n\r\n  private getAccountingDataPreviewTemplate(target: AccountingTargetSettings) {\r\n    switch(target.channel) {\r\n      case AccountingChannel.VismaFivaldi:\r\n        return \"salaxy-components/report/modals/FivaldiPreview.html\";\r\n      default:\r\n        return \"\";\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Absences, ApiListItem, Calculations, Calculation, Dates, irepr, IrEarningsPayments, AbsenceCauseCode } from \"@salaxy/core\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { Calculator2019Controller } from \"../../controllers\";\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for user interface of Earnings Payment Report (\"Tulorekisteri-ilmoitus\").\r\n */\r\nexport class IrEarningsPaymentCrudController extends ApiCrudObjectController<irepr.EarningsPayment, any> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"IrEarningsPayments\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"Calculations\",\r\n    \"Absences\",\r\n    \"SessionService\"\r\n  ];\r\n\r\n  /** Calculation controller  */\r\n  public calcController: Calculator2019Controller;\r\n\r\n  private _calculation: Calculation;\r\n  private _calculationId: string;\r\n\r\n  constructor(\r\n    private fullApi: IrEarningsPayments,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private calcApi: Calculations,\r\n    private absencesApi: Absences,\r\n    private session: SessionService,\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"irepr\",\r\n      detailsUrl: this.detailsUrl || \"/irepr/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/IrEpr.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Gets calculation */\r\n  public get calculation() {\r\n    if (this.current?.info?.calculationId != null) {\r\n      this.calculationId = this.current.info.calculationId;\r\n    }\r\n    return this._calculation;\r\n  }\r\n\r\n  /**\r\n   * Sets calculation and if it is different then starts the loading of the EarningsPayment object to that calculation.\r\n   */\r\n  public set calculation(value: Calculation) {\r\n    if (value == null || value.id == null) {\r\n      this._calculation = null;\r\n      this._calculationId = null;\r\n      return;\r\n    }\r\n    if (this.calculationId === value?.id) {\r\n      return;\r\n    }\r\n    this._calculation = value;\r\n    this._calculationId = value.id;\r\n    if (this.current?.info?.calculationId !== value.id) {\r\n      this.setStatus(this.calcApi.getEpr(value.id)).then((data) => {\r\n        this.setCurrent(data);\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Gets calculation */\r\n  public get calculationId(): string {\r\n    return this._calculation?.id ?? this._calculationId;\r\n  }\r\n\r\n  /**\r\n   * Sets calculation and if it is different then starts the loading of the EarningsPayment object to that calculation.\r\n   */\r\n  public set calculationId(value: string) {\r\n    if (value == null) {\r\n      this._calculation = null;\r\n      this._calculationId = null;\r\n      return;\r\n    }\r\n    if (this.calculationId === value) {\r\n      return;\r\n    }\r\n    this._calculation = null;\r\n    this._calculationId = value;\r\n    this.calcApi.getSingle(value).then((calc) => {\r\n      this._calculation = calc;\r\n    });\r\n    if (this.current?.info?.calculationId !== value) {\r\n      this.setStatus(this.calcApi.getEpr(value)).then((data) => {\r\n        this.setCurrent(data);\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Returns true if the report can be canceled. */\r\n  public get isCancellable() {\r\n    return this.current && this.getLatestNonErrorReportLogEntry()?.eventType === irepr.ReportLogEventType.Sent;\r\n  }\r\n\r\n  /** Returns true if the item is read-only */\r\n  public get isReadOnly(): boolean {\r\n    return super.isReadOnly || (!(this as any).tempShowEditInNonAdminMode && !this.session.isInRole(\"admin\"));\r\n  }\r\n\r\n  /** Save resource */\r\n  public saveChanges(): Promise<irepr.EarningsPayment> {\r\n    if (this._calculation && this.calcController && this.calcController.hasChanges) {\r\n      return this.calcApi.saveIr(this._calculation).then((calc) => {\r\n        this._calculation = calc;\r\n        return this.calcApi.convertToEpr(this._calculation).then((epr) => {\r\n          this.current.deliveryData.reports[0].transactions = epr.deliveryData.reports[0].transactions;\r\n          return this.save().then(() => {\r\n            this.calcController.setCurrent(this._calculation);\r\n            return this.current;\r\n          });\r\n        });\r\n      });\r\n    } else {\r\n      return this.save().then(() => {\r\n        return this.current;\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Send to incomes register. */\r\n  public sendToIncomesRegister(startAt: Date): Promise<irepr.EarningsPayment> {\r\n    return this.saveChanges().then((epr) => {\r\n      if (epr.validation.isValid) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.EarningsPaymentComponent.common.loaderTextSending\");\r\n        const aso: irepr.IrApiScheduleObject = {\r\n          id: this.current.id,\r\n          startAt: startAt ? JSON.stringify(startAt).replace(/\"/g, \"\") : null,\r\n          action: irepr.IrScheduleAction.Send\r\n        };\r\n        return this.fullApi.sendSchedule(aso).then(() => {\r\n          return this.reloadFromServer().then(() => {\r\n            loader.dismiss();\r\n            return this.current;\r\n          });\r\n        });\r\n      } else {\r\n        this.uiHelpers.showAlert(\"SALAXY.NG1.EarningsPaymentComponent.common.sendFailureTitle\", \"SALAXY.NG1.EarningsPaymentComponent.common.validationErrorText\");\r\n        return this.current;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Get latest incomes register report log entry */\r\n  private getLatestNonErrorReportLogEntry(): irepr.ReportLogEntry {\r\n    if (this.current.reportLog != null) {\r\n      const nonErrorEntries = this.current.reportLog.filter((x) => x.eventType !== irepr.ReportLogEventType.Error);\r\n      if (nonErrorEntries.length > 0) {\r\n        return nonErrorEntries[nonErrorEntries.length - 1];\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Sends cancel request to incomes register */\r\n  public cancelToIncomesRegister(): Promise<irepr.EarningsPayment> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.EarningsPaymentComponent.common.loaderTextCanceling\");\r\n    const aso: irepr.IrApiScheduleObject = {\r\n      id: this.current.id,\r\n      action: irepr.IrScheduleAction.Cancel\r\n    };\r\n    return this.fullApi.sendSchedule(aso).then(() => {\r\n      return this.reloadFromServer().then(() => {\r\n        loader.dismiss();\r\n        return this.current;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Opens sheculing dialog and sends scheduling after successful dialog close */\r\n  public openSetScheduleDialog() {\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/report/modals/IrScheduleSendDialog.html\", {\r\n      startAt: new Date()\r\n    }, {})\r\n      .then((dialog) => {\r\n        if (dialog.result === \"ok\") {\r\n          return this.sendToIncomesRegister(dialog.item.startAt);\r\n        } else {\r\n          return this.current;\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Remove Incomes register queue item */\r\n  public removeIrQueueItem(): Promise<irepr.EarningsPayment> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.EarningsPaymentComponent.common.loaderTextRemoving\");\r\n    return this.fullApi.removeIrQueueItem(this.current.id).then(() => {\r\n      return this.reloadFromServer().then(() => {\r\n        loader.dismiss();\r\n        return this.current;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Opens a dialog for importing absences. */\r\n  public importAbsences() {\r\n    this.absencesApi.getForEmployment(this.calculation.worker.employmentId).then((workerAbsences) => {\r\n      this.uiHelpers.openEditDialog(\"salaxy-components/report/modals/IrImportAbsencesDialog.html\", workerAbsences, {}).then((dialog) => {\r\n        if (dialog.result === \"ok\" && workerAbsences.periods) {\r\n          const selectedAbsences = workerAbsences.periods.filter((x) => (x as any).selected);\r\n          if (selectedAbsences.length > 0) {\r\n            const report = this.current.deliveryData.reports[0];\r\n            report.absence = report.absence ?? {};\r\n            let absencesStartDate = null;\r\n            let absencesEndDate = null;\r\n            selectedAbsences.forEach((period) => {\r\n              if (period.isPaid) {\r\n                report.absence.paidAbsence = report.absence.paidAbsence ?? {};\r\n                report.absence.paidAbsence.paidAbsencePeriods = report.absence.paidAbsence.paidAbsencePeriods ?? [];\r\n                report.absence.paidAbsence.paidAbsencePeriods.push({\r\n                  startDate : period.period?.start,\r\n                  endDate : period.period?.end,\r\n                  causeCode : this.getPaidAbsenceCauseCode(period.causeCode),\r\n                  absenceDays : period.period?.daysCount,\r\n                  amount : period.amount,\r\n                });\r\n              } else {\r\n                report.absence.unpaidAbsence = report.absence.unpaidAbsence ?? {};\r\n                report.absence.unpaidAbsence.unpaidAbsencePeriods = report.absence.unpaidAbsence.unpaidAbsencePeriods ?? [];\r\n                report.absence.unpaidAbsence.unpaidAbsencePeriods.push({\r\n                  startDate : period.period?.start,\r\n                  endDate : period.period?.end,\r\n                  causeCode : this.getUnpaidAbsenceCauseCode(period.causeCode),\r\n                  absenceDays : period.period?.daysCount,\r\n                });\r\n              }\r\n              if (!absencesStartDate || ( period.period && period.period.start && Dates.asDate(absencesStartDate) > Dates.asDate(period.period.start))) {\r\n                absencesStartDate = period.period?.start;\r\n              }\r\n              if (!absencesEndDate || ( period.period && period.period.end && Dates.asDate(absencesEndDate) < Dates.asDate(period.period.end))) {\r\n                absencesEndDate = period.period?.end;\r\n              }\r\n            });\r\n            report.absence.absenceRepStartDate = absencesStartDate;\r\n            report.absence.absenceRepEndDate = absencesEndDate;\r\n          }\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n\r\n  /** Checks if the IR report is modified. */\r\n  public isIrModified(item: ApiListItem): boolean {\r\n    return item.flags.some((x) => x === \"modified\");\r\n  }\r\n\r\n  /** Checks if the Epr is delayed. */\r\n  public isDelayed(item: ApiListItem): boolean {\r\n    if (!item.data.firstDeliveredAt) {\r\n      const officialDate = Dates.add(item.salaryDate,5, \"day\");\r\n      const expiresAt = Dates.addWorkdays(officialDate, 0);\r\n      const today = Dates.asDate(\"today\");\r\n      return today > expiresAt;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  private reloadFromServer(): Promise<irepr.EarningsPayment> {\r\n    return this.setStatus(this.api.getSingle(this.current.id)).then((data) => {\r\n      this.setCurrent(data);\r\n      return data;\r\n    });\r\n  }\r\n\r\n  private getUnpaidAbsenceCauseCode(causeCode: AbsenceCauseCode): irepr.UnpaidAbsenceCauseCode {\r\n    switch (causeCode) {\r\n      case AbsenceCauseCode.Illness:\r\n        return irepr.UnpaidAbsenceCauseCode.Illness;\r\n      case AbsenceCauseCode.PartTimeSickLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.PartTimeSickLeave;\r\n      case AbsenceCauseCode.ParentalLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.ParentalLeave;\r\n      case AbsenceCauseCode.SpecialMaternityLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.SpecialMaternityLeave;\r\n      case AbsenceCauseCode.Rehabilitation:\r\n        return irepr.UnpaidAbsenceCauseCode.Rehabilitation;\r\n      case AbsenceCauseCode.ChildIllness:\r\n        return irepr.UnpaidAbsenceCauseCode.ChildIllness;\r\n      case AbsenceCauseCode.PartTimeChildCareLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.PartTimeChildCareLeave;\r\n      case AbsenceCauseCode.Training:\r\n        return irepr.UnpaidAbsenceCauseCode.Training;\r\n      case AbsenceCauseCode.JobAlternationLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.JobAlternationLeave;\r\n      case AbsenceCauseCode.StudyLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.StudyLeave;\r\n      case AbsenceCauseCode.IndustrialAction:\r\n        return irepr.UnpaidAbsenceCauseCode.IndustrialAction;\r\n      case AbsenceCauseCode.InterruptionInWorkProvision:\r\n        return irepr.UnpaidAbsenceCauseCode.InterruptionInWorkProvision;\r\n      case AbsenceCauseCode.LeaveOfAbsence:\r\n        return irepr.UnpaidAbsenceCauseCode.LeaveOfAbsence;\r\n      case AbsenceCauseCode.MilitaryRefresherTraining:\r\n        return irepr.UnpaidAbsenceCauseCode.MilitaryRefresherTraining;\r\n      case AbsenceCauseCode.MilitaryService:\r\n        return irepr.UnpaidAbsenceCauseCode.MilitaryService;\r\n      case AbsenceCauseCode.LayOff:\r\n        return irepr.UnpaidAbsenceCauseCode.LayOff;\r\n      case AbsenceCauseCode.ChildCareLeave:\r\n        return irepr.UnpaidAbsenceCauseCode.ChildCareLeave;\r\n      case AbsenceCauseCode.Other:\r\n      default:\r\n        return irepr.UnpaidAbsenceCauseCode.Other;\r\n    }\r\n  }\r\n\r\n  private getPaidAbsenceCauseCode(causeCode: AbsenceCauseCode): irepr.PaidAbsenceCauseCode {\r\n    switch (causeCode) {\r\n      case AbsenceCauseCode.Illness:\r\n        return irepr.PaidAbsenceCauseCode.Illness;\r\n      case AbsenceCauseCode.PartTimeSickLeave:\r\n        return irepr.PaidAbsenceCauseCode.PartTimeSickLeave;\r\n      case AbsenceCauseCode.ParentalLeave:\r\n        return irepr.PaidAbsenceCauseCode.ParentalLeave;\r\n      case AbsenceCauseCode.SpecialMaternityLeave:\r\n        return irepr.PaidAbsenceCauseCode.SpecialMaternityLeave;\r\n      case AbsenceCauseCode.Rehabilitation:\r\n        return irepr.PaidAbsenceCauseCode.Rehabilitation;\r\n      case AbsenceCauseCode.ChildIllness:\r\n        return irepr.PaidAbsenceCauseCode.ChildIllness;\r\n      case AbsenceCauseCode.PartTimeChildCareLeave:\r\n        return irepr.PaidAbsenceCauseCode.PartTimeChildCareLeave;\r\n      case AbsenceCauseCode.Training:\r\n        return irepr.PaidAbsenceCauseCode.Training;\r\n      case AbsenceCauseCode.LeaveOfAbsence:\r\n        return irepr.PaidAbsenceCauseCode.LeaveOfAbsence;\r\n      case AbsenceCauseCode.MilitaryRefresherTraining:\r\n        return irepr.PaidAbsenceCauseCode.MilitaryRefresherTraining;\r\n      case AbsenceCauseCode.MidWeekHoliday:\r\n        return irepr.PaidAbsenceCauseCode.MidWeekHoliday;\r\n      case AbsenceCauseCode.AccruedHoliday:\r\n        return irepr.PaidAbsenceCauseCode.AccruedHoliday;\r\n      case AbsenceCauseCode.OccupationalAccident:\r\n        return irepr.PaidAbsenceCauseCode.OccupationalAccident;\r\n      case AbsenceCauseCode.AnnualLeave:\r\n        return irepr.PaidAbsenceCauseCode.AnnualLeave;\r\n      case AbsenceCauseCode.PartTimeAbsenceDueToRehabilitation:\r\n        return irepr.PaidAbsenceCauseCode.PartTimeAbsenceDueToRehabilitation;\r\n      case AbsenceCauseCode.Other:\r\n      default:\r\n        return irepr.PaidAbsenceCauseCode.Other;\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiListItem, Dates, irpsr, IrPayerSummaries } from \"@salaxy/core\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for user interface of Payer Summary Report (\"Tulorekisteri-ilmoitus\").\r\n */\r\nexport class IrPayerSummaryCrudController extends ApiCrudObjectController<irpsr.PayerSummary, any> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"IrPayerSummaries\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"SessionService\"\r\n  ];\r\n\r\n  constructor(\r\n    private fullApi: IrPayerSummaries,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private session: SessionService,\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"irpsr\",\r\n      detailsUrl: this.detailsUrl || \"/irpsr/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/IrPsr.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Returns true if the report can be canceled. */\r\n  public get isCancellable() {\r\n    return this.current && this.getLatestNonErrorReportLogEntry()?.eventType === irpsr.ReportLogEventType.Sent;\r\n  }\r\n\r\n  /** Returns true if the item is read-only */\r\n  public get isReadOnly(): boolean {\r\n    return super.isReadOnly || (!(this as any).tempShowEditInNonAdminMode && !this.session.isInRole(\"admin\"));\r\n  }\r\n\r\n\r\n  /** Send to incomes register  */\r\n  public sendToIncomesRegister(startAt: Date): Promise<irpsr.PayerSummary> {\r\n    return this.save().then((psr) => {\r\n      if (psr.validation.isValid) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayerSummaryComponent.common.loaderTextSending\");\r\n        const aso: irpsr.IrApiScheduleObject = {\r\n          id: this.current.id,\r\n          startAt: startAt ? JSON.stringify(startAt).replace(/\"/g, \"\"): null,\r\n          action: irpsr.IrScheduleAction.Send\r\n        };\r\n\r\n        return this.fullApi.sendSchedule(aso).then(() => {\r\n          return this.reloadFromServer().then(() => {\r\n            loader.dismiss();\r\n            return this.current;\r\n          });\r\n        });\r\n\r\n      } else {\r\n        this.uiHelpers.showAlert(\"SALAXY.NG1.PayerSummaryComponent.common.sendFailureTitle\", \"SALAXY.NG1.PayerSummaryComponent.common.validationErrorText\");\r\n        return this.current;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Get latest incomes register report log entry */\r\n  private getLatestNonErrorReportLogEntry(): irpsr.ReportLogEntry {\r\n    if (this.current.reportLog != null) {\r\n      const nonErrorEntries = this.current.reportLog.filter((x) => x.eventType !== irpsr.ReportLogEventType.Error);\r\n      if (nonErrorEntries.length > 0) {\r\n        return nonErrorEntries[nonErrorEntries.length - 1];\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Sends cancel request to incomes register */\r\n  public cancelToIncomesRegister(): Promise<irpsr.PayerSummary> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayerSummaryComponent.common.loaderTextCanceling\");\r\n    const aso: irpsr.IrApiScheduleObject = {\r\n      id: this.current.id,\r\n      action: irpsr.IrScheduleAction.Cancel\r\n    };\r\n    return this.fullApi.sendSchedule(aso).then(() => {\r\n      return this.reloadFromServer().then( () => {\r\n        loader.dismiss();\r\n        return this.current;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Opens sheculing dialog and sends scheduling after successful dialog close */\r\n  public openSetScheduleDialog(): Promise<irpsr.PayerSummary>  {\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/report/modals/IrScheduleSendDialog.html\", {\r\n      startAt: new Date() }, {}).then((dialog) => {\r\n        if (dialog.result === \"ok\") {\r\n          return this.sendToIncomesRegister(dialog.item.startAt);\r\n        } else {\r\n          return this.current;\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Remove Incomes register queue item */\r\n  public removeIrQueueItem(): Promise<irpsr.PayerSummary> {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.PayerSummaryComponent.common.loaderTextRemoving\");\r\n    return this.fullApi.removeIrQueueItem(this.current.id).then(() => {\r\n      return this.reloadFromServer().then(() => {\r\n        loader.dismiss();\r\n        return this.current;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Checks if the IR report is modified. */\r\n  public isIrModified(item: ApiListItem): boolean {\r\n    return item.flags.some( (x) => x === \"modified\");\r\n  }\r\n\r\n  /** Checks if the Psr is delayed. */\r\n  public isDelayed(item: ApiListItem): boolean {\r\n    if (!item.data.firstDeliveredAt) {\r\n      const officialDate = Dates.add(Dates.add(item.logicalDate,1, \"month\"),4, \"day\");\r\n      const expiresAt = Dates.addWorkdays(officialDate, 0); // the day or next work day\r\n      const today = Dates.asDate(\"today\");\r\n      return today > expiresAt;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  private reloadFromServer(): Promise<irpsr.PayerSummary> {\r\n    return this.setStatus(this.api.getSingle(this.current.id)).then((data) => {\r\n      this.setCurrent(data);\r\n      return data;\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {  Report, reportPartial, ReportsLogic, ReportType } from \"@salaxy/core\";\r\n\r\nimport { ReportsService, SessionService } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for fetching, showing and later generating Reports\r\n */\r\nexport class ReportsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"ReportsService\",\r\n    \"SessionService\",\r\n  ];\r\n\r\n  /**\r\n   * Current report type for this controller. Default for the getReports() method.\r\n   */\r\n  public reportType: ReportType;\r\n\r\n  /**\r\n   * When using getReportHtmlById(), the HTML is set here.\r\n   * Also contains a spinner for loading and sets an alert if there is a problem.\r\n   */\r\n  public reportHtml;\r\n\r\n  /**\r\n   * Static instance of getReportTypes() to avoid a $digest problem that occured when calling getReportTypes() directly from the view.\r\n   * HACK: This may not work in a scenario where Controller is created before the Session.\r\n   */\r\n  public types = this.getReportTypes();\r\n\r\n  constructor(\r\n    private reportsService: ReportsService,\r\n    private sessionService: SessionService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit = () => {\r\n    //\r\n  };\r\n\r\n  /**\r\n   * Gets a list of reports (metadata only) filtered by a report type.\r\n   * @param type - Type of report. See type (string enumeration) for possible values. Default is the property reportType.\r\n   */\r\n  public getReports(type: ReportType = this.reportType): Report[] | Promise<Report[]> {\r\n    return this.reportsService.getReports(type);\r\n  }\r\n\r\n  /**\r\n   * Gets a list of available report types for the current user.\r\n   * TODO: This method is still under construction.\r\n   */\r\n  public getReportTypes() {\r\n    // TODO: Generalize this role logic and merge with moveToCore\r\n    const allReportTypes = ReportsLogic.getReportTypes();\r\n    const filtered = allReportTypes.filter((x) => this.sessionService.isInSomeRole(x.roles));\r\n    return filtered;\r\n  }\r\n\r\n  /**\r\n   * Gets an HTML report based on Calculation ID, runs it through $sce\r\n   * and sets it as reportHtml.\r\n   * @param reportType - Type of the report to fetch. See the HtmlReportType enumeration for possible values.\r\n   * @param calculationId - GUID for the calculation\r\n   * @returns A Promise with result HTML - already run through $sce.\r\n   */\r\n  public getReportHtmlById(reportType: reportPartial, calculationId: string): Promise<any> {\r\n    this.reportHtml = \"<salaxy-spinner></salaxy-spinner>\";\r\n    return this.reportsService.getReportHtmlById(reportType, calculationId).then((html) => {\r\n      this.reportHtml = html;\r\n      return html;\r\n    }).catch((reason) => {\r\n      this.reportHtml = `<div class=\"alert alert-danger\"><strong>Error in fetching report</strong><pre>${angular.toJson(reason)}</pre></div>`;\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Calculations } from \"@salaxy/core\";\r\n\r\nimport { InvoicesService, ReportsService, SessionService, UiHelpers } from \"../../services\";\r\n\r\nimport { CalculationCrudController } from \"../calc\";\r\n\r\n/**\r\n * The new ApiCrudObject type of CRUD controller for the calculation reports.\r\n * Note that SalaryRepots does not have separate CRUD methods, but instead\r\n * the CRUD structure is based on Calculations (extends CalculationCrudController).\r\n */\r\nexport class SalaryReportCrudController extends CalculationCrudController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Calculations\", \"ReportsService\", \"UiHelpers\", \"$location\", \"$routeParams\", \"SessionService\", \"InvoicesService\"];\r\n\r\n  /** Default query options for panel */\r\n  public panelQueryOptions = {\r\n    $filter: \"status eq 'paymentSucceeded'\",\r\n    $top: 5,\r\n    $orderby: \"salaryDate desc\",\r\n  };\r\n  /** Default query options for full list view */\r\n  public queryOptions = {\r\n    $filter: \"status eq 'paymentSucceeded'\",\r\n    $top: 20,\r\n    $orderby: \"salaryDate desc\",\r\n  };\r\n\r\n  constructor(\r\n    calculationsApi: Calculations,\r\n    reportsService: ReportsService,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    sessionService: SessionService,\r\n    protected invoicesService: InvoicesService,\r\n  ) {\r\n    super(calculationsApi, reportsService, uiHelpers, $location, $routeParams, sessionService, invoicesService);\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"reports/salary-reports\",\r\n      detailsUrl: this.detailsUrl || \"/calc/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/SalaryReportsPanel.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Unselect all */\r\n  public unselectAll() {\r\n    if (this.odataController.selectedItems) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n    }\r\n  }\r\n\r\n  /** Select all */\r\n  public selectAll() {\r\n    if (this.odataController.selectedItems && this.odataController.items) {\r\n      this.odataController.selectedItems.splice(0, this.odataController.selectedItems.length);\r\n      this.odataController.selectedItems.push(...this.odataController.items);\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiListItem, ApiValidation, Dates, Reports, Translations } from \"@salaxy/core\";\r\n\r\nimport { WizardService, WizardStep } from \"../../services\";\r\nimport { WizardController } from \"../bases/WizardController\";\r\n\r\n/**\r\n * Provides methods for generating pay certificates.\r\n */\r\nexport class PayCertificateController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"Reports\"];\r\n\r\n  /** Worker for the report */\r\n  public worker: ApiListItem = null;\r\n\r\n  /** Selected workers */\r\n  public selectedWorkers: ApiListItem[] = [];\r\n\r\n  /** Period calculations */\r\n  public periodCalculations: ApiListItem[] = [];\r\n\r\n  /** Validation for the report. */\r\n  public validation: ApiValidation = null;\r\n\r\n  /** Pay certificate wizard configuration */\r\n  public wizardSteps: WizardStep[] = [\r\n    {\r\n      title: Translations.get(\"SALAXY.NG1.PayCertificateComponent.wizard.stepSelectWorkerTitle\"),\r\n      view: \"salaxy-components/report/PayCertificateStep1.html\",\r\n    },\r\n    {\r\n      title: Translations.get(\"SALAXY.NG1.PayCertificateComponent.wizard.stepSelectPeriodCalcsTitle\"),\r\n      view: \"salaxy-components/report/PayCertificateStep2.html\",\r\n    },\r\n    {\r\n      title: Translations.get(\"SALAXY.NG1.PayCertificateComponent.wizard.stepAdditionalInfoTitle\"),\r\n      view: \"salaxy-components/report/PayCertificateStep3.html\",\r\n    },\r\n  ];\r\n\r\n  constructor($scope: angular.IScope, wizardService: WizardService, private reports: Reports) {\r\n    super($scope, wizardService);\r\n  }\r\n\r\n  /**\r\n   * Initialization of the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    this.wizardService.setSteps(this.wizardSteps);\r\n    this.wizardService.activeStepNumber = 1;\r\n  }\r\n\r\n  /** Returns true if goNext is enabled  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.step === 1 && this.selectedWorkers.length === 0) {\r\n          return false;\r\n        }\r\n        if (this.step === 2 && this.periodCalculations.length === 0) {\r\n          return false;\r\n        }\r\n\r\n        return true;\r\n\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible\r\n   */\r\n  public goNext() {\r\n    super.goNext();\r\n    if (this.step === 3) {\r\n      this.validate();\r\n    }\r\n  }\r\n\r\n  /** Selects the worker and advances the workflow */\r\n  public selectWorker(worker: ApiListItem, isSelected: boolean) {\r\n    if (isSelected) {\r\n      this.worker = worker;\r\n      this.selectedWorkers.splice(0, this.selectedWorkers.length);\r\n      this.selectedWorkers.push(this.worker);\r\n      this.periodCalculations = [];\r\n      this.validation = null;\r\n      this.goNext();\r\n    }\r\n  }\r\n\r\n  /** Selects calculations from the period */\r\n  public selectCalculations(items: ApiListItem[], weeks: number) {\r\n\r\n    // go x weeks to past\r\n    let periodStart = Dates.add(\"today\",-1 * weeks, \"week\");\r\n    // set to monday of that week\r\n    periodStart = Dates.startEnd(periodStart, \"start-week\");\r\n\r\n    this.periodCalculations.splice(0, this.periodCalculations.length);\r\n    for (const item of items) {\r\n      if (Dates.asDate(item.salaryDate) >= periodStart) {\r\n        this.periodCalculations.push(item);\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Selects calculations from the period */\r\n  public unselectCalculations() {\r\n    this.periodCalculations.splice(0, this.periodCalculations.length);\r\n  }\r\n\r\n  /**\r\n   * Returns the url for downloading pdf.\r\n   * @param inline If true will open the pdf. The default is false: download as attachment.\r\n   * @returns URL for downloading the report.\r\n   */\r\n  public getDownloadPdfUrl(inline = false): string {\r\n    if (\r\n      !this.worker ||\r\n      !this.periodCalculations ||\r\n      this.periodCalculations.length === 0) {\r\n      return null;\r\n    }\r\n    return this.reports.getPayCertificatePdfUrl(this.worker.otherId, this.periodCalculations.map( (x) => x.id), inline);\r\n  }\r\n\r\n  /**\r\n   * Validates the report server side.\r\n   */\r\n  public validate() {\r\n    this.validation = null;\r\n    if (\r\n      !this.worker ||\r\n      !this.periodCalculations ||\r\n      this.periodCalculations.length === 0) {\r\n      return;\r\n    }\r\n    this.reports.validatePayCertificate(this.worker.otherId, this.periodCalculations.map( (x) => x.id)).then((result: ApiValidation) => {\r\n      this.validation = result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Start new wizard\r\n   */\r\n  public startNew() {\r\n    this.step = 1;\r\n    this.worker = null;\r\n    this.selectedWorkers.splice(0, this.selectedWorkers.length);\r\n    this.periodCalculations = [];\r\n    this.validation = null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CalculationListItem, Configs, Datasets, DatasetStatus, Dates, PeriodType, PeriodDateKind, WorkerListItem, PayrollListItem, DatasetType, ApiListItem, Avatar } from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\n\r\n/** Report template */\r\ninterface Template {\r\n  /** Template id */\r\n  id: string;\r\n  /** Owner of the template */\r\n  owner: string;\r\n  /** Template label */\r\n  label: string;\r\n  /** Template configuration*/\r\n  config: {\r\n    columnState?: any,\r\n    filterModel?: any,\r\n    columnGroupState?: any,\r\n    isPivotMode?: boolean,\r\n  };\r\n  /** Boolean indicating if the template is a user template */\r\n  isReadOnly: boolean;\r\n  /** Owners avatar */\r\n  avatar?: Avatar;\r\n}\r\n\r\n/**\r\n * Controller base class for configurable grid reports.\r\n */\r\nexport abstract class ConfigurableGridReportControllerBase<TData> implements angular.IController {\r\n\r\n  /** Usecase uri for report templates */\r\n  public abstract usecaseUri: string;\r\n\r\n  /** Current grid options. */\r\n  public abstract gridOptions: any;\r\n\r\n  /** ID for the element containing grid. */\r\n  public abstract gridElmentId;\r\n\r\n  /** default templates */\r\n  protected abstract defaultTemplates: Template[];\r\n\r\n  /** Current data */\r\n  public data: TData;\r\n\r\n  /** Current grid. */\r\n  public grid: any;\r\n\r\n  /** Options for data query. */\r\n  public queryOptions:\r\n    {\r\n      period: {\r\n        /** Period type for the query. */\r\n        periodType: PeriodType,\r\n        /** Ref date for the period. */\r\n        refDate?: string,\r\n        /** End date for the custom period. */\r\n        endDate?: string,\r\n        /** Period date kind */\r\n        periodDateKind: PeriodDateKind,\r\n        /** Selected workers */\r\n        selectedWorkers: WorkerListItem[],\r\n      },\r\n      calculations: CalculationListItem[],\r\n      payrolls: PayrollListItem[],\r\n    } = {\r\n      period: {\r\n        periodType: PeriodType.Month,\r\n        refDate: Dates.format(Dates.add(\"today\",-1, \"month\"),\"YYYY-MM-01\"),\r\n        endDate: null,\r\n        periodDateKind: PeriodDateKind.SalaryDate,\r\n        selectedWorkers: [],\r\n      },\r\n      calculations: [],\r\n      payrolls: [],\r\n  };\r\n\r\n  /** Current report template */\r\n  public templateId: string;\r\n\r\n  /** All loaded templates */\r\n  public templates: Template[] = [];\r\n\r\n  constructor(protected datasets: Datasets, protected uiHelpers: UiHelpers, protected sessionService: SessionService) {\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    const getSalaxyGridModule = (): Promise<any> => {\r\n      // Support both esm and umd builds...\r\n      return Promise.resolve(Configs.global.agGrid);\r\n    };\r\n\r\n    getSalaxyGridModule().then((agGridModule) => {\r\n      const agGrid = agGridModule;\r\n      const AG_GRID_LICENCE_KEY = \"CompanyName=Suomen Palkanlaskenta Oy,LicensedGroup=Palkkaus.fi,LicenseType=MultipleApplications,LicensedConcurrentDeveloperCount=3,LicensedProductionInstancesCount=1,AssetReference=AG-012462,ExpiryDate=17_December_2021_[v2]_MTYzOTY5OTIwMDAwMA==5d6e41ff68f667b432fc0424ad42ca1d\";\r\n      agGrid.LicenseManager.setLicenseKey(AG_GRID_LICENCE_KEY);\r\n      if (!agGrid.ModuleRegistry.getRegisteredModules().length) {\r\n        agGrid.ModuleRegistry.registerModules(agGrid.AllModules);\r\n      }\r\n\r\n      const eGridDiv = document.querySelector(this.gridElmentId);\r\n      this.grid = new agGrid.Grid(eGridDiv, this.gridOptions);\r\n\r\n      this.loadTemplates();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns the template definition\r\n   * @param templateId Template id.\r\n   */\r\n  public getTemplate(templateId: string) {\r\n    return this.templates.find((x) => x.id === templateId);\r\n  }\r\n\r\n  /**\r\n   * Selects the template to show\r\n   * @param templateId The selected template.\r\n   */\r\n  public selectTemplate(templateId: any) {\r\n    this.templateId = templateId;\r\n    if (this.grid) {\r\n      this.loadTemplateConfig(templateId).then((template) => {\r\n        this.setTemplateStateToGrid(template);\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Save template\r\n   */\r\n  public showSaveTemplate() {\r\n    const currentTemplate = this.getTemplate(this.templateId);\r\n    const item: {\r\n      /** Boolean indicating a new template */\r\n      isNew: boolean,\r\n      /** Boolean indicating if the template can be edited. */\r\n      isEditable: boolean,\r\n      /** Label for the template */\r\n      label: string,\r\n    } = {\r\n      isNew: currentTemplate.isReadOnly,\r\n      isEditable: !currentTemplate.isReadOnly,\r\n      label: currentTemplate.isReadOnly ? \"Uusi raportti (\" + (this.templates.filter((x) => !x.isReadOnly).length + 1) + \")\" : currentTemplate.label,\r\n    };\r\n\r\n    const saveTemplate = (template: Template): Promise<Template> => {\r\n      return this.datasets.save({\r\n        id: template.id,\r\n        info: {\r\n          label: template.label,\r\n          status: DatasetStatus.Template,\r\n          type: DatasetType.ReportAdHoc,\r\n        },\r\n        usecase: {\r\n          uri: this.usecaseUri\r\n        },\r\n        data: [{\r\n          content: [\r\n            template.config\r\n          ]\r\n        }]\r\n      }).then((dataset) => ({\r\n        id: dataset.id,\r\n        owner: dataset.owner,\r\n        label: dataset.info.label,\r\n        config: dataset.data[0].content[0],\r\n        isReadOnly: dataset.isReadOnly,\r\n        avatar: this.sessionService.avatar,\r\n      }));\r\n    };\r\n\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/report/modals/CalculationReportSaveTemplate.html\",\r\n      item,\r\n      null).then((saveResult) => {\r\n        if (saveResult.action === \"ok\") {\r\n          const editedTemplate = saveResult.item;\r\n          if (!editedTemplate.isNew) {\r\n            currentTemplate.label = editedTemplate.label;\r\n            this.setGridStateToTemplate(currentTemplate);\r\n            saveTemplate(currentTemplate);\r\n          } else {\r\n            const newTemplate = {\r\n              id: null,\r\n              owner: null,\r\n              label: editedTemplate.label,\r\n              config: {},\r\n              isReadOnly: false,\r\n            };\r\n            this.setGridStateToTemplate(newTemplate);\r\n            saveTemplate(newTemplate).then((savedTemplate) => {\r\n              this.templates.push(savedTemplate);\r\n              this.selectTemplate(savedTemplate.id);\r\n            });\r\n          }\r\n        } else if (saveResult.action === \"delete\") {\r\n          this.showDeleteTemplate();\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Delete template\r\n   */\r\n  public showDeleteTemplate() {\r\n    const template = this.getTemplate(this.templateId);\r\n    this.uiHelpers.showConfirm(`Haluatko poistaa tämän raporttipohjan '${template.label}'?`).then((result) => {\r\n      if (result) {\r\n        if (!template.isReadOnly) {\r\n          const idx = this.templates.findIndex((x) => x.id === this.templateId);\r\n          this.templates.splice(idx, 1);\r\n          this.selectTemplate(this.templates[idx - 1].id);\r\n          this.datasets.delete(template.id);\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the period selection dialog and makes the search.\r\n   */\r\n  public showPeriodSelection() {\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/report/modals/CalculationReportPeriodSelection.html\",\r\n      this.queryOptions.period,\r\n      {\r\n        showWorkerSelection: (workerPeriod: any) => {\r\n          this.uiHelpers.openEditDialog(\r\n            \"salaxy-components/modals/calc/WorkerList.html\",\r\n            [].concat(...workerPeriod.selectedWorkers),\r\n            {\r\n              title: \"Valitse työntekijät\",\r\n            }).then((selectionResult) => {\r\n              if (selectionResult.action === \"ok\") {\r\n                workerPeriod.selectedWorkers.splice(0, workerPeriod.selectedWorkers.length);\r\n                workerPeriod.selectedWorkers.push(...selectionResult.item);\r\n              }\r\n            });\r\n        }\r\n      }).then((periodResult) => {\r\n        if (periodResult.action === \"ok\") {\r\n          this.queryOptions.period = periodResult.item;\r\n          this.gridOptions.api.showLoadingOverlay();\r\n          const workerIds = periodResult.item.selectedWorkers.length > 0 ? periodResult.item.selectedWorkers.map((x) => x.otherPartyInfo.avatar.id) : null;\r\n          this.queryDataForPeriod(periodResult.item.refDate, periodResult.item.periodType, periodResult.item.endDate, periodResult.item.periodDateKind, workerIds)\r\n            .then((dataResult) => {\r\n              this.setData(dataResult);\r\n            });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows the calculation selection dialog and makes the search.\r\n   */\r\n  public showCalcsSelection() {\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/CalcList.html\",\r\n      this.queryOptions.calculations,\r\n      {\r\n        title: \"Valitse maksetut palkat\",\r\n        category: \"paid\",\r\n      }).then((selectionResult) => {\r\n        if (selectionResult.action === \"ok\" && selectionResult.item.length > 0) {\r\n          this.queryOptions.calculations = selectionResult.item;\r\n          const ids = selectionResult.item.map((x) => x.id);\r\n          this.gridOptions.api.showLoadingOverlay();\r\n          this.queryDataForCalculationIds(ids).then((dataResult) => {\r\n            this.setData(dataResult);\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows the calculation selection dialog and makes the search.\r\n   */\r\n  public showPayrollSelection() {\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/payroll/PayrollList.html\",\r\n      this.queryOptions.payrolls,\r\n      {\r\n        title: \"Valitse palkkalistat\",\r\n        category: \"paid\",\r\n      }, \"lg\").then((selectionResult) => {\r\n        if (selectionResult.action === \"ok\" && selectionResult.item.length > 0) {\r\n          this.queryOptions.payrolls = selectionResult.item;\r\n          const ids = selectionResult.item.reduce((all, x) => all.concat(x.businessObjects), []);\r\n          this.gridOptions.api.showLoadingOverlay();\r\n          this.queryDataForCalculationIds(ids).then((dataResult) => {\r\n            this.setData(dataResult);\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets the data based on given set of calculations.\r\n   * @param calculationIds - Calculations that are the bases for the report.\r\n   * @returns A Promise with result data.\r\n   */\r\n  public abstract queryDataForCalculationIds(calculationIds: string[]): Promise<TData>;\r\n\r\n  /**\r\n   * Gets the monthly / quarterly / yearly cumulative data for the current account.\r\n   * @param refDate Reference date for the period. Please note that even if the date is not the first day of the given period, the entire period is returned.\r\n   * @param periodType Month, quarter, year or a custom period. The custom period requires endDate. Default value is the month.\r\n   * @param endDate End date for the period. Required only for the custom period.\r\n   * @param periodDateKind Period date type: paid at date, salary date or work date.\r\n   * @param workers List of worker official ids.\r\n   * @returns A Promise with result data.\r\n   */\r\n   public abstract queryDataForPeriod(refDate: string, periodType?: PeriodType | \"all\", endDate?: string, periodDateKind?: PeriodDateKind, workers?: string[]): Promise<TData>;\r\n\r\n   /**\r\n    * Processes and sets the data.\r\n    */\r\n  public abstract setData(result: TData);\r\n\r\n  private loadTemplates() {\r\n    this.templates.splice(0);\r\n    const filter = `status eq '${DatasetStatus.Template}' and entityType eq '${DatasetType.ReportAdHoc}' and data/usecaseUri eq '${this.usecaseUri}'`;\r\n    this.datasets.getOData({ $filter: filter }).then((result) => {\r\n      const customerTemplates = result.items.map((x: ApiListItem) => ({\r\n        id: x.id,\r\n        owner: x.owner,\r\n        label: x.shortText,\r\n        config: null,\r\n        isReadOnly: x.isReadOnly,\r\n        avatar: x.ownerInfo.avatar,\r\n      }));\r\n      this.templates.push(...this.defaultTemplates.concat(...customerTemplates));\r\n    });\r\n  }\r\n\r\n  private loadTemplateConfig(templateId: string) {\r\n    const template = this.getTemplate(templateId);\r\n    if (template.config) {\r\n      return Promise.resolve(template);\r\n    }\r\n    else {\r\n      return this.datasets.getSingle(template.id + (template.isReadOnly ? `@${template.owner}` : \"\")).then((dataset) => {\r\n        template.config = dataset.data.length == 1 && dataset.data[0].content.length == 1 ? dataset.data[0].content[0] : {};\r\n        return template;\r\n      });\r\n    }\r\n  }\r\n\r\n  private setTemplateStateToGrid(template: Template) {\r\n    this.gridOptions.columnApi.setPivotMode(template.config.isPivotMode ?? false);\r\n    if (template.config.columnState) {\r\n      this.gridOptions.columnApi.applyColumnState({\r\n        state: template.config.columnState,\r\n        applyOrder: true\r\n      });\r\n    }\r\n    else\r\n    {\r\n      this.gridOptions.columnApi.resetColumnState();\r\n    }\r\n    if (template.config.columnGroupState) {\r\n      this.gridOptions.columnApi.setColumnGroupState(template.config.columnGroupState);\r\n    }\r\n    else\r\n    {\r\n      this.gridOptions.columnApi.resetColumnGroupState();\r\n    }\r\n\r\n    this.gridOptions.api.setFilterModel(template.config.filterModel);\r\n  }\r\n\r\n  private setGridStateToTemplate(template: Template) {\r\n    template.config = template.config ?? {};\r\n    template.config.columnState = this.gridOptions.columnApi.getColumnState();\r\n    template.config.columnGroupState = this.gridOptions.columnApi.getColumnGroupState();\r\n    template.config.filterModel = this.gridOptions.api.getFilterModel();\r\n    template.config.isPivotMode = this.gridOptions.columnApi.isPivotMode();\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CalculationReportData, Datasets, Dates, Numeric, PeriodType, PeriodDateKind, Reports, Texts, LegalEntityType } from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\nimport { ConfigurableGridReportControllerBase } from \"./ConfigurableGridReportControllerBase\";\r\n\r\n/**\r\n * Controller for calculation reports.\r\n */\r\nexport class CalculationReportController extends ConfigurableGridReportControllerBase<CalculationReportData> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Datasets\", \"UiHelpers\", \"SessionService\", \"Reports\", \"$timeout\"];\r\n\r\n  /** Usecase uri for report templates */\r\n  public usecaseUri = \"palkkaus.fi/reports/calculationReport\";\r\n\r\n  /** Current grid options. */\r\n  public gridOptions: any = {\r\n    statusBar: {\r\n      statusPanels: [\r\n        { statusPanel: \"agTotalAndFilteredRowCountComponent\", key: \"totalAndFilter\", align: \"left\" },\r\n        { statusPanel: \"agSelectedRowCountComponent\", align: \"left\" },\r\n        { statusPanel: \"agAggregationComponent\", align: \"right\" }\r\n      ]\r\n    },\r\n    enableMultiRowDragging: true,\r\n    rowGroupPanelShow: \"always\",\r\n    pivotPanelShow: \"always\",\r\n    enableCharts: true,\r\n    enableRangeSelection: true,\r\n\r\n    defaultExportParams: {\r\n      columnGroups: true,\r\n      headerRowHeight: 30,\r\n      rowHeight: 22,\r\n      fontSize: 14,\r\n    },\r\n    defaultColDef: {\r\n      flex: 1,\r\n      minWidth: 200,\r\n      sortable: true,\r\n      filter: true,\r\n      resizable: true,\r\n      floatingFilter: true,\r\n    },\r\n    sideBar: { toolPanels: [\"columns\", \"filters\"] },\r\n    rowData: [],\r\n  };\r\n\r\n  /** ID for the element containing grid. */\r\n  public gridElmentId = \"#dataGrid\";\r\n\r\n  /** Default templates */\r\n  public defaultTemplates = [\r\n      {\r\n        id: \"incomeTypes\",\r\n        owner: null,\r\n        label: \"Tulolajiraportti\",\r\n        config: null,\r\n        isReadOnly: true,\r\n        avatar: {\r\n          initials: \"TLR\",\r\n          entityType: LegalEntityType.Company,\r\n          color: \"#009fd8\"\r\n        }\r\n      },\r\n      {\r\n        id: \"totals\",\r\n        owner: null,\r\n        label: \"Palkanmaksujen erittely\",\r\n        config: null,\r\n        isReadOnly: true,\r\n        avatar: {\r\n          initials: \"PME\",\r\n          entityType: LegalEntityType.Company,\r\n          color: \"#009fd8\"\r\n        }\r\n      },\r\n      {\r\n        id: \"plain\",\r\n        owner: null,\r\n        label: \"Kaikki sarakkeet\",\r\n        config: {},\r\n        isReadOnly: true,\r\n        avatar: {\r\n          initials: \"Kasa\",\r\n          entityType: LegalEntityType.Company,\r\n          color: \"#009fd8\"\r\n        }\r\n      }\r\n  ];\r\n\r\n  constructor(datasets: Datasets, uiHelpers: UiHelpers, sessionService: SessionService, private reports: Reports,  private $timeout: angular.ITimeoutService) {\r\n    super(datasets, uiHelpers, sessionService);\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Processes and sets the data.\r\n   */\r\n  public setData(result: CalculationReportData) {\r\n    this.data = result;\r\n\r\n    const sortingDateComparator = (a, b) => {\r\n      if (!a || !b) {\r\n        return a === b ? 0 : a ? 1 : -1;\r\n      }\r\n      const mA = Dates.asDate(a);\r\n      const mB = Dates.asDate(b);\r\n      return mA === mB ? 0 : mA > mB ? 1 : -1;\r\n    };\r\n    const filterDateComparator = (a, b) => sortingDateComparator(b, a);\r\n\r\n    const columnDefs = [];\r\n    columnDefs.push(\r\n      {\r\n        headerName: \"Laskelmat\",\r\n        children: [\r\n          {\r\n            headerName: \"Työntekijä\",\r\n            rowDrag: true,\r\n            field: \"worker\",\r\n            enableRowGroup: true,\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Laskelma\",\r\n            // rowDrag: true,\r\n            field: \"calculation\",\r\n            // enableRowGroup: true,\r\n            valueGetter: (params) => {\r\n              if (params.node && params.node.data) {\r\n                return `${params.node.data.worker} ${params.node.data.salaryDate} ${Numeric.formatPrice(params.node.data[\"totals-totalGrossSalary\"])}`;\r\n              }\r\n              return \"\";\r\n            },\r\n            cellRenderer: (params) => {\r\n              if (params.node && params.node.data) {\r\n                return `<a href=\"#/calc/details/${params.node.data.calculationId}\" target=\"_blank\" rel=\"noopener\">${Texts.escapeHtml(params.node.data.worker)} ${params.node.data.salaryDate} ${Numeric.formatPrice(params.node.data[\"totals-totalGrossSalary\"])}</a>`;\r\n              }\r\n              return \"\";\r\n            }\r\n          },\r\n          {\r\n            headerName: \"Työntekijän syntymäaika\",\r\n            field: \"workerBirthDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Palkkapäivä\",\r\n            field: \"salaryDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Brutto\",\r\n            field: \"totalGrossSalary\",\r\n            valueGetter: (params) => {\r\n              if (params.node && params.node.data) {\r\n                return params.node.data[\"totals-totalGrossSalary\"];\r\n              }\r\n              return null;\r\n            },\r\n            type: [\"numericColumn\"],\r\n            valueFormatter: params => Numeric.formatNumber(params.value, 2),\r\n            filter: \"agNumberColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Kuvaus\",\r\n            field: \"workDescription\",\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Aloituspäivä\",\r\n            field: \"workStartDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Lopetuspäivä\",\r\n            field: \"workEndDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Työsuhteen aloituspäivä\",\r\n            field: \"workerEmploymentStartDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Työsuhteen päättymispäivä\",\r\n            field: \"workerEmploymentEndDate\",\r\n            valueFormatter: params => Dates.getFormattedDate(params.value),\r\n            type: [\"rightAligned\"],\r\n            filter: \"agDateColumnFilter\",\r\n            comparator: sortingDateComparator,\r\n            filterParams: { comparator: filterDateComparator, },\r\n          },\r\n          {\r\n            headerName: \"Määräaikainen työsuhde\",\r\n            field: \"workerEmploymentIsFixedTerm\",\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n        ]\r\n      },\r\n      {\r\n        headerName: \"Ryhmittelyt\",\r\n        children: [\r\n          {\r\n            headerName: \"Kuukausi\",\r\n            field: \"salaryMonth\",\r\n            enablePivot: true,\r\n            enableRowGroup: true,\r\n            type: [\"numericColumn\"],\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Vuosi\",\r\n            field: \"salaryYear\",\r\n            enablePivot: true,\r\n            enableRowGroup: true,\r\n            type: [\"numericColumn\"],\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Ammattiluokka\",\r\n            field: \"occupationCode\",\r\n            enablePivot: true,\r\n            enableRowGroup: true,\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n          {\r\n            headerName: \"Eläketurva\",\r\n            field: \"pensionCalculation\",\r\n            enablePivot: true,\r\n            enableRowGroup: true,\r\n            filter: \"agMultiColumnFilter\",\r\n          },\r\n        ],\r\n      }\r\n    );\r\n    const irGroupDef = {\r\n      headerName: \"Tulolajit\",\r\n      children: [],\r\n    };\r\n    columnDefs.push(irGroupDef);\r\n    Object.keys(this.data.irLabels).forEach((key) => {\r\n      irGroupDef.children.push({\r\n        field: key,\r\n        headerName: this.data.irLabels[key],\r\n        enableValue: true,\r\n        type: [\"numericColumn\"],\r\n        valueFormatter: params => Numeric.formatNumber(params.value, 2),\r\n        filter: \"agNumberColumnFilter\",\r\n      });\r\n    });\r\n\r\n    const typeGroupDef = {\r\n      headerName: \"Rivityypit\",\r\n      children: [],\r\n    };\r\n    columnDefs.push(typeGroupDef);\r\n    Object.keys(this.data.typeLabels).forEach((key) => {\r\n      typeGroupDef.children.push({\r\n        field: key,\r\n        headerName: this.data.typeLabels[key],\r\n        enableValue: true,\r\n        type: [\"numericColumn\"],\r\n        valueFormatter: params => Numeric.formatNumber(params.value, 2),\r\n        filter: \"agNumberColumnFilter\",\r\n      });\r\n    });\r\n\r\n    const employerCalcDef = {\r\n      headerName: \"Työnantaja\",\r\n      children: [],\r\n    };\r\n    const workerCalcDef = {\r\n      headerName: \"Työntekijä\",\r\n      children: [],\r\n    };\r\n    const totalsDef = {\r\n      headerName: \"Yhteensä\",\r\n      children: [],\r\n    };\r\n    const totalGroupDef = {\r\n      headerName: \"Maksut\",\r\n      children: [\r\n        workerCalcDef,\r\n        employerCalcDef,\r\n        totalsDef,\r\n      ],\r\n    };\r\n    columnDefs.push(totalGroupDef);\r\n    Object.keys(this.data.totalLabels).forEach((key) => {\r\n      const def = key.indexOf(\"employerCalc\") === 0 ? employerCalcDef :\r\n        key.indexOf(\"workerCalc\") === 0 ? workerCalcDef : totalsDef;\r\n\r\n      def.children.push({\r\n        field: key,\r\n        headerName: this.data.totalLabels[key],\r\n        enableValue: true,\r\n        type: [\"numericColumn\"],\r\n        valueFormatter: params => Numeric.formatNumber(params.value, 2),\r\n        filter: \"agNumberColumnFilter\",\r\n      });\r\n    });\r\n\r\n    // Create presets if not created.\r\n    const incomeTypes = this.getTemplate(\"incomeTypes\");\r\n    incomeTypes.config = incomeTypes.config ?? { columnState: this.createIncomeTypesPreset(columnDefs, this.data.rows)};\r\n\r\n    const totals = this.getTemplate(\"totals\");\r\n    totals.config = totals.config ?? { columnState: this.createTotalsPreset(columnDefs)};\r\n\r\n    // create the grid passing in the div to use together with the columns & data we want to use\r\n    this.$timeout(() => {\r\n      const filterModel = this.gridOptions.api.getFilterModel();\r\n      this.gridOptions.api.setFilterModel(null);\r\n      this.gridOptions.api.setRowData(this.data.rows);\r\n      this.gridOptions.api.setColumnDefs(columnDefs);\r\n      this.gridOptions.api.setFilterModel(filterModel);\r\n      this.selectTemplate(this.templateId ?? \"incomeTypes\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the monthly / quarterly / yearly cumulative data for the current account.\r\n   * @param refDate Reference date for the period. Please note that even if the date is not the first day of the given period, the entire period is returned.\r\n   * @param periodType Month, quarter, year or a custom period. The custom period requires endDate. Default value is the month.\r\n   * @param endDate End date for the period. Required only for the custom period.\r\n   * @param periodDateKind Period date type: paid at date, salary date or work date.\r\n   * @param workers List of worker official ids.\r\n   * @returns A Promise with result data.\r\n   */\r\n  public queryDataForPeriod(refDate: string, periodType?: PeriodType | \"all\", endDate?: string, periodDateKind?: PeriodDateKind, workers?: string[]): Promise<CalculationReportData> {\r\n\r\n    if (periodType === \"all\") {\r\n      refDate = \"2010-01-01\";\r\n      endDate = \"2100-01-01\";\r\n      periodType = PeriodType.Custom;\r\n    }\r\n    return this.reports.getCalculationReportData(refDate,periodType,endDate, periodDateKind, workers);\r\n  }\r\n\r\n  /**\r\n   * Gets the cumulative data based on given set of calculations.\r\n   * @param calculationIds - Calculations that are the bases for the report.\r\n   * @returns A Promise with result data.\r\n   */\r\n  public queryDataForCalculationIds(calculationIds: string[]): Promise<CalculationReportData> {\r\n    return this.reports.getCalculationReportDataForCalculationIds(calculationIds);\r\n  }\r\n\r\n  private createIncomeTypesPreset(columnDefs: any, rows: any[]) {\r\n    const preset = [];\r\n\r\n    // Laskelmat\r\n    const calculationDef = columnDefs[0];\r\n    for (const def of calculationDef.children) {\r\n      switch (def.field) {\r\n        case \"worker\":\r\n          preset.push(this.createPresetCol(def.field, true, true));\r\n          break;\r\n        case \"calculation\":\r\n          preset.push(this.createPresetCol(def.field, false));\r\n          break;\r\n        default:\r\n          preset.push(this.createPresetCol(def.field, true));\r\n      }\r\n    }\r\n    // Dimensiot\r\n    const dimensionDef = columnDefs[1];\r\n    for (const def of dimensionDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n    // Tulolajit\r\n    const incomeTypeDef = columnDefs[2];\r\n    for (const def of incomeTypeDef.children) {\r\n      const hide = !(rows ?? []).find( x => x[def.field]);\r\n      if (def.field.endsWith(\"-price\")) {\r\n        preset.push(this.createPresetCol(def.field, hide, false, \"avg\"));\r\n      } else {\r\n        preset.push(this.createPresetCol(def.field, hide, false, \"sum\"));\r\n      }\r\n    }\r\n\r\n    // Rivityypit\r\n    const rowTypeDef = columnDefs[3];\r\n    for (const def of rowTypeDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    // Maksut - työntekijä\r\n    const workerTotalsDef = columnDefs[4].children[0];\r\n    for (const def of workerTotalsDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    // Maksut - työnantaja\r\n    const employerTotalsDef = columnDefs[4].children[1];\r\n    for (const def of employerTotalsDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    // Maksut - yhteensä\r\n    const totalsDef = columnDefs[4].children[2];\r\n    for (const def of totalsDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    return preset;\r\n  }\r\n\r\n  private createTotalsPreset(columnDefs: any) {\r\n    const preset = [];\r\n\r\n    // Laskelmat\r\n    const calculationDef = columnDefs[0];\r\n    for (const def of calculationDef.children) {\r\n      switch (def.field) {\r\n        case \"worker\":\r\n          preset.push(this.createPresetCol(def.field, true, true));\r\n          break;\r\n        case \"salaryDate\":\r\n        case \"workStartDate\":\r\n        case \"workEndDate\":\r\n          preset.push(this.createPresetCol(def.field, false));\r\n          break;\r\n        default:\r\n          preset.push(this.createPresetCol(def.field, true));\r\n          break;\r\n      }\r\n    }\r\n    // Dimensiot\r\n    const dimensionDef = columnDefs[1];\r\n    for (const def of dimensionDef.children) {\r\n      switch (def.field) {\r\n        case \"pensionCalculation\":\r\n          preset.push(this.createPresetCol(def.field, false));\r\n          break;\r\n        default:\r\n          preset.push(this.createPresetCol(def.field, true));\r\n          break;\r\n      }\r\n    }\r\n    // Tulolajit\r\n    const incomeTypeDef = columnDefs[2];\r\n    for (const def of incomeTypeDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    // Rivityypit\r\n    const rowTypeDef = columnDefs[3];\r\n    for (const def of rowTypeDef.children) {\r\n      preset.push(this.createPresetCol(def.field, true));\r\n    }\r\n\r\n    const totalFields = [\r\n      \"totals-totalGrossSalary\",\r\n      \"workerCalc-benefits\",\r\n      \"totals-annualHolidayCompensation\",\r\n      \"totals-holidayBonus\",\r\n      \"totals-holidaySalary\",\r\n      // \"muut vähennettävät erät ml. luontoiseduista vähennettävät\"\r\n      \"totals-totalTaxable\",\r\n      \"workerCalc-tax\",\r\n      \"workerCalc-pension\",\r\n      \"workerCalc-unemploymentInsurance\",\r\n      \"workerCalc-unionPayment\",\r\n      \"workerCalc-foreclosure\",\r\n      \"workerCalc-salaryAdvance\",\r\n      \"workerCalc-otherDeductions\",\r\n      \"workerCalc-deductions\",\r\n      \"workerCalc-prepaidExpenses\",\r\n      \"totals-totalExpenses\",\r\n      \"workerCalc-totalWorkerPayment\",\r\n      \"employerCalc-totalPayment\",\r\n      \"employerCalc-palkkaus\",\r\n      \"employerCalc-service\",\r\n      \"employerCalc-socialSecurity\",\r\n      \"totals-pension\",\r\n      \"employerCalc-pension\",\r\n      \"totals-unemployment\",\r\n      \"employerCalc-unemployment\",\r\n      \"totals-totalPensionInsuranceBase\",\r\n      \"totals-totalSocialSecurityBase\",\r\n      \"totals-totalHealthInsuranceBase\",\r\n      \"totals-totalUnemploymentInsuranceBase\",\r\n      \"totals-totalAccidentInsuranceBase\",\r\n      \"totals-totalAccidentInsurance\",\r\n      \"totals-totalGroupLifeInsurance\"\r\n    ];\r\n\r\n    for (const field of totalFields) {\r\n      preset.push(this.createPresetCol(field, false, false, \"sum\"));\r\n    }\r\n\r\n    // Maksut - työntekijä\r\n    const workerTotalsDef = columnDefs[4].children[0];\r\n    for (const def of workerTotalsDef.children) {\r\n      if (totalFields.indexOf(def.field) < 0) {\r\n        preset.push(this.createPresetCol(def.field, true));\r\n      }\r\n    }\r\n\r\n    // Maksut - työnantaja\r\n    const employerTotalsDef = columnDefs[4].children[1];\r\n    for (const def of employerTotalsDef.children) {\r\n      if (totalFields.indexOf(def.field) < 0) {\r\n        preset.push(this.createPresetCol(def.field, true));\r\n      }\r\n    }\r\n\r\n    // Maksut - yhteensä\r\n    const totalsDef = columnDefs[4].children[2];\r\n    for (const def of totalsDef.children) {\r\n      if (totalFields.indexOf(def.field) < 0) {\r\n        preset.push(this.createPresetCol(def.field, true));\r\n      }\r\n    }\r\n\r\n    return preset;\r\n  }\r\n\r\n  private createPresetCol(colId: string, hide: boolean, rowGroup = false, aggFunc: string = null) {\r\n    return {\r\n      aggFunc,\r\n      colId,\r\n      flex: 1,\r\n      hide,\r\n      pinned: null,\r\n      pivot: false,\r\n      pivotIndex: null,\r\n      rowGroup,\r\n      rowGroupIndex: null,\r\n      sort: null,\r\n      sortIndex: null,\r\n      width: 200,\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingRowReportData, Datasets, Dates, LegalEntityType, Numeric, PeriodType, PeriodDateKind, Reports } from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers } from \"../../services\";\r\nimport { ConfigurableGridReportControllerBase } from \"./ConfigurableGridReportControllerBase\";\r\n\r\n/**\r\n * Controller for accounting row based reports.\r\n */\r\nexport class AccountingRowReportController extends ConfigurableGridReportControllerBase<AccountingRowReportData> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Datasets\", \"UiHelpers\", \"SessionService\", \"Reports\", \"$timeout\"];\r\n\r\n  /** Usecase uri for report templates */\r\n  public usecaseUri = \"palkkaus.fi/reports/accountingRowReport\";\r\n\r\n  /** Current grid options. */\r\n  public gridOptions: any = {\r\n    statusBar: {\r\n      statusPanels: [\r\n        { statusPanel: \"agTotalAndFilteredRowCountComponent\", key: \"totalAndFilter\", align: \"left\" },\r\n        { statusPanel: \"agSelectedRowCountComponent\", align: \"left\" },\r\n        { statusPanel: \"agAggregationComponent\", align: \"right\" }\r\n      ]\r\n    },\r\n    enableMultiRowDragging: true,\r\n    rowGroupPanelShow: \"always\",\r\n    pivotPanelShow: \"always\",\r\n    enableCharts: true,\r\n    enableRangeSelection: true,\r\n    pivotMode: true,\r\n    suppressExpandablePivotGroups: true,\r\n\r\n    defaultExportParams: {\r\n      columnGroups: true,\r\n      headerRowHeight: 30,\r\n      rowHeight: 22,\r\n      fontSize: 14,\r\n    },\r\n    defaultColDef: {\r\n      flex: 1,\r\n      minWidth: 200,\r\n      sortable: true,\r\n      filter: true,\r\n      resizable: true,\r\n      floatingFilter: true,\r\n    },\r\n    sideBar: { toolPanels: [\"columns\", \"filters\"] },\r\n    rowData: [],\r\n  };\r\n\r\n  /** ID for the element containing grid. */\r\n  public gridElmentId = \"#dataGrid\";\r\n\r\n  /** Default templates */\r\n  public defaultTemplates = [\r\n    {\r\n      id: \"holidays\",\r\n      owner: null,\r\n      label: \"Lomapalkkaraportti\",\r\n      config: null,\r\n      isReadOnly: true,\r\n      avatar: {\r\n        initials: \"LPR\",\r\n        entityType: LegalEntityType.Company,\r\n        color: \"#009fd8\"\r\n      }\r\n    },\r\n    {\r\n      id: \"plain\",\r\n      owner: null,\r\n      label: \"Kaikki sarakkeet\",\r\n      config: { isPivotMode: false},\r\n      isReadOnly: true,\r\n      avatar: {\r\n        initials: \"Kasa\",\r\n        entityType: LegalEntityType.Company,\r\n        color: \"#009fd8\"\r\n      }\r\n    }\r\n  ];\r\n\r\n  private entryCodeGroups = {\r\n    totalType: \"Yhteensä\",\r\n    incomeType: \"Tulolaji\"\r\n  };\r\n  private entryCodes = {\r\n    totalPensionWorker: \"Työntekijöiden TyEL-maksut\",\r\n    totalPensionEmployer: \"Työnantajan TyEL-maksu\",\r\n    totalPension: \"TyEL-maksut\",\r\n    totalUnemploymentWorker: \"Työntekijöiden työttömyysvakuutusmaksut\",\r\n    totalUnemploymentEmployer: \"Työnantajan työttömyysvakuutusmaksu\",\r\n    totalUnemployment: \"Työttömyysvakuutusmaksut\",\r\n    totalSocialSecurityEmployer: \"Työnantajan sairausvakuutusmaksu\",\r\n    totalTax: \"Ennakonpidätykset\",\r\n    totalPalkkaus: \"Palkkaus.fi-palkkio\",\r\n    totalWorkerPayment: \"Työntekijän nettopalkka ja kulukorvaukset\",\r\n    totalPayment: \"Maksettu asiakasvaratilille\",\r\n    totalAccidentInsurance: \"Työtapaturma- ja ammattitautivakuutusmaksut\",\r\n    totalGroupLifeInsurance: \"Ryhmähenkivakuutusmaksut\",\r\n    totalAccruedHolidayPay: \"Kertyneet lomapalkat\",\r\n    totalAccruedHolidaySocialSecurity: \"Kertyneet lomapalkkojen sairausvakuutusmaksut\",\r\n    totalAccruedHolidayPension: \"Kertyneet lomapalkkojen TyEL-maksut\",\r\n    totalAccruedHolidayUnemployment: \"Kertyneet lomapalkkojen työttömyysvakuutusmaksut (TVR)\",\r\n    totalPaidHolidaySalary: \"Maksetut loma-ajan palkat\",\r\n    totalPaidHolidayBonus: \"Maksetut lomarahat\",\r\n    totalPaidHolidayCompensation: \"Maksetut lomakorvaukset\",\r\n    totalPaidHolidaySocialSecurity: \"Maksetut lomapalkkojen sairausvakuutusmaksut\",\r\n    totalPaidHolidayPension: \"Maksetut lomapalkkojen TyEL-maksut\",\r\n    totalPaidHolidayUnemployment: \"Maksetut lomapalkkojen työttömyysvakuutusmaksut (TVR)\",\r\n    totalGrossSalary: \"Bruttopalkka\",\r\n  };\r\n\r\n  constructor(datasets: Datasets, uiHelpers: UiHelpers, sessionService: SessionService, private reports: Reports,  private $timeout: angular.ITimeoutService) {\r\n    super(datasets, uiHelpers, sessionService);\r\n  }\r\n\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Processes and sets the data.\r\n   */\r\n  public setData(result: AccountingRowReportData) {\r\n    this.data = result;\r\n\r\n    const sortingDateComparator = (a, b) => {\r\n      if (!a || !b) {\r\n        return a === b ? 0 : a ? 1 : -1;\r\n      }\r\n      const mA = Dates.asDate(a);\r\n      const mB = Dates.asDate(b);\r\n      return mA === mB ? 0 : mA > mB ? 1 : -1;\r\n    };\r\n    const filterDateComparator = (a, b) => sortingDateComparator(b, a);\r\n\r\n    const columnDefs = [];\r\n\r\n    columnDefs.push(...[\r\n      {\r\n        field: \"message\",\r\n        headerName: \"Selite\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n      },\r\n      {\r\n        field: \"entryDate\",\r\n        headerName: \"Päiväys\",\r\n        valueFormatter: params => Dates.getFormattedDate(params.value),\r\n        type: [\"rightAligned\"],\r\n        filter: \"agDateColumnFilter\",\r\n        comparator: sortingDateComparator,\r\n        filterParams: { comparator: filterDateComparator, },\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n      },\r\n      {\r\n        field: \"amount\",\r\n        headerName: \"Summa\",\r\n        enableValue: true,\r\n        type: [\"numericColumn\"],\r\n        valueFormatter: params => Numeric.formatNumber(params.value, 2),\r\n        filter: \"agNumberColumnFilter\",\r\n      },\r\n      {\r\n        field: \"dimension.workerName\",\r\n        headerName: \"Työntekijä\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n      },\r\n      /*\r\n      {\r\n        field: \"dimension.dimensions.costCenter\",\r\n        headerName: \"Kustannuspaikka\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n      },\r\n      {\r\n        field: \"dimension.rowType\",\r\n        headerName: \"Laskelmarivin tyyppi\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n      },\r\n      */\r\n      {\r\n        field: \"entryCodeGroup\",\r\n        headerName: \"Kirjanpitorivin tyyppi\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n        valueGetter: params =>  this.getEntryCodeGroupName(params?.data?.entryCodeGroup)\r\n      },\r\n      {\r\n        field: \"entryCode\",\r\n        headerName: \"Kirjanpitorivin tunniste\",\r\n        filter: \"agMultiColumnFilter\",\r\n        enablePivot: true,\r\n        enableRowGroup: true,\r\n        valueGetter: params =>  this.getEntryCodeName(params?.data?.entryCode)\r\n      },\r\n    ]);\r\n\r\n    // Create presets if not created.\r\n    const holidays = this.getTemplate(\"holidays\");\r\n    holidays.config = holidays.config ?? {\r\n      isPivotMode: true,\r\n      columnState: this.createHolidaysPreset(columnDefs),\r\n      filterModel: {\r\n        entryCodeGroup: {\r\n          filterType: \"multi\",\r\n          filterModels: [\r\n            null,\r\n            {\r\n              values: [\r\n                this.entryCodeGroups[\"totalType\"],\r\n              ],\r\n              filterType: \"set\"\r\n            }\r\n          ]\r\n        },\r\n        entryCode: {\r\n          filterType: \"multi\",\r\n          filterModels: [\r\n            null,\r\n            {\r\n              values: [\r\n                this.entryCodes[\"totalGrossSalary\"],\r\n                this.entryCodes[\"totalAccruedHolidayPay\"],\r\n                this.entryCodes[\"totalAccruedHolidaySocialSecurity\"],\r\n                this.entryCodes[\"totalAccruedHolidayPension\"],\r\n                this.entryCodes[\"totalAccruedHolidayUnemployment\"],\r\n                this.entryCodes[\"totalPaidHolidaySalary\"],\r\n                this.entryCodes[\"totalPaidHolidayBonus\"],\r\n                this.entryCodes[\"totalPaidHolidayCompensation\"],\r\n                this.entryCodes[\"totalPaidHolidaySocialSecurity\"],\r\n                this.entryCodes[\"totalPaidHolidayPension\"],\r\n                this.entryCodes[\"totalPaidHolidayUnemployment\"],\r\n              ],\r\n              filterType: \"set\"\r\n            }\r\n          ]\r\n        }\r\n      },\r\n    };\r\n    // create the grid passing in the div to use together with the columns & data we want to use\r\n    this.$timeout(() => {\r\n      const filterModel = this.gridOptions.api.getFilterModel();\r\n      this.gridOptions.api.setFilterModel(null);\r\n      this.gridOptions.api.setRowData(this.data.rows);\r\n      this.gridOptions.api.setColumnDefs(columnDefs);\r\n      this.gridOptions.api.setFilterModel(filterModel);\r\n      this.selectTemplate(this.templateId ?? \"holidays\");\r\n    });\r\n  }\r\n\r\n  private getEntryCodeGroupName(id: string) {\r\n    const name =  this.entryCodeGroups[\"\" + id] ?? null;\r\n    return name;\r\n  }\r\n\r\n  private getEntryCodeName(id: string) {\r\n    const name =  this.entryCodes[\"\" + id] ?? null;\r\n    return name;\r\n  }\r\n\r\n  /**\r\n   * Gets the monthly / quarterly / yearly accounitng row data for the current account.\r\n   * @param refDate Reference date for the period. Please note that even if the date is not the first day of the given period, the entire period is returned.\r\n   * @param periodType Month, quarter, year or a custom period. The custom period requires endDate. Default value is the month.\r\n   * @param endDate End date for the period. Required only for the custom period.\r\n   * @param periodDateKind Period date type: paid at date, salary date or work date.\r\n   * @param workers List of worker official ids.\r\n   * @returns A Promise with result data.\r\n   */\r\n  public queryDataForPeriod(refDate: string, periodType?: PeriodType | \"all\", endDate?: string, periodDateKind?: PeriodDateKind, workers?: string[]): Promise<AccountingRowReportData> {\r\n\r\n    if (periodType === \"all\") {\r\n      refDate = \"2010-01-01\";\r\n      endDate = \"2100-01-01\";\r\n      periodType = PeriodType.Custom;\r\n    }\r\n\r\n    return this.reports.getAccountingRowReportData(refDate,periodType,endDate,periodDateKind,workers);\r\n  }\r\n\r\n  /**\r\n   * Gets the accounting row data based on given set of calculations.\r\n   * @param calculationIds - Calculations that are the bases for the report.\r\n   * @returns A Promise with result data.\r\n   */\r\n  public queryDataForCalculationIds(calculationIds: string[]): Promise<AccountingRowReportData> {\r\n    return this.reports.getAccountingRowReportDataForCalculationIds(calculationIds);\r\n  }\r\n\r\n  private createHolidaysPreset(columnDefs: any) {\r\n    const preset = [];\r\n\r\n    for (const def of columnDefs) {\r\n      switch (def.field) {\r\n        case \"dimension.workerName\":\r\n          preset.push(this.createPresetCol(def.field, false, true));\r\n          break;\r\n        default:\r\n          preset.push(this.createPresetCol(def.field, true));\r\n          break;\r\n      }\r\n    }\r\n\r\n    preset.push(this.createPresetCol(\"amount\", false, false, \"sum\"));\r\n\r\n    preset.push(this.createPresetCol(\"entryCodeGroup\", false, false, null, true, 0));\r\n\r\n    preset.push(this.createPresetCol(\"entryCode\", false, false, null, true, 1));\r\n\r\n\r\n    return preset;\r\n  }\r\n\r\n  private createPresetCol(colId: string, hide: boolean, rowGroup = false, aggFunc: string = null, pivot = false, pivotIndex: number = null) {\r\n    return {\r\n      aggFunc,\r\n      colId,\r\n      flex: 1,\r\n      hide,\r\n      pinned: null,\r\n      pivot: pivot,\r\n      pivotIndex: pivotIndex,\r\n      rowGroup,\r\n      rowGroupIndex: null,\r\n      sort: null,\r\n      sortIndex: null,\r\n      width: 200,\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { PeriodType, Reports } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for displaying summary report\r\n */\r\nexport class SummaryReportDisplayController implements angular.IController {\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Reports\"\r\n  ];\r\n  /**\r\n   * Creates a new instance of SummaryReportDisplayController\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private reports: Reports\r\n\r\n  ) { }\r\n\r\n  /**\r\n   * Display Summary report\r\n   * @param refDate date\r\n   * @param type report type\r\n   */\r\n  public display(refDate: string, type: string): void {\r\n    const data = {\r\n      summaryReportData: null,\r\n      isLoading: true\r\n    };\r\n    this.reports.getSummaryReportData(refDate, this.getPeriodType(type)).then(summaryReportData => {\r\n      data.summaryReportData = summaryReportData;\r\n      data.isLoading = false;\r\n    });\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/report/SummaryReport.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"landscape\",\r\n      true);\r\n  }\r\n\r\n  private getPeriodType(reportType: string): PeriodType {\r\n    switch (reportType) {\r\n      case \"monthlyDetails\":\r\n        return PeriodType.Month;\r\n      case \"yearlyDetails\":\r\n        return PeriodType.Year;\r\n    }\r\n  }\r\n\r\n}","import angular from \"angular\";\r\nimport { SummaryReportData, Numeric, Translations, Language, Configs, Ajax } from \"@salaxy/core\";\r\nimport { SettingsService, UiHelpers, SessionService } from \"../../services\";\r\nimport {\r\n  SummaryMapper,\r\n  ReportData,\r\n  ReportOptions,\r\n  Templates,\r\n} from \"@salaxy/reports\";\r\n\r\n\r\n/**\r\n * Renders a summary report or a calculation summary report for the given calculation(s).\r\n * Uses Handlebars templates (@salaxy/reports).\r\n */\r\nexport class SummaryReportController implements angular.IController {\r\n  public data: SummaryReportData;\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Templates\", \"$sce\", \"SettingsService\", \"$timeout\", \"$http\", \"UiHelpers\", \"SessionService\", \"AjaxNg1\"];\r\n\r\n  /** Template for the report */\r\n  public templateName = \"summaryReport\";\r\n\r\n  /** Boolean indicating if the refresh is in progress. */\r\n  public refreshInprogress: boolean;\r\n\r\n  /**Selected report language */\r\n  public lang: Language;\r\n\r\n  private renderedData: SummaryReportData;\r\n\r\n  private renderedLang: string;\r\n\r\n  private htmlData: any;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private reportTemplate = \"summaryReport\";\r\n\r\n  private reportData: ReportData<SummaryReportData> = {\r\n    headerFooter: {},\r\n    layout: {},\r\n    report: {},\r\n  };\r\n\r\n  private _reportLang: Language = Language.Default;\r\n\r\n\r\n\r\n  /**\r\n   * Creates a new CalcReportController\r\n   * @ignore\r\n   */\r\n  constructor(private templates: Templates,\r\n    private $sce: angular.ISCEService,\r\n    private settingsService: SettingsService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $http: angular.IHttpService,\r\n    private uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n    private ajax: Ajax\r\n  ) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.sessionService.getReportLang().then((lang) => {\r\n      this.reportLang = lang;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get _reportLang\r\n   */\r\n  public get reportLang() {\r\n    return this._reportLang;\r\n  }\r\n\r\n  /**\r\n   * Set _reportLang & lang\r\n   */\r\n  public set reportLang(lang: Language) {\r\n    this._reportLang = lang;\r\n    if (lang !== Language.Default) {\r\n      this.lang = this._reportLang;\r\n    } else {\r\n      this.sessionService.getReportLang().then(lang => {\r\n        this.lang = lang;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return languge text to ui\r\n   */\r\n  public get languageText() {\r\n    switch (this.reportLang) {\r\n      case Language.Fi:\r\n        return \"SALAXY.ENUM.Language.fi.label\";\r\n      case Language.En:\r\n        return \"SALAXY.ENUM.Language.en.label\";\r\n      case Language.Sv:\r\n        return \"SALAXY.ENUM.Language.sv.label\";\r\n      case Language.Default:\r\n        return \"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\";\r\n    }\r\n  }\r\n\r\n  /** Bindable and trusted html. */\r\n  public get html(): any {\r\n    if (!this.data) {\r\n      this.renderedData = null;\r\n      this.renderedLang = null;\r\n    } else {\r\n      const summaryReportData = angular.copy(this.data);\r\n\r\n      if (!this.renderedData || !angular.equals(summaryReportData, this.renderedData)\r\n        || this.renderedLang !== this.lang) {\r\n        this.lang = this.lang === Language.Default ? Language.Fi : this.lang;\r\n        this.renderedData = angular.copy(summaryReportData);\r\n        this.renderedLang = this.lang;\r\n        this.refresh();\r\n      }\r\n    }\r\n    return this.htmlData;\r\n  }\r\n\r\n  private async refresh() {\r\n    if (this.refreshInprogress) {\r\n      return;\r\n    }\r\n    this.refreshInprogress = true;\r\n    this.settingsService.getReportOptions().then( async(options) => {\r\n      this.reportOptions = options;\r\n      const renderingLang = this.lang ?? Language.Fi;\r\n      await Translations.loadLanguage(renderingLang);\r\n      const reportOptions = this.getDefaultReportOptions(angular.copy(this.reportOptions));\r\n      this.reportData.headerFooter = SummaryMapper.getSummaryReportHeaderFooter(this.data, reportOptions, renderingLang);\r\n      this.reportData.report = SummaryMapper.getSummaryReport(this.data);\r\n      this.reportData.layout = SummaryMapper.getReportLayout(false, false);\r\n      const css = \"\";\r\n      this.reportData.layout.hasCustomCss = false;\r\n      this.reportData.layout.customCss = (css || \"\");\r\n      this.reportData.layout.margin = {\r\n        top: reportOptions.margin.top,\r\n        right: reportOptions.margin.right,\r\n        bottom: reportOptions.margin.bottom,\r\n        left: reportOptions.margin.left\r\n      };\r\n      const templates = new Templates();\r\n      this.reportData.headerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.headerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.reportData.footerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.footerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.htmlData = this.$sce.trustAsHtml(this.templates.getHtml(this.templateName, this.reportData, renderingLang));\r\n      this.refreshInprogress = false;\r\n      this.$timeout();\r\n    });\r\n  }\r\n  /**\r\n   * Shows a download dialog for the given summary report.\r\n   * @param inline - If true, the download link opens the pdf into a new web page.\r\n   */\r\n  public showDownloadDialog(inline = false) {\r\n    const url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(\"monthlyDetails\")}&template=${encodeURIComponent(this.reportTemplate)}&language=${encodeURIComponent(this.lang)}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n    this.handlePdfRequest(url, inline, this.data);\r\n  }\r\n\r\n  private getDefaultReportOptions(optionsInput?: ReportOptions): ReportOptions {\r\n    optionsInput = optionsInput || {};\r\n    optionsInput.margin = optionsInput.margin || {};\r\n    optionsInput.margin.top = Numeric.parseNumber(optionsInput.margin.top) || 30;\r\n    optionsInput.margin.right = Numeric.parseNumber(optionsInput.margin.right) || 10;\r\n    optionsInput.margin.bottom = Numeric.parseNumber(optionsInput.margin.bottom) || 40;\r\n    optionsInput.margin.left = Numeric.parseNumber(optionsInput.margin.left) || 10;\r\n    return optionsInput;\r\n  }\r\n\r\n  /**\r\n   * Handles pdf request\r\n   * @param url post url\r\n   * @param inline inline pdf\r\n   * @param data business object\r\n   */\r\n  private handlePdfRequest(url: string, inline: boolean, data: SummaryReportData): void {\r\n    this.$http.post(url, { object: data }, { responseType: \"blob\" }).then((response) => {\r\n      if (response.data) {\r\n        if (inline) {\r\n          this.uiHelpers.openFile(response.data as any);\r\n        } else {\r\n          this.uiHelpers.downloadFile(response.data as any, response.headers(\"content-disposition\").split(\";\")[1].split(\"filename\")[1].split(\"=\")[1].trim().replace(/\"/g, \"\"));\r\n        }\r\n      }\r\n    }, (error) => {\r\n      console.error(error);\r\n    });\r\n  }\r\n\r\n}\r\n\r\n","import angular from \"angular\";\r\nimport { AccountingData, PeriodType, Reports, PeriodDateKind } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for displaying accounting report\r\n */\r\nexport class AccountingReportDisplayController implements angular.IController {\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Reports\"\r\n  ];\r\n  /**\r\n   * Creates a new instance of AccountingReportDisplayController\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private reports: Reports\r\n\r\n  ) { }\r\n\r\n  /**\r\n   * Display accounting report\r\n   * @param refDate date\r\n   */\r\n  public display(refDate: string): void {\r\n    const getAccountingData = (target: string) => this.reports.getAccountingDataForPeriod(refDate, target ?? \"default\", PeriodType.Month, null, PeriodDateKind.PaidAtDate);\r\n    const data = {\r\n      accountingData: null,\r\n      isLoading: true,\r\n      reader: {\r\n        /**\r\n         * Function to read data into given array\r\n         * TODO: Should make interface for this or otherwise go-through.\r\n         */\r\n        // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n        read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n          if (data.accountingData) {\r\n            arr.push(data.accountingData);\r\n          }\r\n          return Promise.resolve();\r\n        },\r\n        /** Optional label for data export */\r\n        exportLabel: null,\r\n        /** Indicates if the export is not possible */\r\n        disabled: () => !data.accountingData,\r\n        /* Indicates if row is expandable */\r\n        showExpand: true,\r\n        /* Indicates if rows exists*/\r\n        hasRows: () => !data.accountingData?.ledgerAccounts\r\n      },\r\n      loadCurrent: (targetId) => {\r\n        data.isLoading = true;\r\n        getAccountingData(targetId).then(accountingData => {\r\n          data.accountingData = accountingData;\r\n          data.isLoading = false;\r\n        });\r\n      }\r\n    };\r\n    data.isLoading = true;\r\n    getAccountingData(null).then(accountingData => {\r\n      data.accountingData = accountingData;\r\n      data.isLoading = false;\r\n    });\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/report/AccountingReport.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"lg\",\r\n      true);\r\n  }\r\n}","import angular from \"angular\";\r\nimport { SummaryReportData, Numeric, Translations, Language, Configs, Ajax, WorkerSummaryReportData } from \"@salaxy/core\";\r\nimport { SettingsService, UiHelpers, SessionService } from \"../../services\";\r\nimport { WorkerSummaryMapper, ReportData, ReportOptions, Templates } from \"@salaxy/reports\";\r\n\r\n\r\n/**\r\n * Renders a worker summary report or a calculation summary report for the given calculation(s).\r\n * Uses Handlebars templates (@salaxy/reports).\r\n */\r\nexport class WorkerSummaryReportController implements angular.IController {\r\n  public data: WorkerSummaryReportData;\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Templates\", \"$sce\", \"SettingsService\", \"$timeout\", \"$http\", \"UiHelpers\", \"SessionService\", \"AjaxNg1\"];\r\n\r\n  /** Template for the report */\r\n  public templateName = \"workerSummaryReport\";\r\n\r\n  /** Boolean indicating if the refresh is in progress. */\r\n  public refreshInprogress: boolean;\r\n\r\n  /**Selected report language */\r\n  public lang: Language;\r\n\r\n  private renderedData: WorkerSummaryReportData;\r\n\r\n  private renderedLang: string;\r\n\r\n  private htmlData: any;\r\n\r\n  private reportOptions: ReportOptions;\r\n\r\n  private reportTemplate = \"workerSummaryReport\";\r\n\r\n  private reportData: ReportData<WorkerSummaryReportData> = {\r\n    headerFooter: {},\r\n    layout: {},\r\n    report: {},\r\n  };\r\n\r\n  private _reportLang: Language = Language.Default;\r\n\r\n\r\n\r\n  /**\r\n   * Creates a new CalcReportController\r\n   * @ignore\r\n   */\r\n  constructor(private templates: Templates,\r\n    private $sce: angular.ISCEService,\r\n    private settingsService: SettingsService,\r\n    private $timeout: angular.ITimeoutService,\r\n    private $http: angular.IHttpService,\r\n    private uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n    private ajax: Ajax\r\n  ) { }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.sessionService.getReportLang().then((lang) => {\r\n      this.reportLang = lang;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get _reportLang\r\n   */\r\n  public get reportLang() {\r\n    return this._reportLang;\r\n  }\r\n\r\n  /**\r\n   * Set _reportLang & lang\r\n   */\r\n  public set reportLang(lang: Language) {\r\n    this._reportLang = lang;\r\n    if (lang !== Language.Default) {\r\n      this.lang = this._reportLang;\r\n    } else {\r\n      this.sessionService.getReportLang().then(lang => {\r\n        this.lang = lang;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return languge text to ui\r\n   */\r\n  public get languageText() {\r\n    switch (this.reportLang) {\r\n      case Language.Fi:\r\n        return \"SALAXY.ENUM.Language.fi.label\";\r\n      case Language.En:\r\n        return \"SALAXY.ENUM.Language.en.label\";\r\n      case Language.Sv:\r\n        return \"SALAXY.ENUM.Language.sv.label\";\r\n      case Language.Default:\r\n        return \"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\";\r\n    }\r\n  }\r\n\r\n  /** Bindable and trusted html. */\r\n  public get html(): any {\r\n    if (!this.data) {\r\n      this.renderedData = null;\r\n      this.renderedLang = null;\r\n    } else {\r\n      const workerSummaryReportData = angular.copy(this.data);\r\n\r\n      if (!this.renderedData || !angular.equals(workerSummaryReportData, this.renderedData)\r\n        || this.renderedLang !== this.lang) {\r\n        this.lang = this.lang === Language.Default ? Language.Fi : this.lang;\r\n        this.renderedData = angular.copy(workerSummaryReportData);\r\n        this.renderedLang = this.lang;\r\n        this.refresh();\r\n      }\r\n    }\r\n    return this.htmlData;\r\n  }\r\n\r\n  private async refresh() {\r\n    if (this.refreshInprogress) {\r\n      return;\r\n    }\r\n    this.refreshInprogress = true;\r\n    this.settingsService.getReportOptions().then(async (options) => {\r\n      this.reportOptions = options;\r\n      const renderingLang = this.lang ?? Language.Fi;\r\n      await Translations.loadLanguage(renderingLang);\r\n      const reportOptions = this.getDefaultReportOptions(angular.copy(this.reportOptions));\r\n      this.reportData.headerFooter = WorkerSummaryMapper.getWorkerSummaryReportHeaderFooter(this.data, reportOptions, renderingLang);\r\n      this.reportData.report = WorkerSummaryMapper.getWorkerSummaryReport(this.data, renderingLang);\r\n      this.reportData.layout = WorkerSummaryMapper.getReportLayout(true, false);\r\n      const css = \"\";\r\n      this.reportData.layout.hasCustomCss = false;\r\n      this.reportData.layout.customCss = (css || \"\");\r\n      this.reportData.layout.margin = {\r\n        top: reportOptions.margin.top,\r\n        right: reportOptions.margin.right,\r\n        bottom: reportOptions.margin.bottom,\r\n        left: reportOptions.margin.left\r\n      };\r\n      const templates = new Templates();\r\n      this.reportData.headerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.headerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.reportData.footerHtml = this.reportOptions?.headerTemplate ? templates.getHtmlDynamic(this.reportOptions.footerTemplate, this.reportData.headerFooter, renderingLang) : \"\";\r\n      this.htmlData = this.$sce.trustAsHtml(this.templates.getHtml(this.templateName, this.reportData, renderingLang));\r\n      this.refreshInprogress = false;\r\n      this.$timeout();\r\n    });\r\n  }\r\n  /**\r\n   * Shows a download dialog for the given summary report.\r\n   * @param inline - If true, the download link opens the pdf into a new web page.\r\n   */\r\n  public showDownloadDialog(inline = false) {\r\n    const url = `${Configs.current.reportServer}/pdf?id=&reportType=${encodeURIComponent(\"yearlyWorkerSummary\")}&template=${encodeURIComponent(this.reportTemplate)}&language=${encodeURIComponent(this.lang)}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n    this.handlePdfRequest(url, inline, this.data);\r\n  }\r\n\r\n  private getDefaultReportOptions(optionsInput?: ReportOptions): ReportOptions {\r\n    optionsInput = optionsInput || {};\r\n    optionsInput.margin = optionsInput.margin || {};\r\n    optionsInput.margin.top = Numeric.parseNumber(optionsInput.margin.top) || 30;\r\n    optionsInput.margin.right = Numeric.parseNumber(optionsInput.margin.right) || 10;\r\n    optionsInput.margin.bottom = Numeric.parseNumber(optionsInput.margin.bottom) || 40;\r\n    optionsInput.margin.left = Numeric.parseNumber(optionsInput.margin.left) || 10;\r\n    return optionsInput;\r\n  }\r\n\r\n  /**\r\n   * Handles pdf request\r\n   * @param url post url\r\n   * @param inline inline pdf\r\n   * @param data business object\r\n   */\r\n  private handlePdfRequest(url: string, inline: boolean, data: SummaryReportData): void {\r\n    this.$http.post(url, { object: data }, { responseType: \"blob\" }).then((response) => {\r\n      if (response.data) {\r\n        if (inline) {\r\n          this.uiHelpers.openFile(response.data as any);\r\n        } else {\r\n          this.uiHelpers.downloadFile(response.data as any, response.headers(\"content-disposition\").split(\";\")[1].split(\"filename\")[1].split(\"=\")[1].trim().replace(/\"/g, \"\"));\r\n        }\r\n      }\r\n    }, (error) => {\r\n      console.error(error);\r\n    });\r\n  }\r\n\r\n}\r\n\r\n","import angular from \"angular\";\r\nimport { PeriodDateKind, PeriodType, Reports } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interaction for displaying worker summary report\r\n */\r\nexport class WorkerSummaryReportDisplayController implements angular.IController {\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Reports\"\r\n  ];\r\n  /**\r\n   * Creates a new instance of WorkerSummaryReportDisplayController\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private reports: Reports\r\n\r\n  ) { }\r\n\r\n  /**\r\n   * Parses workerId from report url\r\n   * @param reportUrl url to be parsed\r\n   * @returns workerId\r\n   */\r\n  public parseWorkerID(reportUrl: string) {\r\n    const regex = new RegExp(\"[?&]\" + \"id\" + \"(=([^&#]*)|&|#|$)\");\r\n    const results = regex.exec(reportUrl);\r\n    return results[2];\r\n  }\r\n\r\n  /**\r\n   * Query WorkerSummaryReportData and display it in dialog\r\n   * @param refDate date\r\n   */\r\n  public display(refDate: string, workerId: string, employerId: string): void {\r\n    const data = {\r\n      workerSummaryReportData: null,\r\n      isLoading: true\r\n    };\r\n    // Parsing id from url because listing does not provide workerID yet\r\n    this.reports.getWorkerSummaryReportData(refDate, workerId, employerId, PeriodType.Year, null, PeriodDateKind.SalaryDate ).then(workerSummaryReportData => {\r\n      data.workerSummaryReportData = workerSummaryReportData;\r\n      data.isLoading = false;\r\n    });\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/report/WorkerSummaryReport.html\",\r\n      null,\r\n      data,\r\n      null,\r\n      \"landscape\",\r\n      true);\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  Dates,\r\n  Reports,\r\n  Avatar,\r\n  Translations,\r\n  Employments,\r\n  EnumerationsLogic,\r\n  ODataQueryOptions,\r\n  EmploymentListItem,\r\n  HolidaysLogic,\r\n  HolidayCode,\r\n  HolidayCalculationDTO,\r\n  AccountingHolidayPayDebtReportDataYear,\r\n  AccountingHolidayPayDebtReportData,\r\n  Numeric,\r\n  HolidayYears,\r\n  Arrays,\r\n} from \"@salaxy/core\";\r\nimport { UiHelpers, ExcelHelpers, UiCrudHelpers } from \"../../services\";\r\n\r\n\r\n/**\r\n * Component for displaying holiday report.\r\n */\r\nexport class HolidayReportController implements angular.IController {\r\n\r\n\r\n  /** Ref date for the report. */\r\n  public refDate = Dates.getToday();\r\n\r\n  /** Current holiday years in the result. */\r\n  public years: string[] = [];\r\n\r\n  /** Current selected year. */\r\n  public year: string | undefined;\r\n\r\n  /** Result rows */\r\n  public resultRows: ResultRow[] = [];\r\n\r\n  /** Total holiday calculation */\r\n  public holidayCalc: {[key: string]: HolidayCalculationDTO };\r\n\r\n  /** Total of totals. */\r\n  public holidayCalcTotal: {[key: string]: number };\r\n\r\n  /**\r\n   * Helper flag for UI. Indicates whether the debt has been queried.\r\n   */\r\n  public hasQueryedDebt = false;\r\n\r\n  private data: AccountingHolidayPayDebtReportData;\r\n\r\n  private employmentListItems: EmploymentListItem[] = [];\r\n\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"HolidayYears\",\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n    \"Employments\",\r\n    \"UiCrudHelpers\",\r\n  ];\r\n\r\n  constructor(private holidayYears: HolidayYears, private reports: Reports, private uiHelpers: UiHelpers, private employments: Employments, private uiCrudHelpers: UiCrudHelpers,) {\r\n  }\r\n\r\n  /** Controller initialization */\r\n  public $onInit() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    this.loadEmployments().then( employments => {\r\n      this.employmentListItems = employments;\r\n      this.query();\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows an edit dialog for the employment.\r\n   * @param row Row that contains field employmentId (Identifier for the employment).\r\n   * @param row.employmentId The row must contain the employment identifier.\r\n   */\r\n  public showEditEmploymentDialog(row: ResultRow ): void {\r\n    if (!row.employment?.id) {\r\n      console.error(\"EmploymentId is missing\", row);\r\n      return;\r\n    }\r\n    this.uiCrudHelpers.openEditEmploymentDialog(row.employment?.id, \"default\", \"holidays\");\r\n  }\r\n\r\n  /** Query Holiday year data. */\r\n  public query(queryDebt = false): Promise<AccountingHolidayPayDebtReportData> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n\r\n    const apiQuery = () : Promise<AccountingHolidayPayDebtReportData> => {\r\n      if (queryDebt) {\r\n        return this.reports.getAccountingHolidayPayDebtReportData(this.refDate);\r\n      }\r\n      else {\r\n        return this.holidayYears.getForAllYears().then( (data) => ({\r\n            holidayCalc: {\r\n              totalAccruedHolidayPay : 0,\r\n              totalAccruedHolidayBonus: 0,\r\n              totalAccruedHolidaySocialSecurity: 0,\r\n              totalAccruedHolidayPension: 0,\r\n              totalAccruedHolidayUnemployment: 0,\r\n              totalAccruedHolidayAccidentInsurance: 0,\r\n              totalAccruedHolidayGroupLifeInsurance: 0,\r\n            },\r\n            holidayYears: data.map( (year) => ({\r\n              holidayYear: year,\r\n              holidayCalc: {}\r\n            })),\r\n          }));\r\n      }\r\n    };\r\n\r\n    return  apiQuery().then(data => {\r\n      this.data = data;\r\n      this.holidayCalc = {};\r\n      this.holidayCalc[\"total\"] = data.holidayCalc;\r\n      this.holidayCalcTotal = {};\r\n      this.holidayCalcTotal[\"total\"] = Numeric.round(\r\n        (data.holidayCalc?.totalAccruedHolidayPay ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidayBonus  ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidaySocialSecurity  ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidayPension  ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidayUnemployment  ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidayAccidentInsurance  ?? 0) +\r\n        (data.holidayCalc?.totalAccruedHolidayGroupLifeInsurance  ?? 0), 2);\r\n      this.resultRows = [];\r\n      this.years = [];\r\n      this.year = undefined;\r\n      this.data.holidayYears.forEach( (yearData) => {\r\n        const resultRow: ResultRow = {\r\n          employment: this.employmentListItems.find(x => x.id === yearData.holidayYear?.employmentId),\r\n          data: yearData,\r\n          holidayYearReportRow: this.getBlankHolidayYearReportRow(),\r\n        };\r\n        this.resultRows.push(resultRow);\r\n        if (this.years.indexOf(\"\" +yearData.holidayYear.year) < 0) {\r\n          this.years.push(\"\" +yearData.holidayYear.year);\r\n        }\r\n      });\r\n      this.years.sort();\r\n      this.years.reverse();\r\n      this.year = this.years.length > 0 ? this.years[0]: undefined;\r\n      for (const year of this.years) {\r\n        const yearData = this.data.holidayYears.filter(x => x.holidayYear.year == Number.parseInt(year));\r\n        const yearCalc = {\r\n            totalAccruedHolidayPay: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayPay ?? 0), 2),\r\n            totalAccruedHolidayBonus: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayBonus ?? 0), 2),\r\n            totalAccruedHolidaySocialSecurity: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidaySocialSecurity ?? 0), 2),\r\n            totalAccruedHolidayPension: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayPension ?? 0), 2),\r\n            totalAccruedHolidayUnemployment: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayUnemployment ?? 0), 2),\r\n            totalAccruedHolidayAccidentInsurance: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayAccidentInsurance ?? 0), 2),\r\n            totalAccruedHolidayGroupLifeInsurance: Numeric.round(Arrays.sum( yearData, (x) => x.holidayCalc?.totalAccruedHolidayGroupLifeInsurance ?? 0), 2),\r\n          };\r\n        this.holidayCalc[year] = yearCalc;\r\n        this.holidayCalcTotal[year] = Numeric.round(\r\n          (yearCalc.totalAccruedHolidayPay ?? 0) +\r\n          (yearCalc.totalAccruedHolidayBonus  ?? 0) +\r\n          (yearCalc.totalAccruedHolidayPension  ?? 0) +\r\n          (yearCalc.totalAccruedHolidayUnemployment  ?? 0) +\r\n          (yearCalc.totalAccruedHolidayAccidentInsurance  ?? 0) +\r\n          (yearCalc.totalAccruedHolidayGroupLifeInsurance  ?? 0), 2);\r\n      }\r\n\r\n      this.createHolidayYearReportRows();\r\n      if(queryDebt) {\r\n        this.hasQueryedDebt = true;\r\n      }\r\n\r\n      loading.dismiss();\r\n      return data;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Export totalRows to excel\r\n   */\r\n   public exportToExcel(){\r\n\r\n    const year = Number.parseInt(this.year ?? \"0\");\r\n    if (year === 0) {\r\n      return;\r\n    }\r\n\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const tableData = [];\r\n    const headers = [\r\n      Translations.get(\"SALAXY.NG1_Other.Roles.worker\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.startDate\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.endDate\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.employment\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.salary\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.holidayCode\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.periodDefaultAccrual\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.table.holidayPayCalculation\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.startSaldo\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.total\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paid\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.available\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidaySalary\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayCompensation\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paidBonus\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.availableBonus\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayBonus\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayPayDailySalary\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayPay\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayBonus\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidaySocialSecurity\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayPension\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayUnemployment\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayAccidentInsurance\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayGroupLifeInsurance\"),\r\n      Translations.get(\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayTotal\")\r\n    ];\r\n    tableData.push(headers);\r\n    const rowData = this.resultRows.filter(x => x.data.holidayYear.year == year).map(x => {\r\n      const row = x.holidayYearReportRow;\r\n      return [\r\n        row.workerAvatar.displayName,\r\n        row.startDate = Dates.format(row.startDate),\r\n        row.endDate = Dates.format(row.endDate),\r\n        row.employmentType,\r\n        row.grossSalary,\r\n        row.holidayCode,\r\n        row.periodDefaultAccrual,\r\n        row.holidayPayCalculation,\r\n        row.startSaldo,\r\n        row.total,\r\n        row.paid,\r\n        row.available,\r\n        row.holidaySalary,\r\n        row.holidayCompensation,\r\n        row.paidBonus,\r\n        row.availableBonus,\r\n        row.holidayBonus,\r\n        row.holidayPayDailySalary,\r\n        row.totalAccruedHolidayPay,\r\n        row.totalAccruedHolidayBonus,\r\n        row.totalAccruedHolidaySocialSecurity,\r\n        row.totalAccruedHolidayPension,\r\n        row.totalAccruedHolidayUnemployment,\r\n        row.totalAccruedHolidayAccidentInsurance,\r\n        row.totalAccruedHolidayGroupLifeInsurance,\r\n        row.totalAccruedHolidayTotal\r\n      ];\r\n    });\r\n    tableData.push(...rowData);\r\n\r\n    if (tableData.length> 0) {\r\n      ExcelHelpers.export(tableData, `holidayYear-${year}`).then(() => {\r\n        loading.dismiss();\r\n      });\r\n    }\r\n    else\r\n    {\r\n      loading.dismiss();\r\n    }\r\n  }\r\n\r\n  private async loadEmployments(): Promise<EmploymentListItem[]> {\r\n    const items: any[] = [];\r\n    const loadItems = (nextPageLink: string = null): Promise<string> => {\r\n      let options: ODataQueryOptions = null;\r\n      const queryString = nextPageLink?.indexOf(\"?\") ?? -1;\r\n      if (queryString >= 0) {\r\n        const searchParams = new URLSearchParams(nextPageLink.substr(queryString));\r\n        if (searchParams.get(\"$skip\")) {\r\n          options = { $skip:  Number(searchParams.get(\"$skip\"))};\r\n        }\r\n      }\r\n      return this.employments.getOData(options).then((data) => {\r\n        items.push(...data.items);\r\n        return data.nextPageLink ? loadItems(data.nextPageLink) : null;\r\n      });\r\n    };\r\n\r\n    return loadItems().then(() => {\r\n      return items;\r\n    });\r\n\r\n  }\r\n\r\n  private createHolidayYearReportRows(): void {\r\n    this.resultRows.forEach(resultRow => {\r\n      resultRow.holidayYearReportRow.workerAvatar = resultRow.employment?.otherPartyInfo?.avatar;\r\n      resultRow.holidayYearReportRow.workerId = resultRow.employment?.otherPartyInfo?.avatar?.id;\r\n      resultRow.holidayYearReportRow.employmentId = resultRow.employment?.id;\r\n      resultRow.holidayYearReportRow.startDate = resultRow.employment?.data?.startDate;\r\n      resultRow.holidayYearReportRow.endDate = resultRow.employment?.data?.endDate;\r\n      resultRow.holidayYearReportRow.employmentType = EnumerationsLogic.getEnumLabel(\"EmploymentRelationType\", resultRow.employment?.data?.type) === \"#err EmploymentRelationType.NoEnumValue\" ? \"-\" : EnumerationsLogic.getEnumLabel(\"EmploymentRelationType\", resultRow.employment?.data?.type);\r\n      resultRow.holidayYearReportRow.grossSalary =  Numeric.round(resultRow.employment?.grossSalary ?? 0, 2);\r\n      resultRow.holidayYearReportRow.holidayCode = (resultRow.data.holidayYear.spec.code ?? HolidayCode.Undefined) == HolidayCode.Undefined ? \"\" : EnumerationsLogic.getEnumLabel(\"HolidayCode\", resultRow.data.holidayYear.spec.code);\r\n      resultRow.holidayYearReportRow.periodDefaultAccrual = (resultRow.data.holidayYear.spec.code == HolidayCode.Permanent14Days || resultRow.data.holidayYear.spec.code == HolidayCode.Permanent35Hours || resultRow.data.holidayYear.spec.code == HolidayCode.TemporaryTimeOff) ? resultRow.data.holidayYear.accrual.defaultAccrual : null;\r\n      resultRow.holidayYearReportRow.holidayPayCalculation = (resultRow.data.holidayYear.spec.holidayPayCalculation ?? \"undefined\") == \"undefined\" ? \"\" : EnumerationsLogic.getEnumLabel(\"HolidayPayCalculation\", resultRow.data.holidayYear.spec.holidayPayCalculation);\r\n      resultRow.holidayYearReportRow.startSaldo = Numeric.round(resultRow.data.holidayYear.accrual.startSaldo ?? 0, 0);\r\n      resultRow.holidayYearReportRow.total =  Numeric.round(resultRow.data.holidayYear.accrual.total ?? 0, 0);\r\n      resultRow.holidayYearReportRow.paid =  Numeric.round(HolidaysLogic.getPaidHolidaysCalculation(resultRow.data.holidayYear, \"total\").holidayDays ?? 0, 0);\r\n      resultRow.holidayYearReportRow.available =  Numeric.round(HolidaysLogic.getPaidHolidaysCalculation(resultRow.data.holidayYear, \"endSaldo\").holidayDays ?? 0, 0);\r\n      resultRow.holidayYearReportRow.holidaySalary = HolidaysLogic.getPaidHolidaysCalculation(resultRow.data.holidayYear, \"total\").holidaySalary ?? 0;\r\n      resultRow.holidayYearReportRow.holidayCompensation = HolidaysLogic.getPaidHolidaysCalculation(resultRow.data.holidayYear, \"total\").holidayCompensation ?? 0;\r\n      resultRow.holidayYearReportRow.paidBonus =  Numeric.round(HolidaysLogic.getPaidBonusCalculation(resultRow.data.holidayYear, \"total\").holidayDays ?? 0, 0);\r\n      resultRow.holidayYearReportRow.availableBonus =  Numeric.round(HolidaysLogic.getPaidBonusCalculation(resultRow.data.holidayYear, \"endSaldo\").holidayDays ?? 0, 0);\r\n      resultRow.holidayYearReportRow.holidayBonus = HolidaysLogic.getPaidBonusCalculation(resultRow.data.holidayYear, \"total\").holidayBonus ?? 0;\r\n      resultRow.holidayYearReportRow.holidayPayDailySalary = HolidaysLogic.getHolidayPayDailySalary(resultRow.data.holidayYear)?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayPay = resultRow.data.holidayCalc?.totalAccruedHolidayPay ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayBonus = resultRow.data.holidayCalc?.totalAccruedHolidayBonus ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidaySocialSecurity = resultRow.data.holidayCalc?.totalAccruedHolidaySocialSecurity ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayPension = resultRow.data.holidayCalc?.totalAccruedHolidayPension ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayUnemployment = resultRow.data.holidayCalc?.totalAccruedHolidayUnemployment ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayAccidentInsurance = resultRow.data.holidayCalc?.totalAccruedHolidayAccidentInsurance ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayGroupLifeInsurance = resultRow.data.holidayCalc?.totalAccruedHolidayGroupLifeInsurance ?? 0;\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayTotal = Numeric.round(\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayPay +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayBonus +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidaySocialSecurity +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayPension +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayUnemployment +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayAccidentInsurance +\r\n      resultRow.holidayYearReportRow.totalAccruedHolidayGroupLifeInsurance, 2);\r\n    });\r\n  }\r\n  private getBlankHolidayYearReportRow(): HolidayYearReportRow {\r\n    return {\r\n      workerAvatar: null,\r\n      workerId: null,\r\n      employmentId: null,\r\n      startDate: null,\r\n      endDate: null,\r\n      employmentType: null,\r\n      grossSalary: 0,\r\n      holidayCode: null,\r\n      periodDefaultAccrual: null,\r\n      holidayPayCalculation: null,\r\n      startSaldo: 0,\r\n      total: 0,\r\n      paid: 0,\r\n      available: 0,\r\n      holidaySalary: 0,\r\n      holidayCompensation: 0,\r\n      paidBonus: 0,\r\n      availableBonus: 0,\r\n      holidayBonus: 0,\r\n      holidayPayDailySalary: 0,\r\n      totalAccruedHolidayPay: 0,\r\n      totalAccruedHolidayBonus: 0,\r\n      totalAccruedHolidaySocialSecurity: 0,\r\n      totalAccruedHolidayPension: 0,\r\n      totalAccruedHolidayUnemployment: 0,\r\n      totalAccruedHolidayAccidentInsurance: 0,\r\n      totalAccruedHolidayGroupLifeInsurance: 0,\r\n      totalAccruedHolidayTotal: 0,\r\n    };\r\n  }\r\n}\r\n\r\ninterface ResultRow {\r\n  employment: EmploymentListItem;\r\n  data: AccountingHolidayPayDebtReportDataYear;\r\n  holidayYearReportRow: HolidayYearReportRow;\r\n}\r\n\r\ninterface HolidayYearReportRow {\r\n  workerAvatar: Avatar;\r\n  workerId: string;\r\n  employmentId: string;\r\n  startDate: string;\r\n  endDate: string;\r\n  employmentType: string;\r\n  grossSalary: number;\r\n  holidayCode: string;\r\n  periodDefaultAccrual: number;\r\n  holidayPayCalculation: string;\r\n  startSaldo: number;\r\n  total: number;\r\n  paid: number;\r\n  available: number;\r\n  holidaySalary: number;\r\n  holidayCompensation: number;\r\n  paidBonus: number;\r\n  availableBonus: number;\r\n  holidayBonus: number;\r\n  holidayPayDailySalary: number;\r\n\r\n  totalAccruedHolidayPay: number;\r\n  /** Total sum of accrued holiday pays. */\r\n  totalAccruedHolidayBonus: number;\r\n  /** Total sum of social security payments for accrued holiday pays. */\r\n  totalAccruedHolidaySocialSecurity: number;\r\n  /** Total sum of pension payments for accrued holiday pays. */\r\n  totalAccruedHolidayPension: number;\r\n  /** Total sum of unemployment insurance payments for accrued holiday pays. */\r\n  totalAccruedHolidayUnemployment: number;\r\n  /** Total accident insurance. */\r\n  totalAccruedHolidayAccidentInsurance: number;\r\n  /** Total accident insurance. */\r\n  totalAccruedHolidayGroupLifeInsurance: number;\r\n  totalAccruedHolidayTotal: number;\r\n\r\n}","import angular from \"angular\";\r\nimport JSZip from \"@progress/jszip-esm\";\r\nimport * as FileSaver from \"file-saver\";\r\nimport { Ajax, Configs, Translations, Texts, Dates } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Provides functionality to export salary slip(s) as pdf or zipped pdf.\r\n */\r\nexport class SalarySlipDownloadController implements angular.IController {\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"$http\",\r\n    \"AjaxNg1\",\r\n    \"UiHelpers\"\r\n  ];\r\n\r\n  constructor(\r\n    private $http: angular.IHttpService,\r\n    private ajax: Ajax,\r\n    private uiHelpers: UiHelpers\r\n  ) {}\r\n\r\n  /**\r\n   * Export items\r\n   * One item is exported as pdf and multiple items are exported as zip containg pdfs.\r\n   */\r\n  public async export(items: any[]) {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    const promises = items.map(x => {\r\n      const url = `${Configs.current.apiServer}/v03/api/reports/assure-pdf/salarySlip?language=${encodeURIComponent(Translations.getLanguage())}&ids=${x.id}&disposition=inline&access_token=${this.ajax.getCurrentToken()}`;\r\n      return this.$http.get(url, { responseType: \"blob\" });\r\n    });\r\n    const responses = await Promise.all(promises);\r\n    if(responses.length === 1) {\r\n      this.uiHelpers.downloadFile(responses[0].data as any, decodeURIComponent(responses[0].headers(\"content-disposition\")).match(/filename\\s*=\\s*\"?(?<file>.*?)(?:\\s*;|\"|\\s*$)/)?.groups?.file);\r\n      loading.dismiss();\r\n    } else {\r\n      const zip = new JSZip();\r\n      const fileNames = {};\r\n      responses.forEach(response => {\r\n        const fileName = `${decodeURIComponent(response.headers(\"content-disposition\")).match(/filename\\s*=\\s*\"?(?<file>.*?)(?:\\s*;|\"|\\s*$)/)?.groups?.file}`;\r\n        if(Object.keys(fileNames).includes(fileName)) {\r\n          ++fileNames[fileName];\r\n          zip.file(`${fileNames[fileName]}_${fileName}`, response.data as Blob);\r\n        } else {\r\n          fileNames[fileName] = 1;\r\n          zip.file(fileName, response.data as Blob);\r\n        }\r\n      });\r\n      const zipBlob = await zip.generateAsync({type: \"blob\", mimeType: \"application/zip\"});\r\n      FileSaver.saveAs(zipBlob, Texts.escapeFileName(`${Translations.get(\"SALAXY.UI_Terms.downLoadableMaterialTypes.calculations\")}_${Dates.format(\"today\",\"YYYYMMDD\")}`));\r\n      loading.dismiss();\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingData, Dates, Reports } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Provides functionality for building ad hoc accounting holiday pay debt reports.\r\n */\r\nexport class AccountingHolidayPayDebtReportQueryController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  /**\r\n   * Report view table only (partial) or pdf preview (full)\r\n   * Defaults to 'partial'\r\n   */\r\n  public view: \"partial\" | \"full\";\r\n\r\n  /** Ref date to which the debt is calculated. */\r\n  public refDate: string = Dates.getToday();\r\n\r\n  /** Accounting data */\r\n  public data: AccountingData;\r\n\r\n  /**Selected report language */\r\n  public lang: string;\r\n\r\n  /** Data reader for the control. */\r\n  public dataReader = {\r\n  /**\r\n   * Function to read data into given array\r\n   */\r\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n   read: (target: string, ruleSet: string, arr: AccountingData[], message: string): Promise<void> => {\r\n      if (this.data) {\r\n        arr.push(this.data);\r\n      }\r\n      return Promise.resolve();\r\n    },\r\n    /** Optional label for data export */\r\n    exportLabel: null,\r\n    /** Indicates if the export is not possible */\r\n    disabled: () => !this.data,\r\n    /* Indicates if row is expandable */\r\n    showExpand: true,\r\n    /* Indicates if rows exists*/\r\n    hasRows: () => !this.data?.ledgerAccounts\r\n  };\r\n\r\n  constructor(\r\n    private reportsApi: Reports,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /**\r\n   * Initialize controller values.\r\n   */\r\n  public $onInit() {\r\n    this.view = this.view || \"partial\";\r\n  }\r\n\r\n  /** Queries the report data. */\r\n  public queryData(target = \"default\") {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    this.reportsApi.getAccountingDataForHolidayPayDebt(this.refDate, target)\r\n      .then((result) => {\r\n        this.data = result;\r\n        loading.dismiss();\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { HolidayYears, HolidayPayCalculationReportData, IrRow, CalculationRowType, EnumerationsLogic, IncomeTypesLogic, HolidayPayCalculationReportDataCalc, Arrays, Numeric, ODataResult, ApiListItem } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Provides functionality for building ad hoc holiday pay reports.\r\n */\r\nexport class HolidayPayReportQueryController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"HolidayYears\",\r\n    \"UiHelpers\",\r\n    \"$routeParams\",\r\n  ];\r\n\r\n  /** Raw report from api */\r\n  public data: HolidayPayCalculationReportData;\r\n\r\n  /** Current employment id */\r\n  public employmentId: string;\r\n\r\n  /** Current holidayYear */\r\n  public year: number;\r\n\r\n  //** All holiday years for the worker */\r\n  public years: string[] = [];\r\n\r\n  public totals: HolidayPayCalculationReportDataCalc = {\r\n     total: 0,\r\n     hours: 0,\r\n     overtimeHours: 0,\r\n     workingDays: 0,\r\n     absenceDays: 0\r\n  };\r\n\r\n  constructor(\r\n    private holidayYearsApi: HolidayYears,\r\n    private uiHelpers: UiHelpers,\r\n    private $routeParams: angular.route.IRouteParamsService,\r\n\r\n  ) {\r\n  }\r\n\r\n  /** Controller initialization */\r\n  public $onInit() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const crudItemId = this.$routeParams.crudItemId ?? \"\";\r\n    this.year = crudItemId.split(\"/\")[0];\r\n    this.employmentId = crudItemId.split(\"/\")[1];\r\n    this.loadYears().then( years => {\r\n      this.years = years;\r\n      this.query();\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n\r\n  /** Queries the report data. */\r\n  public query() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    this.holidayYearsApi.getHolidayPayCalculationReportData(this.year, this.employmentId)\r\n      .then((result) => {\r\n        this.data = result;\r\n        // round accruals\r\n        (this.data.holidayYear.accrual.total as any) = Numeric.round(this.data.holidayYear.accrual.total, 0);\r\n        this.totals.total = Numeric.round(Arrays.sum(this.data.calculations, (x) => x.total), 2);\r\n        this.totals.hours = Numeric.round(Arrays.sum(this.data.calculations, (x) => x.hours), 2);\r\n        this.totals.overtimeHours = Numeric.round(Arrays.sum(this.data.calculations, (x) => x.overtimeHours), 2);\r\n        this.totals.workingDays = Numeric.round(Arrays.sum(this.data.calculations, (x) => x.workingDays), 2);\r\n        this.totals.absenceDays = Numeric.round(Arrays.sum(this.data.calculations, (x) => x.absenceDays), 2);\r\n        loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Returns label for the ir row. */\r\n  public getLabel(irRow: IrRow): string {\r\n\r\n    //TODO: add this logic to UiHelpers.\r\n\r\n    if (irRow.message) {\r\n      return irRow.message;\r\n    }\r\n    let rowType = irRow.data.calculationRowType || CalculationRowType.Unknown;\r\n    rowType = (rowType.substr(0, 1).toLowerCase() + rowType.substr(1)) as CalculationRowType;\r\n    const code = irRow.irData?.code as number;\r\n    const kind = irRow.data.kind as string;\r\n\r\n    let label = \"\";\r\n    if (rowType === CalculationRowType.IrIncomeType) {\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => (kind && x.transactionCode === kind) || (code > 0 && x.code === code))?.label;\r\n    } else if (rowType === CalculationRowType.MealBenefit && code !== 334) {\r\n      // Meal benefit deductions\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => code > 0 && x.code === code)?.label;\r\n    } else if([\r\n      CalculationRowType.Unknown,\r\n      CalculationRowType.CarBenefit,\r\n      CalculationRowType.BicycleBenefit,\r\n      CalculationRowType.SubsidisedCommute,\r\n      CalculationRowType.TaxAtSource,\r\n      CalculationRowType.HourlySalaryWithWorkingTimeCompensation\r\n    ].includes(rowType))\r\n    {\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => code > 0 && x.code === code)?.label;\r\n    }\r\n    else if([\r\n      CalculationRowType.DailyAllowance,\r\n      CalculationRowType.EmploymentTermination,\r\n      CalculationRowType.WorkingTimeCompensation,\r\n      CalculationRowType.Remuneration,\r\n      CalculationRowType.OtherCompensation,\r\n      CalculationRowType.NonProfitOrg,\r\n      CalculationRowType.MealBenefit, // main MealBenefit\r\n      CalculationRowType.Training,\r\n      CalculationRowType.PaidSickLeave,\r\n    ].includes(rowType) && kind) {\r\n      label =  EnumerationsLogic.getEnumLabel(`${irRow.data.calculationRowType}Kind`, kind, null, null);\r\n    }\r\n    return label || EnumerationsLogic.getEnumLabel(\"CalculationRowType\", rowType, null, null);\r\n\r\n  }\r\n\r\n  private loadYears(): Promise<string[]> {\r\n    return this.holidayYearsApi.getOData({$filter: `data/employmentId eq '${this.employmentId}'`}).then((data: ODataResult<ApiListItem>) => {\r\n        const years = data.items.map((x) => \"\" + x.data.year);\r\n        years.sort();\r\n        years.reverse();\r\n        return years;\r\n      });\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport {\r\n  Calculation,\r\n  CalculationRowType,\r\n  Dates,\r\n  PeriodDateKind,\r\n  PeriodType,\r\n  Reports,\r\n  SummaryReportData,\r\n  Avatar,\r\n  Translations,\r\n  Numeric,\r\n  Employments,\r\n  EnumerationsLogic,\r\n  EmploymentTerminationKind,\r\n  IrRow,\r\n  IncomeTypesLogic,\r\n  WorkingTimeCompensationKind,\r\n  RemunerationKind,\r\n  OtherCompensationKind,\r\n  NonProfitOrgKind,\r\n  TrainingKind,\r\n  Unit,\r\n  PaidSickLeaveKind,\r\n  DailyAllowanceKind,\r\n  AllowanceCode,\r\n  ODataQueryOptions,\r\n  Objects,\r\n  EmploymentListItem,\r\n} from \"@salaxy/core\";\r\nimport { SummaryMapper } from \"@salaxy/reports\";\r\nimport { UiHelpers, ExcelHelpers, UiCrudHelpers } from \"../../services\";\r\n\r\n/**\r\n * Component for displaying summary report of selected period.\r\n */\r\nexport class SummaryReportQueryController implements angular.IController {\r\n  /** Parameters related to report query*/\r\n  public queryOptions: {\r\n    /** Period type for the query. */\r\n    periodType: PeriodType,\r\n    /** Ref date for the period. */\r\n    refDate?: string,\r\n    /** End date for the custom period. */\r\n    endDate?: string,\r\n    /** Period date kind */\r\n    periodDateKind: PeriodDateKind,\r\n  } = {\r\n    periodType: PeriodType.Year,\r\n    refDate: Dates.getDate(Dates.getYear(\"today\"), 1, 1),\r\n    endDate: Dates.getDate(Dates.getYear(\"today\"), 12, 31),\r\n    periodDateKind: PeriodDateKind.SalaryDate,\r\n  };\r\n\r\n  /** Result rows */\r\n  public resultRows: ResultRow[] = [];\r\n\r\n  /** Current tab. */\r\n  public currentTab: \"incomeReport\" | \"salaryPaymentReport\" = \"incomeReport\";\r\n\r\n  private summaryReportData: SummaryReportData;\r\n\r\n  private employmentListItems: EmploymentListItem[] = [];\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Reports\",\r\n    \"UiHelpers\",\r\n    \"Employments\",\r\n    \"UiCrudHelpers\",\r\n  ];\r\n\r\n  constructor(private reports: Reports, private uiHelpers: UiHelpers, private employments: Employments, private uiCrudHelpers: UiCrudHelpers,) {\r\n  }\r\n\r\n  /** Controller initialization */\r\n  public $onInit() {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    this.loadEmployments().then( employments => {\r\n      this.employmentListItems = employments;\r\n      this.query();\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Return query info text */\r\n  public getQueryInfoText(): string {\r\n    if (this.summaryReportData?.startDate && this.summaryReportData?.endDate) {\r\n      return `${Translations.get(\"SALAXY.NG1.HolidayReportComponent.irIncomeTypeReportInfo\")}: ${Dates.getFormattedDate(this.summaryReportData.startDate)} - ${Dates.getFormattedDate(this.summaryReportData.endDate)}`;\r\n    }\r\n    return \"\";\r\n  }\r\n\r\n  /**\r\n   * Shows the period selection dialog and makes the search.\r\n   */\r\n  public showPeriodSelection() {\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/report/modals/SummaryReportPeriodSelection.html\",\r\n      this.queryOptions,\r\n      null).then((periodResult) => {\r\n        if (periodResult.action === \"ok\") {\r\n          this.queryOptions = periodResult.item;\r\n          this.query();\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Shows an edit dialog for the employment.\r\n   * @param row Row that contains field employmentId (Identifier for the employment).\r\n   * @param row.employmentId The row must contain the employment identifier.\r\n   */\r\n  public showEditEmploymentDialog(row: { employmentId: string } ): void {\r\n    if (!row.employmentId) {\r\n      console.error(\"EmploymentId is missing\", row);\r\n      return;\r\n    }\r\n    this.uiCrudHelpers.openEditEmploymentDialog(row.employmentId, \"default\").then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.query();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Filters zero rows off\r\n   * @returns IrCodeIncomeReportRow[] containing not zero rows\r\n   */\r\n  public getIrReportRows(): IrCodeIncomeReportRow[] {\r\n    const results: IrCodeIncomeReportRow[] = [];\r\n    const irRows = this.resultRows.map(x => x.irCodeIncomeReportRow);\r\n    irRows.forEach( irRow => {\r\n      if(irRow) {\r\n        results.push(irRow);\r\n      }\r\n    });\r\n    return results;\r\n  }\r\n\r\n  /**\r\n   * Groups each result rows summary report entrepreneur results\r\n   * @returns array of grouped entrepreneur results\r\n   */\r\n  public getEntrepreneurSummaryReportResults(): SummaryReportRowResult[] {\r\n    const results = [];\r\n    this.resultRows.forEach(resultRow => {\r\n      if(resultRow?.summaryReportRow?.result?.entrepreneurResult) {\r\n        resultRow.summaryReportRow.result = resultRow.summaryReportRow.result || {};\r\n        resultRow.summaryReportRow.result.entrepreneurResult = resultRow.summaryReportRow.result.entrepreneurResult || this.getBlankSummaryReportRowResult();\r\n        resultRow.summaryReportRow.result.entrepreneurResult.avatar = resultRow.avatar;\r\n        resultRow.summaryReportRow.result.entrepreneurResult.workerId = resultRow.workerId;\r\n        resultRow.summaryReportRow.result.entrepreneurResult.employmentId = resultRow.employmentId;\r\n        results.push(resultRow.summaryReportRow.result.entrepreneurResult);\r\n      }\r\n    });\r\n    return results;\r\n  }\r\n\r\n  /**\r\n   * Groups each result rows summary report worker results\r\n   * @returns array of grouped worker results\r\n   */\r\n  public getWorkerSummaryReportResults(): SummaryReportRowResult[] {\r\n    const results = [];\r\n    this.resultRows.forEach(resultRow => {\r\n      if(resultRow.summaryReportRow.result.workerResult) {\r\n        resultRow.summaryReportRow.result.workerResult.avatar = resultRow.avatar;\r\n        resultRow.summaryReportRow.result.workerResult.workerId = resultRow.workerId;\r\n        resultRow.summaryReportRow.result.workerResult.employmentId = resultRow.employmentId;\r\n        results.push(resultRow.summaryReportRow.result.workerResult);\r\n      }\r\n    });\r\n    return results;\r\n  }\r\n\r\n  /**\r\n   * Return one total result as array (all total results are same)\r\n   * @returns array of total results\r\n   */\r\n  public getTotalSummaryReportResults():SummaryReportRowResult[] {\r\n    return [this.resultRows[0]?.summaryReportRow?.result?.totalResult] || [];\r\n  }\r\n\r\n  /**\r\n   * Export totalRows to excel\r\n   */\r\n   public exportToExcel(){\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    const tableData = [];\r\n    if(this.currentTab === \"incomeReport\") {\r\n      const irReportRows = this.getIrReportRows();\r\n      if (irReportRows.length > 0) {\r\n        tableData.push([Translations.get(\"SALAXY.NG1_Other.Roles.worker\"), ...irReportRows[0].rows.map(row => row.label)]);\r\n        const rowData = irReportRows.map(row => {\r\n          return [row.workerAvatar.displayName, ...row.rows.map(item => item.total)];\r\n        });\r\n        tableData.push(...rowData);\r\n      }\r\n    }\r\n    else if(this.currentTab === \"salaryPaymentReport\") {\r\n      const headers = [\r\n        Translations.get(\"SALAXY.NG1_Other.Roles.worker\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalGrossSalary\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalRowCategory\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.benefits\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.irCode\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalTaxable\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.tax\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.pension\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.unemploymentInsurance\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.unionPayment\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.foreclosure\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.otherDeductions\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalExpenses\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalWorkerPayment\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalPayment\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.palkkaus\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.service\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.socialSecurity\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.totalPensions\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.employerPension\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.unemployment\"),\r\n        Translations.get(\"SALAXY.REPORTS.summary.table.employerUnemployment\")\r\n      ];\r\n      tableData.push(headers);\r\n\r\n      if(this.getEntrepreneurSummaryReportResults().length > 0) {\r\n        const rowData = this.getEntrepreneurSummaryReportResults().map(row => {\r\n          return [\r\n            `${row.avatar.displayName} (YEL)`,\r\n            row.totalGrossSalary,\r\n            row.totalRowCategory,\r\n            row.benefits,\r\n            row.irCode,\r\n            row.totalTaxable,\r\n            row.tax,\r\n            row.pension,\r\n            row.unemploymentInsurance,\r\n            row.unionPayment,\r\n            row.foreclosure,\r\n            row.otherDeductions,\r\n            row.totalExpenses,\r\n            row.totalWorkerPayment,\r\n            row.totalPayment,\r\n            row.palkkaus,\r\n            row.service,\r\n            row.socialSecurity,\r\n            row.totalPensions,\r\n            row.employerPension,\r\n            row.unemployment,\r\n            row.employerUnemployment,\r\n          ];\r\n        });\r\n        tableData.push(...rowData);\r\n      }\r\n    if(this.getWorkerSummaryReportResults().length > 0) {\r\n      const rowData = this.getWorkerSummaryReportResults().map(row => {\r\n        return [\r\n          `${row.avatar.displayName} (TyEL)`,\r\n          row.totalGrossSalary,\r\n          row.totalRowCategory,\r\n          row.benefits,\r\n          row.irCode,\r\n          row.totalTaxable,\r\n          row.tax,\r\n          row.pension,\r\n          row.unemploymentInsurance,\r\n          row.unionPayment,\r\n          row.foreclosure,\r\n          row.otherDeductions,\r\n          row.totalExpenses,\r\n          row.totalWorkerPayment,\r\n          row.totalPayment,\r\n          row.palkkaus,\r\n          row.service,\r\n          row.socialSecurity,\r\n          row.totalPensions,\r\n          row.employerPension,\r\n          row.unemployment,\r\n          row.employerUnemployment,\r\n        ];\r\n      });\r\n      tableData.push(...rowData);\r\n    }\r\n    if(this.getWorkerSummaryReportResults().length > 0 || this.getEntrepreneurSummaryReportResults().length > 0) {\r\n      const rowData = this.getTotalSummaryReportResults().map(row => {\r\n        return [\r\n          Translations.get(\"SALAXY.REPORTS.summary.table.total\"),\r\n          row.totalGrossSalary,\r\n          row.totalRowCategory,\r\n          row.benefits,\r\n          row.irCode,\r\n          row.totalTaxable,\r\n          row.tax,\r\n          row.pension,\r\n          row.unemploymentInsurance,\r\n          row.unionPayment,\r\n          row.foreclosure,\r\n          row.otherDeductions,\r\n          row.totalExpenses,\r\n          row.totalWorkerPayment,\r\n          row.totalPayment,\r\n          row.palkkaus,\r\n          row.service,\r\n          row.socialSecurity,\r\n          row.totalPensions,\r\n          row.employerPension,\r\n          row.unemployment,\r\n          row.employerUnemployment,\r\n        ];\r\n      });\r\n      tableData.push(...rowData);\r\n    }\r\n    }\r\n    const reportName = this.currentTab == \"incomeReport\" ? `incomeReport-${Dates.getToday()}` : `salaryPaymentReport-${Dates.getToday()}`;\r\n\r\n    if (tableData.length> 0) {\r\n      ExcelHelpers.export(tableData, reportName).then(() => {\r\n        loading.dismiss();\r\n      });\r\n    }\r\n    else\r\n    {\r\n      loading.dismiss();\r\n    }\r\n  }\r\n\r\n  private async loadEmployments(): Promise<EmploymentListItem[]> {\r\n    const items: any[] = [];\r\n    const loadItems = (nextPageLink: string = null): Promise<string> => {\r\n      let options: ODataQueryOptions = null;\r\n      const queryString = nextPageLink?.indexOf(\"?\") ?? -1;\r\n      if (queryString >= 0) {\r\n        const searchParams = new URLSearchParams(nextPageLink.substr(queryString));\r\n        if (searchParams.get(\"$skip\")) {\r\n          options = { $skip:  Number(searchParams.get(\"$skip\"))};\r\n        }\r\n      }\r\n      return this.employments.getOData(options).then((data) => {\r\n        items.push(...data.items);\r\n        return data.nextPageLink ? loadItems(data.nextPageLink) : null;\r\n      });\r\n    };\r\n\r\n    return loadItems().then(() => {\r\n      return items;\r\n    });\r\n\r\n  }\r\n\r\n  private query(): Promise<SummaryReportData> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    return this.reports.getSummaryReportData(`${Dates.asDate(this.queryOptions.refDate)}`, this.queryOptions.periodType, `${Dates.asDate(this.queryOptions.endDate)}`, this.queryOptions.periodDateKind).then(data => {\r\n      this.summaryReportData = data;\r\n      this.resultRows = [];\r\n\r\n      this.summaryReportData?.calculations?.forEach(calc => {\r\n        let resultRow = this.resultRows.find(x => x.employmentId === calc.worker?.employmentId);\r\n        if(!resultRow) {\r\n          const newRow = this.getBlankResultRow();\r\n          newRow.employmentId = calc.worker.employmentId;\r\n          newRow.avatar = this.employmentListItems.find(x => x.id === calc.worker.employmentId)?.otherPartyInfo?.avatar;\r\n          newRow.workerId = this.employmentListItems.find(x => x.id === calc.worker.employmentId)?.otherPartyInfo?.avatar?.id;\r\n          this.resultRows.push(newRow);\r\n          resultRow = newRow;\r\n        }\r\n        resultRow.calculations.push(calc);\r\n      });\r\n      this.createIrReportRows();\r\n      this.createSummaryReportRows();\r\n      loading.dismiss();\r\n      return data;\r\n    });\r\n  }\r\n\r\n  private createIrReportRows(): void {\r\n    this.resultRows.forEach(resultRow => {\r\n      //Create headers\r\n      const irRows = this.summaryReportData?.calculations?.map(x => x.result.irRows).flat().filter(x => x.irData.code !== 1 && x.irData.code !== 0) ?? [];\r\n      irRows.forEach(irRow => {\r\n        if(!resultRow.irCodeIncomeReportRow.rows.some(x => x.key === `${irRow.data.calculationRowType}-${irRow.irData.code}`)) {\r\n          resultRow.irCodeIncomeReportRow.rows.push({\r\n            key: `${irRow.data.calculationRowType}-${irRow.irData.code}`,\r\n            label: this.getLabel(irRow),\r\n            code: irRow.irData.code,\r\n            isCount: false,\r\n            total: 0\r\n          });\r\n        }\r\n        resultRow.irCodeIncomeReportRow.rows.sort((a, b) => a.code > b.code ? 1 : -1);\r\n      });\r\n      const hourlySalaryRowIndex = resultRow.irCodeIncomeReportRow.rows.findIndex(x => x.key === \"HourlySalary-201\");\r\n      if(hourlySalaryRowIndex >= 0) {\r\n        resultRow.irCodeIncomeReportRow.rows.splice(hourlySalaryRowIndex + 1, 0, {\r\n          key: \"salaryPaymentWorkingHours\",\r\n          label: Translations.get(\"SALAXY.NG1.HolidayReportComponent.salaryPaymentWorkingHours\"),\r\n          code: null,\r\n          isCount: true,\r\n          total: 0\r\n        });\r\n      }\r\n      // Insert salaryPaymentMonths after MonthlySalary-201 key\r\n      const monthlySalaryRowIndex = resultRow.irCodeIncomeReportRow.rows.findIndex(x => x.key === \"MonthlySalary-201\");\r\n      if(monthlySalaryRowIndex >= 0) {\r\n        resultRow.irCodeIncomeReportRow.rows.splice(monthlySalaryRowIndex + 1, 0, {\r\n          key: \"salaryPaymentMonths\",\r\n          label: Translations.get(\"SALAXY.NG1.HolidayReportComponent.salaryPaymentMonths\"),\r\n          code: null,\r\n          isCount: true,\r\n          total: 0\r\n        });\r\n      }\r\n\r\n      // Sum rows\r\n      const item: IrCodeIncomeReportRow = {\r\n        workerAvatar: resultRow.avatar,\r\n        workerId: resultRow.workerId,\r\n        employmentId: resultRow.employmentId,\r\n        rows: [...structuredClone(resultRow.irCodeIncomeReportRow.rows)]\r\n      };\r\n      resultRow.calculations.map(x => x.result.irRows).flat().filter(x => x.irData.code !== 1 && x.irData.code !== 0).forEach(irRow => {\r\n        const row = item.rows.find(x => x.key === `${irRow.data.calculationRowType}-${irRow.irData.code}`);\r\n        row.total += irRow.total;\r\n      });\r\n\r\n      const salaryPaymentHoursRow = item.rows.find(x => x.key === \"salaryPaymentWorkingHours\");\r\n      if(salaryPaymentHoursRow) {\r\n        const hourlySalariesCals = resultRow.calculations.filter(x => x.result.irRows.some(x => x.unit === Unit.Hours && x.irData.code === 201));\r\n        salaryPaymentHoursRow.total = Numeric.round(hourlySalariesCals.map(x => x.rows).flat().map(x => x.count).reduce((prev, next) => (prev + next), 0));\r\n      }\r\n\r\n\r\n      const salaryPaymentMonthsRow = item.rows.find(x => x.key === \"salaryPaymentMonths\");\r\n      if(salaryPaymentMonthsRow) {\r\n        const monthlySalariesCals = resultRow.calculations.filter(x => x.result.irRows.some(x => /*x.unit === Unit.Period &&*/ x.irData.code === 201));\r\n        salaryPaymentMonthsRow.total = [... new Set(monthlySalariesCals.map(x => Dates.getMonth(x.workflow.salaryDate)))].length;\r\n      }\r\n      if(item.rows.some(x => x.total > 0)) {\r\n        resultRow.irCodeIncomeReportRow = item;\r\n      } else {\r\n        resultRow.irCodeIncomeReportRow = null;\r\n      }\r\n    });\r\n  }\r\n\r\n  private createSummaryReportRows() {\r\n    if(!this.summaryReportData || Object.keys(this.summaryReportData).length === 0) {\r\n      return;\r\n    }\r\n    const summaryReportData = Objects.copy(this.summaryReportData);\r\n    this.resultRows.forEach(resultRow => {\r\n      summaryReportData.calculations = resultRow.calculations;\r\n      (SummaryMapper.getSummaryReport(summaryReportData)as any).result.workerResult.forEach(item => {\r\n        this.createSummaryReportRowResult(resultRow, item, \"workerResult\");\r\n      });\r\n      (SummaryMapper.getSummaryReport(summaryReportData)as any).result.entrepreneurResult.forEach(item => {\r\n        this.createSummaryReportRowResult(resultRow, item, \"entrepreneurResult\");\r\n      });\r\n      (SummaryMapper.getSummaryReport(summaryReportData)as any).totalResult.forEach(item => {\r\n        this.createSummaryReportRowResult(resultRow, item, \"totalResult\");\r\n      });\r\n    });\r\n  }\r\n\r\n  private createSummaryReportRowResult(resultRow: ResultRow, item: any, resultType: \"workerResult\" | \"entrepreneurResult\" | \"totalResult\"): void {\r\n    if(!resultRow.summaryReportRow.result[resultType]) {\r\n      resultRow.summaryReportRow.result[resultType] = this.getBlankSummaryReportRowResult();\r\n    }\r\n      delete item.worker;\r\n      delete item.workStartDate;\r\n      delete item.workStartEndDate;\r\n      for (const [key, value] of Object.entries(item)) {\r\n        resultRow.summaryReportRow.result[resultType][key] += Numeric.parseNumber(value as string);\r\n        Numeric.round(resultRow.summaryReportRow.result[resultType][key]);\r\n      }\r\n  }\r\n\r\n  private getLabel(irRow: IrRow): string {\r\n    let rowType = irRow.data.calculationRowType || CalculationRowType.Unknown;\r\n    rowType = (rowType.substr(0, 1).toLowerCase() + rowType.substr(1)) as CalculationRowType;\r\n    const code = irRow.irData?.code as number;\r\n    const kind = this.getKind(irRow);\r\n    let label = \"\";\r\n    if (rowType === CalculationRowType.IrIncomeType) {\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => (kind && x.transactionCode === kind) || (code > 0 && x.code === code))?.label + `(${code})`;\r\n    } else if (rowType === CalculationRowType.MealBenefit && code !== 334) {\r\n      // Meal benefit deductions\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => code > 0 && x.code === code)?.label + `(${code})`;\r\n    } else if([\r\n      CalculationRowType.Unknown,\r\n      CalculationRowType.CarBenefit,\r\n      CalculationRowType.BicycleBenefit,\r\n      CalculationRowType.SubsidisedCommute,\r\n      CalculationRowType.TaxAtSource,\r\n      CalculationRowType.HourlySalaryWithWorkingTimeCompensation\r\n    ].includes(rowType))\r\n    {\r\n      label = IncomeTypesLogic.getAll(null).find( (x) => code > 0 && x.code === code)?.label + `(${code})`;\r\n    }\r\n    else if([\r\n      CalculationRowType.DailyAllowance,\r\n      CalculationRowType.EmploymentTermination,\r\n      CalculationRowType.WorkingTimeCompensation,\r\n      CalculationRowType.Remuneration,\r\n      CalculationRowType.OtherCompensation,\r\n      CalculationRowType.NonProfitOrg,\r\n      CalculationRowType.MealBenefit, // main MealBenefit\r\n      CalculationRowType.Training,\r\n      CalculationRowType.PaidSickLeave,\r\n    ].includes(rowType) && kind) {\r\n      label =  EnumerationsLogic.getEnumLabel(`${irRow.data.calculationRowType}Kind`, kind, null, null)  + `(${code})`;\r\n    }\r\n    return label || EnumerationsLogic.getEnumLabel(\"CalculationRowType\", rowType, null, null) + `(${code})`;\r\n  }\r\n\r\n  private getKind(irRow: IrRow): string {\r\n    if(irRow.data.kind) {\r\n      return irRow.data.kind;\r\n    }\r\n    // this forward, for backward compatibility\r\n    const rowType = (irRow.data.calculationRowType.substr(0, 1).toLowerCase() + irRow.data.calculationRowType.substr(1)) as CalculationRowType;\r\n    switch(rowType) {\r\n      case CalculationRowType.DailyAllowance: {\r\n        const code = irRow.irData.dailyAllowance[0];\r\n        const codeMapping = {\r\n          [AllowanceCode.InternationalDailyAllowance]: DailyAllowanceKind.InternationalDailyAllowance,\r\n          [AllowanceCode.PartialDailyAllowance]: DailyAllowanceKind.PartialDailyAllowance,\r\n          [AllowanceCode.MealAllowance]: DailyAllowanceKind.MealAllowance,\r\n          [AllowanceCode.FullDailyAllowance]: DailyAllowanceKind.FullDailyAllowance,\r\n        };\r\n        return codeMapping[code] ?? DailyAllowanceKind.Undefined;\r\n      }\r\n      case CalculationRowType.EmploymentTermination: {\r\n        switch(irRow.irData.code) {\r\n          case 208:\r\n            return EmploymentTerminationKind.NoticePeriodCompensation;\r\n          case 224:\r\n            return EmploymentTerminationKind.MonetaryWorkingTimeBankCompensation;\r\n          case 229:\r\n            return EmploymentTerminationKind.TerminationAndLayOffDamages;\r\n          case 231:\r\n            return EmploymentTerminationKind.VoluntaryTerminationCompensation;\r\n          case 338:\r\n            return EmploymentTerminationKind.PensionPaidByEmployer;\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.WorkingTimeCompensation: {\r\n        switch(irRow.irData.code) {\r\n          case 205:\r\n            return WorkingTimeCompensationKind.EmergencyWorkCompensation;\r\n          case 206:\r\n            return WorkingTimeCompensationKind.EveningWorkCompensation;\r\n          case 207:\r\n            return WorkingTimeCompensationKind.EveningShiftAllowance;\r\n          case 211:\r\n            return WorkingTimeCompensationKind.SaturdayPay;\r\n          case 212:\r\n            return WorkingTimeCompensationKind.ExtraWorkPremium;\r\n          case 216:\r\n            return WorkingTimeCompensationKind.OtherCompensation;\r\n          case 217:\r\n            return WorkingTimeCompensationKind.WaitingTimeCompensation;\r\n          case 221:\r\n            return WorkingTimeCompensationKind.SundayWorkCompensation;\r\n          case 230:\r\n            return WorkingTimeCompensationKind.StandByCompensation;\r\n          case 232:\r\n            return WorkingTimeCompensationKind.WeeklyRestCompensation;\r\n          case 235:\r\n            return WorkingTimeCompensationKind.OvertimeCompensation;\r\n          case 236:\r\n            return WorkingTimeCompensationKind.NightWorkAllowance;\r\n          case 237:\r\n            return WorkingTimeCompensationKind.NightShiftCompensation;\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.Remuneration: {\r\n        switch(irRow.irData.code) {\r\n          case 202:\r\n            return RemunerationKind.InitiativeFee;\r\n          case 203:\r\n            return RemunerationKind.BonusPay;\r\n          case 220:\r\n            return RemunerationKind.Commission;\r\n          case 223:\r\n            return RemunerationKind.PerformanceBonus;\r\n          case 226:\r\n            return RemunerationKind.ShareIssueForEmployees;\r\n          case 233:\r\n            return RemunerationKind.ProfitSharingBonus;\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.OtherCompensation: {\r\n        switch(irRow.irData.code) {\r\n          case 210:\r\n            return OtherCompensationKind.MeetingFee;\r\n          case 214:\r\n            return OtherCompensationKind.LectureFee;\r\n          case 215:\r\n            return OtherCompensationKind.PositionOfTrustCompensation;\r\n          case 225:\r\n            return OtherCompensationKind.AccruedTimeOffCompensation;\r\n          case 308:\r\n            return OtherCompensationKind.MembershipOfGoverningBodyCompensation;\r\n          case 310:\r\n            return OtherCompensationKind.MonetaryGiftForEmployees;\r\n          case 313:\r\n            return OtherCompensationKind.UseCompensationAsEarnedIncome;\r\n          case 314:\r\n            return OtherCompensationKind.UseCompensationAsCapitalIncome;\r\n          case 316:\r\n            return OtherCompensationKind.OtherTaxableIncomeAsEarnedIncome;\r\n          case 320:\r\n            return OtherCompensationKind.StockOptionsAndGrants;\r\n          case 326:\r\n            return OtherCompensationKind.EmployeeInventionCompensation;\r\n          case 332:\r\n            return OtherCompensationKind.CapitalIncomePayment;\r\n          case 339:\r\n            return OtherCompensationKind.WorkEffortBasedDividendsAsWage;\r\n          case 340:\r\n            return OtherCompensationKind.WorkEffortBasedDividendsAsNonWage;\r\n          case 343:\r\n            return OtherCompensationKind.EmployeeStockOption;\r\n          case 361:\r\n            return OtherCompensationKind.EmployeeStockOptionWithLowerPrice;\r\n          case 366:\r\n            return OtherCompensationKind.CopyrightRoyaltiesEarnedIncome;\r\n          case 367:\r\n            return OtherCompensationKind.StockGrantPaidInMoney;\r\n          case 368:\r\n            return OtherCompensationKind.EmployeeStockOptionPaidInMoney;\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.NonProfitOrg: {\r\n        switch(irRow.irData.code) {\r\n          case 358:\r\n          case 1358:\r\n            return NonProfitOrgKind.DailyAllowance;\r\n          case 357:\r\n            return NonProfitOrgKind.KilometreAllowance;\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.Training: {\r\n        switch(irRow.irData.code) {\r\n          case 227:\r\n            return TrainingKind.TrainingSalary;\r\n          case 201: {\r\n            if(irRow.unit === Unit.Hours) {\r\n              return TrainingKind.TrainingHourlySalary;\r\n            }\r\n            if(irRow.unit === Unit.Period) {\r\n              return TrainingKind.TrainingMonthlySalary;\r\n            }\r\n          }\r\n        }\r\n        break;\r\n      }\r\n      case CalculationRowType.PaidSickLeave: {\r\n        switch(irRow.irData.code) {\r\n          case 227:\r\n            return PaidSickLeaveKind.PaidSickLeaveSalary;\r\n          case 201: {\r\n            if(irRow.unit === Unit.Hours) {\r\n              return PaidSickLeaveKind.PaidSickLeaveHourlySalary;\r\n            }\r\n            if(irRow.unit === Unit.Period) {\r\n              return PaidSickLeaveKind.PaidSickLeaveMonthlySalary;\r\n            }\r\n          }\r\n        }\r\n        break;\r\n      }\r\n      default:\r\n        return null;\r\n    }\r\n  }\r\n\r\n  private getBlankResultRow(): ResultRow {\r\n    return {\r\n      employmentId: null,\r\n      avatar: null,\r\n      workerId: null,\r\n      calculations: [],\r\n      irCodeIncomeReportRow: this.getBlankIrCodeIncomeReportRow(),\r\n      summaryReportRow: this.getBlankSummaryReportRow()\r\n    };\r\n  }\r\n\r\n  private getBlankIrCodeIncomeReportRow(): IrCodeIncomeReportRow  {\r\n    return {\r\n      workerAvatar: null,\r\n      workerId: null,\r\n      employmentId: null,\r\n      rows: []\r\n    };\r\n  }\r\n\r\n  private getBlankSummaryReportRow(): SummaryReportRow {\r\n    return {\r\n      result: {\r\n        workerResult: null,\r\n        entrepreneurResult: null,\r\n        totalResult: null\r\n      }\r\n    };\r\n  }\r\n\r\n  private getBlankSummaryReportRowResult(): SummaryReportRowResult {\r\n    return  {\r\n      avatar: null,\r\n      workerId: null,\r\n      employmentId: null,\r\n      totalGrossSalary: 0,\r\n      totalRowCategory: 0,\r\n      benefits: 0,\r\n      irCode: 0,\r\n      totalTaxable: 0,\r\n      tax: 0,\r\n      pension: 0,\r\n      unemploymentInsurance: 0,\r\n      unionPayment: 0,\r\n      foreclosure: 0,\r\n      otherDeductions: 0,\r\n      totalExpenses: 0,\r\n      totalWorkerPayment: 0,\r\n      totalPayment: 0,\r\n      palkkaus: 0,\r\n      service: 0,\r\n      socialSecurity: 0,\r\n      totalPensions: 0,\r\n      employerPension: 0,\r\n      unemployment: 0,\r\n      employerUnemployment: 0,\r\n    };\r\n  }\r\n}\r\n\r\ninterface ResultRow {\r\n  employmentId: string;\r\n  avatar: Avatar;\r\n  workerId: string;\r\n  calculations: Calculation[];\r\n  irCodeIncomeReportRow: IrCodeIncomeReportRow;\r\n  summaryReportRow: SummaryReportRow;\r\n}\r\n\r\ninterface SummaryReportRow {\r\n  result: SummaryReportResult;\r\n}\r\n\r\ninterface SummaryReportResult {\r\n  workerResult?: SummaryReportRowResult;\r\n  entrepreneurResult?: SummaryReportRowResult;\r\n  totalResult?: SummaryReportRowResult;\r\n}\r\n\r\ninterface SummaryReportRowResult {\r\n  avatar: Avatar;\r\n  workerId: string;\r\n  employmentId: string;\r\n  totalGrossSalary: number;\r\n  totalRowCategory: number;\r\n  benefits: number;\r\n  irCode: number;\r\n  totalTaxable: number;\r\n  tax: number;\r\n  pension: number;\r\n  unemploymentInsurance: number;\r\n  unionPayment: number;\r\n  foreclosure: number;\r\n  otherDeductions: number;\r\n  totalExpenses: number;\r\n  totalWorkerPayment: number;\r\n  totalPayment: number;\r\n  palkkaus: number;\r\n  service: number;\r\n  socialSecurity: number;\r\n  totalPensions: number;\r\n  employerPension: number;\r\n  unemployment: number;\r\n  employerUnemployment: number;\r\n}\r\n\r\ninterface IrCodeIncomeReportRow {\r\n  workerAvatar: Avatar;\r\n  workerId: string;\r\n  employmentId: string;\r\n  rows: IrReportRow[];\r\n}\r\n\r\ninterface IrReportRow {\r\n  code: number;\r\n  key: string;\r\n  total: number;\r\n  label: string;\r\n  isCount: boolean;\r\n}","import angular from \"angular\";\r\n\r\nimport { AccountantType, AccountInIndex, Ajax, LegalEntityType, PrimaryPartnerSettings } from \"@salaxy/core\";\r\n\r\nimport { SettingsService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for the accountant settings.\r\n */\r\nexport class AccountantController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"AjaxNg1\", \"SettingsService\", \"UiHelpers\"];\r\n\r\n\r\n   /** if true, removing accountant is disabled */\r\n   public removalDisabled: boolean;\r\n\r\n  constructor(private ajax: Ajax, private settingsService: SettingsService, private uiHelpers: UiHelpers) {\r\n  }\r\n\r\n  /**\r\n   * Returns current accountant.\r\n   */\r\n  public get accountant(): PrimaryPartnerSettings {\r\n    if (this.settingsService.current) {\r\n      return this.settingsService.current.partner;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Returns accountant main type */\r\n  public get accountantMainType(): \"company\" | \"none\" {\r\n    return this.getAccountantMainType(this.accountant);\r\n  }\r\n\r\n  /** Shows the edit dialog */\r\n  public showEdit(removalDisabled = false) {\r\n    const accountant: PrimaryPartnerSettings = this.accountant || {\r\n      type: AccountantType.None,\r\n      info: {\r\n        avatar: {},\r\n      },\r\n    };\r\n    const logic = {\r\n      type: this.getAccountantMainType(accountant),\r\n      searchResult: [] as AccountInIndex[],\r\n      isLoading: false,\r\n      removalDisabled,\r\n      selected: this.getAccountantMainType(accountant) == \"company\" ? accountant.info : null,\r\n      select: (item: PrimaryPartnerSettings, row: AccountInIndex) => {\r\n        item.info = row;\r\n        item.type = AccountantType.PendingPrimaryPartner;\r\n        logic.selected = row;\r\n      },\r\n      reset: (item) => {\r\n        logic.selected = null;\r\n        Object.assign(item, accountant);\r\n      },\r\n      search: (search: string) => {\r\n        logic.isLoading = true;\r\n        return this.ajax.getJSON(`/v03/api/settings/partners?search=${encodeURIComponent(search)}`).then((result) => {\r\n          logic.searchResult = result;\r\n          logic.isLoading = false;\r\n          return logic.searchResult;\r\n        });\r\n      },\r\n    };\r\n\r\n    return this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/settings/AccountantSelection.html\",\r\n      accountant,\r\n      logic,\r\n      \"lg\").then((dialog) => {\r\n        if (dialog.result === \"ok\") {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n\r\n          if (logic.type === \"none\" && (dialog.item.info.avatar.firstName || dialog.item.info.avatar.lastName)) {\r\n            dialog.item.type = AccountantType.None;\r\n            dialog.item.info.avatar.displayName = (dialog.item.info.avatar.firstName + \" \" + dialog.item.info.avatar.lastName).trim();\r\n            dialog.item.info.avatar.color = \"gray\";\r\n            dialog.item.info.avatar.entityType = LegalEntityType.Person;\r\n            dialog.item.info.avatar.initials = (((dialog.item.info.avatar.firstName ?? \"\") + \" \")[0].toUpperCase() + ((dialog.item.info.avatar.lastName ?? \"\") + \" \")[0].toUpperCase()).trim();\r\n          }\r\n\r\n          this.settingsService.current.partner = dialog.item;\r\n          return this.settingsService.save().then(() => {\r\n            loading.dismiss();\r\n            return;\r\n          });\r\n        }\r\n        else if (dialog.result === \"remove\") {\r\n          this.settingsService.current.partner = {\r\n            info: {\r\n              avatar: {},\r\n            },\r\n            type: AccountantType.None,\r\n          };\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n          return this.settingsService.save().then(() => {\r\n              loading.dismiss();\r\n          });\r\n        }\r\n        else if ( dialog.result === \"removePrimaryPartner\") {\r\n          this.showConfirmPartnerRemoval();\r\n          return;\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Removes pricing partner using confirmation dialog. */\r\n  public showConfirmPartnerRemoval() {\r\n    this.uiHelpers.showConfirm(\"SALAXY.NG1.AccountantComponent.showConfirmPartnerRemovalTitle\", \"SALAXY.NG1.AccountantComponent.showConfirmPartnerRemovalDesciption\")\r\n      .then((result) => {\r\n        if (result) {\r\n          this.settingsService.current.partner = {\r\n            info: {\r\n              avatar: {},\r\n            },\r\n            type: AccountantType.None,\r\n          };\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n          return this.settingsService.save().then(() => {\r\n              loading.dismiss();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /** Save current accountant. This mainly for email address. */\r\n  public save(): Promise<void> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n    return this.settingsService.save().then(() => {\r\n      loading.dismiss();\r\n      return;\r\n    });\r\n  }\r\n\r\n  private getAccountantMainType(accountant: PrimaryPartnerSettings): \"company\" | \"none\" {\r\n    if (!accountant ||\r\n        !accountant.type ||\r\n        accountant.type === AccountantType.Unknown ||\r\n        accountant.type === AccountantType.None) {\r\n      return \"none\";\r\n    }\r\n\r\n    return \"company\";\r\n\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { AccountingChannel, AccountingTargets, AccountingTargetSettings, Ajax, Configs, ExportMethod, ExternalDialogData } from \"@salaxy/core\";\r\nimport { ExternalDialogConfig, SessionService, SettingsService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interfaces for specifying settings for Payment Channels (and other payment related settings).\r\n */\r\nexport class AccountingChannelSettingsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SettingsService\", \"UiHelpers\", \"SessionService\", \"$http\", \"AjaxNg1\"];\r\n\r\n  // Function for closing the settings modal in case we need to close the window programmatically\r\n  // e.g. based on the return value fromt the external dialog.\r\n  private closeFn: (string) => any;\r\n\r\n  private static channelPaths = {\r\n    [AccountingChannel.Procountor]: {}, // Procountor accounting channel is under construction.\r\n    [AccountingChannel.VismaNetvisor]: {\r\n      settings: \"vismanetvisor/settings.html\",\r\n      coa: \"vismanetvisor/coa\",\r\n    },\r\n    [AccountingChannel.VismaFivaldi]: {\r\n      settings: \"vismafivaldi/settings.html\",\r\n      coa: \"vismafivaldi/coa\",\r\n    },\r\n  };\r\n\r\n  constructor(\r\n    private settingsService: SettingsService,\r\n    private uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n    private $http: angular.IHttpService,\r\n    private ajax: Ajax\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    // none\r\n  };\r\n\r\n  /**\r\n   * Returns true if the given accounting target item is an API integration type acccounting\r\n   * target.\r\n   * @param item The accounting target item\r\n   * @returns True or false.\r\n   */\r\n  public isApiIntegration(item: any): boolean {\r\n    return (item?.availableMethods ?? []).indexOf(ExportMethod.Api) > -1 && (\r\n        item?.channel === AccountingChannel.Procountor\r\n        || item?.channel === AccountingChannel.VismaNetvisor\r\n        || item?.channel === AccountingChannel.VismaFivaldi\r\n      );\r\n  }\r\n\r\n  /** Opens the channel setup dialog in a new window. */\r\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n  public openChannelSetupDialog(target: AccountingTargetSettings, closeFn: (string) => any) {\r\n    if (!target?.channel) {\r\n      return;\r\n    }\r\n\r\n    this.closeFn = closeFn;\r\n\r\n    this.uiHelpers.showExternalDialog(\r\n      target.id,\r\n      this.getAccountingTargetSettingsUrl(target),\r\n      {},\r\n      this.getExternalDialogConfigByTarget(target)\r\n    )\r\n      .then(res => {\r\n        console.log(\"Accounting target settings saved, results = \", res);\r\n        // If handling of return data caused the settings to be saved\r\n        if (this.handleExternalDialogReturnData(target, res)) {\r\n          // Set the updated data also to the original target, otherwise the updates are not\r\n          // reflected on the caller e.g. on a settings page.\r\n          target.data = { ...target.data, ...(res.item as AccountingTargetSettings).data };\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Loads the chart of accounts from the channel.\r\n   * @param target Accounting target.\r\n   * @param closeFn $close function to call.\r\n   */\r\n  public async configureCoa(target: AccountingTargetSettings, closeFn: (string) => any) {\r\n    this.closeFn = closeFn;\r\n    const coa = await this.loadCoaFromChannel(target);\r\n\r\n    if (!coa) {\r\n      // TODO: Should throw/show some error?\r\n      return;\r\n    }\r\n\r\n    navigator.clipboard.writeText(coa);\r\n    // Navigate to accounting targets configuration view.\r\n    this.closeFn(\"close\");\r\n    const ownerId = ((await new AccountingTargets(this.ajax).getAll()) as any).items.find(v => v.id === target.id)?.owner;\r\n\r\n    if (this.isAdmin()) {\r\n      window.location.href = `/AccountingTargetDto/Client/${ownerId}/#/accounting-targets/details/${target.id}`;\r\n    } else {\r\n      window.location.href = `./#/accounting-targets/details/${target.id}@${ownerId}`;\r\n    }\r\n  }\r\n\r\n  private async loadCoaFromChannel(target: AccountingTargetSettings): Promise<string> {\r\n    const response = await this.$http.get(this.getCoaUrl(target), { responseType: \"json\" });\r\n    return Object.keys(response.data).reduce((pre, cur) => pre + cur + \";\" + response.data[cur] + \"\\n\", \"\");\r\n  }\r\n\r\n  private getAccountingTargetSettingsUrl(target: AccountingTargetSettings): string {\r\n    const accessToken = this.sessionService.getCurrentToken();\r\n    const url = Configs.current.integrationsServer + \"/\" + AccountingChannelSettingsController.channelPaths[target.channel].settings;\r\n\r\n    return `${url}?accessToken=${accessToken}&accountingTargetId=${target.id}`;\r\n  }\r\n\r\n  private getExternalDialogConfigByTarget(target: AccountingTargetSettings): ExternalDialogConfig {\r\n    switch(target.channel) {\r\n      case AccountingChannel.VismaFivaldi:\r\n        return { height: 810 };\r\n      default:\r\n        return {};\r\n    }\r\n  }\r\n\r\n  private getCoaUrl(target: AccountingTargetSettings): string {\r\n    const accessToken = this.sessionService.getCurrentToken();\r\n    const url = Configs.current.integrationsServer + \"/\" + AccountingChannelSettingsController.channelPaths[target.channel].coa;\r\n\r\n    return `${url}?accessToken=${accessToken}&accountingTargetId=${target.id}`;\r\n  }\r\n\r\n  private handleExternalDialogReturnData(target: AccountingTargetSettings, data: ExternalDialogData<any>): boolean {\r\n    switch(data.action) {\r\n      case \"cancel\":\r\n        break;\r\n      case \"save\":\r\n        if (!angular.equals(target.data, (data.item as AccountingTargetSettings).data)){\r\n          this.saveSettings(data.item);\r\n          return true;\r\n        }\r\n        break;\r\n      default:\r\n        return false;\r\n    }\r\n  }\r\n\r\n  private saveSettings(settings: AccountingTargetSettings) {\r\n    const targetToSave = this.findAccountingTargetFromCompanySettings(settings);\r\n    targetToSave.data = { ...targetToSave.data, ...settings.data };\r\n    this.settingsService.save();\r\n  }\r\n\r\n  private findAccountingTargetFromCompanySettings(target: AccountingTargetSettings): AccountingTargetSettings {\r\n    return this.settingsService.current.accounting?.targets\r\n      .find(v => v.id === target.id);\r\n  }\r\n\r\n  private isAdmin(): boolean {\r\n    const result = !!this.sessionService.clientRoles.find(v => v === \"admin\");\r\n    return result;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountingRuleSetAccount, AccountingRuleSetRow, AccountingTarget, AccountingTargetListItem, AccountingTargets, CalculationRowType, IncomeTypesLogic, EmploymentRelationType, FileLogic, Tables, FileDelimiter, ImportResult, DataRow, PensionCalculation, Translations, Language, PaidSickLeaveKind, TrainingKind } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * UI logic for viewing and adding new (modifying) accounting targets.\r\n * Accounting targets define where the accounting data is sent and how it is mapped to a Chart of Accounts (CoA)\r\n */\r\nexport class AccountingTargetCrudController extends ApiCrudObjectController<AccountingTarget, AccountingTargetListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AccountingTargets\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"$timeout\"\r\n  ];\r\n\r\n  /** If the current item is based on template, it should be here once loaded from server. */\r\n  public template: AccountingTarget;\r\n\r\n  /** import data */\r\n  public rawData: string | null;\r\n  public fileExtension: string | null;\r\n\r\n  public accountFilter = \"all\";\r\n\r\n  public showDistinct = false;\r\n\r\n  /** TODO: Move to core  */\r\n  private flags = [\r\n    { value: \"customerSelfPayment\", text: \"Työnantaja hoitaa\", description: \"Työnantaja maksaa itse\", isSelected: false },\r\n    { value: \"cfDeductionAtSalaxy\", text: \"Palkkaus pidättää\", description: \"Palkkaus pidättää asiakasvaratilin kautta\", isSelected: false },\r\n\r\n    { value: \"incomeEarnerEntrepreneur\", text: \"Sovellettava eläketurva: yrittäjä\", description: \"Työntekijä on yrittäjä, sovellettava eläketurva on YEL/MYEL (myös ilman vakuuttamisvelvollisuutta) tai Urheilijan eläke\", isSelected: false },\r\n\r\n    { value: `pensionCalculation.${PensionCalculation.Employee}`, text: \"Sovellettava eläketurva: TyEL\", description: \"Työntekijän sovellettava eläketurva on TyEL\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.Entrepreneur}`, text: \"Sovellettava eläketurva: YEL\", description: \"Työntekijän sovellettava eläketurva on YEL\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.Farmer}`, text: \"Sovellettava eläketurva: MYEL\", description: \"Työntekijän sovellettava eläketurva on MYEL\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.PartialOwner}`, text: \"Sovellettava eläketurva: TyEL, osaomistaja\", description: \"Työntekijän sovellettava eläketurva on TyEL, osaomistaja\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.Athlete}`, text: \"Sovellettava eläketurva: Urheilijan eläke\", description: \"Työntekijän sovellettava eläketurva on urheilijan eläke\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.Compensation}`, text: \"Sovellettava eläketurva: Työkorvaus\", description: \"Työntekijälle maksetaan työkorvausta\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.BoardRemuneration}`, text: \"Sovellettava eläketurva: Hallituspalkkio\", description: \"Hallituksen jäsenelle maksetaan hallituspalkkiota\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.SmallEntrepreneur}`, text: \"Sovellettava eläketurva: YEL, ei vakuuttamisvelvollisuutta\", description: \"Työntekijän sovellettava eläketurva on YEL, ei vakuuttamisvelvollisuutta\", isSelected: false },\r\n    { value: `pensionCalculation.${PensionCalculation.SmallFarmer}`, text: \"Sovellettava eläketurva: MYEL, ei vakuuttamisvelvollisuutta\", description: \"Työntekijän sovellettava eläketurva on MYEL, ei vakuuttamisvelvollisuutta\", isSelected: false },\r\n\r\n\r\n    { value: `employmentType.${EmploymentRelationType.MonthlySalary}`, text: \"Työsuhteen tyyppi: Kuukausipalkkainen työntekijä (TyEL)\", description: \"Työntekijällä on kuukausipalkka, sovellettava eläketurva on TyEL\", isSelected: false },\r\n    { value: `employmentType.${EmploymentRelationType.HourlySalary}`, text: \"Työsuhteen tyyppi: Tuntipalkkainen työntekijä (TyEL)\", description: \"Työntekijällä on tuntipalkka, sovellettava eläketurva on TyEL\", isSelected: false },\r\n    { value: `employmentType.${EmploymentRelationType.Salary}`, text: \"Työsuhteen tyyppi: Urakkapalkkainen työntekijä (TyEL)\", description: \"Työntekijällä on urakkapalkka, sovellettava eläketurva on TyEL\", isSelected: false },\r\n\r\n    { value: `${CalculationRowType.Expenses}`, text: \"Rivityyppi: Kulukorvaus\", description: \"Laskelman rivityyppi on kulukorvaus\", isSelected: false },\r\n    { value: `${CalculationRowType.PrepaidExpenses}`, text: \"Rivityyppi: Kulukorvausennakko\", description: \"Laskelman rivityyppi on ennalta maksettu kulukorvaus\", isSelected: false },\r\n    { value: `${CalculationRowType.Foreclosure}`, text: \"Rivityyppi: Ulosotto\", description: \"Laskelman rivityyppi on ulosotto\", isSelected: false },\r\n    { value: `${CalculationRowType.UnionPayment}`, text: \"Rivityyppi: AY-jäsenmaksu\", description: \"Laskelman rivityyppi on AY-jäsenmaksu\", isSelected: false },\r\n    { value: `${CalculationRowType.Advance}`, text: \"Rivityyppi: Palkkaennakko\", description: \"Laskelman rivityyppi on palkkaennakko\", isSelected: false },\r\n    { value: `${CalculationRowType.Service}`, text: \"Rivityyppi: Palvelumaksu\", description: \"Laskelman rivityyppi on palvelumaksu\", isSelected: false },\r\n    { value: `${CalculationRowType.HolidaySalary}`, text: \"Rivityyppi: Loma-ajan palkka\", description: \"Laskelman rivityyppi on loma-ajan palkka\", isSelected: false },\r\n    { value: `${CalculationRowType.PaidSickLeave}.${PaidSickLeaveKind.PaidSickLeaveSalary}`, text: \"Rivityyppi: Palkallinen sairauspoissaolo, kertakorvaus\", description: \"Laskelman rivityyppi on sairauspoissaoloajan palkka, kertakorvaus.\", isSelected: false },\r\n    { value: `${CalculationRowType.PaidSickLeave}.${PaidSickLeaveKind.PaidSickLeaveHourlySalary}`, text: \"Rivityyppi: Palkallinen sairauspoissaolo, tuntipalkka\", description: \"Laskelman rivityyppi on sairauspoissaoloajan palkka, palkanmaksu tehtyjen tuntien perusteella.\", isSelected: false },\r\n    { value: `${CalculationRowType.PaidSickLeave}.${PaidSickLeaveKind.PaidSickLeaveMonthlySalary}`, text: \"Rivityyppi: Palkallinen sairauspoissaolo, kuukausipalkka\", description: \"Laskelman rivityyppi on sairauspoissaoloajan palkka, kiinteä kuukausipalkka.\", isSelected: false },\r\n    { value: `${CalculationRowType.Training}.${TrainingKind.TrainingSalary}`, text: \"Rivityyppi: Koulutusaika, kertakorvaus\", description: \"Laskelman rivityyppi on koulutusajan palkka, kertakorvaus.\", isSelected: false },\r\n    { value: `${CalculationRowType.Training}.${TrainingKind.TrainingHourlySalary}`, text: \"Rivityyppi: Koulutusaika, tuntipalkka\", description: \"Laskelman rivityyppi on koulutusajan palkka, palkanmaksu tuntien perusteella.\", isSelected: false },\r\n    { value: `${CalculationRowType.Training}.${TrainingKind.TrainingMonthlySalary}`, text: \"Rivityyppi: Koulutusaika, kuukausipalkka\", description: \"Laskelman rivityyppi on koulutusajan palkka, kiinteä kuukausipalkka.\", isSelected: false },\r\n    { value: `${CalculationRowType.DeductibleOfExerciseAndCultureBenefit}`, text: \"Rivityyppi: Liikunta- ja kulttuuri-edun omavastuu\", description: \"Laskelman rivityyppi on liikunta- ja kulttuuri-edun omavastuu (vähennetään nettopalkasta)\", isSelected: false },\r\n  ];\r\n\r\n  private entryCodeGroups =\r\n    {\r\n      incomeType: \"Tulolaji\",\r\n      totalType: \"Laskettu erä\",\r\n    };\r\n\r\n  private totalTypes = {\r\n    totalPensionWorker: \"Työntekijöiden TyEL-maksut\",\r\n    totalPensionEmployer: \"Työnantajan TyEL-maksu\",\r\n    totalPension: \"TyEL-maksut\",\r\n    totalUnemploymentWorker: \"Työntekijöiden työttömyysvakuutusmaksut\",\r\n    totalUnemploymentEmployer: \"Työnantajan työttömyysvakuutusmaksu\",\r\n    totalUnemployment: \"Työttömyysvakuutusmaksut\",\r\n    totalSocialSecurityEmployer: \"Työnantajan sairausvakuutusmaksu\",\r\n    totalTax: \"Ennakonpidätykset\",\r\n    totalPalkkaus: \"Palkkaus.fi-palkkio\",\r\n    totalWorkerPayment: \"Työntekijän nettopalkka ja kulukorvaukset\",\r\n    totalPayment: \"Maksettu asiakasvaratilille\",\r\n    totalAccidentInsurance: \"Työtapaturma- ja ammattitautivakuutusmaksut\",\r\n    totalGroupLifeInsurance: \"Ryhmähenkivakuutusmaksut\",\r\n    totalAccruedHolidayPay: \"Kertyneet lomapalkat\",\r\n    totalAccruedHolidayBonus: \"Kertyneet lomarahat\",\r\n    totalAccruedHolidaySocialSecurity: \"Kertyneet lomapalkkojen sairausvakuutusmaksut\",\r\n    totalAccruedHolidayPension: \"Kertyneet lomapalkkojen TyEL-maksut\",\r\n    totalAccruedHolidayUnemployment: \"Kertyneet lomapalkkojen työttömyysvakuutusmaksut (TVR)\",\r\n    totalAccruedGroupLifeInsurance: \"Kertyneet lomapalkkojen ryhmähenkivakuutusmaksut\",\r\n    totalAccruedAccidentInsurance: \"Kertyneet lomapalkkojen työtapaturma- ja ammattitautivakuutusmaksut\",\r\n    totalPaidHolidaySalary: \"Maksetut loma-ajan palkat\",\r\n    totalPaidHolidayBonus: \"Maksetut lomarahat\",\r\n    totalPaidHolidayCompensation: \"Maksetut lomakorvaukset\",\r\n    totalPaidHolidaySocialSecurity: \"Maksetut lomapalkkojen sairausvakuutusmaksut\",\r\n    totalPaidHolidayPension: \"Maksetut lomapalkkojen TyEL-maksut\",\r\n    totalPaidHolidayUnemployment: \"Maksetut lomapalkkojen työttömyysvakuutusmaksut (TVR)\",\r\n  };\r\n\r\n  private incomeTypes = IncomeTypesLogic.getAll(Translations.getLanguage() as any || Language.Fi).map((x) => ({ value: \"\" + x.code, text: x.code + \" - \" + x.label, title: x.description }));\r\n\r\n  constructor(\r\n    private fullApi: AccountingTargets,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/accounting-targets\",\r\n      detailsUrl: this.detailsUrl || \"/accounting-targets/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/AccountingTargets.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Additional setup after the item has been loaded.\r\n   * @param item Item that has been loaded\r\n   */\r\n  public setCurrentRef(item: AccountingTarget) {\r\n    super.setCurrentRef(item);\r\n    if (this.current?.ruleSet?.templateId) {\r\n      if (this.current.ruleSet.templateId !== this.template?.ruleSet?.templateId) {\r\n        this.fullApi.getSingle(this.current.ruleSet.templateId).then((result) => {\r\n          this.template = result;\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view for the item.\r\n   * Supports viewing public items from other users as read-only.\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showDetails(item: AccountingTargetListItem | AccountingTarget): angular.ILocationService {\r\n    // TODO: Consider adding this support in super\r\n    if (this.parentController) {\r\n      return this.parentController.showDetails(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item) + \"@\" + item.owner);\r\n  }\r\n\r\n  /** Returns flag description */\r\n  public getFlag(value: string) {\r\n    return this.flags.find((x) => x.value === value) || { value, text: value, description: value };\r\n  }\r\n\r\n  /** Gets entry description */\r\n  public getEntryDescription(row: AccountingRuleSetRow) {\r\n    switch (row.entryCodeGroup) {\r\n      case \"incomeType\":\r\n        return this.entryCodeGroups[row.entryCodeGroup] + \": \" + this.incomeTypes.find((x) => x.value === row.entryCode).text;\r\n      case \"totalType\":\r\n        return this.entryCodeGroups[row.entryCodeGroup] + \": \" + this.totalTypes[row.entryCode];\r\n    }\r\n    return \"\";\r\n  }\r\n\r\n  /** Selects entry */\r\n  public selectEntry(row: AccountingRuleSetRow) {\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/report/modals/EntryCodes.html\",\r\n      null,\r\n      {\r\n        entryCodeGroups: this.entryCodeGroups,\r\n        totalTypes: this.totalTypes,\r\n        incomeTypes: this.incomeTypes,\r\n        row: angular.copy(row),\r\n      },\r\n    ).then((result) => {\r\n      if (result && result.entryCode && result.entryCodeGroup) {\r\n        row.entryCode = result.entryCode;\r\n        row.entryCodeGroup = result.entryCodeGroup;\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view with a new item that is a copy of the given item.\r\n   * Please note that this method supports copying public items from other users. Override is required because the default cannoty copy from other users\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n   public showCopyAsNew(item: AccountingTargetListItem | AccountingTarget): angular.ILocationService {\r\n    if (this.parentController) {\r\n      return this.parentController.showCopyAsNew(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item) + \"@\" + item.owner + \"/copy-as-new\");\r\n  }\r\n\r\n  /**\r\n   * Creates a copy of the current set\r\n   * Changes the settings so that the accounting target becomes a new item\r\n   * @param copySource Item (container item) to copy as new.\r\n   */\r\n  public copyItem(copySource: AccountingTarget): AccountingTarget {\r\n    const copy = super.copyItem(copySource);\r\n    copy.info.target.avatar.id = null;\r\n    copy.info.target.avatar.displayName = \"Kopio \" + copy.info.target.avatar.displayName;\r\n    copy.ruleSet.templateId = copySource.id + \"@\" + copySource.owner;\r\n    copy.isReadOnly = false;\r\n    copy.ruleSet.targetCoA = angular.copy(copy.ruleSet.accounts);\r\n    return copy;\r\n  }\r\n\r\n  /** Selects the account */\r\n  public selectAccount(row: AccountingRuleSetRow, isCredit: boolean) {\r\n    const accounts = angular.copy(this.current.ruleSet.accounts);\r\n    for (const account of accounts) {\r\n      if (isCredit) {\r\n        (account as any).isSelected = account.id === row.creditId;\r\n      } else {\r\n        (account as any).isSelected = account.id === row.debitId;\r\n      }\r\n    }\r\n\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/report/modals/AccountNumbers.html\",\r\n      null,\r\n      {\r\n        accounts,\r\n      },\r\n    ).then((account) => {\r\n      if (account) {\r\n        if (isCredit) {\r\n          row.creditId = account.id;\r\n        } else {\r\n          row.debitId = account.id;\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets selectedAccount\r\n   * @param selectedAccount selectedAccount\r\n   */\r\n  public selectTargetAccount(selectedAccount: AccountingRuleSetAccount) {\r\n    const accounts = angular.copy(this.current.ruleSet.targetCoA);\r\n    for (const account of accounts) {\r\n      (account as any).isSelected = account.account === selectedAccount.account;\r\n    }\r\n\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/report/modals/AccountNumbers.html\",\r\n      null,\r\n      {\r\n        accounts,\r\n      },\r\n    ).then((account) => {\r\n      if (account) {\r\n        selectedAccount.account = account.account;\r\n        selectedAccount.text = account.text;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Return targetCoA */\r\n  public get hasTargetCoA(): boolean {\r\n    return !!this.current.ruleSet.targetCoA.length;\r\n  }\r\n\r\n  private groupBy<T>(source: T[], getKey: (item: T) => string, sortKeys = false): { [key: string]: T[] } {\r\n    let result = source.reduce((previousValue, currentValue) => {\r\n      const key = getKey(currentValue);\r\n      previousValue[key] = previousValue[key] || [];\r\n      (previousValue[key]).push(currentValue);\r\n      return previousValue;\r\n    }, {});\r\n    if (sortKeys) {\r\n      result = Object.keys(result).sort().reduce((previousValue, key) => {\r\n        previousValue[key] = result[key];\r\n        return previousValue;\r\n      }, {});\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /** Gets the ruleset rouws grouped by account and grouping */\r\n  public get groupedRows(): { [key: string]: AccountingRuleSetRow[] } {\r\n    return this.uiHelpers.cache(this, \"groupedRows\", () => {\r\n      if (!this.current) {\r\n        return null;\r\n      }\r\n      const getKey = (row: AccountingRuleSetRow): string => {\r\n        if (!row.isIncluded) {\r\n          return \"xxxx\";\r\n        }\r\n        const debit = (this.getAccount(row.debitId)?.account || \"9999\") + (row.debitGrouping || \"yyyy\");\r\n        const credit = (this.getAccount(row.creditId)?.account || \"9999\") + (row.creditGrouping || \"yyyy\");\r\n        return (debit + credit) || \"zzzz\";\r\n      };\r\n      return this.groupBy(this.current.ruleSet.rows, getKey, true);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get rows based on current ruleSet, account and isDebet\r\n   * @param account iterated account from current.ruleSet.accounts\r\n   * @param isDebet indicates if debet or credit account\r\n   */\r\n  public getRulesetByAccount(account: AccountingRuleSetAccount, isDebet: boolean): AccountingRuleSetRow[] {\r\n    return this.current.ruleSet.rows.filter((row) => isDebet ? row.debitId === account.id : row.creditId === account.id);\r\n  }\r\n\r\n  /** Returns account details */\r\n  public getAccount(id: string) {\r\n    return this.current.ruleSet.accounts.find((x) => x.id === id);\r\n  }\r\n\r\n  /** Adds new account */\r\n  public addAccount(addToEnd = false) {\r\n    const idx = addToEnd ? this.current.ruleSet.accounts.length : 0;\r\n    const copyRow = addToEnd ? this.current.ruleSet.accounts[this.current.ruleSet.accounts.length - 1] : this.current.ruleSet.accounts[0];\r\n    const newRow = {\r\n      isReadOnly: false,\r\n      id: this.newGuid(),\r\n      account: copyRow.account,\r\n      text: copyRow.text,\r\n    };\r\n    this.current.ruleSet.accounts.splice(idx, 0, newRow);\r\n  }\r\n\r\n  /**\r\n   * Add new account to TargetCoA\r\n   * @param addToEnd tells if adds to end of array or not\r\n   */\r\n  public addTargetCoaAccount(addToEnd = false) {\r\n    const idx = addToEnd ? this.current.ruleSet.targetCoA.length : 0;\r\n    const copyRow = addToEnd ? this.current.ruleSet.targetCoA[this.current.ruleSet.targetCoA.length - 1] : this.current.ruleSet.targetCoA[0];\r\n    const newRow = {\r\n      isReadOnly: false,\r\n      id: this.newGuid(),\r\n      account: copyRow.account,\r\n      text: copyRow.text,\r\n    };\r\n    this.current.ruleSet.targetCoA.splice(idx, 0, newRow);\r\n  }\r\n\r\n  /** Removes the account */\r\n  public removeAccount(row: AccountingRuleSetAccount, removeFromTargetCoa = false) {\r\n    if (!row.isReadOnly) {\r\n      if (removeFromTargetCoa) {\r\n        const idx = this.current.ruleSet.targetCoA.findIndex((x) => x === row);\r\n        this.current.ruleSet.targetCoA.splice(idx, 1);\r\n      } else {\r\n        // TODO: Consider adding a check if the account is in use in some of the derived rulesets. Perhaps in saving?\r\n        if (this.current.ruleSet.rows.some((r) => r.creditId === row.id || r.debitId === row.id)) {\r\n          this.uiHelpers.showAlert(\"Tiliä ei voi poistaa\", \"Tili on käytössä tiliöintimallissa.\");\r\n          return;\r\n        }\r\n        const idx = this.current.ruleSet.accounts.findIndex((x) => x.id === row.id);\r\n        this.current.ruleSet.accounts.splice(idx, 1);\r\n\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Validated row input\r\n   * @param row Row to be validated\r\n   */\r\n  public isValidAccount(row: AccountingRuleSetAccount): boolean {\r\n    if (!this.current.ruleSet.targetCoA.length) {\r\n      return true;\r\n    }\r\n    return !!this.current.ruleSet.targetCoA.find((x) => x.account.toString() === row.account.toString());\r\n  }\r\n\r\n  /** Adds a new row */\r\n  public addRow(row: AccountingRuleSetRow, addToStart = false) {\r\n    const idx = row ? this.current.ruleSet.rows.findIndex((x) => x.id === row.id) : this.current.ruleSet.rows.length;\r\n    const copyRow = row || (addToStart ? this.current.ruleSet.rows[0] : this.current.ruleSet.rows[this.current.ruleSet.rows.length - 1]);\r\n    const newRow = {\r\n      isReadOnly: false,\r\n      enabled: copyRow.enabled,\r\n      id: this.newGuid(),\r\n      entryCodeGroup: copyRow.entryCodeGroup,\r\n      entryCode: copyRow.entryCode,\r\n      isIncluded: copyRow.isIncluded,\r\n      debitId: copyRow.debitId,\r\n      debitGrouping: copyRow.debitGrouping,\r\n      creditId: copyRow.creditId,\r\n      creditGrouping: copyRow.creditGrouping,\r\n      flags: angular.copy(copyRow.flags),\r\n    };\r\n    this.current.ruleSet.rows.splice(addToStart ? 0 : idx, 0, newRow);\r\n  }\r\n\r\n  /** Removes the row */\r\n  public removeRow(row: AccountingRuleSetRow) {\r\n    const idx = this.current.ruleSet.rows.findIndex((x) => x.id === row.id);\r\n    if (!row.isReadOnly) {\r\n      this.current.ruleSet.rows.splice(idx, 1);\r\n    }\r\n  }\r\n\r\n  /** Selects flags */\r\n  public selectFlags(row: AccountingRuleSetRow) {\r\n    const flags = angular.copy(this.flags);\r\n    for (const flag of flags) {\r\n      flag.isSelected = row.flags.some((x) => x === flag.value);\r\n    }\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/report/modals/Flags.html\",\r\n      null,\r\n      {\r\n        flags,\r\n      },\r\n    ).then((result) => {\r\n      if (result) {\r\n        row.flags = result.filter((x) => x.isSelected).map((x) => x.value);\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Paste data from clipboard. */\r\n  public pasteFromClipboard(): Promise<string> {\r\n    this.rawData = null;\r\n    this.fileExtension = null;\r\n    return (navigator as any).clipboard.readText().then((text) => {\r\n      this.rawData = text;\r\n      this.import();\r\n      // Ensure refresh in UI\r\n      return this.$timeout(() => {\r\n        return this.rawData;\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Reads the file\r\n   * @param file Selected file\r\n   */\r\n  public readFile(file: File): Promise<string> {\r\n    this.rawData = null;\r\n    this.fileExtension = null;\r\n    if (!file) {\r\n      return Promise.resolve(null);\r\n    }\r\n    // TODO detect if excel file and read content using Excel reader.\r\n    if (file.name) {\r\n      this.fileExtension = FileLogic.getExtensionFromFileName(file.name);\r\n    }\r\n\r\n    const read = new Promise<string>((resolve, reject) => {\r\n      const reader = new FileReader();\r\n      reader.onloadend = () => {\r\n        resolve(reader.result as string);\r\n      };\r\n      reader.onerror = () => reject;\r\n      reader.readAsText(file);\r\n    });\r\n\r\n    return read.then((text) => {\r\n      this.rawData = text;\r\n      this.import();\r\n      // Ensure refresh in UI\r\n      return this.$timeout(() => {\r\n        return text;\r\n      });\r\n    });\r\n\r\n  }\r\n\r\n  /**\r\n   * Import data\r\n   */\r\n  public import(): void {\r\n    let tableData: ImportResult<DataRow> = null;\r\n    if (this.fileExtension && this.fileExtension === \"xlsx\") {\r\n      this.uiHelpers.showAlert(\"Tiedoston muotoa ei tueta\", \"Excel-tiedostot eivät ole vielä tuettuja. Tallenna Excel-taulukko csv-muodossa tai kopioi taulukko leikepöydän kautta.\");\r\n      return;\r\n    }\r\n    const fileDelimeter = FileLogic.getFileDelimiter(this.rawData);\r\n    if (fileDelimeter === FileDelimiter.Unknown) {\r\n      this.uiHelpers.showAlert(\"Tiedoston muotoa ei tueta\", \"Virheellinen\");\r\n      return;\r\n    }\r\n    const firstRow = Tables.getFirstRow(this.rawData, fileDelimeter);\r\n    if (!firstRow.length) {\r\n      this.uiHelpers.showAlert(\"Tiedoston rivejä ei voida lukea\", \"Virheellinen\");\r\n      return;\r\n    }\r\n\r\n    const keys = Object.keys(firstRow);\r\n    const headers = !/\\d/.test(firstRow[keys[0]]) && !/\\d/.test(firstRow[keys[1]]) ? null : [\"aaaa\", \"bbbb\"];\r\n    tableData = Tables.import(this.rawData, FileLogic.getTableFormatByDelimeter(fileDelimeter), FileLogic.getCsvLocale(fileDelimeter), headers);\r\n\r\n\r\n    const validation = this.validateTableData(tableData);\r\n    if (validation.validationSuccess) {\r\n      const mappingResult = tableData.data.map((item) => {\r\n        return { account: item[validation.account].toString(), text: item[validation.text] } as AccountingRuleSetAccount;\r\n      });\r\n\r\n      if (this.current.ruleSet.targetCoA.length) {\r\n        this.uiHelpers.showConfirm(\"Tilikartan päivitys\", \"Haluatko korvata aikaisemman tilikarttasi tuodulla\", \"Kyllä\", \"En\").then((result) => {\r\n          if (result) {\r\n            this.current.ruleSet.targetCoA = mappingResult;\r\n          }\r\n        });\r\n      } else {\r\n        this.current.ruleSet.targetCoA = mappingResult;\r\n      }\r\n\r\n    } else {\r\n      this.uiHelpers.showAlert(\"Tiedoston muotoa ei tueta\", \"Virheellinen\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sort accounts\r\n   */\r\n  public sortRulesetAccounts(): void {\r\n    this.current.ruleSet.accounts.sort((a, b) => {\r\n      if (a.account > b.account) {\r\n        return 1;\r\n      }\r\n\r\n      if (a.account < b.account) {\r\n        return -1;\r\n      }\r\n\r\n      return 0;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Updates ruleSet account with provided targetCoA account\r\n   * @param targetCoaAccount targetCoA account\r\n   */\r\n  public updateRuleSetAccount(targetCoaAccount: AccountingRuleSetAccount) {\r\n    const item = this.current.ruleSet.accounts.find(x => x.account === targetCoaAccount.account);\r\n    if (item) {\r\n      item.text = targetCoaAccount.text;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Updates provided account text to match targetCoa account\r\n   * @param rulesetAccount ruleSet account\r\n   */\r\n  public updateAccountToMatchTargetCoa(rulesetAccount: AccountingRuleSetAccount) {\r\n    const item = this.current.ruleSet.targetCoA.find(x => x.account === rulesetAccount.account);\r\n    if (item) {\r\n      rulesetAccount.text = item.text;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return account text to ui\r\n   */\r\n   public get accountFilterText() {\r\n    switch (this.accountFilter) {\r\n      case \"all\":\r\n        return \"SALAXY.NG1.AccountingTargetDetailsComponent.filters.all\";\r\n      case \"includedAndEnabled\":\r\n        return \"SALAXY.NG1.AccountingTargetDetailsComponent.filters.includedAndEnabled\";\r\n      case \"error\":\r\n        return \"SALAXY.NG1.AccountingTargetDetailsComponent.filters.error\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Filter accounts\r\n   */\r\n  public get filteredAccounts(): AccountingRuleSetAccount[] {\r\n    switch(this.accountFilter) {\r\n      case \"all\":\r\n        return this.current.ruleSet.accounts;\r\n      case \"includedAndEnabled\":\r\n        return this.current.ruleSet.accounts.filter(account => this.current.ruleSet.rows.find(x => x.enabled && x.isIncluded && (x.debitId === account.id || x.creditId === account.id)));\r\n      case \"error\":\r\n        return this.current.ruleSet.accounts.filter(x => !this.current.ruleSet.targetCoA.map(item => { return item.account; }).includes(x.account));\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Get accounting rules acount for distinct view\r\n   * @param account account id\r\n   * @returns rules count as number\r\n   */\r\n  public getRulesCount(account: string): number {\r\n    const ids = this.current.ruleSet.accounts.filter(x => x.account === account).map(x => x.id);\r\n    switch(this.accountFilter) {\r\n      case \"all\":\r\n      case \"error\":\r\n        return this.current.ruleSet.rows.filter(x => ids.indexOf(x.debitId) >= 0 || ids.indexOf(x.creditId) >= 0).length;\r\n      case \"includedAndEnabled\":\r\n          return this.current.ruleSet.rows.filter(x => x.enabled && x.isIncluded && (ids.indexOf(x.debitId) >= 0  || ids.indexOf(x.creditId) >= 0)).length;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Created distinct object array with account key\r\n   */\r\n  public get distinctAccounts(): AccountingRuleSetAccount[] {\r\n    return [...new Map(this.filteredAccounts.map(item => [item[\"account\"], item])).values()];\r\n  }\r\n\r\n  /**\r\n   * Acount number of digits in account candidate\r\n   */\r\n  private countDigits(accountCandidate: string): number {\r\n    const digitsArr = accountCandidate.match(/\\d+/g);\r\n    if (digitsArr) {\r\n      return digitsArr.join(\"\").length;\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /**\r\n   * Validated generated Tables data\r\n   * @returns is TableData valid\r\n   */\r\n  private validateTableData(tableData: ImportResult<DataRow>): { validationSuccess: boolean, account: string, text: string } {\r\n    //Validate if data exists\r\n    if (!tableData.data) {\r\n      return { validationSuccess: false, account: null, text: null };\r\n    }\r\n\r\n    //Validate errors\r\n    if (tableData.errors.length !== 0) {\r\n      return { validationSuccess: false, account: null, text: null };\r\n    }\r\n\r\n    // Validate data array\r\n    if (tableData.data && tableData.data.length < 1) {\r\n      return { validationSuccess: false, account: null, text: null };\r\n    }\r\n\r\n    // Validate first data array entry key and value\r\n    for (const [key, value] of Object.entries(tableData.data[0])) {\r\n      if (key.length < 2 || value.length < 2) {\r\n        return { validationSuccess: false, account: null, text: null };\r\n      }\r\n    }\r\n\r\n    // Validate numeric field\r\n    for (const item of tableData.data) {\r\n      const keys = Object.keys(item);\r\n      // Check if item[keys[0]] or item[keys[0]] containt digits\r\n      // If no return validation false\r\n      // otherwise return validationSuccess true and figure out account and text\r\n      const firstKey = this.countDigits(item[keys[0]].toString());\r\n      const secondKey = this.countDigits(item[keys[1]].toString());\r\n      return !/\\d/.test(item[keys[0]]) && !/\\d/.test(item[keys[1]]) ? { validationSuccess: false, account: null, text: null } : { validationSuccess: true, account: firstKey > secondKey ? keys[0] : keys[1], text: firstKey > secondKey ? keys[1] : keys[0] };\r\n    }\r\n  }\r\n  private newGuid(): string {\r\n    let dt = new Date().getTime();\r\n    const uuid = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\r\n      /* eslint-disable-next-line no-bitwise */\r\n      const r = (dt + Math.random() * 16) % 16 | 0;\r\n      dt = Math.floor(dt / 16);\r\n      /* eslint-disable-next-line no-bitwise */\r\n      return (c === \"x\" ? r : (r & 0x3 | 0x8)).toString(16);\r\n    });\r\n    return uuid;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { AccountingTargetListItem, AccountingTargetSettings, CompanyAccountSettings, Dates, InputEnumOption, InsuranceContract, PensionContract, SettingsLogic, SettingsStatus, Years, InvoicesLogic, Usecase, UsecaseListItem, ApiItemType, Arrays, ExportMethod, WorkerSalarySlipDeliveryMethod, Configs, Ajax, PaymentChannel} from \"@salaxy/core\";\r\nimport { SessionService, SettingsService, UiHelpers } from \"../../services\";\r\n\r\ntype SettingsSection = \"pensionContracts\" |\r\n  \"yelPensionContracts\" |\r\n  \"insuranceContracts\" |\r\n  \"incomesRegister\" |\r\n  \"eInvoice\" |\r\n  \"sepa\" |\r\n  \"taxAndSocialSecuritySelfHandling\" |\r\n  \"workerSelfHandling\" |\r\n  \"unemploymentSelfHandling\" |\r\n  \"payslip\" |\r\n  \"omapalkka\";\r\n/**\r\n * Controller for the accountant settings.\r\n */\r\nexport class CompanySettingsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\", \"SettingsService\", \"UiHelpers\", \"AjaxNg1\", \"$sce\"];\r\n\r\n  /** If true, current item is read only */\r\n  public isReadOnlyForced: boolean;\r\n\r\n  /** Possibility to restrict sections that are visible in settings. */\r\n  public sections: SettingsSection[];\r\n\r\n  /** Yearly sidecosts */\r\n  public sideCosts = Years.getYearlyChangingNumbers(new Date()).sideCosts;\r\n\r\n  /** The current editable settings */\r\n  private _current: CompanyAccountSettings;\r\n\r\n  private saves: { [key: string]: boolean } = {};\r\n\r\n  constructor(private sessionService: SessionService, private settingsService: SettingsService, private uiHelpers: UiHelpers, private ajax: Ajax, private $sce: angular.ISCEService) {\r\n  }\r\n\r\n  /**\r\n   * Initializes the controller\r\n   */\r\n  public $onInit() {\r\n    this.sections = this.sections || [\"pensionContracts\", \"yelPensionContracts\", \"insuranceContracts\", \"incomesRegister\", \"payslip\", \"omapalkka\"];\r\n  }\r\n\r\n  /** Copy current from SettingsService */\r\n  public get current(): CompanyAccountSettings {\r\n    if (!this._current && this.settingsService.current) {\r\n      this._current = angular.copy(this.settingsService.current);\r\n    }\r\n    return this._current;\r\n  }\r\n\r\n\r\n  /** Returns current pension contracts once loaded assuring there is at least one active item. */\r\n  public get pensionContracts(): PensionContract[] | null {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!CompanySettingsController.getActive(this.current.calc.pensionContracts)) {\r\n      this.current.calc.pensionContracts.push({});\r\n    }\r\n    return this.current.calc.pensionContracts;\r\n  }\r\n\r\n  /** Returns current insurance contracts once loaded assuring there is at least one active item. */\r\n  public get insuranceContracts(): InsuranceContract[] | null {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!CompanySettingsController.getActive(this.current.calc.insuranceContracts)) {\r\n      this.current.calc.insuranceContracts.push({});\r\n    }\r\n    return this.current.calc.insuranceContracts;\r\n  }\r\n\r\n  /**\r\n   * Returns current default accounting target.\r\n   */\r\n  public get defaultAccountingTarget(): AccountingTargetSettings {\r\n    if (!this.current?.accounting?.targets || !this.current?.accounting?.defaultTargetId) {\r\n      return null;\r\n    }\r\n    return this.current.accounting.targets.find((x) => x.id == this.current?.accounting.defaultTargetId);\r\n  }\r\n\r\n  /**\r\n   * Returns true, if the contract should be visible:\r\n   * Companies: All pending contracts and first active contract.\r\n   * Personal: The first active contract, no pending contracts.\r\n   * @param contract Contract to evaluate\r\n   * @param allContracts Collection of contracts that contain the contract to evaluate.\r\n   */\r\n  public isVisibleContract<ContractType extends PensionContract | InsuranceContract>(contract: ContractType, allContracts: ContractType[]): boolean {\r\n    if (contract.status === SettingsStatus.Pending) {\r\n      // Show all pending for companies. For households, this is an error / legacy.\r\n      return this.sessionService.isInRole(\"company\") ? true : false;\r\n    }\r\n    return contract === CompanySettingsController.getActive(allContracts);\r\n  }\r\n\r\n  /** Gets the relevant contracts that are shown in personal (household) userinterface. */\r\n  public get personal(): {\r\n    insurance: InsuranceContract,\r\n    pension: PensionContract,\r\n  } {\r\n    const result = {\r\n      insurance: null,\r\n      pension: null,\r\n    };\r\n    if (!this.current) {\r\n      return result;\r\n    }\r\n    result.insurance = CompanySettingsController.getActive(this.insuranceContracts);\r\n    result.pension = CompanySettingsController.getActive(this.pensionContracts);\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Saves changes for settings\r\n   * @param section Section to save: Copies only that section to settingsService.\r\n   * Null saves nothing.\r\n   */\r\n  public save(section: SettingsSection | \"all\" | null) {\r\n    switch (section) {\r\n      case \"pensionContracts\":\r\n        this.settingsService.current.calc.pensionContracts = angular.copy(this.current.calc.pensionContracts);\r\n        this.settingsService.current.payments.customerFunds.isPensionSelfHandling = this.current.payments.customerFunds.isPensionSelfHandling;\r\n        break;\r\n      case \"insuranceContracts\":\r\n        this.settingsService.current.calc.insuranceContracts = angular.copy(this.current.calc.insuranceContracts);\r\n        break;\r\n      case \"incomesRegister\":\r\n        this.settingsService.current.calc.incomesRegister = angular.copy(this.current.calc.incomesRegister);\r\n        break;\r\n      case \"eInvoice\":\r\n        this.settingsService.current.payments.invoice.eInvoiceReceiver = this.current.payments.invoice.eInvoiceReceiver;\r\n        this.settingsService.current.payments.invoice.eInvoiceIntermediator = this.current.payments.invoice.eInvoiceIntermediator;\r\n        break;\r\n      case \"sepa\":\r\n        this.settingsService.current.payments.invoice.sepaBankPartyId = this.current.payments.invoice.sepaBankPartyId;\r\n        this.settingsService.current.payments.invoice.ibanNumber = this.current.payments.invoice.ibanNumber;\r\n        break;\r\n      case \"taxAndSocialSecuritySelfHandling\":\r\n        this.settingsService.current.payments.customerFunds.isTaxAndSocialSecuritySelfHandling = this.current.payments.customerFunds.isTaxAndSocialSecuritySelfHandling;\r\n        break;\r\n      case \"workerSelfHandling\":\r\n        this.settingsService.current.payments.customerFunds.isWorkerSelfHandling = this.current.payments.customerFunds.isWorkerSelfHandling;\r\n        break;\r\n      case \"unemploymentSelfHandling\":\r\n        return;\r\n      case \"payslip\": {\r\n        const methods = this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.filter(x => x !== WorkerSalarySlipDeliveryMethod.Payslip);\r\n        this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.splice(0, this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.length);\r\n        this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.push(...methods);\r\n        if(this.current.messaging.workerSalarySlipDeliveryMethods.indexOf(WorkerSalarySlipDeliveryMethod.Payslip) > -1) {\r\n          this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.push(WorkerSalarySlipDeliveryMethod.Payslip);\r\n        }\r\n        break;\r\n      }\r\n      case \"omapalkka\": {\r\n        const methods = this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.filter(x => x !== WorkerSalarySlipDeliveryMethod.Omapalkka);\r\n        this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.splice(0, this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.length);\r\n        this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.push(...methods);\r\n        if(this.current.messaging.workerSalarySlipDeliveryMethods.indexOf(WorkerSalarySlipDeliveryMethod.Omapalkka) > -1) {\r\n          this.settingsService.current.messaging.workerSalarySlipDeliveryMethods.push(WorkerSalarySlipDeliveryMethod.Omapalkka);\r\n        }\r\n        break;\r\n      }\r\n      case \"all\":\r\n        this.settingsService.current = angular.copy(this.current);\r\n        break;\r\n    }\r\n    if (section) {\r\n      this.saves[section] = true;\r\n      this.settingsService.save().then((data) => {\r\n        switch (section) {\r\n          case \"pensionContracts\":\r\n            this.current.calc.pensionContracts = angular.copy(data.calc.pensionContracts);\r\n            this.current.payments.customerFunds.isPensionSelfHandling = data.payments.customerFunds.isPensionSelfHandling;\r\n            break;\r\n          case \"insuranceContracts\":\r\n            this.current.calc.insuranceContracts = angular.copy(data.calc.insuranceContracts);\r\n            break;\r\n          case \"incomesRegister\":\r\n            this.current.calc.incomesRegister = angular.copy(data.calc.incomesRegister);\r\n            break;\r\n          case \"eInvoice\":\r\n            this.current.payments.invoice.eInvoiceReceiver = data.payments.invoice.eInvoiceReceiver;\r\n            this.current.payments.invoice.eInvoiceIntermediator = data.payments.invoice.eInvoiceIntermediator;\r\n            break;\r\n          case \"sepa\":\r\n            this.current.payments.invoice.sepaBankPartyId = data.payments.invoice.sepaBankPartyId;\r\n            this.current.payments.invoice.ibanNumber = data.payments.invoice.ibanNumber;\r\n            break;\r\n          case \"taxAndSocialSecuritySelfHandling\":\r\n            this.current.payments.customerFunds.isTaxAndSocialSecuritySelfHandling = data.payments.customerFunds.isTaxAndSocialSecuritySelfHandling;\r\n            break;\r\n          case \"workerSelfHandling\":\r\n            this.current.payments.customerFunds.isWorkerSelfHandling = data.payments.customerFunds.isWorkerSelfHandling;\r\n            break;\r\n          case \"payslip\":\r\n          case \"omapalkka\":\r\n            this.current.messaging.workerSalarySlipDeliveryMethods = data.messaging.workerSalarySlipDeliveryMethods;\r\n            break;\r\n          case \"all\":\r\n            this._current = angular.copy(data);\r\n            break;\r\n        }\r\n        this.saves[section] = false;\r\n      });\r\n    }\r\n  }\r\n  /**\r\n   * Send all workers paid calculations to omapalkka\r\n   */\r\n  public sendPaidCalculationsToOmapalkka() {\r\n    const loading = this.uiHelpers.showLoading();\r\n    this.ajax.postJSON(`${Configs.current.getOmapalkkaApiServer()}/api/messages/create-for-salary/all`, {}).then(() => {\r\n      loading.dismiss();\r\n    }).catch(e => {\r\n      console.error(e);\r\n      loading.dismiss();\r\n    });\r\n  }\r\n\r\n  /** Checks if switch input should be disabled on salarySlipDeliveryMethodsForm*/\r\n  public disableSwitchInput(): boolean{\r\n    return this.isSaving(\"omapalkka\") || this.isSaving(\"payslip\") || !!this.isReadOnlyForced || (!this.current.messaging.denyServiceModel && this.current.partner.serviceModel.features.messaging);\r\n  }\r\n\r\n  /**\r\n   * Sets pension number for test account to the given contract\r\n   * @param item Pension contract\r\n   */\r\n  public setPensionNumberForTest(item: PensionContract) {\r\n    item.contractNumber = SettingsLogic.getPensionNumberForTest(item.company);\r\n  }\r\n\r\n  /**\r\n   * Shows the eInvoice selection dialog\r\n   */\r\n  public selectEInvoiceAddress() {\r\n    this.settingsService.selectEInvoiceAddress(this.current.payments.invoice);\r\n  }\r\n\r\n  /**\r\n   * Gets the progress of save operation.\r\n   * @param section Section to check for saving.\r\n   * Note that \"all\" will check only \"all\" operations, not underlying sub-sections saving (\"any\").\r\n   */\r\n  public isSaving(section: SettingsSection | \"all\"): boolean {\r\n    return !!(this.saves[section] || this.saves[\"all\"]);\r\n  }\r\n\r\n  /**\r\n   * Event handler for accounting target selection.\r\n   * @param current Settings object to edit/create.\r\n   * @param logic Logic object passed to the dialog controller.\r\n   * @param logic.isReadOnly Read-only flag in logic.\r\n   * @param value Boolean indicating if the item is selected or not.\r\n   * @param item  The selected item.\r\n   * @param allItems All selected items.\r\n   */\r\n  public onAccountingTargetSelect(current: AccountingTargetSettings, logic: { isReadOnly: boolean }, value: boolean, item: AccountingTargetListItem, allItems: AccountingTargetListItem[]) {\r\n    allItems.splice(0, allItems.length);\r\n    logic.isReadOnly = true;\r\n    if (value == true) {\r\n      current.id = item.id;\r\n      current.avatar = item.otherPartyInfo.avatar;\r\n      current.format = item.data.format;\r\n      current.channel = item.data.channel;\r\n      current.method = item.data.method;\r\n      current.availableMethods = Arrays.assureArray(item.data.availableMethods) as ExportMethod[];\r\n      logic.isReadOnly = false;\r\n      allItems.push(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Event handler for usecase selection.\r\n   * @param current Settings object to edit/create.\r\n   * @param logic Logic object passed to the dialog controller.\r\n   * @param logic.isReadOnly Read-only flag in logic.\r\n   * @param value Boolean indicating if the item is selected or not.\r\n   * @param item  The selected item.\r\n   * @param allItems All selected items.\r\n   */\r\n  public onUsecaseSelect(current: Usecase, logic: { isReadOnly: boolean }, value: boolean, item: UsecaseListItem, allItems: UsecaseListItem[]) {\r\n    allItems.splice(0, allItems.length);\r\n    logic.isReadOnly = true;\r\n    if (value == true) {\r\n      current.uri = item.reference;\r\n      current.label = item.shortText;\r\n      current.itemType = item.entityType as ApiItemType;\r\n      current.status = item.status;\r\n      current.order = item.data.order;\r\n      logic.isReadOnly = false;\r\n      allItems.push(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return Avatar from current.payment.channels ENUM\r\n   * @returns Avatar\r\n   */\r\n  public getPaymentChannelAvatar(item) {\r\n    return InvoicesLogic.getChannelAvatar(item.channel);\r\n  }\r\n\r\n  /**\r\n   * Created InputEnumOption [] from current.accounting.targets\r\n   * @returns InputEnumOption [] for template\r\n   */\r\n  public getSelectableAccountingTargets(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"selectableAccountingTargets\", () => {\r\n      return this.current.accounting.targets.map(item => ({\r\n        text: item.avatar.displayName,\r\n        value: item.id,\r\n        ui: { avatar: item.avatar }\r\n      }) as InputEnumOption);\r\n    }, () => this.current.accounting.targets.map(item => item.id)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Created InputEnumOption [] from current.payment.channels\r\n   * @returns InputEnumOption [] for template\r\n   */\r\n\r\n  public getSelectablePaymenMethods(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"selectablePaymentMethods\", () => {\r\n      return this.current.payments.channels.map(item => {\r\n        const avatar = InvoicesLogic.getChannelAvatar(item.channel) ?? InvoicesLogic.getChannelAvatar(PaymentChannel.Undefined);\r\n        return {\r\n          text: avatar.displayName,\r\n          value: avatar.id,\r\n          ui: { avatar: avatar }\r\n        } as InputEnumOption;\r\n      });\r\n    }, () => this.current.payments.channels.map(item => InvoicesLogic.getChannelAvatar(item.channel)?.id)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Returns true if the payslip is included in worker's SalarySlipDeliveryMethods.\r\n   */\r\n  public get payslip(): boolean {\r\n    return this.current?.messaging?.workerSalarySlipDeliveryMethods?.indexOf(WorkerSalarySlipDeliveryMethod.Payslip) >= 0 || false;\r\n  }\r\n\r\n  /**\r\n   * Sets/unsets the payslip as one of worker's SalarySlipDeliveryMethods.\r\n   * @param value Boolean value if the payslip should be set.\r\n   */\r\n   public set payslip(value: boolean) {\r\n    if (!this.current) {\r\n      return;\r\n    }\r\n    if (!value) {\r\n      const methods = this.current.messaging.workerSalarySlipDeliveryMethods.filter(x => x !== WorkerSalarySlipDeliveryMethod.Payslip);\r\n      this.current.messaging.workerSalarySlipDeliveryMethods.splice(0, this.current.messaging.workerSalarySlipDeliveryMethods.length);\r\n      this.current.messaging.workerSalarySlipDeliveryMethods.push(...methods);\r\n    } else {\r\n      if (this.current.messaging.workerSalarySlipDeliveryMethods.indexOf(WorkerSalarySlipDeliveryMethod.Payslip) < 0) {\r\n        this.current.messaging.workerSalarySlipDeliveryMethods.push(WorkerSalarySlipDeliveryMethod.Payslip);\r\n      }\r\n    }\r\n    this.save(\"payslip\");\r\n  }\r\n\r\n  /**\r\n   * Returns true if the omapalkka is included in worker's SalarySlipDeliveryMethods.\r\n   */\r\n  public get omapalkka(): boolean {\r\n    return this.current?.messaging?.workerSalarySlipDeliveryMethods?.indexOf(WorkerSalarySlipDeliveryMethod.Omapalkka) >= 0 || false;\r\n  }\r\n\r\n  /**\r\n   * Sets/unsets the omapalkka as one of worker's SalarySlipDeliveryMethods.\r\n   * @param value Boolean value if the payslip should be set.\r\n   */\r\n   public set omapalkka(value: boolean) {\r\n    if (!this.current) {\r\n      return;\r\n    }\r\n    if (!value) {\r\n      const methods = this.current.messaging.workerSalarySlipDeliveryMethods.filter(x => x !== WorkerSalarySlipDeliveryMethod.Omapalkka);\r\n      this.current.messaging.workerSalarySlipDeliveryMethods.splice(0, this.current.messaging.workerSalarySlipDeliveryMethods.length);\r\n      this.current.messaging.workerSalarySlipDeliveryMethods.push(...methods);\r\n    } else {\r\n      if (this.current.messaging.workerSalarySlipDeliveryMethods.indexOf(WorkerSalarySlipDeliveryMethod.Omapalkka) < 0) {\r\n        this.current.messaging.workerSalarySlipDeliveryMethods.push(WorkerSalarySlipDeliveryMethod.Omapalkka);\r\n      }\r\n    }\r\n    this.save(\"omapalkka\");\r\n  }\r\n\r\n  /**\r\n   * Confirm service change\r\n   */\r\n  public confirmServiceModelChange() {\r\n    this.uiHelpers.showConfirm(\"Palvelumallin ohitus\", \"Olet muuttamassa palvelumallin käyttöä. Paina 'Ok' tallentaaksesi\").then((result) => {\r\n      if (result) {\r\n        this.save(\"all\");\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Creates datauri for given image\r\n   * @param logo Logo for dataurl\r\n   */\r\n  public createReportLogoDatauri(logo: any) {\r\n    const createDataUri = (logo): Promise<string> => {\r\n      return new Promise((resolve, reject) => {\r\n        const reader = new FileReader();\r\n        reader.onload = (event) => {\r\n          resolve(event.target?.result as string);\r\n        };\r\n        reader.onerror = (error) => {\r\n          reject(error);\r\n        };\r\n        reader.readAsDataURL(logo);\r\n      });\r\n    };\r\n    createDataUri(logo).then(dataUri => {\r\n      this.current.reporting.logo = `<img src=\"${dataUri}\">`;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Retrieves the report logo.\r\n   * @returns The report logo as a html string.\r\n   */\r\n  public getReportLogo(): string {\r\n    if(!this.current.reporting.logo){\r\n      return \"\";\r\n    }\r\n\r\n    if(this.current.reporting.logo.startsWith(\"<img src=\")){\r\n      return this.current.reporting.logo;\r\n    }\r\n\r\n    if(this.current.reporting.logo.startsWith(\"<svg\")){\r\n      return this.$sce.trustAsHtml(this.current.reporting.logo);\r\n    }\r\n  }\r\n\r\n  private static getActive<ContractType extends PensionContract | InsuranceContract>(contracts: ContractType[]): ContractType {\r\n    const today = Dates.getToday();\r\n    return contracts?.find((x) => x.status !== SettingsStatus.Pending &&\r\n    Dates.isSameOrAfter(today, x.startDate ?? \"1900-01-01\") &&\r\n    Dates.isBefore(today, Dates.add(x.endDate ?? \"2100-01-01\", 1,\"day\")));\r\n  }\r\n}\r\n\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, LocalTapiolaInsuranceOrder, LocalTapiolaInsuranceOrderType, PartnerServices, Translations } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, WizardService, WizardStep } from \"../../services\";\r\n\r\nimport { WizardController } from \"../bases/WizardController\";\r\n\r\n/**\r\n * Wizard for sending Local Tapiola Insurance Order\r\n */\r\nexport class InsuranceWizardController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   */\r\n  public static $inject = [\"$scope\", \"WizardService\", \"PartnerServices\", \"UiHelpers\"];\r\n\r\n\r\n  /** Insurance action */\r\n  public action: \"newInsurance\" | \"moveInsurance\" | \"newInsuranceForEntrepreneur\";\r\n\r\n  /** Form data validity */\r\n  public formDataValidity: boolean;\r\n\r\n  /** Indicates if the order has been sent. */\r\n  public isSent = false;\r\n\r\n  /** Indicates if order is just sending */\r\n  public isSending = false;\r\n\r\n  /** Current Local Tapiola insurance order data. */\r\n  public current: LocalTapiolaInsuranceOrder = null;\r\n\r\n\r\n  /** Today (for datepicker minDate) */\r\n  public today = Dates.getToday();\r\n\r\n  /** Minimum date for new insurance contract start date (datepicker-options.minDate) */\r\n  public insuranceDateOptions = {\r\n    minDate: this.today,\r\n  };\r\n\r\n  public countryCodes = {\r\n    FI: \"Suomi\",\r\n    SV: \"Sverige\",\r\n    EE: \"Eesti\"\r\n  };\r\n\r\n  /** Next possible dates for moving insurance to LocalTapiola */\r\n  public insuranceStartingPointDateOptions = {};\r\n\r\n  /** LocalTapiola Insurance wizard configuration */\r\n  private wizardSteps: WizardStep[] = [\r\n    { // 0\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.start.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.start.wizard.title\"),\r\n      intro: \"\",\r\n      active: true,\r\n      view: \"salaxy-components/modals/localTapiola/Start.html\",\r\n    },\r\n    { // 1\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfo.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfo.wizard.heading\"),\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/ContactInfo.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 2\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Owner-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 3\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Beneficiary-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    {\r\n      // 4\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.insuranceInfoNew.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.insuranceInfoNew.wizard.heading\"),\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/InsuranceInfo-new.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-send.html\", //buttons send\r\n    },\r\n    {\r\n      // 5\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.entrepreneur.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.entrepreneur.wizard.heading\"),\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/Entrepreneur.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 6\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfoEntrepreneur.wizard.title\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfoEntrepreneur.wizard.heading\"),\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/ContactInfo-entrepreneur.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 7\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.titleAlt\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Owner-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 8\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.titleAlt\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Beneficiary-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-send.html\",\r\n    },\r\n    { // 9\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfo.wizard.titleAlt\"),\r\n      heading: \"\",\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.contactInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/ContactInfo.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 10\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.titleMoveInsurance\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.ownerInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Owner-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 11\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.titleMoveInsurance\"),\r\n      heading: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.heading\"),\r\n      intro: Translations.get(\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.intro\"),\r\n      view: \"salaxy-components/modals/localTapiola/Beneficiary-info.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-default.html\",\r\n    },\r\n    { // 12\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.insuranceMove.wizard.title\"),\r\n      heading: \"\",\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/InsuranceInfo-move.html\",\r\n      buttonsView: \"salaxy-components/modals/localTapiola/buttons-send.html\",\r\n    },\r\n    { // 13\r\n      title: Translations.get(\"SALAXY.NG1.InsuranceComponent.thankYou.wizard.title\"),\r\n      heading: \"\",\r\n      intro: \"\",\r\n      view: \"salaxy-components/modals/localTapiola/ThankYou.html\",\r\n\r\n    },\r\n  ];\r\n\r\n  private newSteps = [\r\n    this.wizardSteps[0], // start\r\n    this.wizardSteps[1], // contact new\r\n    this.wizardSteps[2], // owner info\r\n    this.wizardSteps[3], // beneficiary info\r\n    this.wizardSteps[4], // additional info\r\n    this.wizardSteps[13], // thank you\r\n  ];\r\n\r\n  private newEntrepreneurSteps = [\r\n    this.wizardSteps[0], // start\r\n    this.wizardSteps[5], // additional info entrepreneur\r\n    this.wizardSteps[6], // contact info\r\n    this.wizardSteps[7], // owner info\r\n    this.wizardSteps[8], // beneficiary info\r\n    this.wizardSteps[13], // thank you\r\n  ];\r\n\r\n  private moveSteps = [\r\n    this.wizardSteps[0], // start\r\n    this.wizardSteps[9], // contact info (move)\r\n    this.wizardSteps[10], // owner info\r\n    this.wizardSteps[11], // beneficiary info\r\n    this.wizardSteps[12], // additional info (move)\r\n    this.wizardSteps[13], // thank you\r\n  ];\r\n\r\n  /**\r\n   * Creates a new WizardController\r\n   * @param $scope - The Angular scope\r\n   * @param wizardService - Maintains the state of the wizard\r\n   * @param partnerServices - Local Tapiola insurance orders API\r\n   * @param uiHelpers - Salaxy UI helpers\r\n   */\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    wizardService: WizardService,\r\n    private partnerServices: PartnerServices,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    super($scope, wizardService);\r\n  }\r\n\r\n  /**\r\n   * Sets the current wizard action and wizard steps\r\n   * @param insuranceAction - Action to performs: order new or move existing insurance.\r\n   */\r\n  public setInsuranceAction(insuranceAction: \"newInsurance\" | \"moveInsurance\" | \"newInsuranceForEntrepreneur\") {\r\n    this.isSending = false;\r\n    this.isSent = false;\r\n    this.formDataValidity = true;\r\n    this.action = insuranceAction;\r\n    this.getStartingPointDates();\r\n    this.current.id = null;\r\n    if (this.current.company.beneficiaries.length === 0) {\r\n      this.current.company.beneficiaries.push({});\r\n    }\r\n    if (this.current.company.owners.length === 0) {\r\n      this.current.company.owners.push({});\r\n    }\r\n\r\n\r\n    switch (insuranceAction) {\r\n      case \"newInsurance\":\r\n        this.current.items = [\r\n          {\r\n            orderType: LocalTapiolaInsuranceOrderType.NewWorkerInsurance,\r\n            occupations: [{}],\r\n          }\r\n        ];\r\n        this.wizardService.setSteps(this.newSteps);\r\n        break;\r\n      case \"moveInsurance\":\r\n        this.current.items = [\r\n          {\r\n            orderType: LocalTapiolaInsuranceOrderType.MoveWorkerInsurance,\r\n            occupations: [{}],\r\n          }\r\n        ];\r\n        this.wizardService.setSteps(this.moveSteps);\r\n        break;\r\n      case \"newInsuranceForEntrepreneur\":\r\n        this.current.items = [\r\n          {\r\n            orderType: LocalTapiolaInsuranceOrderType.NewEntrepreneurInsurance,\r\n            occupations: [{}],\r\n          }\r\n        ];\r\n        this.wizardService.setSteps(this.newEntrepreneurSteps);\r\n        break;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    this.partnerServices.getNewLocalTapiolaInsuranceOrder().then((data) => {\r\n      this.current = data;\r\n    });\r\n  };\r\n\r\n\r\n  /** Send the current order. */\r\n  public send() {\r\n\r\n    if (this.isSending) {\r\n      return;\r\n    }\r\n    if (this.isSent) {\r\n      this.goNext();\r\n      return;\r\n    }\r\n    this.isSending = true;\r\n\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n\r\n    this.partnerServices.sendLocalTapiolaInsuranceOrder(this.current).then(() => {\r\n      loading.dismiss();\r\n      this.goNext();\r\n      this.isSent = true;\r\n      this.isSending = false;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get next possible dates for moving existing insurance contract to LocalTapiola\r\n   */\r\n  public getStartingPointDates() {\r\n    // Quarter starting dates as strings\r\n    const asap = \"Ensimmäinen mahdollinen ajankohta\";\r\n    const firstDate = Dates.add(Dates.startEnd(\"today\",\"start-quarter\"),1, \"quarter\");\r\n    const secondDate = Dates.add(Dates.startEnd(\"today\",\"start-quarter\"),2, \"quarter\");\r\n    const thirdDate = Dates.add(Dates.startEnd(\"today\",\"start-quarter\"),3, \"quarter\");\r\n    const fourthDate = Dates.add(Dates.startEnd(\"today\",\"start-quarter\"),4, \"quarter\");\r\n\r\n\r\n    this.insuranceStartingPointDateOptions = {\r\n      [asap]: \"Ensimmäinen mahdollinen ajankohta\",\r\n      [Dates.format(firstDate,\"YYYY-MM-DD\")]: Dates.format(firstDate,\"D.M.YYYY\"),\r\n      [Dates.format(secondDate,\"YYYY-MM-DD\")]: Dates.format(secondDate,\"D.M.YYYY\"),\r\n      [Dates.format(thirdDate,\"YYYY-MM-DD\")]: Dates.format(thirdDate,\"D.M.YYYY\"),\r\n      [Dates.format(fourthDate,\"YYYY-MM-DD\")]: Dates.format(fourthDate,\"D.M.YYYY\"),\r\n    };\r\n\r\n  }\r\n\r\n  /** Go to the next step */\r\n  public goNext() {\r\n    // TODO remove when ready and use super\r\n    this.step++;\r\n    //super.goNext();\r\n  }\r\n\r\n  /**\r\n   * Go to the last step (\"thank you\" step)\r\n   */\r\n  public goToLast() {\r\n    this.step = this.steps.length;\r\n  }\r\n  /**\r\n   * Navigates to the previous step if possible and saves the data.\r\n   */\r\n  public goPrevious() {\r\n    super.goPrevious();\r\n  }\r\n\r\n  /**\r\n   * Returns true, if the given order type exists in the current order items.\r\n   * @param orderTypes - Order type to check.\r\n   * @returns True, if the order type is found, otherwise default.\r\n   */\r\n  public hasOrderType(...orderTypes: LocalTapiolaInsuranceOrderType[]): boolean {\r\n    return (orderTypes ?? []).some((x) => !!(this.current.items ?? []).find((i) => i.orderType === x));\r\n  }\r\n\r\n  /** Returns true if user can go forward in wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity) {\r\n          return true;\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Opens the insurance dialog. */\r\n  public openModal() {\r\n    this.wizardService.setSteps([this.wizardSteps[0]]);\r\n    this.step = 1;\r\n    this.uiHelpers.showDialog(\r\n      \"salaxy-components/modals/account/Insurance.html\",\r\n      \"InsuranceWizardController\",\r\n      null,\r\n      null,\r\n      \"lg\");\r\n  }\r\n\r\n  /**\r\n   * Validates the order.\r\n   */\r\n  public validate(): Promise<LocalTapiolaInsuranceOrder> {\r\n    return this.partnerServices.validateLocalTapiolaInsuranceOrder(this.current).then((order) => {\r\n      this.current = order;\r\n      return this.current;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Resets the current order.\r\n   */\r\n  public reset() {\r\n    // this.current = null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Arrays, BeneficialOwners, BeneficialOwnersApi } from \"@salaxy/core\";\r\n\r\n/**\r\n * Handles user interfaces for Owner and Beneficiary lists\r\n */\r\nexport class OwnerSettingsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"BeneficialOwnersApi\", \"$timeout\"];\r\n\r\n  /** Mode */\r\n  public mode: \"byPercent\" | \"byAmount\" = \"byAmount\";\r\n\r\n  /** Current owners. */\r\n  public current: BeneficialOwners = null;\r\n\r\n  /** If true, current item is read only */\r\n  public isReadOnlyForced: \"<\";\r\n\r\n  private saves: { [key: string] : boolean } = {};\r\n\r\n  constructor(private beneficialOwnersApi: BeneficialOwnersApi, private $timoeut: angular.ITimeoutService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n\r\n    this.beneficialOwnersApi.get().then((data) => {\r\n      this.current = data;\r\n    });\r\n  };\r\n\r\n  /**\r\n   * Total amount of user input shares\r\n   */\r\n  public getTotalAmount(): number {\r\n    if (!this.mode || !this.current) {\r\n      return 0;\r\n    }\r\n    return Arrays.sum(this.current.owners, (x) => x.numberOfShares ?? 0);\r\n  }\r\n\r\n  /**\r\n   * Total percentage of user input shares\r\n   */\r\n  public getTotalPercent(): number {\r\n    if (!this.mode || !this.current) {\r\n      return 0;\r\n    }\r\n    return Arrays.sum(this.current.owners, (x) => x.percentOfShares ?? 0);\r\n  }\r\n\r\n  /**\r\n   * Calculates percentage from the given share amount\r\n   */\r\n  public getPercentFromAmount(numberOfShares: number): number {\r\n    if (this.mode == \"byAmount\" && this.current && this.current.ownedCompanyDetails.totalNumberOfShares != null) {\r\n      return (numberOfShares / this.current.ownedCompanyDetails.totalNumberOfShares) * 100;\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /**\r\n   * Calculates share amount from the given share percentage\r\n   */\r\n  public getAmountFromPercent(percentOfShares: number): number {\r\n    if (this.mode == \"byPercent\" && this.current && this.current.ownedCompanyDetails.totalNumberOfShares != null) {\r\n      return this.current.ownedCompanyDetails.totalNumberOfShares * (percentOfShares / 100);\r\n    }\r\n    return 0;\r\n  }\r\n\r\n  /**\r\n   * update\r\n   */\r\n  public recalculateShares() {\r\n    if (!this.mode || !this.current) {\r\n      return;\r\n    }\r\n    if (this.mode == \"byPercent\") {\r\n      for (const singleOwner of this.current.owners) {\r\n        singleOwner.numberOfShares = this.current.ownedCompanyDetails.totalNumberOfShares * ( singleOwner.percentOfShares / 100 );\r\n      }\r\n    }\r\n    if (this.mode == \"byAmount\") {\r\n      for (const singleOwner of this.current.owners) {\r\n        singleOwner.percentOfShares = ( singleOwner.numberOfShares / this.current.ownedCompanyDetails.totalNumberOfShares ) * 100;\r\n      }\r\n    }\r\n  }\r\n\r\n  /** Saves the current owners and beneficiaries to backend. */\r\n  public save(target: \"owners\" | \"beneficiaries\") {\r\n    this.saves[target] = true;\r\n    this.beneficialOwnersApi.save(this.current).then( (data) => {\r\n      this.current = data;\r\n      this.saves[target] = false;\r\n    });\r\n  }\r\n\r\n  /** Indicates the progress of save operation. */\r\n  public isSaving(target: \"owners\" | \"beneficiaries\"): boolean {\r\n    return this.saves[target] || false;\r\n  }\r\n\r\n}","import { Avatar, Configs, InvoicesLogic, PaymentChannel, PaymentChannelSettings, PaymentChannelSettingsInfo, PensionCompany } from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, SessionService, SettingsService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Handles user interfaces for specifying settings for Payment Channels (and other payment related settings).\r\n */\r\nexport class PaymentChannelSettingsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SettingsService\", \"UiHelpers\", \"SessionService\"];\r\n\r\n  private lastPaymentChannelWindow: PaymentChannel;\r\n\r\n  private _siteChannels: PaymentChannelSettings[] = null;\r\n\r\n  constructor(\r\n    private settingsService: SettingsService,\r\n    private uiHelpers: UiHelpers,\r\n    private sessionService: SessionService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Controller initializations\r\n   */\r\n  public $onInit = () => {\r\n    // none\r\n  };\r\n\r\n  /**\r\n   * Gets the current settings object as soon as it is loaded.\r\n   * Note that this is null until the settings have been loaded from server.\r\n   */\r\n  public get current() {\r\n    return this.settingsService.current;\r\n  }\r\n\r\n  /**\r\n   * If the channels are set site specific (e.g. custom sites), the settings cannot be saved.\r\n   * Site specific changes are done to session, and exposed by InvoicesService\r\n   */\r\n  public get isReadOnly() {\r\n    // no settings\r\n    if (!this.current) {\r\n      return true;\r\n    }\r\n    // partner override\r\n    if (this.current.partner.serviceModel.features.payments && !this.current.payments.denyServiceModel) {\r\n      return true;\r\n    }\r\n    // site override\r\n    if (this.isSiteSpecific) {\r\n      return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  /** Returns true, if the settings are site specific. */\r\n  public get isSiteSpecific() {\r\n    const enabled = this.current.payments.channels.filter( (x) => x.isAvailable && x.isEnabled);\r\n    const sameLength = enabled.length === this.sessionService.getSession()?.settings?.paymentChannels?.length;\r\n    if (sameLength && enabled.length > 0) {\r\n      const sameIds = this.sessionService.getSession().settings.paymentChannels.every((x) => enabled.some((c) => c.channel === x));\r\n      if (sameIds) {\r\n        return false;\r\n      }\r\n    }\r\n    return true;\r\n  }\r\n\r\n  /**\r\n   * Gets the payment channel.\r\n   * @param type Type of the channel to list:\r\n   *\r\n   * - enabled: Enabled channels\r\n   * - available: Available channels that can be enabled (have not yet been enabled).\r\n   * - unavailable: Unavailable channels (cannot be enabled)\r\n   * - all: Really all channels, even the technical ones that cannot be enabled.\r\n   */\r\n  public getPaymentChannels(type: \"all\" | \"available\" | \"enabled\" | \"unavailable\"): PaymentChannelSettings[] {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    let all: PaymentChannelSettings[] = [];\r\n    if (this.isSiteSpecific) {\r\n      if (this._siteChannels === null) {\r\n        this._siteChannels = this.sessionService.getSession().settings.paymentChannels.map<PaymentChannelSettings>((c) => ({ channel: c, isEnabled: true, isAvailable: true }));\r\n      }\r\n      all = all.concat(this._siteChannels);\r\n    } else {\r\n      all = all.concat(this.current.payments.channels);\r\n    }\r\n    all = all.filter((x) =>\r\n      x.channel !== PaymentChannel.PalkkausManual ||\r\n      (x.channel === PaymentChannel.PalkkausManual && this.sessionService.isInSomeRole(\"pro,sepaPartner\"))\r\n    );\r\n\r\n    switch (type) {\r\n      case \"all\":\r\n        return all;\r\n      case \"available\":\r\n        return all.filter((x) => x.isAvailable && !x.isEnabled);\r\n      case \"unavailable\":\r\n        return all.filter((x) => !x.isAvailable);\r\n      case \"enabled\":\r\n      default:\r\n        return all.filter((x) => x.isAvailable && x.isEnabled);\r\n    }\r\n  }\r\n\r\n  /** Gets the visual representation and language versioned UI texts of the payment channel */\r\n  public getAvatar(channel: PaymentChannel): Avatar {\r\n    return InvoicesLogic.getChannelAvatar(channel);\r\n  }\r\n\r\n  /** Gets the default channel. */\r\n  public get defaultChannel() {\r\n    return this.sessionService.getSession().settings.defaultPaymentChannel;\r\n  }\r\n\r\n  /** Opens the channel setup dialog in a new window. */\r\n  public openChannelSetupDialog(channel: PaymentChannel) {\r\n    let url = null;\r\n    let isExternal = false;\r\n    switch (channel) {\r\n      case PaymentChannel.Test:\r\n        isExternal = true;\r\n        url =\r\n          Configs.current.isTestData ?\r\n            \"https://test-integrations.salaxy.com/test#/dialogs/settings\" :\r\n            \"https://integrations.salaxy.com/test#/dialogs/settings\";\r\n        url += \"?token=\" + this.sessionService.getCurrentToken();\r\n        break;\r\n      case PaymentChannel.Procountor:\r\n        isExternal = true;\r\n        url =\r\n          Configs.current.isTestData ?\r\n            \"http://localhost:93/procountor/settings.html\" :\r\n            \"https://integrations.salaxy.com/procountor/settings.html\";\r\n        url += \"?token=\" + this.sessionService.getCurrentToken();\r\n        break;\r\n      case PaymentChannel.VismaNetvisor:\r\n        isExternal = true;\r\n        url =\r\n          Configs.current.isTestData ?\r\n            \"http://localhost:93/vismanetvisor/settings.html\" :\r\n            \"https://integrations.salaxy.com/vismanetvisor/settings.html\";\r\n        url += \"?token=\" + this.sessionService.getCurrentToken();\r\n        break;\r\n      default:\r\n        break;\r\n    }\r\n\r\n    const channelInEdit = this.getPaymentChannels(\"all\").find((x) => x.channel === channel);\r\n    if (!channelInEdit) {\r\n      this.uiHelpers.showAlert(\"Maksutapaa ei voi muokata\", \"Palkanlaskentasivuston asetukset estävät maksutavan muokkauksen.\");\r\n      return;\r\n    }\r\n\r\n    const p = this.current.payments;\r\n    const supportedCompanies = [PensionCompany.None, PensionCompany.Ilmarinen, PensionCompany.Elo, PensionCompany.Varma];\r\n    const isPensionIncludedSupported = this.current.calc.pensionContracts\r\n      .every((x) => supportedCompanies.indexOf(x.company) >= 0);\r\n\r\n    // TODO: Go through this data model and see what really is necessary?\r\n    const channelSettings: PaymentChannelSettingsInfo | any = {\r\n      id: channelInEdit.channel,\r\n      isDefault: channelInEdit.channel == this.defaultChannel,\r\n      settings: {\r\n        data: channelInEdit.data,\r\n        isAvailable: channelInEdit.isAvailable,\r\n        isEnabled: channelInEdit.isEnabled,\r\n      },\r\n      customerFundsSettings: {\r\n        isPensionIncludedSupported,\r\n        isPensionSelfHandling: p.customerFunds.isPensionSelfHandling,\r\n        isTaxAndSocialSecuritySelfHandling: p.customerFunds.isTaxAndSocialSecuritySelfHandling,\r\n        isWorkerSelfHandling: p.customerFunds.isWorkerSelfHandling,\r\n      },\r\n      invoiceSettings: {\r\n        eInvoiceIntermediator: p.invoice.eInvoiceIntermediator,\r\n        eInvoiceReceiver: p.invoice.eInvoiceReceiver,\r\n        ibanNumber: p.invoice.ibanNumber,\r\n        sepaBankPartyId: p.invoice.sepaBankPartyId,\r\n      },\r\n      isReadOnly: this.isReadOnly,\r\n    };\r\n\r\n    const saveSettings = (action: EditDialogKnownActions | \"set-default\", data: PaymentChannelSettingsInfo | any) => {\r\n\r\n      if (action === EditDialogKnownActions.Cancel) {\r\n        console.debug(\"Canceling: Remove this message\");\r\n        return;\r\n      }\r\n      if (data.id !== this.lastPaymentChannelWindow) {\r\n        throw new Error(`Invalid response from channel ${data.id || \"undefined\"}, expected ${this.lastPaymentChannelWindow}.`);\r\n      }\r\n\r\n      let channelToSave = p.channels.find((x) => x.channel === channel);\r\n      if (!channelToSave) {\r\n        channelToSave = channelInEdit;\r\n        p.channels.push(channelToSave);\r\n      }\r\n\r\n      if (action === EditDialogKnownActions.Ok || action === \"set-default\") {\r\n\r\n        channelToSave.data = data.settings.data;\r\n        channelToSave.isEnabled = channelToSave.isAvailable && true;\r\n        if (action === \"set-default\") {\r\n          p.defaultChannel = channel;\r\n        }\r\n\r\n        p.customerFunds.isPensionSelfHandling = data.customerFundsSettings.isPensionSelfHandling;\r\n        p.customerFunds.isTaxAndSocialSecuritySelfHandling = data.customerFundsSettings.isTaxAndSocialSecuritySelfHandling;\r\n        p.customerFunds.isWorkerSelfHandling = data.customerFundsSettings.isWorkerSelfHandling;\r\n\r\n        p.invoice.eInvoiceIntermediator = data.invoiceSettings.eInvoiceIntermediator;\r\n        p.invoice.eInvoiceReceiver = data.invoiceSettings.eInvoiceReceiver;\r\n        p.invoice.ibanNumber = data.invoiceSettings.ibanNumber;\r\n        p.invoice.sepaBankPartyId = data.invoiceSettings.sepaBankPartyId;\r\n\r\n        this.settingsService.save();\r\n      }\r\n      if (action === EditDialogKnownActions.Delete) {\r\n        channelInEdit.isEnabled = false;\r\n        // TODO: Make sure that server-side does not allow deleting last channel and that it sets the default channel if none is selected.\r\n        this.settingsService.save();\r\n      }\r\n    };\r\n\r\n    this.lastPaymentChannelWindow = channel;\r\n    if (isExternal) {\r\n      this.uiHelpers.showExternalDialog(channelSettings.id, url, channelSettings).then((dialogResult) => {\r\n          saveSettings(dialogResult.action as EditDialogKnownActions, dialogResult.item);\r\n      });\r\n    } else {\r\n      this.uiHelpers.openEditDialog(`salaxy-components/modals/settings/PaymentChannel.html`, channelSettings,\r\n        {\r\n          channelAvatar: InvoicesLogic.getChannelAvatar(channelSettings.id),\r\n          selectEInvoiceAddress: (itemRef) => {\r\n            this.settingsService.selectEInvoiceAddress(itemRef);\r\n          },\r\n        }\r\n      ).then((dialogResult) => {\r\n          saveSettings(dialogResult.action as EditDialogKnownActions, dialogResult.item);\r\n      });\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { EditDialogKnownActions, RowTypeService, UiHelpers } from \"../../services\";\r\nimport { CalcRowConfig, CalcRowsLogic, CalculationRowCategory, CalculationRowSource, CalculationRowType, CalculatorLogic, Employment, InputEnumOption, UserDefinedRowLogic, RowTypeDefinition, RowsUsecaseLogic } from \"@salaxy/core\";\r\n\r\n/**\r\n * Controller for editing the row types in settings (Palkkalajit)\r\n */\r\nexport class RowTypesSettingsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"RowTypeService\", \"UiHelpers\", \"$timeout\", \"$element\"];\r\n\r\n  /**\r\n   * Set this property if you want to explicitly set the model (currently only Employment).\r\n   * If undefinded, the component binds to company settings.\r\n   */\r\n  public model?: Employment;\r\n\r\n  /**\r\n   * Defines the type of rows editor: \"builtIn\" for built-in rows,\r\n   * \"custom\" for custom rows, \"prices\" company specific default prices per row type.\r\n   */\r\n  public mode: \"builtIn\" | \"custom\" | \"prices\";\r\n\r\n  /** If set, filters the rows based on categories (plus rowTypes if set) */\r\n  public categories: CalculationRowCategory[];\r\n\r\n  /** Search text that is potentially input by the user. */\r\n  public searchText: string;\r\n\r\n  private listCache: {\r\n    /** Cache key */\r\n    key: string,\r\n    /** Cache value */\r\n    value: CalcRowConfig[],\r\n  } = null;\r\n\r\n  constructor(private rowTypeService: RowTypeService, private uiHelpers: UiHelpers, private $timeout: angular.ITimeoutService, private $element: JQLite) {\r\n  }\r\n\r\n  /** New empty row for databinding when creating a new row. */\r\n  public newRow: RowTypeDefinition;\r\n\r\n  /** Sets the default values in init. */\r\n  public $onInit() {\r\n    this.newRow = this.getBlank();\r\n  }\r\n\r\n  /** Saves the changes to row types. */\r\n  public save() {\r\n    this.rowTypeService.save();\r\n    this.listCache = null;\r\n  }\r\n\r\n  /**\r\n   * Gets the current object: Either the rows collection from settings as soon as it is loaded or an employment relation.\r\n   */\r\n  public get current(): RowTypeDefinition[] | Employment | undefined {\r\n    if (this.model) {\r\n      return this.model;\r\n    }\r\n    return this.rowTypeService.isReady ? this.rowTypeService.allCustomRows : undefined;\r\n  }\r\n\r\n  /**\r\n   * List of items to edit: In settings or Employment relation.\r\n   */\r\n  public get list(): RowTypeDefinition[] {\r\n    if ((this.current as Employment)?.work?.salaryDefaults) {\r\n      return (this.current as Employment).work.salaryDefaults as RowTypeDefinition[];\r\n    }\r\n    return this.rowTypeService.allCustomRows;\r\n  }\r\n\r\n  /**\r\n   * Gets the price rows in the current modeel.\r\n   */\r\n  public get pricesList(): RowTypeDefinition[] {\r\n    return this.list.filter(x => x.source === CalculationRowSource.PriceCompany || x.source == CalculationRowSource.PriceEmployment) as RowTypeDefinition[];\r\n  }\r\n\r\n  /**\r\n   * Gets the default rows from the current model\r\n   */\r\n  public get defaultsList(): RowTypeDefinition[] {\r\n    return this.list.filter(x => !x.source || x.source === CalculationRowSource.Undefined || x.source == CalculationRowSource.ManualRow) as RowTypeDefinition[];\r\n  }\r\n\r\n  /**\r\n   * Gets the list of company specific rows, always in settings even if the bound model is employment.\r\n   */\r\n  public get settingsList(): RowTypeDefinition[] {\r\n    if (!this.rowTypeService.isReady) {\r\n      console.error(\"Settings not yet loaded, handle this edge case.\");\r\n      return undefined;\r\n    }\r\n    return this.rowTypeService.allCustomRows;\r\n  }\r\n\r\n  /**\r\n   * Gets the configuration object for a row definition.\r\n   * @param row Row for which the configuration is fetched.\r\n   * @returns The configuration for the row.\r\n   */\r\n  public getConfig(row: RowTypeDefinition): CalcRowConfig {\r\n    return this.rowTypeService.getConfig(row);\r\n  }\r\n\r\n  /** Creating of a new item. */\r\n    public getBlank(): RowTypeDefinition {\r\n      const nextId = Math.max(...this.list.map(x => x.rowIndex), 0) + 1;\r\n      const newRow = UserDefinedRowLogic.getBlank(nextId) as RowTypeDefinition;\r\n      newRow.config = {} as any;\r\n      return newRow;\r\n    }\r\n\r\n  /**\r\n   * Gets the search as cached item: Can be bound to ng-repeat.\r\n   * @param searchText The search text. If null or empty, returns the full list.\r\n   */\r\n  public getCachedSearch(searchText: string): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"search\",\r\n      () => {\r\n        return this.search(searchText, (this.mode == \"builtIn\" || this.mode == \"custom\") ? this.mode : undefined);\r\n      },\r\n      () => this.listCache?.key + this.rowTypeService.timestamp + searchText + this.categories?.toString() + this.mode);\r\n  }\r\n\r\n  /**\r\n   * Searches the row types.\r\n   * @param searchText The search text. If null or empty, returns the full list.\r\n   */\r\n  public search(searchText: string, group: \"builtIn\" | \"custom\" | undefined): InputEnumOption[] {\r\n    const toOption = (config: CalcRowConfig) => {\r\n      return {\r\n        text: config.label,\r\n        value: config.name,\r\n        title: config.descr,\r\n        ui: {\r\n          color: config.color,\r\n          iconText: config.iconText,\r\n          addedByChild: null,\r\n          // TODO: Requires refactoring\r\n          group: config.group,\r\n          type: config.type,\r\n          rowType: config.rowType,\r\n        },\r\n      };\r\n    };\r\n    const result: InputEnumOption[] = [];\r\n    searchText = (searchText || \"\").trim().toLowerCase();\r\n    this.getRowTypes(group).forEach((rowConfig) => {\r\n      let isParentAdded = false;\r\n      if (\r\n        !searchText\r\n        || (rowConfig.label + rowConfig.descr + rowConfig.name).toLowerCase().indexOf(searchText) >= 0\r\n      ) {\r\n        result.push(toOption(rowConfig));\r\n        isParentAdded = true;\r\n      }\r\n      if (rowConfig.kind?.values) {\r\n        rowConfig.kind.values.forEach((kind) => {\r\n          if (\r\n            !(kind.name == \"undefined\" || kind.name == \"unknown\") &&\r\n            (searchText && (kind.label + kind.descr + kind.name).toLowerCase().indexOf(searchText) >= 0)\r\n          ) {\r\n            if (!isParentAdded) {\r\n              const option = toOption(rowConfig);\r\n              option.ui.addedByChild = true;\r\n              result.push(option);\r\n              isParentAdded = true;\r\n            }\r\n            result.push({\r\n              text: kind.label,\r\n              value: rowConfig.name + \".\" + kind.name,\r\n              title: kind.descr,\r\n              // TODO: Requires refactoring\r\n              ui: {\r\n                group: rowConfig.group,\r\n                type: rowConfig.type,\r\n                rowType: rowConfig.rowType,\r\n              }\r\n            });\r\n          }\r\n        });\r\n      }\r\n    });\r\n    if (result.length === 2 && result[0].ui.addedByChild) {\r\n      // If only one parent with one child (child is exact match) => Merge to one row.\r\n      return [{\r\n        text: result[0].text + \": \" + result[1].text,\r\n        value: result[1].value,\r\n        title: result[1].title,\r\n        ui: result[0].ui,\r\n      }];\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Opens an edit dialog for price or default row => Opening just a normal dialog.\r\n   * @param row Row to edit: This should be a price row or default row: Not a custom row.\r\n   */\r\n  public showEdit(row: RowTypeDefinition) {\r\n    if (!row) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    const isNew = false; // Add if necessary\r\n    const calc = CalculatorLogic.getBlank();\r\n    calc.usecase.data.standAloneRows = true;\r\n    calc.isReadOnly = false;\r\n\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/calc/rows/CalcRows2019EditDialog.html\", row, {\r\n      calc,\r\n    }, \"\", \"CalcRows2019Controller\").then((result) => {\r\n      if (result.action === \"ok-no-save\") {\r\n        if (isNew) {\r\n          this.list.push(result.item);\r\n        }\r\n      } else if (result.action === \"delete-no-save\") {\r\n        if (!isNew) {\r\n          this.delete(row);\r\n        }\r\n      } else {\r\n        // No changes, cancel\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes a row. This does not save changes.\r\n   * @param row Row to delete.\r\n   */\r\n  public delete(row: RowTypeDefinition) {\r\n    this.list.splice(this.list.indexOf(row), 1);\r\n  }\r\n\r\n  /** Copies the given text to clipboard. */\r\n  public copyToClipboard(text: string) {\r\n    navigator.clipboard.writeText(text);\r\n  }\r\n\r\n  /**\r\n   * Commits the new row in newRow property and adds it to the rows list.\r\n   * Updates usecase and sets the newRow as new blank row.\r\n   */\r\n  public commitNewRow(source: CalculationRowSource | \"price\", showEdit = false): RowTypeDefinition {\r\n    if (!this.newRow?.type) {\r\n      return null;\r\n    }\r\n    const row = this.getBlank();\r\n    if (source == \"price\") {\r\n      row.source = this.model?.work ? CalculationRowSource.PriceEmployment : CalculationRowSource.PriceCompany;\r\n    } else {\r\n      row.source = source;\r\n    }\r\n    if (this.newRow.config?.group === \"custom\") {\r\n      // Custom row type\r\n      row.type = this.newRow.type;\r\n      // HACK: Not sure if we should store the config here => Should probably fetch it on-the-fly when presenting the row.\r\n      row.config = this.getRowTypes(undefined).find(x => x.type === row.type);\r\n      if (!row.config) {\r\n        throw new Error(\"Row type not found in config: \" + row.type);\r\n      }\r\n      row.rowType = row.config.rowType;\r\n      const settingsRow = this.settingsList.find(x => x.type === row.type);\r\n      if (!settingsRow) {\r\n        throw new Error(\"Row type not found in settings: \" + row.type);\r\n      }\r\n      row.data.kind = settingsRow.data.kind;\r\n      row.price = settingsRow.price;\r\n    } else {\r\n      // Old logic\r\n      row.rowType = this.newRow.rowType;\r\n      row.data.kind = this.newRow.data.kind;\r\n      row.type = this.newRow.type;\r\n      row.config = {\r\n        group: \"builtIn\",\r\n      } as any;\r\n    }\r\n\r\n    RowsUsecaseLogic.getUsecaseLogicForCalc(row, CalculatorLogic.getBlank(), true);\r\n    this.list.push(row);\r\n    // TODO: Consider adding this => Does it make sense in prices / default rows?\r\n    // this.rowTypeChanged(row);\r\n    this.$timeout(() => {\r\n      // Reset new row type after timeout to avoid debounce\r\n      this.newRow = this.getBlank();\r\n    }, 300);\r\n    if (showEdit) {\r\n      this.showEdit(row); // TODO: What was the relevance of this: , \"auto\");\r\n    } else {\r\n      this.$timeout(() => {\r\n        let elem: HTMLElement = null;\r\n        elem = (this.$element[0] as HTMLElement).querySelector(\r\n          \"#iptPrice\" + row.rowIndex\r\n        );\r\n        if (elem) {\r\n          elem.focus();\r\n        }\r\n      }, 500);\r\n    }\r\n    return row;\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for editing the row-type or that shows information about the row-type if read-only.\r\n   * @param rowType The row type to show information about.\r\n   */\r\n  public showRowTypeDetails(rowType: InputEnumOption) {\r\n    let editableType: RowTypeDefinition = this.settingsList\r\n      .find(x => x.source == CalculationRowSource.CustomRowtype && (x as RowTypeDefinition).config.name == rowType.value) as RowTypeDefinition;\r\n    if (!editableType) {\r\n      // Not (an existing) custom row type => Show read-only dialog for a built-in type.\r\n      editableType = {\r\n        rowIndex: 0,\r\n        rowType: rowType.value as CalculationRowType,\r\n        source: CalculationRowSource.CustomRowtype,\r\n        data: {\r\n          dimensions: {},\r\n          accounting: {},\r\n        },\r\n        config: structuredClone(CalcRowsLogic.getRowConfig(rowType.value as CalculationRowType)),\r\n      };\r\n      editableType.config.group = \"builtIn\";\r\n    }\r\n    if (!editableType) {\r\n      throw new Error(\"Row type not found: \" + rowType.value);\r\n    }\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/calc/rows/RowTypeEditDialog.html\", editableType, {\r\n      calc: CalculatorLogic.getBlank(),\r\n      definitionEditor: this.getDialogLogic(editableType.config.group),\r\n    }, \"lg\", \"CalcRows2019Controller\",).then((_result) => {\r\n      if (_result.action == EditDialogKnownActions.Ok) {\r\n        this.rowTypeService.save();\r\n        this.listCache = null;\r\n      }\r\n    });\r\n  }\r\n\r\n  private getDialogLogic(mode: \"builtIn\" | \"custom\") {\r\n    return {\r\n      // Perhaps this is not really necessary => You could just get it from the config?\r\n      mode,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Creates a new custom row type.\r\n   * @param rowType Base row type for the custom type.\r\n   */\r\n  public async createCustomRowType(rowType: InputEnumOption): Promise<void> {\r\n    const name = prompt(\"Syötä rivityypille ID (a-z, 0-9, _):\");\r\n    if (!name) {\r\n      return;\r\n    }\r\n    if (name.match(/[^a-zA-Z0-9_]/)) {\r\n      alert(\"Virheellinen ID\");\r\n      return;\r\n    }\r\n    if (this.getRowTypes(undefined).find((x) => x.name === name)) {\r\n      alert(`ID on '${name}' jo käytössä`);\r\n      return;\r\n    }\r\n    const config = structuredClone(CalcRowsLogic.getRowConfig(rowType.value as CalculationRowType));\r\n    config.group = \"custom\";\r\n    config.name = name;\r\n    config.type = \"/custom/\" + name;\r\n    config.label = name + \" (uusi)\";\r\n\r\n    const editableType: RowTypeDefinition = {\r\n      type: \"/custom/\" + name,\r\n      rowType: rowType.value as CalculationRowType,\r\n      rowIndex: 0,\r\n      // HACK: Custom only if really custom\r\n      source: CalculationRowSource.CustomRowtype,\r\n      data: {\r\n        dimensions: {},\r\n        accounting: {},\r\n      },\r\n      config,\r\n    };\r\n    const _result = await this.uiHelpers.openEditDialog(\"salaxy-components/calc/rows/RowTypeEditDialog.html\", editableType, {\r\n      calc: CalculatorLogic.getBlank(),\r\n      definitionEditor: this.getDialogLogic(\"custom\"),\r\n    }, \"lg\", \"CalcRows2019Controller\");\r\n    if (_result.action == EditDialogKnownActions.Ok) {\r\n      this.rowTypeService.allCustomRows.push(editableType);\r\n      this.rowTypeService.save().then(() => {\r\n        // TODO: Best UI would be if the tab would be changed from built-in to custom here.\r\n      });\r\n      this.listCache = null;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Deletes a custom row type.\r\n   * @param rowType The row type to delete.\r\n   */\r\n  public deleteCustomRowType(rowType: InputEnumOption) {\r\n    if (!confirm(\"Haluatko poistaa rivityypin '\" + rowType.text + \"'?\")) {\r\n      return;\r\n    }\r\n    this.rowTypeService.deleteRow(this.settingsList.find(x => x.source == CalculationRowSource.CustomRowtype && (x as RowTypeDefinition).config.name == rowType.value));\r\n    this.rowTypeService.save();\r\n  }\r\n\r\n  /**\r\n   * Gets the list of row types. Method filters based on rowTypes and categories,\r\n   * the texts are language versioned.\r\n   */\r\n  private getRowTypes(group: \"builtIn\" | \"custom\" | undefined): CalcRowConfig[] {\r\n    if (!this.rowTypeService.isReady) {\r\n      console.error(\"Row types not yet loaded, handle this edge case.\");\r\n      return [];\r\n    }\r\n    const result = this.rowTypeService.getConfigs(group, this.categories);\r\n    return result;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  AccountingTargetSettings, AccountingTargetListItem, ApiItemType, Arrays, ExportMethod, InputEnumOption, InvoicesLogic,\r\n  OpenAPIV3, ServiceModel, ServiceModels, SitemapNode, Translations, TranslationsInstance, TranslationsDictionary,\r\n  Usecase, UsecaseListItem, ServiceModelListItem\r\n} from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { SitemapHelper } from \"../../helpers\";\r\n/**\r\n * UI logic for viewing and adding new (modifying) service models\r\n * Service models define service models\r\n */\r\nexport class ServiceModelCrudController extends ApiCrudObjectController<ServiceModel, ServiceModelListItem> {\r\n  isSaving: boolean;\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"ServiceModels\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\"\r\n  ];\r\n\r\n  constructor(\r\n    private fullApi: ServiceModels,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  $onInit() {\r\n    super.$onInit();\r\n    this.initLanguage();\r\n  }\r\n\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/service-models\",\r\n      detailsUrl: this.detailsUrl || \"/service-models/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/ServiceModels.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Event handler for accounting target selection.\r\n   * @param current Settings object to edit/create.\r\n   * @param logic Logic object passed to the dialog controller.\r\n   * @param logic.isReadOnly Read-only flag in logic.\r\n   * @param value Boolean indicating if the item is selected or not.\r\n   * @param item  The selected item.\r\n   * @param allItems All selected items.\r\n   */\r\n  public onAccountingTargetSelect(current: AccountingTargetSettings, logic: { isReadOnly: boolean }, value: boolean, item: AccountingTargetListItem, allItems: AccountingTargetListItem[]) {\r\n    allItems.splice(0, allItems.length);\r\n    logic.isReadOnly = true;\r\n    if (value == true) {\r\n      current.id = item.id;\r\n      current.avatar = item.otherPartyInfo.avatar;\r\n      current.format = item.data.format;\r\n      current.channel = item.data.channel;\r\n      current.method = item.data.method;\r\n      current.availableMethods = Arrays.assureArray(item.data.availableMethods) as ExportMethod[];\r\n      logic.isReadOnly = false;\r\n      allItems.push(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Event handler for usecase selection.\r\n   * @param current Settings object to edit/create.\r\n   * @param logic Logic object passed to the dialog controller.\r\n   * @param logic.isReadOnly Read-only flag in logic.\r\n   * @param value Boolean indicating if the item is selected or not.\r\n   * @param item  The selected item.\r\n   * @param allItems All selected items.\r\n   */\r\n  public onUsecaseSelect(current: Usecase, logic: { isReadOnly: boolean }, value: boolean, item: UsecaseListItem, allItems: UsecaseListItem[]) {\r\n    allItems.splice(0, allItems.length);\r\n    logic.isReadOnly = true;\r\n    if (value == true) {\r\n      current.uri = item.reference;\r\n      current.label = item.shortText;\r\n      current.itemType = item.entityType as ApiItemType;\r\n      current.status = item.status;\r\n      current.order = item.data.order;\r\n      logic.isReadOnly = false;\r\n      allItems.push(item);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return Avatar from current.payment.channels ENUM\r\n   * @returns Avatar\r\n   */\r\n  /* public getPaymentChannelAvatar(item) {\r\n    return InvoicesLogic.getChannelAvatar(item.channel);\r\n  } */\r\n\r\n  /**\r\n   * Created InputEnumOption [] from current.accounting.targets\r\n   * @returns InputEnumOption [] for template\r\n   */\r\n  public getSelectableAccountingTargets(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"selectableAccountingTargets\", () => {\r\n      return this.current.accounting.targets.map(item => ({\r\n        text: item.avatar.displayName,\r\n        value: item.id,\r\n        ui: { avatar: item.avatar }\r\n      }) as InputEnumOption);\r\n    }, () => this.current.accounting.targets.map(item => item.id)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Created InputEnumOption [] from all payment channels\r\n   * @returns InputEnumOption [] for template\r\n   */\r\n  public getSelectablePaymentChannels(): InputEnumOption[] {\r\n    if (this.current.payments.channels) {\r\n      return this.uiHelpers.cache(this, \"selectablePaymentChannels\", () => {\r\n        return this.current.payments.channels.map(item => {\r\n          const avatar = InvoicesLogic.getChannelAvatar(item.channel);\r\n          return {\r\n            text: avatar.displayName,\r\n            value: avatar.id,\r\n            ui: { avatar: avatar }\r\n          } as InputEnumOption;\r\n        });\r\n      }, () => this.current.payments.channels.map(item => InvoicesLogic.getChannelAvatar(item.channel).id)\r\n      );\r\n    }\r\n  }\r\n\r\n  /** Returns all payment channels. */\r\n  public getAllPaymentChannels(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"allSelectablePaymentChannels\", () => {\r\n      return InvoicesLogic.getAllChannels().map(item => {\r\n        return {\r\n          text: item.displayName,\r\n          value: item.id,\r\n          ui: { avatar: item }\r\n        } as InputEnumOption;\r\n      });\r\n    }, () => InvoicesLogic.getAllChannels().map(item => item.id)\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Save service model\r\n   */\r\n  public saveServiceModel() {\r\n    this.isSaving = true;\r\n    this.commitSitemapNode();\r\n    this.save().then(() => {\r\n      this.isSaving = false;\r\n    });\r\n  }\r\n\r\n  /**********************\r\n   * Sitemap functionality\r\n   **********************/\r\n\r\n  private _sitemap: SitemapNode[];\r\n\r\n  private _currentSitemapNode: SitemapNode;\r\n\r\n  /** Current instance of Translations. */\r\n  private translations: TranslationsInstance;\r\n\r\n  /** Clean dictionary for reloading the translations */\r\n  private cleanDictionary: TranslationsDictionary;\r\n\r\n  /** Gets the editable version of the sitemap */\r\n  public get sitemap(): SitemapNode[] {\r\n    if (!this._sitemap) {\r\n      this.translations.setTerms(this.current?.site?.texts);\r\n      this._sitemap = SitemapHelper.getEditableSitemap(this.current.site);\r\n      this.currentSitemapNode = this._sitemap[0];\r\n    }\r\n    return this._sitemap;\r\n  }\r\n\r\n  /** Resets all sitemap changes */\r\n  public resetSitemapChanges(): void {\r\n    this._sitemap = null;\r\n    this.current.site.texts = {};\r\n    this.current.site.sitemap = {};\r\n  }\r\n\r\n  /**\r\n   * Show / hide all nodes in the sitemap.\r\n   * @param open If true open / show all nodes. Default is close all nodes.\r\n   */\r\n  public showHideAll(open: boolean) {\r\n    this.sitemap.forEach((level1) => {\r\n      level1.$edit.$isOpen = open;\r\n      (level1.children || []).forEach((level2) => {\r\n        level2.$edit.$isOpen = open;\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Currently edited sitemap node */\r\n  public get currentSitemapNode(): SitemapNode {\r\n    return this._currentSitemapNode;\r\n  }\r\n  public set currentSitemapNode(value) {\r\n    this.commitSitemapNode();\r\n    this._currentSitemapNode = value;\r\n  }\r\n\r\n  /** Commits the changes of the current sitemap node to current service model (no save to server.)  */\r\n  public commitSitemapNode() {\r\n    const node = this._currentSitemapNode;\r\n    if (node) {\r\n      this.current.site.sitemap = this.current.site.sitemap || {};\r\n      const entries = Object.entries(node.$edit).filter(([key, value]) => value != null && value != \"\" && !(Array.isArray(value) && value.length == 0) && key[0] != \"$\" && !(key == \"visible\" || value == \"default\"));\r\n      if (entries.length) {\r\n        const objToStore = Object.fromEntries(entries);\r\n        if (objToStore.roles) {\r\n          // TODO: Add proper Array editor and remove this (also in getEditableSitemap()).\r\n          objToStore.roles = Arrays.assureArray(objToStore.roles as string).map((x) => x.trim());\r\n        }\r\n        this.current.site.sitemap[node.$edit.$id] = objToStore;\r\n      } else if (this.current.site.sitemap[node.$edit.$id]) {\r\n        delete this.current.site.sitemap[node.$edit.$id];\r\n      }\r\n      this.translations = new TranslationsInstance(angular.copy(this.cleanDictionary));\r\n      this.translations.setTerms(this.current?.site?.texts);\r\n      this._sitemap = SitemapHelper.getEditableSitemap(this.current.site, this._sitemap);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Resets all changes for the current sitemap node.\r\n   * @param resetCommitted If true, also resets the values that are committed to the\r\n   * original values from in the library\r\n   */\r\n  public resetSitemapNode(resetCommitted: boolean) {\r\n    const node = this.currentSitemapNode;\r\n    if (resetCommitted) {\r\n      if (this.current.site.sitemap[node.$edit.$id]) {\r\n        delete this.current.site.sitemap[node.$edit.$id];\r\n      }\r\n    }\r\n    this.translations = new TranslationsInstance(angular.copy(this.cleanDictionary));\r\n    this.translations.setTerms(this.current?.site?.texts);\r\n    this._sitemap = SitemapHelper.getEditableSitemap(this.current.site, this._sitemap);\r\n  }\r\n\r\n  /**\r\n   * Returns true, if the node has test role set.\r\n   * @param node Node to evaluate.\r\n   */\r\n  public getIsTest(node: SitemapNode): boolean {\r\n    const roles = node.$edit.roles?.length ? node.$edit.roles : node.roles;\r\n    return roles ? Arrays.assureArray(roles).indexOf(\"test\") >= 0 : false;\r\n  }\r\n\r\n\r\n  /**\r\n   * Gets all roles except \"test\" (which is displayed by getIsTest) as comma separated string.\r\n   * @param node Node to evaluate.\r\n   */\r\n  public getRoles(node: SitemapNode): string {\r\n    const roles = node.$edit.roles?.length ? node.$edit.roles : node.roles;\r\n    return roles ? Arrays.assureArray(roles).filter((x) => x != \"test\").join(\", \") : null;\r\n  }\r\n\r\n  /** Gets the params schema from the sitemap (service model). */\r\n  public getSitemapParamsSchema(): OpenAPIV3.Document {\r\n    return this.uiHelpers.cache(this, \"sitemapNodeParams\", () => {\r\n      const node = this.currentSitemapNode;\r\n      const result: OpenAPIV3.Document = {\r\n        openapi: \"3.0.1\",\r\n        info: {\r\n          title: \"SitemapParams_\" + node.id,\r\n          version: \"1.0\",\r\n          description: `Sitemap parameters for node ${node.$edit.$id}`,\r\n        },\r\n        paths: {},\r\n        components: {\r\n          schemas: {},\r\n        }\r\n      };\r\n      this.addNodeParamSchemas(this.sitemap, result.components.schemas);\r\n      return result;\r\n    }, () => this.currentSitemapNode?.$edit.$id);\r\n  }\r\n\r\n  /** Field to export / import the current object (shown in code editor). */\r\n  public json: string;\r\n\r\n  /** Exports the current object as json to property this.json. */\r\n  public exportJson() {\r\n    this.json = JSON.stringify(this.current, null, 2);\r\n  }\r\n\r\n  /** Sets current object from the JSON (this.json shown in code editor). */\r\n  public importJson() {\r\n    this._sitemap = null;\r\n    this._currentSitemapNode = null;\r\n    this.translations = new TranslationsInstance(angular.copy(this.cleanDictionary));\r\n    this.translations.setTerms(this.current?.site?.texts);\r\n    this.setCurrentValue(JSON.parse(this.json));\r\n  }\r\n\r\n  private addNodeParamSchemas(nodes: SitemapNode[], schemas: { [key: string]: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject }): void {\r\n    if (!nodes?.length) {\r\n      return;\r\n    }\r\n    nodes.forEach((node) => {\r\n      if (Object.keys(node.params || {}).length) {\r\n        const schema = angular.copy(this.defaultParamsSchema);\r\n        schema.properties = {...schema.properties, ...this.currentSitemapNode.params};\r\n        schemas[node.$edit.$id] = schema;\r\n      } else {\r\n        schemas[node.$edit.$id] = this.defaultParamsSchema;\r\n      }\r\n      this.addNodeParamSchemas(node.children, schemas);\r\n    });\r\n  }\r\n\r\n  private defaultParamsSchema: OpenAPIV3.SchemaObject = {\r\n    title: \"Current sitemap node\",\r\n    type: \"object\",\r\n    properties: {}\r\n  };\r\n\r\n  /**\r\n   * Translates the given key to current language with the translations in the current service model\r\n   * @param key The translation key\r\n   */\r\n  public translate(key: string): string {\r\n    return this.translations.get(key);\r\n  }\r\n\r\n  /** Initializes the Translations instance (loads the language and sets the current language). */\r\n  private initLanguage() {\r\n    const lang = Translations.getLanguage();\r\n    if (!this.translations) {\r\n      this.translations = new TranslationsInstance();\r\n      this.translations.localesPath = Translations.instance.localesPath; // Get the locales path from the current site (global instance)\r\n    }\r\n    this.translations.loadLanguage(lang)\r\n      .then(() => {\r\n        this.cleanDictionary = angular.copy(this.translations.getCurrentDictionary());\r\n        this.translations.setLanguage(lang);\r\n        this.translations.setTerms(this.current?.site?.texts);\r\n      });\r\n  }\r\n\r\n}","import angular from \"angular\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for code editing user interfaces: JSON Schema, JSON, JavaScript and HTML.\r\n */\r\nexport class SxyCodeEditorController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"$transclude\", \"$element\"];\r\n\r\n  /** Type of user interface to render: Monaco or basic HTML (textarea/pre) */\r\n  public mode: \"monaco\" | \"basic\";\r\n\r\n  /** If true, the component is read-only */\r\n  public readOnly: boolean;\r\n\r\n  /**\r\n   * Type of the main object that is called \"item\" in the code.\r\n   * Type should be one of @salaxy/core types (e.g. \"Calculation\") or supported\r\n   * native types (currently [\"any\", \"string\", \"[]\"]). Default is any.\r\n   */\r\n  public itemType: string;\r\n\r\n  /**\r\n   * Language of the code, e.g. \"javascript\" (default), \"html\", \"json\" or \"css\".\r\n   * Currently only affects the Monaco editor.\r\n   */\r\n  public lang: string;\r\n\r\n  /** The model that is bound to the input */\r\n  public model: angular.INgModelController;\r\n\r\n  /** The height of the editor as CSS, (e.g. \"calc(100vh - 600px)\"). Default is \"400px\" */\r\n  public height: string;\r\n\r\n  /**\r\n   * Raw value field, mainly used in direct AngularJS NgModel data binding and as internal storage.\r\n   * Typically, you should use get/set code for display and setting of the value.\r\n   */\r\n  public value: string;\r\n\r\n  /** iFrame URL for the Monaco editor. */\r\n  public monacoUrl: string;\r\n\r\n  /**\r\n   * IFrame element that hosts the Monaco view.\r\n   * Only set after the window has loaded and sent the initialization message (Monaco window is ready).\r\n   */\r\n  public monacoIFrame: HTMLIFrameElement;\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n\r\n    private $transclude: angular.ITranscludeFunction,\r\n\r\n    private $element: JQLite,\r\n  ) {\r\n\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.registerTransclude();\r\n    if (this.model) {\r\n      this.model.$render = () => {\r\n        this.value = this.model.$viewValue;\r\n        if (this.monacoIFrame) {\r\n          this.monacoIFrame.contentWindow.postMessage({ code: this.code }, this.monacoIFrame.contentWindow.origin);\r\n        }\r\n      };\r\n    }\r\n    this.registerMonacoWindow();\r\n  }\r\n\r\n  /** Clears the window event hooks */\r\n  public $onDestroy() {\r\n    window.removeEventListener(\"message\", this.onEditorMessage, false);\r\n  }\r\n\r\n  /** The code that is shown in editor. */\r\n  public get code(): string {\r\n    return this.value;\r\n  }\r\n  public set code(value: string) {\r\n    this.value = value;\r\n    if (this.model) {\r\n      this.model.$setViewValue(this.value);\r\n    }\r\n  }\r\n\r\n  /** On change of the value, do preventive operations and set value to model. */\r\n  protected onChange() {\r\n    if (this.model) {\r\n      this.model.$setViewValue(this.value);\r\n    }\r\n  }\r\n\r\n  private registerMonacoWindow() {\r\n    if (this.mode == \"basic\") {\r\n      return;\r\n    }\r\n    this.monacoUrl = `/monaco/index.html?readonly=${this.readOnly}&lang=${ this.lang || \"\"}`;\r\n    if (this.itemType) {\r\n      this.monacoUrl += \"&item=\" + this.itemType;\r\n    }\r\n    origin = window.origin; // Change origin according to monacoUrl if it is taken to another domain.\r\n    window.addEventListener(\"message\", this.onEditorMessage, false);\r\n  }\r\n\r\n  private onEditorMessage = (ev: MessageEvent<any>) => {\r\n    if (ev.origin !== origin) {\r\n      return;\r\n    }\r\n    if (this.monacoIFrame) {\r\n      if (this.monacoIFrame.contentWindow !== ev.source) {\r\n        return;\r\n      }\r\n      if (Object.prototype.hasOwnProperty.call(ev.data, \"code\")) {\r\n        this.code = ev.data.code;\r\n      }\r\n    }\r\n    else if (Object.prototype.hasOwnProperty.call(ev.data, \"loaded\")) {\r\n      // First message is for registration only.\r\n      const iFrame = this.monacoIFrame = (this.$element.find(\"iframe\")[0] as HTMLIFrameElement);\r\n      if (iFrame.contentWindow !== ev.source) {\r\n        return;\r\n      }\r\n      this.monacoIFrame = iFrame;\r\n      iFrame.contentWindow.postMessage({ code: this.code }, origin);\r\n      return;\r\n    }\r\n  };\r\n\r\n  private registerTransclude() {\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    this.$transclude((clonedElement, scope) => {\r\n      let content = \"\";\r\n      for (let i = 0; i < clonedElement.length; i++) {\r\n        if (clonedElement[i].nodeType === 3) {\r\n          content += (clonedElement[i] as unknown as Text).textContent;\r\n        } else {\r\n          content += (clonedElement[i].outerHTML || \"\").replace(\" ng-scope\", \"\").replace(\"ng-scope\", \"\").replace(\" class=\\\"\\\"\", \"\");\r\n        }\r\n      }\r\n      content = content.trim();\r\n      if (content) {\r\n        this.value = content;\r\n      }\r\n      return clonedElement;\r\n    });\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { OpenAPIV3 } from \"@salaxy/core\";\r\n\r\nimport { ApiValidation, ApiValidationError, ApiValidationErrorType, FormHelpers, InputMetadata, JsonInputType, JsonSchemaProperty, JsonSchemaUtils, Objects, Translations } from \"@salaxy/core\";\r\n\r\nimport { JsonSchemaService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Sxy form contains the definition for an editor used interface that\r\n * typically corresponds to an HTML form.\r\n */\r\nexport class SxyFormController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"JsonSchemaService\", \"$rootScope\", \"UiHelpers\", \"$timeout\"];\r\n\r\n  /** The model that is being edited. */\r\n  public model: any;\r\n\r\n  /** The schema model */\r\n  public schemaModel: OpenAPIV3.SchemaObject;\r\n\r\n  /**\r\n   * The translation code for the label / title.\r\n   * Default is \"SALAXY.MODEL.[type].title\"] or if not available, just the type text.\r\n   */\r\n  public label: string;\r\n\r\n  /**\r\n   * Sets the entire form as read-only. The value is true/1.\r\n   * Default value false/0, has no real effect: The behavior comes from either input or schema.\r\n   * Individual field may still be set read-only=false/1 to make it editable.\r\n   */\r\n  public readOnly: string;\r\n\r\n  /** If true, the schema loading is ready: The form can be rendered. */\r\n  public isReady: boolean;\r\n\r\n  /**\r\n   * URL for the Open API document that contains the definition for the type.\r\n   * The url can be an absolute url, relative url or an url with salaxy-secure/ -prefix.\r\n   * The salaxy-secure/ -prefix will be replaced in runtime with the salaxy api server url of the curren environment.\r\n   */\r\n  public openApi: string;\r\n\r\n  /** References a schema document directly: the schema document is not fetched from the UI */\r\n  public openApiDoc: any;\r\n\r\n  /** If true, shows the debugger view for the form. */\r\n  public debugger: boolean;\r\n\r\n  /** Unique id for the form. Init assures that this is unique in the AngularJs root scope. */\r\n  public id: string;\r\n\r\n  /** The angular form with validation etc. */\r\n  public ngForm: angular.IFormController;\r\n\r\n  /** If true, the inner for is auto-generated. */\r\n  public autoGen: boolean;\r\n\r\n  private lastUniqueId = 0;\r\n\r\n  private _info: OpenAPIV3.InfoObject;\r\n\r\n  public _type: string;\r\n\r\n  constructor(\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private $rootScope: angular.IRootScopeService,\r\n    private uiHelpers: UiHelpers,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.init();\r\n  }\r\n\r\n  /**\r\n   * Type of the model: Bases for the user interface.\r\n   * This may be either a TypeScript typename or OpenApi schema component name.\r\n   */\r\n  public get type(): string {\r\n    return this._type;\r\n  }\r\n  public set type(value: string) {\r\n    this._type = value;\r\n    if (this.id) {\r\n      // Init has been done => redo and refresh\r\n      this.isReady = false;\r\n      this.$timeout().then(() => {\r\n        this.init();\r\n      });\r\n    }\r\n  }\r\n\r\n  /** Initializes or re-initializes the data model. */\r\n  public init() {\r\n    this.model = this.model || {};\r\n    this.id = (this.type || \"undefined\") + this.$rootScope.$id.toString();\r\n    if (this.openApi && this.type) {\r\n      if (this.openApiDoc) {\r\n        // TODO: Assure that the schema is cached in final implementation\r\n        this.jsonSchemaService.addSchemaDocument(this.openApi, this.openApiDoc);\r\n        this.schemaModel = this.jsonSchemaService.findSchema(this.openApi, this.type);\r\n        if (!this.model) {\r\n          this.model = {};\r\n        }\r\n        this._info = this.openApiDoc.info || {\r\n          title: \"unknown\",\r\n          version: \"0\",\r\n        };\r\n        this.label = this.label || Translations.getWithDefault(`${this.getModelNamespace()}.${this.type}.title`, this.schemaModel?.title || this.type);\r\n        this.isReady = true;\r\n      } else {\r\n        this.jsonSchemaService.assureSchemaDocument(this.openApi).then((openApiDoc) => {\r\n          this._info = openApiDoc.info || {\r\n            title: \"unknown\",\r\n            version: \"0\",\r\n          };\r\n          this.schemaModel = this.jsonSchemaService.findSchema(this.openApi, this.type);\r\n          if (!this.model) {\r\n            this.model = {};\r\n          }\r\n          this.label = this.label || Translations.getWithDefault(`${this.getModelNamespace()}.${this.type}.title`, this.schemaModel?.title || this.type);\r\n          this.isReady = true;\r\n        });\r\n      }\r\n    } else {\r\n      this.schemaModel = null;\r\n      this.isReady = true;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Registers an input (control) to a data point in the form.\r\n   * @param path Data path that the input registers to.\r\n   * This should be either \"form\" to register to the root of the form or\r\n   * more typically \"form.prop.perhapsSubProperty\" to register to a property.\r\n   */\r\n  public registerInput(path: string, type?: JsonInputType, format?: string): {\r\n    /** Description of the property or if path is \"form\" the data model of the form. */\r\n    prop: JsonSchemaProperty,\r\n    /** True, if the element is the form root. Otherwise this is a property.  */\r\n    isRoot: boolean,\r\n    /** Unique ID within the form */\r\n    id: string,\r\n    /** AngularJS template for rendering the input. */\r\n    templateUrl: string,\r\n    /** Metadata that can be used for rendering the input */\r\n    input: InputMetadata,\r\n  } {\r\n    if (!(path || \"\").trim()) {\r\n      throw Error(\"Path / model is required for each sxy-input element. Use e.g. 'form.temp'.\");\r\n    }\r\n    const result = {\r\n      prop: this.getProperty(path),\r\n      id: null,\r\n      isRoot: false,\r\n      templateUrl: null,\r\n      input: null,\r\n    };\r\n    if (!result.prop) {\r\n      // This is not a property\r\n      result.isRoot = path === \"form\";\r\n      if (result.isRoot) {\r\n        // \"form\": bound to root\r\n        result.id = `${this.id}_form${this.getUniqueId()}`;\r\n        result.input = this.schemaModel ? FormHelpers.getInputForSelf(this.schemaModel, null, path) : null;\r\n        if (result.input) {\r\n          result.input.format = format || result.input.format;\r\n        }\r\n        result.prop = {\r\n          isRequired: false,\r\n          parentName: this.type,\r\n          propertyName: null,\r\n          schema: this.schemaModel,\r\n        };\r\n        result.templateUrl = result.input ? this.jsonSchemaService.getTemplate(result.input) : null;\r\n      } else {\r\n        // Property path is there, but it is not found in the schema (perhaps a new or unofficial property)\r\n        const propertyName = path.substr(path.lastIndexOf(\".\") + 1);\r\n        result.id = `${this.id}_${propertyName}${this.getUniqueId()}`;\r\n        type = type || \"string\";\r\n        result.input = {\r\n          name: propertyName,\r\n          format,\r\n          isEnum: null,\r\n          path,\r\n          type,\r\n          content: `Property \"${path}\" does not exist in schema.`,\r\n        };\r\n        result.prop = {\r\n          isRequired: false,\r\n          parentName: null,\r\n          propertyName,\r\n          schema: null,\r\n        };\r\n        result.templateUrl = this.jsonSchemaService.getTemplate(result.input);\r\n      }\r\n    } else {\r\n      result.id = `${this.id}_${result.prop.propertyName}${this.getUniqueId()}`;\r\n      result.input = FormHelpers.getInputMetadata(result.prop.schema, result.prop.propertyName, path);\r\n      result.input.format = format || result.input.format;\r\n      result.templateUrl = this.jsonSchemaService.getTemplate(result.input);\r\n    }\r\n    this.registeredInputs[result.id] = result.prop;\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Gets the model for a property that an invidual input within the form can bind to.\r\n   * @param path Property path, currently always starting with \"form.\",\r\n   * e.g. \"form.id\" or \"form.employer.accountId\"\r\n   */\r\n  public getProperty(path: string): JsonSchemaProperty {\r\n    const propPath = this.getFormPath(path);\r\n    if (!propPath) {\r\n      return null; // Path is \"form\" - this is not a property.\r\n    }\r\n    return JsonSchemaUtils.getProperty(this.schemaModel, propPath);\r\n  }\r\n\r\n  /**\r\n   * Sets a value in the model using property path.\r\n   * @param path Property path, currently always starting with \"form.\",\r\n   * e.g. \"form.id\" or \"form.owner.id\"\r\n   * @param value Value to set to model.\r\n   * @returns True if the property is set. Value is not set if there is no propertyPath/obj or\r\n   * if the value is already set to new value (currently strict equality check \"===\",\r\n   * but may be changed without it being a breaking change).\r\n   */\r\n  public setValue(path: string, value: any): boolean {\r\n    const propPath = this.getFormPath(path);\r\n    if (!propPath) {\r\n      throw new Error(\"Cannot set the objects own value. setValue only supports setting property values.\");\r\n    }\r\n    return Objects.setProperty(this.model, propPath, value);\r\n  }\r\n\r\n  /**\r\n   * Gets a value from the model using property path.\r\n   * @param path Property path, currently always starting with \"form.\",\r\n   * e.g. \"form.id\" or \"form.owner.id\"\r\n   */\r\n  public getValue(path: string): any {\r\n    const propPath = this.getFormPath(path);\r\n    if (!propPath) {\r\n      return this.model;\r\n    }\r\n    return Objects.getProperty(this.model, this.getFormPath(path));\r\n  }\r\n\r\n  /** Gets the validation based on the current form. */\r\n  public getValidation(): ApiValidation {\r\n    const rawErrors: string[][] = [];\r\n    if (this.ngForm.$invalid) {\r\n      for (const key of Object.keys(this.ngForm.$error)) {\r\n        for (let index = 0; index < this.ngForm.$error[key].length; index++) {\r\n          rawErrors.push([key, this.ngForm.$error[key][index].$name]);\r\n        }\r\n      }\r\n    }\r\n    return this.uiHelpers.cache(this, \"validation\", () => {\r\n      const errors = rawErrors.map((raw) => {\r\n        const key = raw[0];\r\n        const prop = this.registeredInputs[raw[1]];\r\n        const error: ApiValidationError = {\r\n          code: key,\r\n          key: raw[1],\r\n          type: raw[0] === \"required\" ? ApiValidationErrorType.Required : ApiValidationErrorType.Invalid,\r\n          msg: Translations.getWithDefault(\"SALAXY.VALIDATION.ValidationErrors.\" + key,\r\n            Translations.get(\"SALAXY.VALIDATION.ValidationErrors.unknown\", { error: key })),\r\n        };\r\n        if (prop?.propertyName) {\r\n          if (prop.parentName) {\r\n            // TODO: Better form path from a combination of prop/input\r\n            error.key = prop.parentName + \".\" + prop.propertyName;\r\n          } else {\r\n            error.key = prop.propertyName;\r\n          }\r\n          error.msg = Translations.getWithDefault(`${this.getModelNamespace()}.${error.key}.title`, prop.propertyName) + \": \" + error.msg;\r\n        }\r\n        return error;\r\n      });\r\n      return {\r\n        hasAllRequiredFields: !errors.find((x) => x.type === ApiValidationErrorType.Required),\r\n        isValid: errors.length === 0,\r\n        errors,\r\n      };\r\n    }, () => rawErrors);\r\n  }\r\n\r\n  /** Returns the namespace for the current openApi model, the default is SALAXY.MODEL */\r\n  public getModelNamespace(): string {\r\n    return this._info?.[\"x-salaxy-model-namespace\"] || \"SALAXY.MODEL\";\r\n  }\r\n\r\n  /** Returns the namespace for the current openApi enums, the default is SALAXY.ENUM */\r\n  public getEnumNamespace(): string {\r\n    return this._info?.[\"x-salaxy-enum-namespace\"] || \"SALAXY.ENUM\";\r\n  }\r\n\r\n  protected registeredInputs: {\r\n    [key: string]: JsonSchemaProperty;\r\n  } = {};\r\n\r\n  private getFormPath(path: string): string {\r\n    if (path === \"form\") {\r\n      return null;\r\n    }\r\n    if (!path.startsWith(\"form.\")) {\r\n      throw new Error(\"Currently, only 'form' and 'form.' supported in property paths.\");\r\n    }\r\n    return path.replace(\"form.\", \"\");\r\n  }\r\n\r\n  /** Gets a unique id to form components / inputs. This may later further track the inputs. */\r\n  private getUniqueId(): number {\r\n    return this.lastUniqueId++;\r\n  }\r\n}\r\n","\r\n/**\r\n * Controller for misc form elements that are not inputs:\r\n * These are not bound to models, but handle misc. form layout and grouping tasks.\r\n */\r\nexport class SxyFormElementController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [];\r\n\r\n  /**\r\n   * Typing depending on the component.\r\n   *\r\n   * - sxy-alert: \"default\" | \"primary\" | \"success\" | \"info\" | \"warning\" | \"danger\"\r\n   */\r\n  public type: \"default\" | \"primary\" | \"success\" | \"info\" | \"warning\" | \"danger\" | string;\r\n\r\n  /**\r\n   * For sxy-fieldset, defines the model that the fieldset should generate fields for.\r\n   * Should be \"form\" to refer to the current form or property path starting\r\n   * with \"form\", e.g. \"form.result.employerCalc\"\r\n   */\r\n  public model: string;\r\n\r\n  /**\r\n   * For alerts, possibility to speicfy a font-awesome icon.\r\n   * Setting \"none\", will show no icon.\r\n   * If not set, it is determined by type.\r\n   */\r\n  public icon: \"none\" | string;\r\n\r\n  constructor() {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    // init\r\n  }\r\n\r\n  /** For alert component, gets the classes that format the alert. */\r\n  public getAlertClasses() {\r\n    switch (this.type) {\r\n      case \"default\":\r\n      case \"primary\":\r\n      case \"success\":\r\n      case \"info\":\r\n      case \"warning\":\r\n      case \"danger\":\r\n        return `alert alert-${this.type}`;\r\n      case \"error\":\r\n        return `alert alert-danger`;\r\n      default:\r\n        return `alert alert-info`;\r\n    }\r\n  }\r\n\r\n  /** Returns the icon based on the type. */\r\n  public getAlertIcon() {\r\n    if (!this.icon) {\r\n      switch (this.type) {\r\n        case \"danger\":\r\n        case \"error\":\r\n          return \"fa-exclamation\";\r\n        case \"success\":\r\n          return \"fa-check\";\r\n        case \"warning\":\r\n          return \"fa-exclamation-triangle\";\r\n        default:\r\n          return \"fa-info\";\r\n      }\r\n    }\r\n    if (this.icon === \"none\") {\r\n      return null;\r\n    }\r\n    return this.icon;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiValidation, ApiValidationErrorType, Arrays, CellRenderingLogic, Configs, DataMapper, DataMappersLogic, EnumerationsLogic, Exportable, FileParser,\r\n  Importable, InputEnumOption, JsonSchemaUtils, OpenAPIV3\r\n} from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, JsonSchemaService, FileService } from \"../../services\";\r\n\r\n/** Provides Grid UI for viewing and editing arrays. */\r\nexport class SxyGridController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"JsonSchemaService\", \"UiHelpers\", \"$element\", \"$timeout\", \"FileService\"];\r\n\r\n  /** Default bindings to the components */\r\n  public static bindings = {\r\n\r\n    /**\r\n     * The schema definition that defines the structure of the grid.\r\n     */\r\n    schemaDef: \"<\",\r\n\r\n    /**\r\n     * URL of the schema document that contains the schemaDef.\r\n     * If set with schema in init, loads the document.\r\n     */\r\n    doc: \"@\",\r\n\r\n    /**\r\n     * Key of schemaDef in doc.\r\n     * If set with doc in init, will load the schema document from server and set the schemaDef.\r\n     */\r\n    schema: \"@\",\r\n\r\n    /** Data that is rendered / edited in the grid. */\r\n    data: \"<\",\r\n\r\n    /**\r\n     * List of columns to include in the grid. Raw field names - may be a property tree.\r\n     */\r\n    include: \"<\",\r\n\r\n    /**\r\n     * List of columns to exclude from the grid.\r\n     * This property is currenlty used only if include property is undefined, i.e. in default\r\n     * rendering, which will render the first-level properties. As such, exclude does not really support property paths.\r\n     */\r\n    exclude: \"<\",\r\n\r\n  };\r\n\r\n  /**\r\n   * URL of the schema document that contains the schemaDef.\r\n   * If set with schema in init, loads the document.\r\n   */\r\n  public doc: string;\r\n\r\n  /**\r\n   * Key of schemaDef in doc.\r\n   * If set with doc in init (and schemaDef not set),\r\n   * will load the schema document from server and set the schemaDef.\r\n   */\r\n  public schema: string;\r\n\r\n  /** Data that is rendered / edited in the grid. */\r\n  public data: any[];\r\n\r\n  /**\r\n   * List of columns to include in the grid. Raw field names - may be a property tree.\r\n   */\r\n  public include: string | string[];\r\n\r\n  /**\r\n   * List of columns to exclude from the grid.\r\n   * This property is currenlty used only if include property is undefined, i.e. in default\r\n   * rendering, which will render the first-level properties. As such, exclude does not really support property paths.\r\n   */\r\n  public exclude: string | string[];\r\n\r\n  /** Array of items that is selected in the grid. These are grid nodes, not data items. */\r\n  public selection: any[] = [];\r\n\r\n  /**\r\n   * The grid options\r\n   * TODO: Consider adding at least some typing.\r\n   */\r\n  private gridOptions: any;\r\n\r\n  private isInitDone = false;\r\n\r\n  _schemaDef: OpenAPIV3.NonArraySchemaObject;\r\n\r\n  constructor(\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private uiHelpers: UiHelpers,\r\n    private $element: JQLite,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private fileService: FileService,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.initModel();\r\n  }\r\n\r\n  /**\r\n   * The schema definition that defines the structure of each item in the grid.\r\n   */\r\n  public get schemaDef(): OpenAPIV3.NonArraySchemaObject {\r\n    return this._schemaDef;\r\n  }\r\n  public set schemaDef(value: OpenAPIV3.NonArraySchemaObject) {\r\n    this._schemaDef = value;\r\n    if (this.isInitDone) {\r\n      this.renderGrid();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Adds an empty row to the grid.\r\n   * @param rowData Data to add to the grid. Array of of objects.\r\n   * @param index Index position. If null, will add to the end.\r\n   */\r\n  public addRow(rowData: any[] = [{}], index = null): void {\r\n    this.gridOptions.api.applyTransaction({\r\n      add: rowData,\r\n      addIndex: index,\r\n    });\r\n    this.commit();\r\n  }\r\n\r\n  /** Delete the selected rows from the grid. */\r\n  public deleteSelectedRows(): void {\r\n    const selectedRows = this.gridOptions.api.getSelectedRows();\r\n    this.gridOptions.api.applyTransaction({ remove: selectedRows });\r\n    this.commit();\r\n  }\r\n\r\n  /** Clears all rows in the grid. Sets the data to an empty array. */\r\n  public clear(): void {\r\n    this.gridOptions.api.setRowData([]);\r\n    this.commit();\r\n  }\r\n\r\n  /** Commits the changes in the grid to the source data. */\r\n  public commit(): void {\r\n    this.data.length = 0;\r\n    this.gridOptions.api.forEachNode((node) => {\r\n      this.data.push(node.data);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Validates a single item based on the schema.\r\n   * @param item Item to validate\r\n   */\r\n  public validateItem(item: any): ApiValidation {\r\n    // TODO: Move to core JsonSchema helpers.\r\n    if (!item) {\r\n      return {\r\n        isValid: false,\r\n        hasAllRequiredFields: false,\r\n        errors: [{\r\n          msg: \"Row is empty / null, this is not allowed: Null rows must be filtered out before adding.\",\r\n          type: ApiValidationErrorType.General,\r\n        }],\r\n      };\r\n    }\r\n    const result: ApiValidation = {\r\n      errors: [],\r\n    };\r\n\r\n    Object.keys(item).forEach((key) => {\r\n      const val = item[key];\r\n      const prop = (this.schemaDef || {}).properties[key] as OpenAPIV3.SchemaObject;\r\n      if (prop) {\r\n        // Empty values are OK at least for now, required items may be added later to validation\r\n        if (val) {\r\n          switch (prop.type) {\r\n            case \"integer\":\r\n              if (!Number.isInteger(+val)) {\r\n                result.errors.push({\r\n                  msg: `Value '${val}' in ${key} is not an integer.`,\r\n                  type: ApiValidationErrorType.Invalid,\r\n                  key\r\n                });\r\n              }\r\n              break;\r\n            case \"number\":\r\n              if (isNaN(val)) {\r\n                result.errors.push({\r\n                  msg: `Value '${val}' in ${key} is not a number.`,\r\n                  type: ApiValidationErrorType.Invalid,\r\n                  key\r\n                });\r\n              }\r\n              break;\r\n            case \"boolean\":\r\n              // TODO: Perhaps add 0/1 and kyllä/ei\r\n              if ([\"true\", \"false\"].indexOf((val + \"\").toLowerCase()) < 0) {\r\n                result.errors.push({\r\n                  msg: `Value '${val}' in ${key} is not a valid boolean (true/false).`,\r\n                  type: ApiValidationErrorType.Invalid,\r\n                  key\r\n                });\r\n              }\r\n              break;\r\n            case \"array\":\r\n              if (!Array.isArray(val)) {\r\n                result.errors.push({\r\n                  msg: `Value '${val}' in ${key} is not a valid array.`,\r\n                  type: ApiValidationErrorType.Invalid,\r\n                  key\r\n                });\r\n              }\r\n              break;\r\n          }\r\n        }\r\n      } else {\r\n        result.errors.push({\r\n          msg: `Property ${key} is not defined in the schema.`,\r\n          type: ApiValidationErrorType.Warning,\r\n        });\r\n      }\r\n    });\r\n    (result as any).hasAllRequiredFields = !result.errors.find((x) => x.type == ApiValidationErrorType.Required);\r\n    (result as any).isValid = !result.errors.find((x) => x.type !== ApiValidationErrorType.Warning);\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Takes an input object with string based data and maps to correct typing or empty objects.\r\n   * E.g. \"2\" => 2, \"True\" = true. Original data is not changed and only data in schema is returned.\r\n   * Keep the method in sync with validateItem.\r\n   * @param item Item to convert as typed item.\r\n   * @returns Typed item\r\n   */\r\n  public convertTypes(item: any): any {\r\n    // TODO: Move to core JsonSchema helpers.\r\n    if (!item) {\r\n      return null;\r\n    }\r\n    const result = {};\r\n    Object.keys(item).forEach((key) => {\r\n      const val = item[key];\r\n      const prop = (this.schemaDef || {}).properties[key] as OpenAPIV3.SchemaObject;\r\n      if (prop) {\r\n        // Empty values are OK at least for now, required items may be added later to validation\r\n        if (val) {\r\n          switch (prop.type) {\r\n            case \"integer\":\r\n              if (Number.isInteger(+val)) {\r\n                result[key] = Number(val);\r\n              }\r\n              break;\r\n            case \"number\":\r\n              if (!isNaN(val)) {\r\n                result[key] = Number(val);\r\n              }\r\n              break;\r\n            case \"boolean\":\r\n              if ([\"true\", \"false\"].indexOf((val + \"\").toLowerCase()) >= 0) {\r\n                // TODO: Perhaps add 0/1 and kyllä/ei\r\n                result[key] = (val + \"\").toLowerCase() == \"true\";\r\n              }\r\n              break;\r\n            case \"array\":\r\n              if (!Array.isArray(val)) {\r\n                // TODO: Consider adding validation to sub-items. This would probably need to be recursive.\r\n                result[key] = val;\r\n              }\r\n              break;\r\n            case \"string\":\r\n              result[key] = val;\r\n              break;\r\n          }\r\n        }\r\n      }\r\n    });\r\n    return result;\r\n  }\r\n\r\n  /** Gets the exportable for the current data model. */\r\n  public getExportable(): Exportable<any> {\r\n\r\n    const fullMapper = this.getMapper().reverse(this.schema + \"FullExport\", `Full object export for ${this.schema}`);\r\n\r\n    const exptMapper = new DataMapper<{ [key: string]: string }, any>(this.schema + \"GridExport\", `Table export for ${this.schema}`);\r\n    exptMapper.setSchema(this.schemaDef, this.schema, \"source\");\r\n    exptMapper.setPathsFromSourceSchema(this.getFields());\r\n\r\n    const mappers = [exptMapper, fullMapper];\r\n\r\n    const result: Exportable<any> = {\r\n      exporters: this.fileService.getDefaultExporters(),\r\n      getExportMappers: () => {\r\n        return mappers.map((x) => DataMappersLogic.getInfo(x));\r\n      },\r\n      getExportMapper: (id: string) => {\r\n        return Promise.resolve(mappers.find((x) => x.uri == id));\r\n      },\r\n      list: (maxCount) => {\r\n        const result = maxCount > 0 ? this.data.slice(0, maxCount) : this.data;\r\n        return Promise.resolve(result);\r\n      },\r\n      getSingle: (item) => {\r\n        return Promise.resolve(item);\r\n      },\r\n    };\r\n\r\n    return result;\r\n\r\n  }\r\n\r\n  /** Gets the importable for the current data model. */\r\n  public getImportable(): Importable<any> {\r\n    const mapper = this.getMapper();\r\n    return {\r\n      getImportMappers: () => {\r\n        const result: InputEnumOption = {\r\n          value: null,\r\n          text: mapper.title,\r\n        };\r\n        return [result];\r\n      },\r\n      getImportMapper() {\r\n        return Promise.resolve(mapper);\r\n      },\r\n      finalize: (items) => {\r\n        this.clear();\r\n        this.addRow(items.map((value) => this.convertTypes(value)));\r\n        this.commit();\r\n        return Promise.resolve();\r\n      },\r\n      validate: (itemToValidate: any): Promise<{ item: any, validation: ApiValidation }> => {\r\n        return Promise.resolve({ item: itemToValidate, validation: this.validateItem(itemToValidate) });\r\n      },\r\n      parsers: FileParser.getDefaultParsers(),\r\n    };\r\n  }\r\n\r\n  /** Available object mapper for import based on the current schema. */\r\n  private getMapper(): DataMapper<{ [key: string]: string }, any> {\r\n    const result = new DataMapper<{ [key: string]: string }, any>(this.schema + \"Import_sxyGrid\", `Table import for ${this.schema}`);\r\n    result.setStringToSchemaMapping(this.schemaDef, this.schema);\r\n    return result;\r\n  }\r\n\r\n  private initModel() {\r\n    this.doc = this.doc || \"salaxy-secure/schemas/v02.json\";\r\n    if (!this.schemaDef && this.doc && this.schema) {\r\n      this.jsonSchemaService.assureSchemaDocument(this.doc).then((schemaDoc) => {\r\n        this.isInitDone = true;\r\n        this.schemaDef = schemaDoc.components.schemas[this.schema] as OpenAPIV3.NonArraySchemaObject;\r\n      });\r\n    } else if (this.schemaDef) {\r\n      this.renderGrid();\r\n    }\r\n  }\r\n\r\n  /** Gets the fields based on include OR exclude and schema defs definitions. */\r\n  private getFields(): string[] {\r\n    let fields = Arrays.assureArray(this.include);\r\n    if (fields.length == 0) {\r\n      fields = Object.keys(this.schemaDef?.properties || {});\r\n      const excludeArr = Arrays.assureArray(this.exclude);\r\n      if (excludeArr.length > 0) {\r\n        fields = fields.filter((x) => excludeArr.indexOf(x) < 0);\r\n      }\r\n    }\r\n    return fields;\r\n  }\r\n\r\n  private renderGrid() {\r\n    this.gridOptions = {\r\n      defaultColDef: {\r\n        editable: true\r\n      },\r\n      rowSelection: \"multiple\",\r\n      undoRedoCellEditing: true,\r\n      undoRedoCellEditingLimit: 20,\r\n      onSelectionChanged: (event: {\r\n        /** Grid API */\r\n        api: any;\r\n        /** Column API */\r\n        columnApi: any;\r\n        /** Event identifier */\r\n        type: string;\r\n      }) => {\r\n        this.selection = event.api.getSelectedNodes();\r\n        this.$timeout(0);\r\n      },\r\n    };\r\n    const columnDefs = [];\r\n    this.getFields().forEach((key) => {\r\n      const schema = JsonSchemaUtils.getProperty(this.schemaDef, key)?.schema;\r\n      if (schema) {\r\n        let headerName = schema.title;\r\n        if (!headerName) {\r\n          headerName = key.indexOf(\".\") ? key.substring(key.lastIndexOf(\".\") + 1) : key;\r\n        }\r\n        const colDef = {\r\n          field: key,\r\n          headerName,\r\n        } as any;\r\n        switch (schema.type) {\r\n          case \"integer\":\r\n          case \"number\":\r\n            colDef.type = [\"numericColumn\"];\r\n            break;\r\n          case \"object\":\r\n            colDef.cellRenderer = CellRenderingLogic.getCellRenderer(schema);\r\n            break;\r\n        }\r\n        if (schema.description) {\r\n          colDef.headerTooltip = schema.description;\r\n        }\r\n        if (schema.enum?.length) {\r\n          const enumValues = EnumerationsLogic.getEnumMetadata(schema.format).values;\r\n          colDef.cellEditor = \"agSelectCellEditor\";\r\n          colDef.cellEditorParams = {\r\n            values: enumValues.map((x) => x.name),\r\n          };\r\n          colDef.refData = enumValues.reduce((a, v) => ({ ...a, [v.name]: v.label }), {});\r\n        }\r\n        columnDefs.push(colDef);\r\n      } else {\r\n        console.error(`Cannot find column ${key}`);\r\n      }\r\n    });\r\n    const getSalaxyGridModule = (): Promise<any> => {\r\n      // Support both esm and umd builds...\r\n      return Promise.resolve(Configs.global.salaxy.grid);\r\n    };\r\n\r\n    getSalaxyGridModule().then((salaxyGridModule) => {\r\n      const gridWrapper = salaxyGridModule.GridWrapper;\r\n      const agGrid = gridWrapper.agGrid;\r\n      agGrid.LicenseManager.setLicenseKey(gridWrapper.AG_GRID_LICENCE_KEY);\r\n      if (!agGrid.ModuleRegistry.getRegisteredModules().length) {\r\n        agGrid.ModuleRegistry.registerModules(agGrid.AllModules);\r\n      }\r\n\r\n      const eGridDiv = this.$element[0].querySelector(\"#dataGrid\");\r\n      new agGrid.Grid(eGridDiv, this.gridOptions);\r\n    });\r\n\r\n    // create the grid passing in the div to use together with the columns & data we want to use\r\n    this.$timeout(() => {\r\n      this.gridOptions.api.setRowData(this.data);\r\n      this.gridOptions.api.setColumnDefs(columnDefs);\r\n    });\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { Arrays, DataMapper, DataMappersLogic, EnumerationsLogic, Exportable, FormHelpers, InputEnumOption, InputMetadata, JsonInputType, JsonSchemaUtils, OpenAPIV3, Translations  } from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, EditDialogResult, FileService, UiHelpers } from \"../../services\";\r\nimport { SxyFormController } from \"./SxyFormController\";\r\n\r\n/** Handles user interface logic for different form inputs components (including select etc.) */\r\nexport class SxyInputController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"$transclude\", \"$element\", \"FileService\"];\r\n\r\n  /** Default bindings to the components */\r\n  public static bindings = {\r\n    /**\r\n     * Model in the form. Currently always starts with \"form.\" to bind to main data object of the form.\r\n     * For fieldset, this may also be just \"form\" to bind to main model in form (not a property).\r\n     */\r\n    model: \"@\",\r\n\r\n    /** Possibility to override the label. */\r\n    label: \"@\",\r\n\r\n    /**\r\n     * Type of the input component as one of JSON schema types:\r\n     * 'boolean', 'object', 'number', 'string', 'integer' or 'array'.\r\n     * Typically, this will be inferred from the model, but you may set it explicitly if the property is not yet in the model.\r\n     */\r\n    type: \"@\",\r\n\r\n    /**\r\n     * Format of the input component as JSON schema format:\r\n     * Examples include \"multiline\", \"date\" (string) and \"radio\", \"checkbox\" (boolean).\r\n     */\r\n    format: \"@\",\r\n\r\n    /**\r\n     * True or false forces the read-only mode on the input regardless of the default value.\r\n     * This \"read-only\" attribute behaves differently than the HTML \"readonly\" attribute:\r\n     * The value is boolean (true/1 or false/0). Non existent attribute or empty/null uses\r\n     * the default value from metadata (API model) or from the form.\r\n     * Also, the input will become fully read-only view without any form control.\r\n     */\r\n    readOnly: \"@\",\r\n\r\n    /**\r\n     * True or false forces the disabled mode on the input.\r\n     * This \"disable\" attribute behaves differently than the HTML \"disabled\" attribute:\r\n     * The value is boolean (true/1 or false/0). Non existent attribute or empty/null\r\n     * uses the default value: Currently always false, but may later come from metadata.\r\n     */\r\n    disable: \"@\",\r\n\r\n    /**\r\n     * True or false forces the required mode on the input.\r\n     * This \"require\" attribute behaves differently than the HTML \"required\" attribute:\r\n     * The value is boolean (true/1 or false/0). Non existent attribute or empty/null\r\n     * uses the default value from metadata (API model).\r\n     */\r\n    require: \"@\",\r\n\r\n    /**\r\n     * Minimum value of the field\r\n     */\r\n    minimum: \"@\",\r\n\r\n    /**\r\n     * Maximum value of the field\r\n     */\r\n    maximum: \"@\",\r\n\r\n    /**\r\n     * Multiple of (step) of the value\r\n     */\r\n    multipleOf: \"@\",\r\n\r\n    /**\r\n     * For arrays, fieldsets and other components that enumerate children,\r\n     * defines which children are shown (taken to inputs collection).\r\n     * Comma separated list of property names.\r\n     */\r\n    include: \"@\",\r\n\r\n    /**\r\n     * For arrays, fieldsets and other components that enumerate children,\r\n     * defines which children are hidden (excluded from inputs collection).\r\n     * Comma separated list of property names.\r\n     */\r\n    exclude: \"@\",\r\n  };\r\n\r\n  /** Auto-generated unique id of the input */\r\n  public id: string;\r\n\r\n  /**\r\n   * Auto-generated name of the input.\r\n   * Currently, the same as ID, but this may change in the future.\r\n   * E.g. to make it more compatible with form POST (no id numbers etc.).\r\n   */\r\n  public name: string;\r\n\r\n  /** Model in the form. Currently always starts with \"form.\" to bind to main data object of the form. */\r\n  public model: string;\r\n\r\n  /**\r\n   * Possibility to override the label (default is \"SALAXY.MODEL.[TypeName].[propName].title\").\r\n   * Translated by default, if translation not found, shown as is.\r\n   * If starts with dot, will be interpreted as just the last part of the key,\r\n   * e.g. \".specialLabel\" will fetch key \"SALAXY.MODEL.[TypeName].[propName].specialLabel\".\r\n   */\r\n  public label: string;\r\n\r\n  /** Schema of the property */\r\n  public schemaModel: OpenAPIV3.SchemaObject | null;\r\n\r\n  /** Name of the parent schema (data model). Used in language keys. */\r\n  public parentSchemaName: string;\r\n\r\n  /** Name of the property to which this input is bound in the parentSchema. */\r\n  public propertyName: string;\r\n\r\n  /** SxyForm component that holds the data model and submit / reset logic etc. */\r\n  public form: SxyFormController;\r\n\r\n  /**\r\n   * Type of the input component as one of JSON schema types:\r\n   * 'boolean', 'object', 'number', 'string', 'integer' or 'array'.\r\n   * Typically, this will be inferred from the model, but you may set it explicitly if the property is not yet in the model.\r\n   */\r\n  public type: JsonInputType;\r\n\r\n  /**\r\n   * Format of the input component as JSON schema format:\r\n   * Examples include \"multiline\", \"date\" (string) and \"radio\", \"checkbox\" (boolean).\r\n   */\r\n  public format: string;\r\n\r\n  /**\r\n   * The read-only value as the user set it in the \"read-only\" attribute\r\n   * True or false forces the read-only mode on the input regardless of the default value or\r\n   * the read-only attribute set in the sxy-form level.\r\n   * This \"read-only\" attribute behaves differently than the HTML \"readonly\" attribute:\r\n   * The value is boolean (true/1 or false/0). Non existent attribute or empty/null uses\r\n   * the default value from metadata (API model) or from the form.\r\n   * Also, the input will become fully read-only view without any form control.\r\n   */\r\n  public readOnly: string;\r\n\r\n  /**\r\n   * True or false forces the disabled mode on the input.\r\n   * This \"disable\" attribute behaves differently than the HTML \"disabled\" attribute:\r\n   * The value is boolean (true/1 or false/0). Non existent attribute or empty/null\r\n   * uses the default value: Currently always false, but may later come from metadata.\r\n   */\r\n  public disable: string;\r\n\r\n  /**\r\n   * True or false forces the disabled mode on the input.\r\n   * This \"require\" attribute behaves differently than the HTML \"required\" attribute:\r\n   * The value is boolean (true/1 or false/0). Non existent attribute or empty/null\r\n   * uses the default value from metadata (API model).\r\n   */\r\n  public require: string;\r\n\r\n  /**\r\n   * Minimum value\r\n   */\r\n  public minimum: number | null;\r\n\r\n  /**\r\n   * Maximum value\r\n   */\r\n  public maximum: number | null;\r\n\r\n  /**\r\n   * Multiple of (step) of the value\r\n   */\r\n  public multipleOf: number | null;\r\n\r\n  /** Template URl that is used for rendering the input. */\r\n  public templateUrl: string;\r\n\r\n  /** Input metadata from the schema resolving process. */\r\n  public input: InputMetadata;\r\n\r\n  /**\r\n   * For arrays, fieldsets and other components that enumerate children,\r\n   * defines which children are shown (taken to inputs collection).\r\n   * Comma separated list of property names.\r\n   */\r\n  public include: string | string[];\r\n\r\n  /**\r\n   * For arrays, fieldsets and other components that enumerate children,\r\n   * defines which children are hidden (excluded from inputs collection).\r\n   * Comma separated list of property names.\r\n   */\r\n  public exclude: string | string[];\r\n\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private $transclude: angular.ITranscludeFunction,\r\n    private $element: JQLite,\r\n    private fileService: FileService,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.initModel();\r\n  }\r\n\r\n  /**\r\n   * Gets the formatted value for the input depending on the data type.\r\n   * @param childName For object arrays, gets the value for the specified child input.\r\n   * @param index For object the index of the item in the array.\r\n   * May later support other child scenarios.\r\n   */\r\n  public formatValue(childName?: string, index: number = null) {\r\n    if (childName && index != null) {\r\n      const arrayItemsType = ((this.schemaModel as OpenAPIV3.ArraySchemaObject)?.items as OpenAPIV3.SchemaObject);\r\n      if (arrayItemsType) {\r\n        const childType = arrayItemsType.properties[childName] as OpenAPIV3.SchemaObject;\r\n        const childvalue = this.value[index][childName];\r\n        if (childvalue && childType.format && childType.enum?.length) {\r\n          return EnumerationsLogic.getEnumLabel(`${this.form.getEnumNamespace()}.${childType.format}`, childvalue);\r\n        }\r\n        // TODO: Add number formatting etc. here as necessary.\r\n        return childvalue;\r\n      }\r\n      return `#ERR: formatValue not an array ${childName}, ${index}.`;\r\n    }\r\n    return \"#ERR: TODO Add other formatters here\";\r\n  }\r\n\r\n  /**\r\n   * Gets the label for the input.\r\n   * Default is \"SALAXY.MODEL.[TypeName].[propName].title\" in the dictionary.\r\n   * @param childName For object arrays, gets the label for the specified child input.\r\n   * May later support other child scenarios.\r\n   */\r\n  public getLabel(childName?: string) {\r\n    if (childName) {\r\n      const arrayItemsType = ((this.schemaModel as OpenAPIV3.ArraySchemaObject)?.items as OpenAPIV3.SchemaObject);\r\n      // TODO: We would need to move the type information away from format.\r\n      if (arrayItemsType?.type === \"object\" && arrayItemsType.format) {\r\n        const defaultLabel = (arrayItemsType.properties as OpenAPIV3.SchemaObject)?.[childName]?.title ?? (\"#\" + childName);\r\n        return Translations.getWithDefault(`${this.form.getModelNamespace()}.${arrayItemsType.format}.${childName}.title`, defaultLabel);\r\n      }\r\n      if (this.propertyName) {\r\n        return Translations.getWithDefault(`${this.form.getModelNamespace()}.${this.parentSchemaName}.${this.propertyName}.${childName}.title`, \"#\" + childName);\r\n      }\r\n      if (this.parentSchemaName) {\r\n        return Translations.getWithDefault(`${this.form.getModelNamespace()}.${this.parentSchemaName}.${childName}.title`, \"#\" + childName);\r\n      }\r\n      return \"#ERR: \" + childName;\r\n    }\r\n    if (this.label) {\r\n      if (this.label[0] === \".\" && this.label[1] !== \".\" && this.propertyName) {\r\n        this.label = `${this.form.getModelNamespace()}.${this.parentSchemaName}.${this.propertyName}${this.label}`;\r\n      }\r\n      return Translations.get(this.label);\r\n    }\r\n    if (this.propertyName) {\r\n      const defaultLabel = this.schemaModel?.title ?? (\"#\" + this.propertyName);\r\n      return Translations.getWithDefault(`${this.form.getModelNamespace()}.${this.parentSchemaName}.${this.propertyName}.title`, defaultLabel);\r\n    }\r\n    if (this.parentSchemaName) {\r\n      const defaultLabel = this.schemaModel?.title ?? (\"#\" + this.parentSchemaName);\r\n      return Translations.getWithDefault(`${this.form.getModelNamespace()}.${this.parentSchemaName}.title`, defaultLabel);\r\n    }\r\n    return \"#ERR: \" + this.model;\r\n  }\r\n\r\n  /** Gets the description for the input */\r\n  public getDescr(): string {\r\n    return Translations.getWithDefault(`${this.form.getModelNamespace()}.${this.parentSchemaName}.${this.propertyName}.descr`,\r\n      this.schemaModel?.description);\r\n  }\r\n\r\n  /** Gets the read-only value based on defaults and explicit values. */\r\n  public getReadOnly(): boolean {\r\n    const readOnlyValue = (this.readOnly || \"\").trim().toLowerCase();\r\n    if (readOnlyValue === \"true\" || readOnlyValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (readOnlyValue === \"false\" || readOnlyValue === \"0\") {\r\n      return false;\r\n    }\r\n    const readOnlyFormValue = (this.form.readOnly || \"\").trim().toLowerCase();\r\n    if (readOnlyFormValue === \"true\" || readOnlyFormValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (this.schemaModel?.readOnly != null) {\r\n      return this.schemaModel.readOnly;\r\n    }\r\n    // Default logic - this might later expand and/or some stuff may move to server.\r\n    const readOnlyFields = [\"id\", \"createdAt\", \"updatedAt\", \"isReadOnly\", \"owner\", \"partner\"];\r\n    if (readOnlyFields.indexOf(this.propertyName) >= 0) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets the minimum value */\r\n  public getMinimum(): number {\r\n    if (this.minimum != null) {\r\n      return this.minimum;\r\n    }\r\n    if (this.schemaModel?.minimum != null) {\r\n      return this.schemaModel.minimum;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Gets the maximum value */\r\n  public getMaximum(): number {\r\n    if (this.maximum != null) {\r\n      return this.maximum;\r\n    }\r\n    if (this.schemaModel?.maximum != null) {\r\n      return this.schemaModel.maximum;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Gets the multipleOf value */\r\n  public getMultipleOf(): number {\r\n    if (this.multipleOf != null) {\r\n      return this.multipleOf;\r\n    }\r\n    if (this.schemaModel?.multipleOf != null) {\r\n      return this.schemaModel.multipleOf;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Gets the minimum length value for string input */\r\n  public getMinLength(): number {\r\n    if (this.schemaModel?.minLength != null) {\r\n      return this.schemaModel.minLength;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Gets the maximum length value for string input */\r\n  public getMaxLength(): number {\r\n    if (this.schemaModel?.maxLength != null) {\r\n      return this.schemaModel.maxLength;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Gets the minimum length value for string input */\r\n  public getPattern(): string {\r\n    if (this.schemaModel?.pattern != null) {\r\n      return this.schemaModel.pattern;\r\n    }\r\n    return null;\r\n  }\r\n  /** Gets the require value based on defaults and explicit values. */\r\n  public getRequire(): boolean {\r\n    const requireValue = (this.require || \"\").trim().toLowerCase();\r\n    if (requireValue === \"true\" || requireValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (requireValue === \"false\" || requireValue === \"0\") {\r\n      return false;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets the disable value based on defaults and explicit values. */\r\n  public getDisable(): boolean {\r\n    const disableValue = (this.disable || \"\").trim().toLowerCase();\r\n    if (disableValue === \"true\" || disableValue === \"1\") {\r\n      return true;\r\n    }\r\n    if (disableValue === \"false\" || disableValue === \"0\") {\r\n      return false;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets or sets the value in the model */\r\n  public get value(): any {\r\n    return this.form?.getValue(this.model);\r\n  }\r\n  public set value(value: any) {\r\n    if (this.form) {\r\n      this.form.setValue(this.model, value);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * For datatype \"object\", gets the inputs for child properties.\r\n   * For datatype \"array\", gets the inputs for items.\r\n   * For other types, gets an array with single input for that type\r\n   * (TODO: Does this make sense? It is essentially the same as parent).\r\n   * @param defaultTop Returns top n children.\r\n   * If include is specified (fields are hand-picked), this proeprty is ignored.\r\n   */\r\n  public getChildInputs(defaultTop: number): InputMetadata[] {\r\n    return this.uiHelpers.cache(this, \"childInputs\", () => {\r\n      if (!this.schemaModel) {\r\n        return null;\r\n      }\r\n      let result: InputMetadata[];\r\n      if (this.schemaModel.type === \"object\") {\r\n        result = FormHelpers.getInputsForObject(this.schemaModel, this.model);\r\n      } else if (JsonSchemaUtils.isArraySchemaObject(this.schemaModel)) {\r\n        result = FormHelpers.getInputsForArray(this.schemaModel, this.model);\r\n      } else {\r\n        result = [FormHelpers.getInputForSelf(this.schemaModel, null, \"form\")];\r\n      }\r\n      const includeArr = Arrays.assureArray(this.include);\r\n      if (includeArr.length > 0) {\r\n        result = includeArr.map((x) => result.find((y) => y.name === x)).filter((x) => !!x);\r\n        defaultTop = includeArr.length;\r\n      }\r\n      const excludeArr = Arrays.assureArray(this.exclude);\r\n      if (excludeArr.length > 0) {\r\n        result = result.filter((x) => excludeArr.indexOf(x.name) < 0);\r\n      }\r\n      return result.slice(0, defaultTop);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows an edit dialog for item.\r\n   * @param item Item to edit\r\n   * @param index Index of the item in the current model array if available.\r\n   */\r\n  public edit(item: any, index: number): Promise<EditDialogResult<any>> {\r\n    // HACK: This now only works for array/object => Make more generic.\r\n    const logic = {\r\n      openApi: this.form.openApi,\r\n      type: ((this.schemaModel as OpenAPIV3.ArraySchemaObject)?.items as OpenAPIV3.SchemaObject)?.format,\r\n      title: index < 0 ? Translations.get(\"SALAXY.NG1.SxyInputComponent.addNewRow\") : Translations.get(\"SALAXY.NG1.SxyInputComponent.editRow\"),\r\n      showDelete: index > -1 && !this.getReadOnly(),\r\n      isReadOnly: this.getReadOnly(),\r\n      debugger: this.form.debugger,\r\n    };\r\n    if (this.$transclude?.isSlotFilled(\"form\")) {\r\n      let html = \"\";\r\n\r\n      // The cloning of the slot actually initializes all the components in the slot, be careful.\r\n      // the form has not been bound yet\r\n      this.$transclude((transEl, transScope) => { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n        angular.forEach(transEl, (textOrElem) => {\r\n          if (textOrElem.tagName === \"FORM\") {\r\n            html += textOrElem.innerHTML;\r\n          }\r\n        });\r\n        html = html.trim();\r\n        return null as any;\r\n      }, this.$element, \"form\");\r\n      const template = `<div class=\"modal-header\">\r\n      <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h4 class=\"modal-title\">{{ $ctrl.logic.title }}</h4>\r\n    </div>\r\n    <div class=\"modal-body\">\r\n      <sxy-form open-api=\"{{ $ctrl.logic.openApi }}\" type=\"{{ $ctrl.logic.type }}\" auto-gen=\"false\" debugger=\"$ctrl.logic.debugger\"\r\n        model=\"$ctrl.current\" read-only=\"{{$ctrl.logic.isReadOnly ? 'true' : ''}}\">\r\n        <div>${html || \"Form tag contains no data\"}</div>\r\n      </sxy-form>\r\n    </div>\r\n    <div class=\"modal-footer\">\r\n      <button type=\"button\" ng-if=\"$ctrl.logic.showDelete\" class=\"btn btn-danger pull-left\" ng-click=\"$close('delete-no-save')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n      <button type=\"reset\" ng-if=\"!$ctrl.logic.isReadOnly\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"button\" ng-if=\"!$ctrl.logic.isReadOnly\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n      <button type=\"button\" ng-if=\"$ctrl.logic.isReadOnly\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    </div>`;\r\n      return this.uiHelpers.openEditDialog(null, item, logic, \"\", \"EditDialogController\", { template }).then((result) => {\r\n        if (result.action === EditDialogKnownActions.DeleteNoCommit) {\r\n          this.delete(item, index);\r\n        }\r\n        return result;\r\n      });\r\n    }\r\n    return this.uiHelpers.openEditDialog(\"salaxy-components/sxy-form/SxyInput-dialog-edit.html\", item, logic).then((result) => {\r\n      if (result.action === EditDialogKnownActions.DeleteNoCommit) {\r\n        this.delete(item, index);\r\n      }\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes an item (currently no \"Are you sure?\")\r\n   * @param item Item to delete\r\n   * @param index Index of the item in the current model array. This is currently required.\r\n   */\r\n  public delete(item: any, index: number): void {\r\n    (this.value as []).splice(index, 1);\r\n  }\r\n\r\n  /**\r\n   * Creates a new item to the current array.\r\n   * @param item Item to add. If not specified (default), shows an edit dialog for creating the item.\r\n   */\r\n  public createNew(item: any = null): Promise<EditDialogResult<any>> {\r\n    if (item) {\r\n      if (!this.value) {\r\n        this.value = [];\r\n      }\r\n      (this.value as any[]).push(item);\r\n      return;\r\n    }\r\n    // HACK: This now only works for array/object => Make more generic.\r\n    return this.edit({}, -1).then((result) => {\r\n      if (result.action === \"ok\") {\r\n        if (!this.value) {\r\n          this.value = [];\r\n        }\r\n        (this.value as any[]).push(result.item);\r\n      }\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets an array total for view purposes\r\n   * @param field Name of the field for which the total is calculated\r\n   * @param type Type of calculation. Currently only sum is supported, but others may be added (e.g. \"avg\").\r\n   */\r\n  public getTotal(field: string, type: \"sum\" = \"sum\"): number {\r\n    if (!this.value) {\r\n      return;\r\n    }\r\n    switch (type) {\r\n      case \"sum\":\r\n      default:\r\n        return Arrays.sum(this.value as any[], (x) => x[field]);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the options for enumerations based on schema.\r\n   * For an array, gets the options for item enumeration.\r\n   */\r\n  public getEnumOptions(): InputEnumOption[] {\r\n    // TODO: This is just quick partial implementation based on schema. Need to think through the different scenarios!\r\n    return this.uiHelpers.cache(this, \"getEnumOptions\", () => {\r\n      if (!this.schemaModel) {\r\n        return [];\r\n      }\r\n      let enumArr = this.schemaModel.enum;\r\n      let enumName = this.schemaModel.format;\r\n      if (!enumArr?.length) {\r\n        enumArr = ((this.schemaModel as OpenAPIV3.ArraySchemaObject).items as OpenAPIV3.SchemaObject)?.enum;\r\n        enumName = ((this.schemaModel as OpenAPIV3.ArraySchemaObject).items as OpenAPIV3.SchemaObject)?.format;\r\n      }\r\n      if (enumArr?.length > 0) {\r\n        return enumArr.map(x => ({\r\n          title: EnumerationsLogic.getEnumDescr(`${this.form.getEnumNamespace()}.${enumName}`, x),\r\n          text: EnumerationsLogic.getEnumLabel(`${this.form.getEnumNamespace()}.${enumName}`, x),\r\n          value: x,\r\n        }));\r\n      }\r\n    }, () => this.schemaModel.type + this.schemaModel.format + this.schemaModel.enum?.length);\r\n  }\r\n\r\n  /**\r\n   * Gets the format assuring that it is of supported type.\r\n   * Currently, there is only special logic for enums.\r\n   */\r\n  public getFormat(): string {\r\n    if (this.input.isEnum) {\r\n      const enumFormat = this.format || this.input.format;\r\n      const supportedFormats = [\"select\", \"radio\", \"multi-select\", \"typeahead\", \"list\"];\r\n      if (supportedFormats.indexOf(enumFormat) >= 0) {\r\n        return enumFormat;\r\n      }\r\n      // Especially \"enum\", \"default\" and null.\r\n      // TODO: Exact logic requires go-through.\r\n      return \"select\";\r\n    }\r\n    return this.format;\r\n  }\r\n\r\n    /** Gets the exportable for the current data model: For exporting an array. */\r\n    public getExportable(): Exportable<any> {\r\n      if (!(this.schemaModel as OpenAPIV3.ArraySchemaObject).items) {\r\n        return {\r\n          exporters: [],\r\n          getExportMappers: () => [],\r\n          getExportMapper: () => null,\r\n          list: () => Promise.resolve([]),\r\n          getSingle: (item) => Promise.resolve(item),\r\n        };\r\n      }\r\n\r\n      // TODO: Tarkista mikä ero näillä on käytännössä ja katso otetaanko mukaan molemmat vai toinen. Tarkista voisiko käyttää suoraan Gridiä vai onko se liian kompleksi?\r\n      // TODO: Harkitse tämän logiikan siirtämistä helperiin TAI ExportControlleriin (käytössä myös SxyGridController), samoin fileService tarpeen poistoa\r\n      // TODO: Lisää myös import.\r\n      // const fullMapper = this.getMapper().reverse(this.propertyName + \"FullExport\", `Full object export for ${this.propertyName}`);\r\n\r\n      const exptMapper = new DataMapper<{ [key: string]: string }, any>(this.propertyName + \"GridExport\", `Table export for ${this.propertyName}`);\r\n      exptMapper.setSchema((this.schemaModel as OpenAPIV3.ArraySchemaObject).items as OpenAPIV3.NonArraySchemaObject, this.propertyName, \"source\");\r\n      exptMapper.setPathsFromSourceSchema(this.getChildInputs(100).map((x) => x.name));\r\n\r\n      // const mappers = [exptMapper, fullMapper];\r\n      const mappers = [exptMapper];\r\n\r\n      const result: Exportable<any> = {\r\n        exporters: this.fileService.getDefaultExporters(),\r\n        getExportMappers: () => {\r\n          return mappers.map((x) => DataMappersLogic.getInfo(x));\r\n        },\r\n        getExportMapper: (id: string) => {\r\n          return Promise.resolve(mappers.find((x) => x.uri == id));\r\n        },\r\n        list: (maxCount) => {\r\n          const result = maxCount > 0 ? this.value.slice(0, maxCount) : this.value;\r\n          return Promise.resolve(result);\r\n        },\r\n        getSingle: (item) => {\r\n          return Promise.resolve(item);\r\n        },\r\n      };\r\n\r\n      return result;\r\n    }\r\n\r\n  private initModel() {\r\n    if (!this.model) {\r\n      throw new Error(`Input not bound to model.`);\r\n    }\r\n    if (!this.form) {\r\n      this.input = {\r\n        type: \"error\",\r\n        content: \"No sxy-form for input with model \" + this.model,\r\n        name: this.model,\r\n        path: this.model,\r\n        isEnum: false,\r\n        format: null,\r\n      };\r\n      this.name = this.id = this.input.name;\r\n      this.templateUrl = \"salaxy-components/sxy-form/error/default.html\";\r\n      this.schemaModel = null;\r\n      return;\r\n    }\r\n    const reg = this.form.registerInput(this.model, this.type, this.format);\r\n    this.schemaModel = reg.prop.schema || null;\r\n    this.parentSchemaName = reg.prop.parentName;\r\n    this.name = this.id = reg.id;\r\n    this.propertyName = reg.prop.propertyName;\r\n    if (reg.prop.isRequired && !(this.require || \"\").trim()) {\r\n      this.require = \"true\"; // Set from schema if not explicitly set.\r\n    }\r\n    this.input = reg.input;\r\n    if (this.type && this.type !== this.input.type) {\r\n      console.error(`Input type \"${this.type}\" not supported for property \"${this.input.name}\", defaulting to \"${this.input.type}\".`);\r\n    }\r\n    this.templateUrl = reg.templateUrl;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport { InputEnumOption, OpenAPIV3 } from \"@salaxy/core\";\r\nimport { JsonSchemaService, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Controller for schema editing user interfaces. Current implementation is OpenAPI V3 schema editing.\r\n */\r\nexport class SxySchemaEditorController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"JsonSchemaService\", \"UiHelpers\"];\r\n\r\n  /** Schema object that is being edited. */\r\n  public model: OpenAPIV3.SchemaObject;\r\n\r\n  public types: (InputEnumOption & {\r\n      formats: InputEnumOption[],\r\n    })[];\r\n\r\n  constructor(\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private uiHelpers: UiHelpers,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.types = [];\r\n    const inputs = this.jsonSchemaService.getRegisteredInputs();\r\n    // TODO: Move to dictionary\r\n    const labels = { \"string\": \"Teksti\", \"number\": \"Numero\", \"array\": \"Lista\", \"boolean\": \"On/off (boolean)\", \"integer\": \"Kokonaisluku\", \"object\": \"Muu...\" };\r\n    Object.keys(inputs).forEach((key) => {\r\n      this.types.push({\r\n        text: labels[key],\r\n        value: key,\r\n        formats: Object.keys(inputs[key]).map((x) => ({\r\n          text: x == \"default\" ? \"Oletus\" : x, // TODO: Translate\r\n          value: x == \"default\" ? \"\" : x,\r\n        }))});\r\n    });\r\n  }\r\n\r\n  /** Adds a new property to the current schema */\r\n  public addProperty() {\r\n    // TODO: Add this to UI Helpers (as dialog) and search for prompt().\r\n    const name = window.prompt(\"Mikä on lisättävän tietueen tekninen nimi (a-z, 0-1, ei välejä eikä erikoismerkkejä)?\");\r\n    // TODO: Add property name validation / fix.\r\n    this.model[name] = {};\r\n  }\r\n\r\n  /** Deletes a property from the schema. */\r\n  public deleteProperty(key) {\r\n    delete this.model[key];\r\n  }\r\n\r\n  /** Gets the formats for given type */\r\n  public getFormats(type: string) {\r\n    return this.types.find((x) => x.value == type).formats;\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { OpenAPIV3 } from \"@salaxy/core\";\r\n\r\nimport { JsonSchemaUtils } from \"@salaxy/core\";\r\n\r\nimport { JsonSchemaService } from \"../../services\";\r\nimport { ColumnDefinition, Editor, EventCallBackMethods, Options, TabulatorFull as Tabulator } from \"tabulator-tables\";\r\n\r\n/**\r\n * Configuration object for SxyTable:\r\n * Extends Tabulator Options with events and potentially some SxyTables specific options in the future.\r\n */\r\nexport interface SxyTableOptions extends Options {\r\n  /** Event handlers that are added to Tabulator after it has been created. */\r\n  events?: Partial<EventCallBackMethods>,\r\n}\r\n\r\n/**\r\n * Sxy form contains the definition for an editor used interface that\r\n * typically corresponds to an HTML form.\r\n */\r\nexport class SxyTableController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"JsonSchemaService\", \"$element\", \"$timeout\"];\r\n\r\n  /**\r\n   * The schema definition that defines the structure of the grid.\r\n   */\r\n  public schemaDef?: OpenAPIV3.NonArraySchemaObject;\r\n\r\n  /**\r\n   * URL of the schema document that contains the schemaDef.\r\n   * If set with schema in init, loads the document.\r\n   */\r\n  public doc?: string;\r\n\r\n  /**\r\n   * Key of schemaDef in doc.\r\n   * If set with doc in init, will load the schema document from server and set the schemaDef.\r\n   */\r\n  public schema?: string;\r\n\r\n  /**\r\n   * Data that is rendered / edited in the grid.\r\n   * This is either an array or an object that implements getTabulatorConfig() method for ajax data.\r\n   */\r\n  public data?: any[] | { getTabulatorConfig: () => Options };\r\n\r\n  /**\r\n   * List of columns to include in the grid.\r\n   * This may be an array or comma separated string of field names (or a property tree, e.g. \"owner.avatar.displayName\").\r\n   * Alternatively, the entries in the array may be be full Tabulator column definitions, where `field` propererty defines the\r\n   * data item and fetches the default properties from the schema.\r\n   */\r\n  public include?: string | (string | ColumnDefinition)[];\r\n\r\n  /**\r\n   * List of columns to exclude from the grid.\r\n   * This property is currenlty used only if include property is undefined, i.e. in default\r\n   * rendering, which will render the first-level properties. As such, exclude does not really support property paths.\r\n   */\r\n  public exclude?: string | string[];\r\n\r\n  /** Additional configuration for the table in init. */\r\n  public options?: SxyTableOptions;\r\n\r\n  /** After init, exposes the Tabulator for calling methods. */\r\n  public tabulator?: Tabulator;\r\n\r\n  /**\r\n   * Gets the state of filters or sets the initial state of filters.\r\n   * By default, the filters are not shown before showFilters() function is called.\r\n   * If the property / attribute is set to true before initial render, the filters are shown.\r\n   * Use showFilters() function to show or hide the filters after initial render.\r\n   */\r\n  public filters = false;\r\n\r\n  /**\r\n   * By default, the header filters are not shown before showFilters() function is called.\r\n   * This is the place where the filter definitions are stored in the mean time.\r\n   */\r\n  public filterDefinitions: {\r\n    [key: string]: Editor,\r\n  } = {};\r\n\r\n  private tableConfigCache = {\r\n    data: null,\r\n    include: null,\r\n    exclude: null,\r\n    options: null\r\n  };\r\n\r\n  constructor(\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private $element: JQLite,\r\n    protected $timeout: angular.ITimeoutService\r\n  ) {}\r\n\r\n  /** Initializes the controller */\r\n  public $onInit() {\r\n    this.init();\r\n  }\r\n\r\n  /** Intialises settings */\r\n  public async init(): Promise<void> {\r\n    this.doc = this.doc || \"salaxy-secure/schemas/v02.json\";\r\n    if (!this.schemaDef && this.doc && this.schema) {\r\n      const schemaDoc = await this.jsonSchemaService.assureSchemaDocument(this.doc);\r\n      this.schemaDef = schemaDoc?.components?.schemas?.[this.schema] as OpenAPIV3.NonArraySchemaObject | undefined;\r\n    }\r\n    this.renderTable();\r\n  }\r\n\r\n  /**\r\n   * Method used to refresh table if data, include, exclude or options changes\r\n   */\r\n  public refresh() {\r\n    this.renderTable();\r\n  }\r\n\r\n  private async renderTable() {\r\n    const columns: ColumnDefinition[] = [];\r\n    this.getFields().forEach((colDefOrKey: string | ColumnDefinition) => {\r\n      let key: string;\r\n      let colDef: ColumnDefinition;\r\n      if (typeof colDefOrKey === \"string\") {\r\n        key = colDefOrKey;\r\n        colDef = {\r\n          field: key,\r\n          title: \"#field\", // Will be replaced below\r\n        };\r\n      } else {\r\n        key = colDefOrKey.field || \"\";\r\n        colDef = colDefOrKey;\r\n      }\r\n      if (!key && !colDef.formatter) {\r\n        console.error(\"Invalid column definition (no field): \", colDefOrKey);\r\n        return;\r\n      }\r\n      const schema = JsonSchemaUtils.getProperty(this.schemaDef, key)?.schema;\r\n      if (schema) {\r\n        if (colDef == null || colDef.title == \"#field\") {\r\n          colDef.title = schema.title || \"#field\";\r\n        }\r\n        this.setDefaultFormatter(schema, colDef);\r\n        if (schema.description) {\r\n          colDef.headerTooltip = schema.description;\r\n        }\r\n        if (schema.enum?.length) {\r\n          // TODO: Add enum renderer.\r\n          // const enumValues = SxyForms.i18n.getEnumMetadata(schema.format).values;\r\n        }\r\n      }\r\n      if (colDef.title == null || colDef.title == \"#field\") {\r\n        colDef.title = key.indexOf(\".\") ? key.substring(key.lastIndexOf(\".\") + 1) : key;\r\n      }\r\n      if (colDef.headerFilter) {\r\n        if (colDef.field) {\r\n          this.filterDefinitions[colDef.field] = colDef.headerFilter;\r\n          if (!this.filters) {\r\n            colDef.headerFilter = undefined;\r\n          }\r\n        } else {\r\n          console.error(\"Cannot set filter for column without field: \", colDef);\r\n        }\r\n      }\r\n      columns.push(colDef);\r\n    });\r\n    const tableOptions: SxyTableOptions = {};\r\n    if (this.options) {\r\n      // TODO: Potentially remove the SxyTable-specific options (events etc.) for future backward compatibility.\r\n      Object.assign(tableOptions, this.options);\r\n    }\r\n    if ((this.data as any)?.getTabulatorConfig) {\r\n      Object.assign(tableOptions, (this.data as any).getTabulatorConfig());\r\n    } else {\r\n      tableOptions.data = this.data as any[] || [];\r\n    }\r\n    if (columns.length) {\r\n      tableOptions.columns = columns;\r\n    } else if (tableOptions.autoColumns == null) {\r\n      tableOptions.autoColumns = true;\r\n    }\r\n    const elem = this.$element.find(\"div\")[0] as HTMLElement;\r\n    if (!elem) {\r\n      throw new Error(\"Cannot find div element for table.\");\r\n    }\r\n    this.tabulator = new Tabulator(elem, tableOptions);\r\n    const events = tableOptions.events ?? {};\r\n    Object.keys(events).forEach((keyString: string) => {\r\n      const key = keyString as keyof EventCallBackMethods;\r\n      this.tabulator.on(key, events[key]);\r\n    });\r\n\r\n    await this.$timeout();\r\n  }\r\n\r\n  //TODO: Replaces @salaxy/core assureArray?\r\n  private assureArray<T>(arrayCandidate: string | (T | string)[] | undefined): (T | string)[] {\r\n    if (!arrayCandidate) {\r\n      return [];\r\n    }\r\n    if (Array.isArray(arrayCandidate)) {\r\n      return arrayCandidate;\r\n    }\r\n    return arrayCandidate.split(\",\");\r\n  }\r\n\r\n  private getFields(): (ColumnDefinition | string)[] {\r\n    let fields = this.assureArray(this.include);\r\n    if (fields.length == 0) {\r\n      let keys = Object.keys(this.schemaDef?.properties || {});\r\n      const excludeArr = this.assureArray(this.exclude);\r\n      if (excludeArr.length > 0) {\r\n        keys = keys.filter((x) => excludeArr.indexOf(x) < 0);\r\n      }\r\n      fields = keys;\r\n    }\r\n    return fields;\r\n  }\r\n\r\n  private setDefaultFormatter(schema: OpenAPIV3.SchemaObject, colDef: ColumnDefinition) {\r\n    if (colDef.formatter) {\r\n      return;\r\n    }\r\n    switch (schema.type) {\r\n      case \"integer\":\r\n      case \"number\":\r\n        // TODO: Add number formatter.\r\n        break;\r\n      case \"object\":\r\n        //TODO add avatar / other formatter\r\n        break;\r\n      case \"string\":\r\n        if (schema.format === \"date-time\") {\r\n          // HACK: Consider adding date time handling to utils\r\n          colDef.formatter = (cell, _formatterParams, _onRendered) => {\r\n            const value = cell.getValue();\r\n            if (!value) {\r\n              return \"\";\r\n            }\r\n            const date = new Date(value);\r\n            return date.toLocaleDateString(\"fi-FI\");\r\n          };\r\n          colDef.hozAlign = \"right\";\r\n        }\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, Test } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, SessionService } from \"../../services\";\r\n\r\n/**\r\n * Controller for resetting account data in the test environment.\r\n */\r\nexport class AccountResetController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Test\",\r\n    \"UiHelpers\",\r\n    \"AjaxNg1\",\r\n    \"SessionService\"\r\n  ];\r\n\r\n  /**\r\n   * Creates a new AccountResetController.\r\n   * @param testApi - Api methods for resetting account data.\r\n   * @param uiHelpers - Salaxy UI Helpers.\r\n   * @param ajax - Salaxy ajax component.\r\n   */\r\n  constructor(\r\n    private testApi: Test,\r\n    private uiHelpers: UiHelpers,\r\n    private ajax: Ajax,\r\n    private sessionService: SessionService\r\n  ) { }\r\n\r\n  /**\r\n   * Delete the current account data and credentials (including Auth0 user).\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteCurrent(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccount().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove all calculations, workers etc. user objects except products and signature from the account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteData(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tiliin liittyvän datan?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountData().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove all calculations, payrolls and payments from the account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteCalculations(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin laskelmat?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountCalculations().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove workers including calculations, employment contracts and tax cards from the account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteWorkers(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin työntekijät?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountWorkers().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove all holiday year from all workers. Does not touch the default values of holidays in Worker Employment relation.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteHolidays(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa loma- ja poissaolotiedot?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountHolidays().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Delete all empty accounts (company or worker) created by this account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteAuthorizingAccounts(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin luomat muut tilit?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountAuthorizingAccounts().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove pension and insurance from the account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deletePensionAndInsurance(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tiliin liittyvän TyEL:n ja vakuutukset?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountPensionAndInsurance().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Remove the signature from the account.\r\n   * Can be called only in a test environment.\r\n   */\r\n  public deleteSignature(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin valtuutuksen (allekirjoitus)?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountSignature().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Checks if the KYC (Know Your Customer) process is done for the current account.\r\n   * @returns A boolean value indicating whether the KYC process is done.\r\n   */\r\n  public isKycMissing(): boolean {\r\n    return !((this.sessionService.session?.currentAccount?.identity as any)?.kycUpdatedAt);\r\n  }\r\n\r\n  /**\r\n   * Handles the KYC (Know Your Customer) process.\r\n   * If KYC is missing, it activates the KYC.\r\n   * Otherwise, it deletes the KYC.\r\n   */\r\n  public handleKyc(): void {\r\n    if (this.isKycMissing()) {\r\n      this.activateKyc();\r\n    } else {\r\n      this.deleteKyc();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Deletes the KYC (Know Your Customer) information for the current account.\r\n   * Shows a confirmation dialog before deleting the KYC.\r\n   * If the user confirms, it makes an API call to delete the KYC and logs out the user.\r\n   */\r\n  private deleteKyc(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti poistaa tilin KYCin?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.deleteCurrentAccountKyc().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Activates the KYC for the account.\r\n   * Displays a confirmation dialog and proceeds with the activation if confirmed.\r\n   * Deletes the current account signature and logs out after successful activation.\r\n   */\r\n  private activateKyc(): void {\r\n    this.uiHelpers.showConfirm(\"Haluatko varmasti aktivoidatilin KYCin?\")\r\n      .then((result: boolean) => {\r\n        if (result) {\r\n          const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n          this.testApi.activateCurrentAccountKyc().then(() => {\r\n            loading.dismiss();\r\n            this.logout();\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  private logout() {\r\n    this.ajax.setCurrentToken(null);\r\n    window.location.assign(\"/\");\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CalculatorLogic, Dates, Numeric, ReportType, TaxCard2019Logic, Token } from \"@salaxy/core\";\r\nimport { CalculationMapper, Templates } from \"@salaxy/reports\";\r\nimport { SessionService } from \"../../services\";\r\nimport jsonTest from \"./test.json\";\r\n\r\n/**\r\n * Helps in performing basic smoke test about salaxy libraries:\r\n * Are all the libraries and dependencies loaded and functional in the package.\r\n */\r\nexport class SmokeTestController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** Defines the view / set of tests: \"core\" or \"ng1\" */\r\n  public mode: \"core\" | \"ng1\";\r\n\r\n  public reportsTests = {\r\n    loaded: null as boolean,\r\n    mapper: null as boolean,\r\n    handlebars: null as boolean\r\n  };\r\n\r\n  constructor(public sessionSrv: SessionService) {\r\n  }\r\n\r\n  /**\r\n   * Controller initialization\r\n   */\r\n  public $onInit() {\r\n    try {\r\n      this.runReportTests();\r\n    }\r\n    catch(e)\r\n    {\r\n      console.error(\"Init tests run failed with exception.\");\r\n      console.log(e);\r\n    }\r\n  }\r\n\r\n  /** Gets number 1 from @salaxy/core library. */\r\n  public getNumber(): 1 | number {\r\n    return Numeric.parseNumber(\"1\") || null;\r\n  }\r\n\r\n  /** Gets a date formatted with Dates library: \"20.02.2020\" */\r\n  public getADate(): \"20.02.2020\" | string {\r\n    return Dates.format(Dates.asDate(\"2020-02-20\"));\r\n  }\r\n\r\n  /** Returns true if the code can read the token usin Base64 library. */\r\n  public readToken(): boolean {\r\n    const token = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2Mjg2OTE2OTMsImV4cCI6MTY2MDIyNzY5MywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.WBuoHS5h8iZi0b5cE25onpvgYFv_X-QXbLdf0KjECEY\";\r\n    return Token.parseHeader(token).alg === \"HS256\";\r\n  }\r\n\r\n  /** Runs smoke tests related to Reports library. */\r\n  public runReportTests(): void {\r\n    this.reportsTests.loaded = !!new CalculationMapper();\r\n    this.reportsTests.mapper = this.isCalcMapperWorking();\r\n    this.reportsTests.handlebars = this.isHbsTemplatesWorking();\r\n  }\r\n\r\n  /** Shows a saveAs dialog for text file (\"Hello, world!\"). */\r\n  public saveAs() {\r\n    const blob = new Blob([\"Hello, world!\"], {type: \"text/plain;charset=utf-8\"});\r\n    // This only works in non-module mode (umd package). Implement module version if necessary.\r\n    (window as any).saveAs(blob, \"hello world.txt\");\r\n  }\r\n\r\n  /** Gets a text from json file. */\r\n  public getJson() {\r\n    return jsonTest.test;\r\n  }\r\n\r\n  /** Test chart with annotations */\r\n  public chartData: any = TaxCard2019Logic.getMainChart(\r\n    {\r\n      card: {\r\n        incomeLimit: 30000,\r\n        taxPercent: 10,\r\n        taxPercent2: 30,\r\n        forYear: Dates.getYear(Dates.getToday()),\r\n        personalId: \"111111-111*\",\r\n        validity: {\r\n          start: Dates.getToday(),\r\n        }\r\n     },\r\n     result: {\r\n       totalIncome: 21000,\r\n     },\r\n     incomeLog: [],\r\n    }\r\n  );\r\n  private isCalcMapperWorking(): boolean {\r\n    const calc = CalculatorLogic.getBlank();\r\n    calc.worker.avatar.firstName = \"James\";\r\n    calc.worker.avatar.sortableName = \"JamesB\";\r\n    calc.worker.tax.snapshot = { forYear: 2021, incomeLimit: 999.50 };\r\n    calc.result.totals = {};\r\n    calc.result.workerCalc = {};\r\n    calc.result.responsibilities = {};\r\n    calc.result.employerCalc = {};\r\n    const calcReport = CalculationMapper.getCalculationReport(calc, ReportType.SalarySlip);\r\n\r\n    return (\r\n      calcReport.header.taxcardIncomeLimit === 999.50\r\n      && calcReport.header.worker.avatar.firstName === \"James\"\r\n      && calcReport.header.worker.avatar.sortableName === \"JamesB\"\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Tests that handlebars templates including nested partials and helpers are working correctly.\n   * @returns Returns true if templates are working and otherwise false.\r\n   */\r\n  private isHbsTemplatesWorking(): boolean {\r\n    const html = new Templates().getHtml(\r\n      \"salarySlipV2\",\r\n      {\r\n        report: {\r\n          header: {\r\n            taxcardIncomeLimit: 999.50,\r\n            worker: {\r\n              avatar: {\r\n                firstName: \"James\",\r\n                sortableName: \"JamesB\",\r\n              }\r\n            }\r\n          }\r\n        }\r\n      }\r\n    );\r\n\r\n    return (\r\n      // Produced by a deeply nested partial (salarySlipV2 -> workerReportHeadV2 ->\r\n      // contractPartiesContactDetailsV2)\r\n      html.indexOf(`<div class=\"uppercase\">JamesB</div>`) !== -1\r\n      // Produced by a helper function used in a deeply nested partial (salarySlipV2 ->\r\n      // workerReportHeadV2 -> workerContractDetailsV2 -> c\r\n      && html.indexOf(`<span>999,50€</span>`) !== -1\r\n    );\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ReferenceObject,ReferenceObjectListItem,ReferenceObjects,\r\n} from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * FOR TESTING OR DEVELOPMENT USE ONLY - NOT FOR PRODUCTION USE.\r\n * =============================================================\r\n * Provides UI logic for viewing and adding new (modifying) Reference Objects\r\n * The implementation is based on the current development conventions.\r\n * The reference objects have no meaning or use outside development or testing environments, and they\r\n * should not be used in production for any business purpose.\r\n */\r\nexport class ReferenceObjectCrudController extends ApiCrudObjectController<ReferenceObject, ReferenceObjectListItem> {\r\n  isSaving: boolean;\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"ReferenceObjects\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\"\r\n  ];\r\n\r\n  constructor(\r\n    api: ReferenceObjects,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any\r\n  ) { // Dependency injection\r\n    super(api, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/reference-objects\",\r\n      detailsUrl: this.detailsUrl || \"/reference-objects/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/ReferenceObjects.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n}","import { AbsencePeriod, Arrays, Dates, EnumerationsLogic, HolidaysLogic, WorkerAbsences, CalendarSeries, CalendarUiEvent } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\nclass AbsencePeriodsControllerBindings extends ListControllerBaseBindings {\r\n   /** If true, will format the table with class table-condensed. Later may add some other condensed formatting. */\r\n   public condensed = \"<\";\r\n\r\n   /** Date filter start value. Will be compared to period end date. */\r\n   public filterStart = \"<\";\r\n\r\n   /** Date filter end value. Will be compared to period start date. */\r\n   public filterEnd = \"<\";\r\n}\r\n\r\n/**\r\n * Controls the absences list (poissaolokirjanpito) for a selected holiday year.\r\n */\r\nexport class AbsencePeriodsController extends ListControllerBase<WorkerAbsences, AbsencePeriod> {\r\n\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new AbsencePeriodsControllerBindings();\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /** If true, will format the table with class table-condensed. Later may add some other condensed formatting. */\r\n  public condensed: boolean;\r\n\r\n  /** Date filter start value. Will be applied to period start dates. */\r\n  public filterStart: string;\r\n\r\n  /** Date filter end value. Will be applied to period end dates. */\r\n  public filterEnd: string;\r\n\r\n  constructor(uiHelpers: UiHelpers) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /** List of items */\r\n  public get list(): AbsencePeriod[] {\r\n    if (!this.parent) {\r\n      return null;\r\n    }\r\n    return this.parent.periods;\r\n  }\r\n\r\n  /** Maps WorkerAbsences to calendar series. */\r\n  public mapToCalendar = (abs: WorkerAbsences): CalendarSeries[] => {\r\n    return [{\r\n      key: abs.id,\r\n      title: abs.workerSnapshot?.displayName,\r\n      avatar: abs.workerSnapshot,\r\n      events: abs.periods.map((period) => ({\r\n          start: period.period.start,\r\n          end: period.period.end,\r\n          summary: EnumerationsLogic.getEnumLabel(\"AbsenceCauseCode\", period.causeCode),\r\n          data: period,\r\n        })),\r\n    }];\r\n  };\r\n\r\n  /**\r\n   * Filter that is applied to the list\r\n   * @param value Item in the list\r\n   */\r\n  public filter = (value: AbsencePeriod) => {\r\n    if (this.filterEnd && value.period.start > this.filterEnd) {\r\n      return false;\r\n    }\r\n    if (this.filterStart && value.period.end < this.filterStart) {\r\n      return false;\r\n    }\r\n    return true;\r\n  };\r\n\r\n  /** Creating of a new item. */\r\n  public getBlank(): AbsencePeriod {\r\n    return {\r\n      period: {\r\n        start: Dates.getToday(),\r\n        end: Dates.getToday(),\r\n        daysCount: 1,\r\n      },\r\n    };\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl() {\r\n    return \"salaxy-components/worker/AbsencePeriodsEditDialog.html\";\r\n  }\r\n\r\n  /** Calendar is clicked => Show edit dialog accorging to calendar data. */\r\n  public calendarClick(type: \"event\" | \"day\",  date: string, event: CalendarUiEvent) {\r\n    switch (type) {\r\n      case \"event\":\r\n        this.showEditDialog(event.data);\r\n        break;\r\n      case \"day\": {\r\n        const newItem = this.getBlank();\r\n        newItem.period.start = date;\r\n        newItem.period.end = date;\r\n        this.showEditDialog(newItem, true);\r\n        break;\r\n      }\r\n      default:\r\n        throw new Error(\"Not supported: \" + type);\r\n    }\r\n  }\r\n\r\n  /** Gets the needed logic for Edit dialog */\r\n  public getEditDialogLogic() {\r\n    return HolidaysLogic.getAbsencesEditDialogLogic();\r\n  }\r\n\r\n  /** Gets a total days calculation for different types. */\r\n  public getTotalDays(type: \"all\" | \"absencesPaid\" | \"absencesUnpaid\" | \"absencesHolidayAccrual\" | \"absencesNoHolidayAccrual\" = \"all\") {\r\n    const list = this.list.filter((x) => this.filter(x));\r\n    switch (type) {\r\n      case \"all\":\r\n        return Arrays.sum(list, (x) => x.period.daysCount);\r\n      case \"absencesPaid\":\r\n        return Arrays.sum(list.filter((x) => x.isPaid), (x) => x.period.daysCount);\r\n      case \"absencesUnpaid\":\r\n        return Arrays.sum(list.filter((x) => !x.isPaid), (x) => x.period.daysCount);\r\n      case \"absencesHolidayAccrual\":\r\n        return Arrays.sum(list.filter((x) => x.isHolidayAccrual), (x) => x.period.daysCount);\r\n      case \"absencesNoHolidayAccrual\":\r\n        return Arrays.sum(list.filter((x) => !x.isHolidayAccrual), (x) => x.period.daysCount);\r\n    }\r\n    return null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { CalculationListItem, DataMappersLogic, EmploymentLogic, EmploymentRelationSalaryPaymentMethod, EmploymentRelationTaxcard, EmploymentRelationType, Employments, EnumerationsLogic, Exportable, InsuranceCompany, Numeric, PensionCompany, TaxcardKind, Translations, UserSession } from \"@salaxy/core\";\r\nimport { AccountSettingsInSession, ContactAdvanced, ContactType, Country, Employment, EmploymentListItem, EmploymentSocialSecurityModel, WorkerAccount, Objects } from \"@salaxy/core\";\r\nimport { InternationalSocialSecurityException, PensionCalculation } from \"@salaxy/core\";\r\n\r\nimport { FileService, JsonSchemaService, SessionService, UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport type { EmploymentDetailsTabs } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { EmploymentTaxcardsController } from \"./EmploymentTaxcardsController\";\r\n\r\n/**\r\n * CRUD functionality for Employment relation.\r\n */\r\nexport class EmploymentCrudController extends ApiCrudObjectController<Employment, EmploymentListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Employments\", \"SessionService\", \"FileService\", \"JsonSchemaService\", \"UiCrudHelpers\", \"UiHelpers\", \"$location\", \"$routeParams\", \"$timeout\"];\r\n\r\n  /** If true, the save/delete etc. buttons are not shown (they will come from the container / modal) */\r\n  public isModal: boolean;\r\n\r\n  /**\r\n   * If set, the Worker details component can show infromation about the latest taxcard in the view.\r\n   * This is not present in the employment, but taxcards controller may be present in the same view.\r\n   * @example\r\n   * In the Details.html view we set:\r\n   * <salaxy-employment-taxcards employment-id=\"$ctrl.current.id\" ng-ref=\"$ctrl.taxcardsController\"></salaxy-employment-taxcards>\r\n   */\r\n  public taxcardsController: EmploymentTaxcardsController;\r\n\r\n  private _currentTab = null;\r\n  constructor(\r\n    private fullApi: Employments,\r\n    private sessionService: SessionService,\r\n    private fileService: FileService,\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) {\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/workers\",\r\n      detailsUrl: this.detailsUrl || \"/employments/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Employments.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the taxcard type in employment.\r\n   * In set, shows a confirm dialog before committing the change.\r\n   */\r\n  public get taxcardType(): EmploymentRelationTaxcard {\r\n    return this.current.info.taxcard;\r\n  }\r\n  public set taxcardType(value: EmploymentRelationTaxcard) {\r\n    if (!this.current?.info || this.current.info.taxcard == value) {\r\n      return;\r\n    }\r\n    if ((this.current.info?.taxcard || EmploymentRelationTaxcard.Undefined) == EmploymentRelationTaxcard.Undefined) {\r\n      this.current.info.taxcard = value;\r\n      this.save();\r\n      return;\r\n    }\r\n    this.uiHelpers.showConfirm(\"SALAXY.UI_Terms.areYouSure\", \"SALAXY.NG1.WorkerDetailsComponent.taxCard.typeAreYouSure\").then((result) => {\r\n      if (result) {\r\n        this.current.info.taxcard = value;\r\n        this.save();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * For the tab UI control, returns the current tab, if defined in the path\r\n   * or set explicitly. Defaults to \"default\".\r\n   */\r\n  public get currentTab(): EmploymentDetailsTabs {\r\n    if (this._currentTab) {\r\n      return this._currentTab;\r\n    }\r\n    const supportedHashes: EmploymentDetailsTabs[] = [\"default\", \"calculations\", \"taxcards\", \"employment\", \"calcRows\", \"holidays\", \"absences\", \"records\"];\r\n    const hash: EmploymentDetailsTabs | undefined = (this.$location ? this.$location.hash() || \"\" : \"\").trim().toLowerCase() as EmploymentDetailsTabs | undefined;\r\n    return supportedHashes.indexOf(hash) > -1 ? hash : \"default\";\r\n  }\r\n  public set currentTab(value: EmploymentDetailsTabs) {\r\n    this._currentTab = value;\r\n  }\r\n\r\n  /** Returns true if the employer is a household employer (person as opposed to company). */\r\n  public get isHousehold() {\r\n    return this.sessionService.isInRole(\"person\");\r\n  }\r\n\r\n  /**\r\n   * Gets a description text for an employment relation\r\n   * @param employment The employment relation to describe.\r\n   */\r\n  public getEmploymentDescription(employment: Employment | EmploymentListItem): string {\r\n    if (EmploymentLogic.isListItem(employment)) {\r\n      return EmploymentLogic.getDescription(employment.otherPartyInfo, employment.data.type, employment.data.pensionCalculation);\r\n    }\r\n    return EmploymentLogic.getDescription(employment.personalInfo, employment.info?.type, employment.info?.pensionCalculation);\r\n  }\r\n\r\n  /**\r\n   * Gets a descriptive text on whether the employment is active or not.\r\n   * @param employment Employment relation to get the text for.\r\n   * @returns A text that describes whether the employment is active or not with the dates (start and end).\r\n   */\r\n  public getActiveText(employment: Employment | EmploymentListItem): string {\r\n    return EmploymentLogic.getActiveText(employment);\r\n  }\r\n\r\n  /**\r\n   * Gets the tax card info text for active taxcard.\r\n   */\r\n  public getTaxCardInfo(): {\r\n    /** Text that is shown to the end user. */\r\n    text: string,\r\n    /** If true, the taxcard is missing => show as error. */\r\n    isMissing: boolean,\r\n  } | undefined {\r\n    const result = {\r\n      text: Translations.get(\"SALAXY.UI_Terms.loading\"),\r\n      isMissing: false,\r\n    };\r\n    if (!this.current) {\r\n      return result;\r\n    }\r\n    if (this.current.info.taxcard == EmploymentRelationTaxcard.NoTaxCard) {\r\n      result.text = EnumerationsLogic.getEnumLabel(\"TaxcardKind\", TaxcardKind.NoTaxCard);\r\n      return result;\r\n    }\r\n    if (this.current.info.taxcard == EmploymentRelationTaxcard.TaxAtSource) {\r\n      result.text = EnumerationsLogic.getEnumLabel(\"EmploymentRelationTaxcard\", EmploymentRelationTaxcard.TaxAtSource);\r\n      result.text = `${result.text} ${Numeric.formatPercent(this.current.international.taxAtSource.percent * 100, null)}`;\r\n      return result;\r\n    }\r\n    if (!this.taxcardsController?.current) {\r\n      return result;\r\n    }\r\n    const taxcardData = this.taxcardsController.current;\r\n    const taxCard = taxcardData.active;\r\n    if (!taxCard && taxcardData.employmentTaxcard == EmploymentRelationTaxcard.Auto) {\r\n      result.text = EnumerationsLogic.getEnumLabel(\"TaxcardKind\", TaxcardKind.Auto);\r\n    } else {\r\n      const kind = taxCard ? taxCard.card.kind : TaxcardKind.Undefined;\r\n      result.isMissing = kind == TaxcardKind.Undefined;\r\n      if (kind === TaxcardKind.Undefined || kind === TaxcardKind.NoTaxCard || kind === TaxcardKind.NoWithholdingHousehold) {\r\n        result.text = EnumerationsLogic.getEnumLabel(\"TaxcardKind\", kind);\r\n      } else {\r\n        const percent = taxCard?.card?.taxPercent === 0 ? 0 : (taxCard?.card?.taxPercent || 60);\r\n        result.text = EnumerationsLogic.getEnumLabel(\"TaxcardKind\", kind) + \": \" + Numeric.formatPercent(percent);\r\n      }\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Gets a contact of specific type.\r\n   * @param type Type of contact to get. Use null to fetch any contact type (creates Default if requested).\r\n   * @param createIfNotExists If true creates the contact of given type if one does not exist.\r\n   * @returns Contact of given type or undefined if one is not found AND createIfNotExists is false.\r\n   */\r\n  public getContact(type: ContactType | null, createIfNotExists = true): ContactAdvanced | null {\r\n    return EmploymentLogic.getContact(this.current, type || ContactType.Default, createIfNotExists);\r\n  }\r\n\r\n  private _readOnlyDefaultContact = {};\r\n  /**\r\n   * Returns default contact as read only.\r\n   */\r\n  public get readOnlyDefaultContact() {\r\n    const contact = this.getContact(ContactType.Default) ?? {};\r\n    if (!Objects.equal(contact, this._readOnlyDefaultContact)) {\r\n        this._readOnlyDefaultContact = { ...contact };\r\n    }\r\n    return this._readOnlyDefaultContact;\r\n  }\r\n\r\n  /**\r\n   * Gets the text for a Taxcard type badge (short text in lists).\r\n   * Returns null if the badge should not be shown.\r\n   */\r\n  public getTaxcardBadge(cardType: EmploymentRelationTaxcard): string | null {\r\n    switch (cardType) {\r\n      case EmploymentRelationTaxcard.Auto:\r\n        return \"Auto\";\r\n      case EmploymentRelationTaxcard.Manual:\r\n        return \"Manual\";\r\n      case EmploymentRelationTaxcard.NoTaxCard:\r\n        return \"60%\";\r\n      case EmploymentRelationTaxcard.TaxAtSource:\r\n      default:\r\n        return EnumerationsLogic.getEnumLabel(\"EmploymentRelationTaxcard\", cardType);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Opens the new Employment relation wizard and if a new relation is created, moves the user to the details view.\r\n   */\r\n  public launchCreateEmploymentWizard() {\r\n    this.uiCrudHelpers.createNewEmployment().then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.$location.path(this.getDefaults().detailsUrl + result.item.id);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog for editing an existing employment.\r\n   * If user clicks OK, the changes are saved.\r\n   * @param employmentId - Identifier of the Workers employment.\r\n   * @param buttonTypes \"default\" shows standard save button,\r\n   * \"updateCalc\" shows two buttons \"ok\" for full calc update and \"ok-no-rows\" update without touching default rows.\r\n   * @param initialTab - Tab to open.\r\n   * @returns Dialog result. Note that OK result may be either \"ok\" or \"ok-no-rows\".\r\n   * The latter means that for calculation only worker info should be updated, not the default rows.\r\n   */\r\n  public openEditEmploymentDialog(employmentId: string, buttonTypes: \"default\" | \"updateCalc\", initialTab: EmploymentDetailsTabs = null) {\r\n    return this.uiCrudHelpers.openEditEmploymentDialog(employmentId, buttonTypes, initialTab);\r\n  }\r\n\r\n  /**\r\n   * Returns Exportable api for the used crud.\r\n   * @returns Exportable api.\r\n   */\r\n  public getExportable(): Exportable<Employment> {\r\n    return {\r\n      getExportMappers: () => DataMappersLogic.getMappers([\"Employment\", \"EmploymentListItem\"]),\r\n      getExportMapper: (id) => DataMappersLogic.getBuiltInMapper(id, this.jsonSchemaService.getCache()),\r\n      exporters: this.fileService.getDefaultExporters(),\r\n      getSingle: (item) => this.getApi().getSingle(item.id),\r\n      list: (maxCount?, notify?) => this.odataController.exportItems(maxCount ?? 0, notify),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Opens a list of employment relations in to a dialog window.\r\n   * Creates list of selected employments and updates taxcard to auto.\r\n   * @param items Optional array of currently loaded/visible items.\r\n   * The data.taxcard is updated so that the changes are refelected in the list.\r\n   */\r\n  public selectAutoTaxcardForEmployments(items?: EmploymentListItem[]) {\r\n    const employmentList: EmploymentListItem[] = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/WorkerList.html\",\r\n      employmentList,\r\n      {\r\n        title: \"SALAXY.NG1.PayrollComponent.createNewCalcDialog\",\r\n        okButtonText: \"SALAXY.NG1.WorkerListComponent.okButtonText\",\r\n        infoHtml: \"SALAXY.NG1.WorkerListComponent.infoText.html\"\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && employmentList.length > 0) {\r\n          const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n          let counter = 1;\r\n          employmentList.forEach(selectedItem => {\r\n            loader.setText(`${Translations.get(\"SALAXY.UI_Terms.isSaving\")} ${counter}/${employmentList.length}`);\r\n            this.fullApi.getSingle(selectedItem.id).then((fullEmployment) => {\r\n              fullEmployment.info.taxcard = EmploymentRelationTaxcard.Auto;\r\n              this.fullApi.save(fullEmployment).then((savedEmployment) => {\r\n                if (items) {\r\n                  const item = items.find(x => x.id === savedEmployment.id);\r\n                  if (item) {\r\n                    item.data.taxcard = savedEmployment.info.taxcard;\r\n                  }\r\n                }\r\n                counter++;\r\n                if (counter - 1 === employmentList.length) {\r\n                  loader.dismiss();\r\n                }\r\n              });\r\n            });\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Called when the type of pension calculation changes\r\n   * => Sets the PartialOwner and NoPensionRequired IncomeEarnerTypes accordingly.\r\n   */\r\n  public pensionCalculationChange() {\r\n    EmploymentLogic.resetModelFromPensionCalculation(this.current);\r\n  }\r\n\r\n  /** Gets the session - currently used for company type */\r\n  public get session(): UserSession {\r\n    return this.sessionService.session;\r\n  }\r\n\r\n  /** Called when the type of employment changes => Sets the income earner types accordingly. */\r\n  public employmentTypeChange(): void {\r\n    EmploymentLogic.resetModelFromType(this.current);\r\n  }\r\n\r\n  /** Gets the cached version of the social security selection. */\r\n  public get socSec() {\r\n    return this.uiHelpers.cache(this, \"socSec\",\r\n      () => this.getSocialSecurityModel(\r\n        this.sessionService.session?.settings, this.current.info.type, this.current.international.socialSecurity, this.current.info.pensionCalculation,\r\n        this.current.info.pensionCompany, this.current.info.insuranceCompany, this.current.international.socialSecurityExceptions),\r\n      () => this.current.info.type + this.current.international.socialSecurity + this.current.info.pensionCalculation\r\n        + this.current.info.pensionCompany + this.current?.info.insuranceCompany + this.current.international.socialSecurityExceptions\r\n    );\r\n  }\r\n\r\n  /** Gets or sets the current country. When setting, the \"foreign\" address is reset. When getting Finland (fi) is converted to null. */\r\n  public get country(): Country | null {\r\n    return this.current.international.country == Country.Fi ? null : this.current.international.country;\r\n  }\r\n  public set country(value: Country) {\r\n    this.current.international.country = value;\r\n    this.current.contacts = (this.current.contacts || []).filter(x => x.type != ContactType.Foreign);\r\n    const contact = this.getContact(ContactType.Foreign, true);\r\n    contact.country = value;\r\n  }\r\n\r\n  /**\r\n   * Gets the social security pensions model (available options) for the current selections.\r\n   * @param settings Account settings in the session\r\n   * @param type Type of employment relation selected\r\n   * @param socialSecurity Whether the person is in Finnish or foregion social security - or mixed\r\n   * @param pensionCalculation Type of Pension calculation: employee/TyEL or others (YEL, farmer etc.)\r\n   * @param pensionCompany Pension company (if several) that is selected.\r\n   * @param insuranceCompany Insurance company (if several) that is selected.\r\n   * @param socSecExceptions The selected social security exceptions (not subject to)\r\n   */\r\n  public getSocialSecurityModel(\r\n    settings: AccountSettingsInSession, type: EmploymentRelationType,\r\n    socialSecurity: \"default\" | \"foreign\" | \"mixed\", pensionCalculation: PensionCalculation,\r\n    pensionCompany: PensionCompany, insuranceCompany: InsuranceCompany,\r\n    socSecExceptions: InternationalSocialSecurityException[],\r\n  ): EmploymentSocialSecurityModel {\r\n    return EmploymentLogic.getSocialSecurityModel(settings, type, socialSecurity, pensionCalculation, pensionCompany, insuranceCompany, socSecExceptions);\r\n  }\r\n\r\n  /** Overrides the Save method so that it realoads the taxcards controller if present. */\r\n  public save(): Promise<WorkerAccount> {\r\n    return super.save().then((workerAccount) => {\r\n      if (this.taxcardsController) {\r\n        this.taxcardsController.reload();\r\n      }\r\n      return workerAccount;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets a tooltip that shows which fields are editied in the employment relation to be different\r\n   * from the worker account (what the registered Worker has input in their UI).\r\n   * @param inputName Name of the field in Contact or \"ibanNumber\".\r\n   * @returns Tooltip text if there is a diff and tooltip should be shown.\r\n   */\r\n  public getInputTooltip(inputName: \"email\" | \"telephone\" | \"street\" | \"postalCode\" | \"city\" | \"ibanNumber\"): string | undefined {\r\n    if (inputName == \"ibanNumber\") {\r\n      if (this.current.info.ibanNumber !== this.current.personalInfo.ibanNumber) {\r\n        return `Tilinumeroa on muokattu tähän työsuhteeseen. Rekisteröityneen työntekijän syöttämä arvo on \"${this.current.personalInfo.ibanNumber}\". Jos haluat käyttää työntekijän syöttämää arvoa, voit kopioida sen ja päivittää tiedon kenttään, tai tyhjentää kentän ja painaa Tallenna.`;\r\n      }\r\n      return undefined;\r\n    }\r\n    if (!EmploymentLogic.getContact(this.current, ContactType.EmployerOverride)) {\r\n      // If not originally overridden, we do not wish to show this (user is editing now).\r\n      return undefined;\r\n    }\r\n    const diff = EmploymentLogic.getContact(this.current, ContactType.EmployerOverride)?.[inputName];\r\n    const workerAccountValue = EmploymentLogic.getContact(this.current, ContactType.WorkerAccount)?.[inputName];\r\n    if (diff) {\r\n      return `Yhteystietoa on muokattu tähän työsuhteeseen. Rekisteröityneen työntekijän syöttämä arvo on \"${workerAccountValue}\"`;\r\n    }\r\n    return undefined;\r\n  }\r\n\r\n  /**\r\n   * Returns the true if the field is required for the more complex UI fields.\r\n   * @param inputName Name of the field in Contact address (currently email and telephone never required) or \"ibanNumber\".\r\n   * @returns True if required.\r\n   */\r\n  public isRequired(inputName: \"street\" | \"postalCode\" | \"city\" | \"ibanNumber\"): boolean {\r\n    if (inputName == \"ibanNumber\") {\r\n      if (this.current.info.salaryPaymentMethod != EmploymentRelationSalaryPaymentMethod.BankAccount) {\r\n        return false;\r\n      }\r\n      // Required if worker account is editable (this value is updated to Worker account) OR if worker account value is empty.\r\n      return !this.current.isRegistered || !this.current.personalInfo.ibanNumber;\r\n    }\r\n    // Address is required if Personal ID starts with 9 (keinohetu) AND the same as ibanNumber above (editable or worker account empty).\r\n    return this.isOtherIdentifier && (!this.current.isRegistered || !this.getContact(ContactType.WorkerAccount)[inputName]);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current personal ID is other identifier than Finnish Personal Identification Number (keinohetu).\r\n   */\r\n  public get isOtherIdentifier() {\r\n    return EmploymentLogic.isPersonalIdOther(this.current.identity.personalId);\r\n  }\r\n\r\n  private _otherEmployments: EmploymentListItem[] | \"loading\" | undefined;\r\n\r\n  /**\r\n   * Gets the list of other employments with this personal ID.\r\n   * First call starts the loading process and returns undefined.\r\n   * Once response is received, the getter returns an array of employments (list items).\r\n   */\r\n  public get otherEmployments(): EmploymentListItem[] | undefined {\r\n    if (!this.current) {\r\n      return undefined;\r\n    }\r\n    if (!this._otherEmployments) {\r\n      if (!this.current.personalInfo.officialId) {\r\n        this._otherEmployments = [];\r\n      } else {\r\n        this._otherEmployments = \"loading\";\r\n        this.fullApi.getOData({ $filter: `otherPartyInfo/officialId eq '${this.current.personalInfo.officialId}'` }).then((result) => {\r\n          this._otherEmployments = result.items.filter(x => x.id != this.current.id);\r\n        });\r\n      }\r\n    }\r\n    return this._otherEmployments == \"loading\" ? undefined : this._otherEmployments;\r\n  }\r\n\r\n  /** Provides the logic for worker calculations OData UI. */\r\n  public calcListLogic = {\r\n    /**\r\n     * Returns true if the calculation is for another employment relation than the current one.\r\n     * @param calc Calculation to evaluate.\r\n     * @returns True, if the calculation is for another employment relation.\r\n     */\r\n    isNotCurrentEmployment: (calc: CalculationListItem): boolean => {\r\n      return calc.data.employmentId !== this.currentId;\r\n    }\r\n  };\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, TaxcardListItem, Taxcard, Taxcards, WorkerCurrentTaxcards } from \"@salaxy/core\";\r\nimport { EditDialogKnownActions, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Helps listing current all tax cards for an employment relation (latest and previous ones).\r\n */\r\nexport class EmploymentTaxcardsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Taxcards\", \"UiHelpers\"];\r\n\r\n  /** The data after it has been loaded. Null if nothing is loaded yet.  */\r\n  public current: WorkerCurrentTaxcards;\r\n\r\n  /**\r\n   * View mode:\r\n   *\r\n   * - \"active\" only shows the active taxcard.\r\n   * - \"list\" only shows the history list.\r\n   * - \"all\" (default) shows both active and history.\r\n   */\r\n  public mode: \"active\" | \"list\" | \"all\";\r\n\r\n  /**\r\n   * Today is explicitly defined, so that it can be changed in testing.\r\n   */\r\n  public today = Dates.getToday();\r\n\r\n  /** If true, does not show the save / current buttons - the parent must show them. */\r\n  public hideButtons: boolean;\r\n\r\n  /**\r\n   * Event that is called when a taxcard is saved and the parent UI probably needs to be refreshed.\r\n   * @example <salaxy-employment-taxcards employment-id=\"$ctrl.current.employmentId\" on-save=\"$ctrl.refresh()\"></salaxy-employment-taxcards>\r\n   */\r\n   public onSave: (eventData: {\r\n    /** The selected item. */\r\n    item: Taxcard,\r\n  }) => void;\r\n\r\n  private _employmentId: string;\r\n\r\n  /** Creates a new EmploymentTaxcardsController */\r\n  constructor(\r\n    private taxcards: Taxcards,\r\n    private uiHelpers: UiHelpers) { }\r\n\r\n  /** Initializes the controller. */\r\n  public $onInit = () => {\r\n    this.mode = this.mode || \"all\";\r\n  };\r\n\r\n  /**\r\n   * Defines to which employment relation the functionality is bound to.\r\n   * The setter also starts the loading process.\r\n   */\r\n  public get employmentId(): string {\r\n    return this._employmentId;\r\n  }\r\n  public set employmentId(value: string) {\r\n    this._employmentId = value;\r\n    this.reload();\r\n  }\r\n\r\n  /** List of taxcards after it has been loaded. Null if nothing is loaded yet. */\r\n  public get list(): TaxcardListItem[] {\r\n    if (this.current) {\r\n      return this.current.list;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  /** Reloads the data from the server. */\r\n  public reload() {\r\n    this.current = null;\r\n    if (this.employmentId) {\r\n      this.taxcards.getEmploymentTaxcards(this.employmentId, this.today).then((result) => {\r\n        this.current = result;\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Removes a taxcard from the list and does a refresh.\r\n   * @param id Taxcard id.\r\n   */\r\n  public deleteTaxCard(id: string) {\r\n    this.taxcards.delete(id).then(() => {\r\n      this.reload();\r\n    });\r\n  }\r\n\r\n  /** Edit income log. */\r\n  public editIncomeLog() {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/worker/taxcard-income-log.html\", this.current.active,\r\n    { editable: true }, \"lg\").then((result) => {\r\n      if (result.action === EditDialogKnownActions.Ok) {\r\n        const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.pleaseWait\");\r\n        this.taxcards.save(this.current.active).then((taxcard) => {\r\n          loader.dismiss();\r\n          this.reload();\r\n          if (this.onSave) {\r\n            this.onSave({ item: taxcard});\r\n          }\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AccountSettingsInSession, ContactType, Country, Employment, EmploymentListItem, EmploymentLogic, EmploymentRelationTaxcard, EmploymentRelationType, EmploymentSocialSecurityModel, Employments, InsuranceCompany, InternationalSocialSecurityException, PensionCalculation, PensionCompany, TaxCard2019Logic, Taxcard, TaxcardKind, UserSession, Validation } from \"@salaxy/core\";\r\n\r\nimport { EditDialogParameters, SessionService, UiHelpers, WizardService, WizardStep } from \"../../services\";\r\nimport { WizardController } from \"../bases\";\r\n\r\n/**\r\n * Wizard for creating a new employment relation.\r\n */\r\nexport class EmploymentWizardController extends WizardController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"$scope\", \"EditDialogParameters\", \"WizardService\", \"SessionService\", \"UiHelpers\", \"Employments\"];\r\n\r\n  /** Form data validity: This is bound from the form tag in the view. */\r\n  public formDataValidity: boolean;\r\n\r\n  /** The employment relation that is being added. */\r\n  public current: Employment;\r\n\r\n  /** Taxcard that is optionally added. */\r\n  public taxcard: Taxcard;\r\n\r\n  /**\r\n   * Creates a new WizardController with dependency injection.\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    $scope: angular.IScope,\r\n    private editDialogParameters: EditDialogParameters<Employment>,\r\n    wizardService: WizardService,\r\n    private sessionService: SessionService,\r\n    private uiHelpers: UiHelpers,\r\n    private api: Employments,\r\n  ) {\r\n    super($scope, wizardService);\r\n  }\r\n\r\n  /**\r\n   * Initialization of the controller\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n    this.wizardService.setSteps(this.getWizardSteps());\r\n    if (!this.editDialogParameters) {\r\n      throw new Error(\"No editDialogParameters coming in.\");\r\n    }\r\n    this.current = this.editDialogParameters.current;\r\n  }\r\n\r\n  /** Returns true if user can go forward in the wizard  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        if (this.formDataValidity === true || this.formDataValidity === null) {\r\n          return true;\r\n        }\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Gets the session - currently used for company type */\r\n  public get session(): UserSession {\r\n    return this.sessionService.session;\r\n  }\r\n\r\n  /** Called when the type of employment changes => Sets the income earner types accordingly. */\r\n  public employmentTypeChange(): void {\r\n    EmploymentLogic.resetModelFromType(this.current);\r\n    EmploymentLogic.setSalaryDefaultRows(this.current.info.type, this.current.work);\r\n  }\r\n\r\n  /** Gets the cached version of the social security selection. */\r\n  public get socSec() {\r\n    return this.uiHelpers.cache(this, \"socSec\",\r\n      () => this.getSocialSecurityModel(\r\n        this.sessionService.session?.settings, this.current.info.type, this.current.international.socialSecurity, this.current.info.pensionCalculation,\r\n        this.current.info.pensionCompany, this.current.info.insuranceCompany, this.current.international.socialSecurityExceptions),\r\n      () => this.current.info.type + this.current.international.socialSecurity + this.current.info.pensionCalculation\r\n        + this.current.info.pensionCompany + this.current?.info.insuranceCompany + this.current.international.socialSecurityExceptions\r\n    );\r\n  }\r\n\r\n  /** Gets or sets the current country. When setting, the \"foreign\" address is reset. When getting Finland (fi) is converted to null. */\r\n  public get country(): Country | null {\r\n    return this.current.international.country == Country.Fi ? null : this.current.international.country;\r\n  }\r\n  public set country(value: Country) {\r\n    this.current.international.country = value;\r\n    this.current.contacts = (this.current.contacts || []).filter(x => x.type != ContactType.Foreign);\r\n    const contact = this.getContact(ContactType.Foreign);\r\n    contact.country = value;\r\n  }\r\n\r\n  /**\r\n   * Gets the social security pensions model (available options) for the current selections.\r\n   * @param settings Account settings in the session\r\n   * @param type Type of employment relation selected\r\n   * @param socialSecurity Whether the person is in Finnish or foregion social security - or mixed\r\n   * @param pensionCalculation Type of Pension calculation: employee/TyEL or others (YEL, farmer etc.)\r\n   * @param pensionCompany Pension company (if several) that is selected.\r\n   * @param insuranceCompany Insurance company (if several) that is selected.\r\n   * @param socSecExceptions The selected social security exceptions (not subject to)\r\n   */\r\n  public getSocialSecurityModel(\r\n    settings: AccountSettingsInSession, type: EmploymentRelationType,\r\n    socialSecurity: \"default\" | \"foreign\" | \"mixed\", pensionCalculation: PensionCalculation,\r\n    pensionCompany: PensionCompany, insuranceCompany: InsuranceCompany,\r\n    socSecExceptions: InternationalSocialSecurityException[],\r\n  ): EmploymentSocialSecurityModel {\r\n    return EmploymentLogic.getSocialSecurityModel(settings, type, socialSecurity, pensionCalculation, pensionCompany, insuranceCompany, socSecExceptions);\r\n  }\r\n\r\n  /**\r\n   * Called when the type of pension calculation changes\r\n   * => Sets the PartialOwner and NoPensionRequired IncomeEarnerTypes accordingly.\r\n   */\r\n  public pensionCalculationChange() {\r\n    EmploymentLogic.resetModelFromPensionCalculation(this.current);\r\n  }\r\n\r\n  private _otherEmployments: EmploymentListItem[] | \"loading\" | undefined;\r\n\r\n  private _otherEmploymentsLastPersonalId: string | undefined;\r\n\r\n  /**\r\n   * Gets the list of other employments with this personal ID.\r\n   * First call starts the loading process and returns undefined.\r\n   * Once response is received, the getter returns an array of employments (list items).\r\n   * The method also initializes the taxcard (if personal ID is changed and valid).\r\n   */\r\n  public get otherEmployments(): EmploymentListItem[] | undefined {\r\n    if (!this.current) {\r\n      return undefined;\r\n    }\r\n    this.checkPersonalId();\r\n    return this._otherEmployments == \"loading\" ? undefined : this._otherEmployments;\r\n  }\r\n\r\n  /**\r\n   * Gets a description text for an employment relation\r\n   * @param employment The employment relation to describe.\r\n   */\r\n  public getEmploymentDescription(employment: Employment | EmploymentListItem): string {\r\n    if (EmploymentLogic.isListItem(employment)) {\r\n      return EmploymentLogic.getDescription(employment.otherPartyInfo, employment.data.type, employment.data.pensionCalculation);\r\n    }\r\n    return EmploymentLogic.getDescription(employment.personalInfo, employment.info?.type, employment.info?.pensionCalculation);\r\n  }\r\n\r\n  /**\r\n   * Gets a descriptive text on whether the employment is active or not.\r\n   * @param employment Employment relation to get the text for.\r\n   * @returns A text that describes whether the employment is active or not with the dates (start and end).\r\n   */\r\n  public getActiveText(employment: Employment | EmploymentListItem): string {\r\n    return EmploymentLogic.getActiveText(employment);\r\n  }\r\n\r\n  /**\r\n   * Populates worker with test data.\r\n   * @param useRealPersonaIdRange If true, uses the real personal id range instead of artificial ID range (\"keinohetu\": last 3 numbers start with 9).\r\n   */\r\n  public populateWithTestData(useRealPersonaIdRange = false) {\r\n    EmploymentLogic.populateWithTestData(this.current, useRealPersonaIdRange);\r\n  }\r\n\r\n  /**\r\n   * Deletes a calculation row.\r\n   * @param rowIndex - Zero based row index of the row that should be deleted.\r\n   */\r\n  public deleteSalaryDefaultsRow(rowIndex: number) {\r\n    this.current.work.salaryDefaults.splice(rowIndex);\r\n  }\r\n\r\n  /** Returns true if the employer is a household employer (person as opposed to company). */\r\n  public get isHousehold() {\r\n    return this.sessionService.isInRole(\"person\");\r\n  }\r\n\r\n  /** Worker wizard configuration */\r\n  public getWizardSteps(): WizardStep[] {\r\n    const commonSteps = [{\r\n      title: \"SALAXY.NG1.WorkerWizardComponent.step1.title\",\r\n      view: \"salaxy-components/worker/EmploymentWizard/identity.html\",\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1.WorkerWizardComponent.step2.title\",\r\n      view: \"salaxy-components/worker/EmploymentWizard/person.html\",\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1.WorkerWizardComponent.step3.title\",\r\n      view: \"salaxy-components/worker/EmploymentWizard/type.html\",\r\n    }];\r\n    if (this.isHousehold){\r\n      return commonSteps;\r\n    }\r\n    return [\r\n      ...commonSteps,\r\n      {\r\n        title: \"SALAXY.NG1.WorkerWizardComponent.step4.title\",\r\n        view: \"salaxy-components/worker/EmploymentWizard/work.html\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.WorkerWizardComponent.step5.title\",\r\n        view: \"salaxy-components/worker/EmploymentWizard/tax.html\",\r\n      }\r\n    ];\r\n  }\r\n\r\n  /** Saves the taxcard and closes the dialog. */\r\n  public saveAndClose(closeFunction: (result: any) => any) {\r\n    let card = this.taxcard;\r\n    if (this.current.info.taxcard != EmploymentRelationTaxcard.Manual\r\n      || !card.card.kind || card.card.kind === TaxcardKind.Undefined || card.card.kind === TaxcardKind.Auto) {\r\n      // For clarity, remove the taxcard if it is not manual or if there is no meaningful kind.\r\n      card = null;\r\n    }\r\n    closeFunction({\r\n      action: \"ok\",\r\n      employment: this.current,\r\n      taxcard: card,\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the contact information of the worker. Contact of the specific type will be created if one does not exist.\r\n   * @param type Type of contact info.\r\n   * @returns Contact object for data binding.\r\n   */\r\n  public getContact(type = ContactType.Default) {\r\n    return EmploymentLogic.getContact(this.current, type, true);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the current personal ID is other identifier than Finnish Personal Identification Number (keinohetu).\r\n   */\r\n  public get isOtherIdentifier(){\r\n    return EmploymentLogic.isPersonalIdOther(this.current.identity.personalId);\r\n  }\r\n\r\n  private checkPersonalId(): void {\r\n    const personalId = this.current.identity.personalId;\r\n    if (!personalId || !Validation.isPersonalIdFi(personalId)) {\r\n      if (this._otherEmployments || this._otherEmploymentsLastPersonalId) {\r\n        this._otherEmploymentsLastPersonalId = undefined;\r\n        this._otherEmployments = undefined;\r\n      }\r\n      return;\r\n    }\r\n    if (this.taxcard?.card?.personalId !== personalId) {\r\n      this.current.info.taxcard = EmploymentRelationTaxcard.Auto;\r\n      this.taxcard = TaxCard2019Logic.getBlank(personalId, TaxcardKind.Auto);\r\n    }\r\n    if (this._otherEmploymentsLastPersonalId != this.current.identity.personalId) {\r\n      this._otherEmploymentsLastPersonalId = this.current.identity.personalId;\r\n      this._otherEmployments = \"loading\";\r\n      this.api.getOData({ $filter: `otherPartyInfo/officialId eq '${ this.current.identity.personalId }'` }).then((result) => {\r\n        this._otherEmployments = result.items.filter(x => x.id != this.current.id);\r\n      });\r\n    }\r\n  }\r\n}\r\n","import { Arrays, Brand, Dates, HolidayAccrualEntry, HolidayAccrualSource, HolidayYear, HolidayYears, Translations } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\n/**\r\n * Controls holiday accrual (lomapäivien kertymä) of the annual leave for a selected holiday period.\r\n */\r\nexport class HolidayYearAccrualController extends ListControllerBase<HolidayYear, HolidayAccrualEntry> {\r\n\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new ListControllerBaseBindings();\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"HolidayYears\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  constructor(\r\n    private holidayYears: HolidayYears,\r\n    uiHelpers: UiHelpers,\r\n  ) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /** List of items */\r\n  public get list(): HolidayAccrualEntry[] {\r\n    if (!this.parent || !this.parent.accrual || !this.parent.accrual.months) {\r\n      return [];\r\n    }\r\n    return this.parent.accrual.months;\r\n  }\r\n\r\n  /** Creating of a new item. */\r\n  public getBlank(): HolidayAccrualEntry {\r\n    return {};\r\n  }\r\n\r\n  /**\r\n   * Saves changes to the parent object using the CRUD API.\r\n   */\r\n  public saveParent(): void {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.isSaving\");\r\n    this.holidayYears.save(this.parent)\r\n      .then((saved) => {\r\n        this.parent = saved;\r\n        loader.dismiss();\r\n      });\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl() {\r\n    return \"salaxy-components/worker/holidays/HolidayYearAbsencesEditDialog.html\";\r\n  }\r\n\r\n  /** Chart config for accrual overview. */\r\n  public getChartConfig(list: HolidayAccrualEntry[]) {\r\n    return this.uiHelpers.cache(this, \"accrualChart\",() => this.createConfig(list));\r\n  }\r\n\r\n  private createConfig(list: HolidayAccrualEntry[]): {type: string, data: any, options: any} {\r\n    const data = [[], []];\r\n    const labels = [];\r\n    const startSaldo: number = (this.parent.accrual as any).startSaldo;\r\n    let cumulative = startSaldo;\r\n\r\n    for (const entry of list) {\r\n      cumulative += entry.daysAccrued;\r\n      const startOfMonth = Dates.startEnd(\"today\",\"start-month\");\r\n      data[0].push(entry.month <= startOfMonth ? cumulative : null);\r\n      data[1].push(entry.month >= startOfMonth ? cumulative : null);\r\n      labels.push(Translations.get(`SALAXY.ENUM.CalendarMonth.month${Dates.getMonth(entry.month)}.short`));\r\n    }\r\n    return {\r\n      type: \"line\",\r\n      data: {\r\n        labels,\r\n        datasets: [\r\n          {\r\n            label: Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.accumulated\"),\r\n            data: [\r\n              ...data[0]\r\n            ],\r\n            borderColor: \"rgb(159,192,209)\",\r\n            fill: {\r\n              target: \"origin\",\r\n                above: \"rgb(234,241,245, 0.5)\"\r\n            },\r\n            elements: {\r\n              point: {\r\n                backgroundColor: \"rgb(234,241,245)\"\r\n              }\r\n            },\r\n          },\r\n          {\r\n            label: Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.futureEstimate\"),\r\n            data: [\r\n              ...data[1]\r\n            ],\r\n            fill: {\r\n              target: \"origin\",\r\n                above: \"rgb(248,248,248, 0.5)\"\r\n            },\r\n            elements: {\r\n              point: {\r\n                backgroundColor: \"rgb(248,248,248)\"\r\n              }\r\n            },\r\n          }\r\n        ]\r\n      },\r\n      options: {\r\n        scales: {\r\n          y: {\r\n            ticks: {\r\n              beginAtZero: true,\r\n            },\r\n          },\r\n        },\r\n        plugins: {\r\n          legend: {\r\n            display: false\r\n          }\r\n        }\r\n      },\r\n    };\r\n  }\r\n  /** Gets the color for the row avatar */\r\n  public getRowColor(row: HolidayAccrualEntry | \"start\" | \"total\") {\r\n    if (row === \"start\" || row === \"total\") {\r\n      return Brand.getBrandColor(\"primary\");\r\n    }\r\n    if (row.month > this.getThisMonth()) {\r\n      return \"#ddd\";\r\n    }\r\n    if (row.month === this.getThisMonth()) {\r\n      return Brand.getBrandColor(\"danger\");\r\n    }\r\n    return Brand.getBrandColor(\"primary\");\r\n  }\r\n\r\n  /** Gets this month: The first date of this month */\r\n  public getThisMonth() {\r\n    return Dates.getToday().substr(0, 8) + \"01\";\r\n  }\r\n\r\n  /**\r\n   * Returns the notes if available or, if not, description text based on the source.\r\n   */\r\n  public getAccrualNotes(row: HolidayAccrualEntry) {\r\n    if (row.notes) {\r\n      return row.notes;\r\n    }\r\n    switch (row.source) {\r\n      case HolidayAccrualSource.Manual:\r\n        return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.manual\");\r\n      case HolidayAccrualSource.CalcDraft:\r\n        return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.calcDraft\");\r\n      case HolidayAccrualSource.CalcPaid:\r\n        return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.calcPaid\");\r\n      case HolidayAccrualSource.Initial:\r\n      default:\r\n        if (row.month === this.getThisMonth()) {\r\n          return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.defaultThisMonth\");\r\n        }\r\n        if (row.month > this.getThisMonth()) {\r\n          return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.defaultEstimate\");\r\n        }\r\n        return Translations.get(\"SALAXY.NG1.HolidayYearAccrualComponent.holidayAccrualSource.default\");\r\n    }\r\n  }\r\n\r\n  /** Gets calculations related to holiday accruals */\r\n  public getAccrualCalculations() {\r\n    const startSaldo: number = (this.parent.accrual as any).startSaldo;\r\n    const result = {\r\n      accrual: Arrays.sum(this.list, (x) => x.daysAccrued),\r\n      accrualToday: Arrays.sum(this.list.filter((x) => x.month < Dates.getToday()), (x) => x.daysAccrued),\r\n      total: 0,\r\n      totalToday: 0,\r\n    };\r\n    result.total = result.accrual + startSaldo;\r\n    result.totalToday = result.accrualToday + startSaldo;\r\n    return result;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  Dates, HolidayCode, HolidaysLogic, HolidaySpecification, HolidaySpecificationForYear,\r\n  HolidayYear, HolidayYears, Translations, WageBasis, CalendarSeries,\r\n  InputEnumOption,\r\n  HolidayPayCalculation\r\n} from \"@salaxy/core\";\r\n\r\nimport { UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Plain CRUD controller for HolidayYears.\r\n */\r\nexport class HolidayYearCrudController extends ApiCrudObjectController<HolidayYear, never> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"HolidayYears\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"UiCrudHelpers\",\r\n  ];\r\n\r\n  /** View type currently shown in the UI */\r\n  public viewType: \"overview\" | \"parameters\" | \"accrual\" | \"holidays\" | \"absenses\" = \"overview\";\r\n\r\n  /**\r\n   * If employmentId is set, the controller fetches all the holiday years for this employment relation.\r\n   * The dafault of them will then be set to model and they can be switched easily e.g. using dropdown.\r\n   */\r\n  public employmentHolidayYears: HolidayYear[] = [];\r\n\r\n  /** If getHolidayYears() is called, the result will be here */\r\n  public allYears: HolidayYear[];\r\n\r\n  /**\r\n   * The date for which the UI is rendered. Default is today.\r\n   * For employment holiday years (WorkerHolidays or CalcWorktime), set this to salary period begin\r\n   * => Specifies the the holiday year to choose by default from all holiday years that Worker has:\r\n   * If the date is Jan-March will show the previous year, April-Dec will show the current year.\r\n   */\r\n  public forDate: string;\r\n\r\n  /** Parameters related to holiday report (lomalista). */\r\n  public reportParams: {\r\n    /** Today's date: Set this for testing how user interface is rendered (which view is presented) at different times of year. */\r\n    today: string;\r\n    /** Start date of the view: Can be get/set directly by the view */\r\n    start: string,\r\n    /** Start date of the view: Can be get/set directly by the view */\r\n    end: string,\r\n    /** Start date of the holiday year. Typically, just get: Set by the reportYear setter */\r\n    yearStart: string,\r\n    /** End date of the holiday year. Typically, just get: Set by the reportYear setter */\r\n    yearEnd: string,\r\n    /** Years that can be selected. */\r\n    years: number[];\r\n    /** Underlying field of reportView */\r\n    _view: \"summerPeriod\" | \"winterPeriod\" | \"otherPeriod\" | \"list\",\r\n    /** Underlying field of reportYear */\r\n    _year: number,\r\n  };\r\n\r\n  public isAccrualView = false;\r\n\r\n  private _employmentId: string;\r\n\r\n  private visualizationCache;\r\n  constructor(\r\n    private fullApi: HolidayYears,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /** Controller initialization */\r\n  public $onInit() {\r\n    this.forDate = this.forDate || Dates.getToday();\r\n    const thisYear = Dates.getYear(this.forDate);\r\n    this.reportParams = {\r\n      today: this.forDate,\r\n      years: Array.from({ length: 5 }, (v, ix) => thisYear + 1 - ix),\r\n    } as any;\r\n    // Fetching reportView initializes the rest of parameters with default values. Comment for lint if necessary.\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    const necessaryInitCall = this.reportView;\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/workers\",\r\n      detailsUrl: this.detailsUrl || \"/workers/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Holidays.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Sets the employment ID and if it is different then starts the loading of the Absences object to that employment ID.\r\n   */\r\n  public set employmentId(value: string) {\r\n    if (this._employmentId === value) {\r\n      return;\r\n    }\r\n    this.employmentHolidayYears = [];\r\n    if (!value) {\r\n      if (this._employmentId) {\r\n        this._employmentId = null;\r\n        this.model = null;\r\n        this.reload();\r\n      }\r\n      return;\r\n    }\r\n    this._employmentId = value;\r\n    this.fullApi.getForEmployment(value).then((result) => {\r\n      this.employmentHolidayYears = result;\r\n      this.setYear();\r\n    });\r\n  }\r\n  /** Gets the employment ID */\r\n  public get employmentId() {\r\n    return this._employmentId;\r\n  }\r\n\r\n  /** Initializes the holidays for the current Worker */\r\n  public initHolidays(spec: HolidaySpecification,) {\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.HolidayYearComponent.dialog.creatingYearHolidays\"));\r\n    this.fullApi.initForEmployment(this.employmentId, spec)\r\n      .then((years) => {\r\n        this.employmentHolidayYears = years;\r\n        this.setYear();\r\n        loader.dismiss();\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets the holiday logic for the given specification.\r\n   * @param spec The specification for which the logic is calculated.\r\n   * @returns The logic object that can be used in the UI.\r\n   */\r\n  public getHolidayLogic(spec: HolidaySpecificationForYear) {\r\n    const logic =  {\r\n      /** If true, has holiday years => A warning for overwrite should be shown. */\r\n      hasData: !!this.current,\r\n      /** True if the accrual is based on law. Ui binds to this. */\r\n      accrualByLaw: !spec.accrualFixed,\r\n      /**\r\n       * Sets the accrualFixed value based on accrualByLaw value\r\n       * @param itemData The data that is being edited (current in view)\r\n       */\r\n      accrualByLawChanged: (itemData: HolidaySpecificationForYear) => {\r\n        itemData.accrualFixed = logic.accrualByLaw ? null : (itemData.code === HolidayCode.TemporaryTimeOff ? 2 : 2.5);\r\n      },\r\n      /**\r\n       * Sets the accrualByLaw value based on accrualFixed value\r\n       * @param itemData The data that is being edited (current in view)\r\n       */\r\n      accrualFixedChanged: (itemData: HolidaySpecificationForYear) => {\r\n        if (!itemData.accrualFixed) {\r\n          itemData.accrualFixed = null; // in case of empty string or 0.\r\n          logic.accrualByLaw = true;\r\n        }\r\n      },\r\n      /**\r\n       * Business logic for field visibility\r\n       * @param itemData The data that is being edited (current in view)\r\n       * @param field Name of the field for which the visibility is calculated.\r\n       */\r\n      getVisibility: (itemData: HolidaySpecificationForYear, field: \"accrualFixed\" | \"compensation\" | \"bonusMethod\" | \"bonusPercent\" | \"startSaldo\") => {\r\n        switch (field) {\r\n          case \"startSaldo\":\r\n          case \"accrualFixed\":\r\n          case \"bonusMethod\":\r\n            return itemData.code === HolidayCode.Permanent14Days\r\n              || itemData.code === HolidayCode.Permanent35Hours\r\n              || itemData.code === HolidayCode.TemporaryTimeOff\r\n              ;\r\n          case \"compensation\":\r\n            return itemData.code === HolidayCode.HolidayCompensation\r\n              || itemData.code === HolidayCode.HolidayCompensationIncluded\r\n              ;\r\n          case \"bonusPercent\":\r\n            return itemData.code === HolidayCode.Permanent14Days\r\n              || itemData.code === HolidayCode.Permanent35Hours\r\n              || itemData.code === HolidayCode.TemporaryTimeOff\r\n              || itemData.code === HolidayCode.HolidayCompensation\r\n              || itemData.code === HolidayCode.HolidayCompensationIncluded\r\n              ;\r\n          default:\r\n            return true;\r\n        }\r\n      },\r\n      getholidayPayCalculationOptions:(itemData: HolidaySpecificationForYear): InputEnumOption[] => {\r\n        return this.uiHelpers.cache(this, \"holidayPayCalculationOptions\", () => {\r\n          switch (itemData?.code) {\r\n            case HolidayCode.Permanent14Days:\r\n              if(itemData.wageBasis === WageBasis.Monthly) {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.normalMonthlyPay.label\"), value: HolidayPayCalculation.NormalMonthlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              } else {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.averageHourlyPay.label\"), value: HolidayPayCalculation.AverageHourlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.averageDailyPay.label\"), value: HolidayPayCalculation.AverageDailyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              }\r\n            case HolidayCode.Permanent35Hours:\r\n              if(itemData.wageBasis === WageBasis.Monthly) {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.normalMonthlyPay.label\"), value: HolidayPayCalculation.NormalMonthlyPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.percentageBasedPay.label\"), value: HolidayPayCalculation.PercentageBasedPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              } else {\r\n                return [\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.percentageBasedPay.label\"), value: HolidayPayCalculation.PercentageBasedPay},\r\n                  {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n                ];\r\n              }\r\n            case HolidayCode.TemporaryTimeOff:\r\n              return [\r\n                {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.holidayCompensation.label\"), value: HolidayPayCalculation.HolidayCompensation},\r\n                {text: Translations.get(\"SALAXY.ENUM.HolidayPayCalculation.otherPay.label\"), value: HolidayPayCalculation.OtherPay},\r\n              ];\r\n              break;\r\n            default:\r\n              return [];\r\n          }\r\n        });\r\n      }\r\n    };\r\n    return logic;\r\n  }\r\n\r\n  /** Shows the Init holidays dialog for initializing the holiday years for the given worker */\r\n  public showInitHolidays() {\r\n    if (!this.employmentId) {\r\n      throw Error(\"Employment ID not defined in showInitHolidays().\");\r\n    }\r\n    const loader = this.uiHelpers.showLoading(Translations.get(\"SALAXY.NG1.HolidayYearComponent.dialog.loadingDefaults\"));\r\n    this.fullApi.getDefaultSpecForEmployment(this.employmentId).then((defaults) => {\r\n\r\n      loader.dismiss();\r\n      const logic = this.getHolidayLogic(defaults);\r\n\r\n      this.uiHelpers.openEditDialog(\"salaxy-components/worker/holidays/WorkerHolidaysInitDialog.html\", defaults, logic, \"lg\")\r\n        .then((result) => {\r\n          if (result.action === \"ok\") {\r\n            this.initHolidays(result.item);\r\n          }\r\n        });\r\n    });\r\n  }\r\n\r\n  /** Gets the visualisation data for the selected holiday year. */\r\n  public getYearVisualisation() {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!this.visualizationCache || this.visualizationCache.year !== this.current.year || this.visualizationCache.employmentId !== this.current.employmentId) {\r\n      this.visualizationCache = HolidaysLogic.getYearVisualisation(this.current);\r\n    }\r\n    return this.visualizationCache;\r\n  }\r\n\r\n  /** Gets a total days calculation for different types. */\r\n  public getTotalDays(type: \"all\" | \"summer\" | \"winter\" | \"holidaysSaldoEnd\" | \"holidaysSaldoStart\" = \"all\", year: HolidayYear = null) {\r\n    year = year || this.current;\r\n    return HolidaysLogic.getPlannedLeavesCount(year, type);\r\n  }\r\n\r\n  /**\r\n   * Gets items visibility based on properties of the selected holiday year.\r\n   * @param elements Logical name of group of items in teh view.\r\n   */\r\n  public getVisibility(elements: \"accrual\" | \"compensation\" | \"hourly\") {\r\n    const code = this.current.spec.code;\r\n    switch (elements) {\r\n      case \"accrual\":\r\n        return code === HolidayCode.Permanent14Days\r\n          || code === HolidayCode.Permanent35Hours\r\n          || code === HolidayCode.TemporaryTimeOff\r\n          ;\r\n      case \"hourly\":\r\n        return this.current.spec.wageBasis === WageBasis.Hourly\r\n          || this.current.spec.wageBasis === WageBasis.PerformanceBased\r\n          ;\r\n      case \"compensation\":\r\n        return code === HolidayCode.HolidayCompensation\r\n          || code === HolidayCode.HolidayCompensationIncluded\r\n          ;\r\n      default:\r\n        return true;\r\n    }\r\n  }\r\n\r\n  /** For the reporting purposes, gets or sets the holiday year as year number. */\r\n  public get reportYear(): number {\r\n    if (!this.reportParams._year) {\r\n      let year = Dates.getYear(this.reportParams.today || \"today\");\r\n      if (Dates.getMonth(this.reportParams.today || \"today\") < 3) {\r\n        year--;\r\n      }\r\n      this.reportYear = year; // Call the setter to init related values\r\n    }\r\n    return this.reportParams._year;\r\n  }\r\n  public set reportYear(value: number) {\r\n    value = Math.round(Number(value));\r\n    if (!value || value < 2018 || value > 2100) {\r\n      return;\r\n    }\r\n    this.reportParams._year = value;\r\n    if (this.reportView !== \"otherPeriod\") {\r\n      this.reportParams.yearStart = value + \"-01-01\";\r\n      this.reportParams.yearEnd = (value + 1) + \"-04-30\";\r\n    } else {\r\n      this.reportParams.yearStart = value + \"-05-01\";\r\n      this.reportParams.yearEnd = (value + 1) + \"-04-30\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the report view that is currently shown.\r\n   */\r\n  public get reportView(): \"summerPeriod\" | \"winterPeriod\" | \"otherPeriod\" | \"list\" {\r\n    if (!this.reportParams._view) {\r\n      // Use the setter for setting the defaault value so that dependent fields are also set\r\n      const month = Dates.getMonth(this.reportParams.today || \"today\");\r\n      const year = Dates.getYear(this.reportParams.today || \"today\");\r\n      if (year === this.reportYear) {\r\n        if (month < 10) { this.reportView = \"summerPeriod\"; }\r\n        else { this.reportView = \"winterPeriod\"; }\r\n      } else if (year - 1 === this.reportYear) {\r\n        if (month < 4) { this.reportView = \"winterPeriod\"; } // Current holidays\r\n        else { this.reportView = \"list\"; }\r\n      } else {\r\n        this.reportView = \"list\";\r\n      }\r\n    }\r\n    return this.reportParams._view;\r\n  }\r\n  public set reportView(value: \"summerPeriod\" | \"winterPeriod\" | \"otherPeriod\" | \"list\") {\r\n    this.reportParams._view = value;\r\n    switch (value) {\r\n      case \"summerPeriod\":\r\n        this.reportParams.start = this.reportYear + \"-05-01\";\r\n        this.reportParams.end = this.reportYear + \"-09-30\";\r\n        break;\r\n      case \"winterPeriod\":\r\n        this.reportParams.start = this.reportYear + \"-10-01\";\r\n        this.reportParams.end = this.reportYear + 1 + \"-04-30\";\r\n        break;\r\n      case \"otherPeriod\":\r\n        this.reportParams.start = this.reportYear + \"-01-01\";\r\n        this.reportParams.end = this.reportYear + 1 + \"-04-30\";\r\n        break;\r\n      default:\r\n        this.reportParams.start = this.reportParams.yearStart;\r\n        this.reportParams.end = this.reportParams.yearEnd;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns missing holiday year.\r\n   */\r\n  public get missingHolidayYear() {\r\n    if (!this.employmentHolidayYears || this.employmentHolidayYears.length == 0) {\r\n      // Not holiday years in use.\r\n      return null;\r\n    }\r\n    const today = Dates.getToday();\r\n    const missingYear = 1 + (Dates.getMonth(today) > 3 ? Dates.getYear(today) : Dates.getYear(today) - 1);\r\n    if (this.employmentHolidayYears.find((x) => x.year == missingYear)) {\r\n      return null;\r\n    }\r\n\r\n    return missingYear;\r\n  }\r\n\r\n  /**\r\n   * Saves a holiday year based on calendar input and updates the value in allYears property.\r\n   */\r\n  public saveYear(itemToSave: HolidayYear): Promise<void> {\r\n    const loader = this.uiHelpers.showLoading(`${Translations.get(\"SALAXY.NG1.HolidayYearComponent.dialog.saving\")}...`);\r\n    return this.api.save(itemToSave).then((savedValue) => {\r\n      angular.copy(savedValue, itemToSave);\r\n      loader.dismiss();\r\n      return;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Show an edit dialog for the holiday year.\r\n   * @param year The holiday year to update.\r\n   */\r\n  public showEditDialog(year: HolidayYear): void {\r\n    /* HACK: The edit dialog is not optimal, as it shows the entire edit worker dialog. Should be a separate edit holidays / holiday periods dialog. */\r\n    this.uiCrudHelpers.openEditEmploymentDialog(year.employmentId, \"default\", \"holidays\").then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.getHolidayYears(true);\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows worker selection dialog and after that opens selected workers employment dialog.\r\n   */\r\n  public showAddWorker() {\r\n    const workerList = [];\r\n    this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/calc/WorkerSelect.html\",\r\n      workerList,\r\n      {\r\n        title: \"SALAXY.NG1.PayrollComponent.validate.addWorker\",\r\n      }).then((result) => {\r\n        if (result.action === \"ok\" && result.item.length == 1) {\r\n          this.uiCrudHelpers.openEditEmploymentDialog(result.item[0].id, \"default\", \"holidays\").then((result) => {\r\n            if (result.action === \"ok\") {\r\n              this.getHolidayYears(true);\r\n            }\r\n          });\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets the full holiday years for all Workers for reporting purposes\r\n   * @param keepView If true, does not reset the view based on the incoming data.\r\n   * If true, you should make sure the year does not change because then view will be invalid for the year\r\n   * I.e. should be true only for reload scenarios.\r\n   */\r\n  public getHolidayYears(keepView = false) {\r\n    this.fullApi.getForYear(this.reportYear).then((result: HolidayYear[]) => {\r\n      this.allYears = result;\r\n      if (!keepView) {\r\n        this.reportParams._view = null;\r\n        // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n        const getViewForInitAfterYearChange = this.reportView;\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Maps an array of HolidayYear to calendar series. */\r\n  public mapToCalendar = (years: HolidayYear[]): CalendarSeries[] => {\r\n    return years.map((hy) => {\r\n      return {\r\n        key: hy.id,\r\n        title: hy.workerSnapshot.displayName,\r\n        description: `${Translations.get(\"SALAXY.NG1.HolidayYearComponent.planned\")} ${this.getTotalDays(\"all\", hy)}${Translations.get(\"SALAXY.NG1.HolidayYearComponent.date\")}, ${Translations.get(\"SALAXY.NG1.HolidayYearComponent.accumulation\")} ${hy.accrual.endSaldo}`,\r\n        avatar: hy.workerSnapshot,\r\n        data: hy,\r\n        events: hy.leaves.planned.map((leave) => ({\r\n          start: leave.period.start,\r\n          end: leave.period.end,\r\n          summary: leave.notes || `${Translations.get(\"SALAXY.NG1.HolidayYearComponent.holiday\")} ${leave.period.daysCount} ${Translations.get(\"SALAXY.NG1.HolidayYearComponent.days\")}`,\r\n          data: leave,\r\n        }\r\n        )),\r\n      };\r\n    });\r\n  };\r\n\r\n  /**\r\n   * Returns true, if two objects are different.\r\n   * @param obj1 First object to compare\r\n   * @param obj2 Second object to compare\r\n   */\r\n  public isChanged(obj1, obj2): boolean {\r\n    return !angular.equals(obj1, obj2);\r\n  }\r\n\r\n  /**\r\n   * Sets the view type for the holiday year.\r\n   * @param isAccrualView  If true, the view is set to this.currentYear +1, otherwise to this.currentYear.\r\n   */\r\n  public setAccrualView(isAccrualView: boolean): void {\r\n    this.isAccrualView = isAccrualView;\r\n  }\r\n\r\n  /**\r\n   * Sets the correct holiday year for the view based on the current date.\r\n   * This is for planning/consuming holidays.\r\n   */\r\n  public setYear(): void {\r\n    const date = this.forDate;\r\n    const holidayYear = date > Dates.getDate(Dates.getYear(date), 4, 30) ? Dates.getYear(date) : Dates.getYear(date) - 1;\r\n    this.model = this.employmentHolidayYears.find((x) => x.year === holidayYear) || this.employmentHolidayYears[0];\r\n  }\r\n}\r\n","import { AnnualLeave, Arrays, Dates, HolidaysLogic, HolidayYear } from \"@salaxy/core\";\r\n\r\nimport { EditDialogResult, UiHelpers } from \"../../services\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\nclass HolidayYearHolidaysControllerBindings extends ListControllerBaseBindings {\r\n  /** If true, will format the table with class table-condensed. Later may add some other condensed formatting. */\r\n  public condensed = \"<\";\r\n\r\n  /** Date filter start value. Will be compared to period end date. */\r\n  public filterStart = \"<\";\r\n\r\n  /** Date filter end value. Will be compared to period start date. */\r\n  public filterEnd = \"<\";\r\n}\r\n\r\n/**\r\n * Controls the planned holidays list (lomakirjanpito / lomakalenteri) for a selected holiday year.\r\n */\r\nexport class HolidayYearHolidaysController  extends ListControllerBase<HolidayYear, AnnualLeave> {\r\n\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new HolidayYearHolidaysControllerBindings();\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /** If true, will format the table with class table-condensed. Later may add some other condensed formatting. */\r\n  public condensed: boolean;\r\n\r\n  /** Date filter start value. Will be applied to period start dates. */\r\n  public filterStart: string;\r\n\r\n  /** Date filter end value. Will be applied to period end dates. */\r\n  public filterEnd: string;\r\n\r\n  constructor(uiHelpers: UiHelpers) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /** List of items */\r\n  public get list(): AnnualLeave[] {\r\n    if (!this.parent || !this.parent.leaves || !this.parent.leaves.planned) {\r\n      return [];\r\n    }\r\n    return this.parent.leaves.planned;\r\n  }\r\n\r\n  /**\r\n   * Filter that is applied to the list when displayed.\r\n   * This is done in view: Does not apply to list property, but does affect getTotalDays().\r\n   * @param value Item in the list\r\n   */\r\n  public filter = (value: AnnualLeave) => {\r\n    if (this.filterEnd && value.period.start > this.filterEnd) {\r\n      return false;\r\n    }\r\n    if (this.filterStart && value.period.end < this.filterStart) {\r\n      return false;\r\n    }\r\n    return true;\r\n  };\r\n\r\n  /** Creating of a new item. */\r\n  public getBlank(): AnnualLeave {\r\n    return {\r\n      period: {\r\n        start: Dates.getToday(),\r\n        end: Dates.getToday(),\r\n        daysCount: 1,\r\n      },\r\n    };\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl() {\r\n    return \"salaxy-components/worker/holidays/HolidayYearHolidaysEditDialog.html\";\r\n  }\r\n\r\n  /** Logic for edit dialog. */\r\n  public getEditDialogLogic() {\r\n    return {\r\n      /** Updates the workdays count */\r\n      updatePeriodDays: (current: AnnualLeave) => {\r\n        if (current.period.start > current.period.end) {\r\n          current.period.end = current.period.start;\r\n        }\r\n        if (current.period.start && current.period.end) {\r\n          if (current.period.days) {\r\n            current.period.days = Dates.getVacationDays(current.period.start, current.period.end);\r\n            current.period.daysCount = current.period.days.length;\r\n          } else {\r\n            current.period.daysCount = Dates.getVacationDays(current.period.start, current.period.end).length;\r\n          }\r\n        }\r\n      },\r\n\r\n      /** Sets the days array in period to enable days selection UI. */\r\n      setDaysSelection: (period: AnnualLeave) => {\r\n        period.period.days = Dates.getVacationDays(period.period.start, period.period.end);\r\n        period.period.daysCount = period.period.days.length;\r\n      },\r\n      /**\r\n       * For example, when parent year is 2024:\r\n       * - minDate is 2024-01-01\r\n       * - maxDate is 2025-04-30\r\n       */\r\n      minDate: Dates.getDate(this.parent.year, 1, 1),\r\n      maxDate: Dates.getDate(this.parent.year + 1, 4, 30)\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog.\r\n   * @param item Annual leave to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: AnnualLeave | \"new\", isNew = false) {\r\n    if (!item) {\r\n      throw new Error(\"showEditDialog called without a parameter.\");\r\n    }\r\n    if (item === \"new\") {\r\n      isNew = true;\r\n      item = this.getBlank();\r\n    }\r\n\r\n    const handleResult = (result: EditDialogResult<AnnualLeave>) => {\r\n      if (result.action === \"ok\" || result.action === \"ok-no-save\" ) {\r\n        if (isNew) {\r\n          this.list.push(result.item);\r\n        }\r\n        if (( isNew || result.hasChanges) && result.action !== \"ok-no-save\") {\r\n          this.commit();\r\n        }\r\n      } else if (result.action === \"delete\" || result.action === \"delete-no-save\") {\r\n        if (!isNew) {\r\n          this.delete(item as AnnualLeave);\r\n          if (result.action !== \"delete-no-save\" ) {\r\n            this.commit();\r\n          }\r\n        }\r\n      }\r\n    };\r\n\r\n    this.uiHelpers.openEditDialog(this.getEditDialogTemplateUrl(), item, this.getEditDialogLogic()).then((result) => {\r\n      /**\r\n       * parent is currently used holiday year\r\n       * Check if the holiday is outside the general holiday season (1.5.parent.year -30.4.parent.year + 1). Outside of general holiday season means 1.1.parent.year - 30.4.parent.year\r\n       */\r\n\r\n      if( (result.action === \"ok\" || result.action === \"ok-no-save\") && ( result.item.period.start >= Dates.getDate(this.parent.year,1,1) && result.item.period.end <= Dates.getDate(this.parent.year,4,30))) {\r\n        this.uiHelpers.showConfirm(\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.dialogHeading\", \"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.dialogText\")\r\n        .then((confirmResult: boolean) => {\r\n          if (confirmResult) {\r\n            handleResult(result);\r\n          }\r\n        });\r\n      } else {\r\n        handleResult(result);\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Gets the description text for the planned holiday. */\r\n  public getDescription(row: AnnualLeave) {\r\n    if (row.notes) {\r\n      return row.notes;\r\n    }\r\n    return row.period.start < `${this.parent.year}-10-1` ? \"Kesäloma\" : \"Talviloma\";\r\n  }\r\n\r\n  /** Gets a total days calculation for different types. */\r\n  public getTotalDays(type: \"all\" | \"summer\" | \"winter\" | \"holidaysSaldoEnd\" | \"holidaysSaldoStart\" | \"filtered\" = \"all\") {\r\n    // HACK: jos periodi menee yli filterin tästä tulee väärä tulos (alku ennen filtterin alkua, loppu filtterin alun jälkeen).\r\n    if (type === \"filtered\") {\r\n      return Arrays.sum(this.list.filter((x) => this.filter(x)), (x) => x.period.daysCount);\r\n    }\r\n    if (this.parent) {\r\n      return HolidaysLogic.getPlannedLeavesCount(this.parent, type);\r\n    }\r\n    return null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AnnualLeavePayment, AnnualLeavePaymentKind, Dates, HolidaysLogic, HolidayYear, LegalEntityType, Avatar, HolidayCode, HolidayBonusPaymentMethod } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, ReportsService } from \"../../services\";\r\n\r\nimport { ListControllerBase, ListControllerBaseBindings } from \"../bases\";\r\n\r\ntype AnnualLeavePaymentWithAvatar = AnnualLeavePayment & { avatar: Avatar };\r\n/**\r\n * Controls the annual leave payments: HolidayCompensation, HolidayBonus and HolidaySalary.\r\n * These payments are typically fetched from paid calculations automatically,\r\n * but may also be marked paid manually. Also, in client-side logic, payments are fetched\r\n * optionally from Draft calculations.\r\n */\r\nexport class HolidayYearPaidController  extends ListControllerBase<HolidayYear, AnnualLeavePayment> {\r\n\r\n  /** Bindings for components that use this controller */\r\n  public static bindings = new ListControllerBaseBindings();\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"ReportsService\"\r\n  ];\r\n\r\n  /** Total holiday pays */\r\n  public totals: {\r\n    /** Total calculation  */\r\n    total: AnnualLeavePayment,\r\n    /** Start saldo of the payments */\r\n    startSaldo: AnnualLeavePayment,\r\n\r\n    /** End saldo of the payments. */\r\n    endSaldo: AnnualLeavePayment,\r\n  };\r\n\r\n  /** Total bonus */\r\n  public bonusTotals: {\r\n    /** Total calculation  */\r\n    total: AnnualLeavePayment,\r\n    /** Start saldo of the payments */\r\n    startSaldo: AnnualLeavePayment,\r\n\r\n    /** End saldo of the payments. */\r\n    endSaldo: AnnualLeavePayment,\r\n  };\r\n\r\n  constructor(\r\n    uiHelpers: UiHelpers,\r\n    private reports: ReportsService,\r\n  ) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /** Gets the worker ID for the current holiday year. */\r\n  public get workerId(): string {\r\n    if (!this.parent || !this.parent.workerSnapshot) {\r\n      return null;\r\n    }\r\n    return this.parent.workerSnapshot.id;\r\n  }\r\n\r\n  /** Gets the employment ID for the current holiday year. */\r\n  public get employmentId(): string {\r\n    if (!this.parent || !this.parent.workerSnapshot) {\r\n      return null;\r\n    }\r\n    return this.parent.employmentId;\r\n  }\r\n\r\n  /**\r\n   * List of items fetched from the holiday year,\r\n   * cached to the controller level, except when workerId changes.\r\n   */\r\n  public get list(): AnnualLeavePayment[] {\r\n    if (!this.parent || !this.parent.leaves || !this.parent.leaves.paid) {\r\n      return [];\r\n    }\r\n    return this.getLeavesPaid();\r\n  }\r\n\r\n  /**\r\n   * Returns true if the bonus should be paid for the employee.\r\n   */\r\n  public get shoudPayBonus(): boolean {\r\n    if (!this.parent?.spec) {\r\n      return false;\r\n    }\r\n\r\n    return ( this.parent.spec.code === HolidayCode.Permanent14Days\r\n          || this.parent.spec.code  === HolidayCode.Permanent35Hours\r\n          || this.parent.spec.code  === HolidayCode.TemporaryTimeOff\r\n    ) && this.parent.spec.bonusMethod !== HolidayBonusPaymentMethod.None;\r\n  }\r\n\r\n/**\r\n * List of paid holidays.\r\n */\r\n  private getLeavesPaid(): AnnualLeavePayment[] {\r\n      for (const paidLeave of this.parent.leaves.paid) {\r\n          (paidLeave as any).avatar ??= {};\r\n          if (paidLeave.holidayBonus > 0 && !(paidLeave.holidaySalary > 0 || paidLeave.holidayCompensation > 0)) {\r\n            angular.copy(HolidaysLogic.getPaidBonusAvatar(\"row\", paidLeave), (paidLeave as any).avatar);\r\n          }\r\n          else\r\n          {\r\n            angular.copy(HolidaysLogic.getPaidCalculationAvatar(\"row\", paidLeave), (paidLeave as any).avatar);\r\n          }\r\n      }\r\n\r\n      this.totals ??= {} as any;\r\n      this.totals.startSaldo = this.copyAnnualLeavePayment(HolidaysLogic.getPaidHolidaysCalculation(this.parent, \"startSaldo\"), this.totals.startSaldo);\r\n      this.totals.total = this.copyAnnualLeavePayment(HolidaysLogic.getPaidHolidaysCalculation(this.parent, \"total\"), this.totals.total);\r\n      this.totals.endSaldo = this.copyAnnualLeavePayment(HolidaysLogic.getPaidHolidaysCalculation(this.parent, \"endSaldo\"), this.totals.endSaldo);\r\n\r\n      this.bonusTotals ??= {} as any;\r\n      this.bonusTotals.startSaldo = this.copyAnnualLeavePayment(HolidaysLogic.getPaidBonusCalculation(this.parent, \"startSaldo\"), this.bonusTotals.startSaldo);\r\n      this.bonusTotals.total = this.copyAnnualLeavePayment(HolidaysLogic.getPaidBonusCalculation(this.parent, \"total\"), this.bonusTotals.total);\r\n      this.bonusTotals.endSaldo = this.copyAnnualLeavePayment(HolidaysLogic.getPaidBonusCalculation(this.parent, \"endSaldo\"), this.bonusTotals.endSaldo);\r\n      return this.parent.leaves.paid;\r\n  }\r\n\r\n  private copyAnnualLeavePayment(source: AnnualLeavePayment, target: AnnualLeavePayment):  AnnualLeavePayment{\r\n    target ??= {} as any;\r\n    (target as any).avatar ??= {} as any;\r\n\r\n    angular.copy((source as any).avatar, (target as any).avatar);\r\n    target.holidayBonus = source.holidayBonus;\r\n    target.holidayCompensation = source.holidayCompensation;\r\n    target.holidayDays = source.holidayDays;\r\n    target.holidaySalary = source.holidaySalary;\r\n\r\n    return target;\r\n  }\r\n\r\n  /** Creating of a new item. */\r\n  public getBlank(): AnnualLeavePaymentWithAvatar {\r\n    return {\r\n      kind: AnnualLeavePaymentKind.Undefined,\r\n      avatar: {\r\n        displayName: \"Käsin syötetty korjaus\",\r\n        description: null,\r\n        color: \"rgb(74, 146, 233)\",\r\n        initials: \"edit\",\r\n        entityType: LegalEntityType.Company,\r\n      },\r\n      date: Dates.getToday(),\r\n      period: Dates.getDateRange(Dates.getToday(), Dates.getToday()),\r\n      holidayBonus: null,\r\n      holidayCompensation: null,\r\n      holidayDays: null,\r\n      holidaySalary: null,\r\n    };\r\n  }\r\n\r\n  /** Gets calculations preview pdf url based on given id */\r\n  public getPdfUrl(calcId: string) {\r\n    return this.reports.getPdfUrlForCalc(\"salarySlip\", calcId, true);\r\n  }\r\n\r\n  /** Logic for edit dialog. */\r\n  public getEditDialogLogic() {\r\n    return {\r\n      /** Updates the workdays count */\r\n      updatePeriodDays: (current: AnnualLeavePayment) => {\r\n        if (current.period.start > current.period.end) {\r\n          current.period.end = current.period.start;\r\n        }\r\n        if (current.period.start && current.period.end) {\r\n          if (current.period.days) {\r\n            current.period.days = Dates.getVacationDays(current.period.start, current.period.end);\r\n            current.period.daysCount = current.period.days.length;\r\n          } else {\r\n            current.period.daysCount = Dates.getVacationDays(current.period.start, current.period.end).length;\r\n          }\r\n          current.holidayDays = current.period.daysCount;\r\n        }\r\n      },\r\n      updateDaysCount: (current: AnnualLeavePayment) => {\r\n        current.period.daysCount = current.holidayDays;\r\n      },\r\n      getPdfUrl: (calcId: string): string => this.getPdfUrl(calcId)\r\n    };\r\n  }\r\n\r\n  /** Template for edit UI that is shown in a modal dialog. */\r\n  public getEditDialogTemplateUrl() {\r\n    return \"salaxy-components/worker/holidays/HolidayYearPaidEditDialog.html\";\r\n  }\r\n}","import angular from \"angular\";\r\n\r\nimport { TaxCard2019Logic, Taxcard, TaxcardKind, Taxcards, WorkerCurrentTaxcards } from \"@salaxy/core\";\r\nimport { UiCrudHelpers, UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * Helps listing current account tax cards (latest and previous ones)\r\n * and also the employers that are using the latest taxcards.\r\n */\r\nexport class MyTaxcardsController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Taxcards\", \"UiCrudHelpers\", \"UiHelpers\"];\r\n\r\n  /** The data after it has been loaded. Null if nothing is loaded yet.  */\r\n  public current: WorkerCurrentTaxcards;\r\n\r\n  /** The current active tab. */\r\n  public currentTab: string;\r\n\r\n  /** Creates a new MyTaxcardsController */\r\n  constructor(\r\n    private taxcards: Taxcards,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    private uiHelpers: UiHelpers,\r\n    ) {}\r\n\r\n  /** Initializes the controller. */\r\n  public $onInit = () => {\r\n    this.reload();\r\n  };\r\n\r\n  /** Reloads the data from the server. */\r\n  public reload() {\r\n    this.current = null;\r\n    this.taxcards.getMyTaxcards().then((result) => {\r\n      this.current = result;\r\n      if (this.current?.active) {\r\n        this.currentTab = \"calcs\";\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Removes a taxcard from the list and does a refresh.\r\n   * @param id Taxcard id.\r\n   */\r\n  public deleteTaxCard(id: string) {\r\n    this.taxcards.delete(id).then(() => {\r\n      this.reload();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the users automatic shared taxcard as ON or if already set refreshes the taxcard from tax authorities.\r\n   */\r\n  public setSharedAutoForSelf(): void {\r\n    if (this.current.active?.card.kind === TaxcardKind.Auto) {\r\n      this.uiCrudHelpers.refreshAutoTaxcard(this.current.active.id).then((_taxcards) => {\r\n        this.reload();\r\n      });\r\n    } else {\r\n      const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.loadingTitle\", \"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.loadingText\");\r\n      this.taxcards.setAuto(this.current.personalId).then((x) => {\r\n        if (x == null) {\r\n          loader.dismiss();\r\n          this.uiHelpers.showAlert(\"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.alertTitle\", \"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.alertTextAutoCard\");\r\n        } else {\r\n          this.reload();\r\n          loader.dismiss();\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets the chart type that should be shown.\r\n   */\r\n  public get chartType(): \"full\" | \"pie\" | \"none\" {\r\n    if (!this.current) {\r\n      return \"none\";\r\n    }\r\n    if (this.current.active.card.incomeLimit) {\r\n      return \"full\";\r\n    }\r\n    return \"pie\";\r\n  }\r\n\r\n  /**\r\n   * Gets main chart configuration for <salaxy-chart>\r\n   * @param taxcard current taxcard\r\n   */\r\n  public getMainChartConfig(taxcard: Taxcard) {\r\n    return this.uiHelpers.cache(this, \"mainChartConfig\",\r\n      () => TaxCard2019Logic.getMainChartV2(taxcard),\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(taxcard));\r\n  }\r\n\r\n  /**\r\n   * Gets pie chart configuration for <salaxy-chart>\r\n   * @param taxcard current taxcard\r\n   */\r\n  public getPieChartConfig(taxcard: Taxcard) {\r\n    return this.uiHelpers.cache(this, \"pieChartConfig\",\r\n      () => TaxCard2019Logic.getPieChartDataV2(taxcard),\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(taxcard));\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, Taxcard, TaxCard2019Logic, TaxCardIncomeType, TaxcardKind, Translations } from \"@salaxy/core\";\r\n\r\nimport { SessionService } from \"../../services\";\r\n\r\n/**\r\n * UI logic for adding new manual taxcards.\r\n * Designed to be used in a modal dialog: You must pass personal ID for the Worker in EditDialogParameters.\r\n */\r\nexport class TaxcardManualEditController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"SessionService\"];\r\n\r\n  /** The current taxcard that is being edited. */\r\n  public current: Taxcard;\r\n\r\n  /** Edit taxcard form: Used for checking the validity. */\r\n  public editForm: angular.IFormController;\r\n\r\n  /**\r\n   * Today is explicitly defined, so that it can be changed in testing.\r\n   */\r\n  public today = Dates.getToday();\r\n\r\n  /** If true, shows the today edit box (in test only) */\r\n  public showToday = false;\r\n\r\n  /** Settings / instructions for the \"Create new\" UI (show/hide inputs, formatting etc). */\r\n  public addNewUi = {\r\n    /** If true, shown the 1st tax percent */\r\n    showTaxPercent: false,\r\n    /** If true, shown the income limit AND 2nd tax pecent. */\r\n    showIncomeLimit: false,\r\n    /** If true, the require the income limit AND 2nd tax percent (default yearly). */\r\n    requireIncomeLimit: false,\r\n    /** If true, shows input for previous salaries paid. */\r\n    showPreviousSalariesPaid: false,\r\n    /** If true, the tax percents etc. cannot be edited (no taxcard household or 60%).*/\r\n    readonly: false,\r\n    /** Options for the start date: currently min and max dates. */\r\n    startDateOptions: null as null | {\r\n      minDate: string,\r\n      maxDate: string,\r\n    },\r\n    /**\r\n     * Years that are allowed in the year selection:\r\n     * Current year + next year in December, previous year in January.\r\n     */\r\n    yearsAllowed: null as null | number[],\r\n  };\r\n\r\n  constructor(\r\n    private sessionService: SessionService,\r\n  ) {\r\n    // Dependency injection\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    if (this.sessionService.isInRole(\"company\")) {\r\n      delete this.taxcardKindOptions.noWithholdingHousehold;\r\n    }\r\n  }\r\n\r\n  /** Returns true if one of the edit forms is shown ad if it is valid. */\r\n  public get isFormValid() {\r\n    return this.editForm?.$valid && (this.current?.card?.kind || \"undefined\") != \"undefined\";\r\n  }\r\n\r\n  /**\r\n   * Gets a row for data binding of external salaries paid outside Salaxy system.\r\n   * Will create the row if it does not exist. The save method will remove any empty rows.\r\n   */\r\n  public get previousSalariesRow() {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!this.current.incomeLog) {\r\n      this.current.incomeLog = [];\r\n    }\r\n    if (!this.current.incomeLog.find((x) => x.type === TaxCardIncomeType.ExternalSalaries)) {\r\n      this.current.incomeLog.push({\r\n        type: TaxCardIncomeType.ExternalSalaries,\r\n        id: null,\r\n        description: Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.previousSalariesRow\"),\r\n        startDate: this.today,\r\n        endDate: this.today,\r\n        income: null,\r\n        tax: null,\r\n      });\r\n    }\r\n    return this.current.incomeLog.find((x) => x.type === TaxCardIncomeType.ExternalSalaries);\r\n  }\r\n\r\n  /** Taxcard kinds that should be allowed for the new manual taxcard. */\r\n  public taxcardKindOptions = {\r\n    \"defaultYearly\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.defaultYearly\",\r\n    \"replacement\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.replacement\",\r\n    \"noTaxCard\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noTaxCard\",\r\n    // This is removed from company role in init (only for household employers).\r\n    \"noWithholdingHousehold\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noWithholdingHousehold\",\r\n  };\r\n\r\n  /**\r\n   * Resets the current taxcard as new (when the kind changes).\r\n   * @param kind If specified, reset the taxcard to the given type.\r\n   */\r\n  public resetAsNew(kind?: TaxcardKind) {\r\n    this.setCurrent(TaxCard2019Logic.getBlank(this.current.card.personalId, kind, null, this.today));\r\n    this.updateUISettings();\r\n  }\r\n\r\n  /** Handles change of the year in the years dropdown. */\r\n  public yearChanged() {\r\n    this.setCurrent(TaxCard2019Logic.getBlank(this.current.card.personalId, this.current.card.kind, this.current.card.forYear, this.today));\r\n    this.updateUISettings();\r\n  }\r\n\r\n  /** Sets the current item value keeping the original reference. */\r\n  private setCurrent(newItem: Taxcard) {\r\n    angular.copy(newItem, this.current);\r\n    this.updateUISettings();\r\n  }\r\n\r\n  /** Defines which fields to show/hide, require etc. in the view */\r\n  private updateUISettings() {\r\n    const settings = {\r\n      showTaxPercent: false,\r\n      showIncomeLimit: false,\r\n      requireIncomeLimit: false,\r\n      showPreviousSalariesPaid: false,\r\n      readonly: false,\r\n      startDateOptions: null,\r\n      yearsAllowed: null,\r\n    };\r\n    if (!this.current) {\r\n      this.addNewUi = settings;\r\n      return;\r\n    }\r\n    const todayYear = Dates.getYear(this.today);\r\n    const month = Dates.getMonth(this.today);\r\n    let yearsAllowed: number[];\r\n    if (month === 1) {\r\n      yearsAllowed = [todayYear, todayYear - 1];\r\n    } else if (month === 12) {\r\n      yearsAllowed = [todayYear, todayYear + 1];\r\n    } else {\r\n      yearsAllowed = [todayYear];\r\n    }\r\n    if (yearsAllowed.indexOf(this.current.card.forYear) < 0) {\r\n      if (!this.current.id) {\r\n        this.current.card.forYear = todayYear;\r\n      }\r\n    }\r\n    const forYear = this.current.card.forYear;\r\n    yearsAllowed = yearsAllowed.length < 2 ? null : yearsAllowed; // In the UI, the selection is not shown if there is only one item to select.\r\n    settings.showTaxPercent = true;\r\n\r\n    switch (this.current.card.kind) {\r\n      case TaxcardKind.Auto:\r\n        settings.showTaxPercent = false;\r\n        break;\r\n      case TaxcardKind.NoTaxCard:\r\n      case TaxcardKind.NoWithholdingHousehold:\r\n        settings.readonly = true;\r\n        break;\r\n      case TaxcardKind.Undefined:\r\n        settings.readonly = true;\r\n        settings.showTaxPercent = false;\r\n        break;\r\n      case TaxcardKind.DefaultYearly:\r\n        settings.showIncomeLimit = true;\r\n        settings.showPreviousSalariesPaid = true;\r\n        settings.requireIncomeLimit = true;\r\n        settings.yearsAllowed = yearsAllowed;\r\n        break;\r\n      case TaxcardKind.Replacement:\r\n        settings.showIncomeLimit = true;\r\n        settings.showPreviousSalariesPaid = true;\r\n        settings.yearsAllowed = yearsAllowed;\r\n        settings.startDateOptions = {\r\n            minDate: Dates.asJSDate(forYear + \"-01-01\"),\r\n            maxDate: Dates.asJSDate(forYear + \"-11-31\"),\r\n          };\r\n        break;\r\n    }\r\n    this.addNewUi = settings;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates, EmploymentRelationTaxcard, IUserObjectIndex, PersonAccount, Taxcard, TaxCard2019Logic, TaxCardIncomeType, TaxcardKind, TaxcardListItem, Taxcards, Translations } from \"@salaxy/core\";\r\n\r\nimport { EditDialogKnownActions, SessionService, UiCrudHelpers, UiHelpers, UploadService } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * UI logic for viewing, adding new and editing taxcards.\r\n * You can edit a single taxcard (model to object, id or parent controller).\r\n * Note that creating a new taxcards requires setting Personal ID.\r\n * You can create a new one by setting the model as \"new\" (full add new UI) as well as null (quick buttons).\r\n */\r\nexport class TaxcardCrudController extends ApiCrudObjectController<Taxcard, TaxcardListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Taxcards\",\r\n    \"UiHelpers\",\r\n    \"UiCrudHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"UploadService\",\r\n    \"SessionService\",\r\n    \"$timeout\",\r\n  ];\r\n\r\n  /** Mode is either \"pro\" (for admin / PRO-ui) or \"default\" */\r\n  public mode: \"pro\" | \"default\";\r\n\r\n  /**\r\n   * True if the taxcard is uploaded for the current Worker account (as opposed to Worker of an Employer) .\r\n   * This should typically not be set: It will be set by init (if current account is Worker) and personalId (if 'self' or personal id matches).\r\n   */\r\n  public isSelf: boolean;\r\n\r\n  /** The upload progress 0-100 */\r\n  public uploadProgress: number = null;\r\n\r\n  /** Edit taxcard form: Used for checking the validity. */\r\n  public editForm: angular.IFormController;\r\n\r\n  /**\r\n   * Today is explicitly defined, so that it can be changed in testing.\r\n   */\r\n  public today = Dates.getToday();\r\n\r\n  /** Settings / instructions for the \"Create new\" UI (show/hide inputs, formatting etc). */\r\n  public addNewUi: any;\r\n\r\n  /** If true, does not show the save / current buttons - the parent must show them. */\r\n  public hideButtons: boolean;\r\n\r\n  /** Type of employment taxcard */\r\n  public employmentRelationTaxcardType: EmploymentRelationTaxcard = EmploymentRelationTaxcard.Auto;\r\n\r\n  /** Possible taxcard kinds that should be available for current role to select. */\r\n  public kindSelection: string;\r\n\r\n  /**\r\n   * Event that is called when a taxcard is saved and the parent UI probably needs to be refreshed.\r\n   * @example <salaxy-taxcard-details model=\"$ctrl.current.active\" personal-id=\"$ctrl.current.personalId\" on-save=\"$ctrl.reload()\"></salaxy-taxcard-details>\r\n   */\r\n  public onSave: (eventData: {\r\n    /** The selected item. */\r\n    item: Taxcard,\r\n  }) => void;\r\n\r\n  /** Flags to indicate if the request is in progress */\r\n  public loaders:any = {};\r\n\r\n  private _personalId: string | \"self\";\r\n\r\n  private currentChartConfig: any = {};\r\n\r\n  constructor(\r\n    private fullApi: Taxcards,\r\n    uiHelpers: UiHelpers,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private uploadService: UploadService,\r\n    private sessionService: SessionService,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.mode = this.mode || \"default\";\r\n    if (this.sessionService.isInRole(\"worker\")) {\r\n      // Just as a backup, this component should not be used for role worker any more.\r\n      this.isSelf = true;\r\n    }\r\n    if (this.sessionService.isInRole(\"company\")) {\r\n      delete this.taxcardKindOptions.noWithholdingHousehold;\r\n      delete this.taxcardKindOptionsV2.noWithholdingHousehold;\r\n    }\r\n    if (this.sessionService.isInRole(\"person\")) {\r\n      // Now, enabled for person\r\n      if (this.current?.card.kind === TaxcardKind.Undefined) {\r\n        this.current.card.kind = TaxcardKind.Auto;\r\n      }\r\n    } else {\r\n      if (this.current?.card.kind === TaxcardKind.Undefined) {\r\n        this.current.card.kind = TaxcardKind.Auto;\r\n      }\r\n    }\r\n    super.$onInit();\r\n  }\r\n\r\n  /**\r\n   * Either a valid Finnish Personal ID or \"self\" for the current Worker account.\r\n   * Required for creating a new taxcard: The personal ID is used for setting the connection to Worker account or self.\r\n   * The personal id is used when binding is null (buttons for create new) or \"new\" (actual new UI).\r\n   */\r\n  public get personalId(): string | \"self\" {\r\n    return this._personalId;\r\n  }\r\n  public set personalId(value: string | \"self\") {\r\n    if (!value) {\r\n      this._personalId = null;\r\n      return;\r\n    }\r\n    if (value === \"self\") {\r\n      if (!this.sessionService.isInRole(\"worker\")) {\r\n        throw new Error(\"Cannot bind taxcard to 'self' for Account that is not a Worker.\");\r\n      }\r\n      this._personalId = (this.sessionService.getCurrentAccount() as PersonAccount).identity.officialId;\r\n      this.isSelf = true;\r\n    } else {\r\n      this._personalId = value;\r\n      if ((this.sessionService.getCurrentAccount() as PersonAccount).identity.officialId === value) {\r\n        this.isSelf = true;\r\n      }\r\n    }\r\n    if (value && this.bindingMode === \"new\") {\r\n      this.reload();\r\n    }\r\n  }\r\n\r\n  /** Returns true if one of the edit forms is shown ad if it is valid. */\r\n  public get isFormValid() {\r\n    return this.editForm && this.editForm.$valid;\r\n  }\r\n\r\n  /**\r\n   * Gets the chart type that should be shown.\r\n   * Type \"preview\" means no chart: Only show the preview image of the card.\r\n   */\r\n  public get chartType(): \"preview\" | \"full\" | \"pie\" | \"none\" {\r\n    if (!this.current) {\r\n      return \"none\";\r\n    }\r\n    if (this.current.card.incomeLimit) {\r\n      return \"full\";\r\n    }\r\n    return \"pie\";\r\n  }\r\n\r\n  /**\r\n   * Gets a row for data binding of external salaries paid outside Salaxy system.\r\n   * Will create the row if it does not exist. The save method will remove any empty rows.\r\n   */\r\n  public get previousSalariesRow() {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (!this.current.incomeLog) {\r\n      this.current.incomeLog = [];\r\n    }\r\n    if (!this.current.incomeLog.find((x) => x.type === TaxCardIncomeType.ExternalSalaries)) {\r\n      this.current.incomeLog.push({\r\n        type: TaxCardIncomeType.ExternalSalaries,\r\n        id: null,\r\n        description: Translations.get(\"SALAXY.NG1.CurrentTaxCardComponent.previousSalariesRow\"),\r\n        startDate: this.today,\r\n        endDate: this.today,\r\n        income: null,\r\n        tax: null,\r\n      });\r\n    }\r\n    return this.current.incomeLog.find((x) => x.type === TaxCardIncomeType.ExternalSalaries);\r\n  }\r\n\r\n  /**\r\n   * Starts the reload process depending on the bindingMode:\r\n   */\r\n  public reload(): Promise<Taxcard> {\r\n    if (this.bindingMode === \"new\") {\r\n      this.setCurrentRef(TaxCard2019Logic.getBlank(this.personalId));\r\n      this._currentId = null;\r\n      this.setStatus(null);\r\n      this.updateUISettings();\r\n      return Promise.resolve(this.current);\r\n    }\r\n    return super.reload().then((result) => {\r\n      // TODO: Go through this at the source: Could we assure UI updating in parent controller.\r\n      this.$timeout(() => {\r\n        this.updateUISettings();\r\n      } );\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /** Gets the user interface mode: The UI view that is shown by the component. */\r\n  public getMode(): \"pro\" | \"new\" | \"default\" | \"null\" | \"no-personal-id\" {\r\n    if (this.bindingMode === \"null\") {\r\n      return this.personalId ? \"null\" : \"no-personal-id\";\r\n    }\r\n    if (this.isNew()) {\r\n      return this.personalId ? \"new\" : \"no-personal-id\";\r\n    }\r\n    if (this.mode === \"pro\") {\r\n      return this.mode;\r\n    }\r\n    return \"default\";\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/taxcards\",\r\n      detailsUrl: this.detailsUrl || null,\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Taxcards.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view for the item.\r\n   * Typically, this takes the user to a new page with the ID.\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showDetails(item: Taxcard | IUserObjectIndex): angular.ILocationService {\r\n    if (this.parentController) {\r\n      return this.parentController.showDetails(item);\r\n    }\r\n    if (!this.getDefaults().detailsUrl) {\r\n      if ((item as IUserObjectIndex).otherId) {\r\n        return this.$location.url(\"/employment/details/\" + (item as IUserObjectIndex).id + \"#taxcards\");\r\n      } else if ((item as Taxcard).worker && (item as Taxcard).worker.id) {\r\n        return this.$location.url(\"/employment/details/\" + (item as Taxcard).employmentId + \"#taxcards\");\r\n      } else {\r\n        return this.$location.url(\"/taxcards/details/\" + item.id);\r\n      }\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item));\r\n  }\r\n\r\n  /** Save changes to the current item and then calls the on-save event. */\r\n  public save(): Promise<Taxcard> {\r\n    return super.save().then((savedCard) => {\r\n      if (!savedCard) {\r\n        throw new Error(\"Taxcard saving failed (api returns null): this should only occur with automatic taxcards, and only in adding (this controller is not designed for adding a new taxcard).\");\r\n      }\r\n      if (this.onSave) {\r\n        this.onSave({ item: savedCard });\r\n      }\r\n      return savedCard;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Saves the taxcard and checks the diff after save:\r\n   * If there are paid calculations that should be added to the taxcards, shows a dialog for that.\r\n   */\r\n  public saveCheckDiff(): Promise<Taxcard> {\r\n    return this.save().then((savedTaxcard) => {\r\n      if (savedTaxcard.incomeLog.find((x) => x.diff && x.diff !== \"default\")) {\r\n        return this.uiHelpers.openEditDialog(\"salaxy-components/modals/worker/taxcard-income-log.html\", savedTaxcard, { }, \"lg\")\r\n          .then((incomeLogResult) => {\r\n            if (incomeLogResult.action === \"ok\") {\r\n              const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.CurrentTaxCardComponent.saveCheckDiffSaving\");\r\n              this.fullApi.commitDiff(savedTaxcard).then((commitResult) => {\r\n                loader.dismiss();\r\n                return commitResult;\r\n              });\r\n            } else {\r\n              return savedTaxcard;\r\n            }\r\n          });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Starts the \"Add new\" process for the tax card.\r\n   * By default we do not allow modifying taxcards to the end-user (only allowed for PRO-users).\r\n   * Instead, they will always add a new taxcard.\r\n   * Note: This method breaks the existing model binding of the controller and binds model=\"'new'\".\r\n   */\r\n  public showAddNew() {\r\n    if (!this.personalId) {\r\n      if (!this.current.card.personalId) {\r\n        throw new Error(\"No personal ID: Cannot add new card.\");\r\n      }\r\n      this.personalId = this.current.card.personalId;\r\n    }\r\n    this.loaders[\"showAddNew\"] = true;\r\n    this.uiCrudHelpers.createNewTaxcard(this.personalId).then((result) => {\r\n      if (result.action === \"ok\") {\r\n        if (this.bindingMode === \"url\") {\r\n          this.showDetails(result.item);\r\n        } else {\r\n          this.reload();\r\n          if (this.onSave) {\r\n            this.onSave({ item: result.item });\r\n          }\r\n        }\r\n      }\r\n      this.loaders[\"showAddNew\"] = false;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets auto taxcard and saves it\r\n   */\r\n  public async setAuto() {\r\n    if (!this.personalId) {\r\n      if (!this.current.card.personalId) {\r\n        throw new Error(\"No personal ID: Cannot add new card.\");\r\n      }\r\n      this.personalId = this.current.card.personalId;\r\n    }\r\n    this.loaders[\"showSetAuto\"] = true;\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.loadingTitle\", \"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.loadingText\");\r\n    const taxcard = await this.fullApi.setAuto(this.personalId);\r\n    if (taxcard == null) {\r\n      this.uiHelpers.showAlert(\"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.alertTitle\", \"SALAXY.NG1.WorkerDetailsComponent.taxCard.setSharedAutoForSelf.alertTextAutoCard\");\r\n    } else {\r\n      if (this.onSave) {\r\n        this.onSave({ item: taxcard });\r\n      }\r\n    }\r\n    loader.dismiss();\r\n    this.loaders[\"showSetAuto\"] = false;\r\n  }\r\n\r\n  /** Shows the user interface for editing the minimum percent. */\r\n  public editTaxPercentMin() {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/worker/taxcard-min-percent.html\", {\r\n      taxPercentMin: this.current.card.taxPercentMin,\r\n    }, {}).then((result) => {\r\n      if (result.action == EditDialogKnownActions.Ok) {\r\n        (this.current.card as any).taxPercentMinOwned = result.item.taxPercentMin || null;\r\n        this.current.card.taxPercentMin = result.item.taxPercentMin || null;\r\n        this.save();\r\n      }\r\n    });\r\n  }\r\n  public taxcardKindOptions = {\r\n    \"auto\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.auto\",\r\n    \"defaultYearly\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.defaultYearly\",\r\n    \"replacement\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.replacement\",\r\n    \"noTaxCard\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noTaxCard\",\r\n    \"noWithholdingHousehold\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noWithholdingHousehold\",\r\n  };\r\n\r\n  public taxcardKindOptionsV2 = {\r\n    \"defaultYearly\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.defaultYearly\",\r\n    \"replacement\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.replacement\",\r\n    \"noTaxCard\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noTaxCard\",\r\n    \"noWithholdingHousehold\": \"SALAXY.NG1.CurrentTaxCardComponent.taxcardKindOptions.noWithholdingHousehold\",\r\n  };\r\n\r\n  /** Edit income log. */\r\n  public editIncomeLog() {\r\n    this.uiHelpers.openEditDialog(\"salaxy-components/modals/worker/taxcard-income-log.html\", this.current,\r\n    { editable: true }, \"lg\").then((result) => {\r\n      if (result.action === EditDialogKnownActions.Ok) {\r\n        this.save();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Resets the current taxcard as new.\r\n   * @param kind If specified, reset the taxcard to the given type.\r\n   */\r\n  public resetAsNew(kind?: TaxcardKind) {\r\n    this.setCurrentValue(TaxCard2019Logic.getBlank(this.personalId, kind, null, this.today));\r\n    this.updateUISettings();\r\n  }\r\n\r\n  /** Handles change of the year in the years dropdown. */\r\n  public yearChanged() {\r\n    this.setCurrentValue(TaxCard2019Logic.getBlank(this.personalId, this.current.card.kind, this.current.card.forYear, this.today));\r\n    this.updateUISettings();\r\n  }\r\n\r\n  /**\r\n   * Returns the url where to download the tax card\r\n   * @param taxCard Taxcard or if null, the current is used.\r\n   */\r\n  public getTaxcardDownloadUrl(taxCard?: Taxcard): string {\r\n    taxCard = taxCard || this.current;\r\n    return this.fullApi.getDownloadUrl(taxCard);\r\n  }\r\n\r\n  /**\r\n   * Returns the url where to preview the tax card\r\n   * @param taxCard Taxcard or if null, the current is used.\r\n   */\r\n  public getTaxcardPreviewUrl(taxCard?: Taxcard): string {\r\n    taxCard = taxCard || this.current;\r\n    return this.fullApi.getPreviewUrl(taxCard);\r\n  }\r\n\r\n  /**\r\n   * Returns the url where to preview the tax card in upload scenario.\r\n   * When uploading (adding a new taxcard) the taxcard is not necessarily saved so the preview cannot be fetched based on taxcard id.\r\n   * On the other hand we are always in current user context (current user is the file owner), so we can use previewUri directly\r\n   * @param taxCard Taxcard or if null, the current is used.\r\n   */\r\n  public getUploadPreviewUrl(taxCard?: Taxcard): string {\r\n    taxCard = taxCard || this.current;\r\n    if (!taxCard || !taxCard.card.previewUri) {\r\n      return null;\r\n    }\r\n    return this.uploadService.getPreviewUrl(taxCard.card.previewUri);\r\n  }\r\n\r\n  /**\r\n   * Uploads tax card to the server.\r\n   * @param file - selected file\r\n   */\r\n  public uploadTaxCard(file: any) {\r\n    this.uploadProgress = null;\r\n    if (!file) {\r\n      return;\r\n    }\r\n    this.uploadService.upload<Taxcard>(this.fullApi.getUploadUrl(), { file }, (progress, error) => {\r\n      this.uploadProgress = progress;\r\n    }).then(\r\n      (resp) => {\r\n        this.uploadProgress = null;\r\n        this.current.card.fileUri = resp.card.fileUri;\r\n        this.current.card.previewUri = resp.card.previewUri;\r\n      }).catch((response) => {\r\n        this.uiHelpers.showAlert(\"SALAXY.UI_Terms.error\", \"SALAXY.NG1.CurrentTaxCardComponent.uploadTaxCardAlertDescr\");\r\n        throw new Error(response);\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets main chart configuration for <salaxy-chart>\r\n   * @param taxcard current taxcard\r\n   */\r\n  public getMainChartConfig(taxcard: Taxcard) {\r\n    return this.uiHelpers.cache(this, \"mainChartConfig\",\r\n      () => TaxCard2019Logic.getMainChartV2(taxcard),\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(taxcard));\r\n  }\r\n\r\n  /**\r\n   * Gets pie chart configuration for <salaxy-chart>\r\n   * @param taxcard current taxcard\r\n   */\r\n  public getPieChartConfig(taxcard: Taxcard) {\r\n    return this.uiHelpers.cache(this, \"pieChartConfig\",\r\n      () => TaxCard2019Logic.getPieChartDataV2(taxcard),\r\n      () => TaxCard2019Logic.getIncomeLimitInfo(taxcard));\r\n  }\r\n  /**\r\n   * Checks if the tax card is expired\r\n   * A tax card still valid in the next year's January\r\n   */\r\n  public isTaxCardExpired(taxCard: Taxcard): boolean {\r\n    return !TaxCard2019Logic.isTaxcardValid(taxCard, this.today);\r\n  }\r\n\r\n  /**\r\n   * Gets a language versioned error description ng-file-upload invalidFile errors (client-side before actual upload).\r\n   * @param invalidFile Invalid file of ng-file-upload component.\r\n   */\r\n  public getInvalidFileDescription(invalidFile) {\r\n    return this.uploadService.getInvalidFileDescription(invalidFile);\r\n  }\r\n\r\n  /**\r\n   * Adds a new taxcard for list item and after adding updates the current list without going to server.\r\n   * This is needed because refreshing of the list may not provide the correct results as search is asynchronous.\r\n   */\r\n  public showTaxCardAddDialogForTaxCardsList(listItem: TaxcardListItem) {\r\n    this.loaders[\"showTaxCardAddDialogForTaxCardsList\"] = true;\r\n    this.uiCrudHelpers.createNewTaxcard(listItem.otherPartyInfo.officialId).then((result) => {\r\n      if (result.action === \"ok\") {\r\n        const card = result.item.card;\r\n        listItem.data.employmentId = result.item.employmentId;\r\n        listItem.data.forYear = card.forYear;\r\n        listItem.data.incomeLimit = card.incomeLimit;\r\n        listItem.data.kind = card.kind as any;\r\n        listItem.data.taxPercent = card.taxPercent;\r\n        listItem.data.taxPercent2 = card.taxPercent2;\r\n        (listItem as any).payment = result.item.result.payment;\r\n        listItem.data.totalIncome = result.item.result.totalIncome;\r\n        listItem.startAt = card.validity.start;\r\n        listItem.endAt = card.validity.end;\r\n      }\r\n      this.loaders[\"showTaxCardAddDialogForTaxCardsList\"] = false;\r\n    });\r\n  }\r\n\r\n  /** Commits the DIFF's to storage: synchs the taxcard to actual paid calculations. */\r\n  public commitDiff() {\r\n    this.fullApi.commitDiff(this.current).then((result) => {\r\n      this.setCurrentValue(result, true);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a dialog during the check of auto taxcard.\r\n   */\r\n  public showRefreshAutoTaxcardDialog() {\r\n    this.loaders[\"showRefreshAutoTaxcardDialog\"] = true;\r\n    this.uiCrudHelpers.refreshAutoTaxcard(this.current.id).then( (taxcards) => {\r\n        // reload\r\n        if (taxcards.length) {\r\n          this.setStatus(this.api.getSingle(taxcards[0].id)).then((taxcard) => {\r\n            this.setCurrent(taxcard);\r\n          });\r\n        }\r\n        this.loaders[\"showRefreshAutoTaxcardDialog\"] = false;\r\n    });\r\n  }\r\n\r\n  /** Defines which fields to show/hide, require etc. in the view */\r\n  private updateUISettings() {\r\n    const settings = {\r\n      /** If true, shown the 1st tax percent */\r\n      showTaxPercent: false,\r\n      /** If true, shown the income limit AND 2nd tax pecent. */\r\n      showIncomeLimit: false,\r\n      /** If true, the require the income limit AND 2nd tax percent. */\r\n      requireIncomeLimit: false,\r\n      /** If true, shows input for previous salaries paid. */\r\n      showPreviousSalariesPaid: false,\r\n      /** If true shows the image of an example tax card. */\r\n      showExampleTaxCard: true,\r\n      /** Upload is either hidden, shown as optional (at the end) or required (in the beginning). */\r\n      upload: \"hide\" as \"hide\" | \"show\" | \"required\",\r\n      /**\r\n       * If true, the tax percents etc. cannot be edited.\r\n       * In this case, also the helper numbers (1.-5.) that show where the number is in the PDF should not be shown.,\r\n       */\r\n      readonly: false,\r\n      /** Options for the start date: currently min and max dates. */\r\n      startDateOptions: null,\r\n      /**\r\n       * Years that are allowed in the year selection:\r\n       * Current year + next year in December, previous year in January.\r\n       */\r\n      yearsAllowed: null,\r\n    };\r\n    if (!this.current) {\r\n      this.addNewUi = settings;\r\n      return;\r\n    }\r\n    const todayYear = Dates.getYear(this.today);\r\n    const month = Dates.getMonth(this.today);\r\n    let yearsAllowed: number[];\r\n    if (month === 1) {\r\n      yearsAllowed = [todayYear, todayYear - 1];\r\n    } else if (month === 12) {\r\n      yearsAllowed = [todayYear, todayYear + 1];\r\n    } else {\r\n      yearsAllowed = [todayYear];\r\n    }\r\n    if (yearsAllowed.indexOf(this.current.card.forYear) < 0) {\r\n      if (!this.current.id) {\r\n        this.current.card.forYear = todayYear;\r\n      }\r\n    }\r\n    const forYear = this.current.card.forYear;\r\n    yearsAllowed = yearsAllowed.length < 2 ? null : yearsAllowed; // In the UI, the selection is not shown if there is only one item to select.\r\n    settings.showTaxPercent = true;\r\n    settings.showExampleTaxCard = true;\r\n\r\n    switch (this.current.card.kind) {\r\n      case TaxcardKind.Auto:\r\n        settings.showExampleTaxCard = false;\r\n        settings.showTaxPercent = false;\r\n        break;\r\n      case TaxcardKind.NoTaxCard:\r\n      case TaxcardKind.NoWithholdingHousehold:\r\n        settings.readonly = true;\r\n        settings.showExampleTaxCard = false;\r\n        break;\r\n      case TaxcardKind.Undefined:\r\n        settings.readonly = true;\r\n        settings.showTaxPercent = false;\r\n        break;\r\n      case TaxcardKind.DefaultYearly:\r\n        settings.showIncomeLimit = true;\r\n        settings.showPreviousSalariesPaid = true;\r\n        settings.requireIncomeLimit = true;\r\n        settings.showExampleTaxCard = true;\r\n        settings.upload = this.isSelf ? \"required\" : \"show\";\r\n        settings.yearsAllowed = yearsAllowed;\r\n        break;\r\n      case TaxcardKind.Replacement:\r\n        settings.showIncomeLimit = true;\r\n        settings.showPreviousSalariesPaid = true;\r\n        settings.showExampleTaxCard = true;\r\n        settings.upload = this.isSelf ? \"required\" : \"show\";\r\n        settings.yearsAllowed = yearsAllowed;\r\n        settings.startDateOptions = {\r\n            minDate: Dates.asJSDate(forYear + \"-01-01\"),\r\n            maxDate: Dates.asJSDate(forYear + \"-11-31\"),\r\n          };\r\n        break;\r\n    }\r\n    this.addNewUi = settings;\r\n  }\r\n}\r\n","import { Arrays, Dates, Taxcard, TaxCardIncome, TaxCardIncomeType } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ListControllerBase } from \"../bases\";\r\n\r\n/**\r\n * Handles user interface logic for viewing and editing the income log within a taxcard.\r\n */\r\nexport class TaxcardIncomeLogController extends ListControllerBase<Taxcard, TaxCardIncome> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\"];\r\n\r\n  /** If true, the list can be edited, by default it is read-only. */\r\n  public editable: boolean;\r\n\r\n  /**\r\n   * Creates a new TaxcardIncomeLogController.\r\n   */\r\n  constructor(protected uiHelpers: UiHelpers) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /** List that is edited */\r\n  public get list(): TaxCardIncome[] {\r\n    if (!this.parent) {\r\n      return null;\r\n    }\r\n    return this.parent.incomeLog;\r\n  }\r\n\r\n  /**\r\n   * Shows the edit dialog.\r\n   * @param item Item to edit or string \"new\" for creating a new one.\r\n   * @param isNew Optional way of specifying that the item is a new item (with default values, not yet added to the list).\r\n   * If item is string \"new\", this parameter will have no effect (will always be true).\r\n   */\r\n  public showEditDialog(item: TaxCardIncome | \"new\", isNew = false) {\r\n    if (!this.editable || (item !== \"new\" && this.isReadOnly(item))) {\r\n      return null;\r\n    }\r\n    super.showEditDialog(item, isNew);\r\n  }\r\n\r\n  /** Gets the URL for the log entry edit dialog. */\r\n  public getEditDialogTemplateUrl(): string {\r\n    return \"salaxy-components/worker/taxcard/TaxcardIncomeLogEditDialog.html\";\r\n  }\r\n\r\n  /** Gets a new blank entry with default values. */\r\n  public getBlank(): TaxCardIncome {\r\n    return {\r\n      type: TaxCardIncomeType.ExternalSalaries,\r\n      paidAt: Dates.getToday(),\r\n    };\r\n  }\r\n\r\n  /** Returns true, if the calculations paid are different than the calculations in the income log. */\r\n  public get hasDiff(): boolean {\r\n    return !!(this.list || []).find((x) => x.diff && x.diff !== \"default\");\r\n  }\r\n\r\n  /** Gets a sum from the list */\r\n  public getSum(field: \"tax\" | \"income\"): number {\r\n    if (!this.list) {\r\n      return null;\r\n    }\r\n    return Arrays.sum(this.list, (x) => x[field]);\r\n  }\r\n\r\n  /** Returns true if the row is read-only */\r\n  public isReadOnly(row: TaxCardIncome) {\r\n    return row.type !== TaxCardIncomeType.ExternalSalaries;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { AbsencePeriod, Absences, Arrays, DateRange, Dates, EnumerationsLogic, Translations, WorkerAbsences, CalendarSeries, ApiListItem } from \"@salaxy/core\";\r\nimport { UiCrudHelpers, UiHelpers } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n\r\n/**\r\n * Plain CRUD controller for WorkerAbsences.\r\n */\r\nexport class WorkerAbsencesCrudController extends ApiCrudObjectController<WorkerAbsences, ApiListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Absences\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"UiCrudHelpers\",\r\n  ];\r\n\r\n  /** UI view that is shown */\r\n  public viewType: \"overview\" | \"list\" = \"overview\";\r\n\r\n  /**\r\n   * Years that are available in the drop-down selection.\r\n   * Currently, only affects the calendar, but will probably also affect the lists etc.\r\n   * Currently, starting from 2019 until this year.\r\n   */\r\n  public years: number[];\r\n\r\n  /** Contains all the absences, once getAbsences() has been called. */\r\n  public allAbsences: WorkerAbsences[];\r\n\r\n  /** Current year: Currently, affects only the chart */\r\n  public currentYear: number;\r\n\r\n  /**\r\n   * The date for which the UI is rendered. Default is today.\r\n   * For employment holiday years (WorkerHolidays or CalcWorktime), set this to salary period begin\r\n   * => Specifies the the holiday year to choose by default from all holiday years that Worker has:\r\n   * If the date is Jan-April will show the previous year, May-Dec will show the current year.\r\n   */\r\n  public forDate: string;\r\n\r\n  /** Parameters related to holiday report (lomalista). */\r\n  public reportParams: {\r\n    /** Today's date: Set this for testing how user interface is rendered (which view is presented) at different times of year. */\r\n    today: string;\r\n    /** Start date of the view: Can be get/set directly by the view */\r\n    start: string,\r\n    /** Start date of the view: Can be get/set directly by the view */\r\n    end: string,\r\n    /** Underlying field of reportView */\r\n    _view: \"thisYear\" | \"lastYear\" | \"lastMonth\" | \"thisMonth\" | \"all\",\r\n  };\r\n\r\n  private _employmentId: string;\r\n\r\n  constructor(\r\n    private fullApi: Absences,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private uiCrudHelpers: UiCrudHelpers,\r\n  ) { // Dependency injection\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    this.currentYear = Dates.getYear(\"today\");\r\n    this.years = Arrays.getRange(2019, this.currentYear);\r\n    this.reportParams = {\r\n      today: Dates.getToday(),\r\n    } as any;\r\n    this.reportView = \"thisYear\";\r\n    // Fetching reportView initializes the rest of parameters with default values. Comment for lint if necessary.\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    const necessaryInitCall = this.reportView;\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/workers\",\r\n      detailsUrl: this.detailsUrl || \"/workers/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Absences.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Sets the employment ID and if it is different then starts the loading of the Absences object to that employment ID.\r\n   */\r\n  public set employmentId(value: string) {\r\n    if (this._employmentId === value) {\r\n      return;\r\n    }\r\n    if (!value) {\r\n      if (this._employmentId) {\r\n        this._employmentId = null;\r\n        this.model = null;\r\n        this.reload();\r\n      }\r\n      return;\r\n    }\r\n    this.fullApi.getForEmployment(value).then((model) => {\r\n      this.model = model;\r\n    });\r\n  }\r\n  /** Gets the employment ID */\r\n  public get employmentId() {\r\n    return this._employmentId;\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the report view that is currently shown.\r\n   */\r\n  public get reportView(): \"thisYear\" | \"lastYear\" | \"lastMonth\" | \"thisMonth\" | \"all\" {\r\n    if (!this.reportParams._view) {\r\n      // Use the setter for setting the defaault value so that dependent fields are also set\r\n      this.reportView = \"thisMonth\";\r\n    }\r\n    return this.reportParams._view;\r\n  }\r\n  public set reportView(value: \"thisYear\" | \"lastYear\" | \"lastMonth\" | \"thisMonth\" | \"all\") {\r\n    this.reportParams._view = value;\r\n    const thisYear = Dates.getYear(this.reportParams.today);\r\n    const todayDay = Dates.asDate(this.reportParams.today);\r\n    const monthStart = Dates.startEnd(todayDay,\"start-month\");\r\n    const monthEnd = Dates.startEnd(todayDay,\"end-month\");\r\n    const previousMonthStart = Dates.add(Dates.startEnd(todayDay,\"start-month\"),-1, \"month\");\r\n    const previousMonthEnd = Dates.startEnd(previousMonthStart,\"end-month\");\r\n    switch (value) {\r\n      case \"thisYear\":\r\n        this.reportParams.start = thisYear + \"-01-01\";\r\n        this.reportParams.end = thisYear + \"-12-31\";\r\n        break;\r\n      case \"lastYear\":\r\n        this.reportParams.start = (thisYear - 1) + \"-01-01\";\r\n        this.reportParams.end = (thisYear - 1) + \"-12-31\";\r\n        break;\r\n      case \"thisMonth\":\r\n        this.reportParams.start = monthStart;\r\n        this.reportParams.end = monthEnd;\r\n        break;\r\n      case \"lastMonth\":\r\n        this.reportParams.start = previousMonthStart;\r\n        this.reportParams.end = previousMonthEnd;\r\n        break;\r\n      default:\r\n        this.reportParams.start = this.years[0] + \"-01-01\";\r\n        this.reportParams.end = this.years[this.years.length - 1] + \"-12-31\";\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Maps an array of Absences to array of calendar series\r\n   * @param source Absences to map.\r\n   */\r\n  public mapToCalendar = (source: WorkerAbsences[]): CalendarSeries[] => {\r\n    return source.map((abs) => {\r\n      return {\r\n        key: abs.id,\r\n        title: abs.workerSnapshot.displayName,\r\n        description: `${Translations.get(\"SALAXY.NG1.WorkerAbsencesCrudComponent.absencesPaid\")} ${this.getPeriodCalculation(abs, \"absencesPaid\")}, ${Translations.get(\"SALAXY.NG1.WorkerAbsencesCrudComponent.absencesUnpaid\")} ${this.getPeriodCalculation(abs, \"absencesUnpaid\")}`,\r\n        avatar: abs.workerSnapshot,\r\n        data: abs,\r\n        events: abs.periods.filter(this.filter).map((period) => ({\r\n          start: period.period.start,\r\n          end: period.period.end,\r\n          summary: EnumerationsLogic.getEnumLabel(\"AbsenceCauseCode\", period.causeCode) + ` ${Dates.getFormattedRange(period.period.start, period.period.end)}, ${period.period.days?.length || period.period.daysCount} ${Translations.get(\"SALAXY.NG1.WorkerAbsencesCrudComponent.days\")}.`,\r\n          data: period,\r\n        })),\r\n      };\r\n    });\r\n  };\r\n\r\n  /**\r\n   * Filter that is applied to the list\r\n   * @param value Item in the list\r\n   */\r\n  public filter = (value: AbsencePeriod) => {\r\n    if (this.reportParams.end && value.period.start > this.reportParams.end) {\r\n      return false;\r\n    }\r\n    if (this.reportParams.start && value.period.end < this.reportParams.start) {\r\n      return false;\r\n    }\r\n    return true;\r\n  };\r\n\r\n  /**\r\n   * Saves a the Worker absences based on calendar input and updates the value in allAbsences property.\r\n   * @param itemToSave A Worker absences object.\r\n   */\r\n  public saveAbsences(itemToSave: WorkerAbsences): Promise<void> {\r\n    const loader = this.uiHelpers.showLoading(`${Translations.get(\"SALAXY.NG1.WorkerAbsencesCrudComponent.saving\")}...`);\r\n    return this.api.save(itemToSave).then((savedValue) => {\r\n      angular.copy(savedValue, itemToSave);\r\n      loader.dismiss();\r\n      return;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Show an edit dialog for the absences.\r\n   * @param absences The Worker absences to update.\r\n   */\r\n   public showEditDialog(absences: WorkerAbsences): void {\r\n    /* TODO: The edit dialog is not optimal, as it shows the entire edit worker dialog. Should be a separate edit absence periods dialog. */\r\n    this.uiCrudHelpers.openEditEmploymentDialog(absences.employmentId, \"default\", \"absences\").then((result) => {\r\n      if (result.action === \"ok\") {\r\n        this.getAbsences();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the add worker dialog: A\r\n   */\r\n  public showAddWorker() {\r\n    this.uiHelpers.openSelectEmployments().then((result) => {\r\n      if (result.action === \"ok\" && result.item.length) {\r\n        const newAbsences  = result.item.filter((x) => !this.allAbsences.find((absence) => absence.employmentId === x.id));\r\n        newAbsences.forEach((item) => {\r\n          const newItem = this.api.getBlank();\r\n          newItem.employmentId = item.id;\r\n          newItem.workerSnapshot = item.otherPartyInfo.avatar;\r\n          this.allAbsences.push(newItem);\r\n          this.saveAbsences(newItem);\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Gets the full absence objects for all Workers.\r\n   */\r\n  public getAbsences() {\r\n    this.fullApi.getLatest().then((result: WorkerAbsences[]) => {\r\n      this.allAbsences = result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Returns true, if two objects are different.\r\n   * @param obj1 First object to compare\r\n   * @param obj2 Second object to compare\r\n   */\r\n  public isChanged(obj1, obj2): boolean {\r\n    return !angular.equals(obj1, obj2);\r\n  }\r\n\r\n  /**\r\n   * Gets a calculated value based on filtered absence periods.\r\n   * TODO: Consider moving to core (there is the same code in AbsencePeriodsController)\r\n   * @param absences Worker absences object.\r\n   * @param type Type of calculation\r\n   */\r\n  public getPeriodCalculation(absences: WorkerAbsences, type: \"all\" | \"length\" | \"firstPeriod\" | \"lastPeriod\" | \"absencesPaid\"\r\n    | \"absencesUnpaid\" | \"absencesHolidayAccrual\" | \"absencesNoHolidayAccrual\" = \"all\"): number | DateRange {\r\n    const list = absences.periods.filter(this.filter);\r\n    switch (type) {\r\n      case \"all\":\r\n        return Arrays.sum(list, (x) => x.period.daysCount);\r\n      case \"length\":\r\n        return list.length;\r\n      case \"firstPeriod\":\r\n        return list.length ? list[0].period : null;\r\n      case \"lastPeriod\":\r\n        return list.length ? list[list.length - 1].period : null;\r\n      case \"absencesPaid\":\r\n        return Arrays.sum(list.filter((x) => x.isPaid), (x) => x.period.daysCount);\r\n      case \"absencesUnpaid\":\r\n        return Arrays.sum(list.filter((x) => !x.isPaid), (x) => x.period.daysCount);\r\n      case \"absencesHolidayAccrual\":\r\n        return Arrays.sum(list.filter((x) => x.isHolidayAccrual), (x) => x.period.daysCount);\r\n      case \"absencesNoHolidayAccrual\":\r\n        return Arrays.sum(list.filter((x) => !x.isHolidayAccrual), (x) => x.period.daysCount);\r\n    }\r\n    return null;\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { WorkerAccount, WorkerListItem, Workers } from \"@salaxy/core\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { UiHelpers } from \"../../services\";\r\n\r\n/**\r\n * LEGACY: This used to be the controller for viewing and editing Worker AND Employment details, but now the EmploymentCrudController is used instead.\r\n * @deprecated Use EmploymentCrudController instead.\r\n */\r\nexport class WorkerAccountCrudController extends ApiCrudObjectController<WorkerAccount, WorkerListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"Workers\", \"UiHelpers\", \"$location\", \"$routeParams\"];\r\n\r\n  constructor(\r\n    fullApi: Workers,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n  ) {\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Initialization code.\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/workers\",\r\n      detailsUrl: this.detailsUrl || \"/workers/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Employments.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Ajax, WorkerAccount } from \"@salaxy/core\";\r\n\r\nimport { ODataQueryController } from \"../../controllers/bases/ODataQueryController\";\r\n\r\nimport { UiHelpers } from \"../../services\";\r\nimport { EmploymentCrudController } from \"./EmploymentCrudController\";\r\n\r\n/**\r\n * Controller for creating stand-alone worker accounts.\r\n */\r\nexport class WorkerAssureController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\"UiHelpers\", \"AjaxNg1\"];\r\n\r\n  /** Data binding field for submitAssureWorkerAccount() method  */\r\n  public assureWorkerAccountReq = this.getEmptyAssureWorkerAccountReq();\r\n\r\n  /**\r\n   * Creates a new WorkerAssureController\r\n   * @param uiHelpers - Salaxy ui helpers service.\r\n   * @param ajax - Salaxy ajax service.\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private ajax: Ajax,\r\n\r\n  ) {\r\n  }\r\n\r\n  /** Controller initialization */\r\n  public $onInit() {\r\n    // Empty\r\n  }\r\n\r\n  /**\r\n   * Calls the AssureWorkerAccount method in the API with the data defined in assureWorkerAccountReq\r\n   */\r\n  public submitAssureWorkerAccount(detailsCtrl: EmploymentCrudController, listCtrl: ODataQueryController): Promise<WorkerAccount> {\r\n    const loading = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.wait\");\r\n    let method = \"/partner/assureworker\";\r\n    method += \"?officialId=\" + encodeURIComponent(this.assureWorkerAccountReq.officialId);\r\n    method += \"&firstName=\" + encodeURIComponent(this.assureWorkerAccountReq.firstName);\r\n    method += \"&lastName=\" + encodeURIComponent(this.assureWorkerAccountReq.lastName);\r\n    method += \"&email=\" + encodeURIComponent(this.assureWorkerAccountReq.email);\r\n    method += \"&telephone=\" + encodeURIComponent(this.assureWorkerAccountReq.telephone);\r\n    method += \"&bankAccountIban=\" + encodeURIComponent(this.assureWorkerAccountReq.bankAccountIban);\r\n    if (this.assureWorkerAccountReq.startDate) {\r\n      method += \"&startDate=\" + encodeURIComponent(this.assureWorkerAccountReq.startDate);\r\n    }\r\n    if (this.assureWorkerAccountReq.endDate) {\r\n      method += \"&endDate=\" + encodeURIComponent(this.assureWorkerAccountReq.endDate);\r\n    }\r\n    return this.ajax.postJSON(method, \"\")\r\n      .then((account: WorkerAccount) => {\r\n          const worker = listCtrl.items.find((x) => x.otherId === account.id);\r\n          if (worker == null) {\r\n            listCtrl.items.unshift({\r\n              createdAt: account.createdAt,\r\n              updatedAt: account.updatedAt,\r\n              otherId: account.id,\r\n              otherPartyInfo: {\r\n                avatar: account.avatar,\r\n                officialId: account.officialPersonId,\r\n                email: account.contact.email,\r\n                telephone: account.contact.telephone,\r\n                ibanNumber: account.ibanNumber,\r\n              },\r\n              data: {\r\n                type: account.employment.type,\r\n                pensionCalculation: account.employment.pensionCalculation,\r\n              },\r\n            });\r\n          }\r\n          detailsCtrl.model = account.employmentId;\r\n\r\n          this.resetAssureWorkerAccount();\r\n          loading.dismiss();\r\n          return account;\r\n        });\r\n  }\r\n\r\n  /**\r\n   * Resets assure worker account model.\r\n   */\r\n  public resetAssureWorkerAccount() {\r\n    this.assureWorkerAccountReq = this.getEmptyAssureWorkerAccountReq();\r\n  }\r\n\r\n  /** Gets an empty assureWorkerAccountReq - used for reset. */\r\n  private getEmptyAssureWorkerAccountReq() {\r\n    return {\r\n      officialId: null,\r\n      firstName: null,\r\n      lastName: null,\r\n      email: null,\r\n      telephone: null,\r\n      bankAccountIban: null,\r\n      startDate: null,\r\n      endDate: null,\r\n    };\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ApiItemType, CalendarAction, CalendarActionType, CalendarEvent, CalendarEvents, Dates, DateRange, DateTimes, EnumerationsLogic, IUserObjectIndex, RecurringEventCreateMode, Translations, CalendarOccurence, CalendarSeries, CalendarUiEvent, CalendarEventListItem } from \"@salaxy/core\";\r\n\r\nimport { UiHelpers, WizardService, WizardStep } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\n\r\n/**\r\n * Controller for implementing Calendars that contain CalendarEvents (iCalendar).\r\n */\r\nexport class CalendarEventsCrudController extends ApiCrudObjectController<CalendarEvent, CalendarEventListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"CalendarEvents\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"WizardService\",\r\n  ];\r\n\r\n  /** Styling classes for columns. */\r\n  public colWidthClasses = [\"col-sm-12\", \"col-sm-12\", \"col-sm-6\", \"col-sm-4\", \"col-sm-3\", \"col-sm-fifth\", \"col-sm-2\"];\r\n\r\n  /** Gets all the steps in the Wizard */\r\n  public get steps(): WizardStep[] {\r\n    return this.wizardService.getSteps();\r\n  }\r\n\r\n  /** Gets the number of the currently active step */\r\n  public get step(): number {\r\n    return this.wizardService.activeStepNumber;\r\n  }\r\n  /** Sets the number of the currently active step */\r\n  public set step(stepNumber: number) {\r\n    this.wizardService.activeStepNumber = stepNumber;\r\n  }\r\n\r\n  /** The currently selected step object */\r\n  public get currentStep(): WizardStep {\r\n    return this.wizardService.getCurrentStepObject();\r\n  }\r\n\r\n  /** Active styling properties */\r\n  public get style() {\r\n    return {\r\n      colWidthClass: this.colWidthClasses[this.steps.length],\r\n    };\r\n  }\r\n\r\n  /** Returns true if goNext is enabled  */\r\n  public get canGoNext(): boolean {\r\n    if (this.steps.length > this.step) {\r\n      if (this.steps[this.step] && !this.steps[this.step].disabled) {\r\n        return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /** Returns true if goNext is enabled  */\r\n  public get canGoPrevious(): boolean {\r\n    if (this.step > 1 && !this.steps[this.step - 2].disabled) {\r\n      return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Navigates to the next step if possible\r\n   */\r\n  public goNext() {\r\n    if (this.canGoNext) {\r\n      this.step++;\r\n    }\r\n  }\r\n\r\n  /** Navigates to the previous step if possible */\r\n  public goPrevious() {\r\n    if (this.canGoPrevious) {\r\n      this.step--;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creates a new WorkflowController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private fullApi: CalendarEvents,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private wizardService: WizardService,\r\n  ) {\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Controller initialization\r\n   */\r\n  public $onInit() {\r\n    this.wizardService.setSteps([\r\n      {\r\n        title: \"SALAXY.NG1.ODataCalendarEventComponent.step1Title\",\r\n        active: true,\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.ODataCalendarEventComponent.step2Title\",\r\n      },\r\n      {\r\n        title: \"SALAXY.NG1.ODataCalendarEventComponent.step3Title\",\r\n      },\r\n    ]);\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/calendar\",\r\n      detailsUrl: this.detailsUrl || \"/calendar/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/calendar/Events.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Loads a recurring event from the data storage and sets it as current item.\r\n   */\r\n  public getRecurringEvent(type: ApiItemType, id: string): Promise<CalendarEvent> {\r\n    return this.setStatus(this.fullApi.getRecurringEvent(id, type, RecurringEventCreateMode.CreateRecurrence))\r\n      .then((item) => {\r\n        if (!item) {\r\n          throw new Error(`Item ${this.currentId} not found.`);\r\n        }\r\n        this.model = item;\r\n        return item;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * GetId is overriden so that the id contains also the payload type besides the id\r\n   * @param item The item for which to fetch the ID.\r\n   */\r\n   public getId(item: CalendarEvent | IUserObjectIndex) {\r\n    if (!item) {\r\n      throw new Error(\"getId called for null item.\");\r\n    }\r\n    if ((item as IUserObjectIndex).containerGuid) {\r\n      // This may not work for all types (Payload type is perhaps not the same as API item type?).\r\n      return (item as IUserObjectIndex).containerGuid + \"/\" + (item as IUserObjectIndex).payloadType;\r\n    }\r\n    return item.id + \"/\" + item.payloadType;\r\n  }\r\n\r\n  /** Adds a new recurrence rule to the event */\r\n  public addRecurrenceRule() {\r\n    this.current.event.recurrenceRules = this.current.event.recurrenceRules || [];\r\n    this.current.event.recurrenceRules.push(\"FREQ=MONTHLY;INTERVAL=1\");\r\n  }\r\n\r\n  /** Adds a new action to the event */\r\n  public addAction() {\r\n    this.current.event.actions = this.current.event.actions || [];\r\n    const newAction: CalendarAction = {\r\n      type: this.current.event.actions.length ? CalendarActionType.Email : CalendarActionType.CreateItem,\r\n    };\r\n    this.current.event.actions.push(newAction);\r\n  }\r\n\r\n  /**\r\n   * Deletes an item in the recurrence rules\r\n   * @param index The index number of the item to delete.\r\n   */\r\n  public deleteRecurrence(index: number): void {\r\n    this.current.event.recurrenceRules.splice(index, 1);\r\n  }\r\n\r\n  /**\r\n   * Deletes an item in the actions\r\n   * @param index The index number of the item to delete.\r\n   */\r\n  public deleteAction(index: number): void {\r\n    this.current.event.actions.splice(index, 1);\r\n  }\r\n\r\n  /**\r\n   * Saves the calendar item.\r\n   * Override done so that durations (timespans) are converted from number to string.\r\n   */\r\n  public save(): Promise<CalendarEvent> {\r\n    this.checkDurations();\r\n    return super.save();\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view for the event in a dialog.\r\n   * @param id Identifier of the calendar event to edit.\r\n   * Use \"new\" to add a new item.\r\n   */\r\n  public showDetailsDialog(id: string | \"new\"): void {\r\n    const loader = this.uiHelpers.showLoading(\"SALAXY.UI_Terms.loading\");\r\n    const title = id === \"new\" ? \"SALAXY.NG1.ODataCalendarEventComponent.showDetailsDialogTitle\" : \"SALAXY.NG1.ODataCalendarEventComponent.showDetailsDialogTitle2\";\r\n    this.fullApi.getSingle(id).then((item) => {\r\n      loader.setHeading(\"Muokkaus auki\");\r\n      this.uiHelpers.openEditCalendarEvent(item, title).then((result) => {\r\n        if (result.action === \"ok\") {\r\n          loader.setHeading(\"SALAXY.UI_Terms.isSaving\");\r\n          this.fullApi.save(result.item).then(() => {\r\n            loader.dismiss();\r\n            if (this.odataController) {\r\n              this.odataController.reload();\r\n            }\r\n          });\r\n        } else {\r\n          loader.dismiss();\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n  /** Gets the event duration, even if it is null (start and end defined). */\r\n  public getEventDuration() {\r\n    if (!this.current) {\r\n      return null;\r\n    }\r\n    if (this.current.event.duration) {\r\n      return DateTimes.formatDuration(this.current.event.duration);\r\n    }\r\n    let end = this.current.event.end ?? this.current.event.start;\r\n    if (end < this.current.event.start) {\r\n      return Translations.get(\"SALAXY.NG1.ODataCalendarEventComponent.getEventDurationError\");\r\n    }\r\n    if (this.current.event.isAllDay) {\r\n      end = Dates.add(end, 1, \"day\");\r\n    }\r\n    return DateTimes.formatRangeToDuration(this.current.event.start, end);\r\n  }\r\n\r\n  /** Assures that the durations are strings, not numbers. The UI binding makes them numbers. */\r\n  public checkDurations() {\r\n    if (this.current?.event.duration) {\r\n      this.current.event.duration = this.current.event.duration.toString();\r\n    }\r\n    (this.current?.event.actions || []).forEach((action) => {\r\n      if (action.triggerDuration) {\r\n        action.triggerDuration = action.triggerDuration.toString();\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Preview calendar is clicked\r\n   * @param type event or empty day\r\n   * @param date Date as string\r\n   * @param calEvent Calendar event that is clicked.\r\n   */\r\n  public calendarClick(type: \"event\" | \"day\", date: string, calEvent: CalendarUiEvent) {\r\n    // TODO: Go through. This could be made more informative.\r\n    if (type === \"event\") {\r\n      let text;\r\n      const action = (this.preview ?? this.current).event.actions.find((x) => calEvent.data?.id && x.id === calEvent.data.id);\r\n      if (action) {\r\n        text = `${EnumerationsLogic.getEnumLabel(\"CalendarActionType\", action.type)}: ${Dates.getFormattedDate(calEvent.start)}.\r\n${action.summary || \"SALAXY.NG1.ODataCalendarEventComponent.calendarClickNoDescription\"} (${Translations.get(\"SALAXY.NG1.ODataCalendarEventComponent.calendarClickDuration\")}: ${action.triggerDuration || action.triggerDateTime})\r\n\r\n${action.description || \"\"}`;\r\n      } else {\r\n        text = `${Translations.get(\"SALAXY.NG1.ODataCalendarEventComponent.reoccuringEvent\")}: ${Dates.getFormattedDate(calEvent.start)}.`;\r\n      }\r\n      this.uiHelpers.showAlert(calEvent.summary, text);\r\n    }\r\n  }\r\n\r\n  public preview: CalendarEvent & {\r\n    start?: string,\r\n    end?: string,\r\n  };\r\n\r\n  /**\r\n   * Reloads the preview from the server.\r\n   */\r\n  public reloadPreview() {\r\n    this.preview = null;\r\n    this.checkDurations();\r\n    this.fullApi.recalculate(this.current).then((result: CalendarEvent) => {\r\n      this.preview = result;\r\n      const previewRange = this.getPreviewRange(result);\r\n      this.preview.start = previewRange.start;\r\n      this.preview.end = previewRange.end;\r\n    });\r\n  }\r\n\r\n  /** Gets a peview range (currently 4 months) for a calendar event  */\r\n  public getPreviewRange(event: CalendarEvent): DateRange {\r\n    const today = Dates.getToday();\r\n    if (event.occurenceInfo.occurencesEnd < today) {\r\n      return {\r\n        start: Dates.add(Dates.startEnd(event.occurenceInfo.occurencesEnd, \"start-month\"), -3, \"month\"),\r\n        end: Dates.startEnd(event.occurenceInfo.occurencesEnd, \"end-month\"),\r\n      };\r\n    }\r\n    let startMonth: string;\r\n    if (event.occurenceInfo.occurencesStart > Dates.add(\"today\", 1, \"month\")) {\r\n      startMonth = Dates.startEnd(event.occurenceInfo.occurencesStart, \"start-month\");\r\n    } else {\r\n      startMonth = Dates.startEnd(Dates.add(\"today\", -1, \"month\"), \"start-month\");\r\n    }\r\n    return {\r\n      start: startMonth,\r\n      end: Dates.startEnd(Dates.add(startMonth, 4, \"month\"), \"end-month\"),\r\n    };\r\n  }\r\n\r\n  /** The calendar mapper updates the calendar start and end dates. */\r\n  public calendarView: {\r\n    start?: string,\r\n    end?: string,\r\n  };\r\n\r\n  /** Maps the occurence from the preview object to calendar. */\r\n  public calendarMapper = (src: CalendarEvent): CalendarSeries[] => {\r\n    const result: CalendarSeries = {\r\n      key: \"default\",\r\n      title: \"Preview\",\r\n      events: [],\r\n    };\r\n    const icons = {\r\n      \"undefined\": null,\r\n      \"display\": \"fa-bell\",\r\n      \"email\": \"fa-envelope\",\r\n      \"audio\": \"fa-volume-off\",\r\n      \"createItem\": \"fa-star\",\r\n      \"paymentDate\": \"fa-money\",\r\n      \"script\": \"fa-cog\",\r\n    };\r\n    const colors = [\"info\", \"default\", \"success\", \"primary\"];\r\n    this.calendarView = {};\r\n    src.occurenceInfo.next.forEach((occ: CalendarOccurence, index: number) => {\r\n      const color = colors[index % 4];\r\n      if (occ.start < (this.calendarView.start || \"9999-01-01\")) {\r\n        this.calendarView.start = occ.start;\r\n      }\r\n      let end = occ.end;\r\n      if (occ.duration == \"1.00:00:00\") {\r\n        end = null;\r\n      } else if (occ.isAllDay) {\r\n        // In iCalendar, one day is until the beginning of next day (e.g. day \"2020-01-01\" is start:\"2020-01-01\", end:\"2020-01-02\").\r\n        // Our calendar component is only about days (e.g. day \"2020-01-01\" is start:\"2020-01-01\", end:\"2020-01-01\" OR end:null).\r\n        end = Dates.add(end, -1, \"day\");\r\n      }\r\n      result.events.push({\r\n        start: occ.start,\r\n        end,\r\n        summary: Translations.get(occ.summary) || Translations.get(\"SALAXY.NG1.ODataCalendarEventComponent.event\"),\r\n        cssClass: `salaxy-cal-event-${color}`,\r\n      });\r\n      occ.actions.forEach((action: any) => {\r\n        if (action.start < this.calendarView.start) {\r\n          this.calendarView.start = action.start;\r\n        }\r\n        result.events.push({\r\n          start: action.start,\r\n          summary: Translations.get(action.summary) || Translations.getWithDefault((\"SALAXY.ENUM.CalendarActionType.\" + action.type), action.type),\r\n          icon: icons[action.type],\r\n          cssClass: `btn-${color}`,\r\n        });\r\n      });\r\n    });\r\n    this.calendarView.start = Dates.startEnd(this.calendarView.start || Dates.getToday(), \"start-month\");\r\n    this.calendarView.end = Dates.add(Dates.add(this.calendarView.start, 3, \"month\"), -1, \"day\");\r\n    return [result];\r\n  };\r\n\r\n  /**\r\n   * Gets or sets the value of whether the e-mail notification should be sent.\r\n   * Used by simplified view as boolean: Adds or removes a second item to actions array.\r\n   */\r\n  public get notificationEnabled(): boolean {\r\n    return !!this.current.event.actions.find((x) => x.type == CalendarActionType.Email);\r\n  }\r\n  public set notificationEnabled(value: boolean) {\r\n    if (value) {\r\n      this.current.event.actions.push({\r\n        type: CalendarActionType.Email,\r\n        summary: Translations.get(\"SALAXY.NG1.ODataCalendarEventComponent.notificationEnabledSummary\"),\r\n        triggerDuration: this.current.event.actions[1]?.triggerDuration ?? \"10.00:00\",\r\n        description: null,\r\n        attendees: [{ email: null }],\r\n      });\r\n    } else {\r\n      this.current.event.actions = this.current.event.actions.filter((x) => x.type != CalendarActionType.Email);\r\n    }\r\n  }\r\n\r\n  /** Gets the notification if one exists. */\r\n  public get notification() {\r\n    return this.current.event.actions.find((x) => x.type == CalendarActionType.Email);\r\n  }\r\n\r\n  /** Shows the create/edit dialog for the current event. */\r\n  public showEditEvent(): void {\r\n    this.fullApi.getRecurringEvent(this.currentId, ApiItemType.PayrollDetails, RecurringEventCreateMode.CreateRecurrence).then((ev) => {\r\n      this.uiHelpers.openEditCalendarEvent(ev, \"SALAXY.NG1.ODataCalendarEventComponent.showEditEventTitle\", \"simplified\").then((dialogResult) => {\r\n        if (dialogResult.action === \"ok\") {\r\n          this.setCurrentRef(dialogResult.item);\r\n          this.save();\r\n        } else if (dialogResult.action === \"delete\") {\r\n          this.setCurrentRef(dialogResult.item);\r\n          this.delete();\r\n        }\r\n      });\r\n    });\r\n  }\r\n}\r\n","import { Dates, CalendarEventListItem, DateRange, CalendarEvents, ODataResult, Arrays, ApiItemType, Translations, CalendarSeries, CalendarUiEvent } from \"@salaxy/core\";\r\nimport { UiHelpers } from \"../../services\";\r\nimport { ListControllerBase } from \"../bases/ListControllerBase\";\r\n\r\n/**\r\n * Controller for displaying occurences and actions (alarm in iCalendar) based on CalendarEvents.\r\n */\r\nexport class CalendarOccurencesController extends ListControllerBase<ODataResult<CalendarEventListItem>, CalendarEventListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"CalendarEvents\",\r\n    \"UiHelpers\",\r\n  ];\r\n\r\n  /** The date range that is shown in the calendar and loaded from the server. */\r\n  public range: DateRange;\r\n\r\n  /** Comma separated list of categories that are fetched from the server and shown in the calendar.. */\r\n  public categories: string;\r\n\r\n  /** Set to true if the list is loading (show spinner) */\r\n  public isLoading = false;\r\n\r\n\r\n  /** Preset selection of categories user interface. */\r\n  public categorySelections = {\r\n    [ApiItemType.CalendarEvent]: Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.calendarEvent\"),\r\n    [ApiItemType.Calculation]: Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.calculation\"),\r\n    [ApiItemType.CalculationPaid]: Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.calculationPaid\"),\r\n    [ApiItemType.PayrollDetails]: Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.payrollDetails\"),\r\n    [ApiItemType.MessageThread]: Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.messageThread\"),\r\n    \"calculation,payrollDetails,calculationPaid\": Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.calculationsAndPayrolls\"),\r\n    \"all\": Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.all\"),\r\n    \"none\": Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.none\"),\r\n    \"default\": Translations.get(\"SALAXY.NG1_Pages.Calendar.categorySelections.default\"),\r\n    /*\r\n    action: \"Automaattiset työnkulut\",\r\n    holiday: \"Lomat\",\r\n    absencePeriod: \"Poissaolot\",\r\n    */\r\n  };\r\n\r\n  /** Lists the occurences for the current week based on the current day. */\r\n  public currentWeek: {\r\n    /** Date of teh day */\r\n    date: string,\r\n    /** Occurences on the day */\r\n    occurences: any[], // TODO: Think through what the type should be here.\r\n  }[];\r\n\r\n  /** Occurences on currentDay */\r\n  public todayOccurences: CalendarEventListItem[];\r\n\r\n  /** Periods for the use in calendar components. */\r\n  public calendarPeriods: CalendarSeries[];\r\n\r\n  private _currentDay: string;\r\n\r\n  private emptyArr = [];\r\n\r\n  /**\r\n   * Creates a new WorkflowController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private calendarEvents: CalendarEvents,\r\n    uiHelpers: UiHelpers,\r\n  ) {\r\n    super(uiHelpers);\r\n  }\r\n\r\n  /**\r\n   * Controller initialization\r\n   */\r\n  public $onInit() {\r\n    const start = Dates.add(Dates.startEnd(\"today\", \"start-month\"), -1, \"month\");\r\n    this.range = this.range || {\r\n      start,\r\n      end: Dates.add(Dates.add(start, 3, \"month\"), -1, \"day\"),\r\n    };\r\n    this.categories = this.categories || ApiItemType.Calculation;\r\n    this.reload();\r\n  }\r\n\r\n  /** Gets the list of occurences */\r\n  public get list(): CalendarEventListItem[] {\r\n    return this.parent?.items || this.emptyArr;\r\n  }\r\n\r\n  /** Gets the edit dialog template URL */\r\n  public getEditDialogTemplateUrl(): string {\r\n    return \"salaxy-components/workflow/calendar/Occurences-details.html\";\r\n  }\r\n\r\n  /** Gets a blank event occurence (currently not supported / thows an error) */\r\n  public getBlank(): CalendarEventListItem {\r\n    throw new Error(\"You cannot create an event occurence directly: Create and event instead.\");\r\n  }\r\n\r\n  /** Gets the custom logic for dialog */\r\n  public getEditDialogLogic(): any {\r\n    return {};\r\n  }\r\n\r\n  /** Reload the OData query using the range and categories parameters */\r\n  public reload(): void {\r\n    this.isLoading = true;\r\n    this.calendarEvents.getOccurences(Arrays.assureArray(this.categories), this.range.start, this.range.end)\r\n      .then((result) => {\r\n        this.parent = result;\r\n        this.isLoading = false;\r\n        const periods: CalendarSeries = {\r\n          key: \"periods\",\r\n          title: Translations.get(\"SALAXY.NG1_Pages.Calendar.calendarSeriesPeriods\"),\r\n          events: result.items.map((x) => ({\r\n            summary: x.shortText,\r\n            start: x.startAt,\r\n            end: x.endAt,\r\n          }))\r\n        };\r\n        const actions: CalendarSeries = {\r\n          key: \"actions\",\r\n          title: Translations.get(\"SALAXY.NG1_Pages.Calendar.calendarSeriesActions\"),\r\n          events: [],\r\n        };\r\n        result.items.forEach((occurence) => {\r\n          // TODO: Switch type to CalendarOccurenceListItem\r\n          periods.events.push(...((occurence as any).actions as CalendarUiEvent[]));\r\n        });\r\n        this.calendarPeriods = [periods, actions];\r\n        let currentDay = this.currentDay;\r\n        if (currentDay < this.range.start) {\r\n          currentDay = this.range.start;\r\n        } else if (currentDay > this.range.end) {\r\n          currentDay = this.range.end;\r\n        }\r\n        this.currentDay = currentDay; // Set to refresh daily and weekly views\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Gets or sets the current day for the daily and weekly calendar.\r\n   * Setting to null will set the day as today.\r\n   */\r\n   public get currentDay() {\r\n    if (!this._currentDay) {\r\n      this._currentDay = Dates.getToday();\r\n    }\r\n    return this._currentDay;\r\n  }\r\n  public set currentDay(value: string) {\r\n    value = Dates.asDate(value);\r\n    this._currentDay = value || Dates.getToday();\r\n    const nextDay = Dates.add(this._currentDay, 1, \"day\");\r\n    this.todayOccurences = this.list.filter(x => x.endAt >= this._currentDay && x.startAt < nextDay);\r\n    const mondayDay = Dates.startEnd(this._currentDay,\"start-week\");\r\n    this.currentWeek = [];\r\n    for (let i = 0; i < 7; i++) {\r\n      const date = mondayDay;\r\n      const nextDay = Dates.add(mondayDay,1, \"day\");\r\n      this.currentWeek.push({\r\n        date,\r\n        occurences: this.list.filter(x => x.endAt >= date && x.startAt < nextDay),\r\n      });\r\n    }\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { ActionExecutor, ApiItemType, Dataset, DatasetListItem, Datasets, InputEnumOption, OpenAPIV3, UsecaseAction } from \"@salaxy/core\";\r\n\r\nimport { JsonSchemaService, SessionService, SessionUsecase, UiHelpers, UsecasesService } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { AjaxNg1 } from \"../../ajax\";\r\n\r\n/**\r\n * Controller for listing, using and setting the data in Datasets:\r\n * Some arbitrary external data, typically Imports, Exports and Reports.\r\n */\r\nexport class DatasetsCrudController extends ApiCrudObjectController<Dataset, DatasetListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Datasets\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"UsecasesService\",\r\n    \"JsonSchemaService\",\r\n    \"SessionService\",\r\n    \"AjaxNg1\",\r\n    \"$timeout\"\r\n  ];\r\n\r\n  /**\r\n   * Type of component user interface.\r\n   * Default is usecase if one is specified, otherwise \"data-edit\".\r\n   * \"full-edit\" shows the full editor with data schema selections, adding new data objects etc.\r\n   */\r\n  public mode: \"full-edit\" | \"data-edit\" | \"usecase\" | \"default\";\r\n\r\n  /**\r\n   * The usecase definition if specified and loaded.\r\n   * If the usecase has been checked from server, but none is defined, the value is \"none\".\r\n   * For checking whether usecase really is available, check e.g. usecase.uri.\r\n   */\r\n  public usecase: null | \"none\" | SessionUsecase = null;\r\n\r\n  /** Defines the default usecase (uri) that is used for new objects. */\r\n  public defaultUsecase: string;\r\n\r\n  /** Available usecases if the user needs to make a selection of which usecase to take. */\r\n  public usecases: InputEnumOption[];\r\n\r\n  /**\r\n   * Creates a new DatasetsCrudController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    fullApi: Datasets,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private usecasesService: UsecasesService,\r\n    private jsonSchemaService: JsonSchemaService,\r\n    private sessionService: SessionService,\r\n    private ajax: AjaxNg1,\r\n    private $timeout: angular.ITimeoutService,\r\n  ) {\r\n    super(fullApi, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Controller initialization\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/datasets\",\r\n      detailsUrl: this.detailsUrl || \"/datasets/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Datasets.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n\r\n  /** Overrides the reload to assure that usecase is also loaded. */\r\n  public reload(): Promise<Dataset> {\r\n    // TODO: Consider moving this functionality to base classes.\r\n    return super.reload().then((result) => {\r\n      if (!result) {\r\n        this.usecase = \"none\";\r\n        return result;\r\n      }\r\n      this.current.data.forEach((x: any) => {\r\n        if ((x.schemaDoc || \"any\") != \"any\" && x.schemaDoc != \"usecase\") {\r\n          // TODO: Assure that this loading does not happen several times for same URL.\r\n          this.jsonSchemaService.assureSchemaDocument(x.schemaDoc);\r\n        }\r\n      });\r\n      const usecaseUri = this.$location?.search().usecase || this.defaultUsecase;\r\n      result.data.forEach((x) => x.content = x.content || []);\r\n      if (usecaseUri || result.usecase?.uri) {\r\n        return this.usecasesService.assureUsecase(ApiItemType.Dataset, result, usecaseUri).then((usecase) => {\r\n          if (usecase) {\r\n            this.usecase = usecase;\r\n          } else {\r\n            this.usecase = \"none\";\r\n            this.assureUsecasesLoaded();\r\n          }\r\n          return result;\r\n        });\r\n      } else {\r\n        this.assureUsecasesLoaded();\r\n        this.usecase = \"none\";\r\n        return result;\r\n      }\r\n    });\r\n  }\r\n\r\n  private assureUsecasesLoaded() {\r\n    this.usecasesService.getActiveUsecaseListItems(ApiItemType.Dataset).then((list) => {\r\n      this.usecases = list.sort((a, b) => (a.data.order || 100) - (b.data.order || 100))\r\n        .map((x) => ({ text: x.shortText, value: x.uri }));\r\n    });\r\n  }\r\n\r\n  /** Gets the user interface mode */\r\n  public getMode(): \"data-edit\" | \"full-edit\" | \"usecase\" | \"loading\" {\r\n    if (this.isLoading || (!(this.usecase as SessionUsecase)?.isLoaded && this.usecase != \"none\")) {\r\n      // TODO: Check the case when dataset has no usecase. Is it infinite loader now?\r\n      return \"loading\";\r\n    }\r\n    switch (this.mode) {\r\n      case \"data-edit\":\r\n      case \"full-edit\":\r\n      case \"usecase\":\r\n        return this.mode;\r\n      default:\r\n        if ((this.usecase as SessionUsecase)?.defaultView) {\r\n          return \"usecase\";\r\n        }\r\n        return \"data-edit\";\r\n    }\r\n  }\r\n\r\n  /** Adds a new \"table\" to the dataset */\r\n  public addDataObject() {\r\n    this.current.data.push({\r\n      label: \"Uusi tietue\"\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Removes a data object from the dataset\r\n   * @param index Index of the object to remove.\r\n   */\r\n  public deleteObject(index: number) {\r\n    // TODO: Add \"Are you sure?\"\r\n    this.current.data.splice(index, 1);\r\n  }\r\n\r\n  /** Executes the current action with the current item. */\r\n  public async executeAction(action: UsecaseAction): Promise<ActionExecutor> {\r\n    const executor = new ActionExecutor(action);\r\n    await executor.execute(this.current, this.sessionService.session, this.ajax);\r\n    if (executor.isAsync) {\r\n      this.$timeout();\r\n    }\r\n    return executor;\r\n  }\r\n\r\n  /**\r\n   * Adds an item to the default view (first view). Adds the view if it does not already exist.\r\n   * Method may later be extended to support multiple views and/or more elaborate column properties.\r\n   * @param dataObjectIndex Index of the data object to which the view item is added.\r\n   * @param type Add include or exclude rule.\r\n   * @param value Value to add to the array.\r\n   */\r\n  public addViewItem(dataObjectIndex: number, type: \"include\" | \"exclude\", value = \"\") {\r\n    const dataObj = this.current.data[dataObjectIndex];\r\n    dataObj.views = dataObj.views || [];\r\n    if (dataObj.views.length < 1) {\r\n      dataObj.views.push({});\r\n    }\r\n    const view = dataObj.views[0];\r\n    if (type == \"exclude\") {\r\n      view.exclude = view.exclude || [];\r\n      view.exclude.push(value);\r\n    } else if (type == \"include\") {\r\n      view.include = view.include || [];\r\n      view.include.push(value);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Helper method to move an item in an array up or down.\r\n   * @param arr Array to operate on\r\n   * @param fromIndex Index of the item to move\r\n   * @param step How many items to move and to which direction: -1 is one up, 1 is one down.\r\n   */\r\n  public arraymove(arr: [], fromIndex: number, step: number) {\r\n    const element = arr[fromIndex];\r\n    arr.splice(fromIndex, 1);\r\n    let toIndex = fromIndex + step;\r\n    if (toIndex > arr.length) {\r\n      toIndex = arr.length;\r\n    }\r\n    if (toIndex < 0) {\r\n      toIndex = 0;\r\n    }\r\n    arr.splice(toIndex, 0, element);\r\n  }\r\n\r\n  /**\r\n   * Gets the available schema documents that can be used for modeling the data objects.\r\n   * @returns Cached collection of available schema documents.\r\n   */\r\n  public getSchemaDocs(): InputEnumOption[] {\r\n    return this.uiHelpers.cache(this, \"schemaList\", () => {\r\n      console.log(\"Refresh cache.\");\r\n      return [\r\n        {\r\n          value: \"any\",\r\n          text: \"Ei määritetty (any)\",\r\n          title: \"any\",\r\n        },\r\n        {\r\n          value: \"usecase\",\r\n          text: \"Räätälöinti\",\r\n          title: \"usecase\",\r\n        },\r\n        ...this.jsonSchemaService.getSchemas().map((x) => ({\r\n          value: x.url,\r\n          text: x.doc.info.title,\r\n          title: x.url,\r\n        }))\r\n      ];\r\n    }, () => this.jsonSchemaService.getSchemas().map((x) => x.url));\r\n  }\r\n\r\n  /**\r\n   * Gets the schemas defined in the specified schema document\r\n   * @param docUrl The URL (unique key in cache) for the schema document.\r\n   */\r\n  public getSchemas(docUrl): InputEnumOption[] {\r\n    if (!docUrl || docUrl == \"any\") {\r\n      docUrl = \"\";\r\n    }\r\n    if (!this.schemaCache[docUrl]) {\r\n      if (docUrl == \"usecase\") {\r\n        if (this.usecase == \"none\") {\r\n          this.schemaCache.usecase = [];\r\n        } else {\r\n          const schemas = this.usecase.schema.components.schemas;\r\n          this.schemaCache[docUrl] = Object.keys(schemas).map((key) => ({\r\n            value: key,\r\n            text: `${schemas[key].title} (${key})`,\r\n            title: schemas[key].description || key,\r\n          }));\r\n        }\r\n      } else {\r\n        const schemas = this.jsonSchemaService.findSchemaDoc(docUrl, true).doc.components.schemas;\r\n        this.schemaCache[docUrl] = Object.keys(schemas).map((key) => {\r\n          const text = (schemas[key] as OpenAPIV3.SchemaObject).title ? `${(schemas[key] as OpenAPIV3.SchemaObject).title} (${key})` : key;\r\n          return {\r\n            value: key,\r\n            text,\r\n            title: (schemas[key] as OpenAPIV3.SchemaObject).description || key,\r\n          };\r\n        });\r\n      }\r\n    }\r\n    return this.schemaCache[docUrl];\r\n  }\r\n\r\n  /**\r\n   * Gets the full schema definition for the specified table.\r\n   * @param index Index number of the data object in the data collection.\r\n   */\r\n  public getSchamaDef(index: number): OpenAPIV3.SchemaObject {\r\n    const docUrl = (this.current.data[index] as any).schemaDoc;\r\n    const schemaKey = this.current.data[index].schema;\r\n    if (!docUrl || docUrl == \"any\") {\r\n      return null;\r\n    }\r\n    if (docUrl == \"usecase\") {\r\n      if (this.usecase == \"none\") {\r\n        return null;\r\n      } else {\r\n        return this.usecase.schema.components.schemas[schemaKey];\r\n      }\r\n    } else {\r\n      const schemaDoc = this.jsonSchemaService.findSchemaDoc(docUrl, false);\r\n      return schemaDoc ? schemaDoc.doc.components.schemas[schemaKey] as OpenAPIV3.SchemaObject : null;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Gets all the properties within a schema for property selection.\r\n   * @param index Index number of the data object in the data collection.\r\n   */\r\n  public getAllPropertiesOfSchema(index: number): InputEnumOption[] {\r\n    const docUrl = (this.current.data[index] as any).schemaDoc;\r\n    const schemaKey = this.current.data[index].schema;\r\n    if (this.propertyTreeCache[docUrl + schemaKey]) {\r\n      return this.propertyTreeCache[docUrl + schemaKey];\r\n    }\r\n    const result = this.getProperties(this.getSchamaDef(index));\r\n    this.propertyTreeCache[docUrl + schemaKey] = result;\r\n    return result;\r\n  }\r\n\r\n  private getProperties(schema: OpenAPIV3.SchemaObject, prefix = \"\"): InputEnumOption[] {\r\n    const result: InputEnumOption[] = [];\r\n    Object.keys(schema.properties || {}).forEach(key => {\r\n      const prop = schema.properties[key] as OpenAPIV3.SchemaObject;\r\n      result.push({\r\n        value: prefix + key,\r\n        text: prefix + key,\r\n        title: prop.title || prop.description,\r\n      });\r\n      if (prop.type == \"object\") {\r\n        result.push(...this.getProperties(prop as OpenAPIV3.SchemaObject, prefix + key + \".\"));\r\n      }\r\n    });\r\n    return result;\r\n  }\r\n\r\n  private schemaCache: { [key: string]: InputEnumOption[] } = {\r\n    \"\": [],\r\n  };\r\n\r\n  private propertyTreeCache: { [key: string]: InputEnumOption[] } = {\r\n    \"\": [],\r\n  };\r\n\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ActionExecutor, ApiItemType, BootstrapStyle, Calculations, Datasets,\r\n  JsonSchemaUtils, Payrolls, Usecase, UsecaseAction, UsecaseActionType, UsecaseStatus, UsecaseListItem,\r\n  Usecases, UsecaseView, Translations, ODataResult\r\n} from \"@salaxy/core\";\r\n\r\nimport { SessionService, UiHelpers, UsecaseApiCrudObject, UsecasesService } from \"../../services\";\r\nimport { ApiCrudObjectController } from \"../bases\";\r\nimport { AjaxNg1 } from \"../../ajax\";\r\n\r\n/**\r\n * Usecases controller.\r\n */\r\nexport class UsecasesCrudController extends ApiCrudObjectController<Usecase, UsecaseListItem> {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"Usecases\",\r\n    \"UiHelpers\",\r\n    \"$location\",\r\n    \"$routeParams\",\r\n    \"UsecasesService\",\r\n    \"SessionService\",\r\n    \"AjaxNg1\",\r\n    \"$timeout\",\r\n    \"Calculations\",\r\n    \"Payrolls\",\r\n    \"Datasets\",\r\n    \"$templateCache\",\r\n  ];\r\n\r\n  /** Action executor for the current action. */\r\n  public currentExecutor: ActionExecutor;\r\n\r\n  /** The current item that is being executed on. If not set, will be set to blank. */\r\n  public currentItem: UsecaseApiCrudObject;\r\n\r\n  /**\r\n   * Current view\r\n   */\r\n  private _currentView: UsecaseView;\r\n\r\n  /** Temporary collection of items: Will be replaced by OData query and/or settings. */\r\n  public localStorageItems: Usecase[];\r\n\r\n  private _currentAction: UsecaseAction;\r\n\r\n  private _currentSchema: {\r\n    key?: string,\r\n    schema?: any,\r\n  } = {};\r\n\r\n  private _list: UsecaseListItem[];\r\n\r\n  /**\r\n   * Creates a new UsecasesCrudController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    usecases: Usecases,\r\n    uiHelpers: UiHelpers,\r\n    $location: angular.ILocationService,\r\n    $routeParams: any,\r\n    private usecasesService: UsecasesService,\r\n    private sessionService: SessionService,\r\n    private ajax: AjaxNg1,\r\n    private $timeout: angular.ITimeoutService,\r\n    private calculations: Calculations,\r\n    private payrolls: Payrolls,\r\n\r\n    private datasets: Datasets,\r\n    private $templateCache: angular.ITemplateCacheService,\r\n  ) {\r\n    super(usecases, uiHelpers, $location, $routeParams);\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    super.$onInit();\r\n  }\r\n\r\n  /** Gets the type name of item type, i.e. \"Calculation\" for \"calculation\" enumeration. */\r\n  public get itemType() {\r\n    return \"CalculationListItem[]\";\r\n    // return ApiLogic.getType(this.current?.itemType);\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view for the item.\r\n   * Supports viewing public items from other users as read-only.\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showDetails(item: UsecaseListItem | Usecase): angular.ILocationService {\r\n    // TODO: Consider adding this support in super\r\n    if (this.parentController) {\r\n      return this.parentController.showDetails(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item) + \"@\" + item.owner);\r\n  }\r\n\r\n  /**\r\n   * Gets the activity type of usecase from the settings.\r\n   * @param item List item to check.\r\n   * @returns Information on whether the usecase is active or not - or default usecase (also active).\r\n   */\r\n  public getActive(item: UsecaseListItem): UsecaseStatus {\r\n    return this.usecasesService.getActive(item.uri);\r\n  }\r\n\r\n  /**\r\n   * Gets the activity bg-color of usecase from the settings.\r\n   * @param status Status for color.\r\n   * @returns Bg color for the status.\r\n   */\r\n    public getStatusBgColor(status: UsecaseStatus): string {\r\n      switch( status ) {\r\n        case UsecaseStatus.Inactive:\r\n          return \"bg-warning\";\r\n        case UsecaseStatus.Active:\r\n          return \"bg-info\";\r\n        case UsecaseStatus.Default:\r\n          return \"bg-danger\";\r\n        case UsecaseStatus.Undefined:\r\n        default:\r\n          return \"bg-default\";\r\n      }\r\n    }\r\n\r\n  /**\r\n   * Gets the order  of usecase from the settings.\r\n   * @param item List item to get the order.\r\n   * @returns Order number for the usecase, 0 if not set.\r\n   */\r\n   public getOrder = (item: UsecaseListItem): number => {\r\n    return this.usecasesService.getOrder(item.uri);\r\n  };\r\n\r\n  private toLowerCamelCase(str) {\r\n    // TODO: Move to core\r\n    return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());\r\n  }\r\n\r\n  /**\r\n   * Shows the detail view with a new item that is a copy of the given item.\r\n   * Supports copying public items from other users.\r\n   * @param item Item may be either Container or list item.\r\n   */\r\n  public showCopyAsNew(item: UsecaseListItem | Usecase): angular.ILocationService {\r\n    // TODO: Consider adding this support in super\r\n    if (this.parentController) {\r\n      return this.parentController.showCopyAsNew(item);\r\n    }\r\n    return this.$location.url(this.getDefaults().detailsUrl + this.getId(item) + \"@\" + item.owner + \"/copy-as-new\");\r\n  }\r\n\r\n  /** The data container in the current business object */\r\n  public get usecase(): Usecase {\r\n    return this.currentItem?.usecase;\r\n  }\r\n\r\n  /** The data part of the usecase: Used in data binding. */\r\n  public get data(): any {\r\n    return this.currentItem?.usecase?.data;\r\n  }\r\n\r\n  /**\r\n   * Gets a list of usecases for the current account.\r\n   * First get will start the load process and then the list is cached to controller scope.\r\n   */\r\n  public get list(): UsecaseListItem[] {\r\n    if (!this._list) {\r\n      this._list = [];\r\n      this.getOData(null).then((result: ODataResult<UsecaseListItem>) => {\r\n        this._list = result.items.sort((a, b) => (a.data.order || 100) - (b.data.order || 100));\r\n      });\r\n    }\r\n    return this._list;\r\n  }\r\n\r\n  /**\r\n   * Checks if the given schema is defined in the current usecase: Exists and has any properties.\r\n   * @param schemaNames One or several names of the schema to check whether they are defined.\r\n   * If any schema is exists and has properties, returns true.\r\n   */\r\n  public isDefined(...schemaNames: string[]): boolean {\r\n    return JsonSchemaUtils.isDefined(this.current?.schema, ...schemaNames);\r\n  }\r\n\r\n  /** Returns the whole Open API schema document as editable string. */\r\n  public get editableSchema(): string {\r\n    return JSON.stringify(this.current.schema || \"{}\", null, \"\\t\");\r\n  }\r\n  /** Parses the schema from the given string. */\r\n  public set editableSchema(value: string) {\r\n    this.current.schema = JSON.parse(value);\r\n  }\r\n\r\n  /** Sets the current editable schema (one of the schemas within the Open API document). */\r\n  public setCurrentSchema(key: string): void {\r\n    this._currentSchema.key = key;\r\n    this._currentSchema.schema = this.current.schema.components.schemas[key];\r\n  }\r\n\r\n  /** Gets the current editable schema (one of the schemas within the Open API document). */\r\n  public get currentSchema(): any {\r\n    return this._currentSchema.schema;\r\n  }\r\n\r\n  /** Gets the property name / key of the current editable schema (one of the schemas within the Open API document). */\r\n  public get currentSchemaKey(): string {\r\n    return this._currentSchema.key;\r\n  }\r\n\r\n  /** Creates a new current editable schema (one of the schemas within the Open API document). */\r\n  public createSchema() {\r\n    // TODO: Add this to UI Helpers (as dialog) and search for prompt().\r\n    const name = window.prompt(Translations.get(\"SALAXY.NG1.UsecaseDetailsComponent.createSchemaName\"));\r\n    // TODO: Add property name validation / fix.\r\n    this._currentSchema.key = name;\r\n    this._currentSchema.schema = {\r\n      type: \"object\",\r\n      title: `${Translations.get(\"SALAXY.NG1.UsecaseDetailsComponent.createSchemaTitle\")} (${name})`,\r\n      properties: {},\r\n    };\r\n    this.current.schema.components.schemas[name] = this._currentSchema.schema;\r\n  }\r\n\r\n  /** Removes an schema from this usecase. */\r\n  public deleteSchema(key: string) {\r\n    delete this.current.schema.components.schemas[key];\r\n    if (this.currentSchemaKey == key) {\r\n      this._currentSchema.key = Object.keys(this.current.schema.components.schemas)[0];\r\n      this._currentSchema.schema = this._currentSchema.key ? this.current.schema.components.schemas[this._currentSchema.key] : null;\r\n    }\r\n  }\r\n\r\n  /** The currently selected editable action (script). */\r\n  public get currentAction(): UsecaseAction {\r\n    return this._currentAction;\r\n  }\r\n  public set currentAction(value: UsecaseAction) {\r\n    this._currentAction = value;\r\n    this.currentExecutor = new ActionExecutor(value);\r\n  }\r\n\r\n  /**\r\n   * Current editable view.\r\n   */\r\n  public get currentView() {\r\n    return this._currentView;\r\n  }\r\n  public set currentView(value: any) {\r\n    const key = \"salaxy-dynamic-templates/usecase-custom-view.html\";\r\n    this.$templateCache.remove(key);\r\n    if (value?.content?.trim()) {\r\n      this.$templateCache.put(key, value.content);\r\n    }\r\n    this._currentView = value;\r\n  }\r\n\r\n  /** Overrides the save for clear cache. */\r\n  public save(): Promise<Usecase> {\r\n    this.usecasesService.clearCache();\r\n    return super.save();\r\n  }\r\n\r\n  /** Create a new action / script to this usecase. */\r\n  public createAction() {\r\n    this.currentAction = {\r\n      actionType: UsecaseActionType.ClientScript,\r\n      uiColor: BootstrapStyle.Default,\r\n      uiText: Translations.get(\"SALAXY.NG1.UsecaseDetailsComponent.createAction\"),\r\n      content: \"// Add script here.\"\r\n    };\r\n    this.current.actions.push(this.currentAction);\r\n  }\r\n\r\n  /** Creates a new view and sets it as current. */\r\n  public createView() {\r\n    this.currentView = {\r\n      label: null,\r\n      description: null,\r\n      content: \"<p>Create your view here.</p>\",\r\n    };\r\n    (this.current as any).views.push(this.currentView);\r\n  }\r\n\r\n  /** Overrides the default reload for clearing the cache. */\r\n  public reload(): Promise<Usecase> {\r\n    return super.reload().then((value) => {\r\n      this.usecasesService.setToCache(value);\r\n      return value;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Refreshes the current usecase to cache: Used in preview.\r\n   */\r\n  public refreshCurrentInCache() {\r\n    this.usecasesService.setToCache(this.current);\r\n  }\r\n\r\n  /** Removes an action from this usecase. */\r\n  public deleteAction(action: UsecaseAction) {\r\n    if (!action) {\r\n      return;\r\n    }\r\n    this.current.actions.splice(this.current.actions.indexOf(action), 1);\r\n    if (this.currentAction == action) {\r\n      this.currentAction = this.current.actions[0];\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Removes a view from this usecase.\r\n   */\r\n  public deleteView(view: UsecaseView) {\r\n    if (!view) {\r\n      return;\r\n    }\r\n    this.current.views.splice(this.current.views.indexOf(view), 1);\r\n    if (this.currentView == view) {\r\n      this.currentView = this.current.views[0];\r\n    }\r\n  }\r\n\r\n  /** Executes the current action with the current item. */\r\n  public async executeAction(action?: UsecaseAction): Promise<ActionExecutor> {\r\n    const executor = action ? new ActionExecutor(action) : this.currentExecutor;\r\n    await executor.execute(this.currentItem, this.sessionService.session, this.ajax);\r\n    if (executor.isAsync) {\r\n      this.$timeout();\r\n    }\r\n    return executor;\r\n  }\r\n\r\n  /**\r\n   * Opens a dialog for selecting the current item for which to execute a usecase.\r\n   * @param type Type of item to select: Select from dialog, new or null/empty.\r\n   */\r\n  public selectItem(type: \"select\" | \"new\" | null) {\r\n    if (!type) {\r\n      this.currentItem = null;\r\n      return;\r\n    }\r\n    switch (this.current.itemType) {\r\n      case ApiItemType.Calculation:\r\n      case ApiItemType.CalculationPaid:\r\n        if (type == \"new\") {\r\n          this.currentItem = this.calculations.getBlank();\r\n        } else {\r\n          const calcType = this.current.itemType == ApiItemType.CalculationPaid ? \"paid\" : \"draft\";\r\n          this.uiHelpers.openSelectCalcs(calcType, \"Select a calculation for demo\").then((result) => {\r\n            if (result.action == \"ok\" && result.item.length > 0) {\r\n              const loader = this.uiHelpers.showLoading();\r\n              this.calculations.getSingle(result.item[0].id).then((calc) => {\r\n                this.currentItem = calc;\r\n                calc.usecase.uri = this.current.uri;\r\n                loader.dismiss();\r\n              });\r\n            }\r\n          });\r\n        }\r\n        return;\r\n      case ApiItemType.PayrollDetails:\r\n        if (type == \"new\") {\r\n          this.currentItem = this.payrolls.getBlank();\r\n        } else {\r\n          alert(\"TODO: Payroll selection not yet supported.\");\r\n        }\r\n        return;\r\n      case ApiItemType.Dataset:\r\n        if (type == \"new\") {\r\n          this.currentItem = this.datasets.getBlank();\r\n        } else {\r\n          this.uiHelpers.openSelect(\"Select a dataset\").then((listItem) => {\r\n            if (listItem) {\r\n              const loader = this.uiHelpers.showLoading();\r\n              this.datasets.getSingle(listItem.id).then((payload) => {\r\n                this.currentItem = payload;\r\n                payload.usecase.uri = this.current.uri;\r\n                loader.dismiss();\r\n              });\r\n            }\r\n          });\r\n        }\r\n        return;\r\n      default:\r\n        alert(`Item type ${this.current.itemType} not supported for debug data.`);\r\n        return;\r\n    }\r\n  }\r\n\r\n  /** Implements the getDefaults of ApiCrudObjectController */\r\n  public getDefaults() {\r\n    return {\r\n      listUrl: this.listUrl || \"/usecases\",\r\n      detailsUrl: this.detailsUrl || \"/usecases/details/\",\r\n      oDataTemplateUrl: \"salaxy-components/odata/lists/Usecases.html\",\r\n      oDataOptions: {},\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  BootstrapStyle,\r\n  SessionUserCredential,\r\n  Translations,\r\n  WorkflowData,\r\n  WorkflowEvent,\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  CredentialService,\r\n  SessionService,\r\n  UiHelpers,\r\n  WorkflowService,\r\n} from \"../../services\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases/ApiCrudObjectController\";\r\n\r\nimport { WorkflowEditorConfig } from \"./WorkflowEditorConfig\";\r\n\r\n/**\r\n * Controller for implementing workflow logic.\r\n */\r\nexport class WorkflowController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"WorkflowService\",\r\n    \"UiHelpers\",\r\n    \"SessionService\",\r\n    \"CredentialService\",\r\n  ];\r\n\r\n  /**\r\n   * API CRUD controller for the object.\r\n   */\r\n  public apiCtrl: ApiCrudObjectController<any, any>;\r\n\r\n  /**\r\n   * Single wfType to show.\r\n   */\r\n  public wfType: string;\r\n\r\n  /** Returns true if the update is in progress */\r\n  public isUpdating = false;\r\n\r\n  /**\r\n   * Function that is called when a new workflow action has happened..\r\n   * Function has the following locals:  item: the parent item for workflow, isDelete: true/false if the workflow action was a removal of the event.\r\n   */\r\n  public onChange: (params: {\r\n    /** Item details after change */\r\n    item: any,\r\n    /** Delete/creation information */\r\n    isDelete: boolean,\r\n  }) => void;\r\n\r\n  /** Read only flag */\r\n  public readOnly: boolean;\r\n\r\n  private _events: WorkflowEvent[] = [];\r\n\r\n  /**\r\n   * Creates a new WorkflowController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    protected workflowService: WorkflowService,\r\n    protected uiHelpers: UiHelpers,\r\n    protected sessionService: SessionService,\r\n    protected credentialService: CredentialService\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    // no initializations\r\n  }\r\n\r\n  /** Returns the events of given type. */\r\n  public get events(): WorkflowEvent[] {\r\n    const eventsOfType = ((this.apiCtrl.current as any)?.workflowData?.events ?? []).filter((x) => x.type == this.wfType);\r\n    this.modifyArray(eventsOfType, this._events);\r\n    return this._events;\r\n  }\r\n\r\n  /**\r\n   * Returns the current workflow event of the given type.\r\n   * @param wfType Event type of the workflow event.\r\n   * @returns Returns the current workflow event of the given type.\r\n   */\r\n  public getWorkflowEvent(wfType: string): WorkflowEvent {\r\n    return this.getSingleWorkflowEvent(wfType);\r\n  }\r\n\r\n  /**\r\n   * Returns true if the workflow of the current item has an event of the given type.\r\n   * @param wfType Event type of the workflow event.\r\n   * @returns Returns true if the current item contains an event of the given type.\r\n   */\r\n  public hasWorkflowEvent(wfType: string): boolean {\r\n    return !!this.getWorkflowEvent(wfType);\r\n  }\r\n\r\n  /**\r\n   * Adds/updates the workflow event for the current item.\r\n   * @param wfEvent Workflow event to add/update.\r\n   * @returns Reloaded item.\r\n   */\r\n  public saveWorkflowEvent(wfEvent: WorkflowEvent): Promise<any> {\r\n    if (this.isUpdating) {\r\n      return;\r\n    }\r\n    this.isUpdating = true;\r\n    return this.workflowService.saveWorkflowEvent(this.apiCtrl, wfEvent).then((result) => {\r\n      this.isUpdating = false;\r\n      if (this.onChange) {\r\n      this.onChange({ item: result, isDelete: false });\r\n      }\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Deletes the given event or all events with given type.\r\n   * @param wfIdOrType Id or type of the workflow event.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public deleteWorkflowEvent(wfIdOrType: string): Promise<any> {\r\n    if (this.isUpdating) {\r\n      return;\r\n    }\r\n    this.isUpdating = true;\r\n    return this.workflowService.deleteWorkflowEvent(this.apiCtrl, wfIdOrType).then((result) => {\r\n      this.isUpdating = false;\r\n      if (this.onChange) {\r\n        this.onChange({ item: result, isDelete: true });\r\n      }\r\n      return result;\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows a workflow editor for the given event.\r\n   * Saves the event and reloads the item.\r\n   * @param config Configuration for the worklow editor.\r\n   * @param wfEvent Workflow event for the editor.\r\n   * @returns - Reloaded item.\r\n   */\r\n  public showWorkflowEventEditor(config: WorkflowEditorConfig, wfEvent: WorkflowEvent): Promise<any> {\r\n    if (!this.apiCtrl.current) {\r\n      return Promise.resolve(this.apiCtrl.current);\r\n    }\r\n\r\n    config.title = config.title || \"SALAXY.NG1.WorkFlowIssueComponent.showWorkflowEventEditorTitle\";\r\n\r\n    return this.uiHelpers.openEditDialog(\r\n      \"salaxy-components/modals/workflow/WorkflowEventEdit.html\",\r\n      wfEvent,\r\n      {\r\n        ...config,\r\n        readOnly: this.readOnly,\r\n      }\r\n    ).then((dialogResult) => {\r\n      if (dialogResult.action === \"ok\") {\r\n        return this.saveWorkflowEvent(dialogResult.item);\r\n      } else {\r\n        return Promise.resolve(this.apiCtrl.current);\r\n      }\r\n    });\r\n  }\r\n\r\n  /** Returns avatar for the given credential. */\r\n  public getCredential(credentialId: string): SessionUserCredential {\r\n    return (this.credentials.find((x) => x.id === credentialId) || {});\r\n  }\r\n\r\n  /** Gets the credetial of the current assigned-to person or undefined if there is no assignment. */\r\n  public getAssignedTo(): SessionUserCredential | undefined {\r\n    const assignedTo = this.getWorkflowEvent(\"PartnerMessageAssignedTo\")?.assignedTo;\r\n    if (!assignedTo) {\r\n      return undefined;\r\n    }\r\n    return this.getCredential(assignedTo);\r\n  }\r\n\r\n  /** Returns credentials for the current account. */\r\n  public get credentials(): SessionUserCredential[] {\r\n    return this.workflowService.credentials;\r\n  }\r\n\r\n  /** Returns the credential for current session */\r\n  public get self(): SessionUserCredential {\r\n    return this.workflowService.self;\r\n  }\r\n\r\n  /**\r\n   * Responds to button click with appropriate UI logic.\r\n   * @param type The button that was clicked.\r\n   * @param credential The credential to assign to. Only for type \"assign\". Use undefined to remove assignment.\r\n   */\r\n  public buttonClick(type: \"close\" | \"assign\" | \"issue\", credential?: SessionUserCredential): void {\r\n    switch (type) {\r\n      case \"close\":\r\n        if (this.hasWorkflowEvent(\"PartnerMessageClosed\")) {\r\n          this.deleteWorkflowEvent(\"PartnerMessageClosed\");\r\n        } else {\r\n          this.saveWorkflowEvent({\r\n            type: \"PartnerMessageClosed\",\r\n            ui: BootstrapStyle.Success,\r\n            message: Translations.get(\"SALAXY.UI_Terms.checked\")\r\n          });\r\n        }\r\n        return;\r\n      case \"issue\":\r\n        if (this.hasWorkflowEvent(\"PartnerMessageIssue\")) {\r\n          this.deleteWorkflowEvent(\"PartnerMessageIssue\");\r\n        } else {\r\n          this.showWorkflowEventEditor(\r\n            { title: undefined, showUi: false },\r\n            { type: \"PartnerMessageIssue\", ui: BootstrapStyle.Danger, message: \"\" }\r\n          );\r\n        }\r\n        return;\r\n      case \"assign\":\r\n        if (credential) {\r\n          this.saveWorkflowEvent({\r\n            type: \"PartnerMessageAssignedTo\",\r\n            ui: BootstrapStyle.Primary,\r\n            message: credential.email || credential.avatar.displayName,\r\n            assignedTo: credential.id,\r\n          });\r\n        } else {\r\n          this.deleteWorkflowEvent(\"PartnerMessageAssignedTo\");\r\n        }\r\n        return;\r\n      default:\r\n        throw new Error(\"Not implemented: \" + type);\r\n    }\r\n  }\r\n\r\n  private modifyArray(\r\n    source: any[],\r\n    target: any[]) {\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    target.splice(0, target.length);\r\n    target.push(...source);\r\n  }\r\n\r\n  private getSingleWorkflowEvent(wfType: string): WorkflowEvent {\r\n    if (!this.apiCtrl.current || !wfType) {\r\n      return null;\r\n    }\r\n\r\n    const workflowData: WorkflowData = (this.apiCtrl.current as any)?.workflowData;\r\n    if (!workflowData || !workflowData.events) {\r\n      return null;\r\n    }\r\n    return workflowData.events.find((x) => (x.type || \"\").toLowerCase() === wfType.toLowerCase());\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport {\r\n  ApiCrudObject,\r\n  ApiListItem,\r\n  Attachment,\r\n  Record,\r\n  Records,\r\n  WorkflowData,\r\n  WorkflowEvent,\r\n} from \"@salaxy/core\";\r\n\r\nimport {\r\n  UiHelpers,\r\n  UploadService,\r\n} from \"../../services\";\r\n\r\nimport { ApiCrudObjectController } from \"../bases/ApiCrudObjectController\";\r\n\r\ntype WorkflowPayload = ApiCrudObject & { workflowData: WorkflowData };\r\n\r\nfunction isWorkflowPayload(model: WorkflowPayload | ApiListItem): model is WorkflowPayload {\r\n  return (model as WorkflowPayload).workflowData !== undefined;\r\n}\r\n\r\nfunction isMessagesListItem(model: WorkflowPayload | ApiListItem): model is ApiListItem {\r\n  return (model as ApiListItem).messages !== undefined;\r\n}\r\n\r\n/**\r\n * Controller for implementing workflow badge logic.\r\n */\r\nexport class WorkflowBadgeController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"UiHelpers\",\r\n    \"Records\",\r\n    \"UploadService\",\r\n  ];\r\n\r\n /**\r\n  * API CRUD controller for the object.\r\n  */\r\n  public apiCtrl: ApiCrudObjectController<any, any>;\r\n\r\n  /**\r\n   * wfTypes to show as badges.\r\n   */\r\n  public wfTypes: string[];\r\n\r\n  /** Bound model: ApiListItem or object with WorkflowData */\r\n  public model: ApiListItem | WorkflowPayload | null;\r\n\r\n  /** Visual mode of the component: horizontal or vertical (default). */\r\n  public mode: \"horizontal\" | \"vertical\";\r\n\r\n  private _events: WorkflowEvent[] = [];\r\n\r\n  /**\r\n   * Creates a new WorkflowBadgeController\r\n   * @ignore\r\n   */\r\n  constructor(\r\n    private uiHelpers: UiHelpers,\r\n    private records: Records,\r\n    private uploadService: UploadService,\r\n  ) {\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    // no initializations\r\n  }\r\n\r\n  /** Workflow events for ui. */\r\n  public get events() {\r\n    if (isWorkflowPayload(this.model)) {\r\n      const eventsOfTypes = (this.model.workflowData?.events ?? []).filter( (x) => !this.wfTypes || this.wfTypes.length == 0 || this.wfTypes.indexOf(x.type) >= 0);\r\n      this.modifyArray(eventsOfTypes, this._events);\r\n    }\r\n    else if (isMessagesListItem(this.model)){\r\n      const eventsOfTypes = [];\r\n      for(const msg of this.model.messages)  {\r\n        const eventOfType = this.toWorkflowEvent(msg);\r\n        if (!this.wfTypes || this.wfTypes.length == 0 || this.wfTypes.indexOf(eventOfType.type) >=0) {\r\n          eventsOfTypes.push(eventOfType);\r\n        }\r\n      }\r\n      this.modifyArray(eventsOfTypes, this._events);\r\n    }\r\n    else {\r\n      this.modifyArray([], this._events);\r\n    }\r\n\r\n    return this._events;\r\n  }\r\n\r\n  /** Opens a display for workflow event details */\r\n  public showEventDetails(original: WorkflowEvent) {\r\n    const ensureItem = (): Promise<any> => {\r\n      if (isMessagesListItem(this.model)) {\r\n        // Support old worker based lists\r\n        const id = this.apiCtrl.getApi().getBaseUrl() === \"/accounts/workers\" ?\r\n        this.model.otherId : this.model.id;\r\n        return this.apiCtrl.getApi().getSingle(id);\r\n      } else {\r\n        return Promise.resolve(this.model);\r\n      }\r\n    };\r\n\r\n    const getWorkflowEvent = () : Promise<{event: WorkflowEvent, record: Record }> => {\r\n      if (original?.id) {\r\n        return ensureItem().then( (item ) => {\r\n          return  Promise.resolve(item.workflowData.events.find(x => x.id == original.id)).then( result => {\r\n            if (!result) {\r\n              // Return original\r\n              return { event: original, record: null };\r\n            }\r\n            if (!result.record) {\r\n              return { event: result, record: null};\r\n            }\r\n            return this.records.getSingle(result.record).then( (record) =>{\r\n              return { event: result, record };\r\n            });\r\n          });\r\n        });\r\n        }\r\n      return Promise.resolve({event: original, record: null});\r\n    };\r\n\r\n    getWorkflowEvent().then( (result) => {\r\n      this.uiHelpers.openEditDialog(\r\n        \"salaxy-components/modals/workflow/WorkflowBadgeDetails.html\",\r\n        result,\r\n        {\r\n          getAttachmentDownloadUrl: (attachment) => this.getAttachmentDownloadUrl(attachment),\r\n          getAttachmentIcon: (attachment) => this.getAttachmentIcon(attachment),\r\n        }\r\n      );\r\n    });\r\n\r\n  }\r\n\r\n    /** Returns file icon for the attachment. */\r\n    private getAttachmentIcon(attachment: Attachment): string {\r\n      return this.uploadService.getFileIcon(attachment?.fileName);\r\n    }\r\n\r\n    /** Returns download url for the attachment. */\r\n    private getAttachmentDownloadUrl(attachment: Attachment): string {\r\n      return this.uploadService.getFileUrl(attachment?.contentId);\r\n    }\r\n  private toWorkflowEvent(messageString: string): WorkflowEvent {\r\n    if (!messageString) {\r\n      return {};\r\n    }\r\n\r\n    // [type] (Ui[ui]):[message] ([User] at [yyyy-MM-dd HH:mm] to [assignedTo] id [id])\r\n\r\n    const uiStartX = messageString.indexOf(\"(Ui\");\r\n    const uiEndX = messageString.indexOf(\"):\", uiStartX + 3);\r\n    const type = (messageString.substring(0, uiStartX - 1) || \"\");\r\n    const ui = messageString.substring(uiStartX + 3, uiEndX).toLowerCase();\r\n    let rest = messageString.substring(uiEndX + 3);\r\n    const messageEndX = rest.lastIndexOf(\"(\");\r\n    const message = rest.substring(0, messageEndX).trim();\r\n    rest = rest.substring(messageEndX + 1); // Remove (\r\n    rest = rest.substring(0, rest.length - 1); // Remove )\r\n\r\n    let id = \"\";\r\n    const idx = rest.lastIndexOf(\" id \");\r\n    if (idx >= 0) {\r\n      id = rest.substring(idx + 4);\r\n      rest = rest.substring(0, idx);\r\n    }\r\n\r\n    let assignedTo = \"\";\r\n    const aIdx = rest.lastIndexOf(\" to \");\r\n    if (aIdx >= 0) {\r\n      assignedTo = rest.substring(aIdx + 4);\r\n      rest = rest.substring(0, aIdx);\r\n    }\r\n\r\n    let time = \"\";\r\n    const tIdx = rest.lastIndexOf(\" at \");\r\n    if (tIdx >= 0) {\r\n      time = rest.substring(tIdx + 4);\r\n      rest = rest.substring(0, tIdx);\r\n      // time\r\n      time = time.replace(\" \", \"T\")+\"Z\";\r\n    }\r\n    const user = rest;\r\n    return {\r\n      id,\r\n      type,\r\n      ui,\r\n      user,\r\n      assignedTo,\r\n      message,\r\n      time,\r\n    } as WorkflowEvent;\r\n  }\r\n\r\n  private modifyArray(\r\n    source: any[],\r\n    target: any[]) {\r\n    if (angular.equals(source, target)) {\r\n      return;\r\n    }\r\n    target.splice(0, target.length);\r\n    target.push(...source);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/** Abstract Base class for salaxy components */\r\nexport abstract class ComponentBase implements angular.IComponentOptions {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public abstract bindings: any;\r\n\r\n    /**\r\n     * Controller has the actual implementation of the component.\r\n     * Same Controller may be reused between different components with different views and binding.\r\n     */\r\n    public abstract controller;\r\n\r\n    /** The default template for the component. */\r\n    public abstract defaultTemplate;\r\n\r\n    /**\r\n     * Set the template-url attribute to specify your custom template.\r\n     * @ignore\r\n     */\r\n    public templateUrl = [\"$element\", \"$attrs\" , ($element: JQLite, $attrs: angular.IAttributes) => {\r\n        if ($attrs.templateUrl) {\r\n            return $attrs.templateUrl;\r\n        }\r\n        return this.defaultTemplate;\r\n    }];\r\n}\r\n","import { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Simple presentation of Salaxy account info: employer and/or worker data\r\n * @example\r\n * ```html\r\n * <salaxy-account-info></salaxy-account-info>\r\n * ```\r\n */\r\nexport class AccountInfo extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to controller implementation\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AccountInfo.html\";\r\n}\r\n","import { PartnerController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Component that assures that customer has specified a partner.\r\n * @example\r\n * ```html\r\n * <salaxy-assure-partner><main>This content is shown if partner selected!</main></salaxy-assure-partner>\r\n * ```\r\n */\r\nexport class AssurePartner extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {};\r\n\r\n    /**\r\n     * The \"main\" element contents is shown if the partner has been selected. Defaults to current partner info.\r\n     * The \"header\" element is shown before the \"main\" Defaults to \"Service provided by\" + an actions drop-down.\r\n     */\r\n    public transclude = {\r\n        main: \"?main\",\r\n        header: \"?header\",\r\n    };\r\n\r\n    /** Uses the AccountAuthorizationController */\r\n    public controller = PartnerController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AssurePartner.html\";\r\n}\r\n","import { AccountAuthorizationController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a card for granting authorization\r\n * @example\r\n * ```html\r\n * <div ng-controller=\"AccountAuthorizationController as authCtrl\">\r\n *   <div class=\"row\">\r\n *     <div class=\"col-xs-12 col-sm-6 col-md-4 col-lg-3\" ng-repeat=\"site in authCtrl.partnerIntegrationSites\">\r\n *       <salaxy-auth-card auth-id=\"site.id\"></salaxy-auth-card>\r\n *     </div>\r\n *   </div>\r\n * </div>\r\n * ```\r\n */\r\nexport class AuthCard extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** Id that specifies what auth card to be shown */\r\n        authId: \"<\",\r\n        /** If set to true, the switch is not shown on the card. */\r\n        hideSwitch: \"@\",\r\n    };\r\n\r\n    /** Uses the AccountAuthorizationController */\r\n    public controller = AccountAuthorizationController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AuthCard.html\";\r\n}\r\n","import { AccountAuthorizationController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of all authorized accounts which can act on behalf of this account.\r\n * @example\r\n * ```html\r\n * <salaxy-authorized-accounts></salaxy-authorized-accounts>\r\n * ```\r\n */\r\nexport class AuthorizedAccounts extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = AccountAuthorizationController.crudBindings;\r\n\r\n    /**\r\n     * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n     * These are positioned to the right side of the table header (thead).\r\n     */\r\n    public transclude = {\r\n        header: \"?header\",\r\n    };\r\n\r\n    /** Uses the AccountAuthorizationController */\r\n    public controller = AccountAuthorizationController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AuthorizedAccounts.html\";\r\n}\r\n","import { AccountAuthorizationController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of all authorizing accounts on behalf of which this account can act.\r\n * @example\r\n * ```html\r\n * <salaxy-authorizing-accounts></salaxy-authorizing-accounts>\r\n * ```\r\n */\r\nexport class AuthorizingAccounts extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n    };\r\n\r\n    /**\r\n     * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n     * These are positioned to the right side of the table header (thead).\r\n     */\r\n    public transclude = {\r\n        header: \"?header\",\r\n    };\r\n\r\n    /** Uses the AccountAuthorizationController */\r\n    public controller = AccountAuthorizationController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AuthorizingAccounts.html\";\r\n}\r\n","import { CertificateController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of all certificates which has been generated for this account.\r\n * @example\r\n * ```html\r\n * <salaxy-certificates></salaxy-certificates>\r\n * ```\r\n */\r\nexport class Certificates extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = CertificateController.crudBindings;\r\n\r\n    /**\r\n     * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n     * These are positioned to the right side of the table header (thead).\r\n     */\r\n    public transclude = {\r\n        header: \"?header\",\r\n    };\r\n\r\n    /** Uses the CertificateController */\r\n    public controller = CertificateController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/Certificates.html\";\r\n}\r\n","import { CredentialController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of all login credentials which can access this account.\r\n * @example\r\n * ```html\r\n * <salaxy-credentials></salaxy-credentials>\r\n * ```\r\n */\r\nexport class Credentials extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      showEdit: \"<\",\r\n    };\r\n\r\n    /**\r\n     * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n     * These are positioned to the right side of the table header (thead).\r\n     */\r\n    public transclude = {\r\n        header: \"?header\",\r\n    };\r\n\r\n    /** Uses the CredentialController */\r\n    public controller = CredentialController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/Credentials.html\";\r\n}\r\n","import { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a language selection control.\r\n * @example\r\n * ```html\r\n * <salaxy-language-selector></salaxy-language-selector>\r\n * ```\r\n */\r\nexport class LanguageSelector extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/LanguageSelector.html\";\r\n\r\n}\r\n","import { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a Login / Logout -button.\r\n * When anonymous, the button shows the login button.\r\n * When loggen in shows: Logout and links to Palkkaus Account and User Account pages.\r\n * @example\r\n * ```html\r\n * <salaxy-login-button redirect-url=\"'/my-page'\"></salaxy-login-button>\r\n * ```\r\n */\r\nexport class LoginButton extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n        /** URL to which the user should be redirected. When you specify string, use quotes. */\r\n        redirectUrl: \"<\",\r\n\r\n        /** If specified, sets the login text. Default is \"SALAXY.UI_Terms.login\"  */\r\n        loginText: \"@\",\r\n\r\n        /** If specified, sets the button class. Default is \"btn-default\". */\r\n        btnClass: \"@\",\r\n    };\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/LoginButton.html\";\r\n\r\n}\r\n","import { SigningController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the signature for the current account for signing.\r\n * @example\r\n * ```html\r\n * <salaxy-signing ng-ref=\"$ctrl.$signing\"></salaxy-signing>\r\n * <div ng-if=\"$ctrl.$signing.isSigningOk\">\r\n *  Signature is OK => Show the rest of the page\r\n * </div>\r\n * ```\r\n */\r\nexport class Signing extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to controller implementation\r\n     */\r\n    public bindings = {\r\n      /** If true, shows the component even if the Signing is already OK. */\r\n      showAlways: \"<\",\r\n      /** If true, component shows success popup */\r\n      showInPopup: \"<\",\r\n    };\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SigningController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/Signing.html\";\r\n}\r\n","import { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Simple presentation of Salaxy user info: employer and/or worker data\r\n * @example\r\n * ```html\r\n * <salaxy-user-info></salaxy-user-info>\r\n * ```\r\n */\r\nexport class UserInfo extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n    };\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/UserInfo.html\";\r\n\r\n}\r\n","\r\nimport { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit the avatar information: Picture upload, Initials + color or Gravatar.\r\n * @example\r\n * ```html\r\n * <salaxy-account-avatar-edit></salaxy-account-avatar-edit>\r\n * ```\r\n */\r\nexport class AccountAvatarEdit extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/account/AccountAvatarEdit.html\";\r\n\r\n}\r\n","\r\nimport { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Editing UI of Contact information for account.\r\n * @example\r\n * ```html\r\n * <salaxy-account-contact-edit></salaxy-account-contact-edit>\r\n * ```\r\n */\r\nexport class AccountContactEdit extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate =  \"salaxy-components/account/AccountContactEdit.html\";\r\n\r\n}\r\n","import { CalcEmploymentController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows / edits the relevant employment relation:\r\n * Employer, if the current user is worker\r\n * Worker, if the current user is employer or potentially both in some future admin / pro scenarios.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-employment model=\"$ctrl.currentCalc\"></salaxy-calc-employment>\r\n * ```\r\n */\r\nexport class CalcEmployment extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = {\r\n    /** The calculation that is being edited  */\r\n    model: \"<\",\r\n\r\n    /**\r\n     * If true, will also update the calculation rows from employment relation when the employment\r\n     * relation is selected. By default, does not update the rows.\r\n     */\r\n    updateRows: \"<\",\r\n  };\r\n\r\n  /** Uses the CalcEmploymentController */\r\n  public controller = CalcEmploymentController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/2022/CalcEmployment.html\";\r\n}\r\n","import { CalcRows2019Controller } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a mobile friendly rows editor for addding calculation rows: Salaries, expenses, benefits etc.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-rows-editor parent=\"$ctrl.current\" title=\"Matkalaskun rivit\" on-commit=\"$ctrl.recalculate()\" show-edit-buttons=\"false\" show-gross-totals=\"true\"\r\n            template-url=\"\"\r\n            categories=\"['expenses']\"\r\n            is-in-edit=\"!$ctrl.current.isReadOnly\">\r\n * ```\r\n */\r\nexport class CalcRowsEditor extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = CalcRows2019Controller.bindings;\r\n\r\n  /**\r\n   * The \"footer\" is at the bottom of the rows list where \"Add new row\" buttons would typically be.\r\n   */\r\n  public transclude = {\r\n    footer: \"?footer\",\r\n  };\r\n\r\n  /** Uses the CalcRows2019Controller */\r\n  public controller = CalcRows2019Controller;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/2022/CalcRowsEditor.html\";\r\n}\r\n","import { Calculator2022Controller } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * The **CalcUsecase** is the 2022 version of the calculator (Calc) that supports\n * usecases: customizations to user interfaces and logic using HTML and JavaScript.\n * It is expected to eventually replace the old Calc component.\n *\n * The component provides functionality for:\n *\n * 1. Selecting the Employment relation / Worker to the calculation (employer if the current user is Worker)\n * 2. Selecting the usecase if one is not provided in the URI.\n * 3. Defining the Worktime information: Period, Absences and holidays.\n * 4. Defining the calculation rows: salary, expences, benefits, deductions etc.\n * 5. Showing the results as charts and reports.\n * 6. Starting the payment process\n *\n * Controllers are defined in **salaxy.ng1.controllers**. Most of the functionality comes from Calculator2022Controller.\n * The view (html) can be modified using the usecase view mechanism.\n * @example\r\n * ```html\r\n * <salaxy-calc-usecase model=\"'new'\"></salaxy-calc-usecase>\r\n * ```\r\n */\r\nexport class CalcUsecase extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = Calculator2022Controller.crudBindings;\r\n\r\n    /** Uses the Calculator2022Controller */\r\n    public controller = Calculator2022Controller;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/2022/CalcUsecase.html\";\r\n\r\n}\r\n","\r\nimport { ApiCrudObjectControllerBindings, Payroll4CrudController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * EXPERIMENTAL new version of the Payroll Details component.\r\n * Payroll (Palkkalista) is a list of employees who receive salary or wages from a particular organization.\r\n * Typical usecase is that a a company has e.g. a monthly salary list that is paid\r\n * at the end of month. For next month, a copy is then made from the latest list and\r\n * the copy is potentially modified with the changes of that particular month.\r\n * Payroll can also be started from scratch either by just writing salaries from\r\n * e.g. an e-mail or by uploading an Excel sheet.\r\n * @example\r\n * ```html\r\n * <salaxy-payroll-details></salaxy-payroll-details>\r\n * ```\r\n */\r\nexport class PayrollDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /** The action buttons shown by the component */\r\n    actions = \"<\";\r\n    /** Currently selected view in the Payroll  */\r\n    headerView = \"@\";\r\n  }());\r\n\r\n  /** Uses the PayrollCrudController */\r\n  public controller = Payroll4CrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/payrollV4/PayrollDetails.html\";\r\n}\r\n","import { ApiCrudObjectControllerBindings, Payroll4CrudController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * EXPERIMENTAL new version of the Payroll Details component.\r\n * Payroll (Palkkalista) is a list of employees who receive salary or wages from a particular organization.\r\n * Typical usecase is that a a company has e.g. a monthly salary list that is paid\r\n * at the end of month. For next month, a copy is then made from the latest list and\r\n * the copy is potentially modified with the changes of that particular month.\r\n * Payroll can also be started from scratch either by just writing salaries from\r\n * e.g. an e-mail or by uploading an Excel sheet.\r\n * @example\r\n * ```html\r\n * <salaxy-payroll-details-list></salaxy-payroll-detais-list>\r\n * ```\r\n */\r\nexport class PayrollDetailsList extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n   /**\r\n    * Option to hide New payroll button.\r\n    * Set this true if the site has action buttons configured elsewhere.\r\n    */\r\n    public hideButton = \"<\";\r\n\r\n   /**\r\n    * Mode of the payroll. Supports \"service\" or default.\r\n    * In \"service\" mode the payroll has less funtionality and payment is disabled.\r\n    */\r\n    public mode = \"<\";\r\n  }());\r\n\r\n\r\n  /**\r\n   * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n   * These are positioned to the right side of the table header (thead).\r\n   */\r\n  public transclude = {\r\n    header: \"?header\",\r\n  };\r\n\r\n  /** Uses the PayrollCrudController */\r\n  public controller = Payroll4CrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/payrollV4/PayrollDetailsList.html\";\r\n}\r\n","\r\nimport { ApiCrudObjectControllerBindings, PayrollCrudController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Payroll (Palkkalista) is a list of employees who receive salary or wages from a particular organization.\r\n * Typical usecase is that a a company has e.g. a monthly salary list that is paid\r\n * at the end of month. For next month, a copy is then made from the latest list and\r\n * the copy is potentially modified with the changes of that particular month.\r\n * Payroll can also be started from scratch either by just writing salaries from\r\n * e.g. an e-mail or by uploading an Excel sheet.\r\n * @example\r\n * ```html\r\n * <salaxy-payroll-edit></salaxy-payroll-edit>\r\n * ```\r\n */\r\nexport class PayrollEdit extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /** The action buttons shown by the component */\r\n    actions = \"<\";\r\n  }());\r\n\r\n  /** Uses the PayrollCrudController */\r\n  public controller = PayrollCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/payroll/PayrollEdit.html\";\r\n}\r\n","import { ApiCrudObjectControllerBindings, PayrollCrudController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Payroll (Palkkalista) is a list of employees who receive salary or wages from a particular organization.\r\n * Typical usecase is that a a company has e.g. a monthly salary list that is paid\r\n * at the end of month. For next month, a copy is then made from the latest list and\r\n * the copy is potentially modified with the changes of that particular month.\r\n * Payroll can also be started from scratch either by just writing salaries from\r\n * e.g. an e-mail or by uploading an Excel sheet.\r\n * @example\r\n * ```html\r\n * <salaxy-payroll-list></salaxy-payroll-list>\r\n * ```\r\n */\r\nexport class PayrollList extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n   /**\r\n    * Option to hide New payroll button.\r\n    * Set this true if the site has action buttons configured elsewhere.\r\n    */\r\n    public hideButton = \"<\";\r\n\r\n   /**\r\n    * Mode of the payroll. Supports \"service\" or default.\r\n    * In \"service\" mode the payroll has less funtionality and payment is disabled.\r\n    */\r\n    public mode = \"<\";\r\n  }());\r\n\r\n\r\n  /**\r\n   * Header is mainly meant for buttons (Usually at least \"Add new\").\r\n   * These are positioned to the right side of the table header (thead).\r\n   */\r\n  public transclude = {\r\n    header: \"?header\",\r\n  };\r\n\r\n  /** Uses the PayrollCrudController */\r\n  public controller = PayrollCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/payroll/PayrollList.html\";\r\n}\r\n","import { ODataQueryController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of calculations\r\n * @example\r\n * ```html\r\n * <salaxy-paryoll-select-list category=\"draft\" limit-to=\"5\"></salaxy-payroll-select-list>\r\n * ```\r\n */\r\nexport class PayrollSelectList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n       /** Filters list by given field:value */\r\n      filter: \"@\",\r\n\r\n      /** Max count of calculations to show in the list. */\r\n      limitTo: \"<\",\r\n\r\n      /** Status category for the list. Possible categories: draft, paid. Default is paid */\r\n      category: \"@\",\r\n\r\n      /**\r\n       * List of statuses to include in the list.\r\n       * WARNING: This may be depricated in v03: Use category and/or $filter instead.\r\n       */\r\n      statusList: \"<\",\r\n\r\n      /**\r\n       * Function that is called when user selects an item in the list.\r\n       * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n       * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n       * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n       */\r\n      onListSelect: \"&\",\r\n\r\n      /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n      selectedItems: \"<\",\r\n\r\n      /** Type of the view. Currently supports \"default\", \"panel\" and \"select\" */\r\n      mode: \"@\",\r\n\r\n      /** OData query options */\r\n      options: \"<\",\r\n\r\n      /** URL to the OData service. */\r\n      url: \"@\",\r\n\r\n      /** Data passed from the parent to the component / view */\r\n      data: \"<\",\r\n\r\n       /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n      readOnly: \"<\",\r\n\r\n      /**\r\n       * CRUD controller that implements Delete and potentially other methods about the object.\r\n       * If you wish to use this in the view use \"as $controllerName\" syntax\r\n       * @example\r\n       * <salaxy-odata-table crud-controller=\"CalculationCrudController as $crud\">\r\n       */\r\n      crudController: \"@\",\r\n\r\n    };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/payroll/PayrollSelectList.html\";\r\n\r\n}\r\n","import { ODataQueryController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of calculations\r\n * @example\r\n * ```html\r\n * <salaxy-payroll-details-select-list category=\"draft\" limit-to=\"5\"></salaxy-payroll-details-select-list>\r\n * ```\r\n */\r\nexport class PayrollDetailsSelectList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n       /** Filters list by given field:value */\r\n      filter: \"@\",\r\n\r\n      /** Max count of calculations to show in the list. */\r\n      limitTo: \"<\",\r\n\r\n      /** Status category for the list. Possible categories: draft, paid. Default is paid */\r\n      category: \"@\",\r\n\r\n      /**\r\n       * List of statuses to include in the list.\r\n       * WARNING: This may be depricated in v03: Use category and/or $filter instead.\r\n       */\r\n      statusList: \"<\",\r\n\r\n      /**\r\n       * Function that is called when user selects an item in the list.\r\n       * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n       * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n       * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n       */\r\n      onListSelect: \"&\",\r\n\r\n      /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n      selectedItems: \"<\",\r\n\r\n      /** Type of the view. Currently supports \"default\", \"panel\" and \"select\" */\r\n      mode: \"@\",\r\n\r\n      /** OData query options */\r\n      options: \"<\",\r\n\r\n      /** URL to the OData service. */\r\n      url: \"@\",\r\n\r\n      /** Data passed from the parent to the component / view */\r\n      data: \"<\",\r\n\r\n       /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n      readOnly: \"<\",\r\n\r\n      /**\r\n       * CRUD controller that implements Delete and potentially other methods about the object.\r\n       * If you wish to use this in the view use \"as $controllerName\" syntax\r\n       * @example\r\n       * <salaxy-odata-table crud-controller=\"CalculationCrudController as $crud\">\r\n       */\r\n      crudController: \"@\",\r\n\r\n    };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/payrollV4/PayrollDetailsSelectList.html\";\r\n\r\n}\r\n","import { CalcIrRowsController, Calculator2019Controller } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Editor for Incomes Register (Tulorekisteri) rows from Calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-ir-rows model=\"'url'\"></salaxy-calc-ir-rows>\r\n * ```\r\n */\r\nexport class CalcIrRows extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Calculator2019Controller.crudBindings;\r\n\r\n  /** Uses the CalcIrRowsController */\r\n  public controller = CalcIrRowsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/rows/CalcIrRows.html\";\r\n\r\n}\r\n","import { CalcRows2019Controller } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a grid-type rows editor for addding calculation rows: Salaries, expenses, benefits etc.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-rows-2019-editor categories=\"['expenses']\" parent=\"$ctrl.currentCalc\" mode=\"edit\"\r\n *     title=\"Kulukorvaukset\"></salaxy-calc-rows-2019-editor>\r\n * ```\r\n */\r\nexport class CalcRows2019Editor extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = CalcRows2019Controller.bindings;\r\n\r\n    /** Uses the CalcRows2019Controller */\r\n    public controller = CalcRows2019Controller;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/rows/CalcRows2019Editor.html\";\r\n\r\n}\r\n","import { CalcRowCostAccountingController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows the cost accounting details for the calculation row.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-row-cost-accounting parent=\"$ctrl.parent\" current=\"$ctrl.current\"></salaxy-calc-row-cost-accounting>\r\n * ```\r\n */\r\nexport class CalcRowCostAccounting extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Calculation for the row. */\r\n      calc: \"<\",\r\n      /** The calculation row. */\r\n      row: \"<\",\r\n      /** Forced read only state */\r\n      readOnly: \"<\",\r\n      /**\r\n       * Optional CostAccountingDimensionDefinitions\r\n       * If not set, cost accounting dimensions and their options are read from the settings.\r\n       */\r\n       dimensions: \"<\",\r\n    };\r\n\r\n    /** Uses the CalcRowCostAccountingController */\r\n    public controller = CalcRowCostAccountingController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/rows/CalcRowCostAccounting.html\";\r\n}\r\n","import { CalcRowDimensionInputController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Represents a component for handling dimension input in a calculation row.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-row-dimension-input></salaxy-calc-row-dimension-input>\r\n * ```\r\n */\r\nexport class CalcRowDimensionInput extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Currently edited row */\r\n      row: \"<\",\r\n      /** Dimension definition. */\r\n      definition: \"<\",\r\n      /** Possible inherited dimensions values from upper lever (e.g. calc level to rows) */\r\n      inherited: \"<\",\r\n      /** Forced read only state */\r\n      readOnly: \"<\",\r\n      /**\r\n       * Style of the inputs.\r\n       * Supports empty or 'openClose'. Only available when not readOnly\r\n       */\r\n      inputMode: \"@\",\r\n    };\r\n\r\n    /** Uses the CalcRowDimensionInputController */\r\n    public controller = CalcRowDimensionInputController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/rows/CalcRowDimensionInput.html\";\r\n\r\n}\r\n","import { CalcsIrRowsController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Component for showing tabulator based report of ir rows of given calculations\r\n * @example\r\n * ```html\r\n * <salaxy-calcs-ir-rows calcs=\"[calc1,calc2]\" lang=\"fi\"></salaxy-calcs-ir-rows calcs\r\n * ```\r\n */\r\nexport class CalcsIrRows extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = {\r\n    /** Calculations for report. */\r\n    calcs: \"<\",\r\n    /** The language of report. */\r\n    lang: \"<\"\r\n  };\r\n\r\n  /** Uses the CalcsIrRowsController */\r\n  public controller = CalcsIrRowsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/rows/CalcsIrRows.html\";\r\n\r\n}\r\n","import { Calculator2019Controller } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * The **salaxy.ng1.components.Calc** is the generic Angular-based salary calculator implementation.\r\n * It shows the basic features required for a salary calculator user interfaces:\r\n *\r\n * 1. Setting the Worker for the calculation\r\n * 2. Defining the Worktime information: Period, Absences and holidays.\r\n * 3. Defining the Salary and the benefits\r\n * 4. Defining Expenses, benefits, household subsidies etc.\r\n * 5. Showing the results as charts and reports.\r\n *\r\n * Controllers are defined in **salaxy.ng1.controllers**. Most of the functionality comes from Calculator2019Controller.\r\n * The views can be modified separately for each component using the templateUrl. See documentation for details.\r\n * @example\r\n * ```html\r\n * <salaxy-calc model=\"'new'\"></salaxy-calc>\r\n * ```\r\n */\r\nexport class Calc extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = Calculator2019Controller.crudBindings;\r\n\r\n    /** Uses the Calculator2019Controller */\r\n    public controller = Calculator2019Controller;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/Calc.html\";\r\n\r\n}\r\n","import { CalcChartController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Chart.js based chart.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-chart role=\"worker\" calc=\"$ctrl.currentCalc\"></salaxy-calc-chart>\r\n * ```\r\n */\r\nexport class CalcChart extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = {\r\n\r\n    /** Calculation for which the chart is rendered.  */\r\n    calc: \"<\",\r\n    /** Role for which the chart is rendered. Currently, 'worker' and 'employer' are supported. Employer is the default. */\r\n    role: \"@\",\r\n    /** If true, the Y axis of this chart is scaled so that if worker and employer charts are side to side, their Y axis are the same */\r\n    scaleYAxis: \"<\",\r\n    /** Type of the chart - \"pie\" and \"bar\" (default) are currently supported. */\r\n    chartType: \"<\",\r\n    /** - colors: Custom colors for the chart as a string containing hex values of the colors, separated by comma */\r\n    colors: \"@\",\r\n  };\r\n\r\n  /** Uses the CalcChartController */\r\n  public controller = CalcChartController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcChart.html\";\r\n}\r\n","import { ODataQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows lists of calculations\r\n * @example\r\n * ```html\r\n * <salaxy-calc-dashboard></salaxy-calc-dashboard>\r\n * ```\r\n */\r\n\r\nexport class CalcDashboard extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n\r\n  public bindings = {\r\n    /**\r\n     * Option to hide new calc button.\r\n     * Set this true if the site has action buttons configured elsewhere.\r\n     */\r\n    hideButton: \"<\",\r\n\r\n    /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n    readOnly: \"<\",\r\n\r\n  };\r\n\r\n  /** Uses the ODataQueryController */\r\n  public controller = ODataQueryController;\r\n  // TODO: Consider should this be ODataQueryController or ApiCrudObjectController.\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcDashboard.html\";\r\n\r\n}\r\n","import { ODataQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of calculations\r\n * @example\r\n * ```html\r\n * <salaxy-calc-list category=\"draft\" limit-to=\"5\"></salaxy-calc-list>\r\n * ```\r\n */\r\nexport class CalcList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n       /** Filters list by given field:value */\r\n      filter: \"@\",\r\n\r\n      /** Max count of calculations to show in the list. */\r\n      limitTo: \"<\",\r\n\r\n      /** Status category for the list. Possible categories: draft, paid. Default is paid */\r\n      category: \"@\",\r\n\r\n      /**\r\n       * List of statuses to include in the list.\r\n       * WARNING: This may be depricated in v03: Use category and/or $filter instead.\r\n       */\r\n      statusList: \"<\",\r\n\r\n      /**\r\n       * Function that is called when user selects an item in the list.\r\n       * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n       * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n       * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n       */\r\n      onListSelect: \"&\",\r\n\r\n      /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n      selectedItems: \"<\",\r\n\r\n      /** Type of the view. Currently supports \"default\", \"panel\" and \"select\" */\r\n      mode: \"@\",\r\n\r\n      /** OData query options */\r\n      options: \"<\",\r\n\r\n      /** URL to the OData service. */\r\n      url: \"@\",\r\n\r\n      /** Data passed from the parent to the component / view */\r\n      data: \"<\",\r\n\r\n       /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n      readOnly: \"<\",\r\n\r\n      /**\r\n       * CRUD controller that implements Delete and potentially other methods about the object.\r\n       * If you wish to use this in the view use \"as $controllerName\" syntax\r\n       * @example\r\n       * <salaxy-odata-table crud-controller=\"CalculationCrudController as $crud\">\r\n       */\r\n      crudController: \"@\",\r\n\r\n    };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcList.html\";\r\n\r\n}\r\n","import { Calculator2019Controller } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows an introduction text (instructions) for the user when user starts a new calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-new-intro model=\"$ctrl.current\"></salaxy-calc-new-intro>\r\n * ```\r\n */\r\nexport class CalcNewIntro extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = Calculator2019Controller.crudBindings;\r\n\r\n    /** Uses the Calculator2019Controller */\r\n    public controller = Calculator2019Controller;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcNewIntro.html\";\r\n\r\n}\r\n","import { CalcReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the report for the given calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-report calc=\"$ctrl.currentCalc\" report-type=\"'salarySlip'\" template-name=\"'salarySlipV2'\"></salaxy-calc-report>\r\n * ```\r\n */\r\nexport class CalcReport extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** The calculation for the report. */\r\n    calc: \"<\",\r\n    /** Calculation report type (for example: salarySlip, employerReport or paymentReport) */\r\n    reportType: \"<\",\r\n    /** Template for the report (for example: salarySlipV2, employerReportV2, paymentReportV2 ) */\r\n    templateName: \"<\",\r\n    /** If true, uses the current style of the site. The default value is false. */\r\n    applySiteStyles: \"<\",\r\n    /** The language for report*/\r\n    lang: \"<\",\r\n    /** If true, adds the preview watermark to the report */\r\n    preview: \"<\",\r\n  };\r\n\r\n  /** Uses the CalcReportController */\r\n  public controller = CalcReportController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcReport.html\";\r\n\r\n}\r\n","import { CalcReportsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the salary reports for the given calculations.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-reports calcs=\"$ctrl.calcs\" report-type=\"'salarySlip'></salaxy-calc-reports>\r\n * ```\r\n */\r\nexport class CalcReports extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** The calculations for the report. */\r\n    calcs: \"<\",\r\n    /** Current report type. */\r\n    reportType: \"<\",\r\n    /**\r\n     * The default view shown in the UI: \"partial\" (default), \"page1\" or \"full\".\r\n     * Please note that not all reports support \"page1\" or \"full\".\r\n     */\r\n    view: \"@\",\r\n    /** If true, adds the preview watermark to the report */\r\n    preview: \"<\",\r\n  };\r\n\r\n  /** Uses the CalcReportsController */\r\n  public controller = CalcReportsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcReports.html\";\r\n\r\n}\r\n","import { Calculator2019Controller } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the results view for the Calculator\r\n * @example\r\n * ```html\r\n * <salaxy-calc-results model=\"$ctrl.current\"></salaxy-calc-results>\r\n * ```\r\n */\r\nexport class CalcResults extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n    public bindings = Calculator2019Controller.crudBindings;\r\n\r\n    /** Uses the Calculator2019Controller */\r\n    public controller = Calculator2019Controller;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcResults.html\";\r\n\r\n}\r\n","import { CalcRowTypeController } from \"../../controllers\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Select component for Calculations row types.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-row-type name=\"rowType\" model=\"row\" label=\"Basic datepicker\"></salaxy-calc-row-type>\r\n * ```\r\n */\r\nexport class CalcRowType extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n      /** Type of the input element. Options are typeahead and list (select, search-list and radio may be supported later). */\r\n      type: \"@\",\r\n\r\n      /** If set, filters the rows based on categories (plus rowTypes if set) */\r\n      categories: \"<\",\r\n\r\n      /** If set, shows only these types (plus categories if set) */\r\n      rowTypes: \"<\",\r\n\r\n      /** Name and identifier of the typeahead input */\r\n      name: \"@\",\r\n\r\n      /**\r\n       * Placeholder text in the typeahead input.\r\n       * Default is 'SALAXY.UI_Terms.select'.\r\n       */\r\n      placeholder: \"@\",\r\n\r\n      /** The calculation row that this component modifies. */\r\n      model: \"<\",\r\n\r\n      /**\r\n       * Function that is called after the row type and potentially kind and message have been changed.\r\n       * @example <salaxy-calc-row-type on-row-changed=\"$ctrl.commitNewRow()\"></salaxy-calc-row-type>\r\n       */\r\n      onRowChanged: \"&\",\r\n\r\n      /** If true, the list will show all the children under each parent that is shown */\r\n      showChildren: \"<\",\r\n\r\n    };\r\n\r\n    /** Uses the InputCalcRowTypeController */\r\n    public controller = CalcRowTypeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcRowType.html\";\r\n}\r\n","import { ApiCrudObjectControllerBindings, CalcSharingReceiptActionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the sharing receipt action control for the given calculation id.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-sharing-receipt-action model=\"$ctrl\" type=\"'approve'\"></salaxy-calc-sharing-receipt-action>\r\n * ```\r\n */\r\nexport class CalcSharingReceiptAction extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /** Sharing action (approve or reject) */\r\n    public type = \"<\";\r\n    /** Disables the control. */\r\n    public disabled = \"<\";\r\n    /** Optional style class to use for button. Defaults to 'btn-block btn-sm' */\r\n    public buttonClass = \"@\";\r\n    /** Shows only icon in button. Used in compact views, i.e. panels */\r\n    public iconOnly = \"<\";\r\n  }());\r\n\r\n  /** Uses the CalcSharingReceiptActionController */\r\n  public controller = CalcSharingReceiptActionController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcSharingReceiptAction.html\";\r\n\r\n}\r\n","import { CalcLeavesController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Displays payments for current calculation period.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-leaves ng-ref=\"$calcLeaves\" calc=\"$ctrl.current.calc\" worktime=\"$ctrl.current.worktime\"></salaxy-calc-leaves>\r\n * ```\r\n */\r\nexport class CalcLeaves extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The calculation*/\r\n      calc: \"<\",\r\n      /** The worktime*/\r\n      worktime: \"<\",\r\n    };\r\n\r\n    /** Uses the CalcLeavesController */\r\n    public controller = CalcLeavesController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcLeaves.html\";\r\n\r\n}\r\n","import { Calculator2019Controller } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows information about the Worker / employment relation within a calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-worker-info model=\"$ctrl.myWorkerOrCalc\"></salaxy-calc-worker-info>\r\n * ```\r\n */\r\nexport class CalcWorkerInfo extends ComponentBase {\r\n\r\n  // TODO: If the component is removed from payment pages, consider having it simply as an include within calculations\r\n  // (and not as a component) OR consider having a calc-component with several different layouts.\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Calculator2019Controller.crudBindings;\r\n\r\n  /** Uses the Calculator2019Controller */\r\n  public controller = Calculator2019Controller;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/calc/CalcWorkerInfo.html\";\r\n\r\n}\r\n","import { CalcWorktimeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * UI for setting the Worktime properties within the calculator\r\n * The process starts by selecting the period based on which relevatn worktime\r\n * data is fetched: Holidays, Absences and later Hours.\r\n * Calculation rows are then added based on this worktime.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-worktime calc=\"$ctrl.currentCalc\"></salaxy-calc-worktime>\r\n * ```\r\n */\r\nexport class CalcWorktime extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The calculation that the component edits (shows in read-only mode). */\r\n      calc: \"<\",\r\n    };\r\n\r\n    /** Uses the CalcWorktimeController */\r\n    public controller = CalcWorktimeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcWorktime.html\";\r\n\r\n}\r\n","import { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a Payment -button or Payment Channel selection dropdown or both for the Calculation or Payroll\r\n * @example\r\n * ```html\r\n * <salaxy-pay-button model=\"$ctrl.current\"></salaxy-pay-button>\r\n * ```\r\n */\r\nexport class PayButton extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n      /**\r\n       * The current business item that is being paid: Either Calculation or PayrollDetails.\r\n       * Currently only supports direct reference. May later support 'url' etc. like CRUD controllers.\r\n       */\r\n      model: \"<\",\r\n\r\n      /** Expression for ng-disabled of the input. */\r\n      disabled: \"<\",\r\n\r\n      /**\r\n       * Additional class / classes for button. Can also be used to override default btn-primary class styles.\r\n       * (i.e. <salaxy-pay-button button-class=\"btn-lg uppercase btn-success\">)\r\n       */\r\n      buttonClass: \"@\",\r\n\r\n      /**\r\n       * Text for the payment button.\r\n       * This is typically customized in custom payment scenarios.\r\n       */\r\n      label: \"@\",\r\n\r\n      /** Mode is either \"pay-button\" (default), \"channel-select\", \"button-and-channel\" or \"button-and-channel-horizontal\" */\r\n      mode: \"@\",\r\n\r\n      /** Called when the payment channel has been changed. */\r\n      onPaymentChannelChange: \"&\",\r\n    };\r\n\r\n    /**\r\n     * Uses the PaymentController\r\n     * This is on purpose not typed. This is because we want the injection to be active for possible customer\r\n     * specific overrides.\r\n     */\r\n    public controller = \"PaymentController\";\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/PayButton.html\";\r\n}\r\n","import { CalculationEditorController, ApiCrudObjectControllerBindings } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Editor for the given calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-editor model=\"'url'\"></salaxy-calc-editor>\r\n * ```\r\n */\r\nexport class CalcEditor extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n\r\n\r\n    }());\r\n\r\n    /** Uses the CalcReportController */\r\n    public controller = CalculationEditorController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcEditor.html\";\r\n\r\n}\r\n","import { CalcCostAccountingController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the cost accounting details for the calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-cost-accounting current=\"$ctrl.current\"></salaxy-calc-cost-accounting>\r\n * ```\r\n */\r\nexport class CalcCostAccounting extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The calculation. */\r\n      calc: \"<\",\r\n      /** Forced read only state */\r\n      readOnly: \"<\",\r\n      /**\r\n       * Optional CostAccountingDimensionDefinitions\r\n       * If not set, cost accounting dimensions and their options are read from the settings.\r\n       */\r\n      dimensions: \"<\",\r\n\r\n      /**\r\n       * Style of the inputs.\r\n       * Supports empty or 'openClose'. Only available in not readOnly\r\n       */\r\n      inputMode: \"@\",\r\n    };\r\n\r\n    /** Uses the CalcCostAccountingController */\r\n    public controller = CalcCostAccountingController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CalcCostAccounting.html\";\r\n\r\n}\r\n","import { CostAccountingController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the cost accounting details for the calculation.\r\n * @example\r\n * ```html\r\n * <salaxy-cost-accounting current=\"calc.accounting.dimensions\" scope=\"calculation\"></salaxy-cost-accounting>\r\n * ```\r\n */\r\nexport class CostAccounting extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Dimension values for edit. */\r\n      current: \"<\",\r\n\r\n      /** Possible inherited dimensions values from upper lever (e.g. calc level to rows) */\r\n      inherited: \"<\",\r\n\r\n      /** Forced read only state */\r\n      readOnly: \"<\",\r\n      /**\r\n       * Optional CostAccountingDimensionDefinitions\r\n       * If not set, cost accounting dimensions and their options are read from the settings.\r\n       */\r\n      dimensions: \"<\",\r\n      /**\r\n       * Scope for the cost accounting: calculation or row.\r\n       */\r\n      scope: \"@\",\r\n\r\n      /**\r\n       * Style of the inputs.\r\n       * Supports empty or 'openClose'. Only available when not readOnly\r\n       */\r\n      inputMode: \"@\"\r\n    };\r\n\r\n    /** Uses the CostAccountingController */\r\n    public controller = CostAccountingController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/CostAccounting.html\";\r\n\r\n}\r\n","import { ComponentBase } from \"../_ComponentBase\";\r\nimport { SalaryDateKindController } from \"../../controllers\";\r\n\r\n/**\r\n * Renders a Salary Date Kind selection -button for the Calculation or Payroll\r\n * @example\r\n * ```html\r\n * <salaxy-salary-date-kind-button disabled=\"$ctrl.isReadOnly\" model=\"$ctrl.current.workflow\"></salaxy-salary-date-kind-button>\r\n * ```\r\n */\r\nexport class SalaryDateKindButton extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n      /**\r\n       * The current object containing salaryDateKind -field: Either Calculation or PayrollDetails.\r\n       */\r\n      model: \"<\",\r\n\r\n      /** Expression for ng-disabled of the input. */\r\n      disabled: \"<\",\r\n\r\n      /**\r\n       * Additional class / classes for button. Can also be used to override default btn-primary class styles.\r\n       * (i.e. <salaxy-pay-button button-class=\"btn-lg uppercase btn-success\">)\r\n       */\r\n      buttonClass: \"@\",\r\n\r\n      /** Called when the salary date kind has been changed. */\r\n      onSalaryDateKindChange: \"&\",\r\n    };\r\n\r\n    /**\r\n     * Uses the SalaryDateKindController\r\n     */\r\n    public controller = SalaryDateKindController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/calc/SalaryDateKindButton.html\";\r\n}\r\n","import { ContactInfoController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the customer service contact info and reference to zendesk's help-widget.\r\n * Options to show short content and hide contact info.\r\n * @example\r\n * ```html\r\n * <salaxy-contact-info></salaxy-contact-info>\r\n * ```\r\n */\r\nexport class ContactInfo extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /** If true, short version of the content is shown */\r\n    showShortContent: \"=\",\r\n\r\n    /** If true, contact info is hidden */\r\n    hideContactInfo: \"<\",\r\n  };\r\n  /** Uses the AlertController */\r\n  public controller = ContactInfoController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/communications/ContactInfo.html\";\r\n}\r\n","import { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { MessageThreadCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit and create new user interface for message thread.\r\n * @example\r\n * ```html\r\n * <salaxy-message-thread></salaxy-message-thread>\r\n * ```\r\n */\r\nexport class MessageThread extends ComponentBase {\r\n\r\n  /**\r\n   * Allows injecting HTML within the component.\r\n   */\r\n  public transclude = {\r\n    /** A \"header\" element can be used to add HTML on top of the message thread (where the header is now). */\r\n    header: \"?header\",\r\n    /** A \"header-new\" element overrides the default text for new message thread. */\r\n    headerNew: \"?headerNew\",\r\n  };\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n    /** Role of the current user: typically \"owner\" (default) or \"otherParty\" */\r\n    public role = \"@\";\r\n\r\n    /** Salaxy ID (IBAN format) for the other party (besides the message thread owner) */\r\n    public otherParty = \"<\";\r\n\r\n    /**\r\n     * If set, shows a drop-down for these options using the enum component.\r\n     * Typically, use object with string key-value pairs.\r\n     */\r\n    public otherPartyOptions = \"<\";\r\n\r\n    /**\r\n     * If set, the controller will mark a message thread as open once it has been loaded.\r\n     * If the value is true, the message is marked as read immediately.\r\n     * If the value is number, the controller waits the given amount of seconds before marking the item as read.\r\n     */\r\n    public markAsRead = \"<\";\r\n\r\n    /**\r\n     * URL for the approval view.\r\n     */\r\n    public approvalUrl = \"@\";\r\n\r\n  }());\r\n\r\n  /** Uses the EmailMessageController */\r\n  public controller = MessageThreadCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/communications/MessageThread.html\";\r\n\r\n}\r\n","import { VarmaBannerController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Varma banner component for displaying Varma popup\r\n * @example\r\n * ```html\r\n * <salaxy-varma-banner></salaxy-varma-banner>\r\n * ```\r\n */\r\nexport class VarmaBanner extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Current calculation */\r\n      calc: \"<\"\r\n\r\n    };\r\n\r\n    /** Uses the VarmaBannerController */\r\n    public controller = VarmaBannerController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/communications/VarmaBanner.html\";\r\n\r\n}\r\n","import { WelcomeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a detail a Welcome message depending on the user profile.\r\n * Typically the first component on the front page.\r\n * @example\r\n * ```html\r\n * <salaxy-welcome></salaxy-welcome>\r\n * ```\r\n */\r\nexport class Welcome extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /**\r\n         * If set to true, the settings are handled by proxy:\r\n         * we do not ask the user to change the settings in\r\n         * the Welcome screen (mainly Pension or Insurance).\r\n         */\r\n        settingsByProxy: \"<\",\r\n    };\r\n\r\n    /** Uses the WelcomeController */\r\n    public controller = WelcomeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/communications/Welcome.html\";\r\n\r\n}\r\n","import { WorkerHourlyReportController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Component for HourlyReport usecase\r\n * @example\r\n * ```html\r\n * <salaxy-hourly-report></salaxy-hourly-report>\r\n * ```\r\n */\r\nexport class HourlyReport extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n     public bindings = WorkerHourlyReportController.bindings;\r\n\r\n    /** Uses the WorkerHourlyReportController */\r\n    public controller = WorkerHourlyReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/communications/messages/message-types/HourlyReport.html\";\r\n\r\n}\r\n","import {\r\n  ListControllerBaseBindings,\r\n  WorkerTimerController,\r\n} from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\nclass TimerBindings extends ListControllerBaseBindings {\r\n  /** The calculation that the component edits (shows in read-only mode). */\r\n  timerMode = \"@\";\r\n  /**\r\n   * CRUD controller that typically defines the values for url template and\r\n   */\r\n  public crudController = \"<\";\r\n}\r\n/**\r\n * Component for timer usecase\r\n * @example\r\n * ```html\r\n * <salaxy-timer></salaxy-timer>\r\n * ```\r\n */\r\nexport class Timer extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = new TimerBindings();\r\n\r\n  /** Uses the WorkerTimerController */\r\n  public controller = WorkerTimerController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate =\r\n    \"salaxy-components/communications/messages/message-types/Timer.html\";\r\n}\r\n","import { WorkerExpenseReportController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Component for ExpenseReport usecase\r\n * @example\r\n * ```html\r\n * <salaxy-expense-report ng-if=\"$ctrl.current\" parent=\"$ctrl.getMessage().contentData\" report-type=\"$ctrl.current.usecase.data.protoId\"></salaxy-expense-report>\r\n * ```\r\n */\r\nexport class ExpenseReport extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n     public bindings = WorkerExpenseReportController.bindings;\r\n\r\n    /** Uses the WorkerExpenseReportController */\r\n    public controller = WorkerExpenseReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/communications/messages/message-types/ExpenseReport.html\";\r\n\r\n}\r\n","import { ODataQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n\r\n/**\r\n * Shows a list of messages.\r\n * @example\r\n * ```html\r\n * <salaxy-message-thread-list limit-to=\"5\" read-only=\"false\"></salaxy-message-thread-list>\r\n * ```\r\n */\r\nexport class MessageThreadList extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /** Max count of threads to show in the list. */\r\n    limitTo: \"<\",\r\n\r\n    /** If readOnly is true, create buttons from the list view are hidden if readOnly property is supported */\r\n    readOnly: \"<\",\r\n\r\n    /**\r\n     * URL for the approval view.\r\n     */\r\n    approvalUrl: \"@\",\r\n\r\n  };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/communications/MessageThreadList.html\";\r\n\r\n}\r\n","import { DatepickerController, InputBase } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Modified ui.bootstrap.datepicker.\r\n * The component can be bound to a string typed variable. The standard ui.bootstrap.datepicker can be bound successfully only to a Date variable.\r\n * @example\r\n * ```html\r\n * <salaxy-datepicker name=\"myDatepicker\" ng-model=\"temp\" label=\"Basic datepicker\"></salaxy-datepicker>\r\n * ```\r\n */\r\nexport class Datepicker extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n        /** options for ui.bootstrap.datepicker */\r\n        datepickerOptions: \"<\",\r\n\r\n        /**\r\n         * Preset algorithms for enabled/disabled dates.\r\n         * Currently, only \"salary\" is supported for salary dates, but more might be added later.\r\n         * If set as \"disable-function\", you should set the disable-function too.\r\n         */\r\n        dateDisabled: \"@\",\r\n\r\n        /** Disable function for date. If set, date-disabled is ignored. */\r\n        disableFunction: \"<\",\r\n\r\n        /** Payment channel. This affects which dates are disabled in the salary date selection. */\r\n        paymentChannel: \"<\",\r\n\r\n        /** Zero payment (no worker net salary payment). This affects which dates are disabled in the salary date selection. */\r\n        zeroPayment: \"<\",\r\n\r\n        /**\r\n         * Minimum available date.\r\n         * Bindable and ISO string version of the datepicker-options.minDate.\r\n         * Currently not supported together with dateDisabled filters.\r\n         */\r\n         minDate: \"<\",\r\n\r\n         /**\r\n          * Maximum available date.\r\n          * Bindable and ISO string version of the datepicker-options.maxDate.\r\n          * Currently not supported together with dateDisabled filters.\r\n          */\r\n         maxDate: \"<\",\r\n\r\n    });\r\n\r\n    /** Uses the DatepickerController */\r\n    public controller = DatepickerController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/Datepicker.html\";\r\n}\r\n","import { DatepickerPopupController, InputBase } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Modified ui.bootstrap.datepickerPopup.\r\n * The component can be bound to a string typed variable. The standard ui.bootstrap.datepickerPopup can be bound successfully only to a Date variable.\r\n * @example\r\n * ```html\r\n *\r\n * <salaxy-datepicker-popup name=\"myDatepickerPopup\" ng-model=\"temp\" label=\"Basic datepicker popup\" label-placement=\"top\"></salaxy-datepicker-popup>\r\n * ```\r\n */\r\nexport class DatepickerPopup extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n        /** options for ui.bootstrap.datepicker */\r\n        datepickerOptions: \"<\",\r\n\r\n        /** popup placement:  */\r\n        popupPlacement: \"@\",\r\n\r\n        /** If 'top', the label is placed on it's own row before input */\r\n        labelPlacement: \"@\",\r\n\r\n        /** Format for the date, default is d.M.yyyy */\r\n        format: \"@\",\r\n\r\n        /**\r\n         * If set to true, sets datepicker-append-to-body to false.\r\n         * By default we set it to true in Salaxy framework,\r\n         * but you may want to set it back to false in e.g. Modal dialogs.\r\n         */\r\n        appendInline: \"@\",\r\n\r\n        /**\r\n         * Preset algorithms for enabled/disabled dates.\r\n         * Currently, only \"salary\" is supported for salary dates, but more might be added later.\r\n         * If set as \"disable-function\", you should set the disable-function too.\r\n         */\r\n        dateDisabled: \"@\",\r\n\r\n        /** Disable function for date. If set, date-disabled is ignored. */\r\n        disableFunction: \"<\",\r\n\r\n        /** Payment channel. This affects which dates are disabled in the salary date selection. */\r\n        paymentChannel: \"<\",\r\n\r\n        /** Zero payment (no worker net salary payment). This affects which dates are disabled in the salary date selection. */\r\n        zeroPayment: \"<\",\r\n\r\n        /**\r\n         * Minimum available date.\r\n         * Bindable and ISO string version of the datepicker-options.minDate.\r\n         * Currently not supported together with dateDisabled filters.\r\n         */\r\n        minDate: \"<\",\r\n\r\n        /**\r\n         * Maximum available date.\r\n         * Bindable and ISO string version of the datepicker-options.maxDate.\r\n         * Currently not supported together with dateDisabled filters.\r\n         */\r\n        maxDate: \"<\",\r\n\r\n    });\r\n\r\n    /** Uses the DatepickerController */\r\n    public controller = DatepickerPopupController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/DatepickerPopup.html\";\r\n}\r\n","import { Objects } from \"@salaxy/core\";\r\n\r\nimport { DateRangeController, InputBase } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Provides a user interface for picking up a date range\r\n * and optionally specifying also the number of working days within that range.\r\n * @example\r\n * ```html\r\n * <salaxy-date-range name=\"myDateRange\" ng-model=\"temp\" label=\"Sample date range\"></salaxy-date-range>\r\n * ```\r\n */\r\nexport class DateRange extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n      /** Options for ui.bootstrap.datepicker */\r\n      datepickerOptions: \"<\",\r\n\r\n      /**\r\n       * Label for the scondary input (Default: SALAXY.NG1.DateRange.labelDaysCount).\r\n       * Translation is attempted.\r\n       */\r\n      labelDaysCount: \"@\",\r\n\r\n      /**\r\n       * Minimum available date.\r\n       * Bindable and ISO string version of the datepicker-options.minDate.\r\n       */\r\n      minDate: \"<\",\r\n\r\n      /**\r\n       * Maximum available date.\r\n       * Bindable and ISO string version of the datepicker-options.maxDate.\r\n       */\r\n      maxDate: \"<\",\r\n\r\n      /**\r\n       * The selection mode is either:\r\n       *\r\n       * - \"range\" for (default) calendar control with start and end.\r\n       * - \"multiple\" for selecting multiple individual dates from a calendar control\r\n       * - \"calc\" for period selection that is optimized for salary calculation (months, 2 weeks, 1/2 months etc.)\r\n       */\r\n      mode: \"@\",\r\n\r\n      /**\r\n       * Fires an event when the model is changing: Any of the values specific to the model are changing: start, end or daysCount.\r\n       * This should typically used instead of ng-change because ng-change will only fire if the object reference changes.\r\n       * On-change fires when dates or day count changes and this is typically what you are looking for.\r\n       * @example <salaxy-date-range ng-model=\"$ctrl.dateRange\" on-change=\"$ctrl.dateRangeChange(value)\"></salaxy-date-range>\r\n       */\r\n      onChange: \"&\",\r\n\r\n    });\r\n\r\n    /** Uses the DateRangeController */\r\n    public controller = DateRangeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/DateRange.html\";\r\n}\r\n","import { FormGroupController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Helper for rendering the HTML for FormGroup:\r\n * This component renders only the label - input html.\r\n * It does not do any of the real form-control logic like ng-model, validations etc. (see salaxy-input for that).\r\n * The \"input\" part of the form group may be a non form control - e.g. just a text.\r\n * Also the label may be hidden.\r\n * @example\r\n * ```html\r\n * <salaxy-form-group label=\"Some label\" class=\"salaxy-read-only\" name=\"div1\"><div class=\"salaxy-read-only-value\">Some text here</div></salaxy-form-group>\r\n * ```\r\n */\r\nexport class FormGroup extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Name of the input - also used as id. */\r\n    name: \"@\",\r\n\r\n    /** Label for the control */\r\n    label: \"@\",\r\n\r\n    /**\r\n     * @deprecated Use \"require\" instead:\r\n     * This attribute overlaps with required/ng-required directive, which produces unexpected results.\r\n     */\r\n    required: \"@\",\r\n\r\n    /** If true the field is required (form validation) */\r\n    require: \"<\",\r\n\r\n    /**\r\n     * Positioning of the label of form-control.\r\n     * Supported values are \"horizontal\" (default), \"no-label\", \"plain\", \"basic\" and \"empty-label\".\r\n     * See FormGourpLabelType for details.\r\n     */\r\n    labelType: \"@\",\r\n\r\n    /**\r\n     * Label columns expressed as Bootstrap grid columns.\r\n     * Default is 'col-sm-4' for label-type: 'horizontal' and 'col-sm-12' for label-type: 'no-label'.\r\n     * Other label-types do not have column classes at the moment.\r\n     */\r\n    labelCols: \"@\",\r\n  };\r\n\r\n  /** Contents of the tag is the input element. */\r\n  public transclude = true;\r\n\r\n  /** Uses the InputController */\r\n  public controller = FormGroupController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/FormGroup.html\";\r\n}\r\n","import { InputBase, InputController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows an input control with label, validation error, info etc.\r\n *\r\n * Basic label-input control for forms.\r\n * @example\r\n * ```html\r\n * <salaxy-input name=\"myInput\" ng-model=\"temp\" label=\"Basic example\"></salaxy-input>\r\n * ```\r\n */\r\nexport class Input extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n        model: \"ngModel\",\r\n\r\n        form: \"?^^form\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n        /** Minimum length for the text value, default is 0 (form validation) */\r\n        minlength: \"@\",\r\n        /** Maximum length for the text value, default is 1024 (form validation) */\r\n        maxlength: \"@\",\r\n        /** Regular expression pattern for validation (form validation) */\r\n        pattern: \"@\",\r\n        /** Type for the input. Defaults to text. Supports currently text and password. */\r\n        type: \"@\",\r\n\r\n     });\r\n\r\n    /** Uses the InputController */\r\n    public controller = InputController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/Input.html\";\r\n}\r\n","\r\nimport { InputBase, InputBooleanController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a boolean input control with label, validation error, info etc.\r\n * @example\r\n * ```html\r\n * <salaxy-input-boolean name=\"myInput\" ng-model=\"temp\" label=\"Basic example\" type=\"radio\"></salaxy-input>\r\n * ```\r\n */\r\n\r\nexport class InputBoolean extends ComponentBase {\r\n\r\n  /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n  public require = {\r\n    model: \"ngModel\",\r\n\r\n    form: \"?^^form\",\r\n};\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n     /** Type of the input element. Options are checkbox, radio, select and switch */\r\n     type: \"@\",\r\n\r\n     /**\r\n      * Text to show as a label for input with value FALSE\r\n      * Supported by types radio and select\r\n      */\r\n     labelFalse: \"@\",\r\n\r\n     /**\r\n      * Text to show as a label for input with value TRUE\r\n      * Supported by types radio, checkbox and select\r\n      */\r\n     labelTrue: \"@\",\r\n\r\n     /**\r\n      * TODO: Is this needed when there's support for 'empty-label' ?\r\n      * BS class for offsetting the input (no-label)\r\n      */\r\n     offsetCols: \"@\",\r\n\r\n     /** If true, the radio buttons are aligned horizontally side-by-side */\r\n     horizontal: \"<\",\r\n\r\n  });\r\n\r\n  /** Uses the InputEnumController */\r\n  public controller = InputBooleanController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/InputBoolean.html\";\r\n}\r\n","import { InputBase, InputEnumController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Select component for enumerations.\r\n * @example\r\n * ```html\r\n * <salaxy-input-enum type=\"select\"  options=\"{FiOy:'Osakeyhtiö', FiTm:'Toiminimi'}\"  name=\"CompanyType\" enum=\"CompanyType\" label=\"Company\" invalid-enums=\"none,other\" required></salaxy-input-enum>\r\n * <salaxy-input-enum type=\"radio\"  name=\"CompanyType\" enum=\"CompanyType\" label=\"Company\" hidden-options=\"unknown\"></salaxy-input-enum>\r\n * <salaxy-input-enum type=\"typeahead\"  name=\"CompanyType\" enum=\"CompanyType\" label=\"Company\" hidden-options=\"unknown\"></salaxy-input-enum>\r\n * ```\r\n */\r\nexport class InputEnum extends ComponentBase {\r\n\r\n  /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n  public require = {\r\n    model: \"ngModel\",\r\n\r\n    form: \"?^^form\",\r\n  };\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Objects.extend(InputBase.crudBindings, {\r\n    /**\r\n     * Binds to an enumeration defined by the Salaxy API.\r\n     * Set the name of the enumeration.\r\n     */\r\n    enum: \"@\",\r\n\r\n    /**\r\n     * TODO: not working well with Typeahead-element\r\n     * Options of the select control as a key-value object.\r\n     */\r\n    options: \"<\",\r\n\r\n    /** Type of the input element. Options are typeahead, select, multi-select, radio and dropdown */\r\n    type: \"@\",\r\n\r\n    /**\r\n     * These values are visible only if they are selected in the data.\r\n     * I.e. after something else is selected, hidden value cannot be selected back.\r\n     * Use for not-selected values (\"Please choose...\") when you do not want selection reversed\r\n     * or legacy data that is not selectable, but may still exist on the server.\r\n     */\r\n    hiddenOptions: \"@\",\r\n\r\n    /**\r\n     * Array or comma separated string to filter the option values to just the given ones.\r\n     * Also sets the order to this order, so works for ordering a given set of values.\r\n     * Note that hiddenOptions is applied first, so if you want e.g. \"undefined\" to appear if selected,\r\n     * you may add it here and it behaves as expected (undefined is still hidden if a value is selevted).\r\n     */\r\n    filter: \"@\",\r\n\r\n    /**\r\n     * Comma serapated list of values that should not be considered as valid in the UI.\r\n     * Default is [\"unknown\"] and is only used when input is \"required\" and input type is \"select\".\r\n     * Use in situations where an unknown/other/none value is set in API but should not be available as an option.\r\n     */\r\n    invalidEnums: \"@\",\r\n\r\n    /** If true, the control is not caching values. */\r\n    disableCache: \"@\",\r\n\r\n    /**\r\n     * Label format for the option. The default format is to show only the text of the option.\r\n     * Options are:\r\n     * \"text\" or empty: only the text of the option is displayed.\r\n     * \"text-value\": in addition to the text, the value is also displayed in the label.\r\n     * \"value\": only the value is displayed.\r\n     */\r\n    labelFormat: \"@\",\r\n\r\n    /**\r\n     * If set, last selected option is stored in LocalStorage and set as default/selected value in element. Currently supported only in type 'select' and 'uib-dropbdown'.\r\n     */\r\n    remember: \"@\",\r\n  });\r\n\r\n  /** Uses the InputEnumController */\r\n  public controller = InputEnumController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/InputEnum.html\";\r\n}\r\n","import { InputCredentialController } from \"../../controllers\";\r\n\r\nimport { InputEnum } from \"./InputEnum\";\r\n\r\n/**\r\n * Select credential.\r\n * @example\r\n * ```html\r\n * <salaxy-input-credential ng-model=\"credential\" type=\"select\"  name=\"Credential\"  label=\"Credential\"></salaxy-input-credential>\r\n * <salaxy-input-credential ng-model=\"credential\" type=\"radio\"  name=\"Credential\" label=\"Credential\" ></salaxy-input-credential>\r\n * <salaxy-input-credential ng-model=\"credential\" type=\"typeahead\"  name=\"Credential\" label=\"Credential\"></salaxy-input-credential>\r\n * ```\r\n */\r\nexport class InputCredential extends InputEnum {\r\n\r\n    constructor() {\r\n      super();\r\n      /** Uses the InputEnumController */\r\n      this.controller = InputCredentialController as any;\r\n    }\r\n}\r\n","\r\nimport { InputBase, InputDurationController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a an editor / display component for a .Net Duration.\r\n * .Net Duration is a string in format \"ddd.hh:mm:ss.ttttttt\".\r\n * @example\r\n * ```html\r\n * <salaxy-input-duration name=\"myInput\" ng-model=\"temp\" label=\"Basic example\"></salaxy-input-duration>\r\n * ```\r\n */\r\n\r\nexport class InputDuration extends ComponentBase {\r\n\r\n  /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n  public require = {\r\n    model: \"ngModel\",\r\n\r\n    form: \"?^^form\",\r\n};\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Objects.extend(InputBase.crudBindings, {});\r\n\r\n  /** Uses the InputDurationController */\r\n  public controller = InputDurationController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/InputDuration.html\";\r\n}\r\n","import { InputBase, InputIncomeTypeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Visual selection for income types (and deductibles) resulting to number code in Incomes register.\r\n * @example\r\n * ```html\r\n * <salaxy-input-income-type name=\"code\" ng-model=\"row.code\" label=\"income type\"></salaxy-input-income-type>\r\n * ```\r\n */\r\nexport class InputIncomeType extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n        /** Type of the input element is either typehead or list. Default is typeahead. */\r\n        type: \"@\",\r\n        /** List of income type codes to exclude from the selection list. */\r\n        hiddenCodes: \"<\",\r\n    });\r\n\r\n    /** Uses the InputIncomeTypeController */\r\n    public controller = InputIncomeTypeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputIncomeType.html\";\r\n}\r\n","import { Objects } from \"@salaxy/core\";\r\n\r\nimport { InputBase, InputNumberController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Input control for numbers.\r\n * @example\r\n * ```html\r\n * <salaxy-input-number name=\"count\" ng-model=\"row.count\" label=\"Number of items\"></salaxy-input-number>\r\n * ```\r\n */\r\nexport class InputNumber extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n      /**\r\n       * Unit for the number.\r\n       * If set, shows a visual clue of the unit.\r\n       * For 'percent' editor value is multiplied by 100.\r\n       */\r\n      unit: \"@\",\r\n\r\n      /**\r\n       * Expression for the allowed Units for the number.\r\n       * If set, shows a selection of control for the unit.\r\n       */\r\n      units: \"<\",\r\n\r\n      /** Minimum number*/\r\n      minimum: \"@\",\r\n\r\n      /** Maximum number*/\r\n      maximum: \"@\",\r\n\r\n      /** Multiple of (step) number*/\r\n      multipleOf: \"@\",\r\n\r\n      /**\r\n       * If true, the input edits negative value: The value is multiplied by -1.\r\n       * E.g. \"3\" days ago => -3.\r\n       */\r\n      negative: \"<\",\r\n\r\n      /** Type of the input element. Options: default or slider */\r\n      type: \"@\",\r\n\r\n      /** Step for slider */\r\n      sliderStep: \"@\",\r\n\r\n    /**\r\n     * Function that is called when the unit has been changed.\r\n     * Function has the following locals:  unit: the selected unit.\r\n     */\r\n      onUnitChange: \"&\",\r\n    });\r\n\r\n    /** Uses the InputNumberController */\r\n    public controller = InputNumberController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputNumber.html\";\r\n}\r\n","\r\nimport { InputBase, InputRruleController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a an editor / display component for a Recurrence Rule (RRule).\r\n * Recurrence rules are a strings defined in iCalendar format, e.g. \"FREQ=MONTHLY;INTERVAL=1\".\r\n * For more information and examples, see http://jakubroztocil.github.io/rrule/ or https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html\r\n * @example\r\n * ```html\r\n * <salaxy-input-rrule name=\"myInput\" ng-model=\"temp\" label=\"Basic example\"></salaxy-input-rrule>\r\n * ```\r\n */\r\n\r\nexport class InputRrule extends ComponentBase {\r\n\r\n  /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n  public require = {\r\n    model: \"ngModel\",\r\n\r\n    form: \"?^^form\",\r\n};\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Objects.extend(InputBase.crudBindings, {});\r\n\r\n  /** Uses the InputRruleController */\r\n  public controller = InputRruleController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/InputRrule.html\";\r\n}\r\n","import { InputBase, InputOccupationTypeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Select component for Occupation types.\r\n * @example\r\n * ```html\r\n * <salaxy-input-occupation-type default-list=\"household\" name=\"occupationType\" ng-model=\"row.occupation\" label=\"occupationType\"></salaxy-input-occupation-type>\r\n * <salaxy-input-occupation-type default-list=\"21490,21510,21532\" name=\"occupationType\" ng-model=\"row.occupation\" label=\"occupationType\"></salaxy-input-occupation-type>\r\n * ```\r\n */\r\nexport class InputOccupationType extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n      /**\r\n       * One or comma-separated list of occupation IDs, or a known keyword to define which occupations are shown\r\n       * Supported keywords: 'household' and 'company'\r\n       * If empty, shows all\r\n       */\r\n      defaultList: \"@\",\r\n\r\n      /**\r\n       * Comma serapated list of values that should not be considered as valid in the UI.\r\n       * Default is [\"other\"] and is only used when input is \"required\".\r\n       * Use in situations where an unknown/other/none value is set in API but should not be available as an option or considered as a valid option.\r\n       */\r\n      invalidEnums: \"@\",\r\n\r\n    });\r\n\r\n    /** Uses the InputOccupationTypeController */\r\n    public controller = InputOccupationTypeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputOccupationType.html\";\r\n}\r\n","import { InputBase, InputController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a textarea control with label, validation error, info etc.\r\n * @example\r\n * ```html\r\n * <salaxy-textarea name=\"myInput\" ng-model=\"temp\" rows=\"5\" label=\"Basic example\"></salaxy-textarea>\r\n * ```\r\n */\r\nexport class Textarea extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n        model: \"ngModel\",\r\n\r\n        form: \"?^^form\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(InputBase.crudBindings, {\r\n\r\n        /** Minimum length for the text value, default is 0 (form validation) */\r\n        minlength: \"@\",\r\n        /** Maximum length for the text value, default is 1024 (form validation) */\r\n        maxlength: \"@\",\r\n        /** Regular expression pattern for validation (form validation) */\r\n        pattern: \"@\",\r\n\r\n        /** The rows property of the textarea. Default is 3. */\r\n        rows: \"<\",\r\n\r\n     });\r\n\r\n    /** Uses the InputController */\r\n    public controller = InputController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/Textarea.html\";\r\n}\r\n","import { ValidationSummaryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a validation summary user interface.\r\n * Currently, this component is used for showing the status of server-side validation,\r\n * but the idea is that later implementation may enable it for using also with client-side validation.\r\n * @example\r\n * ```html\r\n * <salaxy-validation-summary api-validation=\"$ctrl.validationData\">\r\n *       <span>Everything is OK!</span>\r\n * </salaxy-validation-summary>\r\n * ```\r\n */\r\nexport class ValidationSummary extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** The server-side API-validation object that is displayed by this component. */\r\n        apiValidation: \"<\",\r\n\r\n        /** HTML that should be shown when the bound validation data is null. */\r\n        loadingHtml: \"@\",\r\n\r\n        /** Layout of the validation html. Use \"minimal\" for easy customizing*/\r\n        layout: \"@\"\r\n    };\r\n\r\n    /** Inner HTML is shown in case object is valid. */\r\n    public transclude = true;\r\n\r\n    /** Uses the ValidationSummaryController */\r\n    public controller = ValidationSummaryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/ValidationSummary.html\";\r\n}\r\n","import { InputBase, InputAccountingTargetController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Select component for Accounting Targets.\r\n * @example\r\n * ```html\r\n * <salaxy-input-accounting-target></salaxy-input-accounting-target>\r\n * ```\r\n */\r\nexport class InputAccountingTarget extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = InputBase.crudBindings;\r\n\r\n    /** Uses the InputAccountingTargetController */\r\n    public controller = InputAccountingTargetController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputAccountingTarget.html\";\r\n}\r\n","import { InputBase, InputTimeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\n/**\r\n * Input component for time\r\n * @example\r\n * ```html\r\n * <salaxy-input-time type=\"minutes\" name=\"workTime\" label=\"Worktime\" required></salaxy-input-enum>\r\n * <salaxy-input-time type=\"isoTime\" name=\"workTime\" label=\"Worktime\" required></salaxy-input-enum>\r\n * ```\r\n */\r\nexport class InputTime extends ComponentBase {\r\n\r\n  /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n  public require = {\r\n    model: \"ngModel\",\r\n\r\n    form: \"?^^form\",\r\n  };\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = Objects.extend(InputBase.crudBindings, {\r\n    /**\r\n     * Used type in input. Types are minutes and isoTime\r\n     */\r\n    type: \"@\",\r\n  });\r\n\r\n  /** Uses the InputTimeController */\r\n  public controller = InputTimeController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/form-controls/InputTime.html\";\r\n}\r\n","import { InputBase, InputHolidayRowTypeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Form control for defining row type for accrual and holiday pay calculations.\r\n * @example\r\n * ```html\r\n * <salaxy-input-holiday-row-type name=\"salaryType\" ng-model=\"row.salaryType\" label=\"Row type or custom type\"></salaxy-input-holiday-row-type>\r\n * ```\r\n */\r\nexport class InputHolidayRowType extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = InputBase.crudBindings;\r\n\r\n    /** Uses the InputHolidayRowTypeController */\r\n    public controller = InputHolidayRowTypeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputHolidayRowType.html\";\r\n}\r\n","import { InputBase, InputHolidayMultipliersController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Form control for defining multipliers for holiday pay calculations.\r\n * @example\r\n * ```html\r\n * <salaxy-input-holiday-multipliers name=\"multipliers\" ng-model=\"settings.multipliers\" label=\"Multipliers for holiday pay calculation\"></salaxy-input-holiday-multipliers>\r\n * ```\r\n */\r\nexport class InputHolidayMultipliers extends ComponentBase {\r\n\r\n    /** ng-model is required, form tag is optionally used for validation and disabled/readonly */\r\n    public require = {\r\n      model: \"ngModel\",\r\n\r\n      form: \"?^^form\",\r\n  };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = InputBase.crudBindings;\r\n\r\n    /** Uses the InputHolidayMultipliersController */\r\n    public controller = InputHolidayMultipliersController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/form-controls/InputHolidayMultipliers.html\";\r\n}\r\n","import { ActionButtonController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Helper component to generate buttons with known actions such as creating a new worker, new calculation etc.\r\n * @example\r\n * ```html\r\n *  <salaxy-action-button label=\"SALAXY.NG1.WorkerDetailsComponent.newCalculation\" action=\"'newCalcForEmployment'\" options=\"{'id': $ctrl.currentId }\" button-class=\"btn-default pull-right-xs\"></salaxy-action-button>\r\n * ```\r\n */\r\n\r\nexport class ActionButton extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /** Text for the button */\r\n    label: \"@\",\r\n\r\n    /** Additional Bootstrap or custom style classes. Bootstrap I.e. btn-danger, btn-sm, my-btn. Defaults to btn-primary */\r\n    buttonClass: \"@\",\r\n\r\n    /** Disabled but visible */\r\n    disabled: \"<\",\r\n\r\n    /** Options for button. */\r\n    options: \"<\",\r\n\r\n    /**\r\n     * Action to be executed.\r\n     * newCalc: starts a new blank calculation.\r\n     * newCalcForEmployment: starts a new calculation for the given employment id.\r\n     * newPayroll: starts a new blank payroll.\r\n     * newWorker: opens workerWizard for creating a new worker.\r\n     * newMessage: starts a new message thread with partner.\r\n     * payment: Not supported at the moment. opens the payment dialog for the current calculation.\r\n     * newTaxcard: Links to taxcards page. Currently supported only when role is Worker.\r\n     */\r\n    action: \"<\",\r\n\r\n  };\r\n\r\n  /** Uses the NaviController */\r\n  public controller = ActionButtonController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/helpers/ActionButton.html\";\r\n}\r\n","import { AlertController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows an alert box with styling.\r\n *\r\n * Based on Bootstrap alert, but has the following additional functionality:\r\n *\r\n * - primary style (in addition to success, info, warning and danger) for banner type of advertising\r\n * - Icon for better visuality\r\n * - Optional \"Read more\" area\r\n * @example\r\n * ```html\r\n * <salaxy-alert type=\"warning\" text=\"This is a Warning\"></salaxy-alert>\r\n * ```\r\n */\r\nexport class Alert extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n        /**\r\n         * Possibility to speicfy a font-awesome icon.\r\n         * Setting \"none\", will show no icon.\r\n         * If not set, it is determined by type.\r\n         */\r\n        icon: \"@\",\r\n\r\n        /** Type of the alert is the Bootstrap style: Note that also \"primary\" and \"default\" are supported. */\r\n        type: \"@\",\r\n\r\n        /**\r\n         * Alert main content as simple text.\r\n         * You can alternatively provide html as main element.\r\n         */\r\n        text: \"@\",\r\n\r\n        /** If true, the aside part is shown immidiately. Also hides \"read more\"- button. */\r\n        forceMoreInfo: \"<\",\r\n    };\r\n\r\n    /**\r\n     * Transclusion slots\r\n     */\r\n    public transclude = {\r\n        /**\r\n         * The main content of the alert.\r\n         * You can alternatively provide a simple text in \"text\" property.\r\n         */\r\n        main: \"?main\",\r\n\r\n        /**\r\n         * Optional Details part of the alert.\r\n         * Will automatically show \"Read more\" button.\r\n         */\r\n        aside: \"?aside\",\r\n    };\r\n\r\n    /** Uses the AlertController */\r\n    public controller = AlertController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Alert.html\";\r\n}\r\n","import { AvatarController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the Palkkaus Avatar image: This is either an image or a font-icon with a user specific color/initilas combination.\r\n * @example\r\n * ```html\r\n * <salaxy-avatar avatar=\"$ctrl.myAvatar\"></salaxy-avatar>\r\n * ```\r\n */\r\nexport class Avatar extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** The Avatar object that should be rendered */\r\n        avatar: \"=\",\r\n    };\r\n\r\n    /** Uses the AvatarController */\r\n    public controller = AvatarController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Avatar.html\";\r\n\r\n    /** Rendered HTML replaces the original element */\r\n    public replace: true;\r\n}\r\n","import { CalendarController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a monthly calendar where one month is one row and you can show ranges and special days (only partial support).\r\n * Future implementations will support categories / swimlanes of periods (e.g. holidays from several persons)\r\n * and have better support for special days: different types of markers, pop-up etc.\r\n * @example\r\n * ```html\r\n * <salaxy-calendar start=\"'2019-01-5'\" end=\"$ctrl.getToday()\" periods=\"$ctrl.getPeriods()\"></salaxy-chart>\r\n * ```\r\n */\r\nexport class Calendar extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n        /**\r\n         * Start date for the calendar as ISO date yyyy-MM-dd. Renders from the beginning of this month.\r\n         */\r\n        start: \"<\",\r\n\r\n        /**\r\n         * End date of the calendar as ISO date yyyy-MM-dd. Renders until the end of this month.\r\n         */\r\n        end: \"<\",\r\n\r\n        /**\r\n         * Today date for the calendar as ISO date yyyy-MM-dd.\r\n         * Can be set as dately object (e.g. ISO string, JS Date or key string \"today\")\r\n         */\r\n        today: \"<\",\r\n\r\n        /** The data that is plotted on the calendar chart. */\r\n        data: \"<\",\r\n\r\n        /** Optional data mapper function that is used in mapping the data to CalendarSeries array. */\r\n        mapper: \"<\",\r\n\r\n        /** TODO: Remove */\r\n        periods: \"<\",\r\n\r\n        /** TODO: Remove */\r\n        days: \"<\",\r\n\r\n        /** Type of chart: \"align-weekdays\", \"align-left\" or horizontal. */\r\n        mode: \"@\",\r\n\r\n        /**\r\n         * Function that is called when user selects an item in the calendar.\r\n         * Function can have the following locals: type: \"event\" | \"day\", date: string, day: Full calendar day with all the day info,\r\n         * calEvent: The calendar event if type is \"event\", series: Series that the event belongs to or the series that is clicked (not always available).\r\n         * @example <salaxy-calendar on-list-select=\"$ctrl.myCustomSelectFunc(type, date, calEvent)\"></salaxy-calendar>\r\n         */\r\n        onListSelect: \"&\",\r\n\r\n        /** Possibility of specifying a list controller that can be used for item editing. */\r\n        listController: \"<\",\r\n\r\n        /** If set to true, the export buttons are visible. */\r\n        showExport: \"<\",\r\n    };\r\n\r\n    /** Uses the CalendarController */\r\n    public controller = CalendarController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Calendar.html\";\r\n}\r\n","import { ChartController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Controller rendering chart by provided config\r\n * Config type example: config: ChartConfiguration<\"pie\" | \"bar\", { labels: string[]; datasets: any[] }, any>\r\n * Config follows official chart.js ChartConfiguration interface\r\n * @example\r\n * ```html\r\n *  <salaxy-chart config=\"config\"></salaxy-chart>\r\n * ```\r\n */\r\nexport class Chart extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Config of chart */\r\n      config: \"<\",\r\n      /** Custom height of chart */\r\n      customHeight: \"@\",\r\n      /** Custom height of chart */\r\n      customWidth: \"@\",\r\n      /** Custom height of chart */\r\n      customClass: \"@\",\r\n    };\r\n\r\n    /** Uses the ChartController */\r\n    public controller = ChartController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Chart.html\";\r\n}\r\n","import { ModalGenericDialogController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * User interface for debugging definition and values.\r\n * @example\r\n * ```html\r\n * <salaxy-data-mapper model=\"$ctrl.mapper\"></salaxy-data-mapper>\r\n * ```\r\n */\r\nexport class DataMapper extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** The DataMapper that is shown.  */\r\n      model: \"<\",\r\n\r\n      /**\r\n       * Type of the user interface:\r\n       *\r\n       * - \"value-map\" (default) Shows the source values in the table, target mapping is editable.\r\n       * - \"debug\" Full data mapper debugger / editor UI.\r\n       * - \"source-value\" Shows the source values in a table, also the validation column\r\n       * - \"target-value\" Shows the target values in a table, also the validation column\r\n       */\r\n      type: \"@\",\r\n    };\r\n\r\n    /** Uses the ModalGenericDialogController */\r\n    public controller = ModalGenericDialogController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/DataMapper.html\";\r\n}\r\n","import { JsonFormatterController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a JavaScript object JSON as formatted HTML.\r\n * Open attribute accepts a number that indicated how many levels JSON should be open.\r\n * Based on http://azimi.me/json-formatter/demo/demo.html\r\n * @example\r\n * ```html\r\n * <salaxy-json-formatter open=\"1\" json=\"$ctrl.current\"></salaxy-json-formatter>\r\n * <salaxy-json-formatter key=\"'Debugger'\" json=\"$ctrl.sitemap\" open=\"1\" type=\"dialog\"></salaxy-json-formatter>\r\n * ```\r\n */\r\nexport class JsonFormatter extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** The JavaScript object that should be displayed. */\r\n      json: \"<\",\r\n      /** If true json is compared to compare-to value. */\r\n      compare: \"<\",\r\n      /** The original JavaScript to which to show DIFF (show changes in data). */\r\n      compareTo: \"<\",\r\n      /** When displaying children, sets the property / key name for json */\r\n      key: \"<\",\r\n      /** Number that indicated how many levels JSON should be open */\r\n      open: \"<\",\r\n      /**\r\n       * Set to \"dialog\" if you want to show a button that opens the JSON in dialog.\r\n       * Otherwise, an inline tree view is shown.\r\n       */\r\n      type: \"@\",\r\n\r\n      /** Optional button class for the dialog button. Default is \"btn btn-default btn-xs\" */\r\n      btnClass: \"@\",\r\n    };\r\n\r\n    /** Uses the JsonFormatterController */\r\n    public controller = JsonFormatterController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/JsonFormatter.html\";\r\n\r\n    /** Rendered HTML replaces the original element */\r\n    public replace: true;\r\n}\r\n","import { NaviController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Helper component to generate navigation components and views:\r\n * Top- and side-menus, paths and controls that show the current title.\r\n * These controls take the navigation logic from an object (sitemap) and are aware of current node / open page on that sitemap.\r\n *\r\n *\r\n * NOTE: This is just an optional helper to make creating simple demo sites easier.\r\n * There is no need to use NaviService, NaviController or components in your custom site!\r\n * You can use something completely different.\r\n * @example\r\n * ```html\r\n * <salaxy-navi-sitemap></salaxy-navi-sitemap>\r\n * ```\r\n */\r\n\r\nexport class NaviSitemap extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n        /**\r\n         * - mode: \"default\", \"accordion\" or \"horizontal\"\r\n         * - default: shows full two levels of the tree. Typically used as sitemap in the content area.\r\n         * - accordion: shows first level of the navi tree and second level only if is in the current path.\r\n         * Typically used in left menu navigation.\r\n         * - horizontal: Full navi on top bar. Second tier in dropdowns.\r\n         * - 3-levels: Accordion with 3 levels.\r\n         */\r\n        mode: \"@\",\r\n    };\r\n\r\n    /** Uses the NaviController */\r\n    public controller = NaviController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/NaviSitemap.html\";\r\n}\r\n","import { NaviController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Helper component to easily create a web site that is responsive and usable.\r\n * The starter contains:\r\n *\r\n * - Customizable Header with title\r\n * - Left menu with logo, authentication info / login button and sitemap\r\n * - Mobile version with simple header: Title + Hamburger button that shows the menu, which is hidden by default.\r\n * - Loader message / animation\r\n * - Content area as ng-view\r\n * - Alert container\r\n *\r\n *\r\n * NOTE: This is just an optional helper to make creating simple (demo) sites easier.\r\n * There is no need to use NaviStarterLayout, NaviService, NaviController or components in your custom site!\r\n * You can use something completely different.\r\n * @example\r\n * ```html\r\n * <salaxy-navi-starter-layout>\r\n *   <header ng-controller=\"NaviController as navi\">\r\n *     Your html here: {{ navi.title }}\r\n *   </header>\r\n *   <main ng-controller=\"NaviController as navi\">\r\n *   \t<div ng-class=\"navi.current.isFullWidth ? 'container-fluid' : 'container'\" ng-view autoscroll=\"true\"></div>\r\n *   </main>\r\n * </salaxy-navi-starter-layout>\r\n * ```\r\n */\r\nexport class NaviStarterLayout extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /**\r\n     * - mode: \"default\", \"accordion\" or \"horizontal\"\r\n     * - default: shows full two levels of the tree. Typically used as sitemap in the content area.\r\n     * - accordion: shows first level of the navi tree and second level only if is in the current path.\r\n     * - horizontal: Full navi on top bar. Second tier in dropdowns.\r\n     * Typically used in left menu navigation.\r\n     */\r\n    mode: \"@\",\r\n\r\n    /**\r\n     * - layout: \"default\" or \"iframe\"\r\n     * - default: Basic layout with full navigation (left sidebar or horizontal).\r\n     * - iframe: Layout without first tier navigation on left sidebar. Second tier navigation items are under dropdown in top bar / header if mode is default. On horizontal mode full navigation is on top bar.\r\n     */\r\n     layout: \"@\",\r\n  };\r\n\r\n  /**\r\n   * Component may contain header and main tags to\r\n   * override the default rendering of the header (non-mobile) and main content area respectively.\r\n   */\r\n  public transclude = {\r\n    /** Header part of the page. Note that mobile header is defined separately. */\r\n    header: \"?header\",\r\n    /** Main content part of the page */\r\n    main: \"?main\",\r\n    /** The main navigation: By default: left sidebar. */\r\n    nav: \"?nav\",\r\n  };\r\n\r\n  /** Uses the NaviController */\r\n  public controller = NaviController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/helpers/NaviStarterLayout.html\";\r\n\r\n}\r\n","import { SpinnerController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Spinner as a UI component\r\n * @example\r\n * ```html\r\n * <salaxy-spinner salaxy-if-role=\"init\" full-screen=\"true\" heading=\"Loading...\" text=\"Please wait.\"></salaxy-spinner>\r\n * ```\r\n */\r\nexport class Spinner extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** If true, the spinner is shown full screen. */\r\n        fullScreen: \"=\",\r\n\r\n        /**\r\n         * Heading is the larger text under the spinner.\r\n         * The text is translated.\r\n         */\r\n        heading: \"@\",\r\n\r\n        /**\r\n         * Small text - use pre for line breaks.\r\n         * The text is translated.\r\n         */\r\n        text: \"@\",\r\n    };\r\n\r\n    /** Uses the SpinnerController */\r\n    public controller = SpinnerController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Spinner.html\";\r\n}\r\n","import { TabController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Component for a single tab pane in the tabs control.\r\n * Shows a navigation header and a tab pane.\r\n * Contains salaxy-tab-heading element for the tab header.\r\n * Contains salaxy-tab-content element for the tab pane content.\r\n * The disable attribute can be used to disable the tab.\r\n * The index attribute can be used to name the tab. The index\r\n * is used in setting the active tab in the salaxy-tabs element using the active attribute.\r\n * @example\r\n * ```html\r\n * <salaxy-tabs active=\"active\">\r\n *   <salaxy-tab>\r\n *      <salaxy-tab-heading>Tab number one</salaxy-tab-heading>\r\n *      <salaxy-tab-content>\r\n *          <p>Tab one content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n *  <salaxy-tab index=\"'kolme'\">\r\n *      <salaxy-tab-heading><i>Tab number two</i></salaxy-tab-heading>\r\n *      <salaxy-tab-content>\r\n *          <p>Tab two content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n *  <salaxy-tab disable=\"true\" heading=\"Tab text number three\">\r\n *      <salaxy-tab-content>\r\n *          <p>Tab three content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n * </salaxy-tabs>\r\n * ```\r\n */\r\nexport class Tab extends ComponentBase   {\r\n\r\n    /** Require salaxy-tabs */\r\n    public require = {\r\n        tabsCtrl: \"^salaxyTabs\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n     public bindings = {\r\n        /** Index/name for the tab. */\r\n         index: \"<\",\r\n        /** Disable tab attribute. */\r\n         disable: \"<\",\r\n        /** Text heading. */\r\n        heading: \"@\",\r\n        /** Selection event handler */\r\n        onSelect: \"&select\",\r\n     };\r\n\r\n     /** Uses the TabController */\r\n     public controller = TabController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Tab.html\";\r\n\r\n    /** Transclusion */\r\n    public transclude = {\r\n        content: \"?salaxyTabContent\",\r\n        heading: \"?salaxyTabHeading\",\r\n    };\r\n}\r\n","import { TabsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Component for a tabs control.\r\n * Shows navigation headers and tab panes.\r\n * Contains one or more salaxy-tab elements, each for one tab.\r\n * The active-attribute shows/sets the current active tab.\r\n * @example\r\n * ```html\r\n * <salaxy-tabs active=\"active\">\r\n *   <salaxy-tab>\r\n *      <salaxy-tab-heading>Tab number one</salaxy-tab-heading>\r\n *      <salaxy-tab-content>\r\n *          <p>Tab one content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n *  <salaxy-tab index=\"'kolme'\">\r\n *      <salaxy-tab-heading><i>Tab number two</i></salaxy-tab-heading>\r\n *      <salaxy-tab-content>\r\n *          <p>Tab two content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n *  <salaxy-tab disable=\"true\" heading=\"Tab text number three\">\r\n *      <salaxy-tab-content>\r\n *          <p>Tab three content</p>\r\n *      </salaxy-tab-content>\r\n *  </salaxy-tab>\r\n * </salaxy-tabs>\r\n * ```\r\n */\r\nexport class Tabs extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n     public bindings = {\r\n        /** Expression for active tab in the tabset */\r\n        active: \"=?\",\r\n     };\r\n\r\n    /** Uses the TabsController */\r\n    public controller = TabsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/Tabs.html\";\r\n\r\n    /** Transclusion */\r\n    public transclude = true;\r\n\r\n}\r\n","import { UiTranslatorController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * User interface for translating user interfaces\r\n * @example\r\n * ```html\r\n * <salaxy-ui-translator></salaxy-ui-translator>\r\n * ```\r\n */\r\nexport class UiTranslator extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n      /** User interface mode for the component: \"table\" (default) or \"fieldset\" */\r\n      mode: \"@\",\r\n\r\n      /**\r\n       * Beginning of the full key that is used to filtering the dictionary items (allKeyValues filter).\r\n       * The value may be a string, array or comma separated string of values.\r\n       */\r\n      filter: \"<\",\r\n\r\n      /** Texts from serviceModel that are being edited */\r\n      texts: \"<\",\r\n    };\r\n\r\n    /** Uses the UiTranslatorController */\r\n    public controller = UiTranslatorController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/UiTranslator.html\";\r\n}\r\n","import { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Base component for mass data loading.\r\n */\r\nexport abstract class DataImportComponentBase extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = { };\r\n\r\n    /** No controller */\r\n    public controller = null;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/helpers/import/DataImport.html\";\r\n}\r\n","import { CalcImportController } from \"../../../controllers\";\r\nimport { DataImportComponentBase } from \"./DataImportComponentBase\";\r\n\r\n/**\r\n * User interface for calculation mass loading.\r\n * @example\r\n * ```html\r\n * <salaxy-calc-import></salaxy-calc-import>\r\n * ```\r\n */\r\nexport class CalcImport extends DataImportComponentBase {\r\n\r\n    /** Uses the CalcImportController */\r\n    public controller = CalcImportController;\r\n\r\n}","import { CompanyImportController } from \"../../../controllers\";\r\nimport { DataImportComponentBase } from \"./DataImportComponentBase\";\r\n\r\n/**\r\n * User interface for worker mass loading.\r\n * @example\r\n * ```html\r\n * <salaxy-company-import></salaxy-company-import>\r\n * ```\r\n */\r\nexport class CompanyImport extends DataImportComponentBase {\r\n\r\n    /** Uses the CompanyImportController */\r\n    public controller = CompanyImportController;\r\n\r\n}","import { ImportStagingController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Provides an UI to the import staging area if one is available for the current company..\r\n */\r\nexport class ImportStaging extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Binds the current payroll (the full object) typically from the Payroll details view. */\r\n    payroll: \"<\",\r\n\r\n    /** If the list off calculations committed into the Payroll typically from the Payroll details view. */\r\n    payrollCalcs: \"<\",\r\n  };\r\n\r\n  /** Uses the ImportStagingController */\r\n  public controller = ImportStagingController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/helpers/import/staging/ImportStaging.html\";\r\n}\r\n","import { WorkerImportController } from \"../../../controllers\";\r\nimport { DataImportComponentBase } from \"./DataImportComponentBase\";\r\n\r\n/**\r\n * User interface for worker mass loading.\r\n * @example\r\n * ```html\r\n * <salaxy-worker-import></salaxy-worker-import>\r\n * ```\r\n */\r\nexport class WorkerImport extends DataImportComponentBase {\r\n\r\n    /** Uses the WorkerImportController */\r\n    public controller = WorkerImportController;\r\n\r\n}\r\n","import { CreditTransferController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Credit Transfer Form for Invoice visualization.\r\n * @example\r\n * ```html\r\n * <salaxy-credit-transfer invoice=\"$ctrl.current\">\r\n *   <message>My <strong>custom HTML</strong> message</message>\r\n * </salaxy-credit-transfer>\r\n * ```\r\n */\r\nexport class CreditTransfer extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /** Invoice to display in the credit transfer. */\r\n    invoice: \"<\",\r\n\r\n    /** Invoice preview to display in the credit transfer. */\r\n    invoicePreview: \"<\",\r\n\r\n    /**\r\n     * Display mode is either\r\n     *\r\n     * - \"official\": The official printable credit transfer (Finanssialan keskusliitto)\r\n     * - \"barcode-copy\": The copy-paste input + button (in a div) for copy pasting the the barcode into a web bank\r\n     * - \"default\": Both of the above separted by an explaining text.\r\n     */\r\n    mode: \"@\",\r\n  };\r\n\r\n  /**\r\n   * Transclusion slots\r\n   */\r\n  public transclude = {\r\n    /**\r\n     * HTML to include in the message section\r\n     */\r\n    message: \"?message\",\r\n  };\r\n\r\n  /** Uses the CreateCompanyAccountWizardController */\r\n  public controller = CreditTransferController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/invoices/CreditTransfer.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, InvoiceCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit / actions user interface for a single invoice.\r\n * @example\r\n * ```html\r\n * <salaxy-invoice-edit model=\"'url'\"></salaxy-invoice-edit>\r\n * ```\r\n */\r\nexport class InvoiceEdit extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the InvoiceCrudController */\r\n    public controller = InvoiceCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoiceEdit.html\";\r\n\r\n}\r\n","import { InvoiceCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of salary reports.\r\n * @example\r\n * ```html\r\n * <salaxy-invoice-list mode=\"panel\"></salaxy-salary-report-list>\r\n * ```\r\n */\r\nexport class InvoiceList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /**\r\n       * list view 'mode'.\r\n       * If undefined, defaults to full list.\r\n       * Use panel for dashboards etc.\r\n       */\r\n      mode: \"@\",\r\n\r\n      /**\r\n       * Payment channel for SEPA payments.\r\n       * Used when mode is \"sepa\".\r\n       */\r\n      sepaChannel: \"<\",\r\n\r\n     };\r\n\r\n    /** Uses the InvoiceCrudController */\r\n    public controller = InvoiceCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoiceList.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, InvoiceCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a print-like preview for an invoice.\r\n * @example\r\n * ```html\r\n * <salaxy-invoice-preview model=\"$ctrl.current\"></salaxy-invoice-preview>\r\n * ```\r\n */\r\nexport class InvoicePreview extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the InvoiceCrudController */\r\n    public controller = InvoiceCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoicePreview.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, InvoicesCreateController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a view for creating invoices: PaymentChannel selection, validation errors if necessary,\r\n * Payment channel selection and button for creating invoices for Payroll or Calculation.\r\n * If pointed to a paid calculation, shows the invoices that were already created or legacy payment method.\r\n * @example\r\n * ```html\r\n * <salaxy-invoices-create model=\"$ctrl.current\"></salaxy-invoices-create>\r\n * ```\r\n */\r\nexport class InvoicesCreate extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the InvoicesCreateController */\r\n    public controller = InvoicesCreateController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoicesCreate.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, PaymentChannelController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a print-like preview for an invoice.\r\n * @example\r\n * ```html\r\n * <salaxy-payment-channel-invoice-preview model=\"$ctrl.current\"></salaxy-payment-channel-invoice-preview>\r\n * ```\r\n */\r\nexport class PaymentChannelInvoicePreview extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the PaymentChannelController */\r\n    public controller = PaymentChannelController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoicePreview.html\";\r\n\r\n}\r\n","import { InvoiceToolsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the export tools for the invoices.\r\n * @example\r\n * ```html\r\n * <salaxy-invoice-tools reader=\"$ctrl.dataReader\"></salaxy-invoice-tools>\r\n * ```\r\n */\r\nexport class InvoiceTools extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Reference to the data reader object. */\r\n      reader: \"<\",\r\n    };\r\n\r\n    /** Uses the InvoiceToolsController */\r\n    public controller = InvoiceToolsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoiceTools.html\";\r\n\r\n}\r\n","import { InvoiceReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the report for the given invoice.\r\n * @example\r\n * ```html\r\n * <salaxy-invoice-report invoice=\"$ctrl.currentInvoice\"\"></salaxy-invoice-report>\r\n * ```\r\n */\r\nexport class InvoiceReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The invoice for the report. */\r\n      invoice: \"<\",\r\n      /** If true, uses the current style of the site. The default value is false. */\r\n      applySiteStyles: \"<\",\r\n      /** The language for report*/\r\n      lang: \"<\"\r\n    };\r\n\r\n    /** Uses the InvoiceReportController */\r\n    public controller = InvoiceReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoiceReport.html\";\r\n\r\n}\r\n","import { CompanyInvoicesController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the invoice processing ui for companies.\r\n * @example\r\n * ```html\r\n * <salaxy-company-invoices></salaxy-company-invoices>\r\n * ```\r\n */\r\nexport class CompanyInvoices extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /**\r\n       * channel for the invocie processing. Default is PalkkausInvoices.\r\n       */\r\n         channel: \"<\",\r\n    };\r\n\r\n    /** Uses the InvoiceCrudController */\r\n    public controller = CompanyInvoicesController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/CompanyInvoices.html\";\r\n\r\n}\r\n","import { InvoiceAlertsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * TBD\r\n */\r\nexport class InvoiceAlerts extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Payment channels for OData query. */\r\n      paymentChannels: \"<\",\r\n      /** Indicates if used in pro. */\r\n      isPro: \"<\"\r\n    };\r\n\r\n    /** Uses the InvoiceAlertsController */\r\n    public controller = InvoiceAlertsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/invoices/InvoiceAlerts.html\";\r\n\r\n}\r\n","import { WorkerAssureController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * DEPRECATED: Being used by an isolated partner(s) that have special access.\r\n * => Remove in a next major release.\r\n * Alternative component for adding Worker accounts.\r\n * Uses the AssureWorkerAccount API service that is currently reserved for partner access.\r\n * @deprecated Being used by an isolated partner(s) that have special access. => Remove in a next major release.\r\n * @example\r\n * ```html\r\n * <salaxy-worker-assure></salaxy-worker-assure>\r\n * ```\r\n */\r\nexport class WorkerAssure extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the WorkerAssureController */\r\n    public controller = WorkerAssureController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/WorkerAssure.html\";\r\n\r\n}\r\n","import { ODataHelperController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders the footer within OdataTable.\r\n * Requires salaxy-odata-table component as parent.\r\n * TODO: Example\r\n */\r\nexport class OdataFooter extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** Type of paging */\r\n        paging: \"@\",\r\n\r\n        /**\r\n         * Manually defined URL for the nextPageLink.\r\n         * Browser is directed to this URL instead of loading more data from nextPageLink.\r\n         */\r\n        nextPageUrl: \"@\",\r\n    };\r\n\r\n    /** Attribute must be used within salaxy-odata-table component to access the common ODataQueryController  */\r\n    public require = {\r\n      $odata: \"^^salaxyOdataTable\",\r\n    };\r\n\r\n    /** Uses the ODataHelperController */\r\n    public controller = ODataHelperController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/odata/OdataFooter.html\";\r\n}\r\n","import { ODataQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Helper for rendering an OData service based table / grid.\r\n */\r\nexport class OdataTable extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** OData query options */\r\n        options: \"<\",\r\n\r\n        /** URL to the OData service. */\r\n        url: \"@\",\r\n\r\n        /** Data passed from the parent to the component / view */\r\n        data: \"<\",\r\n\r\n        /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n        selectedItems: \"<\",\r\n\r\n        /** Current list of items. */\r\n        items: \"<\",\r\n\r\n        /**\r\n         * Function that is called when user selects an item in the list.\r\n         * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n         * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n         * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n         */\r\n        onListSelect: \"&\",\r\n\r\n        /** Function that is called when the data has been loaded and set as values of the items. */\r\n        onDataLoaded: \"&\",\r\n\r\n        /**\r\n         * CRUD controller that typically defines the values for url template and\r\n         * @example\r\n         * <salaxy-odata-table crud-controller=\"PayrollCrudController as $crud\">\r\n         */\r\n        crudController: \"@\",\r\n\r\n        /**\r\n         * Optional bindings for the CRUD controller. All properties are set to crudController before calling init.\r\n         * @example\r\n         * <salaxy-odata-table crud-controller=\"PayrollCrudController as $crud\" crud-bindings=\"{ myProp: 'foobar' }\">\r\n         */\r\n        crudBindings: \"<\",\r\n\r\n        /** Defines the cache key. A non-null value also means that the caqche is enabled. */\r\n        cacheKey: \"@\",\r\n\r\n        /** Optional reader component for OData. Uses the given url and reads data from the OData source. */\r\n        reader: \"<\",\r\n\r\n        /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n        readOnly: \"<\",\r\n\r\n        /** Logic object for component */\r\n        logic: \"<\",\r\n        /**Select mode for component */\r\n        selectMode: \"<\"\r\n    };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/odata/lists/_default.html\";\r\n\r\n    /** Rendered HTML replaces the original element */\r\n    public replace: true;\r\n}\r\n","import { ODataActionsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders the search box and export/import functions within OdataTable.\r\n * Requires salaxy-odata-table component as parent.\r\n */\r\nexport class OdataActions extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n        /** Default locale for data exports/imports. */\r\n        localeId: \"<\",\r\n        /** Flag indicating if the export options are visible. */\r\n        showExport: \"@\",\r\n    };\r\n\r\n    /** Attribute must be used within salaxy-odata-table component to access the common ODataQueryController  */\r\n    public require = {\r\n      $odata: \"^^salaxyOdataTable\",\r\n    };\r\n\r\n    /** Actions */\r\n    public transclude = true;\r\n\r\n    /** Uses the ODataActionsController */\r\n    public controller = ODataActionsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/odata/OdataActions.html\";\r\n}\r\n","import { SessionController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows account authorization and Credentials information including\r\n * a link to Authorization document (digitally signed pdf) and\r\n * type and UID (typically e-mail) of the current credentials.\r\n * @example\r\n * ```html\r\n * <salaxy-account-authorization-person></salaxy-account-authorization-person>\r\n * ```\r\n */\r\nexport class AccountAuthorizationPerson extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to controller implementation\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountAuthorizationPerson.html\";\r\n}\r\n","\r\nimport { PersonAccountController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit the avatar information: Picture upload, Initials + color or Gravatar.\r\n * Currently used only in Personal accounts, but this could potentially be also\r\n * used in Company side to edit Avatar?\r\n * @example\r\n * ```html\r\n * <salaxy-account-avatar-edit-person></salaxy-account-avatar-edit-person>\r\n * ```\r\n */\r\nexport class AccountAvatarEditPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Current person account. Optional */\r\n      current: \"<\",\r\n    };\r\n\r\n    /** Uses the PersonAccountController */\r\n    public controller = PersonAccountController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountAvatarEditPerson.html\";\r\n\r\n}\r\n","\r\nimport { PersonAccountController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Editing UI of Contact information for Personal account.\r\n * @example\r\n * ```html\r\n * <salaxy-account-contact-edit-person></salaxy-account-contact-edit-person>\r\n * ```\r\n */\r\nexport class AccountContactEditPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Current person account. Optional */\r\n      current: \"<\",\r\n    };\r\n\r\n    /** Uses the PersonAccountController */\r\n    public controller = PersonAccountController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountContactEditPerson.html\";\r\n\r\n}\r\n","\r\nimport { PersonAccountController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Editor view for Person's contact and payment information,\r\n * for example avatar, phone number and bank account number.\r\n * @example\r\n * ```html\r\n * <salaxy-account-details-person></salaxy-account-details-person>\r\n * ```\r\n */\r\nexport class AccountDetailsPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Current tab in initialization. If not set, will be fetched from url hash. */\r\n      currentTab: \"@\",\r\n    };\r\n\r\n    /** Uses the PersonAccountController */\r\n    public controller = PersonAccountController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountDetailsPerson.html\";\r\n\r\n}\r\n","import { PersonAccountController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Editor for main identity data of Personal account: Names (currently opens a wizard),\r\n * Personal ID (read-only) or IBAN (should require strong authentication).\r\n * @example\r\n * ```html\r\n * <salaxy-account-details-edit-person></salaxy-account-details-edit-person>\r\n * ```\r\n */\r\nexport class AccountDetailsEditPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Current person account. Optional */\r\n      current: \"<\",\r\n    };\r\n\r\n    /** Uses the PersonAccountController */\r\n    public controller = PersonAccountController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountDetailsEditPerson.html\";\r\n\r\n}\r\n","import { SessionController} from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Quick basic information about the Person account: Avatar, name, phone and e-mail.\r\n * The component may be bound with ng-model or if omitted binds to session current account.\r\n * The component is currently for Personal acocunt only, but it could be generalized\r\n * for companies as well.\r\n * @example\r\n * ```html\r\n * <salaxy-account-info-person view-type=\"details\" ng-model=\"\"></salaxy-account-info-person>\r\n * ```\r\n */\r\nexport class AccountInfoPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n\r\n    };\r\n\r\n    /** ngModel may be used */\r\n    public require = {\r\n      model: \"?ngModel\",\r\n    };\r\n\r\n    /** Uses the SessionController */\r\n    public controller = SessionController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountInfoPerson.html\";\r\n\r\n}\r\n","\r\nimport { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit UI for Household's own insurance information including Pension and Unemployment insurance.\r\n * Designed for Person Employer only, should not be shown in Worker scenarios as it may be confusing.\r\n * @example\r\n * ```html\r\n * <salaxy-account-insurance-edit-person></salaxy-account-insurance-edit-person>\r\n * ```\r\n */\r\nexport class AccountInsuranceEditPerson extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n    };\r\n\r\n    /** Uses the CompanySettingsController */\r\n    public controller = CompanySettingsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/AccountInsuranceEditPerson.html\";\r\n\r\n}\r\n","import { EmployerListController } from \"../../controllers\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows employer list\r\n * @example\r\n * ```html\r\n * <salaxy-employer-list></salaxy-employer-list>\r\n * ```\r\n */\r\nexport class EmployerList extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n   public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n     /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n     selectedItems = \"<\";\r\n\r\n     /** Current list of items. */\r\n     items = \"<\";\r\n    /**\r\n     * Function that is called when user selects an item in the list.\r\n     * Note that the event is called only in the selection. Not when there is a link to details view in a link list.\r\n     * Function has the following locals: value: true/false, item: the last selected/unselected item.\r\n     * @example <salaxy-employer-select on-employer-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employer-select>\r\n     */\r\n      onEmployerSelect = \"&\";\r\n\r\n    }());\r\n\r\n    /** Uses the CalcSharingController */\r\n    public controller = EmployerListController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/EmployerList.html\";\r\n\r\n}\r\n","import { EmployerReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the employer report.\r\n * @example\r\n * ```html\r\n * <salaxy-employer-report></salaxy-employer-report>\r\n * ```\r\n */\r\nexport class EmployerReport extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n  };\r\n\r\n  /** Uses the EmployerReportController */\r\n  public controller = EmployerReportController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/personal/EmployerReport.html\";\r\n\r\n}\r\n","import { EmployerSelectController } from \"../../controllers\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows employer selection\r\n * @example\r\n * ```html\r\n * <salaxy-employer-select model=\"\" on-employer-select=\"\"></salaxy-employer-select>\r\n * ```\r\n */\r\nexport class EmployerSelect extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n   public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n     /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n     selectedItems = \"<\";\r\n\r\n     /** Current list of items. */\r\n     items = \"<\";\r\n    /**\r\n     * Function that is called when user selects an item in the list.\r\n     * Note that the event is called only in the selection. Not when there is a link to details view in a link list.\r\n     * Function has the following locals: value: true/false, item: the last selected/unselected item.\r\n     * @example <salaxy-employer-select on-employer-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employer-select>\r\n     */\r\n      onEmployerSelect = \"&\";\r\n\r\n    }());\r\n\r\n    /** Uses the CalcSharingController */\r\n    public controller = EmployerSelectController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/EmployerSelect.html\";\r\n\r\n}\r\n","import { CalcHouseholdUsecaseController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * UI for setting the Household Usecases within the calculator\r\n * @example\r\n * ```html\r\n * <salaxy-calc-household-usecase calc=\"$ctrl.currentCalc\"></salaxy-calc-household-usecase>\r\n * ```\r\n */\r\nexport class CalcHouseholdUsecase extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** The calculation that the component edits */\r\n    calc: \"<\",\r\n\r\n    /** Alternative data binding: creates a calculation based on Worker defaults. */\r\n    worker: \"<\",\r\n\r\n    /**\r\n     * Shows the Save and Reset buttons.\r\n     * Currently, this is only enabled for WorkerAccount data binding, but may later be enabled for calc.\r\n     */\r\n    showSave: \"<\",\r\n\r\n    /** isReadOnly*/\r\n    isReadOnly: \"<\"\r\n  };\r\n\r\n  /** Uses the CalcHouseholdUsecaseController */\r\n  public controller = CalcHouseholdUsecaseController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/personal/CalcHouseholdUsecase.html\";\r\n\r\n}\r\n","import { CalcSharingController } from \"../../controllers\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the sharing control for the current calculation\r\n * @example\r\n * ```html\r\n * <salaxy-calc-sharing model='url'></salaxy-calc-sharing>\r\n * ```\r\n */\r\nexport class CalcSharing extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n   public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n       /** If true, template shows option to share direct link to the calculation. Currently used only in Rakennusliitto site. */\r\n      public showLinkSharing = \"<\";\r\n    }());\r\n\r\n    /** Uses the CalcSharingController */\r\n    public controller = CalcSharingController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/CalcSharing.html\";\r\n\r\n}\r\n","import { CalcSharingController } from \"../../controllers\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the current status of sharing for the calculation\r\n * @example\r\n * ```html\r\n * <salaxy-calc-sharing-info model='url'></salaxy-calc-sharing-info>\r\n * ```\r\n */\r\nexport class CalcSharingInfo extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the CalcSharingController */\r\n    public controller = CalcSharingController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/CalcSharingInfo.html\";\r\n\r\n}\r\n","import { HouseholdDeductionReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the household deduction report.\r\n * @example\r\n * ```html\r\n * <salaxy-household-deduction-report></salaxy-household-deduction-report>\r\n * ```\r\n */\r\nexport class HouseholdDeductionReport extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n  };\r\n\r\n  /** Uses the HouseholdDeductionReportController */\r\n  public controller = HouseholdDeductionReportController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/personal/HouseholdDeductionReport.html\";\r\n\r\n}\r\n","import { WorkerReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the worker report.\r\n * @example\r\n * ```html\r\n * <salaxy-worker-report></salaxy-worker-report>\r\n * ```\r\n */\r\nexport class WorkerReport extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n  };\r\n\r\n  /** Uses the WorkerReportController */\r\n  public controller = WorkerReportController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/personal/WorkerReport.html\";\r\n\r\n}\r\n","import { HouseholdYearCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of household yearly deductions.\r\n * @example\r\n * ```html\r\n * <salaxy-household-year-list></salaxy-household-year-list>\r\n * ```\r\n */\r\nexport class HouseholdYearList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = { };\r\n\r\n    /** Uses the HouseholdYearCrudController */\r\n    public controller = HouseholdYearCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/HouseholdYearList.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, HouseholdYearCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Edit / actions user interface for a year specific household deductions.\r\n * @example\r\n * ```html\r\n * <salaxy-household-year-details model=\"'url'\"></salaxy-household-year-details>\r\n * ```\r\n */\r\nexport class HouseholdYearDetails extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the HouseholdYearCrudController */\r\n    public controller = HouseholdYearCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/personal/HouseholdYearDetails.html\";\r\n\r\n}\r\n","import { AccountingReportCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of accounting reports.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-report-list></salaxy-accounting-report-list>\r\n * ```\r\n */\r\nexport class AccountingReportList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /**\r\n       * list view 'mode'.\r\n       * If undefined, defaults to full list.\r\n       * Use panel for dashboards etc.\r\n       */\r\n      mode: \"@\",\r\n\r\n     };\r\n\r\n    /** Uses the AccountingReportCrudController */\r\n    public controller = AccountingReportCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/AccountingReportList.html\";\r\n\r\n}\r\n","import { AccountingReportQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the accounting report builder for ad hoc reporting queries.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-report-query></salaxy-accounting-report-query>\r\n * ```\r\n */\r\nexport class AccountingReportQuery extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /**\r\n       * Specify the calculations that should be reported.\r\n       * If null, will show a user interface to select calculations or period.\r\n       */\r\n      calcs: \"<\",\r\n\r\n      /**\r\n       * Report view table only (partial) or pdf preview (full)\r\n       * Defaults to 'partial'\r\n       */\r\n      view: \"<\",\r\n      /** The language for report*/\r\n      lang: \"<\"\r\n    };\r\n\r\n    /** Uses the AccountingReportQueryController */\r\n    public controller = AccountingReportQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/AccountingReportQuery.html\";\r\n\r\n}\r\n","import { AccountingReportRowsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the rows of the accounting report.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-report-rows data=\"$ctrl.data\"></salaxy-accouting-report-rows>\r\n * ```\r\n */\r\nexport class AccountingReportRows extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Accounting data */\r\n    data: \"<\",\r\n    /**\r\n     * Report view table only (partial) or pdf preview (full)\r\n     * Defaults to 'partial'\r\n     */\r\n    view: \"<\",\r\n    /** The language for report*/\r\n    lang: \"<\"\r\n  };\r\n\r\n  /** Uses the AccountingReportRowsController */\r\n  public controller = AccountingReportRowsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/AccountingReportRows.html\";\r\n\r\n}\r\n","import { AccountingReportToolsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the export tools for the accounting report.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-report-tools reader=\"$ctrl.dataReader\"></salaxy-accouting-report-tools>\r\n * ```\r\n */\r\nexport class AccountingReportTools extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Reference to the data reader object. */\r\n    reader: \"<\",\r\n    /** Called when the target has been changed. */\r\n    onTargetChange: \"&\",\r\n    /** Called when the expand button state changed */\r\n    onExpandChange: \"&\",\r\n    /** Binded expand state*/\r\n    anyExpanded: \"<\",\r\n\r\n    /**\r\n     * Report view table only (partial) or pdf preview (full)\r\n     * Defaults to 'partial'\r\n     */\r\n    view: \"<\"\r\n  };\r\n\r\n  /** Uses the AccountingReportToolsController */\r\n  public controller = AccountingReportToolsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/AccountingReportTools.html\";\r\n\r\n}\r\n","import { AccountingReportCrudController } from \"../../controllers\";\r\nimport { ApiCrudObjectControllerBindings } from \"../../controllers/bases\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the accounting report viewer for the pre-built reports.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-report-viewer model='url'></salaxy-accounting-report-viewer>\r\n * ```\r\n */\r\nexport class AccountingReportViewer extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the AccountingReportCrudController */\r\n    public controller = AccountingReportCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/AccountingReportViewer.html\";\r\n}\r\n","import { CalculationReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the calculation report builder for ad hoc calculation reports.\r\n * @example\r\n * ```html\r\n * <salaxy-calculation-report template-id=\"plain\"></salaxy-calculation-report>\r\n * ```\r\n */\r\nexport class CalculationReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Template for the report */\r\n      templateId: \"<\",\r\n    };\r\n\r\n    /** Uses the CalculationReportController */\r\n    public controller = CalculationReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/CalculationReport.html\";\r\n\r\n}\r\n","import { HolidayReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows holiday report of selected holiday year\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-report></salaxy-holiday-report>\r\n * ```\r\n */\r\nexport class HolidayReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {};\r\n\r\n    /** Uses the HolidayReportController */\r\n    public controller = HolidayReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/HolidayReport.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, IrEarningsPaymentCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a user interface for Earnings Payment Report (\"Tulorekisteri-ilmoitus\").\r\n * Currently, the UI is read-only, but it may later be extended to be editable\r\n * for purposes of corrections.\r\n * @example\r\n * ```html\r\n * <salaxy-ir-earnings-payment model=\"$ctrl.current\"></salaxy-ir-earnings-payment>\r\n * ```\r\n */\r\nexport class IrEarningsPayment extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /**\r\n     * Alternative model binding.\r\n     * Instead of model=\"EarningsPaymentId\", you may specify calculation-id=\"calculationId\"\r\n     */\r\n    public calculationId = \"<\";\r\n\r\n    /**\r\n     * Alternative model binding.\r\n     * Instead of model=\"EarningsPaymentId\", you may specify calculation=\"calculation\"\r\n     */\r\n    public calculation = \"<\";\r\n  }());\r\n\r\n  /** Uses the EarningsPaymentReportController */\r\n  public controller = IrEarningsPaymentCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/IrEarningsPayment.html\";\r\n\r\n}\r\n","import { IrEarningsPaymentCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of earnings payments.\r\n * @example\r\n * ```html\r\n * <salaxy-ir-earnings-payment-list></salaxy-ir-earnings-payment-list>\r\n * ```\r\n */\r\nexport class IrEarningsPaymentList extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n  };\r\n\r\n  /** Uses the AccountingReportCrudController */\r\n  public controller = IrEarningsPaymentCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/IrEarningsPaymentList.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, IrPayerSummaryCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a user interface for Payer Summary Report (\"Erillisilmoitus\").\r\n * Currently, the UI is read-only, but it may later be extended to be editable\r\n * for purposes of corrections.\r\n * @example\r\n * ```html\r\n * <salaxy-ir-payer-summary model=\"$ctrl.current\"></salaxy-ir-payer-summary>\r\n * ```\r\n */\r\nexport class IrPayerSummary extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n  }());\r\n\r\n  /** Uses the IrPayerSummaryCrudController */\r\n  public controller = IrPayerSummaryCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/IrPayerSummary.html\";\r\n\r\n}\r\n","import { IrPayerSummaryCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of payer summaries.\r\n * @example\r\n * ```html\r\n * <salaxy-ir-payer-summary-list></salaxy-ir-payer-summary-list>\r\n * ```\r\n */\r\nexport class IrPayerSummaryList extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n  };\r\n\r\n  /** Uses the AccountingReportCrudController */\r\n  public controller = IrPayerSummaryCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/report/IrPayerSummaryList.html\";\r\n\r\n}\r\n","import { PayCertificateController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a wizard for creating a pay certificate for a worker.\r\n * @example\r\n * ```html\r\n * <salaxy-pay-certificate></salaxy-pay-certificate>\r\n * ```\r\n */\r\nexport class PayCertificate extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = { };\r\n\r\n    /** Uses the PayCertificateController */\r\n    public controller = PayCertificateController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/PayCertificate.html\";\r\n\r\n}\r\n","import { ReportsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of reports\r\n * @example\r\n * ```html\r\n * <salaxy-report-list report-type=\"unemployment\"></salaxy-report-list>\r\n * ```\r\n */\r\nexport class ReportList extends ComponentBase {\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n        /**\r\n         * - report-type: Type of the report (string, see reportType enumeration) that is shown in the list.\r\n         * Also supports value null/\"current\" for showing reports defined by reportsService.currentReportType.\r\n         */\r\n        reportType: \"<\",\r\n\r\n        /**\r\n         * -title\r\n         * Heading of the list. Supports translation keys.\r\n         * Default is reportType based enumeration translation.\r\n         */\r\n        heading: \"@\",\r\n    };\r\n\r\n    /** Uses the ReportsController */\r\n    public controller = ReportsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/ReportList.html\";\r\n\r\n}\r\n","import { SalaryReportCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of salary reports.\r\n * @example\r\n * ```html\r\n * <salaxy-salary-report-list mode=\"panel\"></salaxy-salary-report-list>\r\n * ```\r\n */\r\nexport class SalaryReportList extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /**\r\n       * list view 'mode'.\r\n       * If undefined, defaults to full list.\r\n       * Use panel for dashboards etc.\r\n       */\r\n      mode: \"@\",\r\n\r\n     };\r\n\r\n    /** Uses the AccountingReportCrudController */\r\n    public controller = SalaryReportCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/SalaryReportList.html\";\r\n\r\n}\r\n","import { AccountingRowReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the rows report builder for ad hoc accounting row based reports.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-row-report template-id=\"plain\"></salaxy-accounting-row-report>\r\n * ```\r\n */\r\nexport class AccountingRowReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** Template for the report */\r\n      templateId: \"<\",\r\n    };\r\n\r\n    /** Uses the AccountngRowReportController */\r\n    public controller = AccountingRowReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/AccountingRowReport.html\";\r\n\r\n}\r\n","import { SummaryReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the summary reports for the given data.\r\n * @example\r\n * ```html\r\n * <salaxy-summary-report data=\"$ctrl.data\"></salaxy-summary-report>\r\n * ```\r\n */\r\nexport class SummaryReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The data for the report. */\r\n      data: \"<\"\r\n    };\r\n\r\n    /** Uses the SummaryReportController */\r\n    public controller = SummaryReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/SummaryReport.html\";\r\n\r\n}\r\n","import { WorkerSummaryReportController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the summary reports for the given data.\r\n * @example\r\n * ```html\r\n * <salaxy-worker-summary-report data=\"$ctrl.data\"></salaxy-worker-summary-report>\r\n * ```\r\n */\r\nexport class WorkerSummaryReport extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /** The data for the report. */\r\n      data: \"<\"\r\n    };\r\n\r\n    /** Uses the WorkerSummaryReportController */\r\n    public controller = WorkerSummaryReportController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/WorkerSummaryReport.html\";\r\n\r\n}\r\n","import { AccountingHolidayPayDebtReportQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the accounting holiday debt report builder for ad hoc reporting queries.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-holiday-debt-report-query></salaxy-accounting-holiday-debt-report-query>\r\n * ```\r\n */\r\nexport class AccountingHolidayPayDebtReportQuery extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {\r\n      /**\r\n       * Report view table only (partial) or pdf preview (full)\r\n       * Defaults to 'partial'\r\n       */\r\n      view: \"<\",\r\n      /** The language for report*/\r\n      lang: \"<\"\r\n    };\r\n\r\n    /** Uses the AccountingReportQueryController */\r\n    public controller = AccountingHolidayPayDebtReportQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/AccountingHolidayPayDebtReportQuery.html\";\r\n\r\n}\r\n","import { HolidayPayReportQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows holiday pay report of selected holiday year\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-pay-report-query></salaxy-holiday-pay-report-query>\r\n * ```\r\n */\r\nexport class HolidayPayReportQuery extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {};\r\n\r\n    /** Uses the HolidayPayReportQueryController */\r\n    public controller = HolidayPayReportQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/HolidayPayReportQuery.html\";\r\n\r\n}\r\n","import { SummaryReportQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows summary report of selected period.\r\n * @example\r\n * ```html\r\n * <salaxy-summary-report-query></salaxy-summary-report-query>\r\n * ```\r\n */\r\nexport class SummaryReportQuery extends ComponentBase {\r\n\r\n   /**\r\n    * The following component properties (attributes in HTML) are bound to the Controller.\r\n    * For detailed functionality, refer to [controller](#controller) implementation.\r\n    */\r\n    public bindings = {};\r\n\r\n    /** Uses the SummaryReportQueryController */\r\n    public controller = SummaryReportQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/report/SummaryReportQuery.html\";\r\n\r\n}\r\n","import { AccountantController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Payment Settings\r\n * @example\r\n * ```html\r\n * <salaxy-accountant></salaxy-accountant>\r\n * ```\r\n */\r\n\r\nexport class Accountant extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /** If true, removing accountant is disabled */\r\n    removalDisabled: \"<\"\r\n  };\r\n\r\n  /** Uses the AccountController */\r\n  public controller = AccountantController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/Accountant.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Accounting settings.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-settings></salaxy-accounting-settings>\r\n * ```\r\n */\r\n\r\nexport class AccountingSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {};\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/AccountingSettings.html\";\r\n\r\n}\r\n","import { AccountingTargetCrudController, ApiCrudObjectControllerBindings } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Provides UI for viewing and adding new (modifying) accounting targets.\r\n * Accounting targets define where the accounting data is sent and how it is mapped to a Chart of Accounts (CoA)\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-target-details></salaxy-accounting-target-details>\r\n * ```\r\n */\r\n\r\nexport class AccountingTargetDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n  /** Uses the AccountController */\r\n  public controller = AccountingTargetCrudController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/AccountingTargetDetails.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Accounting target settings.\r\n * @example\r\n * ```html\r\n * <salaxy-accounting-target-settings></salaxy-accounting-target-settings>\r\n * ```\r\n */\r\n\r\nexport class AccountingTargetSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Forced read only state */\r\n    isReadOnlyForced: \"<\"\r\n  };\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/AccountingTargetSettings.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Cost accounting settings.\r\n * @example\r\n * ```html\r\n * <salaxy-cost-accounting-settings></salaxy-cost-accounting-settings>\r\n * ```\r\n */\r\n\r\nexport class CostAccountingSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n     /** Forced read only state */\r\n     isReadOnlyForced: \"<\"\r\n  };\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/CostAccountingSettings.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Holiday settings.\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-settings></salaxy-holiday-settings>\r\n * ```\r\n */\r\n\r\nexport class HolidaySettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {};\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/HolidaySettings.html\";\r\n\r\n}\r\n","import { InsuranceWizardController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shop in shop modal for getting Lähitapiola insurance.\r\n * @example\r\n * ```html\r\n * <salaxy-insurance></salaxy-insurance>\r\n * ```\r\n */\r\nexport class Insurance extends ComponentBase {\r\n\r\n/**\r\n * The following component properties (attributes in HTML) are bound to the Controller.\r\n * For detailed functionality, refer to [controller](#controller) implementation.\r\n */\r\n    public bindings = {};\r\n\r\n    /** Uses the InsuranceWizardController */\r\n    public controller = InsuranceWizardController;\r\n\r\n    /** Uses the controller as aliasing */\r\n    public controllerAs = \"$ctrl\";\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/modals/account/Insurance.html\";\r\n\r\n}","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Settings needed for insurance contracts and pension contracts.\r\n * @example\r\n * ```html\r\n * <salaxy-insurance-settings></salaxy-insurance-settings>\r\n * ```\r\n */\r\n\r\nexport class InsuranceSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /**\r\n     * Array of section ids to show\r\n     * By default: ['pensionContracts','insuranceContracts']\r\n     * All options:\r\n     * 'pensionContracts': Pension related settings\r\n     * 'yelPensionContracts': Pension related settings\r\n     * 'insuranceContracts' : Insureance contract related settings\r\n     */\r\n    sections: \"<\",\r\n\r\n    /** Sets the isReadOnlyForced status. */\r\n    isReadOnlyForced:\"<\"\r\n  };\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/Insurances.html\";\r\n\r\n}\r\n","import { OwnerSettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * User interfaces for Owner and Beneficiary lists.\r\n * @example\r\n * ```html\r\n * <salaxy-owner-settings></salaxy-owner-settings>\r\n * ```\r\n */\r\n\r\nexport class OwnerSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Sets the isReadOnlyForced status. */\r\n    isReadOnlyForced:\"<\"\r\n  };\r\n\r\n  /** Uses the OwnerSettingsController */\r\n  public controller = OwnerSettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/OwnerSettings.html\";\r\n\r\n}\r\n","import { PaymentChannelSettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows and modifies Payment Settings related to Payment Channels\r\n * @example\r\n * ```html\r\n * <salaxy-payment-channel-settings></salaxy-payment-settings>\r\n * ```\r\n */\r\n\r\nexport class PaymentChannelSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {};\r\n\r\n  /** Uses the AccountController */\r\n  public controller = PaymentChannelSettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/PaymentChannelSettings.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Overall settings needed for starting salary payment.\r\n * @example\r\n * ```html\r\n * <salaxy-payment-settings></salaxy-payment-settings>\r\n * ```\r\n */\r\n\r\nexport class PaymentSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /**\r\n     * Array of section ids to show\r\n     * By default: ['pensionContracts','insuranceContracts','incomesRegister']\r\n     * All options:\r\n     * 'pensionContracts': Pension related settings\r\n     * 'insuranceContracts' : Insureance contract related settings\r\n     * 'incomesRegister': Tax reporting related settings\r\n     * 'eInvoice': EInvoice related settings\r\n     * 'sepa' : Sepa payments related settings\r\n     * 'taxAndSocialSecuritySelfHandling': Settings for tax payments\r\n     * 'pensionSelfHandling': Settings for pension payments\r\n     * 'workerSelfHandling': Settings for net salary payments\r\n     * 'unemploymentSelfHandling' Settings for unemployment payments\r\n     */\r\n    sections: \"<\",\r\n\r\n    /** Sets the isReadOnlyForced status. */\r\n    isReadOnlyForced:\"<\"\r\n  };\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/PaymentSettings.html\";\r\n\r\n}\r\n","import { CompanySettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * All settings\r\n * @example\r\n * ```html\r\n * <salaxy-pro-settings></salaxy-pro-settings>\r\n * ```\r\n */\r\n\r\nexport class ProSettings extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {};\r\n\r\n  /** Uses the CompanySettingsController */\r\n  public controller = CompanySettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/ProSettings.html\";\r\n\r\n}\r\n","import { RowTypesSettingsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Settings editor for Row types (Palkkalajit)\r\n * @example\r\n * ```html\r\n * <salaxy-row-types-sessings></salaxy-row-types-sessings>\r\n * ```\r\n */\r\nexport class RowTypesSettings extends ComponentBase {\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /**\r\n     * Defines the type of rows editor: \"builtIn\" for built-in rows,\r\n     * \"custom\" for custom rows, \"prices\" company specific default prices per row type.\r\n     */\r\n    mode: \"@\",\r\n\r\n    /**\r\n     * Set this property if you want to explicitly set the model.\r\n     * If undefinded, the component binds to company settings.\r\n     */\r\n    model: \"<\",\r\n  };\r\n\r\n  /** Uses the AccountController */\r\n  public controller = RowTypesSettingsController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/RowTypesSettings.html\";\r\n\r\n}\r\n","import { ServiceModelCrudController, ApiCrudObjectControllerBindings } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Provides UI for modifying service model.\r\n * @example\r\n * ```html\r\n * <salaxy-service-model-details></salaxy-service-model-details>\r\n * ```\r\n */\r\n\r\nexport class ServiceModelDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n  /** Uses the AccountController */\r\n  public controller = ServiceModelCrudController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/settings/ServiceModelDetails.html\";\r\n\r\n}\r\n","import { SxyFormElementController } from \"../../controllers\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows an alert with type \"error\" or one of the bootstrap styles: \"danger\", \"info\", \"warning\", \"success\".\r\n * @example\r\n * ```html\r\n * <sxy-alert type=\"primary\"><strong>NOTE:</strong> Here is a primary message to user.</sxy-alert>\r\n * <sxy-alert type=\"error\" icon=\"fa-sign-in\" msg=\"SALAXY.NG1.WelcomeComponent.showAnon.main.html\"></sxy-alert>\r\n * ```\r\n */\r\nexport class SxyAlert extends ComponentBase {\r\n\r\n  /** Inner content is the message. */\r\n  public transclude = true;\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /**\r\n     * Possibility to speicfy a font-awesome icon.\r\n     * Setting \"none\", will show no icon.\r\n     * If not set, it is determined by type.\r\n     */\r\n    icon: \"@\",\r\n\r\n    /** Type of the alert is the Bootstrap style: Note that also \"primary\" and \"default\" are supported. */\r\n    type: \"@\",\r\n\r\n    /**\r\n     * Translation key to HTML that should be the main message of the alert.\r\n     * You can alternatively provide html as main element (transclude).\r\n     */\r\n    msg: \"@\",\r\n\r\n    /**\r\n     * Alert main content as simple text.\r\n     * You can alternatively provide html as main element.\r\n     */\r\n    text: \"@\",\r\n\r\n    /**\r\n     * Optional Details part of the alert.\r\n     * Will automatically show \"Read more\" button.\r\n     */\r\n    aside: \"@\",\r\n  };\r\n\r\n  /** Uses the SxyFormElementController */\r\n  public controller = SxyFormElementController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/sxy-form/SxyAlert.html\";\r\n}\r\n","import { SxyCodeEditorController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Code editor can be used in editing JSON, Schema and even JavaScript and HTML.\r\n * The system uses Monaco editor if available or falls back to textarea when not available.\r\n * @example\r\n * ```html\r\n * <sxy-code-editor ng-model=\"$ctrl.currentSchema\" lang=\"json\"></sxy-code-editor>\r\n * ```\r\n */\r\nexport class SxyCodeEditor extends ComponentBase {\r\n\r\n  /** Components contents can be used to set the initial code. */\r\n  public transclude = true;\r\n\r\n  /** ng-model may be used to binding the code to a string in an object. */\r\n  public require = {\r\n    model: \"?ngModel\",\r\n  };\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Type of user interface to render: \"monaco\" (default) or \"basic\" HTML (textarea/pre) */\r\n    mode: \"@\",\r\n    /** If true, the component is read-only */\r\n    readOnly: \"<\",\r\n    /**\r\n     * Language of the code, e.g. \"javascript\" (default), \"html\", \"json\" or \"css\".\r\n     * Currently only affects the Monaco editor.\r\n     */\r\n    lang: \"@\",\r\n\r\n    /**\r\n     * Type of the main object that is called \"item\" in the code.\r\n     * Type should be one of @salaxy/core types (e.g. \"Calculation\") or supported\r\n     * native types (currently [\"any\", \"string\", \"[]\"]). Default is any.\r\n     */\r\n    itemType: \"<\",\r\n\r\n    /** The height of the editor as CSS, (e.g. \"calc(100vh - 600px)\"). Default is \"400px\" */\r\n    height: \"@\",\r\n  };\r\n\r\n  /** Uses the SxyInputController */\r\n  public controller = SxyCodeEditorController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/sxy-form/SxyCodeEditor.html\";\r\n}\r\n","import { Objects } from \"@salaxy/core\";\r\n\r\nimport { SxyInputController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a fieldset based on a given object in form\r\n * @example\r\n * ```html\r\n * <sxy-fieldset model=\"form.identity\"></sxy-fieldset>\r\n * ```\r\n */\r\nexport class SxyFieldset extends ComponentBase {\r\n\r\n    /** sxy-form is required */\r\n    public require = {\r\n        form: \"^^sxyForm\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(SxyInputController.bindings , {});\r\n\r\n    /** Uses the SxyInputController */\r\n    public controller = SxyInputController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/sxy-form/SxyFieldset.html\";\r\n}\r\n","import { SxyFormController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * The sxy-form component encapsulates the data binding and auto-generation logic for editable models using JSON schema.\r\n * @example\r\n * ```html\r\n * <sxy-form type=\"Calculation\" model=\"{}\"></sxy-form>\r\n * ```\r\n */\r\nexport class SxyForm extends ComponentBase {\r\n\r\n  /**\r\n   * Inner DIV element may be transclude.\r\n   * Future implementations will probably contain header, footer etc.\r\n   */\r\n  public transclude = {\r\n    div: \"?div\",\r\n  };\r\n\r\n  /** Component bindings. */\r\n  public bindings = {\r\n\r\n    /** Data object that is being edited by the fieldset. */\r\n    model: \"<\",\r\n\r\n    /** The data type that describes the object and creates the user interface. */\r\n    type: \"@\",\r\n\r\n    /**\r\n     * URL for the Open API document that contains the definition for the type.\r\n     * The url can be an absolute url, relative url or an url with salaxy-secure/ -prefix.\r\n     * The salaxy-secure/ -prefix will be replaced in runtime with the salaxy api server url of the curren environment.\r\n     */\r\n    openApi: \"@\",\r\n\r\n    /** Direct reference to internal document object. */\r\n    openApiDoc: \"<\",\r\n\r\n    /**\r\n     * The translation code for the label/legend/title.\r\n     * Default is \"SALAXY.MODEL.[type].title\"] or if not available, just the type text.\r\n     */\r\n    label: \"@\",\r\n\r\n    /**\r\n     * If true, the form is auto-generated from the type and inner HTML is ignored.\r\n     * If false (default), the inner HTML is used to show the form.\r\n     */\r\n    autoGen: \"<\",\r\n\r\n    /** If true, shows the form debugger */\r\n    debugger: \"<\",\r\n\r\n    /** Sets the entire form as read-only. Individual field may still be set read-only=false to make it editable. */\r\n    readOnly: \"@\",\r\n\r\n  };\r\n\r\n  /** Uses the SxyFormController */\r\n  public controller = SxyFormController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/sxy-form/SxyForm.html\";\r\n}\r\n","import { SxyGridController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows a grid component for view / edit of arrays.\r\n * @example\r\n * ```html\r\n * <sxy-grid schema=\"UserDefinedRow\" data=\"$ctrl.temp\"></sxy-grid>\r\n * ```\r\n */\r\nexport class SxyGrid extends ComponentBase {\r\n\r\n    /** sxy-form is optional */\r\n    public require = {\r\n        form: \"?^^sxyForm\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(SxyGridController.bindings , {});\r\n\r\n    /** Uses the SxyGridController */\r\n    public controller = SxyGridController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/sxy-form/SxyGrid.html\";\r\n}\r\n","import { SxyInputController } from \"../../controllers\";\r\n\r\nimport { Objects } from \"@salaxy/core\";\r\n\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows an input control with label, validation error, info etc.\r\n * @example\r\n * ```html\r\n * <sxy-ipt-text data-sxy=\"form.owner\" model=\"Calculation.owner\"></sxy-ipt-text>\r\n * ```\r\n */\r\nexport class SxyInput extends ComponentBase {\r\n\r\n    /** sxy-form is required */\r\n    public require = {\r\n        form: \"?^^sxyForm\",\r\n    };\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = Objects.extend(SxyInputController.bindings , {});\r\n\r\n    /**\r\n     * Transclude optional templates for input parts.\r\n     * Currently supports form, but may later support header, footer etc.\r\n     */\r\n    public transclude = {\r\n\r\n      /** Defines the inner form of Array dialogs and later potentially other dialogs and sub-forms */\r\n      form: \"?form\"\r\n    };\r\n\r\n    /** Uses the SxyIptController */\r\n    public controller = SxyInputController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/sxy-form/SxyInput.html\";\r\n}\r\n","import { SxySchemaEditorController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Open API schema editor: Used for editing schemas is usecases.\n * @example\r\n * ```html\r\n * <sxy-schema-editor model=\"$ctrl.currentSchema\"></sxy-schema-editor>\r\n * ```\r\n */\r\nexport class SxySchemaEditor extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      model: \"<\",\r\n    };\r\n\r\n    /** Uses the SxyInputController */\r\n    public controller = SxySchemaEditorController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/sxy-form/SxySchemaEditor.html\";\r\n}\r\n","import { SxyTableController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a read-only table based on a schema and ata.\r\n * @example <sxy-table></sxy-table>\r\n */\r\nexport class SxyTable extends ComponentBase {\r\n  /** Component bindings. */\r\n  public bindings = {\r\n    /** The schema definition that defines the structure of the grid. */\r\n    schemaDef: \"<\",\r\n\r\n    /** URL of the schema document that contains the schemaDef. If set with schema in init, loads the document.*/\r\n    doc: \"@\",\r\n\r\n    /** Key of schemaDef in doc. If set with doc in init, will load the schema document from server and set the schemaDef.*/\r\n    schema: \"@\",\r\n\r\n    /** Data that is rendered / edited in the grid. This is either an array or an object that implements getTabulatorConfig() method for ajax data.*/\r\n    data: \"<\",\r\n\r\n    /**\r\n     * List of columns to include in the grid.\r\n     * This may be an array or comma separated string of field names (or a property tree, e.g. \"owner.avatar.displayName\").\r\n     * Alternatively, the entries in the array may be be full Tabulator column definitions, where `field` propererty defines the\r\n     * data item and fetches the default properties from the schema.\r\n     */\r\n    include: \"<\",\r\n\r\n    /**\r\n     * List of columns to exclude from the grid.\r\n     * This property is currenlty used only if include property is undefined, i.e. in default\r\n     * rendering, which will render the first-level properties. As such, exclude does not really support property paths.\r\n     */\r\n    exclude: \"<\",\r\n\r\n    /** Additional configuration for the table in init. */\r\n    options: \"<\",\r\n\r\n    /** After init, exposes the Tabulator for calling methods. */\r\n    tabulator: \"<\",\r\n\r\n    /**\r\n     * Gets the state of filters or sets the initial state of filters.\r\n     * By default, the filters are not shown before showFilters() function is called.\r\n     * If the property / attribute is set to true before initial render, the filters are shown.\r\n     * Use showFilters() function to show or hide the filters after initial render.\r\n     */\r\n    filters: \"<\"\r\n  };\r\n\r\n  /** Uses the SxyTableController */\r\n  public controller = SxyTableController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/sxy-table/SxyTable.html\";\r\n}\r\n","import { AccountResetController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Methods for editing test account\r\n * @example\r\n * ```html\r\n * <salaxy-account-reset></salaxy-account-reset>\r\n * ```\r\n */\r\nexport class AccountReset extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to controller implementation\r\n     */\r\n    public bindings = {};\r\n\r\n    /** Uses the SessionController */\r\n    public controller = AccountResetController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/test/AccountReset.html\";\r\n}\r\n","import * as angular from \"angular\";\r\n\r\nimport { SmokeTestController } from \"../../controllers\";\r\n\r\n/**\r\n * Component for performing basic smoke test about salaxy libraries:\r\n * Are all the libraries and dependencies loaded and functional in the package.\r\n */\r\nexport class SmokeTest implements angular.IComponentOptions {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to controller implementation\r\n   */\r\n  bindings = {\r\n    /** Defines the view / set of tests: \"core\" or \"ng1\" */\r\n    mode: \"@\",\r\n  };\r\n\r\n  /** Uses the SalaxySmokeTestController */\r\n  public controller = SmokeTestController;\r\n\r\n  /** Teh template URL */\r\n  public templateUrl = \"salaxy-components/test/SmokeTest.html\";\r\n}\r\n","import { HolidayYearAccrualController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * UI for holiday accrual (lomapäivien kertymä) of the annual leave for a selected holiday period.\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-year-accrual parent=\"$ctrl.current\"></salaxy-holiday-year-accrual>\r\n * ```\r\n */\r\nexport class HolidayYearAccrual extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = HolidayYearAccrualController.bindings;\r\n\r\n    /** Uses the HolidayYearAccrualController */\r\n    public controller = HolidayYearAccrualController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/holidays/HolidayYearAccrual.html\";\r\n\r\n}\r\n","import { HolidayYearHolidaysController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * UI for the planned holidays list (lomakirjanpito / lomakalenteri) for a selected holiday year.\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-year-holidays></salaxy-holiday-year-holidays>\r\n * ```\r\n */\r\nexport class HolidayYearHolidays extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = HolidayYearHolidaysController.bindings;\r\n\r\n    /** Uses the HolidayYearHolidaysController */\r\n    public controller = HolidayYearHolidaysController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/holidays/HolidayYearHolidays.html\";\r\n\r\n}\r\n","import { HolidayYearPaidController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * User interface for the annual leave payments: HolidayCompensation, HolidayBonus and HolidaySalary.\r\n * These payments are typically fetched from paid calculations automatically,\r\n * but may also be marked paid manually. Also, in client-side logic, payments are fetched\r\n * optionally from Draft calculations.\r\n * @example\r\n * ```html\r\n * <salaxy-holiday-year-paid parent=\"$ctrl.current\"></salaxy-holiday-year-paid>\r\n * ```\r\n */\r\nexport class HolidayYearPaid extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = HolidayYearPaidController.bindings;\r\n\r\n    /** Uses the HolidayYearPaidController */\r\n    public controller = HolidayYearPaidController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/holidays/HolidayYearPaid.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, HolidayYearCrudController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Viewing and modifying of Worker holidays (holiday years and related settings).\r\n * @example\r\n * ```html\r\n * <salaxy-worker-holidays></salaxy-worker-holidays>\r\n * ```\r\n */\r\nexport class WorkerHolidays extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n      /**\r\n       * Alternative model binding.\r\n       * Instead of model=\"holidayYearId\", you may specify employment-id=\"employmentId\".\r\n       * This loads all the holiday years to HolidayYearCrudController.employmentHolidayYears\r\n       */\r\n      public employmentId = \"<\";\r\n\r\n      /**\r\n       * Setting this value (iso date) will specify the the holiday year:\r\n       * If the date is Jan-April will show the previous year, May-Dec will show the current year.\r\n       * Default is today.\r\n       */\r\n      public forDate = \"<\";\r\n\r\n      /**\r\n       * If true, the view is for accruals (not for paid holidays or holiday planning).\r\n       */\r\n      public isAccrualView: \"<\";\r\n\r\n    }());\r\n\r\n    /** Uses the HolidayYearCrudController */\r\n    public controller = HolidayYearCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/holidays/WorkerHolidays.html\";\r\n\r\n}\r\n","import { EmploymentTaxcardsController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Helps listing current all tax cards for an employment relation (latest and previous ones).\r\n * @example\r\n * ```html\r\n * <salaxy-employment-taxcards employment-id=\"$ctrl.current.employmentId\"></salaxy-employment-taxcards>\r\n * ```\r\n */\r\nexport class EmploymentTaxcards extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** Employment ID of the Worker whose taxcards are shown in the component. */\r\n    employmentId: \"<\",\r\n\r\n    /**\r\n     * View mode:\r\n     *\r\n     * - \"active\" only shows the active taxcard.\r\n     * - \"list\" only shows the history list.\r\n     * - \"all\" (default) shows both active and history.\r\n     */\r\n    mode: \"@\",\r\n\r\n    /**\r\n     * Event that is called when a taxcard is saved and the parent UI probably needs to be refreshed.\r\n     * @example <salaxy-employment-taxcards employment-id=\"$ctrl.current.employmentId\" on-save=\"$ctrl.refresh()\"></salaxy-employment-taxcards>\r\n     */\r\n     onSave: \"&\",\r\n\r\n\r\n     /** If true, does not show the save / current buttons - the parent must show them. */\r\n    hideButtons: \"<\",\r\n  };\r\n\r\n  /** Uses the EmploymentTaxcardsController */\r\n  public controller = EmploymentTaxcardsController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/worker/taxcard/EmploymentTaxcards.html\";\r\n}\r\n","import { ApiCrudObjectControllerBindings, TaxcardCrudController } from \"../../../controllers\";\r\n\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows the editor for a taxcard.\r\n * @example\r\n * ```html\r\n * <salaxy-taxcard-details model=\"$ctrl\" mode=\"pro\"></salaxy-taxcard-details>\r\n * ```\r\n */\r\n\r\nexport class TaxcardDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /** Mode is either \"pro\" (for admin / PRO-ui) or \"default\" */\r\n    public mode = \"@\";\r\n    /**\r\n     * Either a valid Finnish Personal ID or \"self\" for the current Worker account.\r\n     * Required for creating a new taxcard: The personal ID is used for setting the connection to Worker account or self.\r\n     */\r\n    public personalId = \"<\";\r\n\r\n    /**\r\n     * Event that is called when a taxcard is saved and the parent UI probably needs to be refreshed.\r\n     * @example <salaxy-taxcard-details model=\"$ctrl.current.active\" personal-id=\"$ctrl.current.personalId\" on-save=\"$ctrl.reload()\"></salaxy-taxcard-details>\r\n     */\r\n    public onSave = \"&\";\r\n\r\n    /** If true, does not show the save / current buttons - the parent must show them. */\r\n    public hideButtons = \"<\";\r\n    /** Type of employment taxcard */\r\n    public employmentRelationTaxcardType = \"<\";\r\n  }());\r\n\r\n  /** Uses the TaxcardCrudController */\r\n  public controller = TaxcardCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/worker/taxcard/TaxcardDetails.html\";\r\n\r\n}\r\n","import { ListControllerBaseBindings, TaxcardIncomeLogController } from \"../../../controllers\";\r\n\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\nclass TaxcardIncomeLogBindings extends ListControllerBaseBindings {\r\n /** If true, the list can be edited, by default it is read-only. */\r\n public editable = \"<\";\r\n}\r\n\r\n/**\r\n * Shows view / editor table for the income log of taxcard.\r\n * @example\r\n * ```html\r\n * <salaxy-taxcard-income-log parent=\"$ctrl.current\"></salaxy-taxcard-income-log>\r\n * ```\r\n */\r\n\r\nexport class TaxcardIncomeLog extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = new TaxcardIncomeLogBindings();\r\n\r\n  /** Uses the TaxcardIncomeLogController */\r\n  public controller = TaxcardIncomeLogController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/worker/taxcard/TaxcardIncomeLog.html\";\r\n\r\n}\r\n","import { TaxcardManualEditController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a UI for editing a manual taxcard.\n * Typically, this is only used for adding a new tacard: You should not edit existing taxcards except in very limited scenarios (admin/pro).\n * @example\r\n * ```html\r\n * <salaxy-taxcard-manual-edit ng-ref=\"$edit\" current=\"$ctrl.item\"></salaxy-taxcard-manual-edit>\r\n * <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" ng-disabled=\"!$edit.isFormValid\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n * ```\r\n */\r\nexport class TaxcardManualEdit extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n    /** The taxcard that is being edited */\r\n    current: \"<\",\r\n  };\r\n\r\n  /** Uses the ODataQueryController */\r\n  public controller = TaxcardManualEditController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/worker/taxcard/TaxcardManualEdit.html\";\r\n\r\n}\r\n","import { ODataQueryController } from \"../../../controllers\";\r\nimport { ComponentBase } from \"../../_ComponentBase\";\r\n\r\n/**\r\n * Shows a list of workers and their taxcards\r\n * @example\r\n * ```html\r\n * <salaxy-tax-cards-list></salaxy-tax-cards-list>\r\n * ```\r\n */\r\nexport class TaxCardsList extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n  };\r\n\r\n  /** Uses the ODataQueryController */\r\n  public controller = ODataQueryController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/worker/taxcard/TaxCardsList.html\";\r\n\r\n}\r\n","import { AbsencePeriodsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * UI for the absences list (poissaolokirjanpito).\r\n * @example\r\n * ```html\r\n * <salaxy-absence-periods></salaxy-absence-periods>\r\n * ```\r\n */\r\nexport class AbsencePeriods extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = AbsencePeriodsController.bindings;\r\n\r\n    /** Uses the AbsencePeriodsController */\r\n    public controller = AbsencePeriodsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/AbsencePeriods.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, EmploymentCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders an edit view for single Employment relation (Worker for one Employer).\r\n * @example\r\n * ```html\r\n * <salaxy-employment-details-edit></salaxy-employment-details-edit>\r\n * ```\r\n */\r\nexport class EmploymentDetails extends ComponentBase {\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n      /** Current tab in initialization. */\r\n      public currentTab = \"@\";\r\n\r\n      /** If true, the component is shown in modal: Hide buttons and switch employment works in a different way. */\r\n      public isModal = \"<\";\r\n    }());\r\n\r\n    /** Uses the EmploymentCrudController */\r\n    public controller = EmploymentCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/employment/Details.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, WorkerAbsencesCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * UI for absences of a single worker / employment relation.\r\n * @example\r\n * ```html\r\n * <salaxy-worker-absences employment-id=\"$ctrl.current.employmentId\"></salaxy-worker-absences>\r\n * ```\r\n */\r\nexport class WorkerAbsences extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n\r\n      /**\r\n       * Alternative model binding.\r\n       * Instead of model=\"absenceObjectId\", you may specify employment-id=\"employmentId\"\r\n       */\r\n      public employmentId = \"<\";\r\n\r\n    }());\r\n\r\n    /** Uses the WorkerAbsencesCrudController */\r\n    public controller = WorkerAbsencesCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/WorkerAbsences.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, WorkerAccountCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * LEGACY: Shows a view of a single worker account, which may have one or several Employments Relations.\r\n * This used to be the main way of viewing and editing Worker AND Employment details, but now the Employment view is used instead.\r\n * @deprecated Use EmploymentDetails instead.\r\n */\r\nexport class WorkerDetails extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n    /** Uses the WorkerAccountCrudController */\r\n    public controller = WorkerAccountCrudController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/WorkerDetails.html\";\r\n\r\n}\r\n","import { ODataQueryController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n\r\n/**\r\n * Shows a list of employment relations for an employer.\r\n * Note that for backward compatibility, this list is also available as\r\n * salaxy-worker-list component (to be removed).\r\n * @example\r\n * ```html\r\n * <salaxy-employment-list limit-to=\"5\" mode=\"select\"></salaxy-employment-list>\r\n * <!--\r\n * Legacy:\r\n * <salaxy-worker-list limit-to=\"5\" mode=\"select\"></salaxy-worker-list>\r\n * -->\r\n * ```\r\n */\r\nexport class EmploymentList extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = {\r\n\r\n    /**\r\n     * Function that is called when user selects an item in the list.\r\n     * Note that the event is called only in the selections (single and multi). Not when there is a link to details view in a link list.\r\n     * Function has the following locals: value: true/false, item: the last selected/unselected item, allItems: Array of all currently selected items.\r\n     * @example <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id)\"></salaxy-employment-list>\r\n     */\r\n    onListSelect: \"&\",\r\n\r\n    /** Selected items for the case where the list is used as a select list (as opposed to link list). */\r\n    selectedItems: \"<\",\r\n\r\n    /** Type of the view. Currently supports \"default\" and \"select\" */\r\n    mode: \"@\",\r\n\r\n    /** Max count of workers to show in the list. */\r\n    limitTo: \"<\",\r\n\r\n    /** If readOnly is true, edit, copy etc. buttons from the new list view are hidden if readOnly property is supported */\r\n    readOnly: \"<\",\r\n\r\n    /** boolean indicating if toolbar should be shown*/\r\n    showToolbar: \"<\"\r\n\r\n  };\r\n\r\n    /** Uses the ODataQueryController */\r\n    public controller = ODataQueryController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/worker/EmploymentList.html\";\r\n\r\n}\r\n","import { ApiCrudObjectControllerBindings, CalendarEventsCrudController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders an editor / details component for a Calendar Event.\r\n * @example\r\n * ```html\r\n * <salaxy-calendar-event-details model=\"'url\"></salaxy-calendar-event-details>\r\n * ```\r\n */\r\nexport class CalendarEventDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = (new class extends ApiCrudObjectControllerBindings {}());\r\n\r\n  /** Uses the CalendarEventsCrudController */\r\n  public controller = CalendarEventsCrudController;\r\n\r\n  /** The default template for the component. */\r\n  public defaultTemplate = \"salaxy-components/workflow/CalendarEventDetails.html\";\r\n}\r\n","import { DatasetsCrudController, ApiCrudObjectControllerBindings } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Provides UI for viewing and editing datasets.\r\n * @example\r\n * ```html\r\n * <salaxy-dataset-details></salaxy-dataset-details>\r\n * ```\r\n */\r\n\r\nexport class DatasetDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n   public bindings = (new class extends ApiCrudObjectControllerBindings {\r\n    /** Type of user interface to show. */\r\n    public mode = \"@\";\r\n\r\n    /** Defines the default usecase (uri) that is used for new calculations. */\r\n    public defaultUsecase = \"@\";\r\n  }());\r\n\r\n  /** Uses the DatasetsCrudController */\r\n  public controller = DatasetsCrudController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/workflow/dataset/DatasetDetails.html\";\r\n\r\n}\r\n","import { UsecasesCrudController, ApiCrudObjectControllerBindings } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Provides UI for viewing and editing usecase.\r\n * @example\r\n * ```html\r\n * <salaxy-usecase-details></salaxy-usecase-details>\r\n * ```\r\n */\r\n\r\nexport class UsecaseDetails extends ComponentBase {\r\n\r\n  /**\r\n   * The following component properties (attributes in HTML) are bound to the Controller.\r\n   * For detailed functionality, refer to [controller](#controller) implementation.\r\n   */\r\n  public bindings = new ApiCrudObjectControllerBindings();\r\n\r\n  /** Uses the UsecasesCrudController */\r\n  public controller = UsecasesCrudController;\r\n\r\n  /** Default template is the view  */\r\n  public defaultTemplate = \"salaxy-components/workflow/usecases/UsecaseDetails.html\";\r\n\r\n}\r\n","import { RecordsController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * UI for records of the entity .\r\n * @example\r\n * ```html\r\n * <salaxy-records entity-type=\"'employment'\" api-ctrl=\"$worker\"></salaxy-records>\r\n * ```\r\n */\r\nexport class Records extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n     /**\r\n      * Binding to entity type\r\n      */\r\n      entityType: \"<\",\r\n\r\n      /** Expression for the api controller . */\r\n      apiCtrl: \"<\",\r\n\r\n      /** Binding to read only state */\r\n      readOnly: \"<\"\r\n\r\n    };\r\n\r\n    /** Uses the WorkerRecordsController */\r\n    public controller = RecordsController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/records/Records.html\";\r\n\r\n}\r\n","import { WorkflowController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a workflow buttons in the toolbar for assign, issue, close.\r\n * @example\r\n * ```html\r\n * <salaxy-workflow-buttons api-ctrl=\"$ctrl\" disabled=\"!ok\"></salaxy-workflow-buttons>\r\n * ```\r\n */\r\nexport class WorkflowButtons extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Expression for the api controller . */\r\n      apiCtrl: \"<\",\r\n      /** Optional binding for enabling/disabling the controls */\r\n      disabled: \"<\",\r\n    };\r\n\r\n    /** Uses the WorkflowController */\r\n    public controller = WorkflowController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/workflow/WorkflowButtons.html\";\r\n}\r\n","import { WorkflowController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Renders a workflow re-open control.\r\n * @example\r\n * ```html\r\n * <salaxy-workflow-reopen api-ctrl=\"$ctrl\"  disabled=\"!ok\" ></salaxy-workflow-reopen>\r\n * ```\r\n */\r\nexport class WorkflowReopen extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Expression for the api controller . */\r\n      apiCtrl: \"<\",\r\n      /** Optional binding for enabling/disabling the control */\r\n      disabled: \"<\",\r\n      /** Called when workflow action has been taken */\r\n      onChange: \"&\",\r\n    };\r\n\r\n    /** Uses the WorkflowController */\r\n    public controller = WorkflowController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/workflow/WorkflowReopen.html\";\r\n}\r\n","import { WorkflowBadgeController } from \"../../controllers\";\r\nimport { ComponentBase } from \"../_ComponentBase\";\r\n\r\n/**\r\n * Shows the workflow badge for object or list item.\r\n * @example\r\n * ```html\r\n * <salaxy-workflow-badge api-ctrl=\"$ctrl\" model=\"$ctrl.current\" wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n * ```\r\n */\r\nexport class WorkflowBadge extends ComponentBase {\r\n\r\n    /**\r\n     * The following component properties (attributes in HTML) are bound to the Controller.\r\n     * For detailed functionality, refer to [controller](#controller) implementation.\r\n     */\r\n    public bindings = {\r\n      /** Expression for the api controller . */\r\n      apiCtrl: \"<\",\r\n      /** Object or list item which contains workflow message data. */\r\n      model: \"<\",\r\n      /** Comma separated list of types to show the badge for. */\r\n      wfTypes: \"<\",\r\n      /** Visual mode of the component: horizontal or vertical (default). */\r\n      mode: \"@\"\r\n    };\r\n\r\n    /** Uses the WorkflowBadgeController */\r\n    public controller = WorkflowBadgeController;\r\n\r\n    /** The default template for the component. */\r\n    public defaultTemplate = \"salaxy-components/workflow/WorkflowBadge.html\";\r\n}\r\n","// Components\r\nimport {\r\n  AbsencePeriods,\r\n  Accountant,\r\n  AccountAuthorizationPerson,\r\n  AccountAvatarEdit,\r\n  AccountAvatarEditPerson,\r\n  AccountContactEdit,\r\n  AccountContactEditPerson,\r\n  AccountDetailsEditPerson,\r\n  AccountDetailsPerson,\r\n  AccountInfo,\r\n  AccountInfoPerson,\r\n  AccountingReportList,\r\n  AccountingReportQuery,\r\n  AccountingHolidayPayDebtReportQuery,\r\n  AccountingReportRows,\r\n  AccountingReportTools,\r\n  AccountingReportViewer,\r\n  AccountingRowReport,\r\n  AccountingSettings,\r\n  AccountingTargetDetails,\r\n  AccountingTargetSettings,\r\n  AccountInsuranceEditPerson,\r\n  AccountReset,\r\n  ActionButton,\r\n  Alert,\r\n  AssurePartner,\r\n  AuthCard,\r\n  AuthorizedAccounts,\r\n  AuthorizingAccounts,\r\n  Avatar,\r\n  Calc,\r\n  CalcChart,\r\n  CalcCostAccounting,\r\n  CalcDashboard,\r\n  CalendarEventDetails,\r\n  CalcEmployment,\r\n  CalcEditor,\r\n  CalcHouseholdUsecase,\r\n  CalcImport,\r\n  CalcIrRows,\r\n  CalcsIrRows,\r\n  CalcList,\r\n  CalcNewIntro,\r\n  CalcReport,\r\n  CalcReports,\r\n  CalcResults,\r\n  CalcRowCostAccounting,\r\n  CalcRowDimensionInput,\r\n  CalcRowsEditor,\r\n  CalcRows2019Editor,\r\n  CalcRowType,\r\n  CalcSharing,\r\n  CalcSharingInfo,\r\n  CalcSharingReceiptAction,\r\n  CalcLeaves,\r\n  CalculationReport,\r\n  CalcUsecase,\r\n  CalcWorkerInfo,\r\n  CalcWorktime,\r\n  Calendar,\r\n  Certificates,\r\n  Chart,\r\n  CompanyImport,\r\n  CompanyInvoices,\r\n  ContactInfo,\r\n  CostAccounting,\r\n  CostAccountingSettings,\r\n  HolidaySettings,\r\n  Credentials,\r\n  CreditTransfer,\r\n  DataMapper,\r\n  DatasetDetails,\r\n  Datepicker,\r\n  DatepickerPopup,\r\n  DateRange,\r\n  EmployerList,\r\n  EmployerReport,\r\n  EmployerSelect,\r\n  EmploymentDetails,\r\n  EmploymentTaxcards,\r\n  ExpenseReport,\r\n  FormGroup,\r\n  HolidayPayReportQuery,\r\n  HolidayReport,\r\n  HolidayYearAccrual,\r\n  HolidayYearHolidays,\r\n  HolidayYearPaid,\r\n  HourlyReport,\r\n  HouseholdDeductionReport,\r\n  HouseholdYearDetails,\r\n  HouseholdYearList,\r\n  ImportStaging,\r\n  InputAccountingTarget,\r\n  Input,\r\n  InputBoolean,\r\n  InputCredential,\r\n  InputDuration,\r\n  InputEnum,\r\n  InputHolidayMultipliers,\r\n  InputHolidayRowType,\r\n  InputIncomeType,\r\n  InputNumber,\r\n  InputOccupationType,\r\n  InputRrule,\r\n  InputTime,\r\n  Insurance,\r\n  InsuranceSettings,\r\n  InvoiceAlerts,\r\n  InvoiceEdit,\r\n  InvoiceList,\r\n  InvoicePreview,\r\n  InvoicesCreate,\r\n  InvoiceTools,\r\n  InvoiceReport,\r\n  IrEarningsPayment,\r\n  IrPayerSummary,\r\n  JsonFormatter,\r\n  LanguageSelector,\r\n  LoginButton,\r\n  MessageThread,\r\n  MessageThreadList,\r\n  NaviSitemap,\r\n  NaviStarterLayout,\r\n  OdataActions,\r\n  OdataFooter,\r\n  OdataTable,\r\n  OwnerSettings,\r\n  PayButton,\r\n  PayCertificate,\r\n  PaymentChannelInvoicePreview,\r\n  PaymentChannelSettings,\r\n  PaymentSettings,\r\n  PayrollDetails,\r\n  PayrollDetailsList,\r\n  PayrollDetailsSelectList,\r\n  PayrollEdit,\r\n  PayrollList,\r\n  PayrollSelectList,\r\n  ProSettings,\r\n  Records,\r\n  ReportList,\r\n  RowTypesSettings,\r\n  SalaryDateKindButton,\r\n  SalaryReportList,\r\n  ServiceModelDetails,\r\n  Signing,\r\n  SmokeTest,\r\n  Spinner,\r\n  SummaryReport,\r\n  SummaryReportQuery,\r\n  SxyAlert,\r\n  SxyCodeEditor,\r\n  SxyFieldset,\r\n  SxyForm,\r\n  SxyTable,\r\n  SxyGrid,\r\n  SxyInput,\r\n  SxySchemaEditor,\r\n  Tab,\r\n  Tabs,\r\n  TaxcardDetails,\r\n  TaxcardIncomeLog,\r\n  TaxcardManualEdit,\r\n  TaxCardsList,\r\n  Textarea,\r\n  Timer,\r\n  UiTranslator,\r\n  UsecaseDetails,\r\n  UserInfo,\r\n  ValidationSummary,\r\n  VarmaBanner,\r\n  Welcome,\r\n  WorkerAbsences,\r\n  WorkerAssure,\r\n  WorkerDetails,\r\n  WorkerHolidays,\r\n  WorkerImport,\r\n  EmploymentList,\r\n  WorkerReport,\r\n  WorkerSummaryReport,\r\n  WorkflowButtons,\r\n  WorkflowBadge,\r\n  WorkflowReopen,\r\n} from \"./index_components\";\r\nimport {\r\n  IrEarningsPaymentList,\r\n  IrPayerSummaryList\r\n} from \"./report\";\r\n\r\n/**\r\n * Provides the method for registering components to the module.\r\n */\r\nexport class ComponentsRegistration {\r\n\r\n  /** Gets the components for Module registration. */\r\n  public static getComponents() {\r\n    return {\r\n      // - account\r\n      salaxyAccountInfo: new AccountInfo() as any,\r\n      salaxyAssurePartner: new AssurePartner() as any,\r\n      salaxyAuthCard: new AuthCard() as any,\r\n      salaxyAuthorizedAccounts: new AuthorizedAccounts() as any,\r\n      salaxyAuthorizingAccounts: new AuthorizingAccounts() as any,\r\n      salaxyCertificates: new Certificates() as any,\r\n      salaxyCredentials: new Credentials() as any,\r\n      salaxyLanguageSelector: new LanguageSelector() as any,\r\n      salaxyLoginButton: new LoginButton() as any,\r\n      salaxySigning: new Signing() as any,\r\n      salaxyUserInfo: new UserInfo() as any,\r\n      salaxyAccountAvatarEdit: new AccountAvatarEdit() as any,\r\n      salaxyAccountContactEdit: new AccountContactEdit() as any,\r\n\r\n      // - personal\r\n      salaxyAccountAuthorizationPerson: new AccountAuthorizationPerson() as any,\r\n      salaxyAccountAvatarEditPerson: new AccountAvatarEditPerson() as any,\r\n      salaxyAccountContactEditPerson: new AccountContactEditPerson() as any,\r\n      salaxyAccountDetailsEditPerson: new AccountDetailsEditPerson() as any,\r\n      salaxyAccountDetailsPerson: new AccountDetailsPerson() as any,\r\n      salaxyAccountInfoPerson: new AccountInfoPerson() as any,\r\n      salaxyAccountInsuranceEditPerson: new AccountInsuranceEditPerson() as any,\r\n      salaxyEmployerList: new EmployerList() as any,\r\n      salaxyEmployerSelect: new EmployerSelect() as any,\r\n\r\n      // - calc\r\n      salaxyCalcEmployment: new CalcEmployment() as any,\r\n      salaxyCalcHouseholdUsecase: new CalcHouseholdUsecase() as any,\r\n      salaxyCalcIrRows: new CalcIrRows() as any,\r\n      salaxyCalcsIrRows: new CalcsIrRows() as any,\r\n      salaxyCalcList: new CalcList() as any,\r\n      salaxyCalcWorktime: new CalcWorktime() as any,\r\n      salaxyCalc: new Calc() as any,\r\n      salaxyCalcChart: new CalcChart() as any,\r\n      salaxyCalcDashboard: new CalcDashboard() as any,\r\n      salaxyCalcEditor: new CalcEditor() as any,\r\n      salaxyCalcNewIntro: new CalcNewIntro() as any,\r\n      salaxyCalcReport: new CalcReport() as any,\r\n      salaxyCalcReports: new CalcReports() as any,\r\n      salaxyCalcResults: new CalcResults() as any,\r\n      salaxyCalcRowType: new CalcRowType() as any,\r\n      salaxyCalcRowsEditor: new CalcRowsEditor() as any,\r\n      salaxyCalcRows2019Editor: new CalcRows2019Editor() as any,\r\n      salaxyCalcUsecase: new CalcUsecase() as any,\r\n      salaxyPayrollDetails: new PayrollDetails() as any,\r\n      salaxyPayrollDetailsList: new PayrollDetailsList() as any,\r\n      salaxyPayrollDetailsSelectList: new PayrollDetailsSelectList() as any,\r\n      salaxyPayrollEdit: new PayrollEdit() as any,\r\n      salaxyPayrollList: new PayrollList() as any,\r\n      salaxyPayButton: new PayButton() as any,\r\n      salaxySalaryDateKindButton: new SalaryDateKindButton() as any,\r\n      salaxyCalcSharing: new CalcSharing() as any,\r\n      salaxyCalcSharingInfo: new CalcSharingInfo() as any,\r\n      salaxyCalcSharingReceiptAction: new CalcSharingReceiptAction() as any,\r\n      salaxyCalcLeaves: new CalcLeaves() as any,\r\n      salaxyCalcWorkerInfo: new CalcWorkerInfo() as any,\r\n      salaxyPayrollSelectList: new PayrollSelectList as any,\r\n      salaxyCalcCostAccounting: new CalcCostAccounting as any,\r\n      salaxyCalcRowCostAccounting: new CalcRowCostAccounting as any,\r\n      salaxyCalcRowDimensionInput: new CalcRowDimensionInput as any,\r\n      salaxyCostAccounting: new CostAccounting as any,\r\n\r\n      // - communications\r\n      salaxyContactInfo: new ContactInfo() as any,\r\n      salaxyHourlyReport: new HourlyReport() as any,\r\n      salaxyMessageThread: new MessageThread() as any,\r\n      salaxyMessageThreadList: new MessageThreadList() as any,\r\n      salaxyTimer: new Timer() as any,\r\n      salaxyVarmaBanner: new VarmaBanner() as any,\r\n      salaxyWelcome: new Welcome() as any,\r\n      salaxyExpenseReport: new ExpenseReport() as any,\r\n\r\n      // - sxy-form framework\r\n      sxyAlert: new SxyAlert() as any,\r\n      sxyCodeEditor: new SxyCodeEditor() as any,\r\n      sxyFieldset: new SxyFieldset() as any,\r\n      sxyForm: new SxyForm() as any,\r\n      sxyGrid: new SxyGrid() as any,\r\n      sxyInput: new SxyInput() as any,\r\n      sxySchemaEditor: new SxySchemaEditor() as any,\r\n\r\n      // - sxy-table framework\r\n      sxyTable: new SxyTable() as any,\r\n\r\n      // - test: Test data and system testing.\r\n      salaxyAccountReset: new AccountReset() as any,\r\n      salaxySmokeTest: new SmokeTest() as any,\r\n\r\n      // - form-controls\r\n      salaxyDatepicker: new Datepicker() as any,\r\n      salaxyDatepickerPopup: new DatepickerPopup() as any,\r\n      salaxyDateRange: new DateRange() as any,\r\n      salaxyFormGroup: new FormGroup() as any,\r\n      salaxyInput: new Input() as any,\r\n      salaxyInputBoolean: new InputBoolean() as any,\r\n      salaxyInputCredential: new InputCredential() as any,\r\n      salaxyInputDuration: new InputDuration() as any,\r\n      salaxyInputEnum: new InputEnum() as any,\r\n      salaxyInputIncomeType: new InputIncomeType() as any,\r\n      salaxyInputNumber: new InputNumber() as any,\r\n      salaxyInputOccupationType: new InputOccupationType() as any,\r\n      salaxyInputRrule: new InputRrule() as any,\r\n      salaxyInputTime: new InputTime() as any,\r\n      salaxyTextarea: new Textarea() as any,\r\n      salaxyValidationSummary: new ValidationSummary() as any,\r\n      salaxyInputAccountingTarget: new InputAccountingTarget() as any,\r\n      salaxyInputHolidayMultipliers: new InputHolidayMultipliers() as any,\r\n      salaxyInputHolidayRowType: new InputHolidayRowType() as any,\r\n\r\n      // - helpers\r\n      salaxyActionButton: new ActionButton() as any,\r\n      salaxyAlert: new Alert() as any,\r\n      salaxyAvatar: new Avatar() as any,\r\n      salaxyChart: new Chart() as any,\r\n      salaxyCalendar: new Calendar() as any,\r\n      salaxyDataMapper: new DataMapper() as any,\r\n      salaxyJsonFormatter: new JsonFormatter() as any,\r\n      salaxyNaviSitemap: new NaviSitemap() as any,\r\n      salaxyNaviStarterLayout: new NaviStarterLayout() as any,\r\n      salaxyOdataActions: new OdataActions() as any,\r\n      salaxyOdataFooter: new OdataFooter() as any,\r\n      salaxyOdataTable: new OdataTable() as any,\r\n      salaxySpinner: new Spinner() as any,\r\n      salaxyTabs: new Tabs() as any,\r\n      salaxyTab: new Tab() as any,\r\n      salaxyUiTranslator: new UiTranslator() as any,\r\n\r\n      // - import\r\n      salaxyCalcImport: new CalcImport() as any,\r\n      salaxyCompanyImport: new CompanyImport() as any,\r\n      salaxyImportStaging: new ImportStaging() as any,\r\n      salaxyWorkerImport: new WorkerImport as any,\r\n\r\n      // - invoices\r\n      salaxyCreditTransfer: new CreditTransfer() as any,\r\n      salaxyInvoiceAlerts: new InvoiceAlerts() as any,\r\n      salaxyInvoiceEdit: new InvoiceEdit() as any,\r\n      salaxyInvoiceList: new InvoiceList() as any,\r\n      salaxyInvoicePreview: new InvoicePreview() as any,\r\n      salaxyInvoicesCreate: new InvoicesCreate() as any,\r\n      salaxyPaymentChannelInvoicePreview: new PaymentChannelInvoicePreview() as any,\r\n      salaxyInvoiceTools: new InvoiceTools() as any,\r\n      salaxyInvoiceReport: new InvoiceReport() as any,\r\n      salaxyCompanyInvoices: new CompanyInvoices,\r\n\r\n      // - report\r\n      salaxyHolidayReport: new HolidayReport() as any,\r\n      salaxyHolidayPayReportQuery: new HolidayPayReportQuery() as any,\r\n      salaxyIrEarningsPayment: new IrEarningsPayment() as any,\r\n      salaxyIrEarningsPaymentList: new IrEarningsPaymentList() as any,\r\n      salaxyIrPayerSummary: new IrPayerSummary() as any,\r\n      salaxyIrPayerSummaryList: new IrPayerSummaryList() as any,\r\n      salaxyReportList: new ReportList() as any,\r\n      salaxySalaryReportList: new SalaryReportList() as any,\r\n      salaxyAccountingReportQuery: new AccountingReportQuery() as any,\r\n      salaxyAccountingHolidayPayDebtReportQuery: new AccountingHolidayPayDebtReportQuery() as any,\r\n      salaxyAccountingReportList: new AccountingReportList() as any,\r\n      salaxyAccountingReportRows: new AccountingReportRows() as any,\r\n      salaxyAccountingReportTools: new AccountingReportTools() as any,\r\n      salaxyAccountingReportViewer: new AccountingReportViewer() as any,\r\n      salaxyPayCertificate: new PayCertificate() as any,\r\n      salaxyCalculationReport: new CalculationReport() as any,\r\n      salaxyAccountingRowReport: new AccountingRowReport() as any,\r\n      salaxyEmployerReport: new EmployerReport() as any,\r\n      salaxyWorkerReport: new WorkerReport() as any,\r\n      salaxyHouseholdDeductionReport: new HouseholdDeductionReport() as any,\r\n      salaxyHouseholdYearDetails: new HouseholdYearDetails() as any,\r\n      salaxyHouseholdYearList: new HouseholdYearList() as any,\r\n      salaxySummaryReport: new SummaryReport() as any,\r\n      salaxySummaryReportQuery: new SummaryReportQuery() as any,\r\n      salaxyWorkerSummaryReport: new WorkerSummaryReport() as any,\r\n\r\n      // - worker\r\n      salaxyAbsencePeriods: new AbsencePeriods() as any,\r\n      salaxyEmploymentDetails: new EmploymentDetails(),\r\n      salaxyEmploymentTaxcards: new EmploymentTaxcards() as any,\r\n      salaxyHolidayYearAccrual: new HolidayYearAccrual() as any,\r\n      salaxyHolidayYearHolidays: new HolidayYearHolidays() as any,\r\n      salaxyHolidayYearPaid: new HolidayYearPaid() as any,\r\n      salaxyTaxcardDetails: new TaxcardDetails() as any,\r\n      salaxyTaxcardIncomeLog: new TaxcardIncomeLog() as any,\r\n      salaxyTaxcardManualEdit: new TaxcardManualEdit() as any,\r\n      salaxyTaxCardsList: new TaxCardsList() as any,\r\n      salaxyWorkerAbsences: new WorkerAbsences() as any,\r\n      salaxyWorkerDetails: new WorkerDetails() as any,\r\n      salaxyWorkerHolidays: new WorkerHolidays() as any,\r\n      salaxyEmploymentList: new EmploymentList() as any,\r\n      salaxyWorkerList: new EmploymentList() as any, // For backward compatibility only\r\n\r\n      // - obsolete\r\n      salaxyWorkerAssure: new WorkerAssure() as any,\r\n\r\n      // - workflow\r\n      salaxyCalendarEventDetails: new CalendarEventDetails() as any,\r\n      salaxyDatasetDetails: new DatasetDetails() as any,\r\n      salaxyWorkflowButtons: new WorkflowButtons() as any,\r\n      salaxyWorkflowReopen: new WorkflowReopen() as any,\r\n      salaxyWorkflowBadge: new WorkflowBadge() as any,\r\n\r\n      // - records\r\n      salaxyRecords: new Records() as any,\r\n\r\n      // - settings\r\n      salaxyAccountant: new Accountant() as any,\r\n      salaxyRowTypesSettings: new RowTypesSettings() as any,\r\n      salaxyAccountingTargetDetails: new AccountingTargetDetails() as any,\r\n      salaxyInsurance: new Insurance() as any,\r\n      salaxyInsuranceSettings: new InsuranceSettings() as any,\r\n      salaxyOwnerSettings: new OwnerSettings() as any,\r\n      salaxyPaymentChannelSettings: new PaymentChannelSettings() as any,\r\n      salaxyPaymentSettings: new PaymentSettings() as any,\r\n      salaxyProSettings: new ProSettings() as any,\r\n      salaxyAccountingTargetSettings: new   AccountingTargetSettings() as any,\r\n      salaxyServiceModelDetails: new ServiceModelDetails() as any,\r\n      salaxyUsecaseDetails: new UsecaseDetails() as any,\r\n      salaxyCostAccountingSettings: new CostAccountingSettings() as any,\r\n      salaxyAccountingSettings: new AccountingSettings() as any,\r\n      salaxyHolidaySettings: new HolidaySettings() as any\r\n    };\r\n  }\r\n}\r\n","/**\n * @license AngularJS v1.8.3\n * (c) 2010-2020 Google LLC. http://angularjs.org\n * License: MIT\n */\n(function(window, angular) {'use strict';\n\n/* global shallowCopy: true */\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for (var i = 0, ii = src.length; i < ii; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n/* global routeToRegExp: true */\n\n/**\n * @param {string} path - The path to parse. (It is assumed to have query and hash stripped off.)\n * @param {Object} opts - Options.\n * @return {Object} - An object containing an array of path parameter names (`keys`) and a regular\n *     expression (`regexp`) that can be used to identify a matching URL and extract the path\n *     parameter values.\n *\n * @description\n * Parses the given path, extracting path parameter names and a regular expression to match URLs.\n *\n * Originally inspired by `pathRexp` in `visionmedia/express/lib/utils.js`.\n */\nfunction routeToRegExp(path, opts) {\n  var keys = [];\n\n  var pattern = path\n    .replace(/([().])/g, '\\\\$1')\n    .replace(/(\\/)?:(\\w+)(\\*\\?|[?*])?/g, function(_, slash, key, option) {\n      var optional = option === '?' || option === '*?';\n      var star = option === '*' || option === '*?';\n      keys.push({name: key, optional: optional});\n      slash = slash || '';\n      return (\n        (optional ? '(?:' + slash : slash + '(?:') +\n        (star ? '(.+?)' : '([^/]+)') +\n        (optional ? '?)?' : ')')\n      );\n    })\n    .replace(/([/$*])/g, '\\\\$1');\n\n  if (opts.ignoreTrailingSlashes) {\n    pattern = pattern.replace(/\\/+$/, '') + '/*';\n  }\n\n  return {\n    keys: keys,\n    regexp: new RegExp(\n      '^' + pattern + '(?:[?#]|$)',\n      opts.caseInsensitiveMatch ? 'i' : ''\n    )\n  };\n}\n\n/* global routeToRegExp: false */\n/* global shallowCopy: false */\n\n// `isArray` and `isObject` are necessary for `shallowCopy()` (included via `src/shallowCopy.js`).\n// They are initialized inside the `$RouteProvider`, to ensure `window.angular` is available.\nvar isArray;\nvar isObject;\nvar isDefined;\nvar noop;\n\n/**\n * @ngdoc module\n * @name ngRoute\n * @description\n *\n * The `ngRoute` module provides routing and deeplinking services and directives for AngularJS apps.\n *\n * ## Example\n * See {@link ngRoute.$route#examples $route} for an example of configuring and using `ngRoute`.\n *\n */\n/* global -ngRouteModule */\nvar ngRouteModule = angular.\n  module('ngRoute', []).\n  info({ angularVersion: '1.8.3' }).\n  provider('$route', $RouteProvider).\n  // Ensure `$route` will be instantiated in time to capture the initial `$locationChangeSuccess`\n  // event (unless explicitly disabled). This is necessary in case `ngView` is included in an\n  // asynchronously loaded template.\n  run(instantiateRoute);\nvar $routeMinErr = angular.$$minErr('ngRoute');\nvar isEagerInstantiationEnabled;\n\n\n/**\n * @ngdoc provider\n * @name $routeProvider\n * @this\n *\n * @description\n *\n * Used for configuring routes.\n *\n * ## Example\n * See {@link ngRoute.$route#examples $route} for an example of configuring and using `ngRoute`.\n *\n * ## Dependencies\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n */\nfunction $RouteProvider() {\n  isArray = angular.isArray;\n  isObject = angular.isObject;\n  isDefined = angular.isDefined;\n  noop = angular.noop;\n\n  function inherit(parent, extra) {\n    return angular.extend(Object.create(parent), extra);\n  }\n\n  var routes = {};\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#when\n   *\n   * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n   *    contains redundant trailing slash or is missing one, the route will still match and the\n   *    `$location.path` will be updated to add or drop the trailing slash to exactly match the\n   *    route definition.\n   *\n   *    * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up\n   *        to the next slash are matched and stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *    * `path` can contain named groups starting with a colon and ending with a star:\n   *        e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`\n   *        when the route matches.\n   *    * `path` can contain optional named groups with a question mark: e.g.`:name?`.\n   *\n   *    For example, routes like `/color/:color/largecode/:largecode*\\/edit` will match\n   *    `/color/brown/largecode/code/with/slashes/edit` and extract:\n   *\n   *    * `color: brown`\n   *    * `largecode: code/with/slashes`.\n   *\n   *\n   * @param {Object} route Mapping information to be assigned to `$route.current` on route\n   *    match.\n   *\n   *    Object properties:\n   *\n   *    - `controller` – `{(string|Function)=}` – Controller fn that should be associated with\n   *      newly created scope or the name of a {@link angular.Module#controller registered\n   *      controller} if passed as a string.\n   *    - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.\n   *      If present, the controller will be published to scope under the `controllerAs` name.\n   *    - `template` – `{(string|Function)=}` – html template as a string or a function that\n   *      returns an html template as a string which should be used by {@link\n   *      ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.\n   *      This property takes precedence over `templateUrl`.\n   *\n   *      If `template` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *      One of `template` or `templateUrl` is required.\n   *\n   *    - `templateUrl` – `{(string|Function)=}` – path or function that returns a path to an html\n   *      template that should be used by {@link ngRoute.directive:ngView ngView}.\n   *\n   *      If `templateUrl` is a function, it will be called with the following parameters:\n   *\n   *      - `{Array.<Object>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route\n   *\n   *      One of `templateUrl` or `template` is required.\n   *\n   *    - `resolve` - `{Object.<string, Function>=}` - An optional map of dependencies which should\n   *      be injected into the controller. If any of these dependencies are promises, the router\n   *      will wait for them all to be resolved or one to be rejected before the controller is\n   *      instantiated.\n   *      If all the promises are resolved successfully, the values of the resolved promises are\n   *      injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is\n   *      fired. If any of the promises are rejected the\n   *      {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired.\n   *      For easier access to the resolved dependencies from the template, the `resolve` map will\n   *      be available on the scope of the route, under `$resolve` (by default) or a custom name\n   *      specified by the `resolveAs` property (see below). This can be particularly useful, when\n   *      working with {@link angular.Module#component components} as route templates.<br />\n   *      <div class=\"alert alert-warning\">\n   *        **Note:** If your scope already contains a property with this name, it will be hidden\n   *        or overwritten. Make sure, you specify an appropriate name for this property, that\n   *        does not collide with other properties on the scope.\n   *      </div>\n   *      The map object is:\n   *\n   *      - `key` – `{string}`: a name of a dependency to be injected into the controller.\n   *      - `factory` - `{string|Function}`: If `string` then it is an alias for a service.\n   *        Otherwise if function, then it is {@link auto.$injector#invoke injected}\n   *        and the return value is treated as the dependency. If the result is a promise, it is\n   *        resolved before its value is injected into the controller. Be aware that\n   *        `ngRoute.$routeParams` will still refer to the previous route within these resolve\n   *        functions.  Use `$route.current.params` to access the new route parameters, instead.\n   *\n   *    - `resolveAs` - `{string=}` - The name under which the `resolve` map will be available on\n   *      the scope of the route. If omitted, defaults to `$resolve`.\n   *\n   *    - `redirectTo` – `{(string|Function)=}` – value to update\n   *      {@link ng.$location $location} path with and trigger route redirection.\n   *\n   *      If `redirectTo` is a function, it will be called with the following parameters:\n   *\n   *      - `{Object.<string>}` - route parameters extracted from the current\n   *        `$location.path()` by applying the current route templateUrl.\n   *      - `{string}` - current `$location.path()`\n   *      - `{Object}` - current `$location.search()`\n   *\n   *      The custom `redirectTo` function is expected to return a string which will be used\n   *      to update `$location.url()`. If the function throws an error, no further processing will\n   *      take place and the {@link ngRoute.$route#$routeChangeError $routeChangeError} event will\n   *      be fired.\n   *\n   *      Routes that specify `redirectTo` will not have their controllers, template functions\n   *      or resolves called, the `$location` will be changed to the redirect url and route\n   *      processing will stop. The exception to this is if the `redirectTo` is a function that\n   *      returns `undefined`. In this case the route transition occurs as though there was no\n   *      redirection.\n   *\n   *    - `resolveRedirectTo` – `{Function=}` – a function that will (eventually) return the value\n   *      to update {@link ng.$location $location} URL with and trigger route redirection. In\n   *      contrast to `redirectTo`, dependencies can be injected into `resolveRedirectTo` and the\n   *      return value can be either a string or a promise that will be resolved to a string.\n   *\n   *      Similar to `redirectTo`, if the return value is `undefined` (or a promise that gets\n   *      resolved to `undefined`), no redirection takes place and the route transition occurs as\n   *      though there was no redirection.\n   *\n   *      If the function throws an error or the returned promise gets rejected, no further\n   *      processing will take place and the\n   *      {@link ngRoute.$route#$routeChangeError $routeChangeError} event will be fired.\n   *\n   *      `redirectTo` takes precedence over `resolveRedirectTo`, so specifying both on the same\n   *      route definition, will cause the latter to be ignored.\n   *\n   *    - `[reloadOnUrl=true]` - `{boolean=}` - reload route when any part of the URL changes\n   *      (including the path) even if the new URL maps to the same route.\n   *\n   *      If the option is set to `false` and the URL in the browser changes, but the new URL maps\n   *      to the same route, then a `$routeUpdate` event is broadcasted on the root scope (without\n   *      reloading the route).\n   *\n   *    - `[reloadOnSearch=true]` - `{boolean=}` - reload route when only `$location.search()`\n   *      or `$location.hash()` changes.\n   *\n   *      If the option is set to `false` and the URL in the browser changes, then a `$routeUpdate`\n   *      event is broadcasted on the root scope (without reloading the route).\n   *\n   *      <div class=\"alert alert-warning\">\n   *        **Note:** This option has no effect if `reloadOnUrl` is set to `false`.\n   *      </div>\n   *\n   *    - `[caseInsensitiveMatch=false]` - `{boolean=}` - match routes without being case sensitive\n   *\n   *      If the option is set to `true`, then the particular route can be matched without being\n   *      case sensitive\n   *\n   * @returns {Object} self\n   *\n   * @description\n   * Adds a new route definition to the `$route` service.\n   */\n  this.when = function(path, route) {\n    //copy original route object to preserve params inherited from proto chain\n    var routeCopy = shallowCopy(route);\n    if (angular.isUndefined(routeCopy.reloadOnUrl)) {\n      routeCopy.reloadOnUrl = true;\n    }\n    if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n      routeCopy.reloadOnSearch = true;\n    }\n    if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n      routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n    }\n    routes[path] = angular.extend(\n      routeCopy,\n      {originalPath: path},\n      path && routeToRegExp(path, routeCopy)\n    );\n\n    // create redirection for trailing slashes\n    if (path) {\n      var redirectPath = (path[path.length - 1] === '/')\n            ? path.substr(0, path.length - 1)\n            : path + '/';\n\n      routes[redirectPath] = angular.extend(\n        {originalPath: path, redirectTo: path},\n        routeToRegExp(redirectPath, routeCopy)\n      );\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc property\n   * @name $routeProvider#caseInsensitiveMatch\n   * @description\n   *\n   * A boolean property indicating if routes defined\n   * using this provider should be matched using a case insensitive\n   * algorithm. Defaults to `false`.\n   */\n  this.caseInsensitiveMatch = false;\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#otherwise\n   *\n   * @description\n   * Sets route definition that will be used on route change when no other route definition\n   * is matched.\n   *\n   * @param {Object|string} params Mapping information to be assigned to `$route.current`.\n   * If called with a string, the value maps to `redirectTo`.\n   * @returns {Object} self\n   */\n  this.otherwise = function(params) {\n    if (typeof params === 'string') {\n      params = {redirectTo: params};\n    }\n    this.when(null, params);\n    return this;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $routeProvider#eagerInstantiationEnabled\n   * @kind function\n   *\n   * @description\n   * Call this method as a setter to enable/disable eager instantiation of the\n   * {@link ngRoute.$route $route} service upon application bootstrap. You can also call it as a\n   * getter (i.e. without any arguments) to get the current value of the\n   * `eagerInstantiationEnabled` flag.\n   *\n   * Instantiating `$route` early is necessary for capturing the initial\n   * {@link ng.$location#$locationChangeStart $locationChangeStart} event and navigating to the\n   * appropriate route. Usually, `$route` is instantiated in time by the\n   * {@link ngRoute.ngView ngView} directive. Yet, in cases where `ngView` is included in an\n   * asynchronously loaded template (e.g. in another directive's template), the directive factory\n   * might not be called soon enough for `$route` to be instantiated _before_ the initial\n   * `$locationChangeSuccess` event is fired. Eager instantiation ensures that `$route` is always\n   * instantiated in time, regardless of when `ngView` will be loaded.\n   *\n   * The default value is true.\n   *\n   * **Note**:<br />\n   * You may want to disable the default behavior when unit-testing modules that depend on\n   * `ngRoute`, in order to avoid an unexpected request for the default route's template.\n   *\n   * @param {boolean=} enabled - If provided, update the internal `eagerInstantiationEnabled` flag.\n   *\n   * @returns {*} The current value of the `eagerInstantiationEnabled` flag if used as a getter or\n   *     itself (for chaining) if used as a setter.\n   */\n  isEagerInstantiationEnabled = true;\n  this.eagerInstantiationEnabled = function eagerInstantiationEnabled(enabled) {\n    if (isDefined(enabled)) {\n      isEagerInstantiationEnabled = enabled;\n      return this;\n    }\n\n    return isEagerInstantiationEnabled;\n  };\n\n\n  this.$get = ['$rootScope',\n               '$location',\n               '$routeParams',\n               '$q',\n               '$injector',\n               '$templateRequest',\n               '$sce',\n               '$browser',\n      function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce, $browser) {\n\n    /**\n     * @ngdoc service\n     * @name $route\n     * @requires $location\n     * @requires $routeParams\n     *\n     * @property {Object} current Reference to the current route definition.\n     * The route definition contains:\n     *\n     *   - `controller`: The controller constructor as defined in the route definition.\n     *   - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n     *     controller instantiation. The `locals` contain\n     *     the resolved values of the `resolve` map. Additionally the `locals` also contain:\n     *\n     *     - `$scope` - The current route scope.\n     *     - `$template` - The current route template HTML.\n     *\n     *     The `locals` will be assigned to the route scope's `$resolve` property. You can override\n     *     the property name, using `resolveAs` in the route definition. See\n     *     {@link ngRoute.$routeProvider $routeProvider} for more info.\n     *\n     * @property {Object} routes Object with all route configuration Objects as its properties.\n     *\n     * @description\n     * `$route` is used for deep-linking URLs to controllers and views (HTML partials).\n     * It watches `$location.url()` and tries to map the path to an existing route definition.\n     *\n     * Requires the {@link ngRoute `ngRoute`} module to be installed.\n     *\n     * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.\n     *\n     * The `$route` service is typically used in conjunction with the\n     * {@link ngRoute.directive:ngView `ngView`} directive and the\n     * {@link ngRoute.$routeParams `$routeParams`} service.\n     *\n     * @example\n     * This example shows how changing the URL hash causes the `$route` to match a route against the\n     * URL, and the `ngView` pulls in the partial.\n     *\n     * <example name=\"$route-service\" module=\"ngRouteExample\"\n     *          deps=\"angular-route.js\" fixBase=\"true\">\n     *   <file name=\"index.html\">\n     *     <div ng-controller=\"MainController\">\n     *       Choose:\n     *       <a href=\"Book/Moby\">Moby</a> |\n     *       <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n     *       <a href=\"Book/Gatsby\">Gatsby</a> |\n     *       <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n     *       <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n     *\n     *       <div ng-view></div>\n     *\n     *       <hr />\n     *\n     *       <pre>$location.path() = {{$location.path()}}</pre>\n     *       <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>\n     *       <pre>$route.current.params = {{$route.current.params}}</pre>\n     *       <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>\n     *       <pre>$routeParams = {{$routeParams}}</pre>\n     *     </div>\n     *   </file>\n     *\n     *   <file name=\"book.html\">\n     *     controller: {{name}}<br />\n     *     Book Id: {{params.bookId}}<br />\n     *   </file>\n     *\n     *   <file name=\"chapter.html\">\n     *     controller: {{name}}<br />\n     *     Book Id: {{params.bookId}}<br />\n     *     Chapter Id: {{params.chapterId}}\n     *   </file>\n     *\n     *   <file name=\"script.js\">\n     *     angular.module('ngRouteExample', ['ngRoute'])\n     *\n     *      .controller('MainController', function($scope, $route, $routeParams, $location) {\n     *          $scope.$route = $route;\n     *          $scope.$location = $location;\n     *          $scope.$routeParams = $routeParams;\n     *      })\n     *\n     *      .controller('BookController', function($scope, $routeParams) {\n     *          $scope.name = 'BookController';\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *      .controller('ChapterController', function($scope, $routeParams) {\n     *          $scope.name = 'ChapterController';\n     *          $scope.params = $routeParams;\n     *      })\n     *\n     *     .config(function($routeProvider, $locationProvider) {\n     *       $routeProvider\n     *        .when('/Book/:bookId', {\n     *         templateUrl: 'book.html',\n     *         controller: 'BookController',\n     *         resolve: {\n     *           // I will cause a 1 second delay\n     *           delay: function($q, $timeout) {\n     *             var delay = $q.defer();\n     *             $timeout(delay.resolve, 1000);\n     *             return delay.promise;\n     *           }\n     *         }\n     *       })\n     *       .when('/Book/:bookId/ch/:chapterId', {\n     *         templateUrl: 'chapter.html',\n     *         controller: 'ChapterController'\n     *       });\n     *\n     *       // configure html5 to get links working on jsfiddle\n     *       $locationProvider.html5Mode(true);\n     *     });\n     *\n     *   </file>\n     *\n     *   <file name=\"protractor.js\" type=\"protractor\">\n     *     it('should load and compile correct template', function() {\n     *       element(by.linkText('Moby: Ch1')).click();\n     *       var content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller: ChapterController/);\n     *       expect(content).toMatch(/Book Id: Moby/);\n     *       expect(content).toMatch(/Chapter Id: 1/);\n     *\n     *       element(by.partialLinkText('Scarlet')).click();\n     *\n     *       content = element(by.css('[ng-view]')).getText();\n     *       expect(content).toMatch(/controller: BookController/);\n     *       expect(content).toMatch(/Book Id: Scarlet/);\n     *     });\n     *   </file>\n     * </example>\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeStart\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted before a route change. At this  point the route services starts\n     * resolving all of the dependencies needed for the route change to occur.\n     * Typically this involves fetching the view template as well as any dependencies\n     * defined in `resolve` route property. Once  all of the dependencies are resolved\n     * `$routeChangeSuccess` is fired.\n     *\n     * The route change (and the `$location` change that triggered it) can be prevented\n     * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n     * for more details about event object.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} next Future route information.\n     * @param {Route} current Current route information.\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeSuccess\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted after a route change has happened successfully.\n     * The `resolve` dependencies are now available in the `current.locals` property.\n     *\n     * {@link ngRoute.directive:ngView ngView} listens for the directive\n     * to instantiate the controller and render the view.\n     *\n     * @param {Object} angularEvent Synthetic event object.\n     * @param {Route} current Current route information.\n     * @param {Route|Undefined} previous Previous route information, or undefined if current is\n     * first route entered.\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeChangeError\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if a redirection function fails or any redirection or resolve promises are\n     * rejected.\n     *\n     * @param {Object} angularEvent Synthetic event object\n     * @param {Route} current Current route information.\n     * @param {Route} previous Previous route information.\n     * @param {Route} rejection The thrown error or the rejection reason of the promise. Usually\n     * the rejection reason is the error that caused the promise to get rejected.\n     */\n\n    /**\n     * @ngdoc event\n     * @name $route#$routeUpdate\n     * @eventType broadcast on root scope\n     * @description\n     * Broadcasted if the same instance of a route (including template, controller instance,\n     * resolved dependencies, etc.) is being reused. This can happen if either `reloadOnSearch` or\n     * `reloadOnUrl` has been set to `false`.\n     *\n     * @param {Object} angularEvent Synthetic event object\n     * @param {Route} current Current/previous route information.\n     */\n\n    var forceReload = false,\n        preparedRoute,\n        preparedRouteIsUpdateOnly,\n        $route = {\n          routes: routes,\n\n          /**\n           * @ngdoc method\n           * @name $route#reload\n           *\n           * @description\n           * Causes `$route` service to reload the current route even if\n           * {@link ng.$location $location} hasn't changed.\n           *\n           * As a result of that, {@link ngRoute.directive:ngView ngView}\n           * creates new scope and reinstantiates the controller.\n           */\n          reload: function() {\n            forceReload = true;\n\n            var fakeLocationEvent = {\n              defaultPrevented: false,\n              preventDefault: function fakePreventDefault() {\n                this.defaultPrevented = true;\n                forceReload = false;\n              }\n            };\n\n            $rootScope.$evalAsync(function() {\n              prepareRoute(fakeLocationEvent);\n              if (!fakeLocationEvent.defaultPrevented) commitRoute();\n            });\n          },\n\n          /**\n           * @ngdoc method\n           * @name $route#updateParams\n           *\n           * @description\n           * Causes `$route` service to update the current URL, replacing\n           * current route parameters with those specified in `newParams`.\n           * Provided property names that match the route's path segment\n           * definitions will be interpolated into the location's path, while\n           * remaining properties will be treated as query params.\n           *\n           * @param {!Object<string, string>} newParams mapping of URL parameter names to values\n           */\n          updateParams: function(newParams) {\n            if (this.current && this.current.$$route) {\n              newParams = angular.extend({}, this.current.params, newParams);\n              $location.path(interpolate(this.current.$$route.originalPath, newParams));\n              // interpolate modifies newParams, only query params are left\n              $location.search(newParams);\n            } else {\n              throw $routeMinErr('norout', 'Tried updating route with no current route');\n            }\n          }\n        };\n\n    $rootScope.$on('$locationChangeStart', prepareRoute);\n    $rootScope.$on('$locationChangeSuccess', commitRoute);\n\n    return $route;\n\n    /////////////////////////////////////////////////////\n\n    /**\n     * @param on {string} current url\n     * @param route {Object} route regexp to match the url against\n     * @return {?Object}\n     *\n     * @description\n     * Check if the route matches the current url.\n     *\n     * Inspired by match in\n     * visionmedia/express/lib/router/router.js.\n     */\n    function switchRouteMatcher(on, route) {\n      var keys = route.keys,\n          params = {};\n\n      if (!route.regexp) return null;\n\n      var m = route.regexp.exec(on);\n      if (!m) return null;\n\n      for (var i = 1, len = m.length; i < len; ++i) {\n        var key = keys[i - 1];\n\n        var val = m[i];\n\n        if (key && val) {\n          params[key.name] = val;\n        }\n      }\n      return params;\n    }\n\n    function prepareRoute($locationEvent) {\n      var lastRoute = $route.current;\n\n      preparedRoute = parseRoute();\n      preparedRouteIsUpdateOnly = isNavigationUpdateOnly(preparedRoute, lastRoute);\n\n      if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n        if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n          if ($locationEvent) {\n            $locationEvent.preventDefault();\n          }\n        }\n      }\n    }\n\n    function commitRoute() {\n      var lastRoute = $route.current;\n      var nextRoute = preparedRoute;\n\n      if (preparedRouteIsUpdateOnly) {\n        lastRoute.params = nextRoute.params;\n        angular.copy(lastRoute.params, $routeParams);\n        $rootScope.$broadcast('$routeUpdate', lastRoute);\n      } else if (nextRoute || lastRoute) {\n        forceReload = false;\n        $route.current = nextRoute;\n\n        var nextRoutePromise = $q.resolve(nextRoute);\n\n        $browser.$$incOutstandingRequestCount('$route');\n\n        nextRoutePromise.\n          then(getRedirectionData).\n          then(handlePossibleRedirection).\n          then(function(keepProcessingRoute) {\n            return keepProcessingRoute && nextRoutePromise.\n              then(resolveLocals).\n              then(function(locals) {\n                // after route change\n                if (nextRoute === $route.current) {\n                  if (nextRoute) {\n                    nextRoute.locals = locals;\n                    angular.copy(nextRoute.params, $routeParams);\n                  }\n                  $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n                }\n              });\n          }).catch(function(error) {\n            if (nextRoute === $route.current) {\n              $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n            }\n          }).finally(function() {\n            // Because `commitRoute()` is called from a `$rootScope.$evalAsync` block (see\n            // `$locationWatch`), this `$$completeOutstandingRequest()` call will not cause\n            // `outstandingRequestCount` to hit zero.  This is important in case we are redirecting\n            // to a new route which also requires some asynchronous work.\n\n            $browser.$$completeOutstandingRequest(noop, '$route');\n          });\n      }\n    }\n\n    function getRedirectionData(route) {\n      var data = {\n        route: route,\n        hasRedirection: false\n      };\n\n      if (route) {\n        if (route.redirectTo) {\n          if (angular.isString(route.redirectTo)) {\n            data.path = interpolate(route.redirectTo, route.params);\n            data.search = route.params;\n            data.hasRedirection = true;\n          } else {\n            var oldPath = $location.path();\n            var oldSearch = $location.search();\n            var newUrl = route.redirectTo(route.pathParams, oldPath, oldSearch);\n\n            if (angular.isDefined(newUrl)) {\n              data.url = newUrl;\n              data.hasRedirection = true;\n            }\n          }\n        } else if (route.resolveRedirectTo) {\n          return $q.\n            resolve($injector.invoke(route.resolveRedirectTo)).\n            then(function(newUrl) {\n              if (angular.isDefined(newUrl)) {\n                data.url = newUrl;\n                data.hasRedirection = true;\n              }\n\n              return data;\n            });\n        }\n      }\n\n      return data;\n    }\n\n    function handlePossibleRedirection(data) {\n      var keepProcessingRoute = true;\n\n      if (data.route !== $route.current) {\n        keepProcessingRoute = false;\n      } else if (data.hasRedirection) {\n        var oldUrl = $location.url();\n        var newUrl = data.url;\n\n        if (newUrl) {\n          $location.\n            url(newUrl).\n            replace();\n        } else {\n          newUrl = $location.\n            path(data.path).\n            search(data.search).\n            replace().\n            url();\n        }\n\n        if (newUrl !== oldUrl) {\n          // Exit out and don't process current next value,\n          // wait for next location change from redirect\n          keepProcessingRoute = false;\n        }\n      }\n\n      return keepProcessingRoute;\n    }\n\n    function resolveLocals(route) {\n      if (route) {\n        var locals = angular.extend({}, route.resolve);\n        angular.forEach(locals, function(value, key) {\n          locals[key] = angular.isString(value) ?\n              $injector.get(value) :\n              $injector.invoke(value, null, null, key);\n        });\n        var template = getTemplateFor(route);\n        if (angular.isDefined(template)) {\n          locals['$template'] = template;\n        }\n        return $q.all(locals);\n      }\n    }\n\n    function getTemplateFor(route) {\n      var template, templateUrl;\n      if (angular.isDefined(template = route.template)) {\n        if (angular.isFunction(template)) {\n          template = template(route.params);\n        }\n      } else if (angular.isDefined(templateUrl = route.templateUrl)) {\n        if (angular.isFunction(templateUrl)) {\n          templateUrl = templateUrl(route.params);\n        }\n        if (angular.isDefined(templateUrl)) {\n          route.loadedTemplateUrl = $sce.valueOf(templateUrl);\n          template = $templateRequest(templateUrl);\n        }\n      }\n      return template;\n    }\n\n    /**\n     * @returns {Object} the current active route, by matching it against the URL\n     */\n    function parseRoute() {\n      // Match a route\n      var params, match;\n      angular.forEach(routes, function(route, path) {\n        if (!match && (params = switchRouteMatcher($location.path(), route))) {\n          match = inherit(route, {\n            params: angular.extend({}, $location.search(), params),\n            pathParams: params});\n          match.$$route = route;\n        }\n      });\n      // No route matched; fallback to \"otherwise\" route\n      return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n    }\n\n    /**\n     * @param {Object} newRoute - The new route configuration (as returned by `parseRoute()`).\n     * @param {Object} oldRoute - The previous route configuration (as returned by `parseRoute()`).\n     * @returns {boolean} Whether this is an \"update-only\" navigation, i.e. the URL maps to the same\n     *                    route and it can be reused (based on the config and the type of change).\n     */\n    function isNavigationUpdateOnly(newRoute, oldRoute) {\n      // IF this is not a forced reload\n      return !forceReload\n          // AND both `newRoute`/`oldRoute` are defined\n          && newRoute && oldRoute\n          // AND they map to the same Route Definition Object\n          && (newRoute.$$route === oldRoute.$$route)\n          // AND `reloadOnUrl` is disabled\n          && (!newRoute.reloadOnUrl\n              // OR `reloadOnSearch` is disabled\n              || (!newRoute.reloadOnSearch\n                  // AND both routes have the same path params\n                  && angular.equals(newRoute.pathParams, oldRoute.pathParams)\n              )\n          );\n    }\n\n    /**\n     * @returns {string} interpolation of the redirect path with the parameters\n     */\n    function interpolate(string, params) {\n      var result = [];\n      angular.forEach((string || '').split(':'), function(segment, i) {\n        if (i === 0) {\n          result.push(segment);\n        } else {\n          var segmentMatch = segment.match(/(\\w+)(?:[?*])?(.*)/);\n          var key = segmentMatch[1];\n          result.push(params[key]);\n          result.push(segmentMatch[2] || '');\n          delete params[key];\n        }\n      });\n      return result.join('');\n    }\n  }];\n}\n\ninstantiateRoute.$inject = ['$injector'];\nfunction instantiateRoute($injector) {\n  if (isEagerInstantiationEnabled) {\n    // Instantiate `$route`\n    $injector.get('$route');\n  }\n}\n\nngRouteModule.provider('$routeParams', $RouteParamsProvider);\n\n\n/**\n * @ngdoc service\n * @name $routeParams\n * @requires $route\n * @this\n *\n * @description\n * The `$routeParams` service allows you to retrieve the current set of route parameters.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * The route parameters are a combination of {@link ng.$location `$location`}'s\n * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.\n * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * Note that the `$routeParams` are only updated *after* a route change completes successfully.\n * This means that you cannot rely on `$routeParams` being correct in route resolve functions.\n * Instead you can use `$route.current.params` to access the new route's parameters.\n *\n * @example\n * ```js\n *  // Given:\n *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n *  // Route: /Chapter/:chapterId/Section/:sectionId\n *  //\n *  // Then\n *  $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}\n * ```\n */\nfunction $RouteParamsProvider() {\n  this.$get = function() { return {}; };\n}\n\nngRouteModule.directive('ngView', ngViewFactory);\nngRouteModule.directive('ngView', ngViewFillContentFactory);\n\n\n/**\n * @ngdoc directive\n * @name ngView\n * @restrict ECA\n *\n * @description\n * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * @animations\n * | Animation                        | Occurs                              |\n * |----------------------------------|-------------------------------------|\n * | {@link ng.$animate#enter enter}  | when the new element is inserted to the DOM |\n * | {@link ng.$animate#leave leave}  | when the old element is removed from to the DOM  |\n *\n * The enter and leave animation occur concurrently.\n *\n * @scope\n * @priority 400\n * @param {string=} onload Expression to evaluate whenever the view updates.\n *\n * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the view is updated.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated\n *                    as an expression yields a truthy value.\n * @example\n    <example name=\"ngView-directive\" module=\"ngViewExample\"\n             deps=\"angular-route.js;angular-animate.js\"\n             animations=\"true\" fixBase=\"true\">\n      <file name=\"index.html\">\n        <div ng-controller=\"MainCtrl as main\">\n          Choose:\n          <a href=\"Book/Moby\">Moby</a> |\n          <a href=\"Book/Moby/ch/1\">Moby: Ch1</a> |\n          <a href=\"Book/Gatsby\">Gatsby</a> |\n          <a href=\"Book/Gatsby/ch/4?key=value\">Gatsby: Ch4</a> |\n          <a href=\"Book/Scarlet\">Scarlet Letter</a><br/>\n\n          <div class=\"view-animate-container\">\n            <div ng-view class=\"view-animate\"></div>\n          </div>\n          <hr />\n\n          <pre>$location.path() = {{main.$location.path()}}</pre>\n          <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>\n          <pre>$route.current.params = {{main.$route.current.params}}</pre>\n          <pre>$routeParams = {{main.$routeParams}}</pre>\n        </div>\n      </file>\n\n      <file name=\"book.html\">\n        <div>\n          controller: {{book.name}}<br />\n          Book Id: {{book.params.bookId}}<br />\n        </div>\n      </file>\n\n      <file name=\"chapter.html\">\n        <div>\n          controller: {{chapter.name}}<br />\n          Book Id: {{chapter.params.bookId}}<br />\n          Chapter Id: {{chapter.params.chapterId}}\n        </div>\n      </file>\n\n      <file name=\"animations.css\">\n        .view-animate-container {\n          position:relative;\n          height:100px!important;\n          background:white;\n          border:1px solid black;\n          height:40px;\n          overflow:hidden;\n        }\n\n        .view-animate {\n          padding:10px;\n        }\n\n        .view-animate.ng-enter, .view-animate.ng-leave {\n          transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n\n          display:block;\n          width:100%;\n          border-left:1px solid black;\n\n          position:absolute;\n          top:0;\n          left:0;\n          right:0;\n          bottom:0;\n          padding:10px;\n        }\n\n        .view-animate.ng-enter {\n          left:100%;\n        }\n        .view-animate.ng-enter.ng-enter-active {\n          left:0;\n        }\n        .view-animate.ng-leave.ng-leave-active {\n          left:-100%;\n        }\n      </file>\n\n      <file name=\"script.js\">\n        angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])\n          .config(['$routeProvider', '$locationProvider',\n            function($routeProvider, $locationProvider) {\n              $routeProvider\n                .when('/Book/:bookId', {\n                  templateUrl: 'book.html',\n                  controller: 'BookCtrl',\n                  controllerAs: 'book'\n                })\n                .when('/Book/:bookId/ch/:chapterId', {\n                  templateUrl: 'chapter.html',\n                  controller: 'ChapterCtrl',\n                  controllerAs: 'chapter'\n                });\n\n              $locationProvider.html5Mode(true);\n          }])\n          .controller('MainCtrl', ['$route', '$routeParams', '$location',\n            function MainCtrl($route, $routeParams, $location) {\n              this.$route = $route;\n              this.$location = $location;\n              this.$routeParams = $routeParams;\n          }])\n          .controller('BookCtrl', ['$routeParams', function BookCtrl($routeParams) {\n            this.name = 'BookCtrl';\n            this.params = $routeParams;\n          }])\n          .controller('ChapterCtrl', ['$routeParams', function ChapterCtrl($routeParams) {\n            this.name = 'ChapterCtrl';\n            this.params = $routeParams;\n          }]);\n\n      </file>\n\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should load and compile correct template', function() {\n          element(by.linkText('Moby: Ch1')).click();\n          var content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller: ChapterCtrl/);\n          expect(content).toMatch(/Book Id: Moby/);\n          expect(content).toMatch(/Chapter Id: 1/);\n\n          element(by.partialLinkText('Scarlet')).click();\n\n          content = element(by.css('[ng-view]')).getText();\n          expect(content).toMatch(/controller: BookCtrl/);\n          expect(content).toMatch(/Book Id: Scarlet/);\n        });\n      </file>\n    </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];\nfunction ngViewFactory($route, $anchorScroll, $animate) {\n  return {\n    restrict: 'ECA',\n    terminal: true,\n    priority: 400,\n    transclude: 'element',\n    link: function(scope, $element, attr, ctrl, $transclude) {\n        var currentScope,\n            currentElement,\n            previousLeaveAnimation,\n            autoScrollExp = attr.autoscroll,\n            onloadExp = attr.onload || '';\n\n        scope.$on('$routeChangeSuccess', update);\n        update();\n\n        function cleanupLastView() {\n          if (previousLeaveAnimation) {\n            $animate.cancel(previousLeaveAnimation);\n            previousLeaveAnimation = null;\n          }\n\n          if (currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if (currentElement) {\n            previousLeaveAnimation = $animate.leave(currentElement);\n            previousLeaveAnimation.done(function(response) {\n              if (response !== false) previousLeaveAnimation = null;\n            });\n            currentElement = null;\n          }\n        }\n\n        function update() {\n          var locals = $route.current && $route.current.locals,\n              template = locals && locals.$template;\n\n          if (angular.isDefined(template)) {\n            var newScope = scope.$new();\n            var current = $route.current;\n\n            // Note: This will also link all children of ng-view that were contained in the original\n            // html. If that content contains controllers, ... they could pollute/change the scope.\n            // However, using ng-view on an element with additional content does not make sense...\n            // Note: We can't remove them in the cloneAttchFn of $transclude as that\n            // function is called before linking the content, which would apply child\n            // directives to non existing elements.\n            var clone = $transclude(newScope, function(clone) {\n              $animate.enter(clone, null, currentElement || $element).done(function onNgViewEnter(response) {\n                if (response !== false && angular.isDefined(autoScrollExp)\n                  && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n                  $anchorScroll();\n                }\n              });\n              cleanupLastView();\n            });\n\n            currentElement = clone;\n            currentScope = current.scope = newScope;\n            currentScope.$emit('$viewContentLoaded');\n            currentScope.$eval(onloadExp);\n          } else {\n            cleanupLastView();\n          }\n        }\n    }\n  };\n}\n\n// This directive is called during the $transclude call of the first `ngView` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngView\n// is called.\nngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];\nfunction ngViewFillContentFactory($compile, $controller, $route) {\n  return {\n    restrict: 'ECA',\n    priority: -400,\n    link: function(scope, $element) {\n      var current = $route.current,\n          locals = current.locals;\n\n      $element.html(locals.$template);\n\n      var link = $compile($element.contents());\n\n      if (current.controller) {\n        locals.$scope = scope;\n        var controller = $controller(current.controller, locals);\n        if (current.controllerAs) {\n          scope[current.controllerAs] = controller;\n        }\n        $element.data('$ngControllerController', controller);\n        $element.children().data('$ngControllerController', controller);\n      }\n      scope[current.resolveAs || '$resolve'] = locals;\n\n      link(scope);\n    }\n  };\n}\n\n\n})(window, window.angular);\n","require('./angular-route');\nmodule.exports = 'ngRoute';\n","'use strict';\nangular.module(\"ngLocale\", [], [\"$provide\", function($provide) {\nvar PLURAL_CATEGORY = {ZERO: \"zero\", ONE: \"one\", TWO: \"two\", FEW: \"few\", MANY: \"many\", OTHER: \"other\"};\nfunction getDecimals(n) {\n  n = n + '';\n  var i = n.indexOf('.');\n  return (i == -1) ? 0 : n.length - i - 1;\n}\n\nfunction getVF(n, opt_precision) {\n  var v = opt_precision;\n\n  if (undefined === v) {\n    v = Math.min(getDecimals(n), 3);\n  }\n\n  var base = Math.pow(10, v);\n  var f = ((n * base) | 0) % base;\n  return {v: v, f: f};\n}\n\n$provide.value(\"$locale\", {\n  \"DATETIME_FORMATS\": {\n    \"AMPMS\": [\n      \"ap.\",\n      \"ip.\"\n    ],\n    \"DAY\": [\n      \"sunnuntaina\",\n      \"maanantaina\",\n      \"tiistaina\",\n      \"keskiviikkona\",\n      \"torstaina\",\n      \"perjantaina\",\n      \"lauantaina\"\n    ],\n    \"ERANAMES\": [\n      \"ennen Kristuksen syntym\\u00e4\\u00e4\",\n      \"j\\u00e4lkeen Kristuksen syntym\\u00e4n\"\n    ],\n    \"ERAS\": [\n      \"eKr.\",\n      \"jKr.\"\n    ],\n    \"FIRSTDAYOFWEEK\": 0,\n    \"MONTH\": [\n      \"tammikuuta\",\n      \"helmikuuta\",\n      \"maaliskuuta\",\n      \"huhtikuuta\",\n      \"toukokuuta\",\n      \"kes\\u00e4kuuta\",\n      \"hein\\u00e4kuuta\",\n      \"elokuuta\",\n      \"syyskuuta\",\n      \"lokakuuta\",\n      \"marraskuuta\",\n      \"joulukuuta\"\n    ],\n    \"SHORTDAY\": [\n      \"su\",\n      \"ma\",\n      \"ti\",\n      \"ke\",\n      \"to\",\n      \"pe\",\n      \"la\"\n    ],\n    \"SHORTMONTH\": [\n      \"tammik.\",\n      \"helmik.\",\n      \"maalisk.\",\n      \"huhtik.\",\n      \"toukok.\",\n      \"kes\\u00e4k.\",\n      \"hein\\u00e4k.\",\n      \"elok.\",\n      \"syysk.\",\n      \"lokak.\",\n      \"marrask.\",\n      \"jouluk.\"\n    ],\n    \"STANDALONEMONTH\": [\n      \"tammikuu\",\n      \"helmikuu\",\n      \"maaliskuu\",\n      \"huhtikuu\",\n      \"toukokuu\",\n      \"kes\\u00e4kuu\",\n      \"hein\\u00e4kuu\",\n      \"elokuu\",\n      \"syyskuu\",\n      \"lokakuu\",\n      \"marraskuu\",\n      \"joulukuu\"\n    ],\n    \"WEEKENDRANGE\": [\n      5,\n      6\n    ],\n    \"fullDate\": \"cccc d. MMMM y\",\n    \"longDate\": \"d. MMMM y\",\n    \"medium\": \"d.M.y H.mm.ss\",\n    \"mediumDate\": \"d.M.y\",\n    \"mediumTime\": \"H.mm.ss\",\n    \"short\": \"d.M.y H.mm\",\n    \"shortDate\": \"d.M.y\",\n    \"shortTime\": \"H.mm\"\n  },\n  \"NUMBER_FORMATS\": {\n    \"CURRENCY_SYM\": \"\\u20ac\",\n    \"DECIMAL_SEP\": \",\",\n    \"GROUP_SEP\": \"\\u00a0\",\n    \"PATTERNS\": [\n      {\n        \"gSize\": 3,\n        \"lgSize\": 3,\n        \"maxFrac\": 3,\n        \"minFrac\": 0,\n        \"minInt\": 1,\n        \"negPre\": \"-\",\n        \"negSuf\": \"\",\n        \"posPre\": \"\",\n        \"posSuf\": \"\"\n      },\n      {\n        \"gSize\": 3,\n        \"lgSize\": 3,\n        \"maxFrac\": 2,\n        \"minFrac\": 2,\n        \"minInt\": 1,\n        \"negPre\": \"-\",\n        \"negSuf\": \"\\u00a0\\u00a4\",\n        \"posPre\": \"\",\n        \"posSuf\": \"\\u00a0\\u00a4\"\n      }\n    ]\n  },\n  \"id\": \"fi\",\n  \"localeID\": \"fi\",\n  \"pluralCat\": function(n, opt_precision) {  var i = n | 0;  var vf = getVF(n, opt_precision);  if (i == 1 && vf.v == 0) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;}\n});\n}]);\n","/*\n * angular-ui-bootstrap\n * http://angular-ui.github.io/bootstrap/\n\n * Version: 2.5.6 - 2017-10-14\n * License: MIT\n */angular.module(\"ui.bootstrap\", [\"ui.bootstrap.tpls\", \"ui.bootstrap.collapse\",\"ui.bootstrap.tabindex\",\"ui.bootstrap.accordion\",\"ui.bootstrap.alert\",\"ui.bootstrap.buttons\",\"ui.bootstrap.carousel\",\"ui.bootstrap.dateparser\",\"ui.bootstrap.isClass\",\"ui.bootstrap.datepicker\",\"ui.bootstrap.position\",\"ui.bootstrap.datepickerPopup\",\"ui.bootstrap.debounce\",\"ui.bootstrap.multiMap\",\"ui.bootstrap.dropdown\",\"ui.bootstrap.stackedMap\",\"ui.bootstrap.modal\",\"ui.bootstrap.paging\",\"ui.bootstrap.pager\",\"ui.bootstrap.pagination\",\"ui.bootstrap.tooltip\",\"ui.bootstrap.popover\",\"ui.bootstrap.progressbar\",\"ui.bootstrap.rating\",\"ui.bootstrap.tabs\",\"ui.bootstrap.timepicker\",\"ui.bootstrap.typeahead\"]);\nangular.module(\"ui.bootstrap.tpls\", [\"uib/template/accordion/accordion-group.html\",\"uib/template/accordion/accordion.html\",\"uib/template/alert/alert.html\",\"uib/template/carousel/carousel.html\",\"uib/template/carousel/slide.html\",\"uib/template/datepicker/datepicker.html\",\"uib/template/datepicker/day.html\",\"uib/template/datepicker/month.html\",\"uib/template/datepicker/year.html\",\"uib/template/datepickerPopup/popup.html\",\"uib/template/modal/window.html\",\"uib/template/pager/pager.html\",\"uib/template/pagination/pagination.html\",\"uib/template/tooltip/tooltip-html-popup.html\",\"uib/template/tooltip/tooltip-popup.html\",\"uib/template/tooltip/tooltip-template-popup.html\",\"uib/template/popover/popover-html.html\",\"uib/template/popover/popover-template.html\",\"uib/template/popover/popover.html\",\"uib/template/progressbar/bar.html\",\"uib/template/progressbar/progress.html\",\"uib/template/progressbar/progressbar.html\",\"uib/template/rating/rating.html\",\"uib/template/tabs/tab.html\",\"uib/template/tabs/tabset.html\",\"uib/template/timepicker/timepicker.html\",\"uib/template/typeahead/typeahead-match.html\",\"uib/template/typeahead/typeahead-popup.html\"]);\nangular.module('ui.bootstrap.collapse', [])\n\n  .directive('uibCollapse', ['$animate', '$q', '$parse', '$injector', function($animate, $q, $parse, $injector) {\n    var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;\n    return {\n      link: function(scope, element, attrs) {\n        var expandingExpr = $parse(attrs.expanding),\n          expandedExpr = $parse(attrs.expanded),\n          collapsingExpr = $parse(attrs.collapsing),\n          collapsedExpr = $parse(attrs.collapsed),\n          horizontal = false,\n          css = {},\n          cssTo = {};\n\n        init();\n\n        function init() {\n          horizontal = !!('horizontal' in attrs);\n          if (horizontal) {\n            css = {\n              width: ''\n            };\n            cssTo = {width: '0'};\n          } else {\n            css = {\n              height: ''\n            };\n            cssTo = {height: '0'};\n          }\n          if (!scope.$eval(attrs.uibCollapse)) {\n            element.addClass('in')\n              .addClass('collapse')\n              .attr('aria-expanded', true)\n              .attr('aria-hidden', false)\n              .css(css);\n          }\n        }\n\n        function getScrollFromElement(element) {\n          if (horizontal) {\n            return {width: element.scrollWidth + 'px'};\n          }\n          return {height: element.scrollHeight + 'px'};\n        }\n\n        function expand() {\n          if (element.hasClass('collapse') && element.hasClass('in')) {\n            return;\n          }\n\n          $q.resolve(expandingExpr(scope))\n            .then(function() {\n              element.removeClass('collapse')\n                .addClass('collapsing')\n                .attr('aria-expanded', true)\n                .attr('aria-hidden', false);\n\n              if ($animateCss) {\n                $animateCss(element, {\n                  addClass: 'in',\n                  easing: 'ease',\n                  css: {\n                    overflow: 'hidden'\n                  },\n                  to: getScrollFromElement(element[0])\n                }).start()['finally'](expandDone);\n              } else {\n                $animate.addClass(element, 'in', {\n                  css: {\n                    overflow: 'hidden'\n                  },\n                  to: getScrollFromElement(element[0])\n                }).then(expandDone);\n              }\n            }, angular.noop);\n        }\n\n        function expandDone() {\n          element.removeClass('collapsing')\n            .addClass('collapse')\n            .css(css);\n          expandedExpr(scope);\n        }\n\n        function collapse() {\n          if (!element.hasClass('collapse') && !element.hasClass('in')) {\n            return collapseDone();\n          }\n\n          $q.resolve(collapsingExpr(scope))\n            .then(function() {\n              element\n              // IMPORTANT: The width must be set before adding \"collapsing\" class.\n              // Otherwise, the browser attempts to animate from width 0 (in\n              // collapsing class) to the given width here.\n                .css(getScrollFromElement(element[0]))\n                // initially all panel collapse have the collapse class, this removal\n                // prevents the animation from jumping to collapsed state\n                .removeClass('collapse')\n                .addClass('collapsing')\n                .attr('aria-expanded', false)\n                .attr('aria-hidden', true);\n\n              if ($animateCss) {\n                $animateCss(element, {\n                  removeClass: 'in',\n                  to: cssTo\n                }).start()['finally'](collapseDone);\n              } else {\n                $animate.removeClass(element, 'in', {\n                  to: cssTo\n                }).then(collapseDone);\n              }\n            }, angular.noop);\n        }\n\n        function collapseDone() {\n          element.css(cssTo); // Required so that collapse works when animation is disabled\n          element.removeClass('collapsing')\n            .addClass('collapse');\n          collapsedExpr(scope);\n        }\n\n        scope.$watch(attrs.uibCollapse, function(shouldCollapse) {\n          if (shouldCollapse) {\n            collapse();\n          } else {\n            expand();\n          }\n        });\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.tabindex', [])\n\n.directive('uibTabindexToggle', function() {\n  return {\n    restrict: 'A',\n    link: function(scope, elem, attrs) {\n      attrs.$observe('disabled', function(disabled) {\n        attrs.$set('tabindex', disabled ? -1 : null);\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])\n\n.constant('uibAccordionConfig', {\n  closeOthers: true\n})\n\n.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {\n  // This array keeps track of the accordion groups\n  this.groups = [];\n\n  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to\n  this.closeOthers = function(openGroup) {\n    var closeOthers = angular.isDefined($attrs.closeOthers) ?\n      $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;\n    if (closeOthers) {\n      angular.forEach(this.groups, function(group) {\n        if (group !== openGroup) {\n          group.isOpen = false;\n        }\n      });\n    }\n  };\n\n  // This is called from the accordion-group directive to add itself to the accordion\n  this.addGroup = function(groupScope) {\n    var that = this;\n    this.groups.push(groupScope);\n\n    groupScope.$on('$destroy', function(event) {\n      that.removeGroup(groupScope);\n    });\n  };\n\n  // This is called from the accordion-group directive when to remove itself\n  this.removeGroup = function(group) {\n    var index = this.groups.indexOf(group);\n    if (index !== -1) {\n      this.groups.splice(index, 1);\n    }\n  };\n}])\n\n// The accordion directive simply sets up the directive controller\n// and adds an accordion CSS class to itself element.\n.directive('uibAccordion', function() {\n  return {\n    controller: 'UibAccordionController',\n    controllerAs: 'accordion',\n    transclude: true,\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/accordion/accordion.html';\n    }\n  };\n})\n\n// The accordion-group directive indicates a block of html that will expand and collapse in an accordion\n.directive('uibAccordionGroup', function() {\n  return {\n    require: '^uibAccordion',         // We need this directive to be inside an accordion\n    transclude: true,              // It transcludes the contents of the directive into the template\n    restrict: 'A',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';\n    },\n    scope: {\n      heading: '@',               // Interpolate the heading attribute onto this scope\n      panelClass: '@?',           // Ditto with panelClass\n      isOpen: '=?',\n      isDisabled: '=?'\n    },\n    controller: function() {\n      this.setHeading = function(element) {\n        this.heading = element;\n      };\n    },\n    link: function(scope, element, attrs, accordionCtrl) {\n      element.addClass('panel');\n      accordionCtrl.addGroup(scope);\n\n      scope.openClass = attrs.openClass || 'panel-open';\n      scope.panelClass = attrs.panelClass || 'panel-default';\n      scope.$watch('isOpen', function(value) {\n        element.toggleClass(scope.openClass, !!value);\n        if (value) {\n          accordionCtrl.closeOthers(scope);\n        }\n      });\n\n      scope.toggleOpen = function($event) {\n        if (!scope.isDisabled) {\n          if (!$event || $event.which === 32) {\n            scope.isOpen = !scope.isOpen;\n          }\n        }\n      };\n\n      var id = 'accordiongroup-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n      scope.headingId = id + '-tab';\n      scope.panelId = id + '-panel';\n    }\n  };\n})\n\n// Use accordion-heading below an accordion-group to provide a heading containing HTML\n.directive('uibAccordionHeading', function() {\n  return {\n    transclude: true,   // Grab the contents to be used as the heading\n    template: '',       // In effect remove this element!\n    replace: true,\n    require: '^uibAccordionGroup',\n    link: function(scope, element, attrs, accordionGroupCtrl, transclude) {\n      // Pass the heading to the accordion-group controller\n      // so that it can be transcluded into the right place in the template\n      // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n      accordionGroupCtrl.setHeading(transclude(scope, angular.noop));\n    }\n  };\n})\n\n// Use in the accordion-group template to indicate where you want the heading to be transcluded\n// You must provide the property on the accordion-group controller that will hold the transcluded element\n.directive('uibAccordionTransclude', function() {\n  return {\n    require: '^uibAccordionGroup',\n    link: function(scope, element, attrs, controller) {\n      scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {\n        if (heading) {\n          var elem = angular.element(element[0].querySelector(getHeaderSelectors()));\n          elem.html('');\n          elem.append(heading);\n        }\n      });\n    }\n  };\n\n  function getHeaderSelectors() {\n      return 'uib-accordion-header,' +\n          'data-uib-accordion-header,' +\n          'x-uib-accordion-header,' +\n          'uib\\\\:accordion-header,' +\n          '[uib-accordion-header],' +\n          '[data-uib-accordion-header],' +\n          '[x-uib-accordion-header]';\n  }\n});\n\nangular.module('ui.bootstrap.alert', [])\n\n.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) {\n  $scope.closeable = !!$attrs.close;\n  $element.addClass('alert');\n  $attrs.$set('role', 'alert');\n  if ($scope.closeable) {\n    $element.addClass('alert-dismissible');\n  }\n\n  var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?\n    $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;\n\n  if (dismissOnTimeout) {\n    $timeout(function() {\n      $scope.close();\n    }, parseInt(dismissOnTimeout, 10));\n  }\n}])\n\n.directive('uibAlert', function() {\n  return {\n    controller: 'UibAlertController',\n    controllerAs: 'alert',\n    restrict: 'A',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/alert/alert.html';\n    },\n    transclude: true,\n    scope: {\n      close: '&'\n    }\n  };\n});\n\nangular.module('ui.bootstrap.buttons', [])\n\n.constant('uibButtonConfig', {\n  activeClass: 'active',\n  toggleEvent: 'click'\n})\n\n.controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {\n  this.activeClass = buttonConfig.activeClass || 'active';\n  this.toggleEvent = buttonConfig.toggleEvent || 'click';\n}])\n\n.directive('uibBtnRadio', ['$parse', function($parse) {\n  return {\n    require: ['uibBtnRadio', 'ngModel'],\n    controller: 'UibButtonsController',\n    controllerAs: 'buttons',\n    link: function(scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n      var uncheckableExpr = $parse(attrs.uibUncheckable);\n\n      element.find('input').css({display: 'none'});\n\n      //model -> UI\n      ngModelCtrl.$render = function() {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));\n      };\n\n      //ui->model\n      element.on(buttonsCtrl.toggleEvent, function() {\n        if (attrs.disabled) {\n          return;\n        }\n\n        var isActive = element.hasClass(buttonsCtrl.activeClass);\n\n        if (!isActive || angular.isDefined(attrs.uncheckable)) {\n          scope.$apply(function() {\n            ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));\n            ngModelCtrl.$render();\n          });\n        }\n      });\n\n      if (attrs.uibUncheckable) {\n        scope.$watch(uncheckableExpr, function(uncheckable) {\n          attrs.$set('uncheckable', uncheckable ? '' : undefined);\n        });\n      }\n    }\n  };\n}])\n\n.directive('uibBtnCheckbox', function() {\n  return {\n    require: ['uibBtnCheckbox', 'ngModel'],\n    controller: 'UibButtonsController',\n    controllerAs: 'button',\n    link: function(scope, element, attrs, ctrls) {\n      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      element.find('input').css({display: 'none'});\n\n      function getTrueValue() {\n        return getCheckboxValue(attrs.btnCheckboxTrue, true);\n      }\n\n      function getFalseValue() {\n        return getCheckboxValue(attrs.btnCheckboxFalse, false);\n      }\n\n      function getCheckboxValue(attribute, defaultValue) {\n        return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;\n      }\n\n      //model -> UI\n      ngModelCtrl.$render = function() {\n        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));\n      };\n\n      //ui->model\n      element.on(buttonsCtrl.toggleEvent, function() {\n        if (attrs.disabled) {\n          return;\n        }\n\n        scope.$apply(function() {\n          ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n          ngModelCtrl.$render();\n        });\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.carousel', [])\n\n.controller('UibCarouselController', ['$scope', '$element', '$interval', '$timeout', '$animate', function($scope, $element, $interval, $timeout, $animate) {\n  var self = this,\n    slides = self.slides = $scope.slides = [],\n    SLIDE_DIRECTION = 'uib-slideDirection',\n    currentIndex = $scope.active,\n    currentInterval, isPlaying;\n\n  var destroyed = false;\n  $element.addClass('carousel');\n\n  self.addSlide = function(slide, element) {\n    slides.push({\n      slide: slide,\n      element: element\n    });\n    slides.sort(function(a, b) {\n      return +a.slide.index - +b.slide.index;\n    });\n    //if this is the first slide or the slide is set to active, select it\n    if (slide.index === $scope.active || slides.length === 1 && !angular.isNumber($scope.active)) {\n      if ($scope.$currentTransition) {\n        $scope.$currentTransition = null;\n      }\n\n      currentIndex = slide.index;\n      $scope.active = slide.index;\n      setActive(currentIndex);\n      self.select(slides[findSlideIndex(slide)]);\n      if (slides.length === 1) {\n        $scope.play();\n      }\n    }\n  };\n\n  self.getCurrentIndex = function() {\n    for (var i = 0; i < slides.length; i++) {\n      if (slides[i].slide.index === currentIndex) {\n        return i;\n      }\n    }\n  };\n\n  self.next = $scope.next = function() {\n    var newIndex = (self.getCurrentIndex() + 1) % slides.length;\n\n    if (newIndex === 0 && $scope.noWrap()) {\n      $scope.pause();\n      return;\n    }\n\n    return self.select(slides[newIndex], 'next');\n  };\n\n  self.prev = $scope.prev = function() {\n    var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;\n\n    if ($scope.noWrap() && newIndex === slides.length - 1) {\n      $scope.pause();\n      return;\n    }\n\n    return self.select(slides[newIndex], 'prev');\n  };\n\n  self.removeSlide = function(slide) {\n    var index = findSlideIndex(slide);\n\n    //get the index of the slide inside the carousel\n    slides.splice(index, 1);\n    if (slides.length > 0 && currentIndex === index) {\n      if (index >= slides.length) {\n        currentIndex = slides.length - 1;\n        $scope.active = currentIndex;\n        setActive(currentIndex);\n        self.select(slides[slides.length - 1]);\n      } else {\n        currentIndex = index;\n        $scope.active = currentIndex;\n        setActive(currentIndex);\n        self.select(slides[index]);\n      }\n    } else if (currentIndex > index) {\n      currentIndex--;\n      $scope.active = currentIndex;\n    }\n\n    //clean the active value when no more slide\n    if (slides.length === 0) {\n      currentIndex = null;\n      $scope.active = null;\n    }\n  };\n\n  /* direction: \"prev\" or \"next\" */\n  self.select = $scope.select = function(nextSlide, direction) {\n    var nextIndex = findSlideIndex(nextSlide.slide);\n    //Decide direction if it's not given\n    if (direction === undefined) {\n      direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';\n    }\n    //Prevent this user-triggered transition from occurring if there is already one in progress\n    if (nextSlide.slide.index !== currentIndex &&\n      !$scope.$currentTransition) {\n      goNext(nextSlide.slide, nextIndex, direction);\n    }\n  };\n\n  /* Allow outside people to call indexOf on slides array */\n  $scope.indexOfSlide = function(slide) {\n    return +slide.slide.index;\n  };\n\n  $scope.isActive = function(slide) {\n    return $scope.active === slide.slide.index;\n  };\n\n  $scope.isPrevDisabled = function() {\n    return $scope.active === 0 && $scope.noWrap();\n  };\n\n  $scope.isNextDisabled = function() {\n    return $scope.active === slides.length - 1 && $scope.noWrap();\n  };\n\n  $scope.pause = function() {\n    if (!$scope.noPause) {\n      isPlaying = false;\n      resetTimer();\n    }\n  };\n\n  $scope.play = function() {\n    if (!isPlaying) {\n      isPlaying = true;\n      restartTimer();\n    }\n  };\n\n  $element.on('mouseenter', $scope.pause);\n  $element.on('mouseleave', $scope.play);\n\n  $scope.$on('$destroy', function() {\n    destroyed = true;\n    resetTimer();\n  });\n\n  $scope.$watch('noTransition', function(noTransition) {\n    $animate.enabled($element, !noTransition);\n  });\n\n  $scope.$watch('interval', restartTimer);\n\n  $scope.$watchCollection('slides', resetTransition);\n\n  $scope.$watch('active', function(index) {\n    if (angular.isNumber(index) && currentIndex !== index) {\n      for (var i = 0; i < slides.length; i++) {\n        if (slides[i].slide.index === index) {\n          index = i;\n          break;\n        }\n      }\n\n      var slide = slides[index];\n      if (slide) {\n        setActive(index);\n        self.select(slides[index]);\n        currentIndex = index;\n      }\n    }\n  });\n\n  function getSlideByIndex(index) {\n    for (var i = 0, l = slides.length; i < l; ++i) {\n      if (slides[i].index === index) {\n        return slides[i];\n      }\n    }\n  }\n\n  function setActive(index) {\n    for (var i = 0; i < slides.length; i++) {\n      slides[i].slide.active = i === index;\n    }\n  }\n\n  function goNext(slide, index, direction) {\n    if (destroyed) {\n      return;\n    }\n\n    angular.extend(slide, {direction: direction});\n    angular.extend(slides[currentIndex].slide || {}, {direction: direction});\n    if ($animate.enabled($element) && !$scope.$currentTransition &&\n      slides[index].element && self.slides.length > 1) {\n      slides[index].element.data(SLIDE_DIRECTION, slide.direction);\n      var currentIdx = self.getCurrentIndex();\n\n      if (angular.isNumber(currentIdx) && slides[currentIdx].element) {\n        slides[currentIdx].element.data(SLIDE_DIRECTION, slide.direction);\n      }\n\n      $scope.$currentTransition = true;\n      $animate.on('addClass', slides[index].element, function(element, phase) {\n        if (phase === 'close') {\n          $scope.$currentTransition = null;\n          $animate.off('addClass', element);\n        }\n      });\n    }\n\n    $scope.active = slide.index;\n    currentIndex = slide.index;\n    setActive(index);\n\n    //every time you change slides, reset the timer\n    restartTimer();\n  }\n\n  function findSlideIndex(slide) {\n    for (var i = 0; i < slides.length; i++) {\n      if (slides[i].slide === slide) {\n        return i;\n      }\n    }\n  }\n\n  function resetTimer() {\n    if (currentInterval) {\n      $interval.cancel(currentInterval);\n      currentInterval = null;\n    }\n  }\n\n  function resetTransition(slides) {\n    if (!slides.length) {\n      $scope.$currentTransition = null;\n    }\n  }\n\n  function restartTimer() {\n    resetTimer();\n    var interval = +$scope.interval;\n    if (!isNaN(interval) && interval > 0) {\n      currentInterval = $interval(timerFn, interval);\n    }\n  }\n\n  function timerFn() {\n    var interval = +$scope.interval;\n    if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {\n      $scope.next();\n    } else {\n      $scope.pause();\n    }\n  }\n}])\n\n.directive('uibCarousel', function() {\n  return {\n    transclude: true,\n    controller: 'UibCarouselController',\n    controllerAs: 'carousel',\n    restrict: 'A',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/carousel/carousel.html';\n    },\n    scope: {\n      active: '=',\n      interval: '=',\n      noTransition: '=',\n      noPause: '=',\n      noWrap: '&'\n    }\n  };\n})\n\n.directive('uibSlide', ['$animate', function($animate) {\n  return {\n    require: '^uibCarousel',\n    restrict: 'A',\n    transclude: true,\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/carousel/slide.html';\n    },\n    scope: {\n      actual: '=?',\n      index: '=?'\n    },\n    link: function (scope, element, attrs, carouselCtrl) {\n      element.addClass('item');\n      carouselCtrl.addSlide(scope, element);\n      //when the scope is destroyed then remove the slide from the current slides array\n      scope.$on('$destroy', function() {\n        carouselCtrl.removeSlide(scope);\n      });\n\n      scope.$watch('active', function(active) {\n        $animate[active ? 'addClass' : 'removeClass'](element, 'active');\n      });\n    }\n  };\n}])\n\n.animation('.item', ['$animateCss',\nfunction($animateCss) {\n  var SLIDE_DIRECTION = 'uib-slideDirection';\n\n  function removeClass(element, className, callback) {\n    element.removeClass(className);\n    if (callback) {\n      callback();\n    }\n  }\n\n  return {\n    beforeAddClass: function(element, className, done) {\n      if (className === 'active') {\n        var stopped = false;\n        var direction = element.data(SLIDE_DIRECTION);\n        var directionClass = direction === 'next' ? 'left' : 'right';\n        var removeClassFn = removeClass.bind(this, element,\n          directionClass + ' ' + direction, done);\n        element.addClass(direction);\n\n        $animateCss(element, {addClass: directionClass})\n          .start()\n          .done(removeClassFn);\n\n        return function() {\n          stopped = true;\n        };\n      }\n      done();\n    },\n    beforeRemoveClass: function (element, className, done) {\n      if (className === 'active') {\n        var stopped = false;\n        var direction = element.data(SLIDE_DIRECTION);\n        var directionClass = direction === 'next' ? 'left' : 'right';\n        var removeClassFn = removeClass.bind(this, element, directionClass, done);\n\n        $animateCss(element, {addClass: directionClass})\n          .start()\n          .done(removeClassFn);\n\n        return function() {\n          stopped = true;\n        };\n      }\n      done();\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.dateparser', [])\n\n.service('uibDateParser', ['$log', '$locale', 'dateFilter', 'orderByFilter', 'filterFilter', function($log, $locale, dateFilter, orderByFilter, filterFilter) {\n  // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js\n  var SPECIAL_CHARACTERS_REGEXP = /[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g;\n\n  var localeId;\n  var formatCodeToRegex;\n\n  this.init = function() {\n    localeId = $locale.id;\n\n    this.parsers = {};\n    this.formatters = {};\n\n    formatCodeToRegex = [\n      {\n        key: 'yyyy',\n        regex: '\\\\d{4}',\n        apply: function(value) { this.year = +value; },\n        formatter: function(date) {\n          var _date = new Date();\n          _date.setFullYear(Math.abs(date.getFullYear()));\n          return dateFilter(_date, 'yyyy');\n        }\n      },\n      {\n        key: 'yy',\n        regex: '\\\\d{2}',\n        apply: function(value) { value = +value; this.year = value < 69 ? value + 2000 : value + 1900; },\n        formatter: function(date) {\n          var _date = new Date();\n          _date.setFullYear(Math.abs(date.getFullYear()));\n          return dateFilter(_date, 'yy');\n        }\n      },\n      {\n        key: 'y',\n        regex: '\\\\d{1,4}',\n        apply: function(value) { this.year = +value; },\n        formatter: function(date) {\n          var _date = new Date();\n          _date.setFullYear(Math.abs(date.getFullYear()));\n          return dateFilter(_date, 'y');\n        }\n      },\n      {\n        key: 'M!',\n        regex: '0?[1-9]|1[0-2]',\n        apply: function(value) { this.month = value - 1; },\n        formatter: function(date) {\n          var value = date.getMonth();\n          if (/^[0-9]$/.test(value)) {\n            return dateFilter(date, 'MM');\n          }\n\n          return dateFilter(date, 'M');\n        }\n      },\n      {\n        key: 'MMMM',\n        regex: $locale.DATETIME_FORMATS.MONTH.join('|'),\n        apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); },\n        formatter: function(date) { return dateFilter(date, 'MMMM'); }\n      },\n      {\n        key: 'MMM',\n        regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); },\n        formatter: function(date) { return dateFilter(date, 'MMM'); }\n      },\n      {\n        key: 'MM',\n        regex: '0[1-9]|1[0-2]',\n        apply: function(value) { this.month = value - 1; },\n        formatter: function(date) { return dateFilter(date, 'MM'); }\n      },\n      {\n        key: 'M',\n        regex: '[1-9]|1[0-2]',\n        apply: function(value) { this.month = value - 1; },\n        formatter: function(date) { return dateFilter(date, 'M'); }\n      },\n      {\n        key: 'd!',\n        regex: '[0-2]?[0-9]{1}|3[0-1]{1}',\n        apply: function(value) { this.date = +value; },\n        formatter: function(date) {\n          var value = date.getDate();\n          if (/^[1-9]$/.test(value)) {\n            return dateFilter(date, 'dd');\n          }\n\n          return dateFilter(date, 'd');\n        }\n      },\n      {\n        key: 'dd',\n        regex: '[0-2][0-9]{1}|3[0-1]{1}',\n        apply: function(value) { this.date = +value; },\n        formatter: function(date) { return dateFilter(date, 'dd'); }\n      },\n      {\n        key: 'd',\n        regex: '[1-2]?[0-9]{1}|3[0-1]{1}',\n        apply: function(value) { this.date = +value; },\n        formatter: function(date) { return dateFilter(date, 'd'); }\n      },\n      {\n        key: 'EEEE',\n        regex: $locale.DATETIME_FORMATS.DAY.join('|'),\n        formatter: function(date) { return dateFilter(date, 'EEEE'); }\n      },\n      {\n        key: 'EEE',\n        regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        formatter: function(date) { return dateFilter(date, 'EEE'); }\n      },\n      {\n        key: 'HH',\n        regex: '(?:0|1)[0-9]|2[0-3]',\n        apply: function(value) { this.hours = +value; },\n        formatter: function(date) { return dateFilter(date, 'HH'); }\n      },\n      {\n        key: 'hh',\n        regex: '0[0-9]|1[0-2]',\n        apply: function(value) { this.hours = +value; },\n        formatter: function(date) { return dateFilter(date, 'hh'); }\n      },\n      {\n        key: 'H',\n        regex: '1?[0-9]|2[0-3]',\n        apply: function(value) { this.hours = +value; },\n        formatter: function(date) { return dateFilter(date, 'H'); }\n      },\n      {\n        key: 'h',\n        regex: '[0-9]|1[0-2]',\n        apply: function(value) { this.hours = +value; },\n        formatter: function(date) { return dateFilter(date, 'h'); }\n      },\n      {\n        key: 'mm',\n        regex: '[0-5][0-9]',\n        apply: function(value) { this.minutes = +value; },\n        formatter: function(date) { return dateFilter(date, 'mm'); }\n      },\n      {\n        key: 'm',\n        regex: '[0-9]|[1-5][0-9]',\n        apply: function(value) { this.minutes = +value; },\n        formatter: function(date) { return dateFilter(date, 'm'); }\n      },\n      {\n        key: 'sss',\n        regex: '[0-9][0-9][0-9]',\n        apply: function(value) { this.milliseconds = +value; },\n        formatter: function(date) { return dateFilter(date, 'sss'); }\n      },\n      {\n        key: 'ss',\n        regex: '[0-5][0-9]',\n        apply: function(value) { this.seconds = +value; },\n        formatter: function(date) { return dateFilter(date, 'ss'); }\n      },\n      {\n        key: 's',\n        regex: '[0-9]|[1-5][0-9]',\n        apply: function(value) { this.seconds = +value; },\n        formatter: function(date) { return dateFilter(date, 's'); }\n      },\n      {\n        key: 'a',\n        regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),\n        apply: function(value) {\n          if (this.hours === 12) {\n            this.hours = 0;\n          }\n\n          if (value === 'PM') {\n            this.hours += 12;\n          }\n        },\n        formatter: function(date) { return dateFilter(date, 'a'); }\n      },\n      {\n        key: 'Z',\n        regex: '[+-]\\\\d{4}',\n        apply: function(value) {\n          var matches = value.match(/([+-])(\\d{2})(\\d{2})/),\n            sign = matches[1],\n            hours = matches[2],\n            minutes = matches[3];\n          this.hours += toInt(sign + hours);\n          this.minutes += toInt(sign + minutes);\n        },\n        formatter: function(date) {\n          return dateFilter(date, 'Z');\n        }\n      },\n      {\n        key: 'ww',\n        regex: '[0-4][0-9]|5[0-3]',\n        formatter: function(date) { return dateFilter(date, 'ww'); }\n      },\n      {\n        key: 'w',\n        regex: '[0-9]|[1-4][0-9]|5[0-3]',\n        formatter: function(date) { return dateFilter(date, 'w'); }\n      },\n      {\n        key: 'GGGG',\n        regex: $locale.DATETIME_FORMATS.ERANAMES.join('|').replace(/\\s/g, '\\\\s'),\n        formatter: function(date) { return dateFilter(date, 'GGGG'); }\n      },\n      {\n        key: 'GGG',\n        regex: $locale.DATETIME_FORMATS.ERAS.join('|'),\n        formatter: function(date) { return dateFilter(date, 'GGG'); }\n      },\n      {\n        key: 'GG',\n        regex: $locale.DATETIME_FORMATS.ERAS.join('|'),\n        formatter: function(date) { return dateFilter(date, 'GG'); }\n      },\n      {\n        key: 'G',\n        regex: $locale.DATETIME_FORMATS.ERAS.join('|'),\n        formatter: function(date) { return dateFilter(date, 'G'); }\n      }\n    ];\n\n    if (angular.version.major >= 1 && angular.version.minor > 4) {\n      formatCodeToRegex.push({\n        key: 'LLLL',\n        regex: $locale.DATETIME_FORMATS.STANDALONEMONTH.join('|'),\n        apply: function(value) { this.month = $locale.DATETIME_FORMATS.STANDALONEMONTH.indexOf(value); },\n        formatter: function(date) { return dateFilter(date, 'LLLL'); }\n      });\n    }\n  };\n\n  this.init();\n\n  function getFormatCodeToRegex(key) {\n    return filterFilter(formatCodeToRegex, {key: key}, true)[0];\n  }\n\n  this.getParser = function (key) {\n    var f = getFormatCodeToRegex(key);\n    return f && f.apply || null;\n  };\n\n  this.overrideParser = function (key, parser) {\n    var f = getFormatCodeToRegex(key);\n    if (f && angular.isFunction(parser)) {\n      this.parsers = {};\n      f.apply = parser;\n    }\n  }.bind(this);\n\n  function createParser(format) {\n    var map = [], regex = format.split('');\n\n    // check for literal values\n    var quoteIndex = format.indexOf('\\'');\n    if (quoteIndex > -1) {\n      var inLiteral = false;\n      format = format.split('');\n      for (var i = quoteIndex; i < format.length; i++) {\n        if (inLiteral) {\n          if (format[i] === '\\'') {\n            if (i + 1 < format.length && format[i+1] === '\\'') { // escaped single quote\n              format[i+1] = '$';\n              regex[i+1] = '';\n            } else { // end of literal\n              regex[i] = '';\n              inLiteral = false;\n            }\n          }\n          format[i] = '$';\n        } else {\n          if (format[i] === '\\'') { // start of literal\n            format[i] = '$';\n            regex[i] = '';\n            inLiteral = true;\n          }\n        }\n      }\n\n      format = format.join('');\n    }\n\n    angular.forEach(formatCodeToRegex, function(data) {\n      var index = format.indexOf(data.key);\n\n      if (index > -1) {\n        format = format.split('');\n\n        regex[index] = '(' + data.regex + ')';\n        format[index] = '$'; // Custom symbol to define consumed part of format\n        for (var i = index + 1, n = index + data.key.length; i < n; i++) {\n          regex[i] = '';\n          format[i] = '$';\n        }\n        format = format.join('');\n\n        map.push({\n          index: index,\n          key: data.key,\n          apply: data.apply,\n          matcher: data.regex\n        });\n      }\n    });\n\n    return {\n      regex: new RegExp('^' + regex.join('') + '$'),\n      map: orderByFilter(map, 'index')\n    };\n  }\n\n  function createFormatter(format) {\n    var formatters = [];\n    var i = 0;\n    var formatter, literalIdx;\n    while (i < format.length) {\n      if (angular.isNumber(literalIdx)) {\n        if (format.charAt(i) === '\\'') {\n          if (i + 1 >= format.length || format.charAt(i + 1) !== '\\'') {\n            formatters.push(constructLiteralFormatter(format, literalIdx, i));\n            literalIdx = null;\n          }\n        } else if (i === format.length) {\n          while (literalIdx < format.length) {\n            formatter = constructFormatterFromIdx(format, literalIdx);\n            formatters.push(formatter);\n            literalIdx = formatter.endIdx;\n          }\n        }\n\n        i++;\n        continue;\n      }\n\n      if (format.charAt(i) === '\\'') {\n        literalIdx = i;\n        i++;\n        continue;\n      }\n\n      formatter = constructFormatterFromIdx(format, i);\n\n      formatters.push(formatter.parser);\n      i = formatter.endIdx;\n    }\n\n    return formatters;\n  }\n\n  function constructLiteralFormatter(format, literalIdx, endIdx) {\n    return function() {\n      return format.substr(literalIdx + 1, endIdx - literalIdx - 1);\n    };\n  }\n\n  function constructFormatterFromIdx(format, i) {\n    var currentPosStr = format.substr(i);\n    for (var j = 0; j < formatCodeToRegex.length; j++) {\n      if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {\n        var data = formatCodeToRegex[j];\n        return {\n          endIdx: i + data.key.length,\n          parser: data.formatter\n        };\n      }\n    }\n\n    return {\n      endIdx: i + 1,\n      parser: function() {\n        return currentPosStr.charAt(0);\n      }\n    };\n  }\n\n  this.filter = function(date, format) {\n    if (!angular.isDate(date) || isNaN(date) || !format) {\n      return '';\n    }\n\n    format = $locale.DATETIME_FORMATS[format] || format;\n\n    if ($locale.id !== localeId) {\n      this.init();\n    }\n\n    if (!this.formatters[format]) {\n      this.formatters[format] = createFormatter(format);\n    }\n\n    var formatters = this.formatters[format];\n\n    return formatters.reduce(function(str, formatter) {\n      return str + formatter(date);\n    }, '');\n  };\n\n  this.parse = function(input, format, baseDate) {\n    if (!angular.isString(input) || !format) {\n      return input;\n    }\n\n    format = $locale.DATETIME_FORMATS[format] || format;\n    format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\\\$&');\n\n    if ($locale.id !== localeId) {\n      this.init();\n    }\n\n    if (!this.parsers[format]) {\n      this.parsers[format] = createParser(format, 'apply');\n    }\n\n    var parser = this.parsers[format],\n        regex = parser.regex,\n        map = parser.map,\n        results = input.match(regex),\n        tzOffset = false;\n    if (results && results.length) {\n      var fields, dt;\n      if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {\n        fields = {\n          year: baseDate.getFullYear(),\n          month: baseDate.getMonth(),\n          date: baseDate.getDate(),\n          hours: baseDate.getHours(),\n          minutes: baseDate.getMinutes(),\n          seconds: baseDate.getSeconds(),\n          milliseconds: baseDate.getMilliseconds()\n        };\n      } else {\n        if (baseDate) {\n          $log.warn('dateparser:', 'baseDate is not a valid date');\n        }\n        fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };\n      }\n\n      for (var i = 1, n = results.length; i < n; i++) {\n        var mapper = map[i - 1];\n        if (mapper.matcher === 'Z') {\n          tzOffset = true;\n        }\n\n        if (mapper.apply) {\n          mapper.apply.call(fields, results[i]);\n        }\n      }\n\n      var datesetter = tzOffset ? Date.prototype.setUTCFullYear :\n        Date.prototype.setFullYear;\n      var timesetter = tzOffset ? Date.prototype.setUTCHours :\n        Date.prototype.setHours;\n\n      if (isValid(fields.year, fields.month, fields.date)) {\n        if (angular.isDate(baseDate) && !isNaN(baseDate.getTime()) && !tzOffset) {\n          dt = new Date(baseDate);\n          datesetter.call(dt, fields.year, fields.month, fields.date);\n          timesetter.call(dt, fields.hours, fields.minutes,\n            fields.seconds, fields.milliseconds);\n        } else {\n          dt = new Date(0);\n          datesetter.call(dt, fields.year, fields.month, fields.date);\n          timesetter.call(dt, fields.hours || 0, fields.minutes || 0,\n            fields.seconds || 0, fields.milliseconds || 0);\n        }\n      }\n\n      return dt;\n    }\n  };\n\n  // Check if date is valid for specific month (and year for February).\n  // Month: 0 = Jan, 1 = Feb, etc\n  function isValid(year, month, date) {\n    if (date < 1) {\n      return false;\n    }\n\n    if (month === 1 && date > 28) {\n      return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0);\n    }\n\n    if (month === 3 || month === 5 || month === 8 || month === 10) {\n      return date < 31;\n    }\n\n    return true;\n  }\n\n  function toInt(str) {\n    return parseInt(str, 10);\n  }\n\n  this.toTimezone = toTimezone;\n  this.fromTimezone = fromTimezone;\n  this.timezoneToOffset = timezoneToOffset;\n  this.addDateMinutes = addDateMinutes;\n  this.convertTimezoneToLocal = convertTimezoneToLocal;\n\n  function toTimezone(date, timezone) {\n    return date && timezone ? convertTimezoneToLocal(date, timezone) : date;\n  }\n\n  function fromTimezone(date, timezone) {\n    return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;\n  }\n\n  //https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207\n  function timezoneToOffset(timezone, fallback) {\n    timezone = timezone.replace(/:/g, '');\n    var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;\n    return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;\n  }\n\n  function addDateMinutes(date, minutes) {\n    date = new Date(date.getTime());\n    date.setMinutes(date.getMinutes() + minutes);\n    return date;\n  }\n\n  function convertTimezoneToLocal(date, timezone, reverse) {\n    reverse = reverse ? -1 : 1;\n    var dateTimezoneOffset = date.getTimezoneOffset();\n    var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n    return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));\n  }\n}]);\n\n// Avoiding use of ng-class as it creates a lot of watchers when a class is to be applied to\n// at most one element.\nangular.module('ui.bootstrap.isClass', [])\n.directive('uibIsClass', [\n         '$animate',\nfunction ($animate) {\n  //                    11111111          22222222\n  var ON_REGEXP = /^\\s*([\\s\\S]+?)\\s+on\\s+([\\s\\S]+?)\\s*$/;\n  //                    11111111           22222222\n  var IS_REGEXP = /^\\s*([\\s\\S]+?)\\s+for\\s+([\\s\\S]+?)\\s*$/;\n\n  var dataPerTracked = {};\n\n  return {\n    restrict: 'A',\n    compile: function(tElement, tAttrs) {\n      var linkedScopes = [];\n      var instances = [];\n      var expToData = {};\n      var lastActivated = null;\n      var onExpMatches = tAttrs.uibIsClass.match(ON_REGEXP);\n      var onExp = onExpMatches[2];\n      var expsStr = onExpMatches[1];\n      var exps = expsStr.split(',');\n\n      return linkFn;\n\n      function linkFn(scope, element, attrs) {\n        linkedScopes.push(scope);\n        instances.push({\n          scope: scope,\n          element: element\n        });\n\n        exps.forEach(function(exp, k) {\n          addForExp(exp, scope);\n        });\n\n        scope.$on('$destroy', removeScope);\n      }\n\n      function addForExp(exp, scope) {\n        var matches = exp.match(IS_REGEXP);\n        var clazz = scope.$eval(matches[1]);\n        var compareWithExp = matches[2];\n        var data = expToData[exp];\n        if (!data) {\n          var watchFn = function(compareWithVal) {\n            var newActivated = null;\n            instances.some(function(instance) {\n              var thisVal = instance.scope.$eval(onExp);\n              if (thisVal === compareWithVal) {\n                newActivated = instance;\n                return true;\n              }\n            });\n            if (data.lastActivated !== newActivated) {\n              if (data.lastActivated) {\n                $animate.removeClass(data.lastActivated.element, clazz);\n              }\n              if (newActivated) {\n                $animate.addClass(newActivated.element, clazz);\n              }\n              data.lastActivated = newActivated;\n            }\n          };\n          expToData[exp] = data = {\n            lastActivated: null,\n            scope: scope,\n            watchFn: watchFn,\n            compareWithExp: compareWithExp,\n            watcher: scope.$watch(compareWithExp, watchFn)\n          };\n        }\n        data.watchFn(scope.$eval(compareWithExp));\n      }\n\n      function removeScope(e) {\n        var removedScope = e.targetScope;\n        var index = linkedScopes.indexOf(removedScope);\n        linkedScopes.splice(index, 1);\n        instances.splice(index, 1);\n        if (linkedScopes.length) {\n          var newWatchScope = linkedScopes[0];\n          angular.forEach(expToData, function(data) {\n            if (data.scope === removedScope) {\n              data.watcher = newWatchScope.$watch(data.compareWithExp, data.watchFn);\n              data.scope = newWatchScope;\n            }\n          });\n        } else {\n          expToData = {};\n        }\n      }\n    }\n  };\n}]);\nangular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.isClass'])\n\n.value('$datepickerSuppressError', false)\n\n.value('$datepickerLiteralWarning', true)\n\n.constant('uibDatepickerConfig', {\n  datepickerMode: 'day',\n  formatDay: 'dd',\n  formatMonth: 'MMMM',\n  formatYear: 'yyyy',\n  formatDayHeader: 'EEE',\n  formatDayTitle: 'MMMM yyyy',\n  formatMonthTitle: 'yyyy',\n  maxDate: null,\n  maxMode: 'year',\n  minDate: null,\n  minMode: 'day',\n  monthColumns: 3,\n  ngModelOptions: {},\n  shortcutPropagation: false,\n  showWeeks: true,\n  yearColumns: 5,\n  yearRows: 4\n})\n\n.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',\n  function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {\n  var self = this,\n      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;\n      ngModelOptions = {},\n      watchListeners = [];\n\n  $element.addClass('uib-datepicker');\n  $attrs.$set('role', 'application');\n\n  if (!$scope.datepickerOptions) {\n    $scope.datepickerOptions = {};\n  }\n\n  // Modes chain\n  this.modes = ['day', 'month', 'year'];\n\n  [\n    'customClass',\n    'dateDisabled',\n    'datepickerMode',\n    'formatDay',\n    'formatDayHeader',\n    'formatDayTitle',\n    'formatMonth',\n    'formatMonthTitle',\n    'formatYear',\n    'maxDate',\n    'maxMode',\n    'minDate',\n    'minMode',\n    'monthColumns',\n    'showWeeks',\n    'shortcutPropagation',\n    'startingDay',\n    'yearColumns',\n    'yearRows'\n  ].forEach(function(key) {\n    switch (key) {\n      case 'customClass':\n      case 'dateDisabled':\n        $scope[key] = $scope.datepickerOptions[key] || angular.noop;\n        break;\n      case 'datepickerMode':\n        $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ?\n          $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode;\n        break;\n      case 'formatDay':\n      case 'formatDayHeader':\n      case 'formatDayTitle':\n      case 'formatMonth':\n      case 'formatMonthTitle':\n      case 'formatYear':\n        self[key] = angular.isDefined($scope.datepickerOptions[key]) ?\n          $interpolate($scope.datepickerOptions[key])($scope.$parent) :\n          datepickerConfig[key];\n        break;\n      case 'monthColumns':\n      case 'showWeeks':\n      case 'shortcutPropagation':\n      case 'yearColumns':\n      case 'yearRows':\n        self[key] = angular.isDefined($scope.datepickerOptions[key]) ?\n          $scope.datepickerOptions[key] : datepickerConfig[key];\n        break;\n      case 'startingDay':\n        if (angular.isDefined($scope.datepickerOptions.startingDay)) {\n          self.startingDay = $scope.datepickerOptions.startingDay;\n        } else if (angular.isNumber(datepickerConfig.startingDay)) {\n          self.startingDay = datepickerConfig.startingDay;\n        } else {\n          self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;\n        }\n\n        break;\n      case 'maxDate':\n      case 'minDate':\n        $scope.$watch('datepickerOptions.' + key, function(value) {\n          if (value) {\n            if (angular.isDate(value)) {\n              self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.getOption('timezone'));\n            } else {\n              if ($datepickerLiteralWarning) {\n                $log.warn('Literal date support has been deprecated, please switch to date object usage');\n              }\n\n              self[key] = new Date(dateFilter(value, 'medium'));\n            }\n          } else {\n            self[key] = datepickerConfig[key] ?\n              dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.getOption('timezone')) :\n              null;\n          }\n\n          self.refreshView();\n        });\n\n        break;\n      case 'maxMode':\n      case 'minMode':\n        if ($scope.datepickerOptions[key]) {\n          $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {\n            self[key] = $scope[key] = angular.isDefined(value) ? value : $scope.datepickerOptions[key];\n            if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) ||\n              key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) {\n              $scope.datepickerMode = self[key];\n              $scope.datepickerOptions.datepickerMode = self[key];\n            }\n          });\n        } else {\n          self[key] = $scope[key] = datepickerConfig[key] || null;\n        }\n\n        break;\n    }\n  });\n\n  $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);\n\n  $scope.disabled = angular.isDefined($attrs.disabled) || false;\n  if (angular.isDefined($attrs.ngDisabled)) {\n    watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {\n      $scope.disabled = disabled;\n      self.refreshView();\n    }));\n  }\n\n  $scope.isActive = function(dateObject) {\n    if (self.compare(dateObject.date, self.activeDate) === 0) {\n      $scope.activeDateId = dateObject.uid;\n      return true;\n    }\n    return false;\n  };\n\n  this.init = function(ngModelCtrl_) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelOptions = extractOptions(ngModelCtrl);\n\n    if ($scope.datepickerOptions.initDate) {\n      self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.getOption('timezone')) || new Date();\n      $scope.$watch('datepickerOptions.initDate', function(initDate) {\n        if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {\n          self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.getOption('timezone'));\n          self.refreshView();\n        }\n      });\n    } else {\n      self.activeDate = new Date();\n    }\n\n    var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();\n    this.activeDate = !isNaN(date) ?\n      dateParser.fromTimezone(date, ngModelOptions.getOption('timezone')) :\n      dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));\n\n    ngModelCtrl.$render = function() {\n      self.render();\n    };\n  };\n\n  this.render = function() {\n    if (ngModelCtrl.$viewValue) {\n      var date = new Date(ngModelCtrl.$viewValue),\n          isValid = !isNaN(date);\n\n      if (isValid) {\n        this.activeDate = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));\n      } else if (!$datepickerSuppressError) {\n        $log.error('Datepicker directive: \"ng-model\" value must be a Date object');\n      }\n    }\n    this.refreshView();\n  };\n\n  this.refreshView = function() {\n    if (this.element) {\n      $scope.selectedDt = null;\n      this._refreshView();\n      if ($scope.activeDt) {\n        $scope.activeDateId = $scope.activeDt.uid;\n      }\n\n      var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n      date = dateParser.fromTimezone(date, ngModelOptions.getOption('timezone'));\n      ngModelCtrl.$setValidity('dateDisabled', !date ||\n        this.element && !this.isDisabled(date));\n    }\n  };\n\n  this.createDateObject = function(date, format) {\n    var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n    model = dateParser.fromTimezone(model, ngModelOptions.getOption('timezone'));\n    var today = new Date();\n    today = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));\n    var time = this.compare(date, today);\n    var dt = {\n      date: date,\n      label: dateParser.filter(date, format),\n      selected: model && this.compare(date, model) === 0,\n      disabled: this.isDisabled(date),\n      past: time < 0,\n      current: time === 0,\n      future: time > 0,\n      customClass: this.customClass(date) || null\n    };\n\n    if (model && this.compare(date, model) === 0) {\n      $scope.selectedDt = dt;\n    }\n\n    if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) {\n      $scope.activeDt = dt;\n    }\n\n    return dt;\n  };\n\n  this.isDisabled = function(date) {\n    return $scope.disabled ||\n      this.minDate && this.compare(date, this.minDate) < 0 ||\n      this.maxDate && this.compare(date, this.maxDate) > 0 ||\n      $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode});\n  };\n\n  this.customClass = function(date) {\n    return $scope.customClass({date: date, mode: $scope.datepickerMode});\n  };\n\n  // Split array into smaller arrays\n  this.split = function(arr, size) {\n    var arrays = [];\n    while (arr.length > 0) {\n      arrays.push(arr.splice(0, size));\n    }\n    return arrays;\n  };\n\n  $scope.select = function(date) {\n    if ($scope.datepickerMode === self.minMode) {\n      var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.getOption('timezone')) : new Date(0, 0, 0, 0, 0, 0, 0);\n      dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n      dt = dateParser.toTimezone(dt, ngModelOptions.getOption('timezone'));\n      ngModelCtrl.$setViewValue(dt);\n      ngModelCtrl.$render();\n    } else {\n      self.activeDate = date;\n      setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);\n\n      $scope.$emit('uib:datepicker.mode');\n    }\n\n    $scope.$broadcast('uib:datepicker.focus');\n  };\n\n  $scope.move = function(direction) {\n    var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),\n        month = self.activeDate.getMonth() + direction * (self.step.months || 0);\n    self.activeDate.setFullYear(year, month, 1);\n    self.refreshView();\n  };\n\n  $scope.toggleMode = function(direction) {\n    direction = direction || 1;\n\n    if ($scope.datepickerMode === self.maxMode && direction === 1 ||\n      $scope.datepickerMode === self.minMode && direction === -1) {\n      return;\n    }\n\n    setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]);\n\n    $scope.$emit('uib:datepicker.mode');\n  };\n\n  // Key event mapper\n  $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };\n\n  var focusElement = function() {\n    self.element[0].focus();\n  };\n\n  // Listen for focus requests from popup directive\n  $scope.$on('uib:datepicker.focus', focusElement);\n\n  $scope.keydown = function(evt) {\n    var key = $scope.keys[evt.which];\n\n    if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {\n      return;\n    }\n\n    evt.preventDefault();\n    if (!self.shortcutPropagation) {\n      evt.stopPropagation();\n    }\n\n    if (key === 'enter' || key === 'space') {\n      if (self.isDisabled(self.activeDate)) {\n        return; // do nothing\n      }\n      $scope.select(self.activeDate);\n    } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {\n      $scope.toggleMode(key === 'up' ? 1 : -1);\n    } else {\n      self.handleKeyDown(key, evt);\n      self.refreshView();\n    }\n  };\n\n  $element.on('keydown', function(evt) {\n    $scope.$apply(function() {\n      $scope.keydown(evt);\n    });\n  });\n\n  $scope.$on('$destroy', function() {\n    //Clear all watch listeners on destroy\n    while (watchListeners.length) {\n      watchListeners.shift()();\n    }\n  });\n\n  function setMode(mode) {\n    $scope.datepickerMode = mode;\n    $scope.datepickerOptions.datepickerMode = mode;\n  }\n\n  function extractOptions(ngModelCtrl) {\n    var ngModelOptions;\n\n    if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing\n      // guarantee a value\n      ngModelOptions = ngModelCtrl.$options ||\n        $scope.datepickerOptions.ngModelOptions ||\n        datepickerConfig.ngModelOptions ||\n        {};\n\n      // mimic 1.6+ api\n      ngModelOptions.getOption = function (key) {\n        return ngModelOptions[key];\n      };\n    } else { // in angular >=1.6 $options is always present\n      // ng-model-options defaults timezone to null; don't let its precedence squash a non-null value\n      var timezone = ngModelCtrl.$options.getOption('timezone') ||\n        ($scope.datepickerOptions.ngModelOptions ? $scope.datepickerOptions.ngModelOptions.timezone : null) ||\n        (datepickerConfig.ngModelOptions ? datepickerConfig.ngModelOptions.timezone : null);\n\n      // values passed to createChild override existing values\n      ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance\n        .createChild(datepickerConfig.ngModelOptions) // lowest precedence\n        .createChild($scope.datepickerOptions.ngModelOptions)\n        .createChild(ngModelCtrl.$options) // highest precedence\n        .createChild({timezone: timezone}); // to keep from squashing a non-null value\n    }\n\n    return ngModelOptions;\n  }\n}])\n\n.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n  var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n  this.step = { months: 1 };\n  this.element = $element;\n  function getDaysInMonth(year, month) {\n    return month === 1 && year % 4 === 0 &&\n      (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month];\n  }\n\n  this.init = function(ctrl) {\n    angular.extend(ctrl, this);\n    scope.showWeeks = ctrl.showWeeks;\n    ctrl.refreshView();\n  };\n\n  this.getDates = function(startDate, n) {\n    var dates = new Array(n), current = new Date(startDate), i = 0, date;\n    while (i < n) {\n      date = new Date(current);\n      dates[i++] = date;\n      current.setDate(current.getDate() + 1);\n    }\n    return dates;\n  };\n\n  this._refreshView = function() {\n    var year = this.activeDate.getFullYear(),\n      month = this.activeDate.getMonth(),\n      firstDayOfMonth = new Date(this.activeDate);\n\n    firstDayOfMonth.setFullYear(year, month, 1);\n\n    var difference = this.startingDay - firstDayOfMonth.getDay(),\n      numDisplayedFromPreviousMonth = difference > 0 ?\n        7 - difference : - difference,\n      firstDate = new Date(firstDayOfMonth);\n\n    if (numDisplayedFromPreviousMonth > 0) {\n      firstDate.setDate(-numDisplayedFromPreviousMonth + 1);\n    }\n\n    // 42 is the number of days on a six-week calendar\n    var days = this.getDates(firstDate, 42);\n    for (var i = 0; i < 42; i ++) {\n      days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {\n        secondary: days[i].getMonth() !== month,\n        uid: scope.uniqueId + '-' + i\n      });\n    }\n\n    scope.labels = new Array(7);\n    for (var j = 0; j < 7; j++) {\n      scope.labels[j] = {\n        abbr: dateFilter(days[j].date, this.formatDayHeader),\n        full: dateFilter(days[j].date, 'EEEE')\n      };\n    }\n\n    scope.title = dateFilter(this.activeDate, this.formatDayTitle);\n    scope.rows = this.split(days, 7);\n\n    if (scope.showWeeks) {\n      scope.weekNumbers = [];\n      var thursdayIndex = (4 + 7 - this.startingDay) % 7,\n          numWeeks = scope.rows.length;\n      for (var curWeek = 0; curWeek < numWeeks; curWeek++) {\n        scope.weekNumbers.push(\n          getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));\n      }\n    }\n  };\n\n  this.compare = function(date1, date2) {\n    var _date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());\n    var _date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());\n    _date1.setFullYear(date1.getFullYear());\n    _date2.setFullYear(date2.getFullYear());\n    return _date1 - _date2;\n  };\n\n  function getISO8601WeekNumber(date) {\n    var checkDate = new Date(date);\n    checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday\n    var time = checkDate.getTime();\n    checkDate.setMonth(0); // Compare with Jan 1\n    checkDate.setDate(1);\n    return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n  }\n\n  this.handleKeyDown = function(key, evt) {\n    var date = this.activeDate.getDate();\n\n    if (key === 'left') {\n      date = date - 1;\n    } else if (key === 'up') {\n      date = date - 7;\n    } else if (key === 'right') {\n      date = date + 1;\n    } else if (key === 'down') {\n      date = date + 7;\n    } else if (key === 'pageup' || key === 'pagedown') {\n      var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);\n      this.activeDate.setMonth(month, 1);\n      date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);\n    } else if (key === 'home') {\n      date = 1;\n    } else if (key === 'end') {\n      date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());\n    }\n    this.activeDate.setDate(date);\n  };\n}])\n\n.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n  this.step = { years: 1 };\n  this.element = $element;\n\n  this.init = function(ctrl) {\n    angular.extend(ctrl, this);\n    ctrl.refreshView();\n  };\n\n  this._refreshView = function() {\n    var months = new Array(12),\n        year = this.activeDate.getFullYear(),\n        date;\n\n    for (var i = 0; i < 12; i++) {\n      date = new Date(this.activeDate);\n      date.setFullYear(year, i, 1);\n      months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {\n        uid: scope.uniqueId + '-' + i\n      });\n    }\n\n    scope.title = dateFilter(this.activeDate, this.formatMonthTitle);\n    scope.rows = this.split(months, this.monthColumns);\n    scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;\n  };\n\n  this.compare = function(date1, date2) {\n    var _date1 = new Date(date1.getFullYear(), date1.getMonth());\n    var _date2 = new Date(date2.getFullYear(), date2.getMonth());\n    _date1.setFullYear(date1.getFullYear());\n    _date2.setFullYear(date2.getFullYear());\n    return _date1 - _date2;\n  };\n\n  this.handleKeyDown = function(key, evt) {\n    var date = this.activeDate.getMonth();\n\n    if (key === 'left') {\n      date = date - 1;\n    } else if (key === 'up') {\n      date = date - this.monthColumns;\n    } else if (key === 'right') {\n      date = date + 1;\n    } else if (key === 'down') {\n      date = date + this.monthColumns;\n    } else if (key === 'pageup' || key === 'pagedown') {\n      var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);\n      this.activeDate.setFullYear(year);\n    } else if (key === 'home') {\n      date = 0;\n    } else if (key === 'end') {\n      date = 11;\n    }\n    this.activeDate.setMonth(date);\n  };\n}])\n\n.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n  var columns, range;\n  this.element = $element;\n\n  function getStartingYear(year) {\n    return parseInt((year - 1) / range, 10) * range + 1;\n  }\n\n  this.yearpickerInit = function() {\n    columns = this.yearColumns;\n    range = this.yearRows * columns;\n    this.step = { years: range };\n  };\n\n  this._refreshView = function() {\n    var years = new Array(range), date;\n\n    for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {\n      date = new Date(this.activeDate);\n      date.setFullYear(start + i, 0, 1);\n      years[i] = angular.extend(this.createDateObject(date, this.formatYear), {\n        uid: scope.uniqueId + '-' + i\n      });\n    }\n\n    scope.title = [years[0].label, years[range - 1].label].join(' - ');\n    scope.rows = this.split(years, columns);\n    scope.columns = columns;\n  };\n\n  this.compare = function(date1, date2) {\n    return date1.getFullYear() - date2.getFullYear();\n  };\n\n  this.handleKeyDown = function(key, evt) {\n    var date = this.activeDate.getFullYear();\n\n    if (key === 'left') {\n      date = date - 1;\n    } else if (key === 'up') {\n      date = date - columns;\n    } else if (key === 'right') {\n      date = date + 1;\n    } else if (key === 'down') {\n      date = date + columns;\n    } else if (key === 'pageup' || key === 'pagedown') {\n      date += (key === 'pageup' ? - 1 : 1) * range;\n    } else if (key === 'home') {\n      date = getStartingYear(this.activeDate.getFullYear());\n    } else if (key === 'end') {\n      date = getStartingYear(this.activeDate.getFullYear()) + range - 1;\n    }\n    this.activeDate.setFullYear(date);\n  };\n}])\n\n.directive('uibDatepicker', function() {\n  return {\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';\n    },\n    scope: {\n      datepickerOptions: '=?'\n    },\n    require: ['uibDatepicker', '^ngModel'],\n    restrict: 'A',\n    controller: 'UibDatepickerController',\n    controllerAs: 'datepicker',\n    link: function(scope, element, attrs, ctrls) {\n      var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      datepickerCtrl.init(ngModelCtrl);\n    }\n  };\n})\n\n.directive('uibDaypicker', function() {\n  return {\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/datepicker/day.html';\n    },\n    require: ['^uibDatepicker', 'uibDaypicker'],\n    restrict: 'A',\n    controller: 'UibDaypickerController',\n    link: function(scope, element, attrs, ctrls) {\n      var datepickerCtrl = ctrls[0],\n        daypickerCtrl = ctrls[1];\n\n      daypickerCtrl.init(datepickerCtrl);\n    }\n  };\n})\n\n.directive('uibMonthpicker', function() {\n  return {\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/datepicker/month.html';\n    },\n    require: ['^uibDatepicker', 'uibMonthpicker'],\n    restrict: 'A',\n    controller: 'UibMonthpickerController',\n    link: function(scope, element, attrs, ctrls) {\n      var datepickerCtrl = ctrls[0],\n        monthpickerCtrl = ctrls[1];\n\n      monthpickerCtrl.init(datepickerCtrl);\n    }\n  };\n})\n\n.directive('uibYearpicker', function() {\n  return {\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/datepicker/year.html';\n    },\n    require: ['^uibDatepicker', 'uibYearpicker'],\n    restrict: 'A',\n    controller: 'UibYearpickerController',\n    link: function(scope, element, attrs, ctrls) {\n      var ctrl = ctrls[0];\n      angular.extend(ctrl, ctrls[1]);\n      ctrl.yearpickerInit();\n\n      ctrl.refreshView();\n    }\n  };\n});\n\nangular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods for working with the DOM.\n * It is meant to be used where we need to absolute-position elements in\n * relation to another element (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n  .factory('$uibPosition', ['$document', '$window', function($document, $window) {\n    /**\n     * Used by scrollbarWidth() function to cache scrollbar's width.\n     * Do not access this variable directly, use scrollbarWidth() instead.\n     */\n    var SCROLLBAR_WIDTH;\n    /**\n     * scrollbar on body and html element in IE and Edge overlay\n     * content and should be considered 0 width.\n     */\n    var BODY_SCROLLBAR_WIDTH;\n    var OVERFLOW_REGEX = {\n      normal: /(auto|scroll)/,\n      hidden: /(auto|scroll|hidden)/\n    };\n    var PLACEMENT_REGEX = {\n      auto: /\\s?auto?\\s?/i,\n      primary: /^(top|bottom|left|right)$/,\n      secondary: /^(top|bottom|left|right|center)$/,\n      vertical: /^(top|bottom)$/\n    };\n    var BODY_REGEX = /(HTML|BODY)/;\n\n    return {\n\n      /**\n       * Provides a raw DOM element from a jQuery/jQLite element.\n       *\n       * @param {element} elem - The element to convert.\n       *\n       * @returns {element} A HTML element.\n       */\n      getRawNode: function(elem) {\n        return elem.nodeName ? elem : elem[0] || elem;\n      },\n\n      /**\n       * Provides a parsed number for a style property.  Strips\n       * units and casts invalid numbers to 0.\n       *\n       * @param {string} value - The style value to parse.\n       *\n       * @returns {number} A valid number.\n       */\n      parseStyle: function(value) {\n        value = parseFloat(value);\n        return isFinite(value) ? value : 0;\n      },\n\n      /**\n       * Provides the closest positioned ancestor.\n       *\n       * @param {element} element - The element to get the offest parent for.\n       *\n       * @returns {element} The closest positioned ancestor.\n       */\n      offsetParent: function(elem) {\n        elem = this.getRawNode(elem);\n\n        var offsetParent = elem.offsetParent || $document[0].documentElement;\n\n        function isStaticPositioned(el) {\n          return ($window.getComputedStyle(el).position || 'static') === 'static';\n        }\n\n        while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {\n          offsetParent = offsetParent.offsetParent;\n        }\n\n        return offsetParent || $document[0].documentElement;\n      },\n\n      /**\n       * Provides the scrollbar width, concept from TWBS measureScrollbar()\n       * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js\n       * In IE and Edge, scollbar on body and html element overlay and should\n       * return a width of 0.\n       *\n       * @returns {number} The width of the browser scollbar.\n       */\n      scrollbarWidth: function(isBody) {\n        if (isBody) {\n          if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {\n            var bodyElem = $document.find('body');\n            bodyElem.addClass('uib-position-body-scrollbar-measure');\n            BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;\n            BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;\n            bodyElem.removeClass('uib-position-body-scrollbar-measure');\n          }\n          return BODY_SCROLLBAR_WIDTH;\n        }\n\n        if (angular.isUndefined(SCROLLBAR_WIDTH)) {\n          var scrollElem = angular.element('<div class=\"uib-position-scrollbar-measure\"></div>');\n          $document.find('body').append(scrollElem);\n          SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;\n          SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;\n          scrollElem.remove();\n        }\n\n        return SCROLLBAR_WIDTH;\n      },\n\n      /**\n       * Provides the padding required on an element to replace the scrollbar.\n       *\n       * @returns {object} An object with the following properties:\n       *   <ul>\n       *     <li>**scrollbarWidth**: the width of the scrollbar</li>\n       *     <li>**widthOverflow**: whether the the width is overflowing</li>\n       *     <li>**right**: the amount of right padding on the element needed to replace the scrollbar</li>\n       *     <li>**rightOriginal**: the amount of right padding currently on the element</li>\n       *     <li>**heightOverflow**: whether the the height is overflowing</li>\n       *     <li>**bottom**: the amount of bottom padding on the element needed to replace the scrollbar</li>\n       *     <li>**bottomOriginal**: the amount of bottom padding currently on the element</li>\n       *   </ul>\n       */\n      scrollbarPadding: function(elem) {\n        elem = this.getRawNode(elem);\n\n        var elemStyle = $window.getComputedStyle(elem);\n        var paddingRight = this.parseStyle(elemStyle.paddingRight);\n        var paddingBottom = this.parseStyle(elemStyle.paddingBottom);\n        var scrollParent = this.scrollParent(elem, false, true);\n        var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));\n\n        return {\n          scrollbarWidth: scrollbarWidth,\n          widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,\n          right: paddingRight + scrollbarWidth,\n          originalRight: paddingRight,\n          heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,\n          bottom: paddingBottom + scrollbarWidth,\n          originalBottom: paddingBottom\n         };\n      },\n\n      /**\n       * Checks to see if the element is scrollable.\n       *\n       * @param {element} elem - The element to check.\n       * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,\n       *   default is false.\n       *\n       * @returns {boolean} Whether the element is scrollable.\n       */\n      isScrollable: function(elem, includeHidden) {\n        elem = this.getRawNode(elem);\n\n        var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;\n        var elemStyle = $window.getComputedStyle(elem);\n        return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);\n      },\n\n      /**\n       * Provides the closest scrollable ancestor.\n       * A port of the jQuery UI scrollParent method:\n       * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js\n       *\n       * @param {element} elem - The element to find the scroll parent of.\n       * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,\n       *   default is false.\n       * @param {boolean=} [includeSelf=false] - Should the element being passed be\n       * included in the scrollable llokup.\n       *\n       * @returns {element} A HTML element.\n       */\n      scrollParent: function(elem, includeHidden, includeSelf) {\n        elem = this.getRawNode(elem);\n\n        var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;\n        var documentEl = $document[0].documentElement;\n        var elemStyle = $window.getComputedStyle(elem);\n        if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {\n          return elem;\n        }\n        var excludeStatic = elemStyle.position === 'absolute';\n        var scrollParent = elem.parentElement || documentEl;\n\n        if (scrollParent === documentEl || elemStyle.position === 'fixed') {\n          return documentEl;\n        }\n\n        while (scrollParent.parentElement && scrollParent !== documentEl) {\n          var spStyle = $window.getComputedStyle(scrollParent);\n          if (excludeStatic && spStyle.position !== 'static') {\n            excludeStatic = false;\n          }\n\n          if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {\n            break;\n          }\n          scrollParent = scrollParent.parentElement;\n        }\n\n        return scrollParent;\n      },\n\n      /**\n       * Provides read-only equivalent of jQuery's position function:\n       * http://api.jquery.com/position/ - distance to closest positioned\n       * ancestor.  Does not account for margins by default like jQuery position.\n       *\n       * @param {element} elem - The element to caclulate the position on.\n       * @param {boolean=} [includeMargins=false] - Should margins be accounted\n       * for, default is false.\n       *\n       * @returns {object} An object with the following properties:\n       *   <ul>\n       *     <li>**width**: the width of the element</li>\n       *     <li>**height**: the height of the element</li>\n       *     <li>**top**: distance to top edge of offset parent</li>\n       *     <li>**left**: distance to left edge of offset parent</li>\n       *   </ul>\n       */\n      position: function(elem, includeMagins) {\n        elem = this.getRawNode(elem);\n\n        var elemOffset = this.offset(elem);\n        if (includeMagins) {\n          var elemStyle = $window.getComputedStyle(elem);\n          elemOffset.top -= this.parseStyle(elemStyle.marginTop);\n          elemOffset.left -= this.parseStyle(elemStyle.marginLeft);\n        }\n        var parent = this.offsetParent(elem);\n        var parentOffset = {top: 0, left: 0};\n\n        if (parent !== $document[0].documentElement) {\n          parentOffset = this.offset(parent);\n          parentOffset.top += parent.clientTop - parent.scrollTop;\n          parentOffset.left += parent.clientLeft - parent.scrollLeft;\n        }\n\n        return {\n          width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),\n          height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),\n          top: Math.round(elemOffset.top - parentOffset.top),\n          left: Math.round(elemOffset.left - parentOffset.left)\n        };\n      },\n\n      /**\n       * Provides read-only equivalent of jQuery's offset function:\n       * http://api.jquery.com/offset/ - distance to viewport.  Does\n       * not account for borders, margins, or padding on the body\n       * element.\n       *\n       * @param {element} elem - The element to calculate the offset on.\n       *\n       * @returns {object} An object with the following properties:\n       *   <ul>\n       *     <li>**width**: the width of the element</li>\n       *     <li>**height**: the height of the element</li>\n       *     <li>**top**: distance to top edge of viewport</li>\n       *     <li>**right**: distance to bottom edge of viewport</li>\n       *   </ul>\n       */\n      offset: function(elem) {\n        elem = this.getRawNode(elem);\n\n        var elemBCR = elem.getBoundingClientRect();\n        return {\n          width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),\n          height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),\n          top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),\n          left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))\n        };\n      },\n\n      /**\n       * Provides offset distance to the closest scrollable ancestor\n       * or viewport.  Accounts for border and scrollbar width.\n       *\n       * Right and bottom dimensions represent the distance to the\n       * respective edge of the viewport element.  If the element\n       * edge extends beyond the viewport, a negative value will be\n       * reported.\n       *\n       * @param {element} elem - The element to get the viewport offset for.\n       * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead\n       * of the first scrollable element, default is false.\n       * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element\n       * be accounted for, default is true.\n       *\n       * @returns {object} An object with the following properties:\n       *   <ul>\n       *     <li>**top**: distance to the top content edge of viewport element</li>\n       *     <li>**bottom**: distance to the bottom content edge of viewport element</li>\n       *     <li>**left**: distance to the left content edge of viewport element</li>\n       *     <li>**right**: distance to the right content edge of viewport element</li>\n       *   </ul>\n       */\n      viewportOffset: function(elem, useDocument, includePadding) {\n        elem = this.getRawNode(elem);\n        includePadding = includePadding !== false ? true : false;\n\n        var elemBCR = elem.getBoundingClientRect();\n        var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};\n\n        var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);\n        var offsetParentBCR = offsetParent.getBoundingClientRect();\n\n        offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;\n        offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;\n        if (offsetParent === $document[0].documentElement) {\n          offsetBCR.top += $window.pageYOffset;\n          offsetBCR.left += $window.pageXOffset;\n        }\n        offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;\n        offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;\n\n        if (includePadding) {\n          var offsetParentStyle = $window.getComputedStyle(offsetParent);\n          offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);\n          offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);\n          offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);\n          offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);\n        }\n\n        return {\n          top: Math.round(elemBCR.top - offsetBCR.top),\n          bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),\n          left: Math.round(elemBCR.left - offsetBCR.left),\n          right: Math.round(offsetBCR.right - elemBCR.right)\n        };\n      },\n\n      /**\n       * Provides an array of placement values parsed from a placement string.\n       * Along with the 'auto' indicator, supported placement strings are:\n       *   <ul>\n       *     <li>top: element on top, horizontally centered on host element.</li>\n       *     <li>top-left: element on top, left edge aligned with host element left edge.</li>\n       *     <li>top-right: element on top, lerightft edge aligned with host element right edge.</li>\n       *     <li>bottom: element on bottom, horizontally centered on host element.</li>\n       *     <li>bottom-left: element on bottom, left edge aligned with host element left edge.</li>\n       *     <li>bottom-right: element on bottom, right edge aligned with host element right edge.</li>\n       *     <li>left: element on left, vertically centered on host element.</li>\n       *     <li>left-top: element on left, top edge aligned with host element top edge.</li>\n       *     <li>left-bottom: element on left, bottom edge aligned with host element bottom edge.</li>\n       *     <li>right: element on right, vertically centered on host element.</li>\n       *     <li>right-top: element on right, top edge aligned with host element top edge.</li>\n       *     <li>right-bottom: element on right, bottom edge aligned with host element bottom edge.</li>\n       *   </ul>\n       * A placement string with an 'auto' indicator is expected to be\n       * space separated from the placement, i.e: 'auto bottom-left'  If\n       * the primary and secondary placement values do not match 'top,\n       * bottom, left, right' then 'top' will be the primary placement and\n       * 'center' will be the secondary placement.  If 'auto' is passed, true\n       * will be returned as the 3rd value of the array.\n       *\n       * @param {string} placement - The placement string to parse.\n       *\n       * @returns {array} An array with the following values\n       * <ul>\n       *   <li>**[0]**: The primary placement.</li>\n       *   <li>**[1]**: The secondary placement.</li>\n       *   <li>**[2]**: If auto is passed: true, else undefined.</li>\n       * </ul>\n       */\n      parsePlacement: function(placement) {\n        var autoPlace = PLACEMENT_REGEX.auto.test(placement);\n        if (autoPlace) {\n          placement = placement.replace(PLACEMENT_REGEX.auto, '');\n        }\n\n        placement = placement.split('-');\n\n        placement[0] = placement[0] || 'top';\n        if (!PLACEMENT_REGEX.primary.test(placement[0])) {\n          placement[0] = 'top';\n        }\n\n        placement[1] = placement[1] || 'center';\n        if (!PLACEMENT_REGEX.secondary.test(placement[1])) {\n          placement[1] = 'center';\n        }\n\n        if (autoPlace) {\n          placement[2] = true;\n        } else {\n          placement[2] = false;\n        }\n\n        return placement;\n      },\n\n      /**\n       * Provides coordinates for an element to be positioned relative to\n       * another element.  Passing 'auto' as part of the placement parameter\n       * will enable smart placement - where the element fits. i.e:\n       * 'auto left-top' will check to see if there is enough space to the left\n       * of the hostElem to fit the targetElem, if not place right (same for secondary\n       * top placement).  Available space is calculated using the viewportOffset\n       * function.\n       *\n       * @param {element} hostElem - The element to position against.\n       * @param {element} targetElem - The element to position.\n       * @param {string=} [placement=top] - The placement for the targetElem,\n       *   default is 'top'. 'center' is assumed as secondary placement for\n       *   'top', 'left', 'right', and 'bottom' placements.  Available placements are:\n       *   <ul>\n       *     <li>top</li>\n       *     <li>top-right</li>\n       *     <li>top-left</li>\n       *     <li>bottom</li>\n       *     <li>bottom-left</li>\n       *     <li>bottom-right</li>\n       *     <li>left</li>\n       *     <li>left-top</li>\n       *     <li>left-bottom</li>\n       *     <li>right</li>\n       *     <li>right-top</li>\n       *     <li>right-bottom</li>\n       *   </ul>\n       * @param {boolean=} [appendToBody=false] - Should the top and left values returned\n       *   be calculated from the body element, default is false.\n       *\n       * @returns {object} An object with the following properties:\n       *   <ul>\n       *     <li>**top**: Value for targetElem top.</li>\n       *     <li>**left**: Value for targetElem left.</li>\n       *     <li>**placement**: The resolved placement.</li>\n       *   </ul>\n       */\n      positionElements: function(hostElem, targetElem, placement, appendToBody) {\n        hostElem = this.getRawNode(hostElem);\n        targetElem = this.getRawNode(targetElem);\n\n        // need to read from prop to support tests.\n        var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');\n        var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');\n\n        placement = this.parsePlacement(placement);\n\n        var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);\n        var targetElemPos = {top: 0, left: 0, placement: ''};\n\n        if (placement[2]) {\n          var viewportOffset = this.viewportOffset(hostElem, appendToBody);\n\n          var targetElemStyle = $window.getComputedStyle(targetElem);\n          var adjustedSize = {\n            width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),\n            height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))\n          };\n\n          placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :\n                         placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :\n                         placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :\n                         placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :\n                         placement[0];\n\n          placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :\n                         placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :\n                         placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :\n                         placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :\n                         placement[1];\n\n          if (placement[1] === 'center') {\n            if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n              var xOverflow = hostElemPos.width / 2 - targetWidth / 2;\n              if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {\n                placement[1] = 'left';\n              } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {\n                placement[1] = 'right';\n              }\n            } else {\n              var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;\n              if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {\n                placement[1] = 'top';\n              } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {\n                placement[1] = 'bottom';\n              }\n            }\n          }\n        }\n\n        switch (placement[0]) {\n          case 'top':\n            targetElemPos.top = hostElemPos.top - targetHeight;\n            break;\n          case 'bottom':\n            targetElemPos.top = hostElemPos.top + hostElemPos.height;\n            break;\n          case 'left':\n            targetElemPos.left = hostElemPos.left - targetWidth;\n            break;\n          case 'right':\n            targetElemPos.left = hostElemPos.left + hostElemPos.width;\n            break;\n        }\n\n        switch (placement[1]) {\n          case 'top':\n            targetElemPos.top = hostElemPos.top;\n            break;\n          case 'bottom':\n            targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;\n            break;\n          case 'left':\n            targetElemPos.left = hostElemPos.left;\n            break;\n          case 'right':\n            targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;\n            break;\n          case 'center':\n            if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n              targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;\n            } else {\n              targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;\n            }\n            break;\n        }\n\n        targetElemPos.top = Math.round(targetElemPos.top);\n        targetElemPos.left = Math.round(targetElemPos.left);\n        targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];\n\n        return targetElemPos;\n      },\n\n      /**\n       * Provides a way to adjust the top positioning after first\n       * render to correctly align element to top after content\n       * rendering causes resized element height\n       *\n       * @param {array} placementClasses - The array of strings of classes\n       * element should have.\n       * @param {object} containerPosition - The object with container\n       * position information\n       * @param {number} initialHeight - The initial height for the elem.\n       * @param {number} currentHeight - The current height for the elem.\n       */\n      adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) {\n        if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {\n          return {\n            top: containerPosition.top - currentHeight + 'px'\n          };\n        }\n      },\n\n      /**\n       * Provides a way for positioning tooltip & dropdown\n       * arrows when using placement options beyond the standard\n       * left, right, top, or bottom.\n       *\n       * @param {element} elem - The tooltip/dropdown element.\n       * @param {string} placement - The placement for the elem.\n       */\n      positionArrow: function(elem, placement) {\n        elem = this.getRawNode(elem);\n\n        var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');\n        if (!innerElem) {\n          return;\n        }\n\n        var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');\n\n        var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');\n        if (!arrowElem) {\n          return;\n        }\n\n        var arrowCss = {\n          top: '',\n          bottom: '',\n          left: '',\n          right: ''\n        };\n\n        placement = this.parsePlacement(placement);\n        if (placement[1] === 'center') {\n          // no adjustment necessary - just reset styles\n          angular.element(arrowElem).css(arrowCss);\n          return;\n        }\n\n        var borderProp = 'border-' + placement[0] + '-width';\n        var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];\n\n        var borderRadiusProp = 'border-';\n        if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n          borderRadiusProp += placement[0] + '-' + placement[1];\n        } else {\n          borderRadiusProp += placement[1] + '-' + placement[0];\n        }\n        borderRadiusProp += '-radius';\n        var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];\n\n        switch (placement[0]) {\n          case 'top':\n            arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;\n            break;\n          case 'bottom':\n            arrowCss.top = isTooltip ? '0' : '-' + borderWidth;\n            break;\n          case 'left':\n            arrowCss.right = isTooltip ? '0' : '-' + borderWidth;\n            break;\n          case 'right':\n            arrowCss.left = isTooltip ? '0' : '-' + borderWidth;\n            break;\n        }\n\n        arrowCss[placement[1]] = borderRadius;\n\n        angular.element(arrowElem).css(arrowCss);\n      }\n    };\n  }]);\n\nangular.module('ui.bootstrap.datepickerPopup', ['ui.bootstrap.datepicker', 'ui.bootstrap.position'])\n\n.value('$datepickerPopupLiteralWarning', true)\n\n.constant('uibDatepickerPopupConfig', {\n  altInputFormats: [],\n  appendToBody: false,\n  clearText: 'Clear',\n  closeOnDateSelection: true,\n  closeText: 'Done',\n  currentText: 'Today',\n  datepickerPopup: 'yyyy-MM-dd',\n  datepickerPopupTemplateUrl: 'uib/template/datepickerPopup/popup.html',\n  datepickerTemplateUrl: 'uib/template/datepicker/datepicker.html',\n  html5Types: {\n    date: 'yyyy-MM-dd',\n    'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',\n    'month': 'yyyy-MM'\n  },\n  onOpenFocus: true,\n  showButtonBar: true,\n  placement: 'auto bottom-left'\n})\n\n.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', '$datepickerPopupLiteralWarning',\nfunction($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, $datepickerPopupLiteralWarning) {\n  var cache = {},\n    isHtml5DateInput = false;\n  var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,\n    datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,\n    ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];\n\n  this.init = function(_ngModel_) {\n    ngModel = _ngModel_;\n    ngModelOptions = extractOptions(ngModel);\n    closeOnDateSelection = angular.isDefined($attrs.closeOnDateSelection) ?\n      $scope.$parent.$eval($attrs.closeOnDateSelection) :\n      datepickerPopupConfig.closeOnDateSelection;\n    appendToBody = angular.isDefined($attrs.datepickerAppendToBody) ?\n      $scope.$parent.$eval($attrs.datepickerAppendToBody) :\n      datepickerPopupConfig.appendToBody;\n    onOpenFocus = angular.isDefined($attrs.onOpenFocus) ?\n      $scope.$parent.$eval($attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;\n    datepickerPopupTemplateUrl = angular.isDefined($attrs.datepickerPopupTemplateUrl) ?\n      $attrs.datepickerPopupTemplateUrl :\n      datepickerPopupConfig.datepickerPopupTemplateUrl;\n    datepickerTemplateUrl = angular.isDefined($attrs.datepickerTemplateUrl) ?\n      $attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;\n    altInputFormats = angular.isDefined($attrs.altInputFormats) ?\n      $scope.$parent.$eval($attrs.altInputFormats) :\n      datepickerPopupConfig.altInputFormats;\n\n    $scope.showButtonBar = angular.isDefined($attrs.showButtonBar) ?\n      $scope.$parent.$eval($attrs.showButtonBar) :\n      datepickerPopupConfig.showButtonBar;\n\n    if (datepickerPopupConfig.html5Types[$attrs.type]) {\n      dateFormat = datepickerPopupConfig.html5Types[$attrs.type];\n      isHtml5DateInput = true;\n    } else {\n      dateFormat = $attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;\n      $attrs.$observe('uibDatepickerPopup', function(value, oldValue) {\n        var newDateFormat = value || datepickerPopupConfig.datepickerPopup;\n        // Invalidate the $modelValue to ensure that formatters re-run\n        // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764\n        if (newDateFormat !== dateFormat) {\n          dateFormat = newDateFormat;\n          ngModel.$modelValue = null;\n\n          if (!dateFormat) {\n            throw new Error('uibDatepickerPopup must have a date format specified.');\n          }\n        }\n      });\n    }\n\n    if (!dateFormat) {\n      throw new Error('uibDatepickerPopup must have a date format specified.');\n    }\n\n    if (isHtml5DateInput && $attrs.uibDatepickerPopup) {\n      throw new Error('HTML5 date input types do not support custom formats.');\n    }\n\n    // popup element used to display calendar\n    popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');\n\n    popupEl.attr({\n      'ng-model': 'date',\n      'ng-change': 'dateSelection(date)',\n      'template-url': datepickerPopupTemplateUrl\n    });\n\n    // datepicker element\n    datepickerEl = angular.element(popupEl.children()[0]);\n    datepickerEl.attr('template-url', datepickerTemplateUrl);\n\n    if (!$scope.datepickerOptions) {\n      $scope.datepickerOptions = {};\n    }\n\n    if (isHtml5DateInput) {\n      if ($attrs.type === 'month') {\n        $scope.datepickerOptions.datepickerMode = 'month';\n        $scope.datepickerOptions.minMode = 'month';\n      }\n    }\n\n    datepickerEl.attr('datepicker-options', 'datepickerOptions');\n\n    if (!isHtml5DateInput) {\n      // Internal API to maintain the correct ng-invalid-[key] class\n      ngModel.$$parserName = 'date';\n      ngModel.$validators.date = validator;\n      ngModel.$parsers.unshift(parseDate);\n      ngModel.$formatters.push(function(value) {\n        if (ngModel.$isEmpty(value)) {\n          $scope.date = value;\n          return value;\n        }\n\n        if (angular.isNumber(value)) {\n          value = new Date(value);\n        }\n\n        $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));\n\n        return dateParser.filter($scope.date, dateFormat);\n      });\n    } else {\n      ngModel.$formatters.push(function(value) {\n        $scope.date = dateParser.fromTimezone(value, ngModelOptions.getOption('timezone'));\n        return value;\n      });\n    }\n\n    // Detect changes in the view from the text box\n    ngModel.$viewChangeListeners.push(function() {\n      $scope.date = parseDateString(ngModel.$viewValue);\n    });\n\n    $element.on('keydown', inputKeydownBind);\n\n    $popup = $compile(popupEl)($scope);\n    // Prevent jQuery cache memory leak (template is now redundant after linking)\n    popupEl.remove();\n\n    if (appendToBody) {\n      $document.find('body').append($popup);\n    } else {\n      $element.after($popup);\n    }\n\n    $scope.$on('$destroy', function() {\n      if ($scope.isOpen === true) {\n        if (!$rootScope.$$phase) {\n          $scope.$apply(function() {\n            $scope.isOpen = false;\n          });\n        }\n      }\n\n      $popup.remove();\n      $element.off('keydown', inputKeydownBind);\n      $document.off('click', documentClickBind);\n      if (scrollParentEl) {\n        scrollParentEl.off('scroll', positionPopup);\n      }\n      angular.element($window).off('resize', positionPopup);\n\n      //Clear all watch listeners on destroy\n      while (watchListeners.length) {\n        watchListeners.shift()();\n      }\n    });\n  };\n\n  $scope.getText = function(key) {\n    return $scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];\n  };\n\n  $scope.isDisabled = function(date) {\n    if (date === 'today') {\n      date = dateParser.fromTimezone(new Date(), ngModelOptions.getOption('timezone'));\n    }\n\n    var dates = {};\n    angular.forEach(['minDate', 'maxDate'], function(key) {\n      if (!$scope.datepickerOptions[key]) {\n        dates[key] = null;\n      } else if (angular.isDate($scope.datepickerOptions[key])) {\n        dates[key] = new Date($scope.datepickerOptions[key]);\n      } else {\n        if ($datepickerPopupLiteralWarning) {\n          $log.warn('Literal date support has been deprecated, please switch to date object usage');\n        }\n\n        dates[key] = new Date(dateFilter($scope.datepickerOptions[key], 'medium'));\n      }\n    });\n\n    return $scope.datepickerOptions &&\n      dates.minDate && $scope.compare(date, dates.minDate) < 0 ||\n      dates.maxDate && $scope.compare(date, dates.maxDate) > 0;\n  };\n\n  $scope.compare = function(date1, date2) {\n    return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());\n  };\n\n  // Inner change\n  $scope.dateSelection = function(dt) {\n    $scope.date = dt;\n    var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function\n    $element.val(date);\n    ngModel.$setViewValue(date);\n\n    if (closeOnDateSelection) {\n      $scope.isOpen = false;\n      $element[0].focus();\n    }\n  };\n\n  $scope.keydown = function(evt) {\n    if (evt.which === 27) {\n      evt.stopPropagation();\n      $scope.isOpen = false;\n      $element[0].focus();\n    }\n  };\n\n  $scope.select = function(date, evt) {\n    evt.stopPropagation();\n\n    if (date === 'today') {\n      var today = new Date();\n      if (angular.isDate($scope.date)) {\n        date = new Date($scope.date);\n        date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());\n      } else {\n        date = dateParser.fromTimezone(today, ngModelOptions.getOption('timezone'));\n        date.setHours(0, 0, 0, 0);\n      }\n    }\n    $scope.dateSelection(date);\n  };\n\n  $scope.close = function(evt) {\n    evt.stopPropagation();\n\n    $scope.isOpen = false;\n    $element[0].focus();\n  };\n\n  $scope.disabled = angular.isDefined($attrs.disabled) || false;\n  if ($attrs.ngDisabled) {\n    watchListeners.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(disabled) {\n      $scope.disabled = disabled;\n    }));\n  }\n\n  $scope.$watch('isOpen', function(value) {\n    if (value) {\n      if (!$scope.disabled) {\n        $timeout(function() {\n          positionPopup();\n\n          if (onOpenFocus) {\n            $scope.$broadcast('uib:datepicker.focus');\n          }\n\n          $document.on('click', documentClickBind);\n\n          var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;\n          if (appendToBody || $position.parsePlacement(placement)[2]) {\n            scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));\n            if (scrollParentEl) {\n              scrollParentEl.on('scroll', positionPopup);\n            }\n          } else {\n            scrollParentEl = null;\n          }\n\n          angular.element($window).on('resize', positionPopup);\n        }, 0, false);\n      } else {\n        $scope.isOpen = false;\n      }\n    } else {\n      $document.off('click', documentClickBind);\n      if (scrollParentEl) {\n        scrollParentEl.off('scroll', positionPopup);\n      }\n      angular.element($window).off('resize', positionPopup);\n    }\n  });\n\n  function cameltoDash(string) {\n    return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });\n  }\n\n  function parseDateString(viewValue) {\n    var date = dateParser.parse(viewValue, dateFormat, $scope.date);\n    if (isNaN(date)) {\n      for (var i = 0; i < altInputFormats.length; i++) {\n        date = dateParser.parse(viewValue, altInputFormats[i], $scope.date);\n        if (!isNaN(date)) {\n          return date;\n        }\n      }\n    }\n    return date;\n  }\n\n  function parseDate(viewValue) {\n    if (angular.isNumber(viewValue)) {\n      // presumably timestamp to date object\n      viewValue = new Date(viewValue);\n    }\n\n    if (!viewValue) {\n      return null;\n    }\n\n    if (angular.isDate(viewValue) && !isNaN(viewValue)) {\n      return viewValue;\n    }\n\n    if (angular.isString(viewValue)) {\n      var date = parseDateString(viewValue);\n      if (!isNaN(date)) {\n        return dateParser.toTimezone(date, ngModelOptions.getOption('timezone'));\n      }\n    }\n\n    return ngModelOptions.getOption('allowInvalid') ? viewValue : undefined;\n  }\n\n  function validator(modelValue, viewValue) {\n    var value = modelValue || viewValue;\n\n    if (!$attrs.ngRequired && !value) {\n      return true;\n    }\n\n    if (angular.isNumber(value)) {\n      value = new Date(value);\n    }\n\n    if (!value) {\n      return true;\n    }\n\n    if (angular.isDate(value) && !isNaN(value)) {\n      return true;\n    }\n\n    if (angular.isString(value)) {\n      return !isNaN(parseDateString(value));\n    }\n\n    return false;\n  }\n\n  function documentClickBind(event) {\n    if (!$scope.isOpen && $scope.disabled) {\n      return;\n    }\n\n    var popup = $popup[0];\n    var dpContainsTarget = $element[0].contains(event.target);\n    // The popup node may not be an element node\n    // In some browsers (IE) only element nodes have the 'contains' function\n    var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);\n    if ($scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {\n      $scope.$apply(function() {\n        $scope.isOpen = false;\n      });\n    }\n  }\n\n  function inputKeydownBind(evt) {\n    if (evt.which === 27 && $scope.isOpen) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      $scope.$apply(function() {\n        $scope.isOpen = false;\n      });\n      $element[0].focus();\n    } else if (evt.which === 40 && !$scope.isOpen) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      $scope.$apply(function() {\n        $scope.isOpen = true;\n      });\n    }\n  }\n\n  function positionPopup() {\n    if ($scope.isOpen) {\n      var dpElement = angular.element($popup[0].querySelector('.uib-datepicker-popup'));\n      var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;\n      var position = $position.positionElements($element, dpElement, placement, appendToBody);\n      dpElement.css({top: position.top + 'px', left: position.left + 'px'});\n      if (dpElement.hasClass('uib-position-measure')) {\n        dpElement.removeClass('uib-position-measure');\n      }\n    }\n  }\n\n  function extractOptions(ngModelCtrl) {\n    var ngModelOptions;\n\n    if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing\n      // guarantee a value\n      ngModelOptions = angular.isObject(ngModelCtrl.$options) ?\n        ngModelCtrl.$options :\n        {\n          timezone: null\n        };\n\n      // mimic 1.6+ api\n      ngModelOptions.getOption = function (key) {\n        return ngModelOptions[key];\n      };\n    } else { // in angular >=1.6 $options is always present\n      ngModelOptions = ngModelCtrl.$options;\n    }\n\n    return ngModelOptions;\n  }\n\n  $scope.$on('uib:datepicker.mode', function() {\n    $timeout(positionPopup, 0, false);\n  });\n}])\n\n.directive('uibDatepickerPopup', function() {\n  return {\n    require: ['ngModel', 'uibDatepickerPopup'],\n    controller: 'UibDatepickerPopupController',\n    scope: {\n      datepickerOptions: '=?',\n      isOpen: '=?',\n      currentText: '@',\n      clearText: '@',\n      closeText: '@'\n    },\n    link: function(scope, element, attrs, ctrls) {\n      var ngModel = ctrls[0],\n        ctrl = ctrls[1];\n\n      ctrl.init(ngModel);\n    }\n  };\n})\n\n.directive('uibDatepickerPopupWrap', function() {\n  return {\n    restrict: 'A',\n    transclude: true,\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';\n    }\n  };\n});\n\nangular.module('ui.bootstrap.debounce', [])\n/**\n * A helper, internal service that debounces a function\n */\n  .factory('$$debounce', ['$timeout', function($timeout) {\n    return function(callback, debounceTime) {\n      var timeoutPromise;\n\n      return function() {\n        var self = this;\n        var args = Array.prototype.slice.call(arguments);\n        if (timeoutPromise) {\n          $timeout.cancel(timeoutPromise);\n        }\n\n        timeoutPromise = $timeout(function() {\n          callback.apply(self, args);\n        }, debounceTime);\n      };\n    };\n  }]);\n\nangular.module('ui.bootstrap.multiMap', [])\n/**\n * A helper, internal data structure that stores all references attached to key\n */\n  .factory('$$multiMap', function() {\n    return {\n      createNew: function() {\n        var map = {};\n\n        return {\n          entries: function() {\n            return Object.keys(map).map(function(key) {\n              return {\n                key: key,\n                value: map[key]\n              };\n            });\n          },\n          get: function(key) {\n            return map[key];\n          },\n          hasKey: function(key) {\n            return !!map[key];\n          },\n          keys: function() {\n            return Object.keys(map);\n          },\n          put: function(key, value) {\n            if (!map[key]) {\n              map[key] = [];\n            }\n\n            map[key].push(value);\n          },\n          remove: function(key, value) {\n            var values = map[key];\n\n            if (!values) {\n              return;\n            }\n\n            var idx = values.indexOf(value);\n\n            if (idx !== -1) {\n              values.splice(idx, 1);\n            }\n\n            if (!values.length) {\n              delete map[key];\n            }\n          }\n        };\n      }\n    };\n  });\n\nangular.module('ui.bootstrap.dropdown', ['ui.bootstrap.multiMap', 'ui.bootstrap.position'])\n\n.constant('uibDropdownConfig', {\n  appendToOpenClass: 'uib-dropdown-open',\n  openClass: 'open'\n})\n\n.service('uibDropdownService', ['$document', '$rootScope', '$$multiMap', function($document, $rootScope, $$multiMap) {\n  var openScope = null;\n  var openedContainers = $$multiMap.createNew();\n\n  this.isOnlyOpen = function(dropdownScope, appendTo) {\n    var openedDropdowns = openedContainers.get(appendTo);\n    if (openedDropdowns) {\n      var openDropdown = openedDropdowns.reduce(function(toClose, dropdown) {\n        if (dropdown.scope === dropdownScope) {\n          return dropdown;\n        }\n\n        return toClose;\n      }, {});\n      if (openDropdown) {\n        return openedDropdowns.length === 1;\n      }\n    }\n\n    return false;\n  };\n\n  this.open = function(dropdownScope, element, appendTo) {\n    if (!openScope) {\n      $document.on('click', closeDropdown);\n    }\n\n    if (openScope && openScope !== dropdownScope) {\n      openScope.isOpen = false;\n    }\n\n    openScope = dropdownScope;\n\n    if (!appendTo) {\n      return;\n    }\n\n    var openedDropdowns = openedContainers.get(appendTo);\n    if (openedDropdowns) {\n      var openedScopes = openedDropdowns.map(function(dropdown) {\n        return dropdown.scope;\n      });\n      if (openedScopes.indexOf(dropdownScope) === -1) {\n        openedContainers.put(appendTo, {\n          scope: dropdownScope\n        });\n      }\n    } else {\n      openedContainers.put(appendTo, {\n        scope: dropdownScope\n      });\n    }\n  };\n\n  this.close = function(dropdownScope, element, appendTo) {\n    if (openScope === dropdownScope) {\n      $document.off('click', closeDropdown);\n      $document.off('keydown', this.keybindFilter);\n      openScope = null;\n    }\n\n    if (!appendTo) {\n      return;\n    }\n\n    var openedDropdowns = openedContainers.get(appendTo);\n    if (openedDropdowns) {\n      var dropdownToClose = openedDropdowns.reduce(function(toClose, dropdown) {\n        if (dropdown.scope === dropdownScope) {\n          return dropdown;\n        }\n\n        return toClose;\n      }, {});\n      if (dropdownToClose) {\n        openedContainers.remove(appendTo, dropdownToClose);\n      }\n    }\n  };\n\n  var closeDropdown = function(evt) {\n    // This method may still be called during the same mouse event that\n    // unbound this event handler. So check openScope before proceeding.\n    if (!openScope || !openScope.isOpen) { return; }\n\n    if (evt && openScope.getAutoClose() === 'disabled') { return; }\n\n    if (evt && evt.which === 3) { return; }\n\n    var toggleElement = openScope.getToggleElement();\n    if (evt && toggleElement && toggleElement[0].contains(evt.target)) {\n      return;\n    }\n\n    var dropdownElement = openScope.getDropdownElement();\n    if (evt && openScope.getAutoClose() === 'outsideClick' &&\n      dropdownElement && dropdownElement[0].contains(evt.target)) {\n      return;\n    }\n\n    openScope.focusToggleElement();\n    openScope.isOpen = false;\n\n    if (!$rootScope.$$phase) {\n      openScope.$apply();\n    }\n  };\n\n  this.keybindFilter = function(evt) {\n    if (!openScope) {\n      // see this.close as ESC could have been pressed which kills the scope so we can not proceed\n      return;\n    }\n\n    var dropdownElement = openScope.getDropdownElement();\n    var toggleElement = openScope.getToggleElement();\n    var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);\n    var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);\n    if (evt.which === 27) {\n      evt.stopPropagation();\n      openScope.focusToggleElement();\n      closeDropdown();\n    } else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      openScope.focusDropdownEntry(evt.which);\n    }\n  };\n}])\n\n.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {\n  var self = this,\n    scope = $scope.$new(), // create a child scope so we are not polluting original one\n    templateScope,\n    appendToOpenClass = dropdownConfig.appendToOpenClass,\n    openClass = dropdownConfig.openClass,\n    getIsOpen,\n    setIsOpen = angular.noop,\n    toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,\n    keynavEnabled = false,\n    selectedOption = null,\n    body = $document.find('body');\n\n  $element.addClass('dropdown');\n\n  this.init = function() {\n    if ($attrs.isOpen) {\n      getIsOpen = $parse($attrs.isOpen);\n      setIsOpen = getIsOpen.assign;\n\n      $scope.$watch(getIsOpen, function(value) {\n        scope.isOpen = !!value;\n      });\n    }\n\n    keynavEnabled = angular.isDefined($attrs.keyboardNav);\n  };\n\n  this.toggle = function(open) {\n    scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n    if (angular.isFunction(setIsOpen)) {\n      setIsOpen(scope, scope.isOpen);\n    }\n\n    return scope.isOpen;\n  };\n\n  // Allow other directives to watch status\n  this.isOpen = function() {\n    return scope.isOpen;\n  };\n\n  scope.getToggleElement = function() {\n    return self.toggleElement;\n  };\n\n  scope.getAutoClose = function() {\n    return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'\n  };\n\n  scope.getElement = function() {\n    return $element;\n  };\n\n  scope.isKeynavEnabled = function() {\n    return keynavEnabled;\n  };\n\n  scope.focusDropdownEntry = function(keyCode) {\n    var elems = self.dropdownMenu ? //If append to body is used.\n      angular.element(self.dropdownMenu).find('a') :\n      $element.find('ul').eq(0).find('a');\n\n    switch (keyCode) {\n      case 40: {\n        if (!angular.isNumber(self.selectedOption)) {\n          self.selectedOption = 0;\n        } else {\n          self.selectedOption = self.selectedOption === elems.length - 1 ?\n            self.selectedOption :\n            self.selectedOption + 1;\n        }\n        break;\n      }\n      case 38: {\n        if (!angular.isNumber(self.selectedOption)) {\n          self.selectedOption = elems.length - 1;\n        } else {\n          self.selectedOption = self.selectedOption === 0 ?\n            0 : self.selectedOption - 1;\n        }\n        break;\n      }\n    }\n    elems[self.selectedOption].focus();\n  };\n\n  scope.getDropdownElement = function() {\n    return self.dropdownMenu;\n  };\n\n  scope.focusToggleElement = function() {\n    if (self.toggleElement) {\n      self.toggleElement[0].focus();\n    }\n  };\n\n  function removeDropdownMenu() {\n    $element.append(self.dropdownMenu);\n  }\n\n  scope.$watch('isOpen', function(isOpen, wasOpen) {\n    var appendTo = null,\n      appendToBody = false;\n\n    if (angular.isDefined($attrs.dropdownAppendTo)) {\n      var appendToEl = $parse($attrs.dropdownAppendTo)(scope);\n      if (appendToEl) {\n        appendTo = angular.element(appendToEl);\n      }\n    }\n\n    if (angular.isDefined($attrs.dropdownAppendToBody)) {\n      var appendToBodyValue = $parse($attrs.dropdownAppendToBody)(scope);\n      if (appendToBodyValue !== false) {\n        appendToBody = true;\n      }\n    }\n\n    if (appendToBody && !appendTo) {\n      appendTo = body;\n    }\n\n    if (appendTo && self.dropdownMenu) {\n      if (isOpen) {\n        appendTo.append(self.dropdownMenu);\n        $element.on('$destroy', removeDropdownMenu);\n      } else {\n        $element.off('$destroy', removeDropdownMenu);\n        removeDropdownMenu();\n      }\n    }\n\n    if (appendTo && self.dropdownMenu) {\n      var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),\n        css,\n        rightalign,\n        scrollbarPadding,\n        scrollbarWidth = 0;\n\n      css = {\n        top: pos.top + 'px',\n        display: isOpen ? 'block' : 'none'\n      };\n\n      rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');\n      if (!rightalign) {\n        css.left = pos.left + 'px';\n        css.right = 'auto';\n      } else {\n        css.left = 'auto';\n        scrollbarPadding = $position.scrollbarPadding(appendTo);\n\n        if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {\n          scrollbarWidth = scrollbarPadding.scrollbarWidth;\n        }\n\n        css.right = window.innerWidth - scrollbarWidth -\n          (pos.left + $element.prop('offsetWidth')) + 'px';\n      }\n\n      // Need to adjust our positioning to be relative to the appendTo container\n      // if it's not the body element\n      if (!appendToBody) {\n        var appendOffset = $position.offset(appendTo);\n\n        css.top = pos.top - appendOffset.top + 'px';\n\n        if (!rightalign) {\n          css.left = pos.left - appendOffset.left + 'px';\n        } else {\n          css.right = window.innerWidth -\n            (pos.left - appendOffset.left + $element.prop('offsetWidth')) + 'px';\n        }\n      }\n\n      self.dropdownMenu.css(css);\n    }\n\n    var openContainer = appendTo ? appendTo : $element;\n    var dropdownOpenClass = appendTo ? appendToOpenClass : openClass;\n    var hasOpenClass = openContainer.hasClass(dropdownOpenClass);\n    var isOnlyOpen = uibDropdownService.isOnlyOpen($scope, appendTo);\n\n    if (hasOpenClass === !isOpen) {\n      var toggleClass;\n      if (appendTo) {\n        toggleClass = !isOnlyOpen ? 'addClass' : 'removeClass';\n      } else {\n        toggleClass = isOpen ? 'addClass' : 'removeClass';\n      }\n      $animate[toggleClass](openContainer, dropdownOpenClass).then(function() {\n        if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n          toggleInvoker($scope, { open: !!isOpen });\n        }\n      });\n    }\n\n    if (isOpen) {\n      if (self.dropdownMenuTemplateUrl) {\n        $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {\n          templateScope = scope.$new();\n          $compile(tplContent.trim())(templateScope, function(dropdownElement) {\n            var newEl = dropdownElement;\n            self.dropdownMenu.replaceWith(newEl);\n            self.dropdownMenu = newEl;\n            $document.on('keydown', uibDropdownService.keybindFilter);\n          });\n        });\n      } else {\n        $document.on('keydown', uibDropdownService.keybindFilter);\n      }\n\n      scope.focusToggleElement();\n      uibDropdownService.open(scope, $element, appendTo);\n    } else {\n      uibDropdownService.close(scope, $element, appendTo);\n      if (self.dropdownMenuTemplateUrl) {\n        if (templateScope) {\n          templateScope.$destroy();\n        }\n        var newEl = angular.element('<ul class=\"dropdown-menu\"></ul>');\n        self.dropdownMenu.replaceWith(newEl);\n        self.dropdownMenu = newEl;\n      }\n\n      self.selectedOption = null;\n    }\n\n    if (angular.isFunction(setIsOpen)) {\n      setIsOpen($scope, isOpen);\n    }\n  });\n}])\n\n.directive('uibDropdown', function() {\n  return {\n    controller: 'UibDropdownController',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      dropdownCtrl.init();\n    }\n  };\n})\n\n.directive('uibDropdownMenu', function() {\n  return {\n    restrict: 'A',\n    require: '?^uibDropdown',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {\n        return;\n      }\n\n      element.addClass('dropdown-menu');\n\n      var tplUrl = attrs.templateUrl;\n      if (tplUrl) {\n        dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;\n      }\n\n      if (!dropdownCtrl.dropdownMenu) {\n        dropdownCtrl.dropdownMenu = element;\n      }\n    }\n  };\n})\n\n.directive('uibDropdownToggle', function() {\n  return {\n    require: '?^uibDropdown',\n    link: function(scope, element, attrs, dropdownCtrl) {\n      if (!dropdownCtrl) {\n        return;\n      }\n\n      element.addClass('dropdown-toggle');\n\n      dropdownCtrl.toggleElement = element;\n\n      var toggleDropdown = function(event) {\n        event.preventDefault();\n\n        if (!element.hasClass('disabled') && !attrs.disabled) {\n          scope.$apply(function() {\n            dropdownCtrl.toggle();\n          });\n        }\n      };\n\n      element.on('click', toggleDropdown);\n\n      // WAI-ARIA\n      element.attr({ 'aria-haspopup': true, 'aria-expanded': false });\n      scope.$watch(dropdownCtrl.isOpen, function(isOpen) {\n        element.attr('aria-expanded', !!isOpen);\n      });\n\n      scope.$on('$destroy', function() {\n        element.off('click', toggleDropdown);\n      });\n    }\n  };\n});\n\nangular.module('ui.bootstrap.stackedMap', [])\n/**\n * A helper, internal data structure that acts as a map but also allows getting / removing\n * elements in the LIFO order\n */\n  .factory('$$stackedMap', function() {\n    return {\n      createNew: function() {\n        var stack = [];\n\n        return {\n          add: function(key, value) {\n            stack.push({\n              key: key,\n              value: value\n            });\n          },\n          get: function(key) {\n            for (var i = 0; i < stack.length; i++) {\n              if (key === stack[i].key) {\n                return stack[i];\n              }\n            }\n          },\n          keys: function() {\n            var keys = [];\n            for (var i = 0; i < stack.length; i++) {\n              keys.push(stack[i].key);\n            }\n            return keys;\n          },\n          top: function() {\n            return stack[stack.length - 1];\n          },\n          remove: function(key) {\n            var idx = -1;\n            for (var i = 0; i < stack.length; i++) {\n              if (key === stack[i].key) {\n                idx = i;\n                break;\n              }\n            }\n            return stack.splice(idx, 1)[0];\n          },\n          removeTop: function() {\n            return stack.pop();\n          },\n          length: function() {\n            return stack.length;\n          }\n        };\n      }\n    };\n  });\nangular.module('ui.bootstrap.modal', ['ui.bootstrap.multiMap', 'ui.bootstrap.stackedMap', 'ui.bootstrap.position'])\n/**\n * Pluggable resolve mechanism for the modal resolve resolution\n * Supports UI Router's $resolve service\n */\n  .provider('$uibResolve', function() {\n    var resolve = this;\n    this.resolver = null;\n\n    this.setResolver = function(resolver) {\n      this.resolver = resolver;\n    };\n\n    this.$get = ['$injector', '$q', function($injector, $q) {\n      var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null;\n      return {\n        resolve: function(invocables, locals, parent, self) {\n          if (resolver) {\n            return resolver.resolve(invocables, locals, parent, self);\n          }\n\n          var promises = [];\n\n          angular.forEach(invocables, function(value) {\n            if (angular.isFunction(value) || angular.isArray(value)) {\n              promises.push($q.resolve($injector.invoke(value)));\n            } else if (angular.isString(value)) {\n              promises.push($q.resolve($injector.get(value)));\n            } else {\n              promises.push($q.resolve(value));\n            }\n          });\n\n          return $q.all(promises).then(function(resolves) {\n            var resolveObj = {};\n            var resolveIter = 0;\n            angular.forEach(invocables, function(value, key) {\n              resolveObj[key] = resolves[resolveIter++];\n            });\n\n            return resolveObj;\n          });\n        }\n      };\n    }];\n  })\n\n/**\n * A helper directive for the $modal service. It creates a backdrop element.\n */\n  .directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',\n  function($animate, $injector, $modalStack) {\n    return {\n      restrict: 'A',\n      compile: function(tElement, tAttrs) {\n        tElement.addClass(tAttrs.backdropClass);\n        return linkFn;\n      }\n    };\n\n    function linkFn(scope, element, attrs) {\n      if (attrs.modalInClass) {\n        $animate.addClass(element, attrs.modalInClass);\n\n        scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n          var done = setIsAsync();\n          if (scope.modalOptions.animation) {\n            $animate.removeClass(element, attrs.modalInClass).then(done);\n          } else {\n            done();\n          }\n        });\n      }\n    }\n  }])\n\n  .directive('uibModalWindow', ['$uibModalStack', '$q', '$animateCss', '$document',\n  function($modalStack, $q, $animateCss, $document) {\n    return {\n      scope: {\n        index: '@'\n      },\n      restrict: 'A',\n      transclude: true,\n      templateUrl: function(tElement, tAttrs) {\n        return tAttrs.templateUrl || 'uib/template/modal/window.html';\n      },\n      link: function(scope, element, attrs) {\n        element.addClass(attrs.windowTopClass || '');\n        scope.size = attrs.size;\n\n        scope.close = function(evt) {\n          var modal = $modalStack.getTop();\n          if (modal && modal.value.backdrop &&\n            modal.value.backdrop !== 'static' &&\n            evt.target === evt.currentTarget) {\n            evt.preventDefault();\n            evt.stopPropagation();\n            $modalStack.dismiss(modal.key, 'backdrop click');\n          }\n        };\n\n        // moved from template to fix issue #2280\n        element.on('click', scope.close);\n\n        // This property is only added to the scope for the purpose of detecting when this directive is rendered.\n        // We can detect that by using this property in the template associated with this directive and then use\n        // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.\n        scope.$isRendered = true;\n\n        // Deferred object that will be resolved when this modal is rendered.\n        var modalRenderDeferObj = $q.defer();\n        // Resolve render promise post-digest\n        scope.$$postDigest(function() {\n          modalRenderDeferObj.resolve();\n        });\n\n        modalRenderDeferObj.promise.then(function() {\n          var animationPromise = null;\n\n          if (attrs.modalInClass) {\n            animationPromise = $animateCss(element, {\n              addClass: attrs.modalInClass\n            }).start();\n\n            scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n              var done = setIsAsync();\n              $animateCss(element, {\n                removeClass: attrs.modalInClass\n              }).start().then(done);\n            });\n          }\n\n\n          $q.when(animationPromise).then(function() {\n            // Notify {@link $modalStack} that modal is rendered.\n            var modal = $modalStack.getTop();\n            if (modal) {\n              $modalStack.modalRendered(modal.key);\n            }\n\n            /**\n             * If something within the freshly-opened modal already has focus (perhaps via a\n             * directive that causes focus) then there's no need to try to focus anything.\n             */\n            if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {\n              var inputWithAutofocus = element[0].querySelector('[autofocus]');\n              /**\n               * Auto-focusing of a freshly-opened modal element causes any child elements\n               * with the autofocus attribute to lose focus. This is an issue on touch\n               * based devices which will show and then hide the onscreen keyboard.\n               * Attempts to refocus the autofocus element via JavaScript will not reopen\n               * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus\n               * the modal element if the modal does not contain an autofocus element.\n               */\n              if (inputWithAutofocus) {\n                inputWithAutofocus.focus();\n              } else {\n                element[0].focus();\n              }\n            }\n          });\n        });\n      }\n    };\n  }])\n\n  .directive('uibModalAnimationClass', function() {\n    return {\n      compile: function(tElement, tAttrs) {\n        if (tAttrs.modalAnimation) {\n          tElement.addClass(tAttrs.uibModalAnimationClass);\n        }\n      }\n    };\n  })\n\n  .directive('uibModalTransclude', ['$animate', function($animate) {\n    return {\n      link: function(scope, element, attrs, controller, transclude) {\n        transclude(scope.$parent, function(clone) {\n          element.empty();\n          $animate.enter(clone, element);\n        });\n      }\n    };\n  }])\n\n  .factory('$uibModalStack', ['$animate', '$animateCss', '$document',\n    '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',\n    function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap, $uibPosition) {\n      var OPENED_MODAL_CLASS = 'modal-open';\n\n      var backdropDomEl, backdropScope;\n      var openedWindows = $$stackedMap.createNew();\n      var openedClasses = $$multiMap.createNew();\n      var $modalStack = {\n        NOW_CLOSING_EVENT: 'modal.stack.now-closing'\n      };\n      var topModalIndex = 0;\n      var previousTopOpenedModal = null;\n      var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';\n\n      //Modal focus behavior\n      var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\\'-1\\']), ' +\n        'button:not([disabled]):not([tabindex=\\'-1\\']),select:not([disabled]):not([tabindex=\\'-1\\']), textarea:not([disabled]):not([tabindex=\\'-1\\']), ' +\n        'iframe, object, embed, *[tabindex]:not([tabindex=\\'-1\\']), *[contenteditable=true]';\n      var scrollbarPadding;\n      var SNAKE_CASE_REGEXP = /[A-Z]/g;\n\n      // TODO: extract into common dependency with tooltip\n      function snake_case(name) {\n        var separator = '-';\n        return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n          return (pos ? separator : '') + letter.toLowerCase();\n        });\n      }\n\n      function isVisible(element) {\n        return !!(element.offsetWidth ||\n          element.offsetHeight ||\n          element.getClientRects().length);\n      }\n\n      function backdropIndex() {\n        var topBackdropIndex = -1;\n        var opened = openedWindows.keys();\n        for (var i = 0; i < opened.length; i++) {\n          if (openedWindows.get(opened[i]).value.backdrop) {\n            topBackdropIndex = i;\n          }\n        }\n\n        // If any backdrop exist, ensure that it's index is always\n        // right below the top modal\n        if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {\n          topBackdropIndex = topModalIndex;\n        }\n        return topBackdropIndex;\n      }\n\n      $rootScope.$watch(backdropIndex, function(newBackdropIndex) {\n        if (backdropScope) {\n          backdropScope.index = newBackdropIndex;\n        }\n      });\n\n      function removeModalWindow(modalInstance, elementToReceiveFocus) {\n        var modalWindow = openedWindows.get(modalInstance).value;\n        var appendToElement = modalWindow.appendTo;\n\n        //clean up the stack\n        openedWindows.remove(modalInstance);\n        previousTopOpenedModal = openedWindows.top();\n        if (previousTopOpenedModal) {\n          topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);\n        }\n\n        removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {\n          var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;\n          openedClasses.remove(modalBodyClass, modalInstance);\n          var areAnyOpen = openedClasses.hasKey(modalBodyClass);\n          appendToElement.toggleClass(modalBodyClass, areAnyOpen);\n          if (!areAnyOpen && scrollbarPadding && scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {\n            if (scrollbarPadding.originalRight) {\n              appendToElement.css({paddingRight: scrollbarPadding.originalRight + 'px'});\n            } else {\n              appendToElement.css({paddingRight: ''});\n            }\n            scrollbarPadding = null;\n          }\n          toggleTopWindowClass(true);\n        }, modalWindow.closedDeferred);\n        checkRemoveBackdrop();\n\n        //move focus to specified element if available, or else to body\n        if (elementToReceiveFocus && elementToReceiveFocus.focus) {\n          elementToReceiveFocus.focus();\n        } else if (appendToElement.focus) {\n          appendToElement.focus();\n        }\n      }\n\n      // Add or remove \"windowTopClass\" from the top window in the stack\n      function toggleTopWindowClass(toggleSwitch) {\n        var modalWindow;\n\n        if (openedWindows.length() > 0) {\n          modalWindow = openedWindows.top().value;\n          modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);\n        }\n      }\n\n      function checkRemoveBackdrop() {\n        //remove backdrop if no longer needed\n        if (backdropDomEl && backdropIndex() === -1) {\n          var backdropScopeRef = backdropScope;\n          removeAfterAnimate(backdropDomEl, backdropScope, function() {\n            backdropScopeRef = null;\n          });\n          backdropDomEl = undefined;\n          backdropScope = undefined;\n        }\n      }\n\n      function removeAfterAnimate(domEl, scope, done, closedDeferred) {\n        var asyncDeferred;\n        var asyncPromise = null;\n        var setIsAsync = function() {\n          if (!asyncDeferred) {\n            asyncDeferred = $q.defer();\n            asyncPromise = asyncDeferred.promise;\n          }\n\n          return function asyncDone() {\n            asyncDeferred.resolve();\n          };\n        };\n        scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);\n\n        // Note that it's intentional that asyncPromise might be null.\n        // That's when setIsAsync has not been called during the\n        // NOW_CLOSING_EVENT broadcast.\n        return $q.when(asyncPromise).then(afterAnimating);\n\n        function afterAnimating() {\n          if (afterAnimating.done) {\n            return;\n          }\n          afterAnimating.done = true;\n\n          $animate.leave(domEl).then(function() {\n            if (done) {\n              done();\n            }\n\n            domEl.remove();\n            if (closedDeferred) {\n              closedDeferred.resolve();\n            }\n          });\n\n          scope.$destroy();\n        }\n      }\n\n      $document.on('keydown', keydownListener);\n\n      $rootScope.$on('$destroy', function() {\n        $document.off('keydown', keydownListener);\n      });\n\n      function keydownListener(evt) {\n        if (evt.isDefaultPrevented()) {\n          return evt;\n        }\n\n        var modal = openedWindows.top();\n        if (modal) {\n          switch (evt.which) {\n            case 27: {\n              if (modal.value.keyboard) {\n                evt.preventDefault();\n                $rootScope.$apply(function() {\n                  $modalStack.dismiss(modal.key, 'escape key press');\n                });\n              }\n              break;\n            }\n            case 9: {\n              var list = $modalStack.loadFocusElementList(modal);\n              var focusChanged = false;\n              if (evt.shiftKey) {\n                if ($modalStack.isFocusInFirstItem(evt, list) || $modalStack.isModalFocused(evt, modal)) {\n                  focusChanged = $modalStack.focusLastFocusableElement(list);\n                }\n              } else {\n                if ($modalStack.isFocusInLastItem(evt, list)) {\n                  focusChanged = $modalStack.focusFirstFocusableElement(list);\n                }\n              }\n\n              if (focusChanged) {\n                evt.preventDefault();\n                evt.stopPropagation();\n              }\n\n              break;\n            }\n          }\n        }\n      }\n\n      $modalStack.open = function(modalInstance, modal) {\n        var modalOpener = $document[0].activeElement,\n          modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;\n\n        toggleTopWindowClass(false);\n\n        // Store the current top first, to determine what index we ought to use\n        // for the current top modal\n        previousTopOpenedModal = openedWindows.top();\n\n        openedWindows.add(modalInstance, {\n          deferred: modal.deferred,\n          renderDeferred: modal.renderDeferred,\n          closedDeferred: modal.closedDeferred,\n          modalScope: modal.scope,\n          backdrop: modal.backdrop,\n          keyboard: modal.keyboard,\n          openedClass: modal.openedClass,\n          windowTopClass: modal.windowTopClass,\n          animation: modal.animation,\n          appendTo: modal.appendTo\n        });\n\n        openedClasses.put(modalBodyClass, modalInstance);\n\n        var appendToElement = modal.appendTo,\n            currBackdropIndex = backdropIndex();\n\n        if (currBackdropIndex >= 0 && !backdropDomEl) {\n          backdropScope = $rootScope.$new(true);\n          backdropScope.modalOptions = modal;\n          backdropScope.index = currBackdropIndex;\n          backdropDomEl = angular.element('<div uib-modal-backdrop=\"modal-backdrop\"></div>');\n          backdropDomEl.attr({\n            'class': 'modal-backdrop',\n            'ng-style': '{\\'z-index\\': 1040 + (index && 1 || 0) + index*10}',\n            'uib-modal-animation-class': 'fade',\n            'modal-in-class': 'in'\n          });\n          if (modal.backdropClass) {\n            backdropDomEl.addClass(modal.backdropClass);\n          }\n\n          if (modal.animation) {\n            backdropDomEl.attr('modal-animation', 'true');\n          }\n          $compile(backdropDomEl)(backdropScope);\n          $animate.enter(backdropDomEl, appendToElement);\n          if ($uibPosition.isScrollable(appendToElement)) {\n            scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);\n            if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {\n              appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});\n            }\n          }\n        }\n\n        var content;\n        if (modal.component) {\n          content = document.createElement(snake_case(modal.component.name));\n          content = angular.element(content);\n          content.attr({\n            resolve: '$resolve',\n            'modal-instance': '$uibModalInstance',\n            close: '$close($value)',\n            dismiss: '$dismiss($value)'\n          });\n        } else {\n          content = modal.content;\n        }\n\n        // Set the top modal index based on the index of the previous top modal\n        topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;\n        var angularDomEl = angular.element('<div uib-modal-window=\"modal-window\"></div>');\n        angularDomEl.attr({\n          'class': 'modal',\n          'template-url': modal.windowTemplateUrl,\n          'window-top-class': modal.windowTopClass,\n          'role': 'dialog',\n          'aria-labelledby': modal.ariaLabelledBy,\n          'aria-describedby': modal.ariaDescribedBy,\n          'size': modal.size,\n          'index': topModalIndex,\n          'animate': 'animate',\n          'ng-style': '{\\'z-index\\': 1050 + $$topModalIndex*10, display: \\'block\\'}',\n          'tabindex': -1,\n          'uib-modal-animation-class': 'fade',\n          'modal-in-class': 'in'\n        }).append(content);\n        if (modal.windowClass) {\n          angularDomEl.addClass(modal.windowClass);\n        }\n\n        if (modal.animation) {\n          angularDomEl.attr('modal-animation', 'true');\n        }\n\n        appendToElement.addClass(modalBodyClass);\n        if (modal.scope) {\n          // we need to explicitly add the modal index to the modal scope\n          // because it is needed by ngStyle to compute the zIndex property.\n          modal.scope.$$topModalIndex = topModalIndex;\n        }\n        $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);\n\n        openedWindows.top().value.modalDomEl = angularDomEl;\n        openedWindows.top().value.modalOpener = modalOpener;\n\n        applyAriaHidden(angularDomEl);\n\n        function applyAriaHidden(el) {\n          if (!el || el[0].tagName === 'BODY') {\n            return;\n          }\n\n          getSiblings(el).forEach(function(sibling) {\n            var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',\n              ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);\n\n            if (!ariaHiddenCount) {\n              ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;\n            }\n\n            sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);\n            sibling.setAttribute('aria-hidden', 'true');\n          });\n\n          return applyAriaHidden(el.parent());\n\n          function getSiblings(el) {\n            var children = el.parent() ? el.parent().children() : [];\n\n            return Array.prototype.filter.call(children, function(child) {\n              return child !== el[0];\n            });\n          }\n        }\n      };\n\n      function broadcastClosing(modalWindow, resultOrReason, closing) {\n        return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;\n      }\n\n      function unhideBackgroundElements() {\n        Array.prototype.forEach.call(\n          document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),\n          function(hiddenEl) {\n            var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),\n              newHiddenCount = ariaHiddenCount - 1;\n            hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);\n\n            if (!newHiddenCount) {\n              hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);\n              hiddenEl.removeAttribute('aria-hidden');\n            }\n          }\n        );\n      }\n\n      $modalStack.close = function(modalInstance, result) {\n        var modalWindow = openedWindows.get(modalInstance);\n        unhideBackgroundElements();\n        if (modalWindow && broadcastClosing(modalWindow, result, true)) {\n          modalWindow.value.modalScope.$$uibDestructionScheduled = true;\n          modalWindow.value.deferred.resolve(result);\n          removeModalWindow(modalInstance, modalWindow.value.modalOpener);\n          return true;\n        }\n\n        return !modalWindow;\n      };\n\n      $modalStack.dismiss = function(modalInstance, reason) {\n        var modalWindow = openedWindows.get(modalInstance);\n        unhideBackgroundElements();\n        if (modalWindow && broadcastClosing(modalWindow, reason, false)) {\n          modalWindow.value.modalScope.$$uibDestructionScheduled = true;\n          modalWindow.value.deferred.reject(reason);\n          removeModalWindow(modalInstance, modalWindow.value.modalOpener);\n          return true;\n        }\n        return !modalWindow;\n      };\n\n      $modalStack.dismissAll = function(reason) {\n        var topModal = this.getTop();\n        while (topModal && this.dismiss(topModal.key, reason)) {\n          topModal = this.getTop();\n        }\n      };\n\n      $modalStack.getTop = function() {\n        return openedWindows.top();\n      };\n\n      $modalStack.modalRendered = function(modalInstance) {\n        var modalWindow = openedWindows.get(modalInstance);\n        if (modalWindow) {\n          modalWindow.value.renderDeferred.resolve();\n        }\n      };\n\n      $modalStack.focusFirstFocusableElement = function(list) {\n        if (list.length > 0) {\n          list[0].focus();\n          return true;\n        }\n        return false;\n      };\n\n      $modalStack.focusLastFocusableElement = function(list) {\n        if (list.length > 0) {\n          list[list.length - 1].focus();\n          return true;\n        }\n        return false;\n      };\n\n      $modalStack.isModalFocused = function(evt, modalWindow) {\n        if (evt && modalWindow) {\n          var modalDomEl = modalWindow.value.modalDomEl;\n          if (modalDomEl && modalDomEl.length) {\n            return (evt.target || evt.srcElement) === modalDomEl[0];\n          }\n        }\n        return false;\n      };\n\n      $modalStack.isFocusInFirstItem = function(evt, list) {\n        if (list.length > 0) {\n          return (evt.target || evt.srcElement) === list[0];\n        }\n        return false;\n      };\n\n      $modalStack.isFocusInLastItem = function(evt, list) {\n        if (list.length > 0) {\n          return (evt.target || evt.srcElement) === list[list.length - 1];\n        }\n        return false;\n      };\n\n      $modalStack.loadFocusElementList = function(modalWindow) {\n        if (modalWindow) {\n          var modalDomE1 = modalWindow.value.modalDomEl;\n          if (modalDomE1 && modalDomE1.length) {\n            var elements = modalDomE1[0].querySelectorAll(tabbableSelector);\n            return elements ?\n              Array.prototype.filter.call(elements, function(element) {\n                return isVisible(element);\n              }) : elements;\n          }\n        }\n      };\n\n      return $modalStack;\n    }])\n\n  .provider('$uibModal', function() {\n    var $modalProvider = {\n      options: {\n        animation: true,\n        backdrop: true, //can also be false or 'static'\n        keyboard: true\n      },\n      $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$uibResolve', '$uibModalStack',\n        function ($rootScope, $q, $document, $templateRequest, $controller, $uibResolve, $modalStack) {\n          var $modal = {};\n\n          function getTemplatePromise(options) {\n            return options.template ? $q.when(options.template) :\n              $templateRequest(angular.isFunction(options.templateUrl) ?\n                options.templateUrl() : options.templateUrl);\n          }\n\n          var promiseChain = null;\n          $modal.getPromiseChain = function() {\n            return promiseChain;\n          };\n\n          $modal.open = function(modalOptions) {\n            var modalResultDeferred = $q.defer();\n            var modalOpenedDeferred = $q.defer();\n            var modalClosedDeferred = $q.defer();\n            var modalRenderDeferred = $q.defer();\n\n            //prepare an instance of a modal to be injected into controllers and returned to a caller\n            var modalInstance = {\n              result: modalResultDeferred.promise,\n              opened: modalOpenedDeferred.promise,\n              closed: modalClosedDeferred.promise,\n              rendered: modalRenderDeferred.promise,\n              close: function (result) {\n                return $modalStack.close(modalInstance, result);\n              },\n              dismiss: function (reason) {\n                return $modalStack.dismiss(modalInstance, reason);\n              }\n            };\n\n            //merge and clean up options\n            modalOptions = angular.extend({}, $modalProvider.options, modalOptions);\n            modalOptions.resolve = modalOptions.resolve || {};\n            modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0);\n\n            if (!modalOptions.appendTo.length) {\n              throw new Error('appendTo element not found. Make sure that the element passed is in DOM.');\n            }\n\n            //verify options\n            if (!modalOptions.component && !modalOptions.template && !modalOptions.templateUrl) {\n              throw new Error('One of component or template or templateUrl options is required.');\n            }\n\n            var templateAndResolvePromise;\n            if (modalOptions.component) {\n              templateAndResolvePromise = $q.when($uibResolve.resolve(modalOptions.resolve, {}, null, null));\n            } else {\n              templateAndResolvePromise =\n                $q.all([getTemplatePromise(modalOptions), $uibResolve.resolve(modalOptions.resolve, {}, null, null)]);\n            }\n\n            function resolveWithTemplate() {\n              return templateAndResolvePromise;\n            }\n\n            // Wait for the resolution of the existing promise chain.\n            // Then switch to our own combined promise dependency (regardless of how the previous modal fared).\n            // Then add to $modalStack and resolve opened.\n            // Finally clean up the chain variable if no subsequent modal has overwritten it.\n            var samePromise;\n            samePromise = promiseChain = $q.all([promiseChain])\n              .then(resolveWithTemplate, resolveWithTemplate)\n              .then(function resolveSuccess(tplAndVars) {\n                var providedScope = modalOptions.scope || $rootScope;\n\n                var modalScope = providedScope.$new();\n                modalScope.$close = modalInstance.close;\n                modalScope.$dismiss = modalInstance.dismiss;\n\n                modalScope.$on('$destroy', function() {\n                  if (!modalScope.$$uibDestructionScheduled) {\n                    modalScope.$dismiss('$uibUnscheduledDestruction');\n                  }\n                });\n\n                var modal = {\n                  scope: modalScope,\n                  deferred: modalResultDeferred,\n                  renderDeferred: modalRenderDeferred,\n                  closedDeferred: modalClosedDeferred,\n                  animation: modalOptions.animation,\n                  backdrop: modalOptions.backdrop,\n                  keyboard: modalOptions.keyboard,\n                  backdropClass: modalOptions.backdropClass,\n                  windowTopClass: modalOptions.windowTopClass,\n                  windowClass: modalOptions.windowClass,\n                  windowTemplateUrl: modalOptions.windowTemplateUrl,\n                  ariaLabelledBy: modalOptions.ariaLabelledBy,\n                  ariaDescribedBy: modalOptions.ariaDescribedBy,\n                  size: modalOptions.size,\n                  openedClass: modalOptions.openedClass,\n                  appendTo: modalOptions.appendTo\n                };\n\n                var component = {};\n                var ctrlInstance, ctrlInstantiate, ctrlLocals = {};\n\n                if (modalOptions.component) {\n                  constructLocals(component, false, true, false);\n                  component.name = modalOptions.component;\n                  modal.component = component;\n                } else if (modalOptions.controller) {\n                  constructLocals(ctrlLocals, true, false, true);\n\n                  // the third param will make the controller instantiate later,private api\n                  // @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126\n                  ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);\n                  if (modalOptions.controllerAs && modalOptions.bindToController) {\n                    ctrlInstance = ctrlInstantiate.instance;\n                    ctrlInstance.$close = modalScope.$close;\n                    ctrlInstance.$dismiss = modalScope.$dismiss;\n                    angular.extend(ctrlInstance, {\n                      $resolve: ctrlLocals.$scope.$resolve\n                    }, providedScope);\n                  }\n\n                  ctrlInstance = ctrlInstantiate();\n\n                  if (angular.isFunction(ctrlInstance.$onInit)) {\n                    ctrlInstance.$onInit();\n                  }\n                }\n\n                if (!modalOptions.component) {\n                  modal.content = tplAndVars[0];\n                }\n\n                $modalStack.open(modalInstance, modal);\n                modalOpenedDeferred.resolve(true);\n\n                function constructLocals(obj, template, instanceOnScope, injectable) {\n                  obj.$scope = modalScope;\n                  obj.$scope.$resolve = {};\n                  if (instanceOnScope) {\n                    obj.$scope.$uibModalInstance = modalInstance;\n                  } else {\n                    obj.$uibModalInstance = modalInstance;\n                  }\n\n                  var resolves = template ? tplAndVars[1] : tplAndVars;\n                  angular.forEach(resolves, function(value, key) {\n                    if (injectable) {\n                      obj[key] = value;\n                    }\n\n                    obj.$scope.$resolve[key] = value;\n                  });\n                }\n            }, function resolveError(reason) {\n              modalOpenedDeferred.reject(reason);\n              modalResultDeferred.reject(reason);\n            })['finally'](function() {\n              if (promiseChain === samePromise) {\n                promiseChain = null;\n              }\n            });\n\n            return modalInstance;\n          };\n\n          return $modal;\n        }\n      ]\n    };\n\n    return $modalProvider;\n  });\n\nangular.module('ui.bootstrap.paging', [])\n/**\n * Helper internal service for generating common controller code between the\n * pager and pagination components\n */\n.factory('uibPaging', ['$parse', function($parse) {\n  return {\n    create: function(ctrl, $scope, $attrs) {\n      ctrl.setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;\n      ctrl.ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl\n      ctrl._watchers = [];\n\n      ctrl.init = function(ngModelCtrl, config) {\n        ctrl.ngModelCtrl = ngModelCtrl;\n        ctrl.config = config;\n\n        ngModelCtrl.$render = function() {\n          ctrl.render();\n        };\n\n        if ($attrs.itemsPerPage) {\n          ctrl._watchers.push($scope.$parent.$watch($attrs.itemsPerPage, function(value) {\n            ctrl.itemsPerPage = parseInt(value, 10);\n            $scope.totalPages = ctrl.calculateTotalPages();\n            ctrl.updatePage();\n          }));\n        } else {\n          ctrl.itemsPerPage = config.itemsPerPage;\n        }\n\n        $scope.$watch('totalItems', function(newTotal, oldTotal) {\n          if (angular.isDefined(newTotal) || newTotal !== oldTotal) {\n            $scope.totalPages = ctrl.calculateTotalPages();\n            ctrl.updatePage();\n          }\n        });\n      };\n\n      ctrl.calculateTotalPages = function() {\n        var totalPages = ctrl.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / ctrl.itemsPerPage);\n        return Math.max(totalPages || 0, 1);\n      };\n\n      ctrl.render = function() {\n        $scope.page = parseInt(ctrl.ngModelCtrl.$viewValue, 10) || 1;\n      };\n\n      $scope.selectPage = function(page, evt) {\n        if (evt) {\n          evt.preventDefault();\n        }\n\n        var clickAllowed = !$scope.ngDisabled || !evt;\n        if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {\n          if (evt && evt.target) {\n            evt.target.blur();\n          }\n          ctrl.ngModelCtrl.$setViewValue(page);\n          ctrl.ngModelCtrl.$render();\n        }\n      };\n\n      $scope.getText = function(key) {\n        return $scope[key + 'Text'] || ctrl.config[key + 'Text'];\n      };\n\n      $scope.noPrevious = function() {\n        return $scope.page === 1;\n      };\n\n      $scope.noNext = function() {\n        return $scope.page === $scope.totalPages;\n      };\n\n      ctrl.updatePage = function() {\n        ctrl.setNumPages($scope.$parent, $scope.totalPages); // Readonly variable\n\n        if ($scope.page > $scope.totalPages) {\n          $scope.selectPage($scope.totalPages);\n        } else {\n          ctrl.ngModelCtrl.$render();\n        }\n      };\n\n      $scope.$on('$destroy', function() {\n        while (ctrl._watchers.length) {\n          ctrl._watchers.shift()();\n        }\n      });\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])\n\n.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) {\n  $scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;\n\n  uibPaging.create(this, $scope, $attrs);\n}])\n\n.constant('uibPagerConfig', {\n  itemsPerPage: 10,\n  previousText: '« Previous',\n  nextText: 'Next »',\n  align: true\n})\n\n.directive('uibPager', ['uibPagerConfig', function(uibPagerConfig) {\n  return {\n    scope: {\n      totalItems: '=',\n      previousText: '@',\n      nextText: '@',\n      ngDisabled: '='\n    },\n    require: ['uibPager', '?ngModel'],\n    restrict: 'A',\n    controller: 'UibPagerController',\n    controllerAs: 'pager',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/pager/pager.html';\n    },\n    link: function(scope, element, attrs, ctrls) {\n      element.addClass('pager');\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n        return; // do nothing if no ng-model\n      }\n\n      paginationCtrl.init(ngModelCtrl, uibPagerConfig);\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])\n.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {\n  var ctrl = this;\n  // Setup configuration parameters\n  var maxSize = angular.isDefined($attrs.maxSize) ? $scope.$parent.$eval($attrs.maxSize) : uibPaginationConfig.maxSize,\n    rotate = angular.isDefined($attrs.rotate) ? $scope.$parent.$eval($attrs.rotate) : uibPaginationConfig.rotate,\n    forceEllipses = angular.isDefined($attrs.forceEllipses) ? $scope.$parent.$eval($attrs.forceEllipses) : uibPaginationConfig.forceEllipses,\n    boundaryLinkNumbers = angular.isDefined($attrs.boundaryLinkNumbers) ? $scope.$parent.$eval($attrs.boundaryLinkNumbers) : uibPaginationConfig.boundaryLinkNumbers,\n    pageLabel = angular.isDefined($attrs.pageLabel) ? function(idx) { return $scope.$parent.$eval($attrs.pageLabel, {$page: idx}); } : angular.identity;\n  $scope.boundaryLinks = angular.isDefined($attrs.boundaryLinks) ? $scope.$parent.$eval($attrs.boundaryLinks) : uibPaginationConfig.boundaryLinks;\n  $scope.directionLinks = angular.isDefined($attrs.directionLinks) ? $scope.$parent.$eval($attrs.directionLinks) : uibPaginationConfig.directionLinks;\n  $attrs.$set('role', 'menu');\n\n  uibPaging.create(this, $scope, $attrs);\n\n  if ($attrs.maxSize) {\n    ctrl._watchers.push($scope.$parent.$watch($parse($attrs.maxSize), function(value) {\n      maxSize = parseInt(value, 10);\n      ctrl.render();\n    }));\n  }\n\n  // Create page object used in template\n  function makePage(number, text, isActive) {\n    return {\n      number: number,\n      text: text,\n      active: isActive\n    };\n  }\n\n  function getPages(currentPage, totalPages) {\n    var pages = [];\n\n    // Default page limits\n    var startPage = 1, endPage = totalPages;\n    var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;\n\n    // recompute if maxSize\n    if (isMaxSized) {\n      if (rotate) {\n        // Current page is displayed in the middle of the visible ones\n        startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);\n        endPage = startPage + maxSize - 1;\n\n        // Adjust if limit is exceeded\n        if (endPage > totalPages) {\n          endPage = totalPages;\n          startPage = endPage - maxSize + 1;\n        }\n      } else {\n        // Visible pages are paginated with maxSize\n        startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1;\n\n        // Adjust last page if limit is exceeded\n        endPage = Math.min(startPage + maxSize - 1, totalPages);\n      }\n    }\n\n    // Add page number links\n    for (var number = startPage; number <= endPage; number++) {\n      var page = makePage(number, pageLabel(number), number === currentPage);\n      pages.push(page);\n    }\n\n    // Add links to move between page sets\n    if (isMaxSized && maxSize > 0 && (!rotate || forceEllipses || boundaryLinkNumbers)) {\n      if (startPage > 1) {\n        if (!boundaryLinkNumbers || startPage > 3) { //need ellipsis for all options unless range is too close to beginning\n        var previousPageSet = makePage(startPage - 1, '...', false);\n        pages.unshift(previousPageSet);\n      }\n        if (boundaryLinkNumbers) {\n          if (startPage === 3) { //need to replace ellipsis when the buttons would be sequential\n            var secondPageLink = makePage(2, '2', false);\n            pages.unshift(secondPageLink);\n          }\n          //add the first page\n          var firstPageLink = makePage(1, '1', false);\n          pages.unshift(firstPageLink);\n        }\n      }\n\n      if (endPage < totalPages) {\n        if (!boundaryLinkNumbers || endPage < totalPages - 2) { //need ellipsis for all options unless range is too close to end\n        var nextPageSet = makePage(endPage + 1, '...', false);\n        pages.push(nextPageSet);\n      }\n        if (boundaryLinkNumbers) {\n          if (endPage === totalPages - 2) { //need to replace ellipsis when the buttons would be sequential\n            var secondToLastPageLink = makePage(totalPages - 1, totalPages - 1, false);\n            pages.push(secondToLastPageLink);\n          }\n          //add the last page\n          var lastPageLink = makePage(totalPages, totalPages, false);\n          pages.push(lastPageLink);\n        }\n      }\n    }\n    return pages;\n  }\n\n  var originalRender = this.render;\n  this.render = function() {\n    originalRender();\n    if ($scope.page > 0 && $scope.page <= $scope.totalPages) {\n      $scope.pages = getPages($scope.page, $scope.totalPages);\n    }\n  };\n}])\n\n.constant('uibPaginationConfig', {\n  itemsPerPage: 10,\n  boundaryLinks: false,\n  boundaryLinkNumbers: false,\n  directionLinks: true,\n  firstText: 'First',\n  previousText: 'Previous',\n  nextText: 'Next',\n  lastText: 'Last',\n  rotate: true,\n  forceEllipses: false\n})\n\n.directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, uibPaginationConfig) {\n  return {\n    scope: {\n      totalItems: '=',\n      firstText: '@',\n      previousText: '@',\n      nextText: '@',\n      lastText: '@',\n      ngDisabled:'='\n    },\n    require: ['uibPagination', '?ngModel'],\n    restrict: 'A',\n    controller: 'UibPaginationController',\n    controllerAs: 'pagination',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/pagination/pagination.html';\n    },\n    link: function(scope, element, attrs, ctrls) {\n      element.addClass('pagination');\n      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (!ngModelCtrl) {\n         return; // do nothing if no ng-model\n      }\n\n      paginationCtrl.init(ngModelCtrl, uibPaginationConfig);\n    }\n  };\n}]);\n\n/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider('$uibTooltip', function() {\n  // The default options tooltip and popover.\n  var defaultOptions = {\n    placement: 'top',\n    placementClassPrefix: '',\n    animation: true,\n    popupDelay: 0,\n    popupCloseDelay: 0,\n    useContentExp: false\n  };\n\n  // Default hide triggers for each show trigger\n  var triggerMap = {\n    'mouseenter': 'mouseleave',\n    'click': 'click',\n    'outsideClick': 'outsideClick',\n    'focus': 'blur',\n    'none': ''\n  };\n\n  // The options specified to the provider globally.\n  var globalOptions = {};\n\n  /**\n   * `options({})` allows global configuration of all tooltips in the\n   * application.\n   *\n   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n   *     // place tooltips left instead of top by default\n   *     $tooltipProvider.options( { placement: 'left' } );\n   *   });\n   */\n\tthis.options = function(value) {\n\t\tangular.extend(globalOptions, value);\n\t};\n\n  /**\n   * This allows you to extend the set of trigger mappings available. E.g.:\n   *\n   *   $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );\n   */\n  this.setTriggers = function setTriggers(triggers) {\n    angular.extend(triggerMap, triggers);\n  };\n\n  /**\n   * This is a helper function for translating camel-case to snake_case.\n   */\n  function snake_case(name) {\n    var regexp = /[A-Z]/g;\n    var separator = '-';\n    return name.replace(regexp, function(letter, pos) {\n      return (pos ? separator : '') + letter.toLowerCase();\n    });\n  }\n\n  /**\n   * Returns the actual instance of the $tooltip service.\n   * TODO support multiple triggers\n   */\n  this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {\n    var openedTooltips = $$stackedMap.createNew();\n    $document.on('keyup', keypressListener);\n\n    $rootScope.$on('$destroy', function() {\n      $document.off('keyup', keypressListener);\n    });\n\n    function keypressListener(e) {\n      if (e.which === 27) {\n        var last = openedTooltips.top();\n        if (last) {\n          last.value.close();\n          last = null;\n        }\n      }\n    }\n\n    return function $tooltip(ttType, prefix, defaultTriggerShow, options) {\n      options = angular.extend({}, defaultOptions, globalOptions, options);\n\n      /**\n       * Returns an object of show and hide triggers.\n       *\n       * If a trigger is supplied,\n       * it is used to show the tooltip; otherwise, it will use the `trigger`\n       * option passed to the `$tooltipProvider.options` method; else it will\n       * default to the trigger supplied to this directive factory.\n       *\n       * The hide trigger is based on the show trigger. If the `trigger` option\n       * was passed to the `$tooltipProvider.options` method, it will use the\n       * mapped trigger from `triggerMap` or the passed trigger if the map is\n       * undefined; otherwise, it uses the `triggerMap` value of the show\n       * trigger; else it will just use the show trigger.\n       */\n      function getTriggers(trigger) {\n        var show = (trigger || options.trigger || defaultTriggerShow).split(' ');\n        var hide = show.map(function(trigger) {\n          return triggerMap[trigger] || trigger;\n        });\n        return {\n          show: show,\n          hide: hide\n        };\n      }\n\n      var directiveName = snake_case(ttType);\n\n      var startSym = $interpolate.startSymbol();\n      var endSym = $interpolate.endSymbol();\n      var template =\n        '<div '+ directiveName + '-popup ' +\n          'uib-title=\"' + startSym + 'title' + endSym + '\" ' +\n          (options.useContentExp ?\n            'content-exp=\"contentExp()\" ' :\n            'content=\"' + startSym + 'content' + endSym + '\" ') +\n          'origin-scope=\"origScope\" ' +\n          'class=\"uib-position-measure ' + prefix + '\" ' +\n          'tooltip-animation-class=\"fade\"' +\n          'uib-tooltip-classes ' +\n          'ng-class=\"{ in: isOpen }\" ' +\n          '>' +\n        '</div>';\n\n      return {\n        compile: function(tElem, tAttrs) {\n          var tooltipLinker = $compile(template);\n\n          return function link(scope, element, attrs, tooltipCtrl) {\n            var tooltip;\n            var tooltipLinkedScope;\n            var transitionTimeout;\n            var showTimeout;\n            var hideTimeout;\n            var positionTimeout;\n            var adjustmentTimeout;\n            var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;\n            var triggers = getTriggers(undefined);\n            var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);\n            var ttScope = scope.$new(true);\n            var repositionScheduled = false;\n            var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;\n            var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;\n            var observers = [];\n            var lastPlacement;\n\n            var positionTooltip = function() {\n              // check if tooltip exists and is not empty\n              if (!tooltip || !tooltip.html()) { return; }\n\n              if (!positionTimeout) {\n                positionTimeout = $timeout(function() {\n                  var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);\n                  var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');\n                  var elementPos = appendToBody ? $position.offset(element) : $position.position(element);\n                  tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });\n                  var placementClasses = ttPosition.placement.split('-');\n\n                  if (!tooltip.hasClass(placementClasses[0])) {\n                    tooltip.removeClass(lastPlacement.split('-')[0]);\n                    tooltip.addClass(placementClasses[0]);\n                  }\n\n                  if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {\n                    tooltip.removeClass(options.placementClassPrefix + lastPlacement);\n                    tooltip.addClass(options.placementClassPrefix + ttPosition.placement);\n                  }\n\n                  adjustmentTimeout = $timeout(function() {\n                    var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');\n                    var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);\n                    if (adjustment) {\n                      tooltip.css(adjustment);\n                    }\n                    adjustmentTimeout = null;\n                  }, 0, false);\n\n                  // first time through tt element will have the\n                  // uib-position-measure class or if the placement\n                  // has changed we need to position the arrow.\n                  if (tooltip.hasClass('uib-position-measure')) {\n                    $position.positionArrow(tooltip, ttPosition.placement);\n                    tooltip.removeClass('uib-position-measure');\n                  } else if (lastPlacement !== ttPosition.placement) {\n                    $position.positionArrow(tooltip, ttPosition.placement);\n                  }\n                  lastPlacement = ttPosition.placement;\n\n                  positionTimeout = null;\n                }, 0, false);\n              }\n            };\n\n            // Set up the correct scope to allow transclusion later\n            ttScope.origScope = scope;\n\n            // By default, the tooltip is not open.\n            // TODO add ability to start tooltip opened\n            ttScope.isOpen = false;\n\n            function toggleTooltipBind() {\n              if (!ttScope.isOpen) {\n                showTooltipBind();\n              } else {\n                hideTooltipBind();\n              }\n            }\n\n            // Show the tooltip with delay if specified, otherwise show it immediately\n            function showTooltipBind() {\n              if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {\n                return;\n              }\n\n              cancelHide();\n              prepareTooltip();\n\n              if (ttScope.popupDelay) {\n                // Do nothing if the tooltip was already scheduled to pop-up.\n                // This happens if show is triggered multiple times before any hide is triggered.\n                if (!showTimeout) {\n                  showTimeout = $timeout(show, ttScope.popupDelay, false);\n                }\n              } else {\n                show();\n              }\n            }\n\n            function hideTooltipBind() {\n              cancelShow();\n\n              if (ttScope.popupCloseDelay) {\n                if (!hideTimeout) {\n                  hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);\n                }\n              } else {\n                hide();\n              }\n            }\n\n            // Show the tooltip popup element.\n            function show() {\n              cancelShow();\n              cancelHide();\n\n              // Don't show empty tooltips.\n              if (!ttScope.content) {\n                return angular.noop;\n              }\n\n              createTooltip();\n\n              // And show the tooltip.\n              ttScope.$evalAsync(function() {\n                ttScope.isOpen = true;\n                assignIsOpen(true);\n                positionTooltip();\n              });\n            }\n\n            function cancelShow() {\n              if (showTimeout) {\n                $timeout.cancel(showTimeout);\n                showTimeout = null;\n              }\n\n              if (positionTimeout) {\n                $timeout.cancel(positionTimeout);\n                positionTimeout = null;\n              }\n            }\n\n            // Hide the tooltip popup element.\n            function hide() {\n              if (!ttScope) {\n                return;\n              }\n\n              // First things first: we don't show it anymore.\n              ttScope.$evalAsync(function() {\n                if (ttScope) {\n                  ttScope.isOpen = false;\n                  assignIsOpen(false);\n                  // And now we remove it from the DOM. However, if we have animation, we\n                  // need to wait for it to expire beforehand.\n                  // FIXME: this is a placeholder for a port of the transitions library.\n                  // The fade transition in TWBS is 150ms.\n                  if (ttScope.animation) {\n                    if (!transitionTimeout) {\n                      transitionTimeout = $timeout(removeTooltip, 150, false);\n                    }\n                  } else {\n                    removeTooltip();\n                  }\n                }\n              });\n            }\n\n            function cancelHide() {\n              if (hideTimeout) {\n                $timeout.cancel(hideTimeout);\n                hideTimeout = null;\n              }\n\n              if (transitionTimeout) {\n                $timeout.cancel(transitionTimeout);\n                transitionTimeout = null;\n              }\n            }\n\n            function createTooltip() {\n              // There can only be one tooltip element per directive shown at once.\n              if (tooltip) {\n                return;\n              }\n\n              tooltipLinkedScope = ttScope.$new();\n              tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {\n                if (appendToBody) {\n                  $document.find('body').append(tooltip);\n                } else {\n                  element.after(tooltip);\n                }\n              });\n\n              openedTooltips.add(ttScope, {\n                close: hide\n              });\n\n              prepObservers();\n            }\n\n            function removeTooltip() {\n              cancelShow();\n              cancelHide();\n              unregisterObservers();\n\n              if (tooltip) {\n                tooltip.remove();\n                \n                tooltip = null;\n                if (adjustmentTimeout) {\n                  $timeout.cancel(adjustmentTimeout);\n                }\n              }\n\n              openedTooltips.remove(ttScope);\n              \n              if (tooltipLinkedScope) {\n                tooltipLinkedScope.$destroy();\n                tooltipLinkedScope = null;\n              }\n            }\n\n            /**\n             * Set the initial scope values. Once\n             * the tooltip is created, the observers\n             * will be added to keep things in sync.\n             */\n            function prepareTooltip() {\n              ttScope.title = attrs[prefix + 'Title'];\n              if (contentParse) {\n                ttScope.content = contentParse(scope);\n              } else {\n                ttScope.content = attrs[ttType];\n              }\n\n              ttScope.popupClass = attrs[prefix + 'Class'];\n              ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;\n              var placement = $position.parsePlacement(ttScope.placement);\n              lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];\n\n              var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);\n              var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);\n              ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;\n              ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;\n            }\n\n            function assignIsOpen(isOpen) {\n              if (isOpenParse && angular.isFunction(isOpenParse.assign)) {\n                isOpenParse.assign(scope, isOpen);\n              }\n            }\n\n            ttScope.contentExp = function() {\n              return ttScope.content;\n            };\n\n            /**\n             * Observe the relevant attributes.\n             */\n            attrs.$observe('disabled', function(val) {\n              if (val) {\n                cancelShow();\n              }\n\n              if (val && ttScope.isOpen) {\n                hide();\n              }\n            });\n\n            if (isOpenParse) {\n              scope.$watch(isOpenParse, function(val) {\n                if (ttScope && !val === ttScope.isOpen) {\n                  toggleTooltipBind();\n                }\n              });\n            }\n\n            function prepObservers() {\n              observers.length = 0;\n\n              if (contentParse) {\n                observers.push(\n                  scope.$watch(contentParse, function(val) {\n                    ttScope.content = val;\n                    if (!val && ttScope.isOpen) {\n                      hide();\n                    }\n                  })\n                );\n\n                observers.push(\n                  tooltipLinkedScope.$watch(function() {\n                    if (!repositionScheduled) {\n                      repositionScheduled = true;\n                      tooltipLinkedScope.$$postDigest(function() {\n                        repositionScheduled = false;\n                        if (ttScope && ttScope.isOpen) {\n                          positionTooltip();\n                        }\n                      });\n                    }\n                  })\n                );\n              } else {\n                observers.push(\n                  attrs.$observe(ttType, function(val) {\n                    ttScope.content = val;\n                    if (!val && ttScope.isOpen) {\n                      hide();\n                    } else {\n                      positionTooltip();\n                    }\n                  })\n                );\n              }\n\n              observers.push(\n                attrs.$observe(prefix + 'Title', function(val) {\n                  ttScope.title = val;\n                  if (ttScope.isOpen) {\n                    positionTooltip();\n                  }\n                })\n              );\n\n              observers.push(\n                attrs.$observe(prefix + 'Placement', function(val) {\n                  ttScope.placement = val ? val : options.placement;\n                  if (ttScope.isOpen) {\n                    positionTooltip();\n                  }\n                })\n              );\n            }\n\n            function unregisterObservers() {\n              if (observers.length) {\n                angular.forEach(observers, function(observer) {\n                  observer();\n                });\n                observers.length = 0;\n              }\n            }\n\n            // hide tooltips/popovers for outsideClick trigger\n            function bodyHideTooltipBind(e) {\n              if (!ttScope || !ttScope.isOpen || !tooltip) {\n                return;\n              }\n              // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked\n              if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {\n                hideTooltipBind();\n              }\n            }\n\n            // KeyboardEvent handler to hide the tooltip on Escape key press\n            function hideOnEscapeKey(e) {\n              if (e.which === 27) {\n                hideTooltipBind();\n              }\n            }\n\n            var unregisterTriggers = function() {\n              triggers.show.forEach(function(trigger) {\n                if (trigger === 'outsideClick') {\n                  element.off('click', toggleTooltipBind);\n                } else {\n                  element.off(trigger, showTooltipBind);\n                  element.off(trigger, toggleTooltipBind);\n                }\n                element.off('keypress', hideOnEscapeKey);\n              });\n              triggers.hide.forEach(function(trigger) {\n                if (trigger === 'outsideClick') {\n                  $document.off('click', bodyHideTooltipBind);\n                } else {\n                  element.off(trigger, hideTooltipBind);\n                }\n              });\n            };\n\n            function prepTriggers() {\n              var showTriggers = [], hideTriggers = [];\n              var val = scope.$eval(attrs[prefix + 'Trigger']);\n              unregisterTriggers();\n\n              if (angular.isObject(val)) {\n                Object.keys(val).forEach(function(key) {\n                  showTriggers.push(key);\n                  hideTriggers.push(val[key]);\n                });\n                triggers = {\n                  show: showTriggers,\n                  hide: hideTriggers\n                };\n              } else {\n                triggers = getTriggers(val);\n              }\n\n              if (triggers.show !== 'none') {\n                triggers.show.forEach(function(trigger, idx) {\n                  if (trigger === 'outsideClick') {\n                    element.on('click', toggleTooltipBind);\n                    $document.on('click', bodyHideTooltipBind);\n                  } else if (trigger === triggers.hide[idx]) {\n                    element.on(trigger, toggleTooltipBind);\n                  } else if (trigger) {\n                    element.on(trigger, showTooltipBind);\n                    element.on(triggers.hide[idx], hideTooltipBind);\n                  }\n                  element.on('keypress', hideOnEscapeKey);\n                });\n              }\n            }\n\n            prepTriggers();\n\n            var animation = scope.$eval(attrs[prefix + 'Animation']);\n            ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;\n\n            var appendToBodyVal;\n            var appendKey = prefix + 'AppendToBody';\n            if (appendKey in attrs && attrs[appendKey] === undefined) {\n              appendToBodyVal = true;\n            } else {\n              appendToBodyVal = scope.$eval(attrs[appendKey]);\n            }\n\n            appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;\n\n            // Make sure tooltip is destroyed and removed.\n            scope.$on('$destroy', function onDestroyTooltip() {\n              unregisterTriggers();\n              removeTooltip();\n              ttScope = null;\n            });\n          };\n        }\n      };\n    };\n  }];\n})\n\n// This is mostly ngInclude code but with a custom scope\n.directive('uibTooltipTemplateTransclude', [\n         '$animate', '$sce', '$compile', '$templateRequest',\nfunction ($animate, $sce, $compile, $templateRequest) {\n  return {\n    link: function(scope, elem, attrs) {\n      var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);\n\n      var changeCounter = 0,\n        currentScope,\n        previousElement,\n        currentElement;\n\n      var cleanupLastIncludeContent = function() {\n        if (previousElement) {\n          previousElement.remove();\n          previousElement = null;\n        }\n\n        if (currentScope) {\n          currentScope.$destroy();\n          currentScope = null;\n        }\n\n        if (currentElement) {\n          $animate.leave(currentElement).then(function() {\n            previousElement = null;\n          });\n          previousElement = currentElement;\n          currentElement = null;\n        }\n      };\n\n      scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {\n        var thisChangeId = ++changeCounter;\n\n        if (src) {\n          //set the 2nd param to true to ignore the template request error so that the inner\n          //contents and scope can be cleaned up.\n          $templateRequest(src, true).then(function(response) {\n            if (thisChangeId !== changeCounter) { return; }\n            var newScope = origScope.$new();\n            var template = response;\n\n            var clone = $compile(template)(newScope, function(clone) {\n              cleanupLastIncludeContent();\n              $animate.enter(clone, elem);\n            });\n\n            currentScope = newScope;\n            currentElement = clone;\n\n            currentScope.$emit('$includeContentLoaded', src);\n          }, function() {\n            if (thisChangeId === changeCounter) {\n              cleanupLastIncludeContent();\n              scope.$emit('$includeContentError', src);\n            }\n          });\n          scope.$emit('$includeContentRequested', src);\n        } else {\n          cleanupLastIncludeContent();\n        }\n      });\n\n      scope.$on('$destroy', cleanupLastIncludeContent);\n    }\n  };\n}])\n\n/**\n * Note that it's intentional that these classes are *not* applied through $animate.\n * They must not be animated as they're expected to be present on the tooltip on\n * initialization.\n */\n.directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {\n  return {\n    restrict: 'A',\n    link: function(scope, element, attrs) {\n      // need to set the primary position so the\n      // arrow has space during position measure.\n      // tooltip.positionTooltip()\n      if (scope.placement) {\n        // // There are no top-left etc... classes\n        // // in TWBS, so we need the primary position.\n        var position = $uibPosition.parsePlacement(scope.placement);\n        element.addClass(position[0]);\n      }\n\n      if (scope.popupClass) {\n        element.addClass(scope.popupClass);\n      }\n\n      if (scope.animation) {\n        element.addClass(attrs.tooltipAnimationClass);\n      }\n    }\n  };\n}])\n\n.directive('uibTooltipPopup', function() {\n  return {\n    restrict: 'A',\n    scope: { content: '@' },\n    templateUrl: 'uib/template/tooltip/tooltip-popup.html'\n  };\n})\n\n.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');\n}])\n\n.directive('uibTooltipTemplatePopup', function() {\n  return {\n    restrict: 'A',\n    scope: { contentExp: '&', originScope: '&' },\n    templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'\n  };\n})\n\n.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {\n    useContentExp: true\n  });\n}])\n\n.directive('uibTooltipHtmlPopup', function() {\n  return {\n    restrict: 'A',\n    scope: { contentExp: '&' },\n    templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'\n  };\n})\n\n.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {\n    useContentExp: true\n  });\n}]);\n\n/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, and selector delegatation.\n */\nangular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])\n\n.directive('uibPopoverTemplatePopup', function() {\n  return {\n    restrict: 'A',\n    scope: { uibTitle: '@', contentExp: '&', originScope: '&' },\n    templateUrl: 'uib/template/popover/popover-template.html'\n  };\n})\n\n.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {\n    useContentExp: true\n  });\n}])\n\n.directive('uibPopoverHtmlPopup', function() {\n  return {\n    restrict: 'A',\n    scope: { contentExp: '&', uibTitle: '@' },\n    templateUrl: 'uib/template/popover/popover-html.html'\n  };\n})\n\n.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibPopoverHtml', 'popover', 'click', {\n    useContentExp: true\n  });\n}])\n\n.directive('uibPopoverPopup', function() {\n  return {\n    restrict: 'A',\n    scope: { uibTitle: '@', content: '@' },\n    templateUrl: 'uib/template/popover/popover.html'\n  };\n})\n\n.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {\n  return $uibTooltip('uibPopover', 'popover', 'click');\n}]);\n\nangular.module('ui.bootstrap.progressbar', [])\n\n.constant('uibProgressConfig', {\n  animate: true,\n  max: 100\n})\n\n.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {\n  var self = this,\n      animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;\n\n  this.bars = [];\n  $scope.max = getMaxOrDefault();\n\n  this.addBar = function(bar, element, attrs) {\n    if (!animate) {\n      element.css({'transition': 'none'});\n    }\n\n    this.bars.push(bar);\n\n    bar.max = getMaxOrDefault();\n    bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';\n\n    bar.$watch('value', function(value) {\n      bar.recalculatePercentage();\n    });\n\n    bar.recalculatePercentage = function() {\n      var totalPercentage = self.bars.reduce(function(total, bar) {\n        bar.percent = +(100 * bar.value / bar.max).toFixed(2);\n        return total + bar.percent;\n      }, 0);\n\n      if (totalPercentage > 100) {\n        bar.percent -= totalPercentage - 100;\n      }\n    };\n\n    bar.$on('$destroy', function() {\n      element = null;\n      self.removeBar(bar);\n    });\n  };\n\n  this.removeBar = function(bar) {\n    this.bars.splice(this.bars.indexOf(bar), 1);\n    this.bars.forEach(function (bar) {\n      bar.recalculatePercentage();\n    });\n  };\n\n  //$attrs.$observe('maxParam', function(maxParam) {\n  $scope.$watch('maxParam', function(maxParam) {\n    self.bars.forEach(function(bar) {\n      bar.max = getMaxOrDefault();\n      bar.recalculatePercentage();\n    });\n  });\n\n  function getMaxOrDefault () {\n    return angular.isDefined($scope.maxParam) ? $scope.maxParam : progressConfig.max;\n  }\n}])\n\n.directive('uibProgress', function() {\n  return {\n    replace: true,\n    transclude: true,\n    controller: 'UibProgressController',\n    require: 'uibProgress',\n    scope: {\n      maxParam: '=?max'\n    },\n    templateUrl: 'uib/template/progressbar/progress.html'\n  };\n})\n\n.directive('uibBar', function() {\n  return {\n    replace: true,\n    transclude: true,\n    require: '^uibProgress',\n    scope: {\n      value: '=',\n      type: '@'\n    },\n    templateUrl: 'uib/template/progressbar/bar.html',\n    link: function(scope, element, attrs, progressCtrl) {\n      progressCtrl.addBar(scope, element, attrs);\n    }\n  };\n})\n\n.directive('uibProgressbar', function() {\n  return {\n    replace: true,\n    transclude: true,\n    controller: 'UibProgressController',\n    scope: {\n      value: '=',\n      maxParam: '=?max',\n      type: '@'\n    },\n    templateUrl: 'uib/template/progressbar/progressbar.html',\n    link: function(scope, element, attrs, progressCtrl) {\n      progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});\n    }\n  };\n});\n\nangular.module('ui.bootstrap.rating', [])\n\n.constant('uibRatingConfig', {\n  max: 5,\n  stateOn: null,\n  stateOff: null,\n  enableReset: true,\n  titles: ['one', 'two', 'three', 'four', 'five']\n})\n\n.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {\n  var ngModelCtrl = { $setViewValue: angular.noop },\n    self = this;\n\n  this.init = function(ngModelCtrl_) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    ngModelCtrl.$formatters.push(function(value) {\n      if (angular.isNumber(value) && value << 0 !== value) {\n        value = Math.round(value);\n      }\n\n      return value;\n    });\n\n    this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;\n    this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;\n    this.enableReset = angular.isDefined($attrs.enableReset) ?\n      $scope.$parent.$eval($attrs.enableReset) : ratingConfig.enableReset;\n    var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles;\n    this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?\n      tmpTitles : ratingConfig.titles;\n\n    var ratingStates = angular.isDefined($attrs.ratingStates) ?\n      $scope.$parent.$eval($attrs.ratingStates) :\n      new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);\n    $scope.range = this.buildTemplateObjects(ratingStates);\n  };\n\n  this.buildTemplateObjects = function(states) {\n    for (var i = 0, n = states.length; i < n; i++) {\n      states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);\n    }\n    return states;\n  };\n\n  this.getTitle = function(index) {\n    if (index >= this.titles.length) {\n      return index + 1;\n    }\n\n    return this.titles[index];\n  };\n\n  $scope.rate = function(value) {\n    if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {\n      var newViewValue = self.enableReset && ngModelCtrl.$viewValue === value ? 0 : value;\n      ngModelCtrl.$setViewValue(newViewValue);\n      ngModelCtrl.$render();\n    }\n  };\n\n  $scope.enter = function(value) {\n    if (!$scope.readonly) {\n      $scope.value = value;\n    }\n    $scope.onHover({value: value});\n  };\n\n  $scope.reset = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n    $scope.onLeave();\n  };\n\n  $scope.onKeydown = function(evt) {\n    if (/(37|38|39|40)/.test(evt.which)) {\n      evt.preventDefault();\n      evt.stopPropagation();\n      $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));\n    }\n  };\n\n  this.render = function() {\n    $scope.value = ngModelCtrl.$viewValue;\n    $scope.title = self.getTitle($scope.value - 1);\n  };\n}])\n\n.directive('uibRating', function() {\n  return {\n    require: ['uibRating', 'ngModel'],\n    restrict: 'A',\n    scope: {\n      readonly: '=?readOnly',\n      onHover: '&',\n      onLeave: '&'\n    },\n    controller: 'UibRatingController',\n    templateUrl: 'uib/template/rating/rating.html',\n    link: function(scope, element, attrs, ctrls) {\n      var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n      ratingCtrl.init(ngModelCtrl);\n    }\n  };\n});\n\nangular.module('ui.bootstrap.tabs', [])\n\n.controller('UibTabsetController', ['$scope', function ($scope) {\n  var ctrl = this,\n    oldIndex;\n  ctrl.tabs = [];\n\n  ctrl.select = function(index, evt) {\n    if (!destroyed) {\n      var previousIndex = findTabIndex(oldIndex);\n      var previousSelected = ctrl.tabs[previousIndex];\n      if (previousSelected) {\n        previousSelected.tab.onDeselect({\n          $event: evt,\n          $selectedIndex: index\n        });\n        if (evt && evt.isDefaultPrevented()) {\n          return;\n        }\n        previousSelected.tab.active = false;\n      }\n\n      var selected = ctrl.tabs[index];\n      if (selected) {\n        selected.tab.onSelect({\n          $event: evt\n        });\n        selected.tab.active = true;\n        ctrl.active = selected.index;\n        oldIndex = selected.index;\n      } else if (!selected && angular.isDefined(oldIndex)) {\n        ctrl.active = null;\n        oldIndex = null;\n      }\n    }\n  };\n\n  ctrl.addTab = function addTab(tab) {\n    ctrl.tabs.push({\n      tab: tab,\n      index: tab.index\n    });\n    ctrl.tabs.sort(function(t1, t2) {\n      if (t1.index > t2.index) {\n        return 1;\n      }\n\n      if (t1.index < t2.index) {\n        return -1;\n      }\n\n      return 0;\n    });\n\n    if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {\n      var newActiveIndex = findTabIndex(tab.index);\n      ctrl.select(newActiveIndex);\n    }\n  };\n\n  ctrl.removeTab = function removeTab(tab) {\n    var index;\n    for (var i = 0; i < ctrl.tabs.length; i++) {\n      if (ctrl.tabs[i].tab === tab) {\n        index = i;\n        break;\n      }\n    }\n\n    if (ctrl.tabs[index].index === ctrl.active) {\n      var newActiveTabIndex = index === ctrl.tabs.length - 1 ?\n        index - 1 : index + 1 % ctrl.tabs.length;\n      ctrl.select(newActiveTabIndex);\n    }\n\n    ctrl.tabs.splice(index, 1);\n  };\n\n  $scope.$watch('tabset.active', function(val) {\n    if (angular.isDefined(val) && val !== oldIndex) {\n      ctrl.select(findTabIndex(val));\n    }\n  });\n\n  var destroyed;\n  $scope.$on('$destroy', function() {\n    destroyed = true;\n  });\n\n  function findTabIndex(index) {\n    for (var i = 0; i < ctrl.tabs.length; i++) {\n      if (ctrl.tabs[i].index === index) {\n        return i;\n      }\n    }\n  }\n}])\n\n.directive('uibTabset', function() {\n  return {\n    transclude: true,\n    replace: true,\n    scope: {},\n    bindToController: {\n      active: '=?',\n      type: '@'\n    },\n    controller: 'UibTabsetController',\n    controllerAs: 'tabset',\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/tabs/tabset.html';\n    },\n    link: function(scope, element, attrs) {\n      scope.vertical = angular.isDefined(attrs.vertical) ?\n        scope.$parent.$eval(attrs.vertical) : false;\n      scope.justified = angular.isDefined(attrs.justified) ?\n        scope.$parent.$eval(attrs.justified) : false;\n    }\n  };\n})\n\n.directive('uibTab', ['$parse', function($parse) {\n  return {\n    require: '^uibTabset',\n    replace: true,\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || 'uib/template/tabs/tab.html';\n    },\n    transclude: true,\n    scope: {\n      heading: '@',\n      index: '=?',\n      classes: '@?',\n      onSelect: '&select', //This callback is called in contentHeadingTransclude\n                          //once it inserts the tab's content into the dom\n      onDeselect: '&deselect'\n    },\n    controller: function() {\n      //Empty controller so other directives can require being 'under' a tab\n    },\n    controllerAs: 'tab',\n    link: function(scope, elm, attrs, tabsetCtrl, transclude) {\n      scope.disabled = false;\n      if (attrs.disable) {\n        scope.$parent.$watch($parse(attrs.disable), function(value) {\n          scope.disabled = !! value;\n        });\n      }\n\n      if (angular.isUndefined(attrs.index)) {\n        if (tabsetCtrl.tabs && tabsetCtrl.tabs.length) {\n          scope.index = Math.max.apply(null, tabsetCtrl.tabs.map(function(t) { return t.index; })) + 1;\n        } else {\n          scope.index = 0;\n        }\n      }\n\n      if (angular.isUndefined(attrs.classes)) {\n        scope.classes = '';\n      }\n\n      scope.select = function(evt) {\n        if (!scope.disabled) {\n          var index;\n          for (var i = 0; i < tabsetCtrl.tabs.length; i++) {\n            if (tabsetCtrl.tabs[i].tab === scope) {\n              index = i;\n              break;\n            }\n          }\n\n          tabsetCtrl.select(index, evt);\n        }\n      };\n\n      tabsetCtrl.addTab(scope);\n      scope.$on('$destroy', function() {\n        tabsetCtrl.removeTab(scope);\n      });\n\n      //We need to transclude later, once the content container is ready.\n      //when this link happens, we're inside a tab heading.\n      scope.$transcludeFn = transclude;\n    }\n  };\n}])\n\n.directive('uibTabHeadingTransclude', function() {\n  return {\n    restrict: 'A',\n    require: '^uibTab',\n    link: function(scope, elm) {\n      scope.$watch('headingElement', function updateHeadingElement(heading) {\n        if (heading) {\n          elm.html('');\n          elm.append(heading);\n        }\n      });\n    }\n  };\n})\n\n.directive('uibTabContentTransclude', function() {\n  return {\n    restrict: 'A',\n    require: '^uibTabset',\n    link: function(scope, elm, attrs) {\n      var tab = scope.$eval(attrs.uibTabContentTransclude).tab;\n\n      //Now our tab is ready to be transcluded: both the tab heading area\n      //and the tab content area are loaded.  Transclude 'em both.\n      tab.$transcludeFn(tab.$parent, function(contents) {\n        angular.forEach(contents, function(node) {\n          if (isTabHeading(node)) {\n            //Let tabHeadingTransclude know.\n            tab.headingElement = node;\n          } else {\n            elm.append(node);\n          }\n        });\n      });\n    }\n  };\n\n  function isTabHeading(node) {\n    return node.tagName && (\n      node.hasAttribute('uib-tab-heading') ||\n      node.hasAttribute('data-uib-tab-heading') ||\n      node.hasAttribute('x-uib-tab-heading') ||\n      node.tagName.toLowerCase() === 'uib-tab-heading' ||\n      node.tagName.toLowerCase() === 'data-uib-tab-heading' ||\n      node.tagName.toLowerCase() === 'x-uib-tab-heading' ||\n      node.tagName.toLowerCase() === 'uib:tab-heading'\n    );\n  }\n});\n\nangular.module('ui.bootstrap.timepicker', [])\n\n.constant('uibTimepickerConfig', {\n  hourStep: 1,\n  minuteStep: 1,\n  secondStep: 1,\n  showMeridian: true,\n  showSeconds: false,\n  meridians: null,\n  readonlyInput: false,\n  mousewheel: true,\n  arrowkeys: true,\n  showSpinners: true,\n  templateUrl: 'uib/template/timepicker/timepicker.html'\n})\n\n.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {\n  var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;\n  var selected = new Date(),\n    watchers = [],\n    ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n    meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS,\n    padHours = angular.isDefined($attrs.padHours) ? $scope.$parent.$eval($attrs.padHours) : true;\n\n  $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;\n  $element.removeAttr('tabindex');\n\n  this.init = function(ngModelCtrl_, inputs) {\n    ngModelCtrl = ngModelCtrl_;\n    ngModelCtrl.$render = this.render;\n\n    ngModelCtrl.$formatters.unshift(function(modelValue) {\n      return modelValue ? new Date(modelValue) : null;\n    });\n\n    var hoursInputEl = inputs.eq(0),\n        minutesInputEl = inputs.eq(1),\n        secondsInputEl = inputs.eq(2);\n\n    hoursModelCtrl = hoursInputEl.controller('ngModel');\n    minutesModelCtrl = minutesInputEl.controller('ngModel');\n    secondsModelCtrl = secondsInputEl.controller('ngModel');\n\n    var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;\n\n    if (mousewheel) {\n      this.setupMousewheelEvents(hoursInputEl, minutesInputEl, secondsInputEl);\n    }\n\n    var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;\n    if (arrowkeys) {\n      this.setupArrowkeyEvents(hoursInputEl, minutesInputEl, secondsInputEl);\n    }\n\n    $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;\n    this.setupInputEvents(hoursInputEl, minutesInputEl, secondsInputEl);\n  };\n\n  var hourStep = timepickerConfig.hourStep;\n  if ($attrs.hourStep) {\n    watchers.push($scope.$parent.$watch($parse($attrs.hourStep), function(value) {\n      hourStep = +value;\n    }));\n  }\n\n  var minuteStep = timepickerConfig.minuteStep;\n  if ($attrs.minuteStep) {\n    watchers.push($scope.$parent.$watch($parse($attrs.minuteStep), function(value) {\n      minuteStep = +value;\n    }));\n  }\n\n  var min;\n  watchers.push($scope.$parent.$watch($parse($attrs.min), function(value) {\n    var dt = new Date(value);\n    min = isNaN(dt) ? undefined : dt;\n  }));\n\n  var max;\n  watchers.push($scope.$parent.$watch($parse($attrs.max), function(value) {\n    var dt = new Date(value);\n    max = isNaN(dt) ? undefined : dt;\n  }));\n\n  var disabled = false;\n  if ($attrs.ngDisabled) {\n    watchers.push($scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {\n      disabled = value;\n    }));\n  }\n\n  $scope.noIncrementHours = function() {\n    var incrementedSelected = addMinutes(selected, hourStep * 60);\n    return disabled || incrementedSelected > max ||\n      incrementedSelected < selected && incrementedSelected < min;\n  };\n\n  $scope.noDecrementHours = function() {\n    var decrementedSelected = addMinutes(selected, -hourStep * 60);\n    return disabled || decrementedSelected < min ||\n      decrementedSelected > selected && decrementedSelected > max;\n  };\n\n  $scope.noIncrementMinutes = function() {\n    var incrementedSelected = addMinutes(selected, minuteStep);\n    return disabled || incrementedSelected > max ||\n      incrementedSelected < selected && incrementedSelected < min;\n  };\n\n  $scope.noDecrementMinutes = function() {\n    var decrementedSelected = addMinutes(selected, -minuteStep);\n    return disabled || decrementedSelected < min ||\n      decrementedSelected > selected && decrementedSelected > max;\n  };\n\n  $scope.noIncrementSeconds = function() {\n    var incrementedSelected = addSeconds(selected, secondStep);\n    return disabled || incrementedSelected > max ||\n      incrementedSelected < selected && incrementedSelected < min;\n  };\n\n  $scope.noDecrementSeconds = function() {\n    var decrementedSelected = addSeconds(selected, -secondStep);\n    return disabled || decrementedSelected < min ||\n      decrementedSelected > selected && decrementedSelected > max;\n  };\n\n  $scope.noToggleMeridian = function() {\n    if (selected.getHours() < 12) {\n      return disabled || addMinutes(selected, 12 * 60) > max;\n    }\n\n    return disabled || addMinutes(selected, -12 * 60) < min;\n  };\n\n  var secondStep = timepickerConfig.secondStep;\n  if ($attrs.secondStep) {\n    watchers.push($scope.$parent.$watch($parse($attrs.secondStep), function(value) {\n      secondStep = +value;\n    }));\n  }\n\n  $scope.showSeconds = timepickerConfig.showSeconds;\n  if ($attrs.showSeconds) {\n    watchers.push($scope.$parent.$watch($parse($attrs.showSeconds), function(value) {\n      $scope.showSeconds = !!value;\n    }));\n  }\n\n  // 12H / 24H mode\n  $scope.showMeridian = timepickerConfig.showMeridian;\n  if ($attrs.showMeridian) {\n    watchers.push($scope.$parent.$watch($parse($attrs.showMeridian), function(value) {\n      $scope.showMeridian = !!value;\n\n      if (ngModelCtrl.$error.time) {\n        // Evaluate from template\n        var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();\n        if (angular.isDefined(hours) && angular.isDefined(minutes)) {\n          selected.setHours(hours);\n          refresh();\n        }\n      } else {\n        updateTemplate();\n      }\n    }));\n  }\n\n  // Get $scope.hours in 24H mode if valid\n  function getHoursFromTemplate() {\n    var hours = +$scope.hours;\n    var valid = $scope.showMeridian ? hours > 0 && hours < 13 :\n      hours >= 0 && hours < 24;\n    if (!valid || $scope.hours === '') {\n      return undefined;\n    }\n\n    if ($scope.showMeridian) {\n      if (hours === 12) {\n        hours = 0;\n      }\n      if ($scope.meridian === meridians[1]) {\n        hours = hours + 12;\n      }\n    }\n    return hours;\n  }\n\n  function getMinutesFromTemplate() {\n    var minutes = +$scope.minutes;\n    var valid = minutes >= 0 && minutes < 60;\n    if (!valid || $scope.minutes === '') {\n      return undefined;\n    }\n    return minutes;\n  }\n\n  function getSecondsFromTemplate() {\n    var seconds = +$scope.seconds;\n    return seconds >= 0 && seconds < 60 ? seconds : undefined;\n  }\n\n  function pad(value, noPad) {\n    if (value === null) {\n      return '';\n    }\n\n    return angular.isDefined(value) && value.toString().length < 2 && !noPad ?\n      '0' + value : value.toString();\n  }\n\n  // Respond on mousewheel spin\n  this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {\n    var isScrollingUp = function(e) {\n      if (e.originalEvent) {\n        e = e.originalEvent;\n      }\n      //pick correct delta variable depending on event\n      var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY;\n      return e.detail || delta > 0;\n    };\n\n    hoursInputEl.on('mousewheel wheel', function(e) {\n      if (!disabled) {\n        $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());\n      }\n      e.preventDefault();\n    });\n\n    minutesInputEl.on('mousewheel wheel', function(e) {\n      if (!disabled) {\n        $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());\n      }\n      e.preventDefault();\n    });\n\n     secondsInputEl.on('mousewheel wheel', function(e) {\n      if (!disabled) {\n        $scope.$apply(isScrollingUp(e) ? $scope.incrementSeconds() : $scope.decrementSeconds());\n      }\n      e.preventDefault();\n    });\n  };\n\n  // Respond on up/down arrowkeys\n  this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {\n    hoursInputEl.on('keydown', function(e) {\n      if (!disabled) {\n        if (e.which === 38) { // up\n          e.preventDefault();\n          $scope.incrementHours();\n          $scope.$apply();\n        } else if (e.which === 40) { // down\n          e.preventDefault();\n          $scope.decrementHours();\n          $scope.$apply();\n        }\n      }\n    });\n\n    minutesInputEl.on('keydown', function(e) {\n      if (!disabled) {\n        if (e.which === 38) { // up\n          e.preventDefault();\n          $scope.incrementMinutes();\n          $scope.$apply();\n        } else if (e.which === 40) { // down\n          e.preventDefault();\n          $scope.decrementMinutes();\n          $scope.$apply();\n        }\n      }\n    });\n\n    secondsInputEl.on('keydown', function(e) {\n      if (!disabled) {\n        if (e.which === 38) { // up\n          e.preventDefault();\n          $scope.incrementSeconds();\n          $scope.$apply();\n        } else if (e.which === 40) { // down\n          e.preventDefault();\n          $scope.decrementSeconds();\n          $scope.$apply();\n        }\n      }\n    });\n  };\n\n  this.setupInputEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {\n    if ($scope.readonlyInput) {\n      $scope.updateHours = angular.noop;\n      $scope.updateMinutes = angular.noop;\n      $scope.updateSeconds = angular.noop;\n      return;\n    }\n\n    var invalidate = function(invalidHours, invalidMinutes, invalidSeconds) {\n      ngModelCtrl.$setViewValue(null);\n      ngModelCtrl.$setValidity('time', false);\n      if (angular.isDefined(invalidHours)) {\n        $scope.invalidHours = invalidHours;\n        if (hoursModelCtrl) {\n          hoursModelCtrl.$setValidity('hours', false);\n        }\n      }\n\n      if (angular.isDefined(invalidMinutes)) {\n        $scope.invalidMinutes = invalidMinutes;\n        if (minutesModelCtrl) {\n          minutesModelCtrl.$setValidity('minutes', false);\n        }\n      }\n\n      if (angular.isDefined(invalidSeconds)) {\n        $scope.invalidSeconds = invalidSeconds;\n        if (secondsModelCtrl) {\n          secondsModelCtrl.$setValidity('seconds', false);\n        }\n      }\n    };\n\n    $scope.updateHours = function() {\n      var hours = getHoursFromTemplate(),\n        minutes = getMinutesFromTemplate();\n\n      ngModelCtrl.$setDirty();\n\n      if (angular.isDefined(hours) && angular.isDefined(minutes)) {\n        selected.setHours(hours);\n        selected.setMinutes(minutes);\n        if (selected < min || selected > max) {\n          invalidate(true);\n        } else {\n          refresh('h');\n        }\n      } else {\n        invalidate(true);\n      }\n    };\n\n    hoursInputEl.on('blur', function(e) {\n      ngModelCtrl.$setTouched();\n      if (modelIsEmpty()) {\n        makeValid();\n      } else if ($scope.hours === null || $scope.hours === '') {\n        invalidate(true);\n      } else if (!$scope.invalidHours && $scope.hours < 10) {\n        $scope.$apply(function() {\n          $scope.hours = pad($scope.hours, !padHours);\n        });\n      }\n    });\n\n    $scope.updateMinutes = function() {\n      var minutes = getMinutesFromTemplate(),\n        hours = getHoursFromTemplate();\n\n      ngModelCtrl.$setDirty();\n\n      if (angular.isDefined(minutes) && angular.isDefined(hours)) {\n        selected.setHours(hours);\n        selected.setMinutes(minutes);\n        if (selected < min || selected > max) {\n          invalidate(undefined, true);\n        } else {\n          refresh('m');\n        }\n      } else {\n        invalidate(undefined, true);\n      }\n    };\n\n    minutesInputEl.on('blur', function(e) {\n      ngModelCtrl.$setTouched();\n      if (modelIsEmpty()) {\n        makeValid();\n      } else if ($scope.minutes === null) {\n        invalidate(undefined, true);\n      } else if (!$scope.invalidMinutes && $scope.minutes < 10) {\n        $scope.$apply(function() {\n          $scope.minutes = pad($scope.minutes);\n        });\n      }\n    });\n\n    $scope.updateSeconds = function() {\n      var seconds = getSecondsFromTemplate();\n\n      ngModelCtrl.$setDirty();\n\n      if (angular.isDefined(seconds)) {\n        selected.setSeconds(seconds);\n        refresh('s');\n      } else {\n        invalidate(undefined, undefined, true);\n      }\n    };\n\n    secondsInputEl.on('blur', function(e) {\n      if (modelIsEmpty()) {\n        makeValid();\n      } else if (!$scope.invalidSeconds && $scope.seconds < 10) {\n        $scope.$apply( function() {\n          $scope.seconds = pad($scope.seconds);\n        });\n      }\n    });\n\n  };\n\n  this.render = function() {\n    var date = ngModelCtrl.$viewValue;\n\n    if (isNaN(date)) {\n      ngModelCtrl.$setValidity('time', false);\n      $log.error('Timepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n    } else {\n      if (date) {\n        selected = date;\n      }\n\n      if (selected < min || selected > max) {\n        ngModelCtrl.$setValidity('time', false);\n        $scope.invalidHours = true;\n        $scope.invalidMinutes = true;\n      } else {\n        makeValid();\n      }\n      updateTemplate();\n    }\n  };\n\n  // Call internally when we know that model is valid.\n  function refresh(keyboardChange) {\n    makeValid();\n    ngModelCtrl.$setViewValue(new Date(selected));\n    updateTemplate(keyboardChange);\n  }\n\n  function makeValid() {\n    if (hoursModelCtrl) {\n      hoursModelCtrl.$setValidity('hours', true);\n    }\n\n    if (minutesModelCtrl) {\n      minutesModelCtrl.$setValidity('minutes', true);\n    }\n\n    if (secondsModelCtrl) {\n      secondsModelCtrl.$setValidity('seconds', true);\n    }\n\n    ngModelCtrl.$setValidity('time', true);\n    $scope.invalidHours = false;\n    $scope.invalidMinutes = false;\n    $scope.invalidSeconds = false;\n  }\n\n  function updateTemplate(keyboardChange) {\n    if (!ngModelCtrl.$modelValue) {\n      $scope.hours = null;\n      $scope.minutes = null;\n      $scope.seconds = null;\n      $scope.meridian = meridians[0];\n    } else {\n      var hours = selected.getHours(),\n        minutes = selected.getMinutes(),\n        seconds = selected.getSeconds();\n\n      if ($scope.showMeridian) {\n        hours = hours === 0 || hours === 12 ? 12 : hours % 12; // Convert 24 to 12 hour system\n      }\n\n      $scope.hours = keyboardChange === 'h' ? hours : pad(hours, !padHours);\n      if (keyboardChange !== 'm') {\n        $scope.minutes = pad(minutes);\n      }\n      $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];\n\n      if (keyboardChange !== 's') {\n        $scope.seconds = pad(seconds);\n      }\n      $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];\n    }\n  }\n\n  function addSecondsToSelected(seconds) {\n    selected = addSeconds(selected, seconds);\n    refresh();\n  }\n\n  function addMinutes(selected, minutes) {\n    return addSeconds(selected, minutes*60);\n  }\n\n  function addSeconds(date, seconds) {\n    var dt = new Date(date.getTime() + seconds * 1000);\n    var newDate = new Date(date);\n    newDate.setHours(dt.getHours(), dt.getMinutes(), dt.getSeconds());\n    return newDate;\n  }\n\n  function modelIsEmpty() {\n    return ($scope.hours === null || $scope.hours === '') &&\n      ($scope.minutes === null || $scope.minutes === '') &&\n      (!$scope.showSeconds || $scope.showSeconds && ($scope.seconds === null || $scope.seconds === ''));\n  }\n\n  $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?\n    $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;\n\n  $scope.incrementHours = function() {\n    if (!$scope.noIncrementHours()) {\n      addSecondsToSelected(hourStep * 60 * 60);\n    }\n  };\n\n  $scope.decrementHours = function() {\n    if (!$scope.noDecrementHours()) {\n      addSecondsToSelected(-hourStep * 60 * 60);\n    }\n  };\n\n  $scope.incrementMinutes = function() {\n    if (!$scope.noIncrementMinutes()) {\n      addSecondsToSelected(minuteStep * 60);\n    }\n  };\n\n  $scope.decrementMinutes = function() {\n    if (!$scope.noDecrementMinutes()) {\n      addSecondsToSelected(-minuteStep * 60);\n    }\n  };\n\n  $scope.incrementSeconds = function() {\n    if (!$scope.noIncrementSeconds()) {\n      addSecondsToSelected(secondStep);\n    }\n  };\n\n  $scope.decrementSeconds = function() {\n    if (!$scope.noDecrementSeconds()) {\n      addSecondsToSelected(-secondStep);\n    }\n  };\n\n  $scope.toggleMeridian = function() {\n    var minutes = getMinutesFromTemplate(),\n        hours = getHoursFromTemplate();\n\n    if (!$scope.noToggleMeridian()) {\n      if (angular.isDefined(minutes) && angular.isDefined(hours)) {\n        addSecondsToSelected(12 * 60 * (selected.getHours() < 12 ? 60 : -60));\n      } else {\n        $scope.meridian = $scope.meridian === meridians[0] ? meridians[1] : meridians[0];\n      }\n    }\n  };\n\n  $scope.blur = function() {\n    ngModelCtrl.$setTouched();\n  };\n\n  $scope.$on('$destroy', function() {\n    while (watchers.length) {\n      watchers.shift()();\n    }\n  });\n}])\n\n.directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {\n  return {\n    require: ['uibTimepicker', '?^ngModel'],\n    restrict: 'A',\n    controller: 'UibTimepickerController',\n    controllerAs: 'timepicker',\n    scope: {},\n    templateUrl: function(element, attrs) {\n      return attrs.templateUrl || uibTimepickerConfig.templateUrl;\n    },\n    link: function(scope, element, attrs, ctrls) {\n      var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n      if (ngModelCtrl) {\n        timepickerCtrl.init(ngModelCtrl, element.find('input'));\n      }\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap.position'])\n\n/**\n * A helper service that can parse typeahead's syntax (string provided by users)\n * Extracted to a separate service for ease of unit testing\n */\n  .factory('uibTypeaheadParser', ['$parse', function($parse) {\n    //                      000001111111100000000000002222222200000000000000003333333333333330000000000044444444000\n    var TYPEAHEAD_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*))\\s+in\\s+([\\s\\S]+?)$/;\n    return {\n      parse: function(input) {\n        var match = input.match(TYPEAHEAD_REGEXP);\n        if (!match) {\n          throw new Error(\n            'Expected typeahead specification in form of \"_modelValue_ (as _label_)? for _item_ in _collection_\"' +\n              ' but got \"' + input + '\".');\n        }\n\n        return {\n          itemName: match[3],\n          source: $parse(match[4]),\n          viewMapper: $parse(match[2] || match[1]),\n          modelMapper: $parse(match[1])\n        };\n      }\n    };\n  }])\n\n  .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$$debounce', '$uibPosition', 'uibTypeaheadParser',\n    function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $$debounce, $position, typeaheadParser) {\n    var HOT_KEYS = [9, 13, 27, 38, 40];\n    var eventDebounceTime = 200;\n    var modelCtrl, ngModelOptions;\n    //SUPPORTED ATTRIBUTES (OPTIONS)\n\n    //minimal no of characters that needs to be entered before typeahead kicks-in\n    var minLength = originalScope.$eval(attrs.typeaheadMinLength);\n    if (!minLength && minLength !== 0) {\n      minLength = 1;\n    }\n\n    originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {\n        minLength = !newVal && newVal !== 0 ? 1 : newVal;\n    });\n\n    //minimal wait time after last character typed before typeahead kicks-in\n    var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;\n\n    //should it restrict model values to the ones selected from the popup only?\n    var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n    originalScope.$watch(attrs.typeaheadEditable, function (newVal) {\n      isEditable = newVal !== false;\n    });\n\n    //binding to a variable that indicates if matches are being retrieved asynchronously\n    var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n    //a function to determine if an event should cause selection\n    var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function(scope, vals) {\n      var evt = vals.$event;\n      return evt.which === 13 || evt.which === 9;\n    };\n\n    //a callback executed when a match is selected\n    var onSelectCallback = $parse(attrs.typeaheadOnSelect);\n\n    //should it select highlighted popup value when losing focus?\n    var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;\n\n    //binding to a variable that indicates if there were no results after the query is completed\n    var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;\n\n    var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;\n\n    var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;\n\n    var appendTo = attrs.typeaheadAppendTo ?\n      originalScope.$eval(attrs.typeaheadAppendTo) : null;\n\n    var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;\n\n    //If input matches an item of the list exactly, select it automatically\n    var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;\n\n    //binding to a variable that indicates if dropdown is open\n    var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;\n\n    var showHint = originalScope.$eval(attrs.typeaheadShowHint) || false;\n\n    //INTERNAL VARIABLES\n\n    //model setter executed upon match selection\n    var parsedModel = $parse(attrs.ngModel);\n    var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');\n    var $setModelValue = function(scope, newValue) {\n      if (angular.isFunction(parsedModel(originalScope)) &&\n        ngModelOptions.getOption('getterSetter')) {\n        return invokeModelSetter(scope, {$$$p: newValue});\n      }\n\n      return parsedModel.assign(scope, newValue);\n    };\n\n    //expressions used by typeahead\n    var parserResult = typeaheadParser.parse(attrs.uibTypeahead);\n\n    var hasFocus;\n\n    //Used to avoid bug in iOS webview where iOS keyboard does not fire\n    //mousedown & mouseup events\n    //Issue #3699\n    var selected;\n\n    //create a child scope for the typeahead directive so we are not polluting original scope\n    //with typeahead-specific data (matches, query etc.)\n    var scope = originalScope.$new();\n    var offDestroy = originalScope.$on('$destroy', function() {\n      scope.$destroy();\n    });\n    scope.$on('$destroy', offDestroy);\n\n    // WAI-ARIA\n    var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n    element.attr({\n      'aria-autocomplete': 'list',\n      'aria-expanded': false,\n      'aria-owns': popupId\n    });\n\n    var inputsContainer, hintInputElem;\n    //add read-only input to show hint\n    if (showHint) {\n      inputsContainer = angular.element('<div></div>');\n      inputsContainer.css('position', 'relative');\n      element.after(inputsContainer);\n      hintInputElem = element.clone();\n      hintInputElem.attr('placeholder', '');\n      hintInputElem.attr('tabindex', '-1');\n      hintInputElem.val('');\n      hintInputElem.css({\n        'position': 'absolute',\n        'top': '0px',\n        'left': '0px',\n        'border-color': 'transparent',\n        'box-shadow': 'none',\n        'opacity': 1,\n        'background': 'none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)',\n        'color': '#999'\n      });\n      element.css({\n        'position': 'relative',\n        'vertical-align': 'top',\n        'background-color': 'transparent'\n      });\n\n      if (hintInputElem.attr('id')) {\n        hintInputElem.removeAttr('id'); // remove duplicate id if present.\n      }\n      inputsContainer.append(hintInputElem);\n      hintInputElem.after(element);\n    }\n\n    //pop-up element used to display matches\n    var popUpEl = angular.element('<div uib-typeahead-popup></div>');\n    popUpEl.attr({\n      id: popupId,\n      matches: 'matches',\n      active: 'activeIdx',\n      select: 'select(activeIdx, evt)',\n      'move-in-progress': 'moveInProgress',\n      query: 'query',\n      position: 'position',\n      'assign-is-open': 'assignIsOpen(isOpen)',\n      debounce: 'debounceUpdate'\n    });\n    //custom item template\n    if (angular.isDefined(attrs.typeaheadTemplateUrl)) {\n      popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);\n    }\n\n    if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {\n      popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);\n    }\n\n    var resetHint = function() {\n      if (showHint) {\n        hintInputElem.val('');\n      }\n    };\n\n    var resetMatches = function() {\n      scope.matches = [];\n      scope.activeIdx = -1;\n      element.attr('aria-expanded', false);\n      resetHint();\n    };\n\n    var getMatchId = function(index) {\n      return popupId + '-option-' + index;\n    };\n\n    // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.\n    // This attribute is added or removed automatically when the `activeIdx` changes.\n    scope.$watch('activeIdx', function(index) {\n      if (index < 0) {\n        element.removeAttr('aria-activedescendant');\n      } else {\n        element.attr('aria-activedescendant', getMatchId(index));\n      }\n    });\n\n    var inputIsExactMatch = function(inputValue, index) {\n      if (scope.matches.length > index && inputValue) {\n        return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();\n      }\n\n      return false;\n    };\n\n    var getMatchesAsync = function(inputValue, evt) {\n      var locals = {$viewValue: inputValue};\n      isLoadingSetter(originalScope, true);\n      isNoResultsSetter(originalScope, false);\n      $q.when(parserResult.source(originalScope, locals)).then(function(matches) {\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        var onCurrentRequest = inputValue === modelCtrl.$viewValue;\n        if (onCurrentRequest && hasFocus) {\n          if (matches && matches.length > 0) {\n            scope.activeIdx = focusFirst ? 0 : -1;\n            isNoResultsSetter(originalScope, false);\n            scope.matches.length = 0;\n\n            //transform labels\n            for (var i = 0; i < matches.length; i++) {\n              locals[parserResult.itemName] = matches[i];\n              scope.matches.push({\n                id: getMatchId(i),\n                label: parserResult.viewMapper(scope, locals),\n                model: matches[i]\n              });\n            }\n\n            scope.query = inputValue;\n            //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n            //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n            //due to other elements being rendered\n            recalculatePosition();\n\n            element.attr('aria-expanded', true);\n\n            //Select the single remaining option if user input matches\n            if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {\n              if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {\n                $$debounce(function() {\n                  scope.select(0, evt);\n                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);\n              } else {\n                scope.select(0, evt);\n              }\n            }\n\n            if (showHint) {\n              var firstLabel = scope.matches[0].label;\n              if (angular.isString(inputValue) &&\n                inputValue.length > 0 &&\n                firstLabel.slice(0, inputValue.length).toUpperCase() === inputValue.toUpperCase()) {\n                hintInputElem.val(inputValue + firstLabel.slice(inputValue.length));\n              } else {\n                hintInputElem.val('');\n              }\n            }\n          } else {\n            resetMatches();\n            isNoResultsSetter(originalScope, true);\n          }\n        }\n        if (onCurrentRequest) {\n          isLoadingSetter(originalScope, false);\n        }\n      }, function() {\n        resetMatches();\n        isLoadingSetter(originalScope, false);\n        isNoResultsSetter(originalScope, true);\n      });\n    };\n\n    // bind events only if appendToBody params exist - performance feature\n    if (appendToBody) {\n      angular.element($window).on('resize', fireRecalculating);\n      $document.find('body').on('scroll', fireRecalculating);\n    }\n\n    // Declare the debounced function outside recalculating for\n    // proper debouncing\n    var debouncedRecalculate = $$debounce(function() {\n      // if popup is visible\n      if (scope.matches.length) {\n        recalculatePosition();\n      }\n\n      scope.moveInProgress = false;\n    }, eventDebounceTime);\n\n    // Default progress type\n    scope.moveInProgress = false;\n\n    function fireRecalculating() {\n      if (!scope.moveInProgress) {\n        scope.moveInProgress = true;\n        scope.$digest();\n      }\n\n      debouncedRecalculate();\n    }\n\n    // recalculate actual position and set new values to scope\n    // after digest loop is popup in right position\n    function recalculatePosition() {\n      scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n      scope.position.top += element.prop('offsetHeight');\n    }\n\n    //we need to propagate user's query so we can higlight matches\n    scope.query = undefined;\n\n    //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later\n    var timeoutPromise;\n\n    var scheduleSearchWithTimeout = function(inputValue) {\n      timeoutPromise = $timeout(function() {\n        getMatchesAsync(inputValue);\n      }, waitTime);\n    };\n\n    var cancelPreviousTimeout = function() {\n      if (timeoutPromise) {\n        $timeout.cancel(timeoutPromise);\n      }\n    };\n\n    resetMatches();\n\n    scope.assignIsOpen = function (isOpen) {\n      isOpenSetter(originalScope, isOpen);\n    };\n\n    scope.select = function(activeIdx, evt) {\n      //called from within the $digest() cycle\n      var locals = {};\n      var model, item;\n\n      selected = true;\n      locals[parserResult.itemName] = item = scope.matches[activeIdx].model;\n      model = parserResult.modelMapper(originalScope, locals);\n      $setModelValue(originalScope, model);\n      modelCtrl.$setValidity('editable', true);\n      modelCtrl.$setValidity('parse', true);\n\n      onSelectCallback(originalScope, {\n        $item: item,\n        $model: model,\n        $label: parserResult.viewMapper(originalScope, locals),\n        $event: evt\n      });\n\n      resetMatches();\n\n      //return focus to the input element if a match was selected via a mouse click event\n      // use timeout to avoid $rootScope:inprog error\n      if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {\n        $timeout(function() { element[0].focus(); }, 0, 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(evt) {\n      //typeahead is open and an \"interesting\" key was pressed\n      if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n        return;\n      }\n\n      var shouldSelect = isSelectEvent(originalScope, {$event: evt});\n\n      /**\n       * if there's nothing selected (i.e. focusFirst) and enter or tab is hit\n       * or\n       * shift + tab is pressed to bring focus to the previous element\n       * then clear the results\n       */\n      if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {\n        resetMatches();\n        scope.$digest();\n        return;\n      }\n\n      evt.preventDefault();\n      var target;\n      switch (evt.which) {\n        case 27: // escape\n          evt.stopPropagation();\n\n          resetMatches();\n          originalScope.$digest();\n          break;\n        case 38: // up arrow\n          scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;\n          scope.$digest();\n          target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];\n          target.parentNode.scrollTop = target.offsetTop;\n          break;\n        case 40: // down arrow\n          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n          scope.$digest();\n          target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];\n          target.parentNode.scrollTop = target.offsetTop;\n          break;\n        default:\n          if (shouldSelect) {\n            scope.$apply(function() {\n              if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {\n                $$debounce(function() {\n                  scope.select(scope.activeIdx, evt);\n                }, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);\n              } else {\n                scope.select(scope.activeIdx, evt);\n              }\n            });\n          }\n      }\n    });\n\n    element.on('focus', function (evt) {\n      hasFocus = true;\n      if (minLength === 0 && !modelCtrl.$viewValue) {\n        $timeout(function() {\n          getMatchesAsync(modelCtrl.$viewValue, evt);\n        }, 0);\n      }\n    });\n\n    element.on('blur', function(evt) {\n      if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {\n        selected = true;\n        scope.$apply(function() {\n          if (angular.isObject(scope.debounceUpdate) && angular.isNumber(scope.debounceUpdate.blur)) {\n            $$debounce(function() {\n              scope.select(scope.activeIdx, evt);\n            }, scope.debounceUpdate.blur);\n          } else {\n            scope.select(scope.activeIdx, evt);\n          }\n        });\n      }\n      if (!isEditable && modelCtrl.$error.editable) {\n        modelCtrl.$setViewValue();\n        scope.$apply(function() {\n          // Reset validity as we are clearing\n          modelCtrl.$setValidity('editable', true);\n          modelCtrl.$setValidity('parse', true);\n        });\n        element.val('');\n      }\n      hasFocus = false;\n      selected = false;\n    });\n\n    // Keep reference to click handler to unbind it.\n    var dismissClickHandler = function(evt) {\n      // Issue #3973\n      // Firefox treats right click as a click on document\n      if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {\n        resetMatches();\n        if (!$rootScope.$$phase) {\n          originalScope.$digest();\n        }\n      }\n    };\n\n    $document.on('click', dismissClickHandler);\n\n    originalScope.$on('$destroy', function() {\n      $document.off('click', dismissClickHandler);\n      if (appendToBody || appendTo) {\n        $popup.remove();\n      }\n\n      if (appendToBody) {\n        angular.element($window).off('resize', fireRecalculating);\n        $document.find('body').off('scroll', fireRecalculating);\n      }\n      // Prevent jQuery cache memory leak\n      popUpEl.remove();\n\n      if (showHint) {\n          inputsContainer.remove();\n      }\n    });\n\n    var $popup = $compile(popUpEl)(scope);\n\n    if (appendToBody) {\n      $document.find('body').append($popup);\n    } else if (appendTo) {\n      angular.element(appendTo).eq(0).append($popup);\n    } else {\n      element.after($popup);\n    }\n\n    this.init = function(_modelCtrl) {\n      modelCtrl = _modelCtrl;\n      ngModelOptions = extractOptions(modelCtrl);\n\n      scope.debounceUpdate = $parse(ngModelOptions.getOption('debounce'))(originalScope);\n\n      //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n      //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n      modelCtrl.$parsers.unshift(function(inputValue) {\n        hasFocus = true;\n\n        if (minLength === 0 || inputValue && inputValue.length >= minLength) {\n          if (waitTime > 0) {\n            cancelPreviousTimeout();\n            scheduleSearchWithTimeout(inputValue);\n          } else {\n            getMatchesAsync(inputValue);\n          }\n        } else {\n          isLoadingSetter(originalScope, false);\n          cancelPreviousTimeout();\n          resetMatches();\n        }\n\n        if (isEditable) {\n          return inputValue;\n        }\n\n        if (!inputValue) {\n          // Reset in case user had typed something previously.\n          modelCtrl.$setValidity('editable', true);\n          return null;\n        }\n\n        modelCtrl.$setValidity('editable', false);\n        return undefined;\n      });\n\n      modelCtrl.$formatters.push(function(modelValue) {\n        var candidateViewValue, emptyViewValue;\n        var locals = {};\n\n        // The validity may be set to false via $parsers (see above) if\n        // the model is restricted to selected values. If the model\n        // is set manually it is considered to be valid.\n        if (!isEditable) {\n          modelCtrl.$setValidity('editable', true);\n        }\n\n        if (inputFormatter) {\n          locals.$model = modelValue;\n          return inputFormatter(originalScope, locals);\n        }\n\n        //it might happen that we don't have enough info to properly render input value\n        //we need to check for this situation and simply return model value if we can't apply custom formatting\n        locals[parserResult.itemName] = modelValue;\n        candidateViewValue = parserResult.viewMapper(originalScope, locals);\n        locals[parserResult.itemName] = undefined;\n        emptyViewValue = parserResult.viewMapper(originalScope, locals);\n\n        return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;\n      });\n    };\n\n    function extractOptions(ngModelCtrl) {\n      var ngModelOptions;\n\n      if (angular.version.minor < 6) { // in angular < 1.6 $options could be missing\n        // guarantee a value\n        ngModelOptions = ngModelCtrl.$options || {};\n\n        // mimic 1.6+ api\n        ngModelOptions.getOption = function (key) {\n          return ngModelOptions[key];\n        };\n      } else { // in angular >=1.6 $options is always present\n        ngModelOptions = ngModelCtrl.$options;\n      }\n\n      return ngModelOptions;\n    }\n  }])\n\n  .directive('uibTypeahead', function() {\n    return {\n      controller: 'UibTypeaheadController',\n      require: ['ngModel', 'uibTypeahead'],\n      link: function(originalScope, element, attrs, ctrls) {\n        ctrls[1].init(ctrls[0]);\n      }\n    };\n  })\n\n  .directive('uibTypeaheadPopup', ['$$debounce', function($$debounce) {\n    return {\n      scope: {\n        matches: '=',\n        query: '=',\n        active: '=',\n        position: '&',\n        moveInProgress: '=',\n        select: '&',\n        assignIsOpen: '&',\n        debounce: '&'\n      },\n      replace: true,\n      templateUrl: function(element, attrs) {\n        return attrs.popupTemplateUrl || 'uib/template/typeahead/typeahead-popup.html';\n      },\n      link: function(scope, element, attrs) {\n        scope.templateUrl = attrs.templateUrl;\n\n        scope.isOpen = function() {\n          var isDropdownOpen = scope.matches.length > 0;\n          scope.assignIsOpen({ isOpen: isDropdownOpen });\n          return isDropdownOpen;\n        };\n\n        scope.isActive = function(matchIdx) {\n          return scope.active === matchIdx;\n        };\n\n        scope.selectActive = function(matchIdx) {\n          scope.active = matchIdx;\n        };\n\n        scope.selectMatch = function(activeIdx, evt) {\n          var debounce = scope.debounce();\n          if (angular.isNumber(debounce) || angular.isObject(debounce)) {\n            $$debounce(function() {\n              scope.select({activeIdx: activeIdx, evt: evt});\n            }, angular.isNumber(debounce) ? debounce : debounce['default']);\n          } else {\n            scope.select({activeIdx: activeIdx, evt: evt});\n          }\n        };\n      }\n    };\n  }])\n\n  .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {\n    return {\n      scope: {\n        index: '=',\n        match: '=',\n        query: '='\n      },\n      link: function(scope, element, attrs) {\n        var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'uib/template/typeahead/typeahead-match.html';\n        $templateRequest(tplUrl).then(function(tplContent) {\n          var tplEl = angular.element(tplContent.trim());\n          element.replaceWith(tplEl);\n          $compile(tplEl)(scope);\n        });\n      }\n    };\n  }])\n\n  .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {\n    var isSanitizePresent;\n    isSanitizePresent = $injector.has('$sanitize');\n\n    function escapeRegexp(queryToEscape) {\n      // Regex: capture the whole query string and replace it with the string that will be used to match\n      // the results, for example if the capture is \"a\" the result will be \\a\n      return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n    }\n\n    function containsHtml(matchItem) {\n      return /<.*>/g.test(matchItem);\n    }\n\n    return function(matchItem, query) {\n      if (!isSanitizePresent && containsHtml(matchItem)) {\n        $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger\n      }\n      matchItem = query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem; // Replaces the capture string with a the same string inside of a \"strong\" tag\n      if (!isSanitizePresent) {\n        matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive\n      }\n      return matchItem;\n    };\n  }]);\n\nangular.module(\"uib/template/accordion/accordion-group.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/accordion/accordion-group.html\",\n    \"<div role=\\\"tab\\\" id=\\\"{{::headingId}}\\\" aria-selected=\\\"{{isOpen}}\\\" class=\\\"panel-heading\\\" ng-keypress=\\\"toggleOpen($event)\\\">\\n\" +\n    \"  <h4 class=\\\"panel-title\\\">\\n\" +\n    \"    <a role=\\\"button\\\" data-toggle=\\\"collapse\\\" href aria-expanded=\\\"{{isOpen}}\\\" aria-controls=\\\"{{::panelId}}\\\" tabindex=\\\"0\\\" class=\\\"accordion-toggle\\\" ng-click=\\\"toggleOpen()\\\" uib-accordion-transclude=\\\"heading\\\" ng-disabled=\\\"isDisabled\\\" uib-tabindex-toggle><span uib-accordion-header ng-class=\\\"{'text-muted': isDisabled}\\\">{{heading}}</span></a>\\n\" +\n    \"  </h4>\\n\" +\n    \"</div>\\n\" +\n    \"<div id=\\\"{{::panelId}}\\\" aria-labelledby=\\\"{{::headingId}}\\\" aria-hidden=\\\"{{!isOpen}}\\\" role=\\\"tabpanel\\\" class=\\\"panel-collapse collapse\\\" uib-collapse=\\\"!isOpen\\\">\\n\" +\n    \"  <div class=\\\"panel-body\\\" ng-transclude></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/accordion/accordion.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/accordion/accordion.html\",\n    \"<div role=\\\"tablist\\\" class=\\\"panel-group\\\" ng-transclude></div>\");\n}]);\n\nangular.module(\"uib/template/alert/alert.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/alert/alert.html\",\n    \"<button ng-show=\\\"closeable\\\" type=\\\"button\\\" class=\\\"close\\\" ng-click=\\\"close({$event: $event})\\\">\\n\" +\n    \"  <span aria-hidden=\\\"true\\\">&times;</span>\\n\" +\n    \"  <span class=\\\"sr-only\\\">Close</span>\\n\" +\n    \"</button>\\n\" +\n    \"<div ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/carousel/carousel.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/carousel/carousel.html\",\n    \"<div class=\\\"carousel-inner\\\" ng-transclude></div>\\n\" +\n    \"<a role=\\\"button\\\" href class=\\\"left carousel-control\\\" ng-click=\\\"prev()\\\" ng-class=\\\"{ disabled: isPrevDisabled() }\\\" ng-show=\\\"slides.length > 1\\\">\\n\" +\n    \"  <span aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-left\\\"></span>\\n\" +\n    \"  <span class=\\\"sr-only\\\">previous</span>\\n\" +\n    \"</a>\\n\" +\n    \"<a role=\\\"button\\\" href class=\\\"right carousel-control\\\" ng-click=\\\"next()\\\" ng-class=\\\"{ disabled: isNextDisabled() }\\\" ng-show=\\\"slides.length > 1\\\">\\n\" +\n    \"  <span aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-right\\\"></span>\\n\" +\n    \"  <span class=\\\"sr-only\\\">next</span>\\n\" +\n    \"</a>\\n\" +\n    \"<ol class=\\\"carousel-indicators\\\" ng-show=\\\"slides.length > 1\\\">\\n\" +\n    \"  <li ng-repeat=\\\"slide in slides | orderBy:indexOfSlide track by $index\\\" ng-class=\\\"{ active: isActive(slide) }\\\" ng-click=\\\"select(slide)\\\">\\n\" +\n    \"    <span class=\\\"sr-only\\\">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if=\\\"isActive(slide)\\\">, currently active</span></span>\\n\" +\n    \"  </li>\\n\" +\n    \"</ol>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/carousel/slide.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/carousel/slide.html\",\n    \"<div class=\\\"text-center\\\" ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepicker/datepicker.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/datepicker/datepicker.html\",\n    \"<div ng-switch=\\\"datepickerMode\\\">\\n\" +\n    \"  <div uib-daypicker ng-switch-when=\\\"day\\\" tabindex=\\\"0\\\" class=\\\"uib-daypicker\\\"></div>\\n\" +\n    \"  <div uib-monthpicker ng-switch-when=\\\"month\\\" tabindex=\\\"0\\\" class=\\\"uib-monthpicker\\\"></div>\\n\" +\n    \"  <div uib-yearpicker ng-switch-when=\\\"year\\\" tabindex=\\\"0\\\" class=\\\"uib-yearpicker\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepicker/day.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/datepicker/day.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{::uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left uib-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-left\\\"></i><span class=\\\"sr-only\\\">previous</span></button></th>\\n\" +\n    \"      <th colspan=\\\"{{::5 + showWeeks}}\\\"><button id=\\\"{{::uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm uib-title\\\" ng-click=\\\"toggleMode()\\\" ng-disabled=\\\"datepickerMode === maxMode\\\" tabindex=\\\"-1\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right uib-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-right\\\"></i><span class=\\\"sr-only\\\">next</span></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th ng-if=\\\"showWeeks\\\" class=\\\"text-center\\\"></th>\\n\" +\n    \"      <th ng-repeat=\\\"label in ::labels track by $index\\\" class=\\\"text-center\\\"><small aria-label=\\\"{{::label.full}}\\\">{{::label.abbr}}</small></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr class=\\\"uib-weeks\\\" ng-repeat=\\\"row in rows track by $index\\\" role=\\\"row\\\">\\n\" +\n    \"      <td ng-if=\\\"showWeeks\\\" class=\\\"text-center h6\\\"><em>{{ weekNumbers[$index] }}</em></td>\\n\" +\n    \"      <td ng-repeat=\\\"dt in row\\\" class=\\\"uib-day text-center\\\" role=\\\"gridcell\\\"\\n\" +\n    \"        id=\\\"{{::dt.uid}}\\\"\\n\" +\n    \"        ng-class=\\\"::dt.customClass\\\">\\n\" +\n    \"        <button type=\\\"button\\\" class=\\\"btn btn-default btn-sm\\\"\\n\" +\n    \"          uib-is-class=\\\"\\n\" +\n    \"            'btn-info' for selectedDt,\\n\" +\n    \"            'active' for activeDt\\n\" +\n    \"            on dt\\\"\\n\" +\n    \"          ng-click=\\\"select(dt.date)\\\"\\n\" +\n    \"          ng-disabled=\\\"::dt.disabled\\\"\\n\" +\n    \"          tabindex=\\\"-1\\\"><span ng-class=\\\"::{'text-muted': dt.secondary, 'text-info': dt.current}\\\">{{::dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepicker/month.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/datepicker/month.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{::uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left uib-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-left\\\"></i><span class=\\\"sr-only\\\">previous</span></button></th>\\n\" +\n    \"      <th colspan=\\\"{{::yearHeaderColspan}}\\\"><button id=\\\"{{::uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm uib-title\\\" ng-click=\\\"toggleMode()\\\" ng-disabled=\\\"datepickerMode === maxMode\\\" tabindex=\\\"-1\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right uib-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-right\\\"></i><span class=\\\"sr-only\\\">next</span></i></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr class=\\\"uib-months\\\" ng-repeat=\\\"row in rows track by $index\\\" role=\\\"row\\\">\\n\" +\n    \"      <td ng-repeat=\\\"dt in row\\\" class=\\\"uib-month text-center\\\" role=\\\"gridcell\\\"\\n\" +\n    \"        id=\\\"{{::dt.uid}}\\\"\\n\" +\n    \"        ng-class=\\\"::dt.customClass\\\">\\n\" +\n    \"        <button type=\\\"button\\\" class=\\\"btn btn-default\\\"\\n\" +\n    \"          uib-is-class=\\\"\\n\" +\n    \"            'btn-info' for selectedDt,\\n\" +\n    \"            'active' for activeDt\\n\" +\n    \"            on dt\\\"\\n\" +\n    \"          ng-click=\\\"select(dt.date)\\\"\\n\" +\n    \"          ng-disabled=\\\"::dt.disabled\\\"\\n\" +\n    \"          tabindex=\\\"-1\\\"><span ng-class=\\\"::{'text-info': dt.current}\\\">{{::dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepicker/popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"uib/template/datepicker/popup.html\",\n    \"<div>\\n\" +\n    \"  <ul class=\\\"uib-datepicker-popup dropdown-menu uib-position-measure\\\" dropdown-nested ng-if=\\\"isOpen\\\" ng-keydown=\\\"keydown($event)\\\" ng-click=\\\"$event.stopPropagation()\\\">\\n\" +\n    \"    <li ng-transclude></li>\\n\" +\n    \"    <li ng-if=\\\"showButtonBar\\\" class=\\\"uib-button-bar\\\">\\n\" +\n    \"      <span class=\\\"btn-group pull-left\\\">\\n\" +\n    \"        <button type=\\\"button\\\" class=\\\"btn btn-sm btn-info uib-datepicker-current\\\" ng-click=\\\"select('today', $event)\\\" ng-disabled=\\\"isDisabled('today')\\\">{{ getText('current') }}</button>\\n\" +\n    \"        <button type=\\\"button\\\" class=\\\"btn btn-sm btn-danger uib-clear\\\" ng-click=\\\"select(null, $event)\\\">{{ getText('clear') }}</button>\\n\" +\n    \"      </span>\\n\" +\n    \"      <button type=\\\"button\\\" class=\\\"btn btn-sm btn-success pull-right uib-close\\\" ng-click=\\\"close($event)\\\">{{ getText('close') }}</button>\\n\" +\n    \"    </li>\\n\" +\n    \"  </ul>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepicker/year.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/datepicker/year.html\",\n    \"<table role=\\\"grid\\\" aria-labelledby=\\\"{{::uniqueId}}-title\\\" aria-activedescendant=\\\"{{activeDateId}}\\\">\\n\" +\n    \"  <thead>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-left uib-left\\\" ng-click=\\\"move(-1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-left\\\"></i><span class=\\\"sr-only\\\">previous</span></button></th>\\n\" +\n    \"      <th colspan=\\\"{{::columns - 2}}\\\"><button id=\\\"{{::uniqueId}}-title\\\" role=\\\"heading\\\" aria-live=\\\"assertive\\\" aria-atomic=\\\"true\\\" type=\\\"button\\\" class=\\\"btn btn-default btn-sm uib-title\\\" ng-click=\\\"toggleMode()\\\" ng-disabled=\\\"datepickerMode === maxMode\\\" tabindex=\\\"-1\\\"><strong>{{title}}</strong></button></th>\\n\" +\n    \"      <th><button type=\\\"button\\\" class=\\\"btn btn-default btn-sm pull-right uib-right\\\" ng-click=\\\"move(1)\\\" tabindex=\\\"-1\\\"><i aria-hidden=\\\"true\\\" class=\\\"glyphicon glyphicon-chevron-right\\\"></i><span class=\\\"sr-only\\\">next</span></button></th>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </thead>\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr class=\\\"uib-years\\\" ng-repeat=\\\"row in rows track by $index\\\" role=\\\"row\\\">\\n\" +\n    \"      <td ng-repeat=\\\"dt in row\\\" class=\\\"uib-year text-center\\\" role=\\\"gridcell\\\"\\n\" +\n    \"        id=\\\"{{::dt.uid}}\\\"\\n\" +\n    \"        ng-class=\\\"::dt.customClass\\\">\\n\" +\n    \"        <button type=\\\"button\\\" class=\\\"btn btn-default\\\"\\n\" +\n    \"          uib-is-class=\\\"\\n\" +\n    \"            'btn-info' for selectedDt,\\n\" +\n    \"            'active' for activeDt\\n\" +\n    \"            on dt\\\"\\n\" +\n    \"          ng-click=\\\"select(dt.date)\\\"\\n\" +\n    \"          ng-disabled=\\\"::dt.disabled\\\"\\n\" +\n    \"          tabindex=\\\"-1\\\"><span ng-class=\\\"::{'text-info': dt.current}\\\">{{::dt.label}}</span></button>\\n\" +\n    \"      </td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/datepickerPopup/popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/datepickerPopup/popup.html\",\n    \"<ul role=\\\"presentation\\\" class=\\\"uib-datepicker-popup dropdown-menu uib-position-measure\\\" dropdown-nested ng-if=\\\"isOpen\\\" ng-keydown=\\\"keydown($event)\\\" ng-click=\\\"$event.stopPropagation()\\\">\\n\" +\n    \"  <li ng-transclude></li>\\n\" +\n    \"  <li ng-if=\\\"showButtonBar\\\" class=\\\"uib-button-bar\\\">\\n\" +\n    \"    <span class=\\\"btn-group pull-left\\\">\\n\" +\n    \"      <button type=\\\"button\\\" class=\\\"btn btn-sm btn-info uib-datepicker-current\\\" ng-click=\\\"select('today', $event)\\\" ng-disabled=\\\"isDisabled('today')\\\">{{ getText('current') }}</button>\\n\" +\n    \"      <button type=\\\"button\\\" class=\\\"btn btn-sm btn-danger uib-clear\\\" ng-click=\\\"select(null, $event)\\\">{{ getText('clear') }}</button>\\n\" +\n    \"    </span>\\n\" +\n    \"    <button type=\\\"button\\\" class=\\\"btn btn-sm btn-success pull-right uib-close\\\" ng-click=\\\"close($event)\\\">{{ getText('close') }}</button>\\n\" +\n    \"  </li>\\n\" +\n    \"</ul>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/modal/backdrop.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"uib/template/modal/backdrop.html\",\n    \"<div class=\\\"modal-backdrop\\\"\\n\" +\n    \"     uib-modal-animation-class=\\\"fade\\\"\\n\" +\n    \"     modal-in-class=\\\"in\\\"\\n\" +\n    \"     ng-style=\\\"{'z-index': 1040 + (index && 1 || 0) + index*10}\\\"\\n\" +\n    \"></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/modal/window.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/modal/window.html\",\n    \"<div class=\\\"modal-dialog {{size ? 'modal-' + size : ''}}\\\"><div class=\\\"modal-content\\\" uib-modal-transclude></div></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/pager/pager.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/pager/pager.html\",\n    \"<li ng-class=\\\"{disabled: noPrevious()||ngDisabled, previous: align}\\\"><a href ng-click=\\\"selectPage(page - 1, $event)\\\" ng-disabled=\\\"noPrevious()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\\n\" +\n    \"<li ng-class=\\\"{disabled: noNext()||ngDisabled, next: align}\\\"><a href ng-click=\\\"selectPage(page + 1, $event)\\\" ng-disabled=\\\"noNext()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/pagination/pagination.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/pagination/pagination.html\",\n    \"<li role=\\\"menuitem\\\" ng-if=\\\"::boundaryLinks\\\" ng-class=\\\"{disabled: noPrevious()||ngDisabled}\\\" class=\\\"pagination-first\\\"><a href ng-click=\\\"selectPage(1, $event)\\\" ng-disabled=\\\"noPrevious()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('first')}}</a></li>\\n\" +\n    \"<li role=\\\"menuitem\\\" ng-if=\\\"::directionLinks\\\" ng-class=\\\"{disabled: noPrevious()||ngDisabled}\\\" class=\\\"pagination-prev\\\"><a href ng-click=\\\"selectPage(page - 1, $event)\\\" ng-disabled=\\\"noPrevious()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\\n\" +\n    \"<li role=\\\"menuitem\\\" ng-repeat=\\\"page in pages track by $index\\\" ng-class=\\\"{active: page.active,disabled: ngDisabled&&!page.active}\\\" class=\\\"pagination-page\\\"><a href ng-click=\\\"selectPage(page.number, $event)\\\" ng-disabled=\\\"ngDisabled&&!page.active\\\" uib-tabindex-toggle>{{page.text}}</a></li>\\n\" +\n    \"<li role=\\\"menuitem\\\" ng-if=\\\"::directionLinks\\\" ng-class=\\\"{disabled: noNext()||ngDisabled}\\\" class=\\\"pagination-next\\\"><a href ng-click=\\\"selectPage(page + 1, $event)\\\" ng-disabled=\\\"noNext()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\\n\" +\n    \"<li role=\\\"menuitem\\\" ng-if=\\\"::boundaryLinks\\\" ng-class=\\\"{disabled: noNext()||ngDisabled}\\\" class=\\\"pagination-last\\\"><a href ng-click=\\\"selectPage(totalPages, $event)\\\" ng-disabled=\\\"noNext()||ngDisabled\\\" uib-tabindex-toggle>{{::getText('last')}}</a></li>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/tooltip/tooltip-html-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/tooltip/tooltip-html-popup.html\",\n    \"<div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"<div class=\\\"tooltip-inner\\\" ng-bind-html=\\\"contentExp()\\\"></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/tooltip/tooltip-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/tooltip/tooltip-popup.html\",\n    \"<div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"<div class=\\\"tooltip-inner\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/tooltip/tooltip-template-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/tooltip/tooltip-template-popup.html\",\n    \"<div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"<div class=\\\"tooltip-inner\\\"\\n\" +\n    \"  uib-tooltip-template-transclude=\\\"contentExp()\\\"\\n\" +\n    \"  tooltip-template-transclude-scope=\\\"originScope()\\\"></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/popover/popover-html.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/popover/popover-html.html\",\n    \"<div class=\\\"arrow\\\"></div>\\n\" +\n    \"\\n\" +\n    \"<div class=\\\"popover-inner\\\">\\n\" +\n    \"    <h3 class=\\\"popover-title\\\" ng-bind=\\\"uibTitle\\\" ng-if=\\\"uibTitle\\\"></h3>\\n\" +\n    \"    <div class=\\\"popover-content\\\" ng-bind-html=\\\"contentExp()\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/popover/popover-template.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/popover/popover-template.html\",\n    \"<div class=\\\"arrow\\\"></div>\\n\" +\n    \"\\n\" +\n    \"<div class=\\\"popover-inner\\\">\\n\" +\n    \"    <h3 class=\\\"popover-title\\\" ng-bind=\\\"uibTitle\\\" ng-if=\\\"uibTitle\\\"></h3>\\n\" +\n    \"    <div class=\\\"popover-content\\\"\\n\" +\n    \"      uib-tooltip-template-transclude=\\\"contentExp()\\\"\\n\" +\n    \"      tooltip-template-transclude-scope=\\\"originScope()\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/popover/popover.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/popover/popover.html\",\n    \"<div class=\\\"arrow\\\"></div>\\n\" +\n    \"\\n\" +\n    \"<div class=\\\"popover-inner\\\">\\n\" +\n    \"    <h3 class=\\\"popover-title\\\" ng-bind=\\\"uibTitle\\\" ng-if=\\\"uibTitle\\\"></h3>\\n\" +\n    \"    <div class=\\\"popover-content\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/progressbar/bar.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/progressbar/bar.html\",\n    \"<div class=\\\"progress-bar\\\" ng-class=\\\"type && 'progress-bar-' + type\\\" role=\\\"progressbar\\\" aria-valuenow=\\\"{{value}}\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{max}}\\\" ng-style=\\\"{width: (percent < 100 ? percent : 100) + '%'}\\\" aria-valuetext=\\\"{{percent | number:0}}%\\\" aria-labelledby=\\\"{{::title}}\\\" ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/progressbar/progress.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/progressbar/progress.html\",\n    \"<div class=\\\"progress\\\" ng-transclude aria-labelledby=\\\"{{::title}}\\\"></div>\");\n}]);\n\nangular.module(\"uib/template/progressbar/progressbar.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/progressbar/progressbar.html\",\n    \"<div class=\\\"progress\\\">\\n\" +\n    \"  <div class=\\\"progress-bar\\\" ng-class=\\\"type && 'progress-bar-' + type\\\" role=\\\"progressbar\\\" aria-valuenow=\\\"{{value}}\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{max}}\\\" ng-style=\\\"{width: (percent < 100 ? percent : 100) + '%'}\\\" aria-valuetext=\\\"{{percent | number:0}}%\\\" aria-labelledby=\\\"{{::title}}\\\" ng-transclude></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/rating/rating.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/rating/rating.html\",\n    \"<span ng-mouseleave=\\\"reset()\\\" ng-keydown=\\\"onKeydown($event)\\\" tabindex=\\\"0\\\" role=\\\"slider\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"{{range.length}}\\\" aria-valuenow=\\\"{{value}}\\\" aria-valuetext=\\\"{{title}}\\\">\\n\" +\n    \"    <span ng-repeat-start=\\\"r in range track by $index\\\" class=\\\"sr-only\\\">({{ $index < value ? '*' : ' ' }})</span>\\n\" +\n    \"    <i ng-repeat-end ng-mouseenter=\\\"enter($index + 1)\\\" ng-click=\\\"rate($index + 1)\\\" class=\\\"glyphicon\\\" ng-class=\\\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\\\" ng-attr-title=\\\"{{r.title}}\\\"></i>\\n\" +\n    \"</span>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/tabs/tab.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/tabs/tab.html\",\n    \"<li ng-class=\\\"[{active: active, disabled: disabled}, classes]\\\" class=\\\"uib-tab nav-item\\\">\\n\" +\n    \"  <a href ng-click=\\\"select($event)\\\" class=\\\"nav-link\\\" uib-tab-heading-transclude>{{heading}}</a>\\n\" +\n    \"</li>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/tabs/tabset.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/tabs/tabset.html\",\n    \"<div>\\n\" +\n    \"  <ul class=\\\"nav nav-{{tabset.type || 'tabs'}}\\\" ng-class=\\\"{'nav-stacked': vertical, 'nav-justified': justified}\\\" ng-transclude></ul>\\n\" +\n    \"  <div class=\\\"tab-content\\\">\\n\" +\n    \"    <div class=\\\"tab-pane\\\"\\n\" +\n    \"         ng-repeat=\\\"tab in tabset.tabs\\\"\\n\" +\n    \"         ng-class=\\\"{active: tabset.active === tab.index}\\\"\\n\" +\n    \"         uib-tab-content-transclude=\\\"tab\\\">\\n\" +\n    \"    </div>\\n\" +\n    \"  </div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/timepicker/timepicker.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/timepicker/timepicker.html\",\n    \"<table class=\\\"uib-timepicker\\\">\\n\" +\n    \"  <tbody>\\n\" +\n    \"    <tr class=\\\"text-center\\\" ng-show=\\\"::showSpinners\\\">\\n\" +\n    \"      <td class=\\\"uib-increment hours\\\"><a ng-click=\\\"incrementHours()\\\" ng-class=\\\"{disabled: noIncrementHours()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noIncrementHours()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-up\\\"></span></a></td>\\n\" +\n    \"      <td>&nbsp;</td>\\n\" +\n    \"      <td class=\\\"uib-increment minutes\\\"><a ng-click=\\\"incrementMinutes()\\\" ng-class=\\\"{disabled: noIncrementMinutes()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noIncrementMinutes()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-up\\\"></span></a></td>\\n\" +\n    \"      <td ng-show=\\\"showSeconds\\\">&nbsp;</td>\\n\" +\n    \"      <td ng-show=\\\"showSeconds\\\" class=\\\"uib-increment seconds\\\"><a ng-click=\\\"incrementSeconds()\\\" ng-class=\\\"{disabled: noIncrementSeconds()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noIncrementSeconds()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-up\\\"></span></a></td>\\n\" +\n    \"      <td ng-show=\\\"showMeridian\\\"></td>\\n\" +\n    \"    </tr>\\n\" +\n    \"    <tr>\\n\" +\n    \"      <td class=\\\"form-group uib-time hours\\\" ng-class=\\\"{'has-error': invalidHours}\\\">\\n\" +\n    \"        <input type=\\\"text\\\" placeholder=\\\"HH\\\" ng-model=\\\"hours\\\" ng-change=\\\"updateHours()\\\" class=\\\"form-control text-center\\\" ng-readonly=\\\"::readonlyInput\\\" maxlength=\\\"2\\\" tabindex=\\\"{{::tabindex}}\\\" ng-disabled=\\\"noIncrementHours()\\\" ng-blur=\\\"blur()\\\">\\n\" +\n    \"      </td>\\n\" +\n    \"      <td class=\\\"uib-separator\\\">:</td>\\n\" +\n    \"      <td class=\\\"form-group uib-time minutes\\\" ng-class=\\\"{'has-error': invalidMinutes}\\\">\\n\" +\n    \"        <input type=\\\"text\\\" placeholder=\\\"MM\\\" ng-model=\\\"minutes\\\" ng-change=\\\"updateMinutes()\\\" class=\\\"form-control text-center\\\" ng-readonly=\\\"::readonlyInput\\\" maxlength=\\\"2\\\" tabindex=\\\"{{::tabindex}}\\\" ng-disabled=\\\"noIncrementMinutes()\\\" ng-blur=\\\"blur()\\\">\\n\" +\n    \"      </td>\\n\" +\n    \"      <td ng-show=\\\"showSeconds\\\" class=\\\"uib-separator\\\">:</td>\\n\" +\n    \"      <td class=\\\"form-group uib-time seconds\\\" ng-class=\\\"{'has-error': invalidSeconds}\\\" ng-show=\\\"showSeconds\\\">\\n\" +\n    \"        <input type=\\\"text\\\" placeholder=\\\"SS\\\" ng-model=\\\"seconds\\\" ng-change=\\\"updateSeconds()\\\" class=\\\"form-control text-center\\\" ng-readonly=\\\"readonlyInput\\\" maxlength=\\\"2\\\" tabindex=\\\"{{::tabindex}}\\\" ng-disabled=\\\"noIncrementSeconds()\\\" ng-blur=\\\"blur()\\\">\\n\" +\n    \"      </td>\\n\" +\n    \"      <td ng-show=\\\"showMeridian\\\" class=\\\"uib-time am-pm\\\"><button type=\\\"button\\\" ng-class=\\\"{disabled: noToggleMeridian()}\\\" class=\\\"btn btn-default text-center\\\" ng-click=\\\"toggleMeridian()\\\" ng-disabled=\\\"noToggleMeridian()\\\" tabindex=\\\"{{::tabindex}}\\\">{{meridian}}</button></td>\\n\" +\n    \"    </tr>\\n\" +\n    \"    <tr class=\\\"text-center\\\" ng-show=\\\"::showSpinners\\\">\\n\" +\n    \"      <td class=\\\"uib-decrement hours\\\"><a ng-click=\\\"decrementHours()\\\" ng-class=\\\"{disabled: noDecrementHours()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noDecrementHours()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-down\\\"></span></a></td>\\n\" +\n    \"      <td>&nbsp;</td>\\n\" +\n    \"      <td class=\\\"uib-decrement minutes\\\"><a ng-click=\\\"decrementMinutes()\\\" ng-class=\\\"{disabled: noDecrementMinutes()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noDecrementMinutes()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-down\\\"></span></a></td>\\n\" +\n    \"      <td ng-show=\\\"showSeconds\\\">&nbsp;</td>\\n\" +\n    \"      <td ng-show=\\\"showSeconds\\\" class=\\\"uib-decrement seconds\\\"><a ng-click=\\\"decrementSeconds()\\\" ng-class=\\\"{disabled: noDecrementSeconds()}\\\" class=\\\"btn btn-link\\\" ng-disabled=\\\"noDecrementSeconds()\\\" tabindex=\\\"-1\\\"><span class=\\\"glyphicon glyphicon-chevron-down\\\"></span></a></td>\\n\" +\n    \"      <td ng-show=\\\"showMeridian\\\"></td>\\n\" +\n    \"    </tr>\\n\" +\n    \"  </tbody>\\n\" +\n    \"</table>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/typeahead/typeahead-match.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/typeahead/typeahead-match.html\",\n    \"<a href\\n\" +\n    \"   tabindex=\\\"-1\\\"\\n\" +\n    \"   ng-bind-html=\\\"match.label | uibTypeaheadHighlight:query\\\"\\n\" +\n    \"   ng-attr-title=\\\"{{match.label}}\\\"></a>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"uib/template/typeahead/typeahead-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"uib/template/typeahead/typeahead-popup.html\",\n    \"<ul class=\\\"dropdown-menu\\\" ng-show=\\\"isOpen() && !moveInProgress\\\" ng-style=\\\"{top: position().top+'px', left: position().left+'px'}\\\" role=\\\"listbox\\\" aria-hidden=\\\"{{!isOpen()}}\\\">\\n\" +\n    \"    <li class=\\\"uib-typeahead-match\\\" ng-repeat=\\\"match in matches track by $index\\\" ng-class=\\\"{active: isActive($index) }\\\" ng-mouseenter=\\\"selectActive($index)\\\" ng-click=\\\"selectMatch($index, $event)\\\" role=\\\"option\\\" id=\\\"{{::match.id}}\\\">\\n\" +\n    \"        <div uib-typeahead-match index=\\\"$index\\\" match=\\\"match\\\" query=\\\"query\\\" template-url=\\\"templateUrl\\\"></div>\\n\" +\n    \"    </li>\\n\" +\n    \"</ul>\\n\" +\n    \"\");\n}]);\nangular.module('ui.bootstrap.carousel').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibCarouselCss && angular.element(document).find('head').prepend('<style type=\"text/css\">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'); angular.$$uibCarouselCss = true; });\nangular.module('ui.bootstrap.datepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerCss && angular.element(document).find('head').prepend('<style type=\"text/css\">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'); angular.$$uibDatepickerCss = true; });\nangular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibPositionCss && angular.element(document).find('head').prepend('<style type=\"text/css\">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'); angular.$$uibPositionCss = true; });\nangular.module('ui.bootstrap.datepickerPopup').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type=\"text/css\">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });\nangular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type=\"text/css\">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });\nangular.module('ui.bootstrap.timepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type=\"text/css\">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });\nangular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type=\"text/css\">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });","require('./dist/ui-bootstrap-tpls');\n\nmodule.exports = 'ui.bootstrap';\n","/**\n * @license AngularJS v1.8.3\n * (c) 2010-2020 Google LLC. http://angularjs.org\n * License: MIT\n */\n(function(window, angular) {'use strict';\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n *     Any commits to this file should be reviewed with security in mind.  *\n *   Changes to this file can potentially create security vulnerabilities. *\n *          An approval from 2 Core members with history of modifying      *\n *                         this file is required.                          *\n *                                                                         *\n *  Does the change somehow allow for arbitrary javascript to be executed? *\n *    Or allows for someone to change the prototype of built-in objects?   *\n *     Or gives undesired access to variables likes document or window?    *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\nvar $sanitizeMinErr = angular.$$minErr('$sanitize');\nvar bind;\nvar extend;\nvar forEach;\nvar isArray;\nvar isDefined;\nvar lowercase;\nvar noop;\nvar nodeContains;\nvar htmlParser;\nvar htmlSanitizeWriter;\n\n/**\n * @ngdoc module\n * @name ngSanitize\n * @description\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\n * See {@link ngSanitize.$sanitize `$sanitize`} for usage.\n */\n\n/**\n * @ngdoc service\n * @name $sanitize\n * @kind function\n *\n * @description\n *   Sanitizes an html string by stripping all potentially dangerous tokens.\n *\n *   The input is sanitized by parsing the HTML into tokens. All safe tokens (from a trusted URI list) are\n *   then serialized back to a properly escaped HTML string. This means that no unsafe input can make\n *   it into the returned string.\n *\n *   The trusted URIs for URL sanitization of attribute values is configured using the functions\n *   `aHrefSanitizationTrustedUrlList` and `imgSrcSanitizationTrustedUrlList` of {@link $compileProvider}.\n *\n *   The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.\n *\n * @param {string} html HTML input.\n * @returns {string} Sanitized HTML.\n *\n * @example\n   <example module=\"sanitizeExample\" deps=\"angular-sanitize.js\" name=\"sanitize-service\">\n   <file name=\"index.html\">\n     <script>\n         angular.module('sanitizeExample', ['ngSanitize'])\n           .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {\n             $scope.snippet =\n               '<p style=\"color:blue\">an html\\n' +\n               '<em onmouseover=\"this.textContent=\\'PWN3D!\\'\">click here</em>\\n' +\n               'snippet</p>';\n             $scope.deliberatelyTrustDangerousSnippet = function() {\n               return $sce.trustAsHtml($scope.snippet);\n             };\n           }]);\n     </script>\n     <div ng-controller=\"ExampleController\">\n        Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <td>Directive</td>\n           <td>How</td>\n           <td>Source</td>\n           <td>Rendered</td>\n         </tr>\n         <tr id=\"bind-html-with-sanitize\">\n           <td>ng-bind-html</td>\n           <td>Automatically uses $sanitize</td>\n           <td><pre>&lt;div ng-bind-html=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind-html=\"snippet\"></div></td>\n         </tr>\n         <tr id=\"bind-html-with-trust\">\n           <td>ng-bind-html</td>\n           <td>Bypass $sanitize by explicitly trusting the dangerous value</td>\n           <td>\n           <pre>&lt;div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"&gt;\n&lt;/div&gt;</pre>\n           </td>\n           <td><div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\"></div></td>\n         </tr>\n         <tr id=\"bind-default\">\n           <td>ng-bind</td>\n           <td>Automatically escapes</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br/>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n       </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should sanitize the html snippet by default', function() {\n       expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).\n         toBe('<p>an html\\n<em>click here</em>\\nsnippet</p>');\n     });\n\n     it('should inline raw snippet if bound to a trusted value', function() {\n       expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).\n         toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n              \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n              \"snippet</p>\");\n     });\n\n     it('should escape snippet without any filter', function() {\n       expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).\n         toBe(\"&lt;p style=\\\"color:blue\\\"&gt;an html\\n\" +\n              \"&lt;em onmouseover=\\\"this.textContent='PWN3D!'\\\"&gt;click here&lt;/em&gt;\\n\" +\n              \"snippet&lt;/p&gt;\");\n     });\n\n     it('should update', function() {\n       element(by.model('snippet')).clear();\n       element(by.model('snippet')).sendKeys('new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).\n         toBe('new <b>text</b>');\n       expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).toBe(\n         'new <b onclick=\"alert(1)\">text</b>');\n       expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).toBe(\n         \"new &lt;b onclick=\\\"alert(1)\\\"&gt;text&lt;/b&gt;\");\n     });\n   </file>\n   </example>\n */\n\n\n/**\n * @ngdoc provider\n * @name $sanitizeProvider\n * @this\n *\n * @description\n * Creates and configures {@link $sanitize} instance.\n */\nfunction $SanitizeProvider() {\n  var hasBeenInstantiated = false;\n  var svgEnabled = false;\n\n  this.$get = ['$$sanitizeUri', function($$sanitizeUri) {\n    hasBeenInstantiated = true;\n    if (svgEnabled) {\n      extend(validElements, svgElements);\n    }\n    return function(html) {\n      var buf = [];\n      htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {\n        return !/^unsafe:/.test($$sanitizeUri(uri, isImage));\n      }));\n      return buf.join('');\n    };\n  }];\n\n\n  /**\n   * @ngdoc method\n   * @name $sanitizeProvider#enableSvg\n   * @kind function\n   *\n   * @description\n   * Enables a subset of svg to be supported by the sanitizer.\n   *\n   * <div class=\"alert alert-warning\">\n   *   <p>By enabling this setting without taking other precautions, you might expose your\n   *   application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned\n   *   outside of the containing element and be rendered over other elements on the page (e.g. a login\n   *   link). Such behavior can then result in phishing incidents.</p>\n   *\n   *   <p>To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg\n   *   tags within the sanitized content:</p>\n   *\n   *   <br>\n   *\n   *   <pre><code>\n   *   .rootOfTheIncludedContent svg {\n   *     overflow: hidden !important;\n   *   }\n   *   </code></pre>\n   * </div>\n   *\n   * @param {boolean=} flag Enable or disable SVG support in the sanitizer.\n   * @returns {boolean|$sanitizeProvider} Returns the currently configured value if called\n   *    without an argument or self for chaining otherwise.\n   */\n  this.enableSvg = function(enableSvg) {\n    if (isDefined(enableSvg)) {\n      svgEnabled = enableSvg;\n      return this;\n    } else {\n      return svgEnabled;\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $sanitizeProvider#addValidElements\n   * @kind function\n   *\n   * @description\n   * Extends the built-in lists of valid HTML/SVG elements, i.e. elements that are considered safe\n   * and are not stripped off during sanitization. You can extend the following lists of elements:\n   *\n   * - `htmlElements`: A list of elements (tag names) to extend the current list of safe HTML\n   *   elements. HTML elements considered safe will not be removed during sanitization. All other\n   *   elements will be stripped off.\n   *\n   * - `htmlVoidElements`: This is similar to `htmlElements`, but marks the elements as\n   *   \"void elements\" (similar to HTML\n   *   [void elements](https://rawgit.com/w3c/html/html5.1-2/single-page.html#void-elements)). These\n   *   elements have no end tag and cannot have content.\n   *\n   * - `svgElements`: This is similar to `htmlElements`, but for SVG elements. This list is only\n   *   taken into account if SVG is {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for\n   *   `$sanitize`.\n   *\n   * <div class=\"alert alert-info\">\n   *   This method must be called during the {@link angular.Module#config config} phase. Once the\n   *   `$sanitize` service has been instantiated, this method has no effect.\n   * </div>\n   *\n   * <div class=\"alert alert-warning\">\n   *   Keep in mind that extending the built-in lists of elements may expose your app to XSS or\n   *   other vulnerabilities. Be very mindful of the elements you add.\n   * </div>\n   *\n   * @param {Array<String>|Object} elements - A list of valid HTML elements or an object with one or\n   *   more of the following properties:\n   *   - **htmlElements** - `{Array<String>}` - A list of elements to extend the current list of\n   *     HTML elements.\n   *   - **htmlVoidElements** - `{Array<String>}` - A list of elements to extend the current list of\n   *     void HTML elements; i.e. elements that do not have an end tag.\n   *   - **svgElements** - `{Array<String>}` - A list of elements to extend the current list of SVG\n   *     elements. The list of SVG elements is only taken into account if SVG is\n   *     {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for `$sanitize`.\n   *\n   * Passing an array (`[...]`) is equivalent to passing `{htmlElements: [...]}`.\n   *\n   * @return {$sanitizeProvider} Returns self for chaining.\n   */\n  this.addValidElements = function(elements) {\n    if (!hasBeenInstantiated) {\n      if (isArray(elements)) {\n        elements = {htmlElements: elements};\n      }\n\n      addElementsTo(svgElements, elements.svgElements);\n      addElementsTo(voidElements, elements.htmlVoidElements);\n      addElementsTo(validElements, elements.htmlVoidElements);\n      addElementsTo(validElements, elements.htmlElements);\n    }\n\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $sanitizeProvider#addValidAttrs\n   * @kind function\n   *\n   * @description\n   * Extends the built-in list of valid attributes, i.e. attributes that are considered safe and are\n   * not stripped off during sanitization.\n   *\n   * **Note**:\n   * The new attributes will not be treated as URI attributes, which means their values will not be\n   * sanitized as URIs using `$compileProvider`'s\n   * {@link ng.$compileProvider#aHrefSanitizationTrustedUrlList aHrefSanitizationTrustedUrlList} and\n   * {@link ng.$compileProvider#imgSrcSanitizationTrustedUrlList imgSrcSanitizationTrustedUrlList}.\n   *\n   * <div class=\"alert alert-info\">\n   *   This method must be called during the {@link angular.Module#config config} phase. Once the\n   *   `$sanitize` service has been instantiated, this method has no effect.\n   * </div>\n   *\n   * <div class=\"alert alert-warning\">\n   *   Keep in mind that extending the built-in list of attributes may expose your app to XSS or\n   *   other vulnerabilities. Be very mindful of the attributes you add.\n   * </div>\n   *\n   * @param {Array<String>} attrs - A list of valid attributes.\n   *\n   * @returns {$sanitizeProvider} Returns self for chaining.\n   */\n  this.addValidAttrs = function(attrs) {\n    if (!hasBeenInstantiated) {\n      extend(validAttrs, arrayToMap(attrs, true));\n    }\n    return this;\n  };\n\n  //////////////////////////////////////////////////////////////////////////////////////////////////\n  // Private stuff\n  //////////////////////////////////////////////////////////////////////////////////////////////////\n\n  bind = angular.bind;\n  extend = angular.extend;\n  forEach = angular.forEach;\n  isArray = angular.isArray;\n  isDefined = angular.isDefined;\n  lowercase = angular.$$lowercase;\n  noop = angular.noop;\n\n  htmlParser = htmlParserImpl;\n  htmlSanitizeWriter = htmlSanitizeWriterImpl;\n\n  nodeContains = window.Node.prototype.contains || /** @this */ function(arg) {\n    // eslint-disable-next-line no-bitwise\n    return !!(this.compareDocumentPosition(arg) & 16);\n  };\n\n  // Regular Expressions for parsing tags and attributes\n  var SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,\n    // Match everything outside of normal chars and \" (quote character)\n    NON_ALPHANUMERIC_REGEXP = /([^#-~ |!])/g;\n\n\n  // Good source of info about elements and attributes\n  // http://dev.w3.org/html5/spec/Overview.html#semantics\n  // http://simon.html5.org/html-elements\n\n  // Safe Void Elements - HTML5\n  // http://dev.w3.org/html5/spec/Overview.html#void-elements\n  var voidElements = stringToMap('area,br,col,hr,img,wbr');\n\n  // Elements that you can, intentionally, leave open (and which close themselves)\n  // http://dev.w3.org/html5/spec/Overview.html#optional-tags\n  var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),\n      optionalEndTagInlineElements = stringToMap('rp,rt'),\n      optionalEndTagElements = extend({},\n                                              optionalEndTagInlineElements,\n                                              optionalEndTagBlockElements);\n\n  // Safe Block Elements - HTML5\n  var blockElements = extend({}, optionalEndTagBlockElements, stringToMap('address,article,' +\n          'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +\n          'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul'));\n\n  // Inline Elements - HTML5\n  var inlineElements = extend({}, optionalEndTagInlineElements, stringToMap('a,abbr,acronym,b,' +\n          'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' +\n          'samp,small,span,strike,strong,sub,sup,time,tt,u,var'));\n\n  // SVG Elements\n  // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\n  // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.\n  // They can potentially allow for arbitrary javascript to be executed. See #11290\n  var svgElements = stringToMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' +\n          'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' +\n          'radialGradient,rect,stop,svg,switch,text,title,tspan');\n\n  // Blocked Elements (will be stripped)\n  var blockedElements = stringToMap('script,style');\n\n  var validElements = extend({},\n                                     voidElements,\n                                     blockElements,\n                                     inlineElements,\n                                     optionalEndTagElements);\n\n  //Attributes that have href and hence need to be sanitized\n  var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base');\n\n  var htmlAttrs = stringToMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +\n      'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +\n      'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +\n      'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +\n      'valign,value,vspace,width');\n\n  // SVG attributes (without \"id\" and \"name\" attributes)\n  // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\n  var svgAttrs = stringToMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n      'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +\n      'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +\n      'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +\n      'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +\n      'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +\n      'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +\n      'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +\n      'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +\n      'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +\n      'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +\n      'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +\n      'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +\n      'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +\n      'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);\n\n  var validAttrs = extend({},\n                                  uriAttrs,\n                                  svgAttrs,\n                                  htmlAttrs);\n\n  function stringToMap(str, lowercaseKeys) {\n    return arrayToMap(str.split(','), lowercaseKeys);\n  }\n\n  function arrayToMap(items, lowercaseKeys) {\n    var obj = {}, i;\n    for (i = 0; i < items.length; i++) {\n      obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;\n    }\n    return obj;\n  }\n\n  function addElementsTo(elementsMap, newElements) {\n    if (newElements && newElements.length) {\n      extend(elementsMap, arrayToMap(newElements));\n    }\n  }\n\n  /**\n   * Create an inert document that contains the dirty HTML that needs sanitizing.\n   * We use the DOMParser API by default and fall back to createHTMLDocument if DOMParser is not\n   * available.\n   */\n  var getInertBodyElement /* function(html: string): HTMLBodyElement */ = (function(window, document) {\n    if (isDOMParserAvailable()) {\n      return getInertBodyElement_DOMParser;\n    }\n\n    if (!document || !document.implementation) {\n      throw $sanitizeMinErr('noinert', 'Can\\'t create an inert html document');\n    }\n    var inertDocument = document.implementation.createHTMLDocument('inert');\n    var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');\n    return getInertBodyElement_InertDocument;\n\n    function isDOMParserAvailable() {\n      try {\n        return !!getInertBodyElement_DOMParser('');\n      } catch (e) {\n        return false;\n      }\n    }\n\n    function getInertBodyElement_DOMParser(html) {\n      // We add this dummy element to ensure that the rest of the content is parsed as expected\n      // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the `<head>` tag.\n      html = '<remove></remove>' + html;\n      try {\n        var body = new window.DOMParser().parseFromString(html, 'text/html').body;\n        body.firstChild.remove();\n        return body;\n      } catch (e) {\n        return undefined;\n      }\n    }\n\n    function getInertBodyElement_InertDocument(html) {\n      inertBodyElement.innerHTML = html;\n\n      // Support: IE 9-11 only\n      // strip custom-namespaced attributes on IE<=11\n      if (document.documentMode) {\n        stripCustomNsAttrs(inertBodyElement);\n      }\n\n      return inertBodyElement;\n    }\n  })(window, window.document);\n\n  /**\n   * @example\n   * htmlParser(htmlString, {\n   *     start: function(tag, attrs) {},\n   *     end: function(tag) {},\n   *     chars: function(text) {},\n   *     comment: function(text) {}\n   * });\n   *\n   * @param {string} html string\n   * @param {object} handler\n   */\n  function htmlParserImpl(html, handler) {\n    if (html === null || html === undefined) {\n      html = '';\n    } else if (typeof html !== 'string') {\n      html = '' + html;\n    }\n\n    var inertBodyElement = getInertBodyElement(html);\n    if (!inertBodyElement) return '';\n\n    //mXSS protection\n    var mXSSAttempts = 5;\n    do {\n      if (mXSSAttempts === 0) {\n        throw $sanitizeMinErr('uinput', 'Failed to sanitize html because the input is unstable');\n      }\n      mXSSAttempts--;\n\n      // trigger mXSS if it is going to happen by reading and writing the innerHTML\n      html = inertBodyElement.innerHTML;\n      inertBodyElement = getInertBodyElement(html);\n    } while (html !== inertBodyElement.innerHTML);\n\n    var node = inertBodyElement.firstChild;\n    while (node) {\n      switch (node.nodeType) {\n        case 1: // ELEMENT_NODE\n          handler.start(node.nodeName.toLowerCase(), attrToMap(node.attributes));\n          break;\n        case 3: // TEXT NODE\n          handler.chars(node.textContent);\n          break;\n      }\n\n      var nextNode;\n      if (!(nextNode = node.firstChild)) {\n        if (node.nodeType === 1) {\n          handler.end(node.nodeName.toLowerCase());\n        }\n        nextNode = getNonDescendant('nextSibling', node);\n        if (!nextNode) {\n          while (nextNode == null) {\n            node = getNonDescendant('parentNode', node);\n            if (node === inertBodyElement) break;\n            nextNode = getNonDescendant('nextSibling', node);\n            if (node.nodeType === 1) {\n              handler.end(node.nodeName.toLowerCase());\n            }\n          }\n        }\n      }\n      node = nextNode;\n    }\n\n    while ((node = inertBodyElement.firstChild)) {\n      inertBodyElement.removeChild(node);\n    }\n  }\n\n  function attrToMap(attrs) {\n    var map = {};\n    for (var i = 0, ii = attrs.length; i < ii; i++) {\n      var attr = attrs[i];\n      map[attr.name] = attr.value;\n    }\n    return map;\n  }\n\n\n  /**\n   * Escapes all potentially dangerous characters, so that the\n   * resulting string can be safely inserted into attribute or\n   * element text.\n   * @param value\n   * @returns {string} escaped text\n   */\n  function encodeEntities(value) {\n    return value.\n      replace(/&/g, '&amp;').\n      replace(SURROGATE_PAIR_REGEXP, function(value) {\n        var hi = value.charCodeAt(0);\n        var low = value.charCodeAt(1);\n        return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n      }).\n      replace(NON_ALPHANUMERIC_REGEXP, function(value) {\n        return '&#' + value.charCodeAt(0) + ';';\n      }).\n      replace(/</g, '&lt;').\n      replace(/>/g, '&gt;');\n  }\n\n  /**\n   * create an HTML/XML writer which writes to buffer\n   * @param {Array} buf use buf.join('') to get out sanitized html string\n   * @returns {object} in the form of {\n   *     start: function(tag, attrs) {},\n   *     end: function(tag) {},\n   *     chars: function(text) {},\n   *     comment: function(text) {}\n   * }\n   */\n  function htmlSanitizeWriterImpl(buf, uriValidator) {\n    var ignoreCurrentElement = false;\n    var out = bind(buf, buf.push);\n    return {\n      start: function(tag, attrs) {\n        tag = lowercase(tag);\n        if (!ignoreCurrentElement && blockedElements[tag]) {\n          ignoreCurrentElement = tag;\n        }\n        if (!ignoreCurrentElement && validElements[tag] === true) {\n          out('<');\n          out(tag);\n          forEach(attrs, function(value, key) {\n            var lkey = lowercase(key);\n            var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');\n            if (validAttrs[lkey] === true &&\n              (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {\n              out(' ');\n              out(key);\n              out('=\"');\n              out(encodeEntities(value));\n              out('\"');\n            }\n          });\n          out('>');\n        }\n      },\n      end: function(tag) {\n        tag = lowercase(tag);\n        if (!ignoreCurrentElement && validElements[tag] === true && voidElements[tag] !== true) {\n          out('</');\n          out(tag);\n          out('>');\n        }\n        // eslint-disable-next-line eqeqeq\n        if (tag == ignoreCurrentElement) {\n          ignoreCurrentElement = false;\n        }\n      },\n      chars: function(chars) {\n        if (!ignoreCurrentElement) {\n          out(encodeEntities(chars));\n        }\n      }\n    };\n  }\n\n\n  /**\n   * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' attribute to declare\n   * ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). This is undesirable since we don't want\n   * to allow any of these custom attributes. This method strips them all.\n   *\n   * @param node Root element to process\n   */\n  function stripCustomNsAttrs(node) {\n    while (node) {\n      if (node.nodeType === window.Node.ELEMENT_NODE) {\n        var attrs = node.attributes;\n        for (var i = 0, l = attrs.length; i < l; i++) {\n          var attrNode = attrs[i];\n          var attrName = attrNode.name.toLowerCase();\n          if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {\n            node.removeAttributeNode(attrNode);\n            i--;\n            l--;\n          }\n        }\n      }\n\n      var nextNode = node.firstChild;\n      if (nextNode) {\n        stripCustomNsAttrs(nextNode);\n      }\n\n      node = getNonDescendant('nextSibling', node);\n    }\n  }\n\n  function getNonDescendant(propName, node) {\n    // An element is clobbered if its `propName` property points to one of its descendants\n    var nextNode = node[propName];\n    if (nextNode && nodeContains.call(node, nextNode)) {\n      throw $sanitizeMinErr('elclob', 'Failed to sanitize html because the element is clobbered: {0}', node.outerHTML || node.outerText);\n    }\n    return nextNode;\n  }\n}\n\nfunction sanitizeText(chars) {\n  var buf = [];\n  var writer = htmlSanitizeWriter(buf, noop);\n  writer.chars(chars);\n  return buf.join('');\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', [])\n  .provider('$sanitize', $SanitizeProvider)\n  .info({ angularVersion: '1.8.3' });\n\n/**\n * @ngdoc filter\n * @name linky\n * @kind function\n *\n * @description\n * Finds links in text input and turns them into html links. Supports `http/https/ftp/sftp/mailto` and\n * plain email address links.\n *\n * Requires the {@link ngSanitize `ngSanitize`} module to be installed.\n *\n * @param {string} text Input text.\n * @param {string} [target] Window (`_blank|_self|_parent|_top`) or named frame to open links in.\n * @param {object|function(url)} [attributes] Add custom attributes to the link element.\n *\n *    Can be one of:\n *\n *    - `object`: A map of attributes\n *    - `function`: Takes the url as a parameter and returns a map of attributes\n *\n *    If the map of attributes contains a value for `target`, it overrides the value of\n *    the target parameter.\n *\n *\n * @returns {string} Html-linkified and {@link $sanitize sanitized} text.\n *\n * @usage\n   <span ng-bind-html=\"linky_expression | linky\"></span>\n *\n * @example\n   <example module=\"linkyExample\" deps=\"angular-sanitize.js\" name=\"linky-filter\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n       Snippet: <textarea ng-model=\"snippet\" cols=\"60\" rows=\"3\"></textarea>\n       <table>\n         <tr>\n           <th>Filter</th>\n           <th>Source</th>\n           <th>Rendered</th>\n         </tr>\n         <tr id=\"linky-filter\">\n           <td>linky filter</td>\n           <td>\n             <pre>&lt;div ng-bind-html=\"snippet | linky\"&gt;<br>&lt;/div&gt;</pre>\n           </td>\n           <td>\n             <div ng-bind-html=\"snippet | linky\"></div>\n           </td>\n         </tr>\n         <tr id=\"linky-target\">\n          <td>linky target</td>\n          <td>\n            <pre>&lt;div ng-bind-html=\"snippetWithSingleURL | linky:'_blank'\"&gt;<br>&lt;/div&gt;</pre>\n          </td>\n          <td>\n            <div ng-bind-html=\"snippetWithSingleURL | linky:'_blank'\"></div>\n          </td>\n         </tr>\n         <tr id=\"linky-custom-attributes\">\n          <td>linky custom attributes</td>\n          <td>\n            <pre>&lt;div ng-bind-html=\"snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}\"&gt;<br>&lt;/div&gt;</pre>\n          </td>\n          <td>\n            <div ng-bind-html=\"snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}\"></div>\n          </td>\n         </tr>\n         <tr id=\"escaped-html\">\n           <td>no filter</td>\n           <td><pre>&lt;div ng-bind=\"snippet\"&gt;<br>&lt;/div&gt;</pre></td>\n           <td><div ng-bind=\"snippet\"></div></td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"script.js\">\n       angular.module('linkyExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.snippet =\n             'Pretty text with some links:\\n' +\n             'http://angularjs.org/,\\n' +\n             'mailto:us@somewhere.org,\\n' +\n             'another@somewhere.org,\\n' +\n             'and one more: ftp://127.0.0.1/.';\n           $scope.snippetWithSingleURL = 'http://angularjs.org/';\n         }]);\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should linkify the snippet with urls', function() {\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);\n       });\n\n       it('should not linkify snippet without the linky filter', function() {\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).\n             toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +\n                  'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n         expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);\n       });\n\n       it('should update', function() {\n         element(by.model('snippet')).clear();\n         element(by.model('snippet')).sendKeys('new http://link.');\n         expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n             toBe('new http://link.');\n         expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);\n         expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())\n             .toBe('new http://link.');\n       });\n\n       it('should work with the target property', function() {\n        expect(element(by.id('linky-target')).\n            element(by.binding(\"snippetWithSingleURL | linky:'_blank'\")).getText()).\n            toBe('http://angularjs.org/');\n        expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');\n       });\n\n       it('should optionally add custom attributes', function() {\n        expect(element(by.id('linky-custom-attributes')).\n            element(by.binding(\"snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}\")).getText()).\n            toBe('http://angularjs.org/');\n        expect(element(by.css('#linky-custom-attributes a')).getAttribute('rel')).toEqual('nofollow');\n       });\n     </file>\n   </example>\n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n  var LINKY_URL_REGEXP =\n        /((s?ftp|https?):\\/\\/|(www\\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s.;,(){}<>\"\\u201d\\u2019]/i,\n      MAILTO_REGEXP = /^mailto:/i;\n\n  var linkyMinErr = angular.$$minErr('linky');\n  var isDefined = angular.isDefined;\n  var isFunction = angular.isFunction;\n  var isObject = angular.isObject;\n  var isString = angular.isString;\n\n  return function(text, target, attributes) {\n    if (text == null || text === '') return text;\n    if (!isString(text)) throw linkyMinErr('notstring', 'Expected string but received: {0}', text);\n\n    var attributesFn =\n      isFunction(attributes) ? attributes :\n      isObject(attributes) ? function getAttributesObject() {return attributes;} :\n      function getEmptyAttributesObject() {return {};};\n\n    var match;\n    var raw = text;\n    var html = [];\n    var url;\n    var i;\n    while ((match = raw.match(LINKY_URL_REGEXP))) {\n      // We can not end in these as they are sometimes found at the end of the sentence\n      url = match[0];\n      // if we did not match ftp/http/www/mailto then assume mailto\n      if (!match[2] && !match[4]) {\n        url = (match[3] ? 'http://' : 'mailto:') + url;\n      }\n      i = match.index;\n      addText(raw.substr(0, i));\n      addLink(url, match[0].replace(MAILTO_REGEXP, ''));\n      raw = raw.substring(i + match[0].length);\n    }\n    addText(raw);\n    return $sanitize(html.join(''));\n\n    function addText(text) {\n      if (!text) {\n        return;\n      }\n      html.push(sanitizeText(text));\n    }\n\n    function addLink(url, text) {\n      var key, linkAttributes = attributesFn(url);\n      html.push('<a ');\n\n      for (key in linkAttributes) {\n        html.push(key + '=\"' + linkAttributes[key] + '\" ');\n      }\n\n      if (isDefined(target) && !('target' in linkAttributes)) {\n        html.push('target=\"',\n                  target,\n                  '\" ');\n      }\n      html.push('href=\"',\n                url.replace(/\"/g, '&quot;'),\n                '\">');\n      addText(text);\n      html.push('</a>');\n    }\n  };\n}]);\n\n\n})(window, window.angular);\n","require('./angular-sanitize');\nmodule.exports = 'ngSanitize';\n","/**!\n * AngularJS file upload directives and services. Supports: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * FileAPI Flash shim for old browsers not supporting FormData\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\n(function () {\n  /** @namespace FileAPI.noContentTimeout */\n\n  function patchXHR(fnName, newFn) {\n    window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);\n  }\n\n  function redefineProp(xhr, prop, fn) {\n    try {\n      Object.defineProperty(xhr, prop, {get: fn});\n    } catch (e) {/*ignore*/\n    }\n  }\n\n  if (!window.FileAPI) {\n    window.FileAPI = {};\n  }\n\n  if (!window.XMLHttpRequest) {\n    throw 'AJAX is not supported. XMLHttpRequest is not defined.';\n  }\n\n  FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad;\n  if (FileAPI.shouldLoad) {\n    var initializeUploadListener = function (xhr) {\n      if (!xhr.__listeners) {\n        if (!xhr.upload) xhr.upload = {};\n        xhr.__listeners = [];\n        var origAddEventListener = xhr.upload.addEventListener;\n        xhr.upload.addEventListener = function (t, fn) {\n          xhr.__listeners[t] = fn;\n          if (origAddEventListener) origAddEventListener.apply(this, arguments);\n        };\n      }\n    };\n\n    patchXHR('open', function (orig) {\n      return function (m, url, b) {\n        initializeUploadListener(this);\n        this.__url = url;\n        try {\n          orig.apply(this, [m, url, b]);\n        } catch (e) {\n          if (e.message.indexOf('Access is denied') > -1) {\n            this.__origError = e;\n            orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);\n          }\n        }\n      };\n    });\n\n    patchXHR('getResponseHeader', function (orig) {\n      return function (h) {\n        return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));\n      };\n    });\n\n    patchXHR('getAllResponseHeaders', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('abort', function (orig) {\n      return function () {\n        return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));\n      };\n    });\n\n    patchXHR('setRequestHeader', function (orig) {\n      return function (header, value) {\n        if (header === '__setXHR_') {\n          initializeUploadListener(this);\n          var val = value(this);\n          // fix for angular < 1.2.0\n          if (val instanceof Function) {\n            val(this);\n          }\n        } else {\n          this.__requestHeaders = this.__requestHeaders || {};\n          this.__requestHeaders[header] = value;\n          orig.apply(this, arguments);\n        }\n      };\n    });\n\n    patchXHR('send', function (orig) {\n      return function () {\n        var xhr = this;\n        if (arguments[0] && arguments[0].__isFileAPIShim) {\n          var formData = arguments[0];\n          var config = {\n            url: xhr.__url,\n            jsonp: false, //removes the callback form param\n            cache: true, //removes the ?fileapiXXX in the url\n            complete: function (err, fileApiXHR) {\n              if (err && angular.isString(err) && err.indexOf('#2174') !== -1) {\n                // this error seems to be fine the file is being uploaded properly.\n                err = null;\n              }\n              xhr.__completed = true;\n              if (!err && xhr.__listeners.load)\n                xhr.__listeners.load({\n                  type: 'load',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (!err && xhr.__listeners.loadend)\n                xhr.__listeners.loadend({\n                  type: 'loadend',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (err === 'abort' && xhr.__listeners.abort)\n                xhr.__listeners.abort({\n                  type: 'abort',\n                  loaded: xhr.__loaded,\n                  total: xhr.__total,\n                  target: xhr,\n                  lengthComputable: true\n                });\n              if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () {\n                return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status;\n              });\n              if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () {\n                return fileApiXHR.statusText;\n              });\n              redefineProp(xhr, 'readyState', function () {\n                return 4;\n              });\n              if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () {\n                return fileApiXHR.response;\n              });\n              var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined);\n              redefineProp(xhr, 'responseText', function () {\n                return resp;\n              });\n              redefineProp(xhr, 'response', function () {\n                return resp;\n              });\n              if (err) redefineProp(xhr, 'err', function () {\n                return err;\n              });\n              xhr.__fileApiXHR = fileApiXHR;\n              if (xhr.onreadystatechange) xhr.onreadystatechange();\n              if (xhr.onload) xhr.onload();\n            },\n            progress: function (e) {\n              e.target = xhr;\n              if (xhr.__listeners.progress) xhr.__listeners.progress(e);\n              xhr.__total = e.total;\n              xhr.__loaded = e.loaded;\n              if (e.total === e.loaded) {\n                // fix flash issue that doesn't call complete if there is no response text from the server\n                var _this = this;\n                setTimeout(function () {\n                  if (!xhr.__completed) {\n                    xhr.getAllResponseHeaders = function () {\n                    };\n                    _this.complete(null, {status: 204, statusText: 'No Content'});\n                  }\n                }, FileAPI.noContentTimeout || 10000);\n              }\n            },\n            headers: xhr.__requestHeaders\n          };\n          config.data = {};\n          config.files = {};\n          for (var i = 0; i < formData.data.length; i++) {\n            var item = formData.data[i];\n            if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {\n              config.files[item.key] = item.val;\n            } else {\n              config.data[item.key] = item.val;\n            }\n          }\n\n          setTimeout(function () {\n            if (!FileAPI.hasFlash) {\n              throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n            }\n            xhr.__fileApiXHR = FileAPI.upload(config);\n          }, 1);\n        } else {\n          if (this.__origError) {\n            throw this.__origError;\n          }\n          orig.apply(xhr, arguments);\n        }\n      };\n    });\n    window.XMLHttpRequest.__isFileAPIShim = true;\n    window.FormData = FormData = function () {\n      return {\n        append: function (key, val, name) {\n          if (val.__isFileAPIBlobShim) {\n            val = val.data[0];\n          }\n          this.data.push({\n            key: key,\n            val: val,\n            name: name\n          });\n        },\n        data: [],\n        __isFileAPIShim: true\n      };\n    };\n\n    window.Blob = Blob = function (b) {\n      return {\n        data: b,\n        __isFileAPIBlobShim: true\n      };\n    };\n  }\n\n})();\n\n(function () {\n  /** @namespace FileAPI.forceLoad */\n  /** @namespace window.FileAPI.jsUrl */\n  /** @namespace window.FileAPI.jsPath */\n\n  function isInputTypeFile(elem) {\n    return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';\n  }\n\n  function hasFlash() {\n    try {\n      var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n      if (fo) return true;\n    } catch (e) {\n      if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true;\n    }\n    return false;\n  }\n\n  function getOffset(obj) {\n    var left = 0, top = 0;\n\n    if (window.jQuery) {\n      return jQuery(obj).offset();\n    }\n\n    if (obj.offsetParent) {\n      do {\n        left += (obj.offsetLeft - obj.scrollLeft);\n        top += (obj.offsetTop - obj.scrollTop);\n        obj = obj.offsetParent;\n      } while (obj);\n    }\n    return {\n      left: left,\n      top: top\n    };\n  }\n\n  if (FileAPI.shouldLoad) {\n    FileAPI.hasFlash = hasFlash();\n\n    //load FileAPI\n    if (FileAPI.forceLoad) {\n      FileAPI.html5 = false;\n    }\n\n    if (!FileAPI.upload) {\n      var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;\n      if (window.FileAPI.jsUrl) {\n        jsUrl = window.FileAPI.jsUrl;\n      } else if (window.FileAPI.jsPath) {\n        basePath = window.FileAPI.jsPath;\n      } else {\n        for (i = 0; i < allScripts.length; i++) {\n          src = allScripts[i].src;\n          index = src.search(/\\/ng\\-file\\-upload[\\-a-zA-z0-9\\.]*\\.js/);\n          if (index > -1) {\n            basePath = src.substring(0, index + 1);\n            break;\n          }\n        }\n      }\n\n      if (FileAPI.staticPath == null) FileAPI.staticPath = basePath;\n      script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');\n      document.getElementsByTagName('head')[0].appendChild(script);\n    }\n\n    FileAPI.ngfFixIE = function (elem, fileElem, changeFn) {\n      if (!hasFlash()) {\n        throw 'Adode Flash Player need to be installed. To check ahead use \"FileAPI.hasFlash\"';\n      }\n      var fixInputStyle = function () {\n        var label = fileElem.parent();\n        if (elem.attr('disabled')) {\n          if (label) label.removeClass('js-fileapi-wrapper');\n        } else {\n          if (!fileElem.attr('__ngf_flash_')) {\n            fileElem.unbind('change');\n            fileElem.unbind('click');\n            fileElem.bind('change', function (evt) {\n              fileApiChangeFn.apply(this, [evt]);\n              changeFn.apply(this, [evt]);\n            });\n            fileElem.attr('__ngf_flash_', 'true');\n          }\n          label.addClass('js-fileapi-wrapper');\n          if (!isInputTypeFile(elem)) {\n            label.css('position', 'absolute')\n              .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px')\n              .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('filter', 'alpha(opacity=0)').css('display', elem.css('display'))\n              .css('overflow', 'hidden').css('z-index', '900000')\n              .css('visibility', 'visible');\n            fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px')\n              .css('position', 'absolute').css('top', '0px').css('left', '0px');\n          }\n        }\n      };\n\n      elem.bind('mouseenter', fixInputStyle);\n\n      var fileApiChangeFn = function (evt) {\n        var files = FileAPI.getFiles(evt);\n        //just a double check for #233\n        for (var i = 0; i < files.length; i++) {\n          if (files[i].size === undefined) files[i].size = 0;\n          if (files[i].name === undefined) files[i].name = 'file';\n          if (files[i].type === undefined) files[i].type = 'undefined';\n        }\n        if (!evt.target) {\n          evt.target = {};\n        }\n        evt.target.files = files;\n        // if evt.target.files is not writable use helper field\n        if (evt.target.files !== files) {\n          evt.__files_ = files;\n        }\n        (evt.__files_ || evt.target.files).item = function (i) {\n          return (evt.__files_ || evt.target.files)[i] || null;\n        };\n      };\n    };\n\n    FileAPI.disableFileInput = function (elem, disable) {\n      if (disable) {\n        elem.removeClass('js-fileapi-wrapper');\n      } else {\n        elem.addClass('js-fileapi-wrapper');\n      }\n    };\n  }\n})();\n\nif (!window.FileReader) {\n  window.FileReader = function () {\n    var _this = this, loadStarted = false;\n    this.listeners = {};\n    this.addEventListener = function (type, fn) {\n      _this.listeners[type] = _this.listeners[type] || [];\n      _this.listeners[type].push(fn);\n    };\n    this.removeEventListener = function (type, fn) {\n      if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);\n    };\n    this.dispatchEvent = function (evt) {\n      var list = _this.listeners[evt.type];\n      if (list) {\n        for (var i = 0; i < list.length; i++) {\n          list[i].call(_this, evt);\n        }\n      }\n    };\n    this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;\n\n    var constructEvent = function (type, evt) {\n      var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};\n      if (evt.result != null) e.target.result = evt.result;\n      return e;\n    };\n    var listener = function (evt) {\n      if (!loadStarted) {\n        loadStarted = true;\n        if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt));\n      }\n      var e;\n      if (evt.type === 'load') {\n        if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt));\n        e = constructEvent('load', evt);\n        if (_this.onload) _this.onload(e);\n        _this.dispatchEvent(e);\n      } else if (evt.type === 'progress') {\n        e = constructEvent('progress', evt);\n        if (_this.onprogress) _this.onprogress(e);\n        _this.dispatchEvent(e);\n      } else {\n        e = constructEvent('error', evt);\n        if (_this.onerror) _this.onerror(e);\n        _this.dispatchEvent(e);\n      }\n    };\n    this.readAsDataURL = function (file) {\n      FileAPI.readAsDataURL(file, listener);\n    };\n    this.readAsText = function (file) {\n      FileAPI.readAsText(file, listener);\n    };\n  };\n}\n\n/**!\n * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort,\n * progress, resize, thumbnail, preview, validation and CORS\n * @author  Danial  <danial.farid@gmail.com>\n * @version 12.2.13\n */\n\nif (window.XMLHttpRequest && !(window.FileAPI && FileAPI.shouldLoad)) {\n  window.XMLHttpRequest.prototype.setRequestHeader = (function (orig) {\n    return function (header, value) {\n      if (header === '__setXHR_') {\n        var val = value(this);\n        // fix for angular < 1.2.0\n        if (val instanceof Function) {\n          val(this);\n        }\n      } else {\n        orig.apply(this, arguments);\n      }\n    };\n  })(window.XMLHttpRequest.prototype.setRequestHeader);\n}\n\nvar ngFileUpload = angular.module('ngFileUpload', []);\n\nngFileUpload.version = '12.2.13';\n\nngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {\n  var upload = this;\n  upload.promisesCount = 0;\n\n  this.isResumeSupported = function () {\n    return window.Blob && window.Blob.prototype.slice;\n  };\n\n  var resumeSupported = this.isResumeSupported();\n\n  function sendHttp(config) {\n    config.method = config.method || 'POST';\n    config.headers = config.headers || {};\n\n    var deferred = config._deferred = config._deferred || $q.defer();\n    var promise = deferred.promise;\n\n    function notifyProgress(e) {\n      if (deferred.notify) {\n        deferred.notify(e);\n      }\n      if (promise.progressFunc) {\n        $timeout(function () {\n          promise.progressFunc(e);\n        });\n      }\n    }\n\n    function getNotifyEvent(n) {\n      if (config._start != null && resumeSupported) {\n        return {\n          loaded: n.loaded + config._start,\n          total: (config._file && config._file.size) || n.total,\n          type: n.type, config: config,\n          lengthComputable: true, target: n.target\n        };\n      } else {\n        return n;\n      }\n    }\n\n    if (!config.disableProgress) {\n      config.headers.__setXHR_ = function () {\n        return function (xhr) {\n          if (!xhr || !xhr.upload || !xhr.upload.addEventListener) return;\n          config.__XHR = xhr;\n          if (config.xhrFn) config.xhrFn(xhr);\n          xhr.upload.addEventListener('progress', function (e) {\n            e.config = config;\n            notifyProgress(getNotifyEvent(e));\n          }, false);\n          //fix for firefox not firing upload progress end, also IE8-9\n          xhr.upload.addEventListener('load', function (e) {\n            if (e.lengthComputable) {\n              e.config = config;\n              notifyProgress(getNotifyEvent(e));\n            }\n          }, false);\n        };\n      };\n    }\n\n    function uploadWithAngular() {\n      $http(config).then(function (r) {\n          if (resumeSupported && config._chunkSize && !config._finished && config._file) {\n            var fileSize = config._file && config._file.size || 0;\n            notifyProgress({\n                loaded: Math.min(config._end, fileSize),\n                total: fileSize,\n                config: config,\n                type: 'progress'\n              }\n            );\n            upload.upload(config, true);\n          } else {\n            if (config._finished) delete config._finished;\n            deferred.resolve(r);\n          }\n        }, function (e) {\n          deferred.reject(e);\n        }, function (n) {\n          deferred.notify(n);\n        }\n      );\n    }\n\n    if (!resumeSupported) {\n      uploadWithAngular();\n    } else if (config._chunkSize && config._end && !config._finished) {\n      config._start = config._end;\n      config._end += config._chunkSize;\n      uploadWithAngular();\n    } else if (config.resumeSizeUrl) {\n      $http.get(config.resumeSizeUrl).then(function (resp) {\n        if (config.resumeSizeResponseReader) {\n          config._start = config.resumeSizeResponseReader(resp.data);\n        } else {\n          config._start = parseInt((resp.data.size == null ? resp.data : resp.data.size).toString());\n        }\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else if (config.resumeSize) {\n      config.resumeSize().then(function (size) {\n        config._start = size;\n        if (config._chunkSize) {\n          config._end = config._start + config._chunkSize;\n        }\n        uploadWithAngular();\n      }, function (e) {\n        throw e;\n      });\n    } else {\n      if (config._chunkSize) {\n        config._start = 0;\n        config._end = config._start + config._chunkSize;\n      }\n      uploadWithAngular();\n    }\n\n\n    promise.success = function (fn) {\n      promise.then(function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.error = function (fn) {\n      promise.then(null, function (response) {\n        fn(response.data, response.status, response.headers, config);\n      });\n      return promise;\n    };\n\n    promise.progress = function (fn) {\n      promise.progressFunc = fn;\n      promise.then(null, null, function (n) {\n        fn(n);\n      });\n      return promise;\n    };\n    promise.abort = promise.pause = function () {\n      if (config.__XHR) {\n        $timeout(function () {\n          config.__XHR.abort();\n        });\n      }\n      return promise;\n    };\n    promise.xhr = function (fn) {\n      config.xhrFn = (function (origXhrFn) {\n        return function () {\n          if (origXhrFn) origXhrFn.apply(promise, arguments);\n          fn.apply(promise, arguments);\n        };\n      })(config.xhrFn);\n      return promise;\n    };\n\n    upload.promisesCount++;\n    if (promise['finally'] && promise['finally'] instanceof Function) {\n      promise['finally'](function () {\n        upload.promisesCount--;\n      });\n    }\n    return promise;\n  }\n\n  this.isUploadInProgress = function () {\n    return upload.promisesCount > 0;\n  };\n\n  this.rename = function (file, name) {\n    file.ngfName = name;\n    return file;\n  };\n\n  this.jsonBlob = function (val) {\n    if (val != null && !angular.isString(val)) {\n      val = JSON.stringify(val);\n    }\n    var blob = new window.Blob([val], {type: 'application/json'});\n    blob._ngfBlob = true;\n    return blob;\n  };\n\n  this.json = function (val) {\n    return angular.toJson(val);\n  };\n\n  function copy(obj) {\n    var clone = {};\n    for (var key in obj) {\n      if (obj.hasOwnProperty(key)) {\n        clone[key] = obj[key];\n      }\n    }\n    return clone;\n  }\n\n  this.isFile = function (file) {\n    return file != null && (file instanceof window.Blob || (file.flashId && file.name && file.size));\n  };\n\n  this.upload = function (config, internal) {\n    function toResumeFile(file, formData) {\n      if (file._ngfBlob) return file;\n      config._file = config._file || file;\n      if (config._start != null && resumeSupported) {\n        if (config._end && config._end >= file.size) {\n          config._finished = true;\n          config._end = file.size;\n        }\n        var slice = file.slice(config._start, config._end || file.size);\n        slice.name = file.name;\n        slice.ngfName = file.ngfName;\n        if (config._chunkSize) {\n          formData.append('_chunkSize', config._chunkSize);\n          formData.append('_currentChunkSize', config._end - config._start);\n          formData.append('_chunkNumber', Math.floor(config._start / config._chunkSize));\n          formData.append('_totalSize', config._file.size);\n        }\n        return slice;\n      }\n      return file;\n    }\n\n    function addFieldToFormData(formData, val, key) {\n      if (val !== undefined) {\n        if (angular.isDate(val)) {\n          val = val.toISOString();\n        }\n        if (angular.isString(val)) {\n          formData.append(key, val);\n        } else if (upload.isFile(val)) {\n          var file = toResumeFile(val, formData);\n          var split = key.split(',');\n          if (split[1]) {\n            file.ngfName = split[1].replace(/^\\s+|\\s+$/g, '');\n            key = split[0];\n          }\n          config._fileKey = config._fileKey || key;\n          formData.append(key, file, file.ngfName || file.name);\n        } else {\n          if (angular.isObject(val)) {\n            if (val.$$ngfCircularDetection) throw 'ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: ' + key;\n\n            val.$$ngfCircularDetection = true;\n            try {\n              for (var k in val) {\n                if (val.hasOwnProperty(k) && k !== '$$ngfCircularDetection') {\n                  var objectKey = config.objectKey == null ? '[i]' : config.objectKey;\n                  if (val.length && parseInt(k) > -1) {\n                    objectKey = config.arrayKey == null ? objectKey : config.arrayKey;\n                  }\n                  addFieldToFormData(formData, val[k], key + objectKey.replace(/[ik]/g, k));\n                }\n              }\n            } finally {\n              delete val.$$ngfCircularDetection;\n            }\n          } else {\n            formData.append(key, val);\n          }\n        }\n      }\n    }\n\n    function digestConfig() {\n      config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n      config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n      config.headers = config.headers || {};\n      config.headers['Content-Type'] = undefined;\n      config.transformRequest = config.transformRequest ?\n        (angular.isArray(config.transformRequest) ?\n          config.transformRequest : [config.transformRequest]) : [];\n      config.transformRequest.push(function (data) {\n        var formData = new window.FormData(), key;\n        data = data || config.fields || {};\n        if (config.file) {\n          data.file = config.file;\n        }\n        for (key in data) {\n          if (data.hasOwnProperty(key)) {\n            var val = data[key];\n            if (config.formDataAppender) {\n              config.formDataAppender(formData, key, val);\n            } else {\n              addFieldToFormData(formData, val, key);\n            }\n          }\n        }\n\n        return formData;\n      });\n    }\n\n    if (!internal) config = copy(config);\n    if (!config._isDigested) {\n      config._isDigested = true;\n      digestConfig();\n    }\n\n    return sendHttp(config);\n  };\n\n  this.http = function (config) {\n    config = copy(config);\n    config.transformRequest = config.transformRequest || function (data) {\n        if ((window.ArrayBuffer && data instanceof window.ArrayBuffer) || data instanceof window.Blob) {\n          return data;\n        }\n        return $http.defaults.transformRequest[0].apply(this, arguments);\n      };\n    config._chunkSize = upload.translateScalars(config.resumeChunkSize);\n    config._chunkSize = config._chunkSize ? parseInt(config._chunkSize.toString()) : null;\n\n    return sendHttp(config);\n  };\n\n  this.translateScalars = function (str) {\n    if (angular.isString(str)) {\n      if (str.search(/kb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1024);\n      } else if (str.search(/mb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1048576);\n      } else if (str.search(/gb/i) === str.length - 2) {\n        return parseFloat(str.substring(0, str.length - 2) * 1073741824);\n      } else if (str.search(/b/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/s/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1));\n      } else if (str.search(/m/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 60);\n      } else if (str.search(/h/i) === str.length - 1) {\n        return parseFloat(str.substring(0, str.length - 1) * 3600);\n      }\n    }\n    return str;\n  };\n\n  this.urlToBlob = function(url) {\n    var defer = $q.defer();\n    $http({url: url, method: 'get', responseType: 'arraybuffer'}).then(function (resp) {\n      var arrayBufferView = new Uint8Array(resp.data);\n      var type = resp.headers('content-type') || 'image/WebP';\n      var blob = new window.Blob([arrayBufferView], {type: type});\n      var matches = url.match(/.*\\/(.+?)(\\?.*)?$/);\n      if (matches.length > 1) {\n        blob.name = matches[1];\n      }\n      defer.resolve(blob);\n    }, function (e) {\n      defer.reject(e);\n    });\n    return defer.promise;\n  };\n\n  this.setDefaults = function (defaults) {\n    this.defaults = defaults || {};\n  };\n\n  this.defaults = {};\n  this.version = ngFileUpload.version;\n}\n\n]);\n\nngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadExif', function ($parse, $timeout, $compile, $q, UploadExif) {\n  var upload = UploadExif;\n  upload.getAttrWithDefaults = function (attr, name) {\n    if (attr[name] != null) return attr[name];\n    var def = upload.defaults[name];\n    return (def == null ? def : (angular.isString(def) ? def : JSON.stringify(def)));\n  };\n\n  upload.attrGetter = function (name, attr, scope, params) {\n    var attrVal = this.getAttrWithDefaults(attr, name);\n    if (scope) {\n      try {\n        if (params) {\n          return $parse(attrVal)(scope, params);\n        } else {\n          return $parse(attrVal)(scope);\n        }\n      } catch (e) {\n        // hangle string value without single qoute\n        if (name.search(/min|max|pattern/i)) {\n          return attrVal;\n        } else {\n          throw e;\n        }\n      }\n    } else {\n      return attrVal;\n    }\n  };\n\n  upload.shouldUpdateOn = function (type, attr, scope) {\n    var modelOptions = upload.attrGetter('ngfModelOptions', attr, scope);\n    if (modelOptions && modelOptions.updateOn) {\n      return modelOptions.updateOn.split(' ').indexOf(type) > -1;\n    }\n    return true;\n  };\n\n  upload.emptyPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.resolve.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.rejectPromise = function () {\n    var d = $q.defer();\n    var args = arguments;\n    $timeout(function () {\n      d.reject.apply(d, args);\n    });\n    return d.promise;\n  };\n\n  upload.happyPromise = function (promise, data) {\n    var d = $q.defer();\n    promise.then(function (result) {\n      d.resolve(result);\n    }, function (error) {\n      $timeout(function () {\n        throw error;\n      });\n      d.resolve(data);\n    });\n    return d.promise;\n  };\n\n  function applyExifRotations(files, attr, scope) {\n    var promises = [upload.emptyPromise()];\n    angular.forEach(files, function (f, i) {\n      if (f.type.indexOf('image/jpeg') === 0 && upload.attrGetter('ngfFixOrientation', attr, scope, {$file: f})) {\n        promises.push(upload.happyPromise(upload.applyExifRotation(f), f).then(function (fixedFile) {\n          files.splice(i, 1, fixedFile);\n        }));\n      }\n    });\n    return $q.all(promises);\n  }\n\n  function resizeFile(files, attr, scope, ngModel) {\n    var resizeVal = upload.attrGetter('ngfResize', attr, scope);\n    if (!resizeVal || !upload.isResizeSupported() || !files.length) return upload.emptyPromise();\n    if (resizeVal instanceof Function) {\n      var defer = $q.defer();\n      return resizeVal(files).then(function (p) {\n        resizeWithParams(p, files, attr, scope, ngModel).then(function (r) {\n          defer.resolve(r);\n        }, function (e) {\n          defer.reject(e);\n        });\n      }, function (e) {\n        defer.reject(e);\n      });\n    } else {\n      return resizeWithParams(resizeVal, files, attr, scope, ngModel);\n    }\n  }\n\n  function resizeWithParams(params, files, attr, scope, ngModel) {\n    var promises = [upload.emptyPromise()];\n\n    function handleFile(f, i) {\n      if (f.type.indexOf('image') === 0) {\n        if (params.pattern && !upload.validatePattern(f, params.pattern)) return;\n        params.resizeIf = function (width, height) {\n          return upload.attrGetter('ngfResizeIf', attr, scope,\n            {$width: width, $height: height, $file: f});\n        };\n        var promise = upload.resize(f, params);\n        promises.push(promise);\n        promise.then(function (resizedFile) {\n          files.splice(i, 1, resizedFile);\n        }, function (e) {\n          f.$error = 'resize';\n          (f.$errorMessages = (f.$errorMessages || {})).resize = true;\n          f.$errorParam = (e ? (e.message ? e.message : e) + ': ' : '') + (f && f.name);\n          ngModel.$ngfValidations.push({name: 'resize', valid: false});\n          upload.applyModelValidation(ngModel, files);\n        });\n      }\n    }\n\n    for (var i = 0; i < files.length; i++) {\n      handleFile(files[i], i);\n    }\n    return $q.all(promises);\n  }\n\n  upload.updateModel = function (ngModel, attr, scope, fileChange, files, evt, noDelay) {\n    function update(files, invalidFiles, newFiles, dupFiles, isSingleModel) {\n      attr.$$ngfPrevValidFiles = files;\n      attr.$$ngfPrevInvalidFiles = invalidFiles;\n      var file = files && files.length ? files[0] : null;\n      var invalidFile = invalidFiles && invalidFiles.length ? invalidFiles[0] : null;\n\n      if (ngModel) {\n        upload.applyModelValidation(ngModel, files);\n        ngModel.$setViewValue(isSingleModel ? file : files);\n      }\n\n      if (fileChange) {\n        $parse(fileChange)(scope, {\n          $files: files,\n          $file: file,\n          $newFiles: newFiles,\n          $duplicateFiles: dupFiles,\n          $invalidFiles: invalidFiles,\n          $invalidFile: invalidFile,\n          $event: evt\n        });\n      }\n\n      var invalidModel = upload.attrGetter('ngfModelInvalid', attr);\n      if (invalidModel) {\n        $timeout(function () {\n          $parse(invalidModel).assign(scope, isSingleModel ? invalidFile : invalidFiles);\n        });\n      }\n      $timeout(function () {\n        // scope apply changes\n      });\n    }\n\n    var allNewFiles, dupFiles = [], prevValidFiles, prevInvalidFiles,\n      invalids = [], valids = [];\n\n    function removeDuplicates() {\n      function equals(f1, f2) {\n        return f1.name === f2.name && (f1.$ngfOrigSize || f1.size) === (f2.$ngfOrigSize || f2.size) &&\n          f1.type === f2.type;\n      }\n\n      function isInPrevFiles(f) {\n        var j;\n        for (j = 0; j < prevValidFiles.length; j++) {\n          if (equals(f, prevValidFiles[j])) {\n            return true;\n          }\n        }\n        for (j = 0; j < prevInvalidFiles.length; j++) {\n          if (equals(f, prevInvalidFiles[j])) {\n            return true;\n          }\n        }\n        return false;\n      }\n\n      if (files) {\n        allNewFiles = [];\n        dupFiles = [];\n        for (var i = 0; i < files.length; i++) {\n          if (isInPrevFiles(files[i])) {\n            dupFiles.push(files[i]);\n          } else {\n            allNewFiles.push(files[i]);\n          }\n        }\n      }\n    }\n\n    function toArray(v) {\n      return angular.isArray(v) ? v : [v];\n    }\n\n    function resizeAndUpdate() {\n      function updateModel() {\n        $timeout(function () {\n          update(keep ? prevValidFiles.concat(valids) : valids,\n            keep ? prevInvalidFiles.concat(invalids) : invalids,\n            files, dupFiles, isSingleModel);\n        }, options && options.debounce ? options.debounce.change || options.debounce : 0);\n      }\n\n      var resizingFiles = validateAfterResize ? allNewFiles : valids;\n      resizeFile(resizingFiles, attr, scope, ngModel).then(function () {\n        if (validateAfterResize) {\n          upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n            .then(function (validationResult) {\n              valids = validationResult.validsFiles;\n              invalids = validationResult.invalidsFiles;\n              updateModel();\n            });\n        } else {\n          updateModel();\n        }\n      }, function () {\n        for (var i = 0; i < resizingFiles.length; i++) {\n          var f = resizingFiles[i];\n          if (f.$error === 'resize') {\n            var index = valids.indexOf(f);\n            if (index > -1) {\n              valids.splice(index, 1);\n              invalids.push(f);\n            }\n            updateModel();\n          }\n        }\n      });\n    }\n\n    prevValidFiles = attr.$$ngfPrevValidFiles || [];\n    prevInvalidFiles = attr.$$ngfPrevInvalidFiles || [];\n    if (ngModel && ngModel.$modelValue) {\n      prevValidFiles = toArray(ngModel.$modelValue);\n    }\n\n    var keep = upload.attrGetter('ngfKeep', attr, scope);\n    allNewFiles = (files || []).slice(0);\n    if (keep === 'distinct' || upload.attrGetter('ngfKeepDistinct', attr, scope) === true) {\n      removeDuplicates(attr, scope);\n    }\n\n    var isSingleModel = !keep && !upload.attrGetter('ngfMultiple', attr, scope) && !upload.attrGetter('multiple', attr);\n\n    if (keep && !allNewFiles.length) return;\n\n    upload.attrGetter('ngfBeforeModelChange', attr, scope, {\n      $files: files,\n      $file: files && files.length ? files[0] : null,\n      $newFiles: allNewFiles,\n      $duplicateFiles: dupFiles,\n      $event: evt\n    });\n\n    var validateAfterResize = upload.attrGetter('ngfValidateAfterResize', attr, scope);\n\n    var options = upload.attrGetter('ngfModelOptions', attr, scope);\n    upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope)\n      .then(function (validationResult) {\n      if (noDelay) {\n        update(allNewFiles, [], files, dupFiles, isSingleModel);\n      } else {\n        if ((!options || !options.allowInvalid) && !validateAfterResize) {\n          valids = validationResult.validFiles;\n          invalids = validationResult.invalidFiles;\n        } else {\n          valids = allNewFiles;\n        }\n        if (upload.attrGetter('ngfFixOrientation', attr, scope) && upload.isExifSupported()) {\n          applyExifRotations(valids, attr, scope).then(function () {\n            resizeAndUpdate();\n          });\n        } else {\n          resizeAndUpdate();\n        }\n      }\n    });\n  };\n\n  return upload;\n}]);\n\nngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {\n  var generatedElems = [];\n\n  function isDelayedClickSupported(ua) {\n    // fix for android native browser < 4.4 and safari windows\n    var m = ua.match(/Android[^\\d]*(\\d+)\\.(\\d+)/);\n    if (m && m.length > 2) {\n      var v = Upload.defaults.androidFixMinorVersion || 4;\n      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);\n    }\n\n    // safari on windows\n    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);\n  }\n\n  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {\n    /** @namespace attr.ngfSelect */\n    /** @namespace attr.ngfChange */\n    /** @namespace attr.ngModel */\n    /** @namespace attr.ngfModelOptions */\n    /** @namespace attr.ngfMultiple */\n    /** @namespace attr.ngfCapture */\n    /** @namespace attr.ngfValidate */\n    /** @namespace attr.ngfKeep */\n    var attrGetter = function (name, scope) {\n      return upload.attrGetter(name, attr, scope);\n    };\n\n    function isInputTypeFile() {\n      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';\n    }\n\n    function fileChangeAttr() {\n      return attrGetter('ngfChange') || attrGetter('ngfSelect');\n    }\n\n    function changeFn(evt) {\n      if (upload.shouldUpdateOn('change', attr, scope)) {\n        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];\n        /* Handle duplicate call in  IE11 */\n        if (!fileList) return;\n        for (var i = 0; i < fileList.length; i++) {\n          files.push(fileList[i]);\n        }\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),\n          files.length ? files : null, evt);\n      }\n    }\n\n    upload.registerModelChangeValidator(ngModel, attr, scope);\n\n    var unwatches = [];\n    if (attrGetter('ngfMultiple')) {\n      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {\n        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));\n      }));\n    }\n    if (attrGetter('ngfCapture')) {\n      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {\n        fileElem.attr('capture', attrGetter('ngfCapture', scope));\n      }));\n    }\n    if (attrGetter('ngfAccept')) {\n      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {\n        fileElem.attr('accept', attrGetter('ngfAccept', scope));\n      }));\n    }\n    unwatches.push(attr.$observe('accept', function () {\n      fileElem.attr('accept', attrGetter('accept'));\n    }));\n    function bindAttrToFileInput(fileElem, label) {\n      function updateId(val) {\n        fileElem.attr('id', 'ngf-' + val);\n        label.attr('id', 'ngf-label-' + val);\n      }\n\n      for (var i = 0; i < elem[0].attributes.length; i++) {\n        var attribute = elem[0].attributes[i];\n        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {\n          if (attribute.name === 'id') {\n            updateId(attribute.value);\n            unwatches.push(attr.$observe('id', updateId));\n          } else {\n            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||\n            attribute.name === 'multiple')) ? attribute.name : attribute.value);\n          }\n        }\n      }\n    }\n\n    function createFileInput() {\n      if (isInputTypeFile()) {\n        return elem;\n      }\n\n      var fileElem = angular.element('<input type=\"file\">');\n\n      var label = angular.element('<label>upload</label>');\n      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')\n        .css('width', '0px').css('height', '0px').css('border', 'none')\n        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');\n      bindAttrToFileInput(fileElem, label);\n\n      generatedElems.push({el: elem, ref: label});\n\n      document.body.appendChild(label.append(fileElem)[0]);\n\n      return fileElem;\n    }\n\n    function clickHandler(evt) {\n      if (elem.attr('disabled')) return false;\n      if (attrGetter('ngfSelectDisabled', scope)) return;\n\n      var r = detectSwipe(evt);\n      // prevent the click if it is a swipe\n      if (r != null) return r;\n\n      resetModel(evt);\n\n      // fix for md when the element is removed from the DOM and added back #460\n      try {\n        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {\n          generatedElems.push({el: elem, ref: fileElem.parent()});\n          document.body.appendChild(fileElem.parent()[0]);\n          fileElem.bind('change', changeFn);\n        }\n      } catch (e) {/*ignore*/\n      }\n\n      if (isDelayedClickSupported(navigator.userAgent)) {\n        setTimeout(function () {\n          fileElem[0].click();\n        }, 0);\n      } else {\n        fileElem[0].click();\n      }\n\n      return false;\n    }\n\n\n    var initialTouchStartY = 0;\n    var initialTouchStartX = 0;\n\n    function detectSwipe(evt) {\n      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);\n      if (touches) {\n        if (evt.type === 'touchstart') {\n          initialTouchStartX = touches[0].clientX;\n          initialTouchStartY = touches[0].clientY;\n          return true; // don't block event default\n        } else {\n          // prevent scroll from triggering event\n          if (evt.type === 'touchend') {\n            var currentX = touches[0].clientX;\n            var currentY = touches[0].clientY;\n            if ((Math.abs(currentX - initialTouchStartX) > 20) ||\n              (Math.abs(currentY - initialTouchStartY) > 20)) {\n              evt.stopPropagation();\n              evt.preventDefault();\n              return false;\n            }\n          }\n          return true;\n        }\n      }\n    }\n\n    var fileElem = elem;\n\n    function resetModel(evt) {\n      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {\n        fileElem.val(null);\n        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);\n      }\n    }\n\n    if (!isInputTypeFile()) {\n      fileElem = createFileInput();\n    }\n    fileElem.bind('change', changeFn);\n\n    if (!isInputTypeFile()) {\n      elem.bind('click touchstart touchend', clickHandler);\n    } else {\n      elem.bind('click', resetModel);\n    }\n\n    function ie10SameFileSelectFix(evt) {\n      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {\n        if (!fileElem[0].parentNode) {\n          fileElem = null;\n          return;\n        }\n        evt.preventDefault();\n        evt.stopPropagation();\n        fileElem.unbind('click');\n        var clone = fileElem.clone();\n        fileElem.replaceWith(clone);\n        fileElem = clone;\n        fileElem.attr('__ngf_ie10_Fix_', 'true');\n        fileElem.bind('change', changeFn);\n        fileElem.bind('click', ie10SameFileSelectFix);\n        fileElem[0].click();\n        return false;\n      } else {\n        fileElem.removeAttr('__ngf_ie10_Fix_');\n      }\n    }\n\n    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {\n      fileElem.bind('click', ie10SameFileSelectFix);\n    }\n\n    if (ngModel) ngModel.$formatters.push(function (val) {\n      if (val == null || val.length === 0) {\n        if (fileElem.val()) {\n          fileElem.val(null);\n        }\n      }\n      return val;\n    });\n\n    scope.$on('$destroy', function () {\n      if (!isInputTypeFile()) fileElem.parent().remove();\n      angular.forEach(unwatches, function (unwatch) {\n        unwatch();\n      });\n    });\n\n    $timeout(function () {\n      for (var i = 0; i < generatedElems.length; i++) {\n        var g = generatedElems[i];\n        if (!document.body.contains(g.el[0])) {\n          generatedElems.splice(i, 1);\n          g.ref.remove();\n        }\n      }\n    });\n\n    if (window.FileAPI && window.FileAPI.ngfFixIE) {\n      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);\n    }\n  }\n\n  return {\n    restrict: 'AEC',\n    require: '?ngModel',\n    link: function (scope, elem, attr, ngModel) {\n      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);\n    }\n  };\n}]);\n\n(function () {\n\n  ngFileUpload.service('UploadDataUrl', ['UploadBase', '$timeout', '$q', function (UploadBase, $timeout, $q) {\n    var upload = UploadBase;\n    upload.base64DataUrl = function (file) {\n      if (angular.isArray(file)) {\n        var d = $q.defer(), count = 0;\n        angular.forEach(file, function (f) {\n          upload.dataUrl(f, true)['finally'](function () {\n            count++;\n            if (count === file.length) {\n              var urls = [];\n              angular.forEach(file, function (ff) {\n                urls.push(ff.$ngfDataUrl);\n              });\n              d.resolve(urls, file);\n            }\n          });\n        });\n        return d.promise;\n      } else {\n        return upload.dataUrl(file, true);\n      }\n    };\n    upload.dataUrl = function (file, disallowObjectUrl) {\n      if (!file) return upload.emptyPromise(file, file);\n      if ((disallowObjectUrl && file.$ngfDataUrl != null) || (!disallowObjectUrl && file.$ngfBlobUrl != null)) {\n        return upload.emptyPromise(disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl, file);\n      }\n      var p = disallowObjectUrl ? file.$$ngfDataUrlPromise : file.$$ngfBlobUrlPromise;\n      if (p) return p;\n\n      var deferred = $q.defer();\n      $timeout(function () {\n        if (window.FileReader && file &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 8') === -1 || file.size < 20000) &&\n          (!window.FileAPI || navigator.userAgent.indexOf('MSIE 9') === -1 || file.size < 4000000)) {\n          //prefer URL.createObjectURL for handling refrences to files of all sizes\n          //since it doesn´t build a large string in memory\n          var URL = window.URL || window.webkitURL;\n          if (URL && URL.createObjectURL && !disallowObjectUrl) {\n            var url;\n            try {\n              url = URL.createObjectURL(file);\n            } catch (e) {\n              $timeout(function () {\n                file.$ngfBlobUrl = '';\n                deferred.reject();\n              });\n              return;\n            }\n            $timeout(function () {\n              file.$ngfBlobUrl = url;\n              if (url) {\n                deferred.resolve(url, file);\n                upload.blobUrls = upload.blobUrls || [];\n                upload.blobUrlsTotalSize = upload.blobUrlsTotalSize || 0;\n                upload.blobUrls.push({url: url, size: file.size});\n                upload.blobUrlsTotalSize += file.size || 0;\n                var maxMemory = upload.defaults.blobUrlsMaxMemory || 268435456;\n                var maxLength = upload.defaults.blobUrlsMaxQueueSize || 200;\n                while ((upload.blobUrlsTotalSize > maxMemory || upload.blobUrls.length > maxLength) && upload.blobUrls.length > 1) {\n                  var obj = upload.blobUrls.splice(0, 1)[0];\n                  URL.revokeObjectURL(obj.url);\n                  upload.blobUrlsTotalSize -= obj.size;\n                }\n              }\n            });\n          } else {\n            var fileReader = new FileReader();\n            fileReader.onload = function (e) {\n              $timeout(function () {\n                file.$ngfDataUrl = e.target.result;\n                deferred.resolve(e.target.result, file);\n                $timeout(function () {\n                  delete file.$ngfDataUrl;\n                }, 1000);\n              });\n            };\n            fileReader.onerror = function () {\n              $timeout(function () {\n                file.$ngfDataUrl = '';\n                deferred.reject();\n              });\n            };\n            fileReader.readAsDataURL(file);\n          }\n        } else {\n          $timeout(function () {\n            file[disallowObjectUrl ? '$ngfDataUrl' : '$ngfBlobUrl'] = '';\n            deferred.reject();\n          });\n        }\n      });\n\n      if (disallowObjectUrl) {\n        p = file.$$ngfDataUrlPromise = deferred.promise;\n      } else {\n        p = file.$$ngfBlobUrlPromise = deferred.promise;\n      }\n      p['finally'](function () {\n        delete file[disallowObjectUrl ? '$$ngfDataUrlPromise' : '$$ngfBlobUrlPromise'];\n      });\n      return p;\n    };\n    return upload;\n  }]);\n\n  function getTagType(el) {\n    if (el.tagName.toLowerCase() === 'img') return 'image';\n    if (el.tagName.toLowerCase() === 'audio') return 'audio';\n    if (el.tagName.toLowerCase() === 'video') return 'video';\n    return /./;\n  }\n\n  function linkFileDirective(Upload, $timeout, scope, elem, attr, directiveName, resizeParams, isBackground) {\n    function constructDataUrl(file) {\n      var disallowObjectUrl = Upload.attrGetter('ngfNoObjectUrl', attr, scope);\n      Upload.dataUrl(file, disallowObjectUrl)['finally'](function () {\n        $timeout(function () {\n          var src = (disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl;\n          if (isBackground) {\n            elem.css('background-image', 'url(\\'' + (src || '') + '\\')');\n          } else {\n            elem.attr('src', src);\n          }\n          if (src) {\n            elem.removeClass('ng-hide');\n          } else {\n            elem.addClass('ng-hide');\n          }\n        });\n      });\n    }\n\n    $timeout(function () {\n      var unwatch = scope.$watch(attr[directiveName], function (file) {\n        var size = resizeParams;\n        if (directiveName === 'ngfThumbnail') {\n          if (!size) {\n            size = {\n              width: elem[0].naturalWidth || elem[0].clientWidth,\n              height: elem[0].naturalHeight || elem[0].clientHeight\n            };\n          }\n          if (size.width === 0 && window.getComputedStyle) {\n            var style = getComputedStyle(elem[0]);\n            if (style.width && style.width.indexOf('px') > -1 && style.height && style.height.indexOf('px') > -1) {\n              size = {\n                width: parseInt(style.width.slice(0, -2)),\n                height: parseInt(style.height.slice(0, -2))\n              };\n            }\n          }\n        }\n\n        if (angular.isString(file)) {\n          elem.removeClass('ng-hide');\n          if (isBackground) {\n            return elem.css('background-image', 'url(\\'' + file + '\\')');\n          } else {\n            return elem.attr('src', file);\n          }\n        }\n        if (file && file.type && file.type.search(getTagType(elem[0])) === 0 &&\n          (!isBackground || file.type.indexOf('image') === 0)) {\n          if (size && Upload.isResizeSupported()) {\n            size.resizeIf = function (width, height) {\n              return Upload.attrGetter('ngfResizeIf', attr, scope,\n                {$width: width, $height: height, $file: file});\n            };\n            Upload.resize(file, size).then(\n              function (f) {\n                constructDataUrl(f);\n              }, function (e) {\n                throw e;\n              }\n            );\n          } else {\n            constructDataUrl(file);\n          }\n        } else {\n          elem.addClass('ng-hide');\n        }\n      });\n\n      scope.$on('$destroy', function () {\n        unwatch();\n      });\n    });\n  }\n\n\n  /** @namespace attr.ngfSrc */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfSrc', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfSrc',\n          Upload.attrGetter('ngfResize', attr, scope), false);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfBackground */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfBackground', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfBackground',\n          Upload.attrGetter('ngfResize', attr, scope), true);\n      }\n    };\n  }]);\n\n  /** @namespace attr.ngfThumbnail */\n  /** @namespace attr.ngfAsBackground */\n  /** @namespace attr.ngfSize */\n  /** @namespace attr.ngfNoObjectUrl */\n  ngFileUpload.directive('ngfThumbnail', ['Upload', '$timeout', function (Upload, $timeout) {\n    return {\n      restrict: 'AE',\n      link: function (scope, elem, attr) {\n        var size = Upload.attrGetter('ngfSize', attr, scope);\n        linkFileDirective(Upload, $timeout, scope, elem, attr, 'ngfThumbnail', size,\n          Upload.attrGetter('ngfAsBackground', attr, scope));\n      }\n    };\n  }]);\n\n  ngFileUpload.config(['$compileProvider', function ($compileProvider) {\n    if ($compileProvider.imgSrcSanitizationWhitelist) $compileProvider.imgSrcSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n    if ($compileProvider.aHrefSanitizationWhitelist) $compileProvider.aHrefSanitizationWhitelist(/^\\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/);\n  }]);\n\n  ngFileUpload.filter('ngfDataUrl', ['UploadDataUrl', '$sce', function (UploadDataUrl, $sce) {\n    return function (file, disallowObjectUrl, trustedUrl) {\n      if (angular.isString(file)) {\n        return $sce.trustAsResourceUrl(file);\n      }\n      var src = file && ((disallowObjectUrl ? file.$ngfDataUrl : file.$ngfBlobUrl) || file.$ngfDataUrl);\n      if (file && !src) {\n        if (!file.$ngfDataUrlFilterInProgress && angular.isObject(file)) {\n          file.$ngfDataUrlFilterInProgress = true;\n          UploadDataUrl.dataUrl(file, disallowObjectUrl);\n        }\n        return '';\n      }\n      if (file) delete file.$ngfDataUrlFilterInProgress;\n      return (file && src ? (trustedUrl ? $sce.trustAsResourceUrl(src) : src) : file) || '';\n    };\n  }]);\n\n})();\n\nngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', function (UploadDataUrl, $q, $timeout) {\n  var upload = UploadDataUrl;\n\n  function globStringToRegex(str) {\n    var regexp = '', excludes = [];\n    if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n      regexp = str.substring(1, str.length - 1);\n    } else {\n      var split = str.split(',');\n      if (split.length > 1) {\n        for (var i = 0; i < split.length; i++) {\n          var r = globStringToRegex(split[i]);\n          if (r.regexp) {\n            regexp += '(' + r.regexp + ')';\n            if (i < split.length - 1) {\n              regexp += '|';\n            }\n          } else {\n            excludes = excludes.concat(r.excludes);\n          }\n        }\n      } else {\n        if (str.indexOf('!') === 0) {\n          excludes.push('^((?!' + globStringToRegex(str.substring(1)).regexp + ').)*$');\n        } else {\n          if (str.indexOf('.') === 0) {\n            str = '*' + str;\n          }\n          regexp = '^' + str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&') + '$';\n          regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n        }\n      }\n    }\n    return {regexp: regexp, excludes: excludes};\n  }\n\n  upload.validatePattern = function (file, val) {\n    if (!val) {\n      return true;\n    }\n    var pattern = globStringToRegex(val), valid = true;\n    if (pattern.regexp && pattern.regexp.length) {\n      var regexp = new RegExp(pattern.regexp, 'i');\n      valid = (file.type != null && regexp.test(file.type)) ||\n        (file.name != null && regexp.test(file.name));\n    }\n    var len = pattern.excludes.length;\n    while (len--) {\n      var exclude = new RegExp(pattern.excludes[len], 'i');\n      valid = valid && (file.type == null || exclude.test(file.type)) &&\n        (file.name == null || exclude.test(file.name));\n    }\n    return valid;\n  };\n\n  upload.ratioToFloat = function (val) {\n    var r = val.toString(), xIndex = r.search(/[x:]/i);\n    if (xIndex > -1) {\n      r = parseFloat(r.substring(0, xIndex)) / parseFloat(r.substring(xIndex + 1));\n    } else {\n      r = parseFloat(r);\n    }\n    return r;\n  };\n\n  upload.registerModelChangeValidator = function (ngModel, attr, scope) {\n    if (ngModel) {\n      ngModel.$formatters.push(function (files) {\n        if (ngModel.$dirty) {\n          var filesArray = files;\n          if (files && !angular.isArray(files)) {\n            filesArray = [files];\n          }\n          upload.validate(filesArray, 0, ngModel, attr, scope).then(function () {\n            upload.applyModelValidation(ngModel, filesArray);\n          });\n        }\n        return files;\n      });\n    }\n  };\n\n  function markModelAsDirty(ngModel, files) {\n    if (files != null && !ngModel.$dirty) {\n      if (ngModel.$setDirty) {\n        ngModel.$setDirty();\n      } else {\n        ngModel.$dirty = true;\n      }\n    }\n  }\n\n  upload.applyModelValidation = function (ngModel, files) {\n    markModelAsDirty(ngModel, files);\n    angular.forEach(ngModel.$ngfValidations, function (validation) {\n      ngModel.$setValidity(validation.name, validation.valid);\n    });\n  };\n\n  upload.getValidationAttr = function (attr, scope, name, validationName, file) {\n    var dName = 'ngf' + name[0].toUpperCase() + name.substr(1);\n    var val = upload.attrGetter(dName, attr, scope, {$file: file});\n    if (val == null) {\n      val = upload.attrGetter('ngfValidate', attr, scope, {$file: file});\n      if (val) {\n        var split = (validationName || name).split('.');\n        val = val[split[0]];\n        if (split.length > 1) {\n          val = val && val[split[1]];\n        }\n      }\n    }\n    return val;\n  };\n\n  upload.validate = function (files, prevLength, ngModel, attr, scope) {\n    ngModel = ngModel || {};\n    ngModel.$ngfValidations = ngModel.$ngfValidations || [];\n\n    angular.forEach(ngModel.$ngfValidations, function (v) {\n      v.valid = true;\n    });\n\n    var attrGetter = function (name, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    var ignoredErrors = (upload.attrGetter('ngfIgnoreInvalid', attr, scope) || '').split(' ');\n    var runAllValidation = upload.attrGetter('ngfRunAllValidations', attr, scope);\n\n    if (files == null || files.length === 0) {\n      return upload.emptyPromise({'validFiles': files, 'invalidFiles': []});\n    }\n\n    files = files.length === undefined ? [files] : files.slice(0);\n    var invalidFiles = [];\n\n    function validateSync(name, validationName, fn) {\n      if (files) {\n        var i = files.length, valid = null;\n        while (i--) {\n          var file = files[i];\n          if (file) {\n            var val = upload.getValidationAttr(attr, scope, name, validationName, file);\n            if (val != null) {\n              if (!fn(file, val, i)) {\n                if (ignoredErrors.indexOf(name) === -1) {\n                  file.$error = name;\n                  (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n                  file.$errorParam = val;\n                  if (invalidFiles.indexOf(file) === -1) {\n                    invalidFiles.push(file);\n                  }\n                  if (!runAllValidation) {\n                    files.splice(i, 1);\n                  }\n                  valid = false;\n                } else {\n                  files.splice(i, 1);\n                }\n              }\n            }\n          }\n        }\n        if (valid !== null) {\n          ngModel.$ngfValidations.push({name: name, valid: valid});\n        }\n      }\n    }\n\n    validateSync('pattern', null, upload.validatePattern);\n    validateSync('minSize', 'size.min', function (file, val) {\n      return file.size + 0.1 >= upload.translateScalars(val);\n    });\n    validateSync('maxSize', 'size.max', function (file, val) {\n      return file.size - 0.1 <= upload.translateScalars(val);\n    });\n    var totalSize = 0;\n    validateSync('maxTotalSize', null, function (file, val) {\n      totalSize += file.size;\n      if (totalSize > upload.translateScalars(val)) {\n        files.splice(0, files.length);\n        return false;\n      }\n      return true;\n    });\n\n    validateSync('validateFn', null, function (file, r) {\n      return r === true || r === null || r === '';\n    });\n\n    if (!files.length) {\n      return upload.emptyPromise({'validFiles': [], 'invalidFiles': invalidFiles});\n    }\n\n    function validateAsync(name, validationName, type, asyncFn, fn) {\n      function resolveResult(defer, file, val) {\n        function resolveInternal(fn) {\n          if (fn()) {\n            if (ignoredErrors.indexOf(name) === -1) {\n              file.$error = name;\n              (file.$errorMessages = (file.$errorMessages || {}))[name] = true;\n              file.$errorParam = val;\n              if (invalidFiles.indexOf(file) === -1) {\n                invalidFiles.push(file);\n              }\n              if (!runAllValidation) {\n                var i = files.indexOf(file);\n                if (i > -1) files.splice(i, 1);\n              }\n              defer.resolve(false);\n            } else {\n              var j = files.indexOf(file);\n              if (j > -1) files.splice(j, 1);\n              defer.resolve(true);\n            }\n          } else {\n            defer.resolve(true);\n          }\n        }\n\n        if (val != null) {\n          asyncFn(file, val).then(function (d) {\n            resolveInternal(function () {\n              return !fn(d, val);\n            });\n          }, function () {\n            resolveInternal(function () {\n              return attrGetter('ngfValidateForce', {$file: file});\n            });\n          });\n        } else {\n          defer.resolve(true);\n        }\n      }\n\n      var promises = [upload.emptyPromise(true)];\n      if (files) {\n        files = files.length === undefined ? [files] : files;\n        angular.forEach(files, function (file) {\n          var defer = $q.defer();\n          promises.push(defer.promise);\n          if (type && (file.type == null || file.type.search(type) !== 0)) {\n            defer.resolve(true);\n            return;\n          }\n          if (name === 'dimensions' && upload.attrGetter('ngfDimensions', attr) != null) {\n            upload.imageDimensions(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDimensions', {$file: file, $width: d.width, $height: d.height}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else if (name === 'duration' && upload.attrGetter('ngfDuration', attr) != null) {\n            upload.mediaDuration(file).then(function (d) {\n              resolveResult(defer, file,\n                attrGetter('ngfDuration', {$file: file, $duration: d}));\n            }, function () {\n              defer.resolve(false);\n            });\n          } else {\n            resolveResult(defer, file,\n              upload.getValidationAttr(attr, scope, name, validationName, file));\n          }\n        });\n      }\n      var deffer = $q.defer();\n      $q.all(promises).then(function (values) {\n        var isValid = true;\n        for (var i = 0; i < values.length; i++) {\n          if (!values[i]) {\n            isValid = false;\n            break;\n          }\n        }\n        ngModel.$ngfValidations.push({name: name, valid: isValid});\n        deffer.resolve(isValid);\n      });\n      return deffer.promise;\n    }\n\n    var deffer = $q.defer();\n    var promises = [];\n\n    promises.push(validateAsync('maxHeight', 'height.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height <= val;\n      }));\n    promises.push(validateAsync('minHeight', 'height.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.height >= val;\n      }));\n    promises.push(validateAsync('maxWidth', 'width.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width <= val;\n      }));\n    promises.push(validateAsync('minWidth', 'width.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return d.width >= val;\n      }));\n    promises.push(validateAsync('dimensions', null, /image/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n    promises.push(validateAsync('ratio', null, /image/,\n      this.imageDimensions, function (d, val) {\n        var split = val.toString().split(','), valid = false;\n        for (var i = 0; i < split.length; i++) {\n          if (Math.abs((d.width / d.height) - upload.ratioToFloat(split[i])) < 0.01) {\n            valid = true;\n          }\n        }\n        return valid;\n      }));\n    promises.push(validateAsync('maxRatio', 'ratio.max', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) < 0.0001;\n      }));\n    promises.push(validateAsync('minRatio', 'ratio.min', /image/,\n      this.imageDimensions, function (d, val) {\n        return (d.width / d.height) - upload.ratioToFloat(val) > -0.0001;\n      }));\n    promises.push(validateAsync('maxDuration', 'duration.max', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d <= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('minDuration', 'duration.min', /audio|video/,\n      this.mediaDuration, function (d, val) {\n        return d >= upload.translateScalars(val);\n      }));\n    promises.push(validateAsync('duration', null, /audio|video/,\n      function (file, val) {\n        return upload.emptyPromise(val);\n      }, function (r) {\n        return r;\n      }));\n\n    promises.push(validateAsync('validateAsyncFn', null, null,\n      function (file, val) {\n        return val;\n      }, function (r) {\n        return r === true || r === null || r === '';\n      }));\n\n    $q.all(promises).then(function () {\n\n      if (runAllValidation) {\n        for (var i = 0; i < files.length; i++) {\n          var file = files[i];\n          if (file.$error) {\n            files.splice(i--, 1);\n          }\n        }\n      }\n\n      runAllValidation = false;\n      validateSync('maxFiles', null, function (file, val, i) {\n        return prevLength + i < val;\n      });\n\n      deffer.resolve({'validFiles': files, 'invalidFiles': invalidFiles});\n    });\n    return deffer.promise;\n  };\n\n  upload.imageDimensions = function (file) {\n    if (file.$ngfWidth && file.$ngfHeight) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve({width: file.$ngfWidth, height: file.$ngfHeight});\n      });\n      return d.promise;\n    }\n    if (file.$ngfDimensionPromise) return file.$ngfDimensionPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('image') !== 0) {\n        deferred.reject('not image');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var img = angular.element('<img>').attr('src', dataUrl)\n          .css('visibility', 'hidden').css('position', 'fixed')\n          .css('max-width', 'none !important').css('max-height', 'none !important');\n\n        function success() {\n          var width = img[0].naturalWidth || img[0].clientWidth;\n          var height = img[0].naturalHeight || img[0].clientHeight;\n          img.remove();\n          file.$ngfWidth = width;\n          file.$ngfHeight = height;\n          deferred.resolve({width: width, height: height});\n        }\n\n        function error() {\n          img.remove();\n          deferred.reject('load error');\n        }\n\n        img.on('load', success);\n        img.on('error', error);\n\n        var secondsCounter = 0;\n        function checkLoadErrorInCaseOfNoCallback() {\n          $timeout(function () {\n            if (img[0].parentNode) {\n              if (img[0].clientWidth) {\n                success();\n              } else if (secondsCounter++ > 10) {\n                error();\n              } else {\n                checkLoadErrorInCaseOfNoCallback();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadErrorInCaseOfNoCallback();\n\n        angular.element(document.getElementsByTagName('body')[0]).append(img);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDimensionPromise = deferred.promise;\n    file.$ngfDimensionPromise['finally'](function () {\n      delete file.$ngfDimensionPromise;\n    });\n    return file.$ngfDimensionPromise;\n  };\n\n  upload.mediaDuration = function (file) {\n    if (file.$ngfDuration) {\n      var d = $q.defer();\n      $timeout(function () {\n        d.resolve(file.$ngfDuration);\n      });\n      return d.promise;\n    }\n    if (file.$ngfDurationPromise) return file.$ngfDurationPromise;\n\n    var deferred = $q.defer();\n    $timeout(function () {\n      if (file.type.indexOf('audio') !== 0 && file.type.indexOf('video') !== 0) {\n        deferred.reject('not media');\n        return;\n      }\n      upload.dataUrl(file).then(function (dataUrl) {\n        var el = angular.element(file.type.indexOf('audio') === 0 ? '<audio>' : '<video>')\n          .attr('src', dataUrl).css('visibility', 'none').css('position', 'fixed');\n\n        function success() {\n          var duration = el[0].duration;\n          file.$ngfDuration = duration;\n          el.remove();\n          deferred.resolve(duration);\n        }\n\n        function error() {\n          el.remove();\n          deferred.reject('load error');\n        }\n\n        el.on('loadedmetadata', success);\n        el.on('error', error);\n        var count = 0;\n\n        function checkLoadError() {\n          $timeout(function () {\n            if (el[0].parentNode) {\n              if (el[0].duration) {\n                success();\n              } else if (count > 10) {\n                error();\n              } else {\n                checkLoadError();\n              }\n            }\n          }, 1000);\n        }\n\n        checkLoadError();\n\n        angular.element(document.body).append(el);\n      }, function () {\n        deferred.reject('load error');\n      });\n    });\n\n    file.$ngfDurationPromise = deferred.promise;\n    file.$ngfDurationPromise['finally'](function () {\n      delete file.$ngfDurationPromise;\n    });\n    return file.$ngfDurationPromise;\n  };\n  return upload;\n}\n]);\n\nngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadValidate, $q) {\n  var upload = UploadValidate;\n\n  /**\n   * Conserve aspect ratio of the original region. Useful when shrinking/enlarging\n   * images to fit into a certain area.\n   * Source:  http://stackoverflow.com/a/14731922\n   *\n   * @param {Number} srcWidth Source area width\n   * @param {Number} srcHeight Source area height\n   * @param {Number} maxWidth Nestable area maximum available width\n   * @param {Number} maxHeight Nestable area maximum available height\n   * @return {Object} { width, height }\n   */\n  var calculateAspectRatioFit = function (srcWidth, srcHeight, maxWidth, maxHeight, centerCrop) {\n    var ratio = centerCrop ? Math.max(maxWidth / srcWidth, maxHeight / srcHeight) :\n      Math.min(maxWidth / srcWidth, maxHeight / srcHeight);\n    return {\n      width: srcWidth * ratio, height: srcHeight * ratio,\n      marginX: srcWidth * ratio - maxWidth, marginY: srcHeight * ratio - maxHeight\n    };\n  };\n\n  // Extracted from https://github.com/romelgomez/angular-firebase-image-upload/blob/master/app/scripts/fileUpload.js#L89\n  var resize = function (imagen, width, height, quality, type, ratio, centerCrop, resizeIf) {\n    var deferred = $q.defer();\n    var canvasElement = document.createElement('canvas');\n    var imageElement = document.createElement('img');\n    imageElement.setAttribute('style', 'visibility:hidden;position:fixed;z-index:-100000');\n    document.body.appendChild(imageElement);\n\n    imageElement.onload = function () {\n      var imgWidth = imageElement.width, imgHeight = imageElement.height;\n      imageElement.parentNode.removeChild(imageElement);\n      if (resizeIf != null && resizeIf(imgWidth, imgHeight) === false) {\n        deferred.reject('resizeIf');\n        return;\n      }\n      try {\n        if (ratio) {\n          var ratioFloat = upload.ratioToFloat(ratio);\n          var imgRatio = imgWidth / imgHeight;\n          if (imgRatio < ratioFloat) {\n            width = imgWidth;\n            height = width / ratioFloat;\n          } else {\n            height = imgHeight;\n            width = height * ratioFloat;\n          }\n        }\n        if (!width) {\n          width = imgWidth;\n        }\n        if (!height) {\n          height = imgHeight;\n        }\n        var dimensions = calculateAspectRatioFit(imgWidth, imgHeight, width, height, centerCrop);\n        canvasElement.width = Math.min(dimensions.width, width);\n        canvasElement.height = Math.min(dimensions.height, height);\n        var context = canvasElement.getContext('2d');\n        context.drawImage(imageElement,\n          Math.min(0, -dimensions.marginX / 2), Math.min(0, -dimensions.marginY / 2),\n          dimensions.width, dimensions.height);\n        deferred.resolve(canvasElement.toDataURL(type || 'image/WebP', quality || 0.934));\n      } catch (e) {\n        deferred.reject(e);\n      }\n    };\n    imageElement.onerror = function () {\n      imageElement.parentNode.removeChild(imageElement);\n      deferred.reject();\n    };\n    imageElement.src = imagen;\n    return deferred.promise;\n  };\n\n  upload.dataUrltoBlob = function (dataurl, name, origSize) {\n    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],\n      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);\n    while (n--) {\n      u8arr[n] = bstr.charCodeAt(n);\n    }\n    var blob = new window.Blob([u8arr], {type: mime});\n    blob.name = name;\n    blob.$ngfOrigSize = origSize;\n    return blob;\n  };\n\n  upload.isResizeSupported = function () {\n    var elem = document.createElement('canvas');\n    return window.atob && elem.getContext && elem.getContext('2d') && window.Blob;\n  };\n\n  if (upload.isResizeSupported()) {\n    // add name getter to the blob constructor prototype\n    Object.defineProperty(window.Blob.prototype, 'name', {\n      get: function () {\n        return this.$ngfName;\n      },\n      set: function (v) {\n        this.$ngfName = v;\n      },\n      configurable: true\n    });\n  }\n\n  upload.resize = function (file, options) {\n    if (file.type.indexOf('image') !== 0) return upload.emptyPromise(file);\n\n    var deferred = $q.defer();\n    upload.dataUrl(file, true).then(function (url) {\n      resize(url, options.width, options.height, options.quality, options.type || file.type,\n        options.ratio, options.centerCrop, options.resizeIf)\n        .then(function (dataUrl) {\n          if (file.type === 'image/jpeg' && options.restoreExif !== false) {\n            try {\n              dataUrl = upload.restoreExif(url, dataUrl);\n            } catch (e) {\n              setTimeout(function () {throw e;}, 1);\n            }\n          }\n          try {\n            var blob = upload.dataUrltoBlob(dataUrl, file.name, file.size);\n            deferred.resolve(blob);\n          } catch (e) {\n            deferred.reject(e);\n          }\n        }, function (r) {\n          if (r === 'resizeIf') {\n            deferred.resolve(file);\n          }\n          deferred.reject(r);\n        });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  return upload;\n}]);\n\n(function () {\n  ngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$window', 'Upload', '$http', '$q',\n    function ($parse, $timeout, $window, Upload, $http, $q) {\n      return {\n        restrict: 'AEC',\n        require: '?ngModel',\n        link: function (scope, elem, attr, ngModel) {\n          linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, Upload, $http, $q);\n        }\n      };\n    }]);\n\n  ngFileUpload.directive('ngfNoFileDrop', function () {\n    return function (scope, elem) {\n      if (dropAvailable()) elem.css('display', 'none');\n    };\n  });\n\n  ngFileUpload.directive('ngfDropAvailable', ['$parse', '$timeout', 'Upload', function ($parse, $timeout, Upload) {\n    return function (scope, elem, attr) {\n      if (dropAvailable()) {\n        var model = $parse(Upload.attrGetter('ngfDropAvailable', attr));\n        $timeout(function () {\n          model(scope);\n          if (model.assign) {\n            model.assign(scope, true);\n          }\n        });\n      }\n    };\n  }]);\n\n  function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, upload, $http, $q) {\n    var available = dropAvailable();\n\n    var attrGetter = function (name, scope, params) {\n      return upload.attrGetter(name, attr, scope, params);\n    };\n\n    if (attrGetter('dropAvailable')) {\n      $timeout(function () {\n        if (scope[attrGetter('dropAvailable')]) {\n          scope[attrGetter('dropAvailable')].value = available;\n        } else {\n          scope[attrGetter('dropAvailable')] = available;\n        }\n      });\n    }\n    if (!available) {\n      if (attrGetter('ngfHideOnDropNotAvailable', scope) === true) {\n        elem.css('display', 'none');\n      }\n      return;\n    }\n\n    function isDisabled() {\n      return elem.attr('disabled') || attrGetter('ngfDropDisabled', scope);\n    }\n\n    if (attrGetter('ngfSelect') == null) {\n      upload.registerModelChangeValidator(ngModel, attr, scope);\n    }\n\n    var leaveTimeout = null;\n    var stopPropagation = $parse(attrGetter('ngfStopPropagation'));\n    var dragOverDelay = 1;\n    var actualDragOverClass;\n\n    elem[0].addEventListener('dragover', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      // handling dragover events from the Chrome download bar\n      if (navigator.userAgent.indexOf('Chrome') > -1) {\n        var b = evt.dataTransfer.effectAllowed;\n        evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';\n      }\n      $timeout.cancel(leaveTimeout);\n      if (!actualDragOverClass) {\n        actualDragOverClass = 'C';\n        calculateDragOverClass(scope, attr, evt, function (clazz) {\n          actualDragOverClass = clazz;\n          elem.addClass(actualDragOverClass);\n          attrGetter('ngfDrag', scope, {$isDragging: true, $class: actualDragOverClass, $event: evt});\n        });\n      }\n    }, false);\n    elem[0].addEventListener('dragenter', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n    }, false);\n    elem[0].addEventListener('dragleave', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      leaveTimeout = $timeout(function () {\n        if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n        actualDragOverClass = null;\n        attrGetter('ngfDrag', scope, {$isDragging: false, $event: evt});\n      }, dragOverDelay || 100);\n    }, false);\n    elem[0].addEventListener('drop', function (evt) {\n      if (isDisabled() || !upload.shouldUpdateOn('drop', attr, scope)) return;\n      evt.preventDefault();\n      if (stopPropagation(scope)) evt.stopPropagation();\n      if (actualDragOverClass) elem.removeClass(actualDragOverClass);\n      actualDragOverClass = null;\n      extractFilesAndUpdateModel(evt.dataTransfer, evt, 'dropUrl');\n    }, false);\n    elem[0].addEventListener('paste', function (evt) {\n      if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n        attrGetter('ngfEnableFirefoxPaste', scope)) {\n        evt.preventDefault();\n      }\n      if (isDisabled() || !upload.shouldUpdateOn('paste', attr, scope)) return;\n      extractFilesAndUpdateModel(evt.clipboardData || evt.originalEvent.clipboardData, evt, 'pasteUrl');\n    }, false);\n\n    if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 &&\n      attrGetter('ngfEnableFirefoxPaste', scope)) {\n      elem.attr('contenteditable', true);\n      elem.on('keypress', function (e) {\n        if (!e.metaKey && !e.ctrlKey) {\n          e.preventDefault();\n        }\n      });\n    }\n\n    function extractFilesAndUpdateModel(source, evt, updateOnType) {\n      if (!source) return;\n      // html needs to be calculated on the same process otherwise the data will be wiped\n      // after promise resolve or setTimeout.\n      var html;\n      try {\n        html = source && source.getData && source.getData('text/html');\n      } catch (e) {/* Fix IE11 that throw error calling getData */\n      }\n      extractFiles(source.items, source.files, attrGetter('ngfAllowDir', scope) !== false,\n        attrGetter('multiple') || attrGetter('ngfMultiple', scope)).then(function (files) {\n        if (files.length) {\n          updateModel(files, evt);\n        } else {\n          extractFilesFromHtml(updateOnType, html).then(function (files) {\n            updateModel(files, evt);\n          });\n        }\n      });\n    }\n\n    function updateModel(files, evt) {\n      upload.updateModel(ngModel, attr, scope, attrGetter('ngfChange') || attrGetter('ngfDrop'), files, evt);\n    }\n\n    function extractFilesFromHtml(updateOn, html) {\n      if (!upload.shouldUpdateOn(updateOn, attr, scope) || typeof html !== 'string') return upload.rejectPromise([]);\n      var urls = [];\n      html.replace(/<(img src|img [^>]* src) *=\\\"([^\\\"]*)\\\"/gi, function (m, n, src) {\n        urls.push(src);\n      });\n      var promises = [], files = [];\n      if (urls.length) {\n        angular.forEach(urls, function (url) {\n          promises.push(upload.urlToBlob(url).then(function (blob) {\n            files.push(blob);\n          }));\n        });\n        var defer = $q.defer();\n        $q.all(promises).then(function () {\n          defer.resolve(files);\n        }, function (e) {\n          defer.reject(e);\n        });\n        return defer.promise;\n      }\n      return upload.emptyPromise();\n    }\n\n    function calculateDragOverClass(scope, attr, evt, callback) {\n      var obj = attrGetter('ngfDragOverClass', scope, {$event: evt}), dClass = 'dragover';\n      if (angular.isString(obj)) {\n        dClass = obj;\n      } else if (obj) {\n        if (obj.delay) dragOverDelay = obj.delay;\n        if (obj.accept || obj.reject) {\n          var items = evt.dataTransfer.items;\n          if (items == null || !items.length) {\n            dClass = obj.accept;\n          } else {\n            var pattern = obj.pattern || attrGetter('ngfPattern', scope, {$event: evt});\n            var len = items.length;\n            while (len--) {\n              if (!upload.validatePattern(items[len], pattern)) {\n                dClass = obj.reject;\n                break;\n              } else {\n                dClass = obj.accept;\n              }\n            }\n          }\n        }\n      }\n      callback(dClass);\n    }\n\n    function extractFiles(items, fileList, allowDir, multiple) {\n      var maxFiles = upload.getValidationAttr(attr, scope, 'maxFiles');\n      if (maxFiles == null) {\n        maxFiles = Number.MAX_VALUE;\n      }\n      var maxTotalSize = upload.getValidationAttr(attr, scope, 'maxTotalSize');\n      if (maxTotalSize == null) {\n        maxTotalSize = Number.MAX_VALUE;\n      }\n      var includeDir = attrGetter('ngfIncludeDir', scope);\n      var files = [], totalSize = 0;\n\n      function traverseFileTree(entry, path) {\n        var defer = $q.defer();\n        if (entry != null) {\n          if (entry.isDirectory) {\n            var promises = [upload.emptyPromise()];\n            if (includeDir) {\n              var file = {type: 'directory'};\n              file.name = file.path = (path || '') + entry.name;\n              files.push(file);\n            }\n            var dirReader = entry.createReader();\n            var entries = [];\n            var readEntries = function () {\n              dirReader.readEntries(function (results) {\n                try {\n                  if (!results.length) {\n                    angular.forEach(entries.slice(0), function (e) {\n                      if (files.length <= maxFiles && totalSize <= maxTotalSize) {\n                        promises.push(traverseFileTree(e, (path ? path : '') + entry.name + '/'));\n                      }\n                    });\n                    $q.all(promises).then(function () {\n                      defer.resolve();\n                    }, function (e) {\n                      defer.reject(e);\n                    });\n                  } else {\n                    entries = entries.concat(Array.prototype.slice.call(results || [], 0));\n                    readEntries();\n                  }\n                } catch (e) {\n                  defer.reject(e);\n                }\n              }, function (e) {\n                defer.reject(e);\n              });\n            };\n            readEntries();\n          } else {\n            entry.file(function (file) {\n              try {\n                file.path = (path ? path : '') + file.name;\n                if (includeDir) {\n                  file = upload.rename(file, file.path);\n                }\n                files.push(file);\n                totalSize += file.size;\n                defer.resolve();\n              } catch (e) {\n                defer.reject(e);\n              }\n            }, function (e) {\n              defer.reject(e);\n            });\n          }\n        }\n        return defer.promise;\n      }\n\n      var promises = [upload.emptyPromise()];\n\n      if (items && items.length > 0 && $window.location.protocol !== 'file:') {\n        for (var i = 0; i < items.length; i++) {\n          if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {\n            var entry = items[i].webkitGetAsEntry();\n            if (entry.isDirectory && !allowDir) {\n              continue;\n            }\n            if (entry != null) {\n              promises.push(traverseFileTree(entry));\n            }\n          } else {\n            var f = items[i].getAsFile();\n            if (f != null) {\n              files.push(f);\n              totalSize += f.size;\n            }\n          }\n          if (files.length > maxFiles || totalSize > maxTotalSize ||\n            (!multiple && files.length > 0)) break;\n        }\n      } else {\n        if (fileList != null) {\n          for (var j = 0; j < fileList.length; j++) {\n            var file = fileList.item(j);\n            if (file.type || file.size > 0) {\n              files.push(file);\n              totalSize += file.size;\n            }\n            if (files.length > maxFiles || totalSize > maxTotalSize ||\n              (!multiple && files.length > 0)) break;\n          }\n        }\n      }\n\n      var defer = $q.defer();\n      $q.all(promises).then(function () {\n        if (!multiple && !includeDir && files.length) {\n          var i = 0;\n          while (files[i] && files[i].type === 'directory') i++;\n          defer.resolve([files[i]]);\n        } else {\n          defer.resolve(files);\n        }\n      }, function (e) {\n        defer.reject(e);\n      });\n\n      return defer.promise;\n    }\n  }\n\n  function dropAvailable() {\n    var div = document.createElement('div');\n    return ('draggable' in div) && ('ondrop' in div) && !/Edge\\/12./i.test(navigator.userAgent);\n  }\n\n})();\n\n// customized version of https://github.com/exif-js/exif-js\nngFileUpload.service('UploadExif', ['UploadResize', '$q', function (UploadResize, $q) {\n  var upload = UploadResize;\n\n  upload.isExifSupported = function () {\n    return window.FileReader && new FileReader().readAsArrayBuffer && upload.isResizeSupported();\n  };\n\n  function applyTransform(ctx, orientation, width, height) {\n    switch (orientation) {\n      case 2:\n        return ctx.transform(-1, 0, 0, 1, width, 0);\n      case 3:\n        return ctx.transform(-1, 0, 0, -1, width, height);\n      case 4:\n        return ctx.transform(1, 0, 0, -1, 0, height);\n      case 5:\n        return ctx.transform(0, 1, 1, 0, 0, 0);\n      case 6:\n        return ctx.transform(0, 1, -1, 0, height, 0);\n      case 7:\n        return ctx.transform(0, -1, -1, 0, height, width);\n      case 8:\n        return ctx.transform(0, -1, 1, 0, 0, width);\n    }\n  }\n\n  upload.readOrientation = function (file) {\n    var defer = $q.defer();\n    var reader = new FileReader();\n    var slicedFile = file.slice ? file.slice(0, 64 * 1024) : file;\n    reader.readAsArrayBuffer(slicedFile);\n    reader.onerror = function (e) {\n      return defer.reject(e);\n    };\n    reader.onload = function (e) {\n      var result = {orientation: 1};\n      var view = new DataView(this.result);\n      if (view.getUint16(0, false) !== 0xFFD8) return defer.resolve(result);\n\n      var length = view.byteLength,\n        offset = 2;\n      while (offset < length) {\n        var marker = view.getUint16(offset, false);\n        offset += 2;\n        if (marker === 0xFFE1) {\n          if (view.getUint32(offset += 2, false) !== 0x45786966) return defer.resolve(result);\n\n          var little = view.getUint16(offset += 6, false) === 0x4949;\n          offset += view.getUint32(offset + 4, little);\n          var tags = view.getUint16(offset, little);\n          offset += 2;\n          for (var i = 0; i < tags; i++)\n            if (view.getUint16(offset + (i * 12), little) === 0x0112) {\n              var orientation = view.getUint16(offset + (i * 12) + 8, little);\n              if (orientation >= 2 && orientation <= 8) {\n                view.setUint16(offset + (i * 12) + 8, 1, little);\n                result.fixedArrayBuffer = e.target.result;\n              }\n              result.orientation = orientation;\n              return defer.resolve(result);\n            }\n        } else if ((marker & 0xFF00) !== 0xFF00) break;\n        else offset += view.getUint16(offset, false);\n      }\n      return defer.resolve(result);\n    };\n    return defer.promise;\n  };\n\n  function arrayBufferToBase64(buffer) {\n    var binary = '';\n    var bytes = new Uint8Array(buffer);\n    var len = bytes.byteLength;\n    for (var i = 0; i < len; i++) {\n      binary += String.fromCharCode(bytes[i]);\n    }\n    return window.btoa(binary);\n  }\n\n  upload.applyExifRotation = function (file) {\n    if (file.type.indexOf('image/jpeg') !== 0) {\n      return upload.emptyPromise(file);\n    }\n\n    var deferred = $q.defer();\n    upload.readOrientation(file).then(function (result) {\n      if (result.orientation < 2 || result.orientation > 8) {\n        return deferred.resolve(file);\n      }\n      upload.dataUrl(file, true).then(function (url) {\n        var canvas = document.createElement('canvas');\n        var img = document.createElement('img');\n\n        img.onload = function () {\n          try {\n            canvas.width = result.orientation > 4 ? img.height : img.width;\n            canvas.height = result.orientation > 4 ? img.width : img.height;\n            var ctx = canvas.getContext('2d');\n            applyTransform(ctx, result.orientation, img.width, img.height);\n            ctx.drawImage(img, 0, 0);\n            var dataUrl = canvas.toDataURL(file.type || 'image/WebP', 0.934);\n            dataUrl = upload.restoreExif(arrayBufferToBase64(result.fixedArrayBuffer), dataUrl);\n            var blob = upload.dataUrltoBlob(dataUrl, file.name);\n            deferred.resolve(blob);\n          } catch (e) {\n            return deferred.reject(e);\n          }\n        };\n        img.onerror = function () {\n          deferred.reject();\n        };\n        img.src = url;\n      }, function (e) {\n        deferred.reject(e);\n      });\n    }, function (e) {\n      deferred.reject(e);\n    });\n    return deferred.promise;\n  };\n\n  upload.restoreExif = function (orig, resized) {\n    var ExifRestorer = {};\n\n    ExifRestorer.KEY_STR = 'ABCDEFGHIJKLMNOP' +\n      'QRSTUVWXYZabcdef' +\n      'ghijklmnopqrstuv' +\n      'wxyz0123456789+/' +\n      '=';\n\n    ExifRestorer.encode64 = function (input) {\n      var output = '',\n        chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0;\n\n      do {\n        chr1 = input[i++];\n        chr2 = input[i++];\n        chr3 = input[i++];\n\n        enc1 = chr1 >> 2;\n        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n        enc4 = chr3 & 63;\n\n        if (isNaN(chr2)) {\n          enc3 = enc4 = 64;\n        } else if (isNaN(chr3)) {\n          enc4 = 64;\n        }\n\n        output = output +\n          this.KEY_STR.charAt(enc1) +\n          this.KEY_STR.charAt(enc2) +\n          this.KEY_STR.charAt(enc3) +\n          this.KEY_STR.charAt(enc4);\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n      } while (i < input.length);\n\n      return output;\n    };\n\n    ExifRestorer.restore = function (origFileBase64, resizedFileBase64) {\n      if (origFileBase64.match('data:image/jpeg;base64,')) {\n        origFileBase64 = origFileBase64.replace('data:image/jpeg;base64,', '');\n      }\n\n      var rawImage = this.decode64(origFileBase64);\n      var segments = this.slice2Segments(rawImage);\n\n      var image = this.exifManipulation(resizedFileBase64, segments);\n\n      return 'data:image/jpeg;base64,' + this.encode64(image);\n    };\n\n\n    ExifRestorer.exifManipulation = function (resizedFileBase64, segments) {\n      var exifArray = this.getExifArray(segments),\n        newImageArray = this.insertExif(resizedFileBase64, exifArray);\n      return new Uint8Array(newImageArray);\n    };\n\n\n    ExifRestorer.getExifArray = function (segments) {\n      var seg;\n      for (var x = 0; x < segments.length; x++) {\n        seg = segments[x];\n        if (seg[0] === 255 & seg[1] === 225) //(ff e1)\n        {\n          return seg;\n        }\n      }\n      return [];\n    };\n\n\n    ExifRestorer.insertExif = function (resizedFileBase64, exifArray) {\n      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', ''),\n        buf = this.decode64(imageData),\n        separatePoint = buf.indexOf(255, 3),\n        mae = buf.slice(0, separatePoint),\n        ato = buf.slice(separatePoint),\n        array = mae;\n\n      array = array.concat(exifArray);\n      array = array.concat(ato);\n      return array;\n    };\n\n\n    ExifRestorer.slice2Segments = function (rawImageArray) {\n      var head = 0,\n        segments = [];\n\n      while (1) {\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {\n          break;\n        }\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {\n          head += 2;\n        }\n        else {\n          var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],\n            endPoint = head + length + 2,\n            seg = rawImageArray.slice(head, endPoint);\n          segments.push(seg);\n          head = endPoint;\n        }\n        if (head > rawImageArray.length) {\n          break;\n        }\n      }\n\n      return segments;\n    };\n\n\n    ExifRestorer.decode64 = function (input) {\n      var chr1, chr2, chr3 = '',\n        enc1, enc2, enc3, enc4 = '',\n        i = 0,\n        buf = [];\n\n      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n      var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n      if (base64test.exec(input)) {\n        console.log('There were invalid base64 characters in the input text.\\n' +\n          'Valid base64 characters are A-Z, a-z, 0-9, ' + ', ' / ',and \"=\"\\n' +\n          'Expect errors in decoding.');\n      }\n      input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n\n      do {\n        enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n\n        chr1 = (enc1 << 2) | (enc2 >> 4);\n        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n        chr3 = ((enc3 & 3) << 6) | enc4;\n\n        buf.push(chr1);\n\n        if (enc3 !== 64) {\n          buf.push(chr2);\n        }\n        if (enc4 !== 64) {\n          buf.push(chr3);\n        }\n\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n\n      } while (i < input.length);\n\n      return buf;\n    };\n\n    return ExifRestorer.restore(orig, resized);  //<= EXIF\n  };\n\n  return upload;\n}]);\n\n","require('./dist/ng-file-upload-all');\nmodule.exports = 'ngFileUpload';","/*!\n * angular-translate - v2.19.1 - 2024-01-21\n * \n * Copyright (c) 2024 The angular-translate team, Pascal Precht; Licensed MIT\n */\n(function (root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module unless amdModuleId is set\n    define([], function () {\n      return (factory());\n    });\n  } else if (typeof module === 'object' && module.exports) {\n    // Node. Does not work with strict CommonJS, but\n    // only CommonJS-like environments that support module.exports,\n    // like Node.\n    module.exports = factory();\n  } else {\n    factory();\n  }\n}(this, function () {\n\n/**\n * @ngdoc overview\n * @name pascalprecht.translate\n *\n * @description\n * The main module which holds everything together.\n */\nrunTranslate.$inject = ['$translate'];\n$translate.$inject = ['$STORAGE_KEY', '$windowProvider', '$translateSanitizationProvider', 'pascalprechtTranslateOverrider'];\n$translateDefaultInterpolation.$inject = ['$interpolate', '$translateSanitization'];\ntranslateDirective.$inject = ['$translate', '$interpolate', '$compile', '$parse', '$rootScope'];\ntranslateAttrDirective.$inject = ['$translate', '$rootScope'];\ntranslateCloakDirective.$inject = ['$translate', '$rootScope'];\ntranslateFilterFactory.$inject = ['$parse', '$translate'];\n$translationCache.$inject = ['$cacheFactory'];\nangular.module('pascalprecht.translate', ['ng'])\n  .run(runTranslate);\n\nfunction runTranslate($translate) {\n\n  'use strict';\n\n  var key = $translate.storageKey(),\n    storage = $translate.storage();\n\n  var fallbackFromIncorrectStorageValue = function () {\n    var preferred = $translate.preferredLanguage();\n    if (angular.isString(preferred)) {\n      $translate.use(preferred);\n      // $translate.use() will also remember the language.\n      // So, we don't need to call storage.put() here.\n    } else {\n      storage.put(key, $translate.use());\n    }\n  };\n\n  fallbackFromIncorrectStorageValue.displayName = 'fallbackFromIncorrectStorageValue';\n\n  if (storage) {\n    if (!storage.get(key)) {\n      fallbackFromIncorrectStorageValue();\n    } else {\n      $translate.use(storage.get(key))['catch'](fallbackFromIncorrectStorageValue);\n    }\n  } else if (angular.isString($translate.preferredLanguage())) {\n    $translate.use($translate.preferredLanguage());\n  }\n}\n\nrunTranslate.displayName = 'runTranslate';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateSanitizationProvider\n *\n * @description\n *\n * Configurations for $translateSanitization\n */\nangular.module('pascalprecht.translate').provider('$translateSanitization', $translateSanitizationProvider);\n\nfunction $translateSanitizationProvider () {\n\n  'use strict';\n\n  var $sanitize,\n      $sce,\n      currentStrategy = null, // TODO change to either 'sanitize', 'escape' or ['sanitize', 'escapeParameters'] in 3.0.\n      hasConfiguredStrategy = false,\n      hasShownNoStrategyConfiguredWarning = false,\n      strategies;\n\n  /**\n   * Definition of a sanitization strategy function\n   * @callback StrategyFunction\n   * @param {string|object} value - value to be sanitized (either a string or an interpolated value map)\n   * @param {string} mode - either 'text' for a string (translation) or 'params' for the interpolated params\n   * @return {string|object}\n   */\n\n  /**\n   * @ngdoc property\n   * @name strategies\n   * @propertyOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Following strategies are built-in:\n   * <dl>\n   *   <dt>sanitize</dt>\n   *   <dd>Sanitizes HTML in the translation text using $sanitize</dd>\n   *   <dt>escape</dt>\n   *   <dd>Escapes HTML in the translation</dd>\n   *   <dt>sanitizeParameters</dt>\n   *   <dd>Sanitizes HTML in the values of the interpolation parameters using $sanitize</dd>\n   *   <dt>escapeParameters</dt>\n   *   <dd>Escapes HTML in the values of the interpolation parameters</dd>\n   *   <dt>escaped</dt>\n   *   <dd>Support legacy strategy name 'escaped' for backwards compatibility (will be removed in 3.0)</dd>\n   * </dl>\n   *\n   */\n\n  strategies = {\n    sanitize: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlSanitizeValue(value);\n      }\n      return value;\n    },\n    escape: function (value, mode/*, context*/) {\n      if (mode === 'text') {\n        value = htmlEscapeValue(value);\n      }\n      return value;\n    },\n    sanitizeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlSanitizeValue);\n      }\n      return value;\n    },\n    escapeParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlEscapeValue);\n      }\n      return value;\n    },\n    sce: function (value, mode, context) {\n      if (mode === 'text') {\n        value = htmlTrustValue(value);\n      } else if (mode === 'params') {\n        if (context !== 'filter') {\n          // do html escape in filter context #1101\n          value = mapInterpolationParameters(value, htmlEscapeValue);\n        }\n      }\n      return value;\n    },\n    sceParameters: function (value, mode/*, context*/) {\n      if (mode === 'params') {\n        value = mapInterpolationParameters(value, htmlTrustValue);\n      }\n      return value;\n    }\n  };\n  // Support legacy strategy name 'escaped' for backwards compatibility.\n  // TODO should be removed in 3.0\n  strategies.escaped = strategies.escapeParameters;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#addStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Adds a sanitization strategy to the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @param {StrategyFunction} strategyFunction - strategy function\n   * @returns {object} this\n   */\n  this.addStrategy = function (strategyName, strategyFunction) {\n    strategies[strategyName] = strategyFunction;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#removeStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Removes a sanitization strategy from the list of known strategies.\n   *\n   * @param {string} strategyName - unique key for a strategy\n   * @returns {object} this\n   */\n  this.removeStrategy = function (strategyName) {\n    delete strategies[strategyName];\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateSanitizationProvider#useStrategy\n   * @methodOf pascalprecht.translate.$translateSanitizationProvider\n   *\n   * @description\n   * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n   *\n   * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n   * @returns {object} this\n   */\n  this.useStrategy = function (strategy) {\n    hasConfiguredStrategy = true;\n    currentStrategy = strategy;\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translateSanitization\n   * @requires $injector\n   * @requires $log\n   *\n   * @description\n   * Sanitizes interpolation parameters and translated texts.\n   *\n   */\n  this.$get = ['$injector', '$log', function ($injector, $log) {\n\n    var cachedStrategyMap = {};\n\n    var applyStrategies = function (value, mode, context, selectedStrategies) {\n      angular.forEach(selectedStrategies, function (selectedStrategy) {\n        if (angular.isFunction(selectedStrategy)) {\n          value = selectedStrategy(value, mode, context);\n        } else if (angular.isFunction(strategies[selectedStrategy])) {\n          value = strategies[selectedStrategy](value, mode, context);\n        } else if (angular.isString(strategies[selectedStrategy])) {\n          if (!cachedStrategyMap[strategies[selectedStrategy]]) {\n            try {\n              cachedStrategyMap[strategies[selectedStrategy]] = $injector.get(strategies[selectedStrategy]);\n            } catch (e) {\n              cachedStrategyMap[strategies[selectedStrategy]] = function() {};\n              throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n            }\n          }\n          value = cachedStrategyMap[strategies[selectedStrategy]](value, mode, context);\n        } else {\n          throw new Error('pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: \\'' + selectedStrategy + '\\'');\n        }\n      });\n      return value;\n    };\n\n    // TODO: should be removed in 3.0\n    var showNoStrategyConfiguredWarning = function () {\n      if (!hasConfiguredStrategy && !hasShownNoStrategyConfiguredWarning) {\n        $log.warn('pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details.');\n        hasShownNoStrategyConfiguredWarning = true;\n      }\n    };\n\n    if ($injector.has('$sanitize')) {\n      $sanitize = $injector.get('$sanitize');\n    }\n    if ($injector.has('$sce')) {\n      $sce = $injector.get('$sce');\n    }\n\n    return {\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#useStrategy\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Selects a sanitization strategy. When an array is provided the strategies will be executed in order.\n       *\n       * @param {string|StrategyFunction|array} strategy The sanitization strategy / strategies which should be used. Either a name of an existing strategy, a custom strategy function, or an array consisting of multiple names and / or custom functions.\n       */\n      useStrategy: (function (self) {\n        return function (strategy) {\n          self.useStrategy(strategy);\n        };\n      })(this),\n\n      /**\n       * @ngdoc function\n       * @name pascalprecht.translate.$translateSanitization#sanitize\n       * @methodOf pascalprecht.translate.$translateSanitization\n       *\n       * @description\n       * Sanitizes a value.\n       *\n       * @param {string|object} value The value which should be sanitized.\n       * @param {string} mode The current sanitization mode, either 'params' or 'text'.\n       * @param {string|StrategyFunction|array} [strategy] Optional custom strategy which should be used instead of the currently selected strategy.\n       * @param {string} [context] The context of this call: filter, service. Default is service\n       * @returns {string|object} sanitized value\n       */\n      sanitize: function (value, mode, strategy, context) {\n        if (!currentStrategy) {\n          showNoStrategyConfiguredWarning();\n        }\n\n        if (!strategy && strategy !== null) {\n          strategy = currentStrategy;\n        }\n\n        if (!strategy) {\n          return value;\n        }\n\n        if (!context) {\n          context = 'service';\n        }\n\n        var selectedStrategies = angular.isArray(strategy) ? strategy : [strategy];\n        return applyStrategies(value, mode, context, selectedStrategies);\n      }\n    };\n  }];\n\n  var htmlEscapeValue = function (value) {\n    var element = angular.element('<div></div>');\n    element.text(value); // not chainable, see #1044\n    return element.html();\n  };\n\n  var htmlSanitizeValue = function (value) {\n    if (!$sanitize) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as \\'escape\\'.');\n    }\n    return $sanitize(value);\n  };\n\n  var htmlTrustValue = function (value) {\n    if (!$sce) {\n      throw new Error('pascalprecht.translate.$translateSanitization: Error cannot find $sce service.');\n    }\n    return $sce.trustAsHtml(value);\n  };\n\n  var mapInterpolationParameters = function (value, iteratee, stack) {\n    if (angular.isDate(value)) {\n      return value;\n    } else if (angular.isObject(value)) {\n      var result = angular.isArray(value) ? [] : {};\n\n      if (!stack) {\n        stack = [];\n      } else {\n        if (stack.indexOf(value) > -1) {\n          throw new Error('pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object');\n        }\n      }\n\n      stack.push(value);\n      angular.forEach(value, function (propertyValue, propertyKey) {\n\n        /* Skipping function properties. */\n        if (angular.isFunction(propertyValue)) {\n          return;\n        }\n\n        result[propertyKey] = mapInterpolationParameters(propertyValue, iteratee, stack);\n      });\n      stack.splice(-1, 1); // remove last\n\n      return result;\n    } else if (angular.isNumber(value)) {\n      return value;\n    } else if (value === true || value === false) {\n      return value;\n    } else if (!angular.isUndefined(value) && value !== null) {\n      return iteratee(value);\n    } else {\n      return value;\n    }\n  };\n}\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateProvider\n * @description\n *\n * $translateProvider allows developers to register translation-tables, asynchronous loaders\n * and similar to configure translation behavior directly inside of a module.\n *\n */\nangular.module('pascalprecht.translate')\n  .constant('pascalprechtTranslateOverrider', {})\n  .provider('$translate', $translate);\n\nfunction $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {\n\n  'use strict';\n\n  var $translationTable = {},\n    $preferredLanguage,\n    $availableLanguageKeys = [],\n    $languageKeyAliases,\n    $fallbackLanguage,\n    $fallbackWasString,\n    $uses,\n    $nextLang,\n    $storageFactory,\n    $storageKey = $STORAGE_KEY,\n    $storagePrefix,\n    $missingTranslationHandlerFactory,\n    $interpolationFactory,\n    $interpolatorFactories = [],\n    $loaderFactory,\n    $cloakClassName = 'translate-cloak',\n    $loaderOptions,\n    $notFoundIndicatorLeft,\n    $notFoundIndicatorRight,\n    $postCompilingEnabled = false,\n    $forceAsyncReloadEnabled = false,\n    $allowNamespaces = true,\n    $nestedObjectDelimeter = '.',\n    $isReady = false,\n    $keepContent = false,\n    loaderCache,\n    directivePriority = 0,\n    statefulFilter = true,\n    postProcessFn,\n    uniformLanguageTagResolver = 'default',\n    languageTagResolver = {\n      'default' : function (tag) {\n        return (tag || '').split('-').join('_');\n      },\n      java : function (tag) {\n        var temp = (tag || '').split('-').join('_');\n        var parts = temp.split('_');\n        return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;\n      },\n      bcp47 : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n\n        switch (parts.length) {\n          case 1: // language only\n            parts[0] = parts[0].toLowerCase();\n            break;\n          case 2: // language-script or language-region\n            parts[0] = parts[0].toLowerCase();\n            if (parts[1].length === 4) { // parts[1] is script\n              parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1).toLowerCase();\n            } else { // parts[1] is region\n              parts[1] = parts[1].toUpperCase();\n            }\n            break;\n          case 3: // language-script-region\n            parts[0] = parts[0].toLowerCase();\n            parts[1] = parts[1].charAt(0).toUpperCase() + parts[1].slice(1).toLowerCase();\n            parts[2] = parts[2].toUpperCase();\n            break;\n          default:\n            return temp;\n        }\n\n        return parts.join('-');\n      },\n      'iso639-1' : function (tag) {\n        var temp = (tag || '').split('_').join('-');\n        var parts = temp.split('-');\n        return parts[0].toLowerCase();\n      }\n    };\n\n  var version = '2.19.1';\n\n  // tries to determine the browsers language\n  var getFirstBrowserLanguage = function () {\n\n    // internal purpose only\n    if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {\n      return pascalprechtTranslateOverrider.getLocale();\n    }\n\n    var nav = $windowProvider.$get().navigator,\n      browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],\n      i,\n      language;\n\n    // support for HTML 5.1 \"navigator.languages\"\n    if (angular.isArray(nav.languages)) {\n      for (i = 0; i < nav.languages.length; i++) {\n        language = nav.languages[i];\n        if (language && language.length) {\n          return language;\n        }\n      }\n    }\n\n    // support for other well known properties in browsers\n    for (i = 0; i < browserLanguagePropertyKeys.length; i++) {\n      language = nav[browserLanguagePropertyKeys[i]];\n      if (language && language.length) {\n        return language;\n      }\n    }\n\n    return null;\n  };\n  getFirstBrowserLanguage.displayName = 'angular-translate/service: getFirstBrowserLanguage';\n\n  // tries to determine the browsers locale\n  var getLocale = function () {\n    var locale = getFirstBrowserLanguage() || '';\n    if (languageTagResolver[uniformLanguageTagResolver]) {\n      locale = languageTagResolver[uniformLanguageTagResolver](locale);\n    }\n    return locale;\n  };\n  getLocale.displayName = 'angular-translate/service: getLocale';\n\n  /**\n   * @name indexOf\n   * @private\n   *\n   * @description\n   * indexOf polyfill. Kinda sorta.\n   *\n   * @param {array} array Array to search in.\n   * @param {string} searchElement Element to search for.\n   *\n   * @returns {int} Index of search element.\n   */\n  var indexOf = function (array, searchElement) {\n    for (var i = 0, len = array.length; i < len; i++) {\n      if (array[i] === searchElement) {\n        return i;\n      }\n    }\n    return -1;\n  };\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function () {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  /**\n   * @name lowercase\n   * @private\n   *\n   * @description\n   * Return the lowercase string only if the type is string\n   *\n   * @returns {string} The string all in lowercase\n   */\n  var lowercase = function (string) {\n    return angular.isString(string) ? string.toLowerCase() : string;\n  };\n\n  var negotiateLocale = function (preferred) {\n    if (!preferred) {\n      return;\n    }\n\n    var avail = [],\n      locale = lowercase(preferred),\n      i = 0,\n      n = $availableLanguageKeys.length;\n\n    for (; i < n; i++) {\n      avail.push(lowercase($availableLanguageKeys[i]));\n    }\n\n    // Check for an exact match in our list of available keys\n    i = indexOf(avail, locale);\n    if (i > -1) {\n      return $availableLanguageKeys[i];\n    }\n\n    if ($languageKeyAliases) {\n      var alias;\n      for (var langKeyAlias in $languageKeyAliases) {\n        if ($languageKeyAliases.hasOwnProperty(langKeyAlias)) {\n          var hasWildcardKey = false;\n          var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) &&\n            lowercase(langKeyAlias) === lowercase(preferred);\n\n          if (langKeyAlias.slice(-1) === '*') {\n            hasWildcardKey = lowercase(langKeyAlias.slice(0, -1)) === lowercase(preferred.slice(0, langKeyAlias.length - 1));\n          }\n          if (hasExactKey || hasWildcardKey) {\n            alias = $languageKeyAliases[langKeyAlias];\n            if (indexOf(avail, lowercase(alias)) > -1) {\n              return alias;\n            }\n          }\n        }\n      }\n    }\n\n    // Check for a language code without region\n    var parts = preferred.split('_');\n\n    if (parts.length > 1 && indexOf(avail, lowercase(parts[0])) > -1) {\n      return parts[0];\n    }\n\n    // If everything fails, return undefined.\n    return;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translations\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a new translation table for specific language key.\n   *\n   * To register a translation table for specific language, pass a defined language\n   * key as first parameter.\n   *\n   * <pre>\n   *  // register translation table for language: 'de_DE'\n   *  $translateProvider.translations('de_DE', {\n   *    'GREETING': 'Hallo Welt!'\n   *  });\n   *\n   *  // register another one\n   *  $translateProvider.translations('en_US', {\n   *    'GREETING': 'Hello world!'\n   *  });\n   * </pre>\n   *\n   * When registering multiple translation tables for for the same language key,\n   * the actual translation table gets extended. This allows you to define module\n   * specific translation which only get added, once a specific module is loaded in\n   * your app.\n   *\n   * Invoking this method with no arguments returns the translation table which was\n   * registered with no language key. Invoking it with a language key returns the\n   * related translation table.\n   *\n   * @param {string} langKey A language key.\n   * @param {object} translationTable A plain old JavaScript object that represents a translation table.\n   *\n   */\n  var translations = function (langKey, translationTable) {\n\n    if (!langKey && !translationTable) {\n      return $translationTable;\n    }\n\n    if (langKey && !translationTable) {\n      if (angular.isString(langKey)) {\n        return $translationTable[langKey];\n      }\n    } else {\n      if (!angular.isObject($translationTable[langKey])) {\n        $translationTable[langKey] = {};\n      }\n      angular.extend($translationTable[langKey], flatObject(translationTable));\n    }\n    return this;\n  };\n\n  this.translations = translations;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#cloakClassName\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the class name for `translate-cloak` directive.\n   * Default class name is `translate-cloak`.\n   *\n   * @param {string} name translate-cloak class name\n   */\n  this.cloakClassName = function (name) {\n    if (!name) {\n      return $cloakClassName;\n    }\n    $cloakClassName = name;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#allowNamespaces\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Let's you disable namespaces, if you don't need nested translation\n   * object files. Disabling namespaces can improve performance.\n   *\n   * Default value is `true`. Namespaces are enabled by default.\n   *\n   * @param {boolean} namespacesEnabled - namespaces are enabled or not\n   */\n  this.allowNamespaces = function (namespacesEnabled) {\n    if (namespacesEnabled === undefined) {\n      return $allowNamespaces;\n    }\n    $allowNamespaces = namespacesEnabled;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#nestedObjectDelimeter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   *\n   * Let's you change the delimiter for namespaced translations.\n   * Default delimiter is `.`.\n   *\n   * @param {string} delimiter namespace separator\n   */\n  this.nestedObjectDelimeter = function (delimiter) {\n    if (!delimiter) {\n      return $nestedObjectDelimeter;\n    }\n    $nestedObjectDelimeter = delimiter;\n    return this;\n  };\n\n  /**\n   * @name flatObject\n   * @private\n   *\n   * @description\n   * Flats an object. This function is used to flatten given translation data with\n   * namespaces, so they are later accessible via dot notation.\n   */\n  var flatObject = function (data, path, result, prevKey) {\n    var key, keyWithPath, keyWithShortPath, val;\n\n    if (!path) {\n      path = [];\n    }\n    if (!result) {\n      result = {};\n    }\n    if (!$allowNamespaces) {\n      return data;\n    }\n    for (key in data) {\n      if (!Object.prototype.hasOwnProperty.call(data, key)) {\n        continue;\n      }\n      val = data[key];\n      if (angular.isObject(val)) {\n        flatObject(val, path.concat(key), result, key);\n      } else {\n        keyWithPath = path.length ? ('' + path.join($nestedObjectDelimeter) + $nestedObjectDelimeter + key) : key;\n        if (path.length && key === prevKey) {\n          // Create shortcut path (foo.bar == foo.bar.bar)\n          keyWithShortPath = '' + path.join($nestedObjectDelimeter);\n          // Link it to original path\n          result[keyWithShortPath] = '@:' + keyWithPath;\n        }\n        result[keyWithPath] = val;\n      }\n    }\n    return result;\n  };\n  flatObject.displayName = 'flatObject';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#addInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Adds interpolation services to angular-translate, so it can manage them.\n   *\n   * @param {object} factory Interpolation service factory\n   */\n  this.addInterpolation = function (factory) {\n    $interpolatorFactories.push(factory);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMessageFormatInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use interpolation functionality of messageformat.js.\n   * This is useful when having high level pluralization and gender selection.\n   */\n  this.useMessageFormatInterpolation = function () {\n    return this.useInterpolation('$translateMessageFormatInterpolation');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useInterpolation\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which interpolation style to use as default, application-wide.\n   * Simply pass a factory/service name. The interpolation service has to implement\n   * the correct interface.\n   *\n   * @param {string} factory Interpolation service name.\n   */\n  this.useInterpolation = function (factory) {\n    $interpolationFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useSanitizeStrategy\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Simply sets a sanitation strategy type.\n   *\n   * @param {string} value Strategy type.\n   */\n  this.useSanitizeValueStrategy = function (value) {\n    $translateSanitizationProvider.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#preferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use for translation\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **prefer**.\n   * It is recommended to call this after {@link pascalprecht.translate.$translate#fallbackLanguage fallbackLanguage()}.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.preferredLanguage = function (langKey) {\n    if (langKey) {\n      setupPreferredLanguage(langKey);\n      return this;\n    }\n    return $preferredLanguage;\n  };\n  var setupPreferredLanguage = function (langKey) {\n    if (langKey) {\n      $preferredLanguage = langKey;\n    }\n    return $preferredLanguage;\n  };\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicator\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found. E.g. when\n   * setting the indicator as 'X' and one tries to translate a translation id\n   * called `NOT_FOUND`, this will result in `X NOT_FOUND X`.\n   *\n   * Internally this methods sets a left indicator and a right indicator using\n   * `$translateProvider.translationNotFoundIndicatorLeft()` and\n   * `$translateProvider.translationNotFoundIndicatorRight()`.\n   *\n   * **Note**: These methods automatically add a whitespace between the indicators\n   * and the translation id.\n   *\n   * @param {string} indicator An indicator, could be any string.\n   */\n  this.translationNotFoundIndicator = function (indicator) {\n    this.translationNotFoundIndicatorLeft(indicator);\n    this.translationNotFoundIndicatorRight(indicator);\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found left to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorLeft = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorLeft;\n    }\n    $notFoundIndicatorLeft = indicator;\n    return this;\n  };\n\n  /**\n   * ngdoc function\n   * @name pascalprecht.translate.$translateProvider#translationNotFoundIndicatorLeft\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets an indicator which is used when a translation isn't found right to the\n   * translation id.\n   *\n   * @param {string} indicator An indicator.\n   */\n  this.translationNotFoundIndicatorRight = function (indicator) {\n    if (!indicator) {\n      return $notFoundIndicatorRight;\n    }\n    $notFoundIndicatorRight = indicator;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#fallbackLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which of the registered translation tables to use when missing translations\n   * at initial startup by passing a language key. Similar to `$translateProvider#use`\n   * only that it says which language to **fallback**.\n   *\n   * @param {string||array} langKey A language key.\n   *\n   */\n  this.fallbackLanguage = function (langKey) {\n    fallbackStack(langKey);\n    return this;\n  };\n\n  var fallbackStack = function (langKey) {\n    if (langKey) {\n      if (angular.isString(langKey)) {\n        $fallbackWasString = true;\n        $fallbackLanguage = [langKey];\n      } else if (angular.isArray(langKey)) {\n        $fallbackWasString = false;\n        $fallbackLanguage = langKey;\n      }\n      if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n        $fallbackLanguage.push($preferredLanguage);\n      }\n\n      return this;\n    } else {\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#use\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Set which translation table to use for translation by given language key. When\n   * trying to 'use' a language which isn't provided, it'll throw an error.\n   *\n   * You actually don't have to use this method since `$translateProvider#preferredLanguage`\n   * does the job too.\n   *\n   * @param {string} langKey A language key.\n   */\n  this.use = function (langKey) {\n    if (langKey) {\n      if (!$translationTable[langKey] && (!$loaderFactory)) {\n        // only throw an error, when not loading translation data asynchronously\n        throw new Error('$translateProvider couldn\\'t find translationTable for langKey: \\'' + langKey + '\\'');\n      }\n      $uses = langKey;\n      return this;\n    }\n    return $uses;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#resolveClientLocale\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n   *\n   * @returns {string} the current client/browser language key\n   */\n  this.resolveClientLocale = function () {\n    return getLocale();\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storageKey\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells the module which key must represent the choosed language by a user in the storage.\n   *\n   * @param {string} key A key for the storage.\n   */\n  var storageKey = function (key) {\n    if (!key) {\n      if ($storagePrefix) {\n        return $storagePrefix + $storageKey;\n      }\n      return $storageKey;\n    }\n    $storageKey = key;\n    return this;\n  };\n\n  this.storageKey = storageKey;\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useUrlLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateUrlLoader` extension service as loader.\n   *\n   * @param {string} url Url\n   * @param {Object=} options Optional configuration object\n   */\n  this.useUrlLoader = function (url, options) {\n    return this.useLoader('$translateUrlLoader', angular.extend({url : url}, options));\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.\n   *\n   * @param {Object=} options Optional configuration object\n   */\n  this.useStaticFilesLoader = function (options) {\n    return this.useLoader('$translateStaticFilesLoader', options);\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoader\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use any other service as loader.\n   *\n   * @param {string} loaderFactory Factory name to use\n   * @param {Object=} options Optional configuration object\n   */\n  this.useLoader = function (loaderFactory, options) {\n    $loaderFactory = loaderFactory;\n    $loaderOptions = options || {};\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLocalStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateLocalStorage` service as storage layer.\n   *\n   */\n  this.useLocalStorage = function () {\n    return this.useStorage('$translateLocalStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useCookieStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use `$translateCookieStorage` service as storage layer.\n   */\n  this.useCookieStorage = function () {\n    return this.useStorage('$translateCookieStorage');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useStorage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use custom service as storage layer.\n   */\n  this.useStorage = function (storageFactory) {\n    $storageFactory = storageFactory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#storagePrefix\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets prefix for storage key.\n   *\n   * @param {string} prefix Storage key prefix\n   */\n  this.storagePrefix = function (prefix) {\n    if (!prefix) {\n      return prefix;\n    }\n    $storagePrefix = prefix;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandlerLog\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to use built-in log handler when trying to translate\n   * a translation Id which doesn't exist.\n   *\n   * This is actually a shortcut method for `useMissingTranslationHandler()`.\n   *\n   */\n  this.useMissingTranslationHandlerLog = function () {\n    return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog');\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useMissingTranslationHandler\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Expects a factory name which later gets instantiated with `$injector`.\n   * This method can be used to tell angular-translate to use a custom\n   * missingTranslationHandler. Just build a factory which returns a function\n   * and expects a translation id as argument.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.useMissingTranslationHandler('customHandler');\n   *  });\n   *\n   *  app.factory('customHandler', function (dep1, dep2) {\n   *    return function (translationId) {\n   *      // something with translationId and dep1 and dep2\n   *    };\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.useMissingTranslationHandler = function (factory) {\n    $missingTranslationHandlerFactory = factory;\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#usePostCompiling\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If post compiling is enabled, all translated values will be processed\n   * again with AngularJS' $compile.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.usePostCompiling(true);\n   *  });\n   * </pre>\n   *\n   * @param {string} factory Factory name\n   */\n  this.usePostCompiling = function (value) {\n    $postCompilingEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#forceAsyncReload\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If force async reload is enabled, async loader will always be called\n   * even if $translationTable already contains the language key, adding\n   * possible new entries to the $translationTable.\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.forceAsyncReload(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.forceAsyncReload = function (value) {\n    $forceAsyncReloadEnabled = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#uniformLanguageTag\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate which language tag should be used as a result when determining\n   * the current browser language.\n   *\n   * This setting must be set before invoking {@link pascalprecht.translate.$translateProvider#methods_determinePreferredLanguage determinePreferredLanguage()}.\n   *\n   * <pre>\n   * $translateProvider\n   *   .uniformLanguageTag('bcp47')\n   *   .determinePreferredLanguage()\n   * </pre>\n   *\n   * The resolver currently supports:\n   * * default\n   *     (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_us\n   * * java\n   *     like default, but the second part will be always in uppercase\n   *     en-US => en_US\n   *     en_US => en_US\n   *     en-us => en_US\n   * * BCP 47 (RFC 4646 & 4647)\n   *     EN => en\n   *     en-US => en-US\n   *     en_US => en-US\n   *     en-us => en-US\n   *     sr-latn => sr-Latn\n   *     sr-latn-rs => sr-Latn-RS\n   *\n   * See also:\n   * * http://en.wikipedia.org/wiki/IETF_language_tag\n   * * http://www.w3.org/International/core/langtags/\n   * * http://tools.ietf.org/html/bcp47\n   *\n   * @param {string|object} options - options (or standard)\n   * @param {string} options.standard - valid values are 'default', 'bcp47', 'java'\n   */\n  this.uniformLanguageTag = function (options) {\n\n    if (!options) {\n      options = {};\n    } else if (angular.isString(options)) {\n      options = {\n        standard : options\n      };\n    }\n\n    uniformLanguageTagResolver = options.standard;\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#determinePreferredLanguage\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Tells angular-translate to try to determine on its own which language key\n   * to set as preferred language. When `fn` is given, angular-translate uses it\n   * to determine a language key, otherwise it uses the built-in `getLocale()`\n   * method.\n   *\n   * The `getLocale()` returns a language key in the format `[lang]_[country]` or\n   * `[lang]` depending on what the browser provides.\n   *\n   * Use this method at your own risk, since not all browsers return a valid\n   * locale (see {@link pascalprecht.translate.$translateProvider#methods_uniformLanguageTag uniformLanguageTag()}).\n   *\n   * @param {Function=} fn Function to determine a browser's locale\n   */\n  this.determinePreferredLanguage = function (fn) {\n\n    var locale = (fn && angular.isFunction(fn)) ? fn() : getLocale();\n\n    if (!$availableLanguageKeys.length) {\n      $preferredLanguage = locale;\n    } else {\n      $preferredLanguage = negotiateLocale(locale) || locale;\n    }\n\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#registerAvailableLanguageKeys\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a set of language keys the app will work with. Use this method in\n   * combination with\n   * {@link pascalprecht.translate.$translateProvider#determinePreferredLanguage determinePreferredLanguage}.\n   * When available languages keys are registered, angular-translate\n   * tries to find the best fitting language key depending on the browsers locale,\n   * considering your language key convention.\n   *\n   * @param {object} languageKeys Array of language keys the your app will use\n   * @param {object=} aliases Alias map.\n   */\n  this.registerAvailableLanguageKeys = function (languageKeys, aliases) {\n    if (languageKeys) {\n      $availableLanguageKeys = languageKeys;\n      if (aliases) {\n        $languageKeyAliases = aliases;\n      }\n      return this;\n    }\n    return $availableLanguageKeys;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#useLoaderCache\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Registers a cache for internal $http based loaders.\n   * {@link pascalprecht.translate.$translationCache $translationCache}.\n   * When false the cache will be disabled (default). When true or undefined\n   * the cache will be a default (see $cacheFactory). When an object it will\n   * be treat as a cache object itself: the usage is $http({cache: cache})\n   *\n   * @param {object} cache boolean, string or cache-object\n   */\n  this.useLoaderCache = function (cache) {\n    if (cache === false) {\n      // disable cache\n      loaderCache = undefined;\n    } else if (cache === true) {\n      // enable cache using AJS defaults\n      loaderCache = true;\n    } else if (typeof(cache) === 'undefined') {\n      // enable cache using default\n      loaderCache = '$translationCache';\n    } else if (cache) {\n      // enable cache using given one (see $cacheFactory)\n      loaderCache = cache;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#directivePriority\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Sets the default priority of the translate directive. The standard value is `0`.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {number} priority for the translate-directive\n   */\n  this.directivePriority = function (priority) {\n    if (priority === undefined) {\n      // getter\n      return directivePriority;\n    } else {\n      // setter with chaining\n      directivePriority = priority;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#statefulFilter\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * Since AngularJS 1.3, filters which are not stateless (depending at the scope)\n   * have to explicit define this behavior.\n   * Sets whether the translate filter should be stateful or stateless. The standard value is `true`\n   * meaning being stateful.\n   * Calling this function without an argument will return the current value.\n   *\n   * @param {boolean} state - defines the state of the filter\n   */\n  this.statefulFilter = function (state) {\n    if (state === undefined) {\n      // getter\n      return statefulFilter;\n    } else {\n      // setter with chaining\n      statefulFilter = state;\n      return this;\n    }\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#postProcess\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * The post processor will be intercept right after the translation result. It can modify the result.\n   *\n   * @param {object} fn Function or service name (string) to be called after the translation value has been set / resolved. The function itself will enrich every value being processed and then continue the normal resolver process\n   */\n  this.postProcess = function (fn) {\n    if (fn) {\n      postProcessFn = fn;\n    } else {\n      postProcessFn = undefined;\n    }\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateProvider#keepContent\n   * @methodOf pascalprecht.translate.$translateProvider\n   *\n   * @description\n   * If keepContent is set to true than translate directive will always use innerHTML\n   * as a default translation\n   *\n   * Example:\n   * <pre>\n   *  app.config(function ($translateProvider) {\n   *    $translateProvider.keepContent(true);\n   *  });\n   * </pre>\n   *\n   * @param {boolean} value - valid values are true or false\n   */\n  this.keepContent = function (value) {\n    $keepContent = !(!value);\n    return this;\n  };\n\n  /**\n   * @ngdoc object\n   * @name pascalprecht.translate.$translate\n   * @requires $interpolate\n   * @requires $log\n   * @requires $rootScope\n   * @requires $q\n   *\n   * @description\n   * The `$translate` service is the actual core of angular-translate. It expects a translation id\n   * and optional interpolate parameters to translate contents.\n   *\n   * <pre>\n   *  $translate('HEADLINE_TEXT').then(function (translation) {\n   *    $scope.translatedText = translation;\n   *  });\n   * </pre>\n   *\n   * @param {string|array} translationId A token which represents a translation id\n   *                                     This can be optionally an array of translation ids which\n   *                                     results that the function returns an object where each key\n   *                                     is the translation id and the value the translation.\n   * @param {object=} [interpolateParams={}] An object hash for dynamic values\n   * @param {string=} [interpolationId=undefined] The id of the interpolation to use (use default unless set via useInterpolation())\n   * @param {string=} [defaultTranslationText=undefined] the optional default translation text that is written as\n   *                                        as default text in case it is not found in any configured language\n   * @param {string=} [forceLanguage=false] A language to be used instead of the current language\n   * @param {string=} [sanitizeStrategy=undefined] force sanitize strategy for this call instead of using the configured one (use default unless set)\n   * @returns {object} promise\n   */\n  this.$get = ['$log', '$injector', '$rootScope', '$q', function ($log, $injector, $rootScope, $q) {\n\n    var Storage,\n      defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'),\n      pendingLoader = false,\n      interpolatorHashMap = {},\n      langPromises = {},\n      fallbackIndex,\n      startFallbackIteration;\n\n    var $translate = function (translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage, sanitizeStrategy) {\n      if (!$uses && $preferredLanguage) {\n        $uses = $preferredLanguage;\n      }\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        // Inspired by Q.allSettled by Kris Kowal\n        // https://github.com/kriskowal/q/blob/b0fa72980717dc202ffc3cbf03b936e10ebbb9d7/q.js#L1553-1563\n        // This transforms all promises regardless resolved or rejected\n        var translateAll = function (translationIds) {\n          var results = {}; // storing the actual results\n          var promises = []; // promises to wait for\n          // Wraps the promise a) being always resolved and b) storing the link id->value\n          var translate = function (translationId) {\n            var deferred = $q.defer();\n            var regardless = function (value) {\n              results[translationId] = value;\n              deferred.resolve([translationId, value]);\n            };\n            // we don't care whether the promise was resolved or rejected; just store the values\n            $translate(translationId, interpolateParams, interpolationId, defaultTranslationText, forceLanguage, sanitizeStrategy).then(regardless, regardless);\n            return deferred.promise;\n          };\n          for (var i = 0, c = translationIds.length; i < c; i++) {\n            promises.push(translate(translationIds[i]));\n          }\n          // wait for all (including storing to results)\n          return $q.all(promises).then(function () {\n            // return the results\n            return results;\n          });\n        };\n        return translateAll(translationId);\n      }\n\n      var deferred = $q.defer();\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      } else {\n        throw new TypeError('translationId must be a not empty string');\n      }\n\n      var promiseToWaitFor = (function () {\n        var promise = langPromises[uses] || langPromises[$preferredLanguage];\n\n        fallbackIndex = 0;\n\n        if ($storageFactory && !promise) {\n          // looks like there's no pending promise for $preferredLanguage or\n          // $uses. Maybe there's one pending for a language that comes from\n          // storage.\n          var langKey = Storage.get($storageKey);\n          promise = langPromises[langKey];\n\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            var index = indexOf($fallbackLanguage, langKey);\n            // maybe the language from storage is also defined as fallback language\n            // we increase the fallback language index to not search in that language\n            // as fallback, since it's probably the first used language\n            // in that case the index starts after the first element\n            fallbackIndex = (index === 0) ? 1 : 0;\n\n            // but we can make sure to ALWAYS fallback to preferred language at least\n            if (indexOf($fallbackLanguage, $preferredLanguage) < 0) {\n              $fallbackLanguage.push($preferredLanguage);\n            }\n          }\n        }\n        return promise;\n      }());\n\n      if (!promiseToWaitFor) {\n        // no promise to wait for? okay. Then there's no loader registered\n        // nor is a one pending for language that comes from storage.\n        // We can just translate.\n        determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n      } else {\n        var promiseResolved = function () {\n          // $uses may have changed while waiting\n          if (!forceLanguage) {\n            uses = $uses;\n          }\n          determineTranslation(translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n        };\n        promiseResolved.displayName = 'promiseResolved';\n\n        promiseToWaitFor['finally'](promiseResolved)['catch'](angular.noop); // we don't care about errors here, already handled\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name applyNotFoundIndicators\n     * @private\n     *\n     * @description\n     * Applies not fount indicators to given translation id, if needed.\n     * This function gets only executed, if a translation id doesn't exist,\n     * which is why a translation id is expected as argument.\n     *\n     * @param {string} translationId Translation id.\n     * @returns {string} Same as given translation id but applied with not found\n     * indicators.\n     */\n    var applyNotFoundIndicators = function (translationId) {\n      // applying notFoundIndicators\n      if ($notFoundIndicatorLeft) {\n        translationId = [$notFoundIndicatorLeft, translationId].join(' ');\n      }\n      if ($notFoundIndicatorRight) {\n        translationId = [translationId, $notFoundIndicatorRight].join(' ');\n      }\n      return translationId;\n    };\n\n    /**\n     * @name useLanguage\n     * @private\n     *\n     * @description\n     * Makes actual use of a language by setting a given language key as used\n     * language and informs registered interpolators to also use the given\n     * key as locale.\n     *\n     * @param {string} key Locale key.\n     */\n    var useLanguage = function (key) {\n      $uses = key;\n\n      // make sure to store new language key before triggering success event\n      if ($storageFactory) {\n        Storage.put($translate.storageKey(), $uses);\n      }\n\n      $rootScope.$emit('$translateChangeSuccess', {language : key});\n\n      // inform default interpolator\n      defaultInterpolator.setLocale($uses);\n\n      var eachInterpolator = function (interpolator, id) {\n        interpolatorHashMap[id].setLocale($uses);\n      };\n      eachInterpolator.displayName = 'eachInterpolatorLocaleSetter';\n\n      // inform all others too!\n      angular.forEach(interpolatorHashMap, eachInterpolator);\n      $rootScope.$emit('$translateChangeEnd', {language : key});\n    };\n\n    /**\n     * @name loadAsync\n     * @private\n     *\n     * @description\n     * Kicks off registered async loader using `$injector` and applies existing\n     * loader options. When resolved, it updates translation tables accordingly\n     * or rejects with given language key.\n     *\n     * @param {string} key Language key.\n     * @return {Promise} A promise.\n     */\n    var loadAsync = function (key) {\n      if (!key) {\n        throw 'No language key specified for loading.';\n      }\n\n      var deferred = $q.defer();\n\n      $rootScope.$emit('$translateLoadingStart', {language : key});\n      pendingLoader = true;\n\n      var cache = loaderCache;\n      if (typeof(cache) === 'string') {\n        // getting on-demand instance of loader\n        cache = $injector.get(cache);\n      }\n\n      var loaderOptions = angular.extend({}, $loaderOptions, {\n        key : key,\n        $http : angular.extend({}, {\n          cache : cache\n        }, $loaderOptions.$http)\n      });\n\n      var onLoaderSuccess = function (data) {\n        var translationTable = {};\n        $rootScope.$emit('$translateLoadingSuccess', {language : key});\n\n        if (angular.isArray(data)) {\n          angular.forEach(data, function (table) {\n            angular.extend(translationTable, flatObject(table));\n          });\n        } else {\n          angular.extend(translationTable, flatObject(data));\n        }\n        pendingLoader = false;\n        deferred.resolve({\n          key : key,\n          table : translationTable\n        });\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderSuccess.displayName = 'onLoaderSuccess';\n\n      var onLoaderError = function (key) {\n        $rootScope.$emit('$translateLoadingError', {language : key});\n        deferred.reject(key);\n        $rootScope.$emit('$translateLoadingEnd', {language : key});\n      };\n      onLoaderError.displayName = 'onLoaderError';\n\n      $injector.get($loaderFactory)(loaderOptions)\n        .then(onLoaderSuccess, onLoaderError);\n\n      return deferred.promise;\n    };\n\n    if ($storageFactory) {\n      Storage = $injector.get($storageFactory);\n\n      if (!Storage.get || !Storage.put) {\n        throw new Error('Couldn\\'t use storage \\'' + $storageFactory + '\\', missing get() or put() method!');\n      }\n    }\n\n    // if we have additional interpolations that were added via\n    // $translateProvider.addInterpolation(), we have to map'em\n    if ($interpolatorFactories.length) {\n      var eachInterpolationFactory = function (interpolatorFactory) {\n        var interpolator = $injector.get(interpolatorFactory);\n        // setting initial locale for each interpolation service\n        interpolator.setLocale($preferredLanguage || $uses);\n        // make'em recognizable through id\n        interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;\n      };\n      eachInterpolationFactory.displayName = 'interpolationFactoryAdder';\n\n      angular.forEach($interpolatorFactories, eachInterpolationFactory);\n    }\n\n    /**\n     * @name getTranslationTable\n     * @private\n     *\n     * @description\n     * Returns a promise that resolves to the translation table\n     * or is rejected if an error occurred.\n     *\n     * @param langKey\n     * @returns {Q.promise}\n     */\n    var getTranslationTable = function (langKey) {\n      var deferred = $q.defer();\n      if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) {\n        deferred.resolve($translationTable[langKey]);\n      } else if (langPromises[langKey]) {\n        var onResolve = function (data) {\n          translations(data.key, data.table);\n          deferred.resolve(data.table);\n        };\n        onResolve.displayName = 'translationTableResolver';\n        langPromises[langKey].then(onResolve, deferred.reject);\n      } else {\n        deferred.reject();\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslation\n     * @private\n     *\n     * @description\n     * Returns a promise that will resolve to the translation\n     * or be rejected if no translation was found for the language.\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {Q.promise}\n     */\n    var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      var onResolve = function (translationTable) {\n        if (Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n          Interpolator.setLocale(langKey);\n          var translation = translationTable[translationId];\n          if (translation.substr(0, 2) === '@:') {\n            getFallbackTranslation(langKey, translation.substr(2), interpolateParams, Interpolator, sanitizeStrategy)\n              .then(deferred.resolve, deferred.reject);\n          } else {\n            var interpolatedValue = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'service', sanitizeStrategy, translationId);\n            interpolatedValue = applyPostProcessing(translationId, translationTable[translationId], interpolatedValue, interpolateParams, langKey);\n\n            deferred.resolve(interpolatedValue);\n\n          }\n          Interpolator.setLocale($uses);\n        } else {\n          deferred.reject();\n        }\n      };\n      onResolve.displayName = 'fallbackTranslationResolver';\n\n      getTranslationTable(langKey).then(onResolve, deferred.reject);\n\n      return deferred.promise;\n    };\n\n    /**\n     * @name getFallbackTranslationInstant\n     * @private\n     *\n     * @description\n     * Returns a translation\n     * This function is currently only used for fallback language translation.\n     *\n     * @param langKey The language to translate to.\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns {string} translation\n     */\n    var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result, translationTable = $translationTable[langKey];\n\n      if (translationTable && Object.prototype.hasOwnProperty.call(translationTable, translationId) && translationTable[translationId] !== null) {\n        Interpolator.setLocale(langKey);\n        result = Interpolator.interpolate(translationTable[translationId], interpolateParams, 'filter', sanitizeStrategy, translationId);\n        result = applyPostProcessing(translationId, translationTable[translationId], result, interpolateParams, langKey, sanitizeStrategy);\n        // workaround for TrustedValueHolderType\n        if (!angular.isString(result) && angular.isFunction(result.$$unwrapTrustedValue)) {\n          var result2 = result.$$unwrapTrustedValue();\n          if (result2.substr(0, 2) === '@:') {\n            return getFallbackTranslationInstant(langKey, result2.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n          }\n        } else if (result.substr(0, 2) === '@:') {\n          return getFallbackTranslationInstant(langKey, result.substr(2), interpolateParams, Interpolator, sanitizeStrategy);\n        }\n        Interpolator.setLocale($uses);\n      }\n\n      return result;\n    };\n\n\n    /**\n     * @name translateByHandler\n     * @private\n     *\n     * Translate by missing translation handler.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param defaultTranslationText\n     * @param sanitizeStrategy sanitize strategy override\n     *\n     * @returns translation created by $missingTranslationHandler or translationId is $missingTranslationHandler is\n     * absent\n     */\n    var translateByHandler = function (translationId, interpolateParams, defaultTranslationText, sanitizeStrategy) {\n      // If we have a handler factory - we might also call it here to determine if it provides\n      // a default text for a translationid that can't be found anywhere in our tables\n      if ($missingTranslationHandlerFactory) {\n        return $injector.get($missingTranslationHandlerFactory)(translationId, $uses, interpolateParams, defaultTranslationText, sanitizeStrategy);\n      } else {\n        return translationId;\n      }\n    };\n\n    /**\n     * @name resolveForFallbackLanguage\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise that will resolve to the translation.\n     */\n    var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      var deferred = $q.defer();\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy).then(\n          function (data) {\n            deferred.resolve(data);\n          },\n          function () {\n            // Look in the next fallback language for a translation.\n            // It delays the resolving by passing another promise to resolve.\n            return resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy).then(deferred.resolve, deferred.reject);\n          }\n        );\n      } else {\n        // No translation found in any fallback language\n        // if a default translation text is set in the directive, then return this as a result\n        if (defaultTranslationText) {\n          deferred.resolve(defaultTranslationText);\n        } else {\n          var missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n\n          // if no default translation is set and an error handler is defined, send it to the handler\n          // and then return the result if it isn't undefined\n          if ($missingTranslationHandlerFactory && missingTranslationHandlerTranslation) {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @name resolveForFallbackLanguageInstant\n     * @private\n     *\n     * Recursive helper function for fallbackTranslation that will sequentially look\n     * for a translation in the fallbackLanguages starting with fallbackLanguageIndex.\n     *\n     * @param fallbackLanguageIndex\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {string} translation\n     */\n    var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      var result;\n\n      if (fallbackLanguageIndex < $fallbackLanguage.length) {\n        var langKey = $fallbackLanguage[fallbackLanguageIndex];\n        result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        if (!result && result !== '') {\n          result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator);\n        }\n      }\n      return result;\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param defaultTranslationText\n     * @param sanitizeStrategy\n     * @returns {Q.promise} Promise, that resolves to the translation.\n     */\n    var fallbackTranslation = function (translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguage((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy);\n    };\n\n    /**\n     * Translates with the usage of the fallback languages.\n     *\n     * @param translationId\n     * @param interpolateParams\n     * @param Interpolator\n     * @param sanitizeStrategy\n     * @returns {String} translation\n     */\n    var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator, sanitizeStrategy) {\n      // Start with the fallbackLanguage with index 0\n      return resolveForFallbackLanguageInstant((startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex), translationId, interpolateParams, Interpolator, sanitizeStrategy);\n    };\n\n    var determineTranslation = function (translationId, interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy) {\n\n      var deferred = $q.defer();\n\n      var table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = (interpolationId) ? interpolatorHashMap[interpolationId] : defaultInterpolator;\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n\n          $translate(translation.substr(2), interpolateParams, interpolationId, defaultTranslationText, uses, sanitizeStrategy)\n            .then(deferred.resolve, deferred.reject);\n        } else {\n          //\n          var resolvedTranslation = Interpolator.interpolate(translation, interpolateParams, 'service', sanitizeStrategy, translationId);\n          resolvedTranslation = applyPostProcessing(translationId, translation, resolvedTranslation, interpolateParams, uses);\n          deferred.resolve(resolvedTranslation);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, defaultTranslationText);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackTranslation(translationId, interpolateParams, Interpolator, defaultTranslationText, sanitizeStrategy)\n            .then(function (translation) {\n              deferred.resolve(translation);\n            }, function (_translationId) {\n              deferred.reject(applyNotFoundIndicators(_translationId));\n            });\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.resolve(missingTranslationHandlerTranslation);\n          }\n        } else {\n          if (defaultTranslationText) {\n            deferred.resolve(defaultTranslationText);\n          } else {\n            deferred.reject(applyNotFoundIndicators(translationId));\n          }\n        }\n      }\n      return deferred.promise;\n    };\n\n    var determineTranslationInstant = function (translationId, interpolateParams, interpolationId, uses, sanitizeStrategy) {\n\n      var result, table = uses ? $translationTable[uses] : $translationTable,\n        Interpolator = defaultInterpolator;\n\n      // if the interpolation id exists use custom interpolator\n      if (interpolatorHashMap && Object.prototype.hasOwnProperty.call(interpolatorHashMap, interpolationId)) {\n        Interpolator = interpolatorHashMap[interpolationId];\n      }\n\n      // if the translation id exists, we can just interpolate it\n      if (table && Object.prototype.hasOwnProperty.call(table, translationId) && table[translationId] !== null) {\n        var translation = table[translationId];\n\n        // If using link, rerun $translate with linked translationId and return it\n        if (translation.substr(0, 2) === '@:') {\n          result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId, uses, sanitizeStrategy);\n        } else {\n          result = Interpolator.interpolate(translation, interpolateParams, 'filter', sanitizeStrategy, translationId);\n          result = applyPostProcessing(translationId, translation, result, interpolateParams, uses, sanitizeStrategy);\n        }\n      } else {\n        var missingTranslationHandlerTranslation;\n        // for logging purposes only (as in $translateMissingTranslationHandlerLog), value is not returned to promise\n        if ($missingTranslationHandlerFactory && !pendingLoader) {\n          missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n        }\n\n        // since we couldn't translate the inital requested translation id,\n        // we try it now with one or more fallback languages, if fallback language(s) is\n        // configured.\n        if (uses && $fallbackLanguage && $fallbackLanguage.length) {\n          fallbackIndex = 0;\n          result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator, sanitizeStrategy);\n        } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          result = missingTranslationHandlerTranslation;\n        } else {\n          result = applyNotFoundIndicators(translationId);\n        }\n      }\n\n      return result;\n    };\n\n    var clearNextLangAndPromise = function (key) {\n      if ($nextLang === key) {\n        $nextLang = undefined;\n      }\n      langPromises[key] = undefined;\n    };\n\n    var applyPostProcessing = function (translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy) {\n      var fn = postProcessFn;\n\n      if (fn) {\n\n        if (typeof(fn) === 'string') {\n          // getting on-demand instance\n          fn = $injector.get(fn);\n        }\n        if (fn) {\n          return fn(translationId, translation, resolvedTranslation, interpolateParams, uses, sanitizeStrategy);\n        }\n      }\n\n      return resolvedTranslation;\n    };\n\n    var loadTranslationsIfMissing = function (key) {\n      if (!$translationTable[key] && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          return translation;\n        });\n      }\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#preferredLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the preferred language.\n     *\n     * @param {string} langKey language String or Array to be used as preferredLanguage (changing at runtime)\n     *\n     * @return {string} preferred language key\n     */\n    $translate.preferredLanguage = function (langKey) {\n      if (langKey) {\n        setupPreferredLanguage(langKey);\n      }\n      return $preferredLanguage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#cloakClassName\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured class name for `translate-cloak` directive.\n     *\n     * @return {string} cloakClassName\n     */\n    $translate.cloakClassName = function () {\n      return $cloakClassName;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#allowNamespaces\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns if namespaces are enabled\n     *\n     * @return {boolean} allowNamespaces value\n     */\n    $translate.allowNamespaces = function () {\n      return $allowNamespaces;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#nestedObjectDelimeter\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the configured delimiter for nested namespaces.\n     *\n     * @return {string} nestedObjectDelimeter\n     */\n    $translate.nestedObjectDelimeter = function () {\n      return $nestedObjectDelimeter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#fallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key for the fallback languages or sets a new fallback stack.\n     * It is recommended to call this before {@link pascalprecht.translate.$translateProvider#preferredLanguage preferredLanguage()}.\n     *\n     * @param {string=} langKey language String or Array of fallback languages to be used (to change stack at runtime)\n     *\n     * @return {string||array} fallback language key\n     */\n    $translate.fallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        fallbackStack(langKey);\n\n        // as we might have an async loader initiated and a new translation language might have been defined\n        // we need to add the promise to the stack also. So - iterate.\n        if ($loaderFactory) {\n          if ($fallbackLanguage && $fallbackLanguage.length) {\n            for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n              if (!langPromises[$fallbackLanguage[i]]) {\n                langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]);\n              }\n            }\n          }\n        }\n        $translate.use($translate.use());\n      }\n      if ($fallbackWasString) {\n        return $fallbackLanguage[0];\n      } else {\n        return $fallbackLanguage;\n      }\n\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#useFallbackLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Sets the first key of the fallback language stack to be used for translation.\n     * Therefore all languages in the fallback array BEFORE this key will be skipped!\n     *\n     * @param {string=} langKey Contains the langKey the iteration shall start with. Set to false if you want to\n     * get back to the whole stack\n     */\n    $translate.useFallbackLanguage = function (langKey) {\n      if (langKey !== undefined && langKey !== null) {\n        if (!langKey) {\n          startFallbackIteration = 0;\n        } else {\n          var langKeyPosition = indexOf($fallbackLanguage, langKey);\n          if (langKeyPosition > -1) {\n            startFallbackIteration = langKeyPosition;\n          }\n        }\n\n      }\n\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#proposedLanguage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the language key of language that is currently loaded asynchronously.\n     *\n     * @return {string} language key\n     */\n    $translate.proposedLanguage = function () {\n      return $nextLang;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storage\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns registered storage.\n     *\n     * @return {object} Storage\n     */\n    $translate.storage = function () {\n      return Storage;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#negotiateLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a language key based on available languages and language aliases. If a\n     * language key cannot be resolved, returns undefined.\n     *\n     * If no or a falsy key is given, returns undefined.\n     *\n     * @param {string} [key] Language key\n     * @return {string|undefined} Language key or undefined if no language key is found.\n     */\n    $translate.negotiateLocale = negotiateLocale;\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#use\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Tells angular-translate which language to use by given language key. This method is\n     * used to change language at runtime. It also takes care of storing the language\n     * key in a configured store to let your app remember the choosed language.\n     *\n     * When trying to 'use' a language which isn't available it tries to load it\n     * asynchronously with registered loaders.\n     *\n     * Returns promise object with loaded language file data or string of the currently used language.\n     *\n     * If no or a falsy key is given it returns the currently used language key.\n     * The returned string will be ```undefined``` if setting up $translate hasn't finished.\n     * @example\n     * $translate.use(\"en_US\").then(function(data){\n       *   $scope.text = $translate(\"HELLO\");\n       * });\n     *\n     * @param {string=} key Language key\n     * @return {object|string} Promise with loaded language data or the language key if a falsy param was given.\n     */\n    $translate.use = function (key) {\n      if (!key) {\n        return $uses;\n      }\n\n      var deferred = $q.defer();\n      deferred.promise.then(null, angular.noop); // AJS \"Possibly unhandled rejection\"\n\n      $rootScope.$emit('$translateChangeStart', {language : key});\n\n      // Try to get the aliased language key\n      var aliasedKey = negotiateLocale(key);\n      // Ensure only registered language keys will be loaded\n      if ($availableLanguageKeys.length > 0 && !aliasedKey) {\n        return $q.reject(key);\n      }\n\n      if (aliasedKey) {\n        key = aliasedKey;\n      }\n\n      // if there isn't a translation table for the language we've requested,\n      // we load it asynchronously\n      $nextLang = key;\n      if (($forceAsyncReloadEnabled || !$translationTable[key]) && $loaderFactory && !langPromises[key]) {\n        langPromises[key] = loadAsync(key).then(function (translation) {\n          translations(translation.key, translation.table);\n          deferred.resolve(translation.key);\n          if ($nextLang === key) {\n            useLanguage(translation.key);\n          }\n          return translation;\n        }, function (key) {\n          $rootScope.$emit('$translateChangeError', {language : key});\n          deferred.reject(key);\n          $rootScope.$emit('$translateChangeEnd', {language : key});\n          return $q.reject(key);\n        });\n        langPromises[key]['finally'](function () {\n          clearNextLangAndPromise(key);\n        })['catch'](angular.noop); // we don't care about errors (clearing)\n      } else if (langPromises[key]) {\n        // we are already loading this asynchronously\n        // resolve our new deferred when the old langPromise is resolved\n        langPromises[key].then(function (translation) {\n          if ($nextLang === translation.key) {\n            useLanguage(translation.key);\n          }\n          deferred.resolve(translation.key);\n          return translation;\n        }, function (key) {\n          // find first available fallback language if that request has failed\n          if (!$uses && $fallbackLanguage && $fallbackLanguage.length > 0 && $fallbackLanguage[0] !== key) {\n            return $translate.use($fallbackLanguage[0]).then(deferred.resolve, deferred.reject);\n          } else {\n            return deferred.reject(key);\n          }\n        });\n      } else {\n        deferred.resolve(key);\n        useLanguage(key);\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#resolveClientLocale\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This returns the current browser/client's language key. The result is processed with the configured uniform tag resolver.\n     *\n     * @returns {string} the current client/browser language key\n     */\n    $translate.resolveClientLocale = function () {\n      return getLocale();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#storageKey\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the key for the storage.\n     *\n     * @return {string} storage key\n     */\n    $translate.storageKey = function () {\n      return storageKey();\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isPostCompilingEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether post compiling is enabled or not\n     *\n     * @return {bool} storage key\n     */\n    $translate.isPostCompilingEnabled = function () {\n      return $postCompilingEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isForceAsyncReloadEnabled\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether force async reload is enabled or not\n     *\n     * @return {boolean} forceAsyncReload value\n     */\n    $translate.isForceAsyncReloadEnabled = function () {\n      return $forceAsyncReloadEnabled;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isKeepContent\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether keepContent or not\n     *\n     * @return {boolean} keepContent value\n     */\n    $translate.isKeepContent = function () {\n      return $keepContent;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#refresh\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Refreshes a translation table pointed by the given langKey. If langKey is not specified,\n     * the module will drop all existent translation tables and load new version of those which\n     * are currently in use.\n     *\n     * Refresh means that the module will drop target translation table and try to load it again.\n     *\n     * In case there are no loaders registered the refresh() method will throw an Error.\n     *\n     * If the module is able to refresh translation tables refresh() method will broadcast\n     * $translateRefreshStart and $translateRefreshEnd events.\n     *\n     * @example\n     * // this will drop all currently existent translation tables and reload those which are\n     * // currently in use\n     * $translate.refresh();\n     * // this will refresh a translation table for the en_US language\n     * $translate.refresh('en_US');\n     *\n     * @param {string} langKey A language key of the table, which has to be refreshed\n     *\n     * @return {promise} Promise, which will be resolved in case a translation tables refreshing\n     * process is finished successfully, and reject if not.\n     */\n    $translate.refresh = function (langKey) {\n      if (!$loaderFactory) {\n        throw new Error('Couldn\\'t refresh translation table, no loader registered!');\n      }\n\n      $rootScope.$emit('$translateRefreshStart', {language : langKey});\n\n      var deferred = $q.defer(), updatedLanguages = {};\n\n      //private helper\n      function loadNewData(languageKey) {\n        var promise = loadAsync(languageKey);\n        //update the load promise cache for this language\n        langPromises[languageKey] = promise;\n        //register a data handler for the promise\n        promise.then(function (data) {\n            //clear the cache for this language\n            $translationTable[languageKey] = {};\n            //add the new data for this language\n            translations(languageKey, data.table);\n            //track that we updated this language\n            updatedLanguages[languageKey] = true;\n          },\n          //handle rejection to appease the $q validation\n          angular.noop);\n        return promise;\n      }\n\n      //set up post-processing\n      deferred.promise.then(\n        function () {\n          for (var key in $translationTable) {\n            if ($translationTable.hasOwnProperty(key)) {\n              //delete cache entries that were not updated\n              if (!(key in updatedLanguages)) {\n                delete $translationTable[key];\n              }\n            }\n          }\n          if ($uses) {\n            useLanguage($uses);\n          }\n        },\n        //handle rejection to appease the $q validation\n        angular.noop\n      )['finally'](\n        function () {\n          $rootScope.$emit('$translateRefreshEnd', {language : langKey});\n        }\n      );\n\n      if (!langKey) {\n        // if there's no language key specified we refresh ALL THE THINGS!\n        var languagesToReload = $fallbackLanguage && $fallbackLanguage.slice() || [];\n        if ($uses && languagesToReload.indexOf($uses) === -1) {\n          languagesToReload.push($uses);\n        }\n        $q.all(languagesToReload.map(loadNewData)).then(deferred.resolve, deferred.reject);\n\n      } else if ($translationTable[langKey]) {\n        //just refresh the specified language cache\n        loadNewData(langKey).then(deferred.resolve, deferred.reject);\n\n      } else {\n        deferred.reject();\n      }\n\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#instant\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns a translation instantly from the internal state of loaded translation. All rules\n     * regarding the current language, the preferred language of even fallback languages will be\n     * used except any promise handling. If a language was not found, an asynchronous loading\n     * will be invoked in the background.\n     *\n     * @param {string|array} translationId A token which represents a translation id\n     *                                     This can be optionally an array of translation ids which\n     *                                     results that the function's promise returns an object where\n     *                                     each key is the translation id and the value the translation.\n     * @param {object=} [interpolateParams={}] Params\n     * @param {string=} [interpolationId=undefined] The id of the interpolation to use (use default unless set via useInterpolation())\n     * @param {string=} [forceLanguage=false] A language to be used instead of the current language\n     * @param {string=} [sanitizeStrategy=undefined] force sanitize strategy for this call instead of using the configured one (use default unless set)\n     *\n     * @return {string|object} translation\n     */\n    $translate.instant = function (translationId, interpolateParams, interpolationId, forceLanguage, sanitizeStrategy) {\n\n      // we don't want to re-negotiate $uses\n      var uses = (forceLanguage && forceLanguage !== $uses) ? // we don't want to re-negotiate $uses\n        (negotiateLocale(forceLanguage) || forceLanguage) : $uses;\n\n      // Detect undefined and null values to shorten the execution and prevent exceptions\n      if (translationId === null || angular.isUndefined(translationId)) {\n        return translationId;\n      }\n\n      // Check forceLanguage is present\n      if (forceLanguage) {\n        loadTranslationsIfMissing(forceLanguage);\n      }\n\n      // Duck detection: If the first argument is an array, a bunch of translations was requested.\n      // The result is an object.\n      if (angular.isArray(translationId)) {\n        var results = {};\n        for (var i = 0, c = translationId.length; i < c; i++) {\n          results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId, forceLanguage, sanitizeStrategy);\n        }\n        return results;\n      }\n\n      // We discarded unacceptable values. So we just need to verify if translationId is empty String\n      if (angular.isString(translationId) && translationId.length < 1) {\n        return translationId;\n      }\n\n      // trim off any whitespace\n      if (translationId) {\n        translationId = trim.apply(translationId);\n      }\n\n      var result, possibleLangKeys = [];\n      if ($preferredLanguage) {\n        possibleLangKeys.push($preferredLanguage);\n      }\n      if (uses) {\n        possibleLangKeys.push(uses);\n      }\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        possibleLangKeys = possibleLangKeys.concat($fallbackLanguage);\n      }\n      for (var j = 0, d = possibleLangKeys.length; j < d; j++) {\n        var possibleLangKey = possibleLangKeys[j];\n        if ($translationTable[possibleLangKey]) {\n          if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') {\n            result = determineTranslationInstant(translationId, interpolateParams, interpolationId, uses, sanitizeStrategy);\n          }\n        }\n        if (typeof result !== 'undefined') {\n          break;\n        }\n      }\n\n      if (!result && result !== '') {\n        if ($notFoundIndicatorLeft || $notFoundIndicatorRight) {\n          result = applyNotFoundIndicators(translationId);\n        } else {\n          // Return translation of default interpolator if not found anything.\n          result = defaultInterpolator.interpolate(translationId, interpolateParams, 'filter', sanitizeStrategy);\n\n          // looks like the requested translation id doesn't exists.\n          // Now, if there is a registered handler for missing translations and no\n          // asyncLoader is pending, we execute the handler\n          var missingTranslationHandlerTranslation;\n          if ($missingTranslationHandlerFactory && !pendingLoader) {\n            missingTranslationHandlerTranslation = translateByHandler(translationId, interpolateParams, sanitizeStrategy);\n          }\n\n          if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) {\n            result = missingTranslationHandlerTranslation;\n          }\n        }\n      }\n\n      return result;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#versionInfo\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the current version information for the angular-translate library\n     *\n     * @return {string} angular-translate version\n     */\n    $translate.versionInfo = function () {\n      return version;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#loaderCache\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns the defined loaderCache.\n     *\n     * @return {boolean|string|object} current value of loaderCache\n     */\n    $translate.loaderCache = function () {\n      return loaderCache;\n    };\n\n    // internal purpose only\n    $translate.directivePriority = function () {\n      return directivePriority;\n    };\n\n    // internal purpose only\n    $translate.statefulFilter = function () {\n      return statefulFilter;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#isReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns whether the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_onReady onReady()}.\n     *\n     * @return {boolean} current value of ready\n     */\n    $translate.isReady = function () {\n      return $isReady;\n    };\n\n    var $onReadyDeferred = $q.defer();\n    $onReadyDeferred.promise.then(function () {\n      $isReady = true;\n    });\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#onReady\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Calls the function provided or resolved the returned promise after the service is \"ready\" to translate (i.e. loading 1st language).\n     *\n     * See also {@link pascalprecht.translate.$translate#methods_isReady isReady()}.\n     *\n     * @param {Function=} fn Function to invoke when service is ready\n     * @return {object} Promise resolved when service is ready\n     */\n    $translate.onReady = function (fn) {\n      var deferred = $q.defer();\n      if (angular.isFunction(fn)) {\n        deferred.promise.then(fn);\n      }\n      if ($isReady) {\n        deferred.resolve();\n      } else {\n        $onReadyDeferred.promise.then(deferred.resolve);\n      }\n      return deferred.promise;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getAvailableLanguageKeys\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * This function simply returns the registered language keys being defined before in the config phase\n     * With this, an application can use the array to provide a language selection dropdown or similar\n     * without any additional effort\n     *\n     * @returns {object} returns the list of possibly registered language keys and mapping or null if not defined\n     */\n    $translate.getAvailableLanguageKeys = function () {\n      if ($availableLanguageKeys.length > 0) {\n        return $availableLanguageKeys;\n      }\n      return null;\n    };\n\n    /**\n     * @ngdoc function\n     * @name pascalprecht.translate.$translate#getTranslationTable\n     * @methodOf pascalprecht.translate.$translate\n     *\n     * @description\n     * Returns translation table by the given language key.\n     *\n     * Unless a language is provided it returns a translation table of the current one.\n     * Note: If translation dictionary is currently downloading or in progress\n     * it will return null.\n     *\n     * @param {string} langKey A token which represents a translation id\n     *\n     * @return {object} a copy of angular-translate $translationTable\n     */\n    $translate.getTranslationTable = function (langKey) {\n      langKey = langKey || $translate.use();\n      if (langKey && $translationTable[langKey]) {\n        return angular.copy($translationTable[langKey]);\n      }\n      return null;\n    };\n\n    // Whenever $translateReady is being fired, this will ensure the state of $isReady\n    var globalOnReadyListener = $rootScope.$on('$translateReady', function () {\n      $onReadyDeferred.resolve();\n      globalOnReadyListener(); // one time only\n      globalOnReadyListener = null;\n    });\n    var globalOnChangeListener = $rootScope.$on('$translateChangeEnd', function () {\n      $onReadyDeferred.resolve();\n      globalOnChangeListener(); // one time only\n      globalOnChangeListener = null;\n    });\n\n    if ($loaderFactory) {\n\n      // If at least one async loader is defined and there are no\n      // (default) translations available we should try to load them.\n      if (angular.equals($translationTable, {})) {\n        if ($translate.use()) {\n          $translate.use($translate.use());\n        }\n      }\n\n      // Also, if there are any fallback language registered, we start\n      // loading them asynchronously as soon as we can.\n      if ($fallbackLanguage && $fallbackLanguage.length) {\n        var processAsyncResult = function (translation) {\n          translations(translation.key, translation.table);\n          $rootScope.$emit('$translateChangeEnd', {language : translation.key});\n          return translation;\n        };\n        for (var i = 0, len = $fallbackLanguage.length; i < len; i++) {\n          var fallbackLanguageId = $fallbackLanguage[i];\n          if ($forceAsyncReloadEnabled || !$translationTable[fallbackLanguageId]) {\n            langPromises[fallbackLanguageId] = loadAsync(fallbackLanguageId).then(processAsyncResult);\n          }\n        }\n      }\n    } else {\n      $rootScope.$emit('$translateReady', {language : $translate.use()});\n    }\n\n    return $translate;\n  }];\n}\n\n$translate.displayName = 'displayName';\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translateDefaultInterpolation\n * @requires $interpolate\n *\n * @description\n * Uses angular's `$interpolate` services to interpolate strings against some values.\n *\n * Be aware to configure a proper sanitization strategy.\n *\n * See also:\n * * {@link pascalprecht.translate.$translateSanitization}\n *\n * @return {object} $translateDefaultInterpolation Interpolator service\n */\nangular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', $translateDefaultInterpolation);\n\nfunction $translateDefaultInterpolation ($interpolate, $translateSanitization) {\n\n  'use strict';\n\n  var $translateInterpolator = {},\n      $locale,\n      $identifier = 'default';\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#setLocale\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Sets current locale (this is currently not use in this interpolation).\n   *\n   * @param {string} locale Language key or locale.\n   */\n  $translateInterpolator.setLocale = function (locale) {\n    $locale = locale;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#getInterpolationIdentifier\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Returns an identifier for this interpolation service.\n   *\n   * @returns {string} $identifier\n   */\n  $translateInterpolator.getInterpolationIdentifier = function () {\n    return $identifier;\n  };\n\n  /**\n   * @deprecated will be removed in 3.0\n   * @see {@link pascalprecht.translate.$translateSanitization}\n   */\n  $translateInterpolator.useSanitizeValueStrategy = function (value) {\n    $translateSanitization.useStrategy(value);\n    return this;\n  };\n\n  /**\n   * @ngdoc function\n   * @name pascalprecht.translate.$translateDefaultInterpolation#interpolate\n   * @methodOf pascalprecht.translate.$translateDefaultInterpolation\n   *\n   * @description\n   * Interpolates given value agains given interpolate params using angulars\n   * `$interpolate` service.\n   *\n   * Since AngularJS 1.5, `value` must not be a string but can be anything input.\n   *\n   * @param {string} value translation\n   * @param {object} [interpolationParams={}] interpolation params\n   * @param {string} [context=undefined] current context (filter, directive, service)\n   * @param {string} [sanitizeStrategy=undefined] sanitize strategy (use default unless set)\n   * @param {string} translationId current translationId\n   *\n   * @returns {string} interpolated string\n   */\n  $translateInterpolator.interpolate = function (value, interpolationParams, context, sanitizeStrategy, translationId) { // jshint ignore:line\n    interpolationParams = interpolationParams || {};\n    interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy, context);\n\n    var interpolatedText;\n    if (angular.isNumber(value)) {\n      // numbers are safe\n      interpolatedText = '' + value;\n    } else if (angular.isString(value)) {\n      // strings must be interpolated (that's the job here)\n      interpolatedText = $interpolate(value)(interpolationParams);\n      interpolatedText = $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy, context);\n    } else {\n      // neither a number or a string, cant interpolate => empty string\n      interpolatedText = '';\n    }\n\n    return interpolatedText;\n  };\n\n  return $translateInterpolator;\n}\n\n$translateDefaultInterpolation.displayName = '$translateDefaultInterpolation';\n\nangular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY');\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate\n * @requires $interpolate,\n * @requires $compile,\n * @requires $parse,\n * @requires $rootScope\n * @restrict AE\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses $translate service to translate the translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate Translation id which could be either string or interpolated string.\n * @param {string=} translate-values Values to pass into translation id. Can be passed as object literal string or interpolated object.\n * @param {string=} translate-attr-ATTR translate Translation id and put it into ATTR attribute.\n * @param {string=} translate-default will be used unless translation was successful\n * @param {string=} translate-sanitize-strategy defines locally sanitize strategy\n * @param {boolean=} translate-compile (default true if present) defines locally activation of {@link pascalprecht.translate.$translateProvider#methods_usePostCompiling}\n * @param {boolean=} translate-keep-content (default true if present) defines that in case a KEY could not be translated, that the existing content is left in the innerHTML}\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre translate=\"TRANSLATION_ID\"></pre>\n        <pre translate>TRANSLATION_ID</pre>\n        <pre translate translate-attr-title=\"TRANSLATION_ID\"></pre>\n        <pre translate=\"{{translationId}}\"></pre>\n        <pre translate>{{translationId}}</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{value: 5}\"></pre>\n        <pre translate translate-values=\"{value: 5}\">WITH_VALUES</pre>\n        <pre translate=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate translate-values=\"{{values}}\">WITH_VALUES</pre>\n        <pre translate translate-attr-title=\"WITH_VALUES\" translate-values=\"{{values}}\"></pre>\n        <pre translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hi\"></pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n          'WITH_CAMEL_CASE_KEY': 'The interpolation key is camel cased: {{camelCaseKey}}'\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<p translate=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate=\"{{translationId}}\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>TRANSLATION_ID</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate>{{translationId}}</p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('Hello there!');\n\n          element = $compile('<p translate translate-attr-title=\"TRANSLATION_ID\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('title')).toBe('Hello there!');\n\n          element = $compile('<p translate=\"WITH_CAMEL_CASE_KEY\" translate-value-camel-case-key=\"Hello\"></p>')($rootScope);\n          $rootScope.$digest();\n          expect(element.text()).toBe('The interpolation key is camel cased: Hello');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translate', translateDirective);\nfunction translateDirective($translate, $interpolate, $compile, $parse, $rootScope) {\n\n  'use strict';\n\n  /**\n   * @name trim\n   * @private\n   *\n   * @description\n   * trim polyfill\n   *\n   * @returns {string} The string stripped of whitespace from both ends\n   */\n  var trim = function() {\n    return this.toString().replace(/^\\s+|\\s+$/g, '');\n  };\n\n  /**\n   * @name lowercase\n   * @private\n   *\n   * @description\n   * Return the lowercase string only if the type is string\n   *\n   * @returns {string} The string all in lowercase\n   */\n  var lowercase = function (string) {\n    return angular.isString(string) ? string.toLowerCase() : string;\n  };\n\n  return {\n    restrict: 'AE',\n    scope: true,\n    priority: $translate.directivePriority(),\n    compile: function (tElement, tAttr) {\n\n      var translateValuesExist = (tAttr.translateValues) ?\n        tAttr.translateValues : undefined;\n\n      var translateInterpolation = (tAttr.translateInterpolation) ?\n        tAttr.translateInterpolation : undefined;\n\n      var translateSanitizeStrategyExist = (tAttr.translateSanitizeStrategy) ?\n        tAttr.translateSanitizeStrategy : undefined;\n\n      var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i);\n\n      var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)',\n          watcherRegExp = '^(.*)' + $interpolate.startSymbol() + '(.*)' + $interpolate.endSymbol() + '(.*)';\n\n      return function linkFn(scope, iElement, iAttr) {\n\n        scope.interpolateParams = {};\n        scope.preText = '';\n        scope.postText = '';\n        scope.translateNamespace = getTranslateNamespace(scope);\n        var translationIds = {};\n\n        var initInterpolationParams = function (interpolateParams, iAttr, tAttr) {\n          // initial setup\n          if (iAttr.translateValues) {\n            angular.extend(interpolateParams, $parse(iAttr.translateValues)(scope.$parent));\n          }\n          // initially fetch all attributes if existing and fill the params\n          if (translateValueExist) {\n            for (var attr in tAttr) {\n              if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n                var attributeName = lowercase(attr.substr(14, 1)) + attr.substr(15);\n                interpolateParams[attributeName] = tAttr[attr];\n              }\n            }\n          }\n        };\n\n        // Ensures any change of the attribute \"translate\" containing the id will\n        // be re-stored to the scope's \"translationId\".\n        // If the attribute has no content, the element's text value (white spaces trimmed off) will be used.\n        var observeElementTranslation = function (translationId) {\n\n          // Remove any old watcher\n          if (angular.isFunction(observeElementTranslation._unwatchOld)) {\n            observeElementTranslation._unwatchOld();\n            observeElementTranslation._unwatchOld = undefined;\n          }\n\n          if (angular.equals(translationId , '') || !angular.isDefined(translationId)) {\n            var iElementText = trim.apply(iElement.text()).replace(/\\n/g, ' ');\n\n            // Resolve translation id by inner html if required\n            var interpolateMatches = iElementText.match(interpolateRegExp);\n            // Interpolate translation id if required\n            if (angular.isArray(interpolateMatches)) {\n              scope.preText = interpolateMatches[1];\n              scope.postText = interpolateMatches[3];\n              translationIds.translate = $interpolate(interpolateMatches[2])(scope.$parent);\n              var watcherMatches = iElementText.match(watcherRegExp);\n              if (angular.isArray(watcherMatches) && watcherMatches[2] && watcherMatches[2].length) {\n                observeElementTranslation._unwatchOld = scope.$watch(watcherMatches[2], function (newValue) {\n                  translationIds.translate = newValue;\n                  updateTranslations();\n                });\n              }\n            } else {\n              // do not assigne the translation id if it is empty.\n              translationIds.translate = !iElementText ? undefined : iElementText;\n            }\n          } else {\n            translationIds.translate = translationId;\n          }\n          updateTranslations();\n        };\n\n        var observeAttributeTranslation = function (translateAttr) {\n          iAttr.$observe(translateAttr, function (translationId) {\n            translationIds[translateAttr] = translationId;\n            updateTranslations();\n          });\n        };\n\n        // initial setup with values\n        initInterpolationParams(scope.interpolateParams, iAttr, tAttr);\n\n        var firstAttributeChangedEvent = true;\n        iAttr.$observe('translate', function (translationId) {\n          if (typeof translationId === 'undefined') {\n            // case of element \"<translate>xyz</translate>\"\n            observeElementTranslation('');\n          } else {\n            // case of regular attribute\n            if (translationId !== '' || !firstAttributeChangedEvent) {\n              translationIds.translate = translationId;\n              updateTranslations();\n            }\n          }\n          firstAttributeChangedEvent = false;\n        });\n\n        for (var translateAttr in iAttr) {\n          if (iAttr.hasOwnProperty(translateAttr) && translateAttr.substr(0, 13) === 'translateAttr' && translateAttr.length > 13) {\n            observeAttributeTranslation(translateAttr);\n          }\n        }\n\n        iAttr.$observe('translateDefault', function (value) {\n          scope.defaultText = value;\n          updateTranslations();\n        });\n\n        if (translateSanitizeStrategyExist) {\n          iAttr.$observe('translateSanitizeStrategy', function (value) {\n            scope.sanitizeStrategy = $parse(value)(scope.$parent);\n            updateTranslations();\n          });\n        }\n\n        if (translateValuesExist) {\n          iAttr.$observe('translateValues', function (interpolateParams) {\n            if (interpolateParams) {\n              scope.$parent.$watch(function () {\n                angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent));\n              });\n            }\n          });\n        }\n\n        if (translateValueExist) {\n          var observeValueAttribute = function (attrName) {\n            iAttr.$observe(attrName, function (value) {\n              var attributeName = lowercase(attrName.substr(14, 1)) + attrName.substr(15);\n              scope.interpolateParams[attributeName] = value;\n            });\n          };\n          for (var attr in iAttr) {\n            if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') {\n              observeValueAttribute(attr);\n            }\n          }\n        }\n\n        // Master update function\n        var updateTranslations = function () {\n          for (var key in translationIds) {\n            if (translationIds.hasOwnProperty(key) && translationIds[key] !== undefined) {\n              updateTranslation(key, translationIds[key], scope, scope.interpolateParams, scope.defaultText, scope.translateNamespace);\n            }\n          }\n        };\n\n        // Put translation processing function outside loop\n        var updateTranslation = function(translateAttr, translationId, scope, interpolateParams, defaultTranslationText, translateNamespace) {\n          if (translationId) {\n            // if translation id starts with '.' and translateNamespace given, prepend namespace\n            if (translateNamespace && translationId.charAt(0) === '.') {\n              translationId = translateNamespace + translationId;\n            }\n\n            $translate(translationId, interpolateParams, translateInterpolation, defaultTranslationText, scope.translateLanguage, scope.sanitizeStrategy)\n              .then(function (translation) {\n                applyTranslation(translation, scope, true, translateAttr);\n              }, function (translationId) {\n                applyTranslation(translationId, scope, false, translateAttr);\n              });\n          } else {\n            // as an empty string cannot be translated, we can solve this using successful=false\n            applyTranslation(translationId, scope, false, translateAttr);\n          }\n        };\n\n        var applyTranslation = function (value, scope, successful, translateAttr) {\n          if (!successful) {\n            if (typeof scope.defaultText !== 'undefined') {\n              value = scope.defaultText;\n            }\n          }\n          if (translateAttr === 'translate') {\n            // default translate into innerHTML\n            if (successful || (!successful && !$translate.isKeepContent() && typeof iAttr.translateKeepContent === 'undefined')) {\n              iElement.empty().append(scope.preText + value + scope.postText);\n            }\n            var globallyEnabled = $translate.isPostCompilingEnabled();\n            var locallyDefined = typeof tAttr.translateCompile !== 'undefined';\n            var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false';\n            if ((globallyEnabled && !locallyDefined) || locallyEnabled) {\n              $compile(iElement.contents())(scope);\n            }\n          } else {\n            // translate attribute\n            var attributeName = iAttr.$attr[translateAttr];\n            if (attributeName.substr(0, 5) === 'data-') {\n              // ensure html5 data prefix is stripped\n              attributeName = attributeName.substr(5);\n            }\n            attributeName = attributeName.substr(15);\n            iElement.attr(attributeName, value);\n          }\n        };\n\n        if (translateValuesExist || translateValueExist || iAttr.translateDefault) {\n          scope.$watch('interpolateParams', updateTranslations, true);\n        }\n\n        // Replaced watcher on translateLanguage with event listener\n        scope.$on('translateLanguageChanged', updateTranslations);\n\n        // Ensures the text will be refreshed after the current language was changed\n        // w/ $translate.use(...)\n        var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n        // ensure translation will be looked up at least one\n        if (iElement.text().length) {\n          if (iAttr.translate) {\n            observeElementTranslation(iAttr.translate);\n          } else {\n            observeElementTranslation('');\n          }\n        } else if (iAttr.translate) {\n          // ensure attribute will be not skipped\n          observeElementTranslation(iAttr.translate);\n        }\n        updateTranslations();\n        scope.$on('$destroy', unbind);\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateDirective.displayName = 'translateDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translate-attr\n * @restrict A\n *\n * @description\n * Translates attributes like translate-attr-ATTR, but with an object like ng-class.\n * Internally it uses `translate` service to translate translation id. It possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate-attr Object literal mapping attributes to translation ids.\n * @param {string=} translate-values Values to pass into the translation ids. Can be passed as object literal string.\n * @param {string=} translate-sanitize-strategy defines locally sanitize strategy\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{value: 5}\" />\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}',\n        }).preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n    <file name=\"scenario.js\">\n      it('should translate', function () {\n        inject(function ($rootScope, $compile) {\n          $rootScope.translationId = 'TRANSLATION_ID';\n\n          element = $compile('<input translate-attr=\"{ placeholder: translationId, title: 'WITH_VALUES' }\" translate-values=\"{ value: 5 }\" />')($rootScope);\n          $rootScope.$digest();\n          expect(element.attr('placeholder)).toBe('Hello there!');\n          expect(element.attr('title)).toBe('The following value is dynamic: 5');\n        });\n      });\n    </file>\n   </example>\n */\n.directive('translateAttr', translateAttrDirective);\nfunction translateAttrDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    priority: $translate.directivePriority(),\n    link: function linkFn(scope, element, attr) {\n\n      var translateAttr,\n          translateValues,\n          translateSanitizeStrategy,\n          previousAttributes = {};\n\n      // Main update translations function\n      var updateTranslations = function () {\n        angular.forEach(translateAttr, function (translationId, attributeName) {\n          if (!translationId) {\n            return;\n          }\n          previousAttributes[attributeName] = true;\n\n          // if translation id starts with '.' and translateNamespace given, prepend namespace\n          if (scope.translateNamespace && translationId.charAt(0) === '.') {\n            translationId = scope.translateNamespace + translationId;\n          }\n          $translate(translationId, translateValues, attr.translateInterpolation, undefined, scope.translateLanguage, translateSanitizeStrategy)\n            .then(function (translation) {\n              element.attr(attributeName, translation);\n            }, function (translationId) {\n              element.attr(attributeName, translationId);\n            });\n        });\n\n        // Removing unused attributes that were previously used\n        angular.forEach(previousAttributes, function (flag, attributeName) {\n          if (!translateAttr[attributeName]) {\n            element.removeAttr(attributeName);\n            delete previousAttributes[attributeName];\n          }\n        });\n      };\n\n      // Watch for attribute changes\n      watchAttribute(\n        scope,\n        attr.translateAttr,\n        function (newValue) { translateAttr = newValue; },\n        updateTranslations\n      );\n      // Watch for value changes\n      watchAttribute(\n        scope,\n        attr.translateValues,\n        function (newValue) { translateValues = newValue; },\n        updateTranslations\n      );\n      // Watch for sanitize strategy changes\n      watchAttribute(\n        scope,\n        attr.translateSanitizeStrategy,\n        function (newValue) { translateSanitizeStrategy = newValue; },\n        updateTranslations\n      );\n\n      if (attr.translateValues) {\n        scope.$watch(attr.translateValues, updateTranslations, true);\n      }\n\n      // Replaced watcher on translateLanguage with event listener\n      scope.$on('translateLanguageChanged', updateTranslations);\n\n      // Ensures the text will be refreshed after the current language was changed\n      // w/ $translate.use(...)\n      var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslations);\n\n      updateTranslations();\n      scope.$on('$destroy', unbind);\n    }\n  };\n}\n\nfunction watchAttribute(scope, attribute, valueCallback, changeCallback) {\n  'use strict';\n  if (!attribute) {\n    return;\n  }\n  if (attribute.substr(0, 2) === '::') {\n    attribute = attribute.substr(2);\n  } else {\n    scope.$watch(attribute, function(newValue) {\n      valueCallback(newValue);\n      changeCallback();\n    }, true);\n  }\n  valueCallback(scope.$eval(attribute));\n}\n\ntranslateAttrDirective.displayName = 'translateAttrDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateCloak\n * @requires $translate\n * @restrict A\n *\n * $description\n * Adds a `translate-cloak` class name to the given element where this directive\n * is applied initially and removes it, once a loader has finished loading.\n *\n * This directive can be used to prevent initial flickering when loading translation\n * data asynchronously.\n *\n * The class name is defined in\n * {@link pascalprecht.translate.$translateProvider#cloakClassName $translate.cloakClassName()}.\n *\n * @param {string=} translate-cloak If a translationId is provided, it will be used for showing\n *                                  or hiding the cloak. Basically it relies on the translation\n *                                  resolve.\n */\n.directive('translateCloak', translateCloakDirective);\n\nfunction translateCloakDirective($translate, $rootScope) {\n\n  'use strict';\n\n  return {\n    compile : function (tElement) {\n      var applyCloak = function (element) {\n          element.addClass($translate.cloakClassName());\n        },\n        removeCloak = function (element) {\n          element.removeClass($translate.cloakClassName());\n        };\n      applyCloak(tElement);\n\n      return function linkFn(scope, iElement, iAttr) {\n        //Create bound functions that incorporate the active DOM element.\n        var iRemoveCloak = removeCloak.bind(this, iElement), iApplyCloak = applyCloak.bind(this, iElement);\n        if (iAttr.translateCloak && iAttr.translateCloak.length) {\n          // Register a watcher for the defined translation allowing a fine tuned cloak\n          iAttr.$observe('translateCloak', function (translationId) {\n            $translate(translationId).then(iRemoveCloak, iApplyCloak);\n          });\n          $rootScope.$on('$translateChangeSuccess', function () {\n            $translate(iAttr.translateCloak).then(iRemoveCloak, iApplyCloak);\n          });\n        } else {\n          $translate.onReady(iRemoveCloak);\n        }\n      };\n    }\n  };\n}\n\ntranslateCloakDirective.displayName = 'translateCloakDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateNamespace\n * @restrict A\n *\n * @description\n * Translates given translation id either through attribute or DOM content.\n * Internally it uses `translate` filter to translate translation id. It is possible to\n * pass an optional `translate-values` object literal as string into translation id.\n *\n * @param {string=} translate namespace name which could be either string or interpolated string.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div translate-namespace=\"CONTENT\">\n\n        <div>\n            <h1 translate>.HEADERS.TITLE</h1>\n            <h1 translate>.HEADERS.WELCOME</h1>\n        </div>\n\n        <div translate-namespace=\".HEADERS\">\n            <h1 translate>.TITLE</h1>\n            <h1 translate>.WELCOME</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en',{\n          'TRANSLATION_ID': 'Hello there!',\n          'CONTENT': {\n            'HEADERS': {\n                TITLE: 'Title'\n            }\n          },\n          'CONTENT.HEADERS.WELCOME': 'Welcome'\n        }).preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateNamespace', translateNamespaceDirective);\n\nfunction translateNamespaceDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return {\n        pre: function (scope, iElement, iAttrs) {\n          scope.translateNamespace = _getTranslateNamespace(scope);\n\n          if (scope.translateNamespace && iAttrs.translateNamespace.charAt(0) === '.') {\n            scope.translateNamespace += iAttrs.translateNamespace;\n          } else {\n            scope.translateNamespace = iAttrs.translateNamespace;\n          }\n        }\n      };\n    }\n  };\n}\n\n/**\n * Returns the scope's namespace.\n * @private\n * @param scope\n * @returns {string}\n */\nfunction _getTranslateNamespace(scope) {\n  'use strict';\n  if (scope.translateNamespace) {\n    return scope.translateNamespace;\n  }\n  if (scope.$parent) {\n    return _getTranslateNamespace(scope.$parent);\n  }\n}\n\ntranslateNamespaceDirective.displayName = 'translateNamespaceDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc directive\n * @name pascalprecht.translate.directive:translateLanguage\n * @restrict A\n *\n * @description\n * Forces the language to the directives in the underlying scope.\n *\n * @param {string=} translate language that will be negotiated.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div>\n\n        <div>\n            <h1 translate>HELLO</h1>\n        </div>\n\n        <div translate-language=\"de\">\n            <h1 translate>HELLO</h1>\n        </div>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider\n          .translations('en',{\n            'HELLO': 'Hello world!'\n          })\n          .translations('de',{\n            'HELLO': 'Hallo Welt!'\n          })\n          .preferredLanguage('en');\n\n      });\n\n    </file>\n   </example>\n */\n.directive('translateLanguage', translateLanguageDirective);\n\nfunction translateLanguageDirective() {\n\n  'use strict';\n\n  return {\n    restrict: 'A',\n    scope: true,\n    compile: function () {\n      return function linkFn(scope, iElement, iAttrs) {\n\n        iAttrs.$observe('translateLanguage', function (newTranslateLanguage) {\n          scope.translateLanguage = newTranslateLanguage;\n        });\n\n        scope.$watch('translateLanguage', function(){\n          scope.$broadcast('translateLanguageChanged');\n        });\n      };\n    }\n  };\n}\n\ntranslateLanguageDirective.displayName = 'translateLanguageDirective';\n\nangular.module('pascalprecht.translate')\n/**\n * @ngdoc filter\n * @name pascalprecht.translate.filter:translate\n * @requires $parse\n * @requires pascalprecht.translate.$translate\n * @function\n *\n * @description\n * Uses `$translate` service to translate contents. Accepts interpolate parameters\n * to pass dynamized values though translation.\n *\n * @param {string} translationId A translation id to be translated.\n * @param {*=} interpolateParams Optional object literal (as hash or string) to pass values into translation.\n *\n * @returns {string} Translated text.\n *\n * @example\n   <example module=\"ngView\">\n    <file name=\"index.html\">\n      <div ng-controller=\"TranslateCtrl\">\n\n        <pre>{{ 'TRANSLATION_ID' | translate }}</pre>\n        <pre>{{ translationId | translate }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:'{value: 5}' }}</pre>\n        <pre>{{ 'WITH_VALUES' | translate:values }}</pre>\n\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('ngView', ['pascalprecht.translate'])\n\n      .config(function ($translateProvider) {\n\n        $translateProvider.translations('en', {\n          'TRANSLATION_ID': 'Hello there!',\n          'WITH_VALUES': 'The following value is dynamic: {{value}}'\n        });\n        $translateProvider.preferredLanguage('en');\n\n      });\n\n      angular.module('ngView').controller('TranslateCtrl', function ($scope) {\n        $scope.translationId = 'TRANSLATION_ID';\n\n        $scope.values = {\n          value: 78\n        };\n      });\n    </file>\n   </example>\n */\n.filter('translate', translateFilterFactory);\n\nfunction translateFilterFactory($parse, $translate) {\n\n  'use strict';\n\n  var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {\n    if (!angular.isObject(interpolateParams)) {\n      var ctx = this || {\n        '__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'\n        };\n      interpolateParams = $parse(interpolateParams)(ctx);\n    }\n\n    return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);\n  };\n\n  if ($translate.statefulFilter()) {\n    translateFilter.$stateful = true;\n  }\n\n  return translateFilter;\n}\n\ntranslateFilterFactory.displayName = 'translateFilterFactory';\n\nangular.module('pascalprecht.translate')\n\n/**\n * @ngdoc object\n * @name pascalprecht.translate.$translationCache\n * @requires $cacheFactory\n *\n * @description\n * The first time a translation table is used, it is loaded in the translation cache for quick retrieval. You\n * can load translation tables directly into the cache by consuming the\n * `$translationCache` service directly.\n *\n * @return {object} $cacheFactory object.\n */\n  .factory('$translationCache', $translationCache);\n\nfunction $translationCache($cacheFactory) {\n\n  'use strict';\n\n  return $cacheFactory('translations');\n}\n\n$translationCache.displayName = '$translationCache';\nreturn 'pascalprecht.translate';\n\n}));\n","import {\r\n  AbsencePeriodsController,\r\n  AccountantController,\r\n  AccountingChannelSettingsController,\r\n  AccountAuthorizationController,\r\n  AccountingHolidayPayDebtReportQueryController,\r\n  AccountingReportCrudController,\r\n  AccountingReportDisplayController,\r\n  AccountingReportQueryController,\r\n  AccountingReportRowsController,\r\n  AccountingReportToolsController,\r\n  AccountingRowReportController,\r\n  AccountingTargetCrudController,\r\n  AccountResetController,\r\n  ActionButtonController,\r\n  AlertController,\r\n  AvatarController,\r\n  BatchProcessController,\r\n  CalcChartController,\r\n  CalcCostAccountingController,\r\n  CalcEmploymentController,\r\n  CalcHouseholdUsecaseController,\r\n  CalcImportController,\r\n  CalcIrRowsController,\r\n  CalcsIrRowsController,\r\n  CalcReportController,\r\n  CalcReportsController,\r\n  CalcReportsDisplayController,\r\n  CalcRowCostAccountingController,\r\n  CalcRowDimensionInputController,\r\n  CalcRowTypeController,\r\n  CalcRows2019Controller,\r\n  CalcSharingController,\r\n  CalcSharingReceiptActionController,\r\n  CalculationCrudController,\r\n  CalculationEditorController,\r\n  CalculationReportController,\r\n  Calculator2019Controller,\r\n  Calculator2022Controller,\r\n  CalcWorktimeController,\r\n  CalendarController,\r\n  CalendarEventsCrudController,\r\n  CalendarOccurencesController,\r\n  CertificateController,\r\n  ChartController,\r\n  CompanyAccountController,\r\n  CompanyInvoicesController,\r\n  CompanyImportController,\r\n  CompanyOnboardingController,\r\n  CompanySettingsController,\r\n  ContactInfoController,\r\n  CostAccountingController,\r\n  CredentialController,\r\n  CreditTransferController,\r\n  CustomerInvoiceCrudController,\r\n  CustomerOnboardingController,\r\n  DatasetsCrudController,\r\n  DatepickerController,\r\n  DatepickerPopupController,\r\n  DateRangeController,\r\n  EditDialogController,\r\n  EmbeddedUiController,\r\n  EmployerListController,\r\n  EmployerReportController,\r\n  EmployerSelectController,\r\n  EmploymentCrudController,\r\n  EmploymentTaxcardsController,\r\n  EmploymentWizardController,\r\n  ExportController,\r\n  HolidayPayReportQueryController,\r\n  HolidayReportController,\r\n  HolidayYearAccrualController,\r\n  HolidayYearCrudController,\r\n  HolidayYearHolidaysController,\r\n  HolidayYearPaidController,\r\n  HouseholdDeductionReportController,\r\n  HouseholdOnboardingController,\r\n  HouseholdYearCrudController,\r\n  ImportController,\r\n  ImportStagingController,\r\n  InputBooleanController,\r\n  InputController,\r\n  InputCredentialController,\r\n  InputDurationController,\r\n  InputEnumController,\r\n  InputHolidayMultipliersController,\r\n  InputHolidayRowTypeController,\r\n  InputIncomeTypeController,\r\n  InputNumberController,\r\n  InputRruleController,\r\n  InputTimeController,\r\n  InsuranceWizardController,\r\n  InvoiceCrudController,\r\n  InvoicesCreateController,\r\n  InvoiceReportController,\r\n  InvoiceSepaController,\r\n  InvoiceToolsController,\r\n  InvoiceAlertsController,\r\n  IrEarningsPaymentCrudController,\r\n  IrPayerSummaryCrudController,\r\n  JsonFormatterController,\r\n  MessageThreadCrudController,\r\n  ModalGenericDialogController,\r\n  MyTaxcardsController,\r\n  NaviController,\r\n  ODataActionsController,\r\n  ODataHelperController,\r\n  ODataQueryController,\r\n  OmapalkkaController,\r\n  OwnerSettingsController,\r\n  PartnerController,\r\n  PayCertificateController,\r\n  PaymentChannelController,\r\n  PaymentController,\r\n  PaymentChannelSettingsController,\r\n  PayrollCrudController,\r\n  Payroll4CrudController,\r\n  PalkkausPersonalPaymentOverviewController,\r\n  PersonAccountController,\r\n  RecordsController,\r\n  ReferenceObjectCrudController,\r\n  ReportsController,\r\n  RowTypesSettingsController,\r\n  SalaryBasesController,\r\n  SalaryDateKindController,\r\n  SalarySlipDownloadController,\r\n  SalaryReportCrudController,\r\n  SessionController,\r\n  SignatureController,\r\n  ServiceModelCrudController,\r\n  SigningController,\r\n  SmokeTestController,\r\n  SpinnerController,\r\n  SxyCodeEditorController,\r\n  SxyFormController,\r\n  SxyFormElementController,\r\n  SxyTableController,\r\n  SxyGridController,\r\n  SxyInputController,\r\n  SxySchemaEditorController,\r\n  TabController,\r\n  TabsController,\r\n  TaxcardManualEditController,\r\n  TaxcardCrudController,\r\n  TaxcardIncomeLogController,\r\n  UiTranslatorController,\r\n  UsecasesCrudController,\r\n  VarmaBannerController,\r\n  WelcomeController,\r\n  WizardController,\r\n  WorkerAbsencesCrudController,\r\n  WorkerAccountCrudController,\r\n  WorkerAssureController,\r\n  WorkerExpenseReportController,\r\n  WorkerHourlyReportController,\r\n  WorkerImportController,\r\n  WorkerOnboardingController,\r\n  WorkerReportController,\r\n  WorkerSummaryReportController,\r\n  WorkerSummaryReportDisplayController,\r\n  WorkerTimerController,\r\n  WorkflowController,\r\n  WorkflowBadgeController,\r\n  SummaryReportDisplayController,\r\n  SummaryReportController,\r\n  SummaryReportQueryController,\r\n  TimesheetWorkerDemoController,\r\n  ValidationSummaryController\r\n} from \".\";\r\nimport { CalcLeavesController } from \"./calc/CalcLeavesController\";\r\n\r\n/**\r\n * Provides methods for registering the Controllers to module\r\n * (and other related metadata in the future).\r\n */\r\nexport class ControllersRegistration {\r\n\r\n  /** Gets the controllers for Module registration. */\r\n  public static getControllers () {\r\n    return {\r\n      AbsencePeriodsController,\r\n      AccountantController,\r\n      AccountingChannelSettingsController,\r\n      AccountAuthorizationController,\r\n      AccountingHolidayPayDebtReportQueryController,\r\n      AccountingReportCrudController,\r\n      AccountingReportDisplayController,\r\n      AccountingReportQueryController,\r\n      AccountingReportRowsController,\r\n      AccountingReportToolsController,\r\n      AccountingRowReportController,\r\n      AccountingTargetCrudController,\r\n      AccountResetController,\r\n      ActionButtonController,\r\n      AlertController,\r\n      AvatarController,\r\n      BatchProcessController,\r\n      CalcChartController,\r\n      CalcCostAccountingController,\r\n      CalcEmploymentController,\r\n      CalcHouseholdUsecaseController,\r\n      CalcImportController,\r\n      CalcIrRowsController,\r\n      CalcsIrRowsController,\r\n      CalcWorktimeController,\r\n      CalcReportController,\r\n      CalcReportsController,\r\n      CalcReportsDisplayController,\r\n      CalcRowCostAccountingController,\r\n      CalcRowDimensionInputController,\r\n      CalcRowTypeController,\r\n      CalcRows2019Controller,\r\n      CalcSharingController,\r\n      CalcSharingReceiptActionController,\r\n      CalculationCrudController,\r\n      CalculationEditorController,\r\n      CalculationReportController,\r\n      Calculator2019Controller,\r\n      Calculator2022Controller,\r\n      CalcLeavesController,\r\n      CalendarController,\r\n      CalendarEventsCrudController,\r\n      CalendarOccurencesController,\r\n      CertificateController,\r\n      ChartController,\r\n      CompanyAccountController,\r\n      CompanyInvoicesController,\r\n      CompanyImportController,\r\n      CompanyOnboardingController,\r\n      CompanySettingsController,\r\n      ContactInfoController,\r\n      CostAccountingController,\r\n      CredentialController,\r\n      CreditTransferController,\r\n      CustomerInvoiceCrudController,\r\n      CustomerOnboardingController,\r\n      DatasetsCrudController,\r\n      DatepickerController,\r\n      DatepickerPopupController,\r\n      DateRangeController,\r\n      EditDialogController,\r\n      EmbeddedUiController,\r\n      EmployerListController,\r\n      EmployerReportController,\r\n      EmployerSelectController,\r\n      EmploymentCrudController,\r\n      EmploymentTaxcardsController,\r\n      EmploymentWizardController,\r\n      ExportController,\r\n      HolidayPayReportQueryController,\r\n      HolidayReportController,\r\n      HolidayYearAccrualController,\r\n      HolidayYearCrudController,\r\n      HolidayYearHolidaysController,\r\n      HolidayYearPaidController,\r\n      HouseholdDeductionReportController,\r\n      HouseholdOnboardingController,\r\n      HouseholdYearCrudController,\r\n      ImportController,\r\n      ImportStagingController,\r\n      InputBooleanController,\r\n      InputController,\r\n      InputCredentialController,\r\n      InputDurationController,\r\n      InputEnumController,\r\n      InputHolidayMultipliersController,\r\n      InputHolidayRowTypeController,\r\n      InputIncomeTypeController,\r\n      InputNumberController,\r\n      InputRruleController,\r\n      InputTimeController,\r\n      InsuranceWizardController,\r\n      InvoiceCrudController,\r\n      InvoicesCreateController,\r\n      InvoiceReportController,\r\n      InvoiceSepaController,\r\n      InvoiceToolsController,\r\n      InvoiceAlertsController,\r\n      IrEarningsPaymentCrudController,\r\n      IrPayerSummaryCrudController,\r\n      JsonFormatterController,\r\n      MessageThreadCrudController,\r\n      ModalGenericDialogController,\r\n      MyTaxcardsController,\r\n      NaviController,\r\n      ODataActionsController,\r\n      ODataHelperController,\r\n      ODataQueryController,\r\n      OmapalkkaController,\r\n      OwnerSettingsController,\r\n      PartnerController,\r\n      PayCertificateController,\r\n      PaymentController,\r\n      PaymentChannelController,\r\n      PaymentChannelSettingsController,\r\n      PayrollCrudController,\r\n      Payroll4CrudController,\r\n      PalkkausPersonalPaymentOverviewController,\r\n      PersonAccountController,\r\n      RecordsController,\r\n      ReferenceObjectCrudController,\r\n      ReportsController,\r\n      RowTypesSettingsController,\r\n      SalaryBasesController,\r\n      SalaryDateKindController,\r\n      SalarySlipDownloadController,\r\n      SalaryReportCrudController,\r\n      SessionController,\r\n      ServiceModelCrudController,\r\n      SignatureController,\r\n      SigningController,\r\n      SmokeTestController,\r\n      SpinnerController,\r\n      SummaryReportController,\r\n      SummaryReportDisplayController,\r\n      SummaryReportQueryController,\r\n      SxyCodeEditorController,\r\n      SxyFormController,\r\n      SxyFormElementController,\r\n      SxyTableController,\r\n      SxyGridController,\r\n      SxyInputController,\r\n      SxySchemaEditorController,\r\n      TabController,\r\n      TabsController,\r\n      TaxcardManualEditController,\r\n      TaxcardCrudController,\r\n      TaxcardIncomeLogController,\r\n      UiTranslatorController,\r\n      UsecasesCrudController,\r\n      VarmaBannerController,\r\n      WelcomeController,\r\n      WizardController,\r\n      WorkerAbsencesCrudController,\r\n      WorkerAccountCrudController,\r\n      WorkerAssureController,\r\n      WorkerExpenseReportController,\r\n      WorkerHourlyReportController,\r\n      WorkerImportController,\r\n      WorkerOnboardingController,\r\n      WorkerReportController,\r\n      WorkerSummaryReportController,\r\n      WorkerSummaryReportDisplayController,\r\n      WorkerTimerController,\r\n      WorkflowController,\r\n      WorkflowBadgeController,\r\n      TimesheetWorkerDemoController,\r\n      ValidationSummaryController\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Appends the given element to the current element.\r\n * The existing element will be removed from the source parent element.\r\n * The attribute value should resolve to an existing DOM node or string.\r\n * @example\r\n * ```html\r\n * <div salaxy-append-node=\"tab.headingElement\"></div>\r\n * ```\r\n */\r\nexport class AppendNodeDirective implements angular.IDirective {\r\n\r\n    /**\r\n     * Factory for directive registration.\r\n     * @ignore\r\n     */\r\n    public static salaxyAppendNode() {\r\n        const factory = () => new AppendNodeDirective();\r\n        factory.$inject = [];\r\n        return factory;\r\n    }\r\n\r\n    /**\r\n     * Applies to attributes only.\r\n     * @ignore\r\n     */\r\n    public restrict = \"A\";\r\n\r\n   /**\r\n    * Creates a new instance of the directive.\r\n    */\r\n    constructor() {\r\n        // initialization\r\n     }\r\n\r\n   /**\r\n    * Evaluates the attribute value (DOM node or default string), and appends it to the current element.\r\n    * @ignore\r\n    */\r\n    public link(scope: any, element: any, attrs: any) {\r\n      const node = scope.$eval(attrs.salaxyAppendNode);\r\n      element.append(node);\r\n    }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Fires the necessary Bootstrap 5 initialization for the given element.\r\n * @example\r\n * ```html\r\n * <a href=\"#\" sxyBs5 data-bs-toggle=\"tooltip\" data-bs-title=\"Default tooltip\">inline links</a>\r\n * ```\r\n */\r\nexport class Bs5 implements angular.IDirective {\r\n\r\n    /**\r\n     * Factory for directive registration.\r\n     * @ignore\r\n     */\r\n    public static salaxyBs5() {\r\n        const factory = () => new Bs5();\r\n        factory.$inject = [];\r\n        return factory;\r\n    }\r\n\r\n    /**\r\n     * Applies to attributes only.\r\n     * @ignore\r\n     */\r\n    public restrict = \"A\";\r\n\r\n   /**\r\n    * Creates a new instance of the directive.\r\n    */\r\n    constructor() {\r\n        // initialization\r\n     }\r\n\r\n   /**\r\n    * Attaches the appropriate Bootstrap scripts to the element.\r\n    * @ignore\r\n    */\r\n    public link(scope: any, element: JQLite, attrs: any) {\r\n      if (attrs.bsToggle == \"tooltip\") {\r\n        if (!globalThis.bootstrap) {\r\n          console.error(\"Bootstrap 5 is required for sxyBs5 directive.\");\r\n        } else {\r\n          const title = scope.$eval(attrs.bsTitle);\r\n          new globalThis.bootstrap.Tooltip(element[0], { title });\r\n        }\r\n      }\r\n      if (attrs.bsToggle == \"popover\") {\r\n        if (!globalThis.bootstrap) {\r\n          console.error(\"Bootstrap 5 is required for sxyBs5 directive.\");\r\n        } else {\r\n          const title = scope.$eval(attrs.bsTitle);\r\n          const content = scope.$eval(attrs.bsContent);\r\n          const placement = scope.$eval(attrs.bsPlacement) || \"top\";\r\n          new globalThis.bootstrap.Popover(element[0], { title, content, placement });\r\n        }\r\n      }\r\n    }\r\n}\r\n","/**\r\n * Parser and formatter functions for different enum inputs.\r\n * This is required for AngularJS versions less than 1.6\r\n */\r\nexport class EnumParserFunctions {\r\n\r\n  /**\r\n   * Boolean conversion.\r\n   * @example\r\n   * ```html\r\n   * <select ng-model=\"model.value\" sxy-enum-as-boolean>\r\n   *  <option value=\"null\">Null</option>\r\n   *  <option value=\"true\">True</option>\r\n   *  <option value=\"false\">False</option>\r\n   * </select>\r\n   * ```\r\n   */\r\n  public static sxyEnumAsBoolean() {\r\n    // eslint-disable-next-line @typescript-eslint/unbound-method\r\n    return () => EnumParserFunctions.directive(\"sxyEnumAsBoolean\", EnumParserFunctions.booleanParser);\r\n  }\r\n\r\n  private static directive(name: string, parser: (input: any) => any, formatter: (input: any) => string = null): any {\r\n    return {\r\n      restrict: \"A\",\r\n      require: \"ngModel\",\r\n      link: EnumParserFunctions.getLink(name, parser, formatter),\r\n    };\r\n  }\r\n\r\n  private static getLink(name: string, parser: (input: any) => any, formatter: (input: any) => string): any {\r\n    return (scope: any, element: any, attrs: any, ngModel: any) => {\r\n      ngModel.$parsers.push(parser);\r\n      // eslint-disable-next-line @typescript-eslint/unbound-method\r\n      ngModel.$formatters.push(formatter || EnumParserFunctions.defaultFormatter);\r\n    };\r\n  }\r\n\r\n  private static booleanParser(val: any): any {\r\n    switch (val) {\r\n      case \"null\":\r\n        return null;\r\n      case \"false\":\r\n        return false;\r\n      case \"true\":\r\n        return true;\r\n    }\r\n    return val;\r\n  }\r\n\r\n  private static defaultFormatter(val: any): string {\r\n    return \"\" + val;\r\n  }\r\n\r\n}\r\n","import angular from \"angular\";\r\nimport { SessionService } from \"../services\";\r\n\r\n/**\r\n * Shows the element if the user is in the given role / in one of the given roles.\r\n * The attribute value should resolve to either role string or array of role strings.\r\n * @example\r\n * ```html\r\n * <div *sxy-if-role=\"anon\">You are not logged in.</div>\r\n * <div *sxy-if-role=\"household,worker\">This text is shown to Household or Worker roles.</div>\r\n * ```\r\n */\r\nexport class IfRoleDirective implements angular.IDirective {\r\n\r\n    /**\r\n     * Factory method for the directive creation.\r\n     * @ignore\r\n     */\r\n    public static sxyIfRole() {\r\n        const factory = (sessionService: SessionService, ngIfDirective: any) => new IfRoleDirective(sessionService, ngIfDirective);\r\n        factory.$inject = [\"SessionService\", \"ngIfDirective\"];\r\n        return factory;\r\n    }\r\n\r\n    /**\r\n     * Directive restrictions.\r\n     * @ignore\r\n     */\r\n    public restrict;\r\n\r\n    /**\r\n     * Transclusion.\r\n     * @ignore\r\n     */\r\n    public transclude;\r\n\r\n    /**\r\n     * Priority parameter.\r\n     * @ignore\r\n     */\r\n    public priority;\r\n\r\n    /**\r\n     * Terminal parameter.\r\n     * @ignore\r\n     */\r\n    public terminal;\r\n\r\n    /** Uses the original ngIf class as bases for the functionality. */\r\n    private ngIf: any;\r\n\r\n   /**\r\n    * Creates a new instance of the directive.\r\n    */\r\n    constructor(private sessionService: SessionService, ngIfDirective: any) {\r\n        this.ngIf = ngIfDirective[0];\r\n        this.restrict = this.ngIf.restrict;\r\n        this.transclude = this.ngIf.transclude;\r\n        this.priority = this.ngIf.priority;\r\n        this.terminal = this.ngIf.terminal;\r\n     }\r\n\r\n   /**\r\n    * Link function for the directive.\r\n    * @ignore\r\n    */\r\n    public link(scope: any, element: any, attrs: any) {\r\n        const value = attrs.sxyIfRole || attrs.salaxyIfRole;\r\n        attrs.ngIf = () => {\r\n            return this.sessionService.isInSomeRole(value);\r\n        };\r\n        // eslint-disable-next-line prefer-spread, prefer-rest-params\r\n        this.ngIf.link.apply(this.ngIf, arguments);\r\n    }\r\n}\r\n","import angular from \"angular\";\r\nimport { NaviService } from \"../services\";\r\n\r\n/**\r\n * Shows the element based on Sitemap parameters:\r\n * Currently supported are Visibility and isFullWidth as interpreted by SitemapHelper.getVisibility() method,\r\n * e.g. \"hidden\" includes HiddenReadOnly, Disabled and current node not resolved situations besides Hidden.\r\n * See description of SitemapHelper.getVisibility() for exact details.\r\n * @example\r\n * ```html\r\n * <div *sxy-if-sitemap=\"hidden\">Shown if the current page is hidden (including HiddenReadOnly, Disabled and current node not resolved)</div>\r\n * <div *sxy-if-sitemap=\"visible\">Shown if the current page is visible (visibility null or Visible).</div>\r\n * ```\r\n */\r\nexport class IfSitemapDirective implements angular.IDirective {\r\n\r\n  /**\r\n   * Factory method for the directive creation.\r\n   * @ignore\r\n   */\r\n  public static sxyIfSitemap() {\r\n    const factory = (naviService: NaviService, ngIfDirective: any) => new IfSitemapDirective(naviService, ngIfDirective);\r\n    factory.$inject = [\"NaviService\", \"ngIfDirective\"];\r\n    return factory;\r\n  }\r\n\r\n  /**\r\n   * Directive restrictions.\r\n   * @ignore\r\n   */\r\n  public restrict;\r\n\r\n  /**\r\n   * Transclusion.\r\n   * @ignore\r\n   */\r\n  public transclude;\r\n\r\n  /**\r\n   * Priority parameter.\r\n   * @ignore\r\n   */\r\n  public priority;\r\n\r\n  /**\r\n   * Terminal parameter.\r\n   * @ignore\r\n   */\r\n  public terminal;\r\n\r\n  /** Uses the original ngIf class as bases for the functionality. */\r\n  private ngIf: any;\r\n\r\n  /**\r\n   * Creates a new instance of the directive.\r\n   */\r\n  constructor(private naviService: NaviService, ngIfDirective: any) {\r\n    this.ngIf = ngIfDirective[0];\r\n    this.restrict = this.ngIf.restrict;\r\n    this.transclude = this.ngIf.transclude;\r\n    this.priority = this.ngIf.priority;\r\n    this.terminal = this.ngIf.terminal;\r\n  }\r\n\r\n  /**\r\n   * Link function for the directive.\r\n   * @ignore\r\n   */\r\n  public link(scope: any, element: any, attrs: any) {\r\n    const value = attrs.sxyIfSitemap;\r\n    const prop = attrs.prop;\r\n    attrs.ngIf = () => {\r\n      if (prop && prop != \"visibility\") {\r\n        const compareTo = this.naviService.current.node?.[prop]?.toString();\r\n        if (compareTo?.trim() && value?.trim()) {\r\n          return compareTo.trim().toLowerCase() == value.trim().toLowerCase();\r\n        }\r\n        return false;\r\n      } else {\r\n        return this.naviService.current.getVisibility(value);\r\n      }\r\n    };\r\n    // eslint-disable-next-line prefer-spread, prefer-rest-params\r\n    this.ngIf.link.apply(this.ngIf, arguments);\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Loading indicator directive.\r\n * Toggles class \"salaxy-loading\" on an element. Toggling is based on  \"salaxy-loader-show\" and \"salaxy-loader-hide\" events from the\r\n * LoaderInterceptor which intercepts http calls.\r\n * @example\r\n * ```html\r\n * <div salaxy-loader class=\"spinner\">\r\n *   <div class=\"bounce1\"></div>\r\n *   <div class=\"bounce2\"></div>\r\n *   <div class=\"bounce3\"></div>\r\n * </div>\r\n * ```\r\n */\r\nexport class LoaderDirective implements angular.IDirective {\r\n\r\n  /**\r\n   * Factory for the directive creation.\r\n   * @ignore\r\n   */\r\n  public static salaxyLoader() {\r\n    const factory = () => new LoaderDirective();\r\n    factory.$inject = [];\r\n    return factory;\r\n  }\r\n\r\n  /**\r\n   * Directive restrictions.\r\n   * @ignore\r\n   */\r\n  public restrict = \"A\";\r\n\r\n  /**\r\n   * Creates a new instance of the directive.\r\n   */\r\n  constructor() {\r\n    // empty\r\n  }\r\n\r\n  /**\r\n   * Link function for the directive.\r\n   * @ignore\r\n   */\r\n  public link(scope: any, element: any, attrs: any) { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n    scope.$on(\"salaxy-loader-show\", () => {\r\n      if (!element.hasClass(\"salaxy-loading\")) {\r\n        element.addClass(\"salaxy-loading\");\r\n      }\r\n    });\r\n    scope.$on(\"salaxy-loader-hide\", () => {\r\n      if (element.hasClass(\"salaxy-loading\")) {\r\n        element.removeClass(\"salaxy-loading\");\r\n      }\r\n    });\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Adds the OData $orderby functionality to table column header.\r\n * Primary design is for thead > tr > th element or for span / div within that tag.\r\n * Requires salaxy-odata-table component as parent.\r\n * @example\r\n * ```html\r\n * <thead>\r\n *   <th>\r\n *     <span sxy-orderby=\"title\">Title</span>\r\n *     <br /> other text\r\n *   </th>\r\n *   <th sxy-orderby=\"section\" class=\"right\"><small>Section</small></th>\r\n * ```\r\n */\r\nexport class OrderbyDirective implements angular.IDirective {\r\n\r\n    /**\r\n     * Factory for directive registration.\r\n     * @ignore\r\n     */\r\n    public static sxyOrderby() {\r\n      const factory = () => new OrderbyDirective();\r\n      factory.$inject = [];\r\n      return factory;\r\n    }\r\n\r\n    /**\r\n     * Applies to attributes only.\r\n     * @ignore\r\n     */\r\n    public restrict = \"A\";\r\n\r\n    /** The view replaces the original element */\r\n    public replace = true;\r\n\r\n    /** Contents of the tag is transcluded: HTML can be used as input. */\r\n    public transclude = true;\r\n\r\n    /** Set isolate scope */\r\n    public scope = true;\r\n\r\n    /** Attribute must be used within salaxy-odata-table component to access the common ODataQueryController  */\r\n    public require = {\r\n      $odata: \"^^salaxyOdataTable\",\r\n    };\r\n\r\n   /**\r\n    * Creates a new instance of the directive.\r\n    */\r\n    constructor() {\r\n        // initialization\r\n     }\r\n\r\n     /**\r\n      * Template is based on the original tag.\r\n      */\r\n    public template(element, attrs: any ) { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n      const tag = element[0].nodeName;\r\n      return `<${tag} ng-click=\"$odata.orderBy(orderby)\" class=\"clickable\">\r\n            <ng-transclude></ng-transclude><i ng-if=\"$odata.getColumnOrder(orderby)\" class=\"fa salaxy-odata-table-sort fa-sort-{{ $odata.getColumnOrder(orderby) }}\" aria-hidden=\"true\"></i></${tag}>`;\r\n    }\r\n\r\n     /**\r\n      * Links the directive: Access to scope, element and attrs.\r\n      * @ignore\r\n      */\r\n    public link = (scope: any, element: any, attrs: any, controllers: any) => {\r\n        scope.$odata = controllers.$odata;\r\n        scope.orderby = attrs.sxyOrderby;\r\n    };\r\n}\r\n","import { Arrays, Validation, Numeric } from \"@salaxy/core\";\r\n\r\n/* eslint-disable @typescript-eslint/unbound-method */\r\n\r\n/**\r\n * Validator directives for different form inputs.\r\n * See mthods for examples of use.\r\n */\r\nexport class ValidatorFunctions {\r\n\r\n    /**\r\n     * Tax percent validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"taxPercent\" type=\"text\" ng-model=\"taxPercent\" sxy-tax-percent>\r\n     * ```\r\n     */\r\n    public static sxyTaxPercent() {\r\n        return () => ValidatorFunctions.directive(\"sxyTaxPercent\", Validation.isTaxPercent);\r\n    }\r\n\r\n    /**\r\n     * Currency value validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"currency\" type=\"text\" ng-model=\"currency\" sxy-currency>\r\n     * ```\r\n     */\r\n    public static sxyCurrency() {\r\n        return () => ValidatorFunctions.directive(\"sxyCurrency\", Validation.isCurrency);\r\n    }\r\n\r\n    /**\r\n     * Iban validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"iban\" type=\"text\" ng-model=\"iban\" sxy-iban>\r\n     * ```\r\n     */\r\n    public static sxyIban() {\r\n        return () => ValidatorFunctions.directive(\"sxyIban\", Validation.isIban);\r\n    }\r\n\r\n    /**\r\n     * Email validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"email\" type=\"text\" ng-model=\"email\" sxy-email>\r\n     * ```\r\n     */\r\n    public static sxyEmail() {\r\n        return () => ValidatorFunctions.directive(\"sxyEmail\", Validation.isEmail);\r\n    }\r\n\r\n    /**\r\n     * Mobile phone validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"mobilePhone\" type=\"text\" ng-model=\"mobilePhone\" sxy-mobile-phone>\r\n     * ```\r\n     */\r\n    public static sxyMobilePhone() {\r\n        return () => ValidatorFunctions.directive(\"sxyMobilePhone\", Validation.isMobilePhone);\r\n    }\r\n\r\n    /**\r\n     * Finnish personal id validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"personalIdFi\" type=\"text\" ng-model=\"personalIdFi\" sxy-personal-id-fi>\r\n     * ```\r\n     */\r\n    public static sxyPersonalIdFi() {\r\n        return () => ValidatorFunctions.directive(\"sxyPersonalIdFi\", Validation.isPersonalIdFi);\r\n    }\r\n\r\n    /**\r\n     * Finnish company id validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"companyIdFi\" type=\"text\" ng-model=\"companyIdFi\" sxy-company-id-fi>\r\n     * ```\r\n     */\r\n    public static sxyCompanyIdFi() {\r\n        return () => ValidatorFunctions.directive(\"sxyCompanyIdFi\", Validation.formatCompanyIdFi);\r\n    }\r\n\r\n    /**\r\n     * Finnish official id validator. Official ID may be either company id orr personal id.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"officialIdFi\" type=\"text\" ng-model=\"officialIdFi\" sxy-official-id-fi>\r\n     * ```\r\n     */\r\n     public static sxyOfficialIdFi() {\r\n      return () => ValidatorFunctions.directive(\"sxyOfficialIdFi\", (input) => {\r\n        return Validation.formatCompanyIdFi(input, true) || Validation.isPersonalIdFi(input);\r\n      });\r\n    }\r\n\r\n    /**\r\n     * Finnish postal code validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"postalCodeFi\" type=\"text\" ng-model=\"postalCodeFi\" sxy-postal-code-fi>\r\n     * ```\r\n     */\r\n    public static sxyPostalCodeFi() {\r\n        return () => ValidatorFunctions.directive(\"sxyPostalCodeFi\", Validation.isPostalCodeFi);\r\n    }\r\n\r\n    /**\r\n     * Number validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"number\" type=\"text\" ng-model=\"number\" sxy-number>\r\n     * ```\r\n     */\r\n    public static sxyNumber() {\r\n        return () => ValidatorFunctions.directive(\"sxyNumber\", Validation.isNumber);\r\n    }\r\n\r\n    /**\r\n     * Pension contract number validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"pensionContractNumber\" type=\"text\" ng-model=\"pensionContractNumber\" sxy-pension-contract-number=\"'varma'\">\r\n     * ```\r\n     */\r\n     public static sxyPensionContractNumber() {\r\n        /** return () => ValidatorFunctions.parserAndFormatterDirective([\"sxyPensionContractNumber\"], [(val) => !!Validation.isPensionContractNumber(val)]);*/\r\n\r\n        return () => ValidatorFunctions.directive(\"sxyPensionContractNumber\", (value: string, attrValue: any) => {\r\n          let result = false;\r\n          if(!attrValue) {\r\n            result = !!Validation.isPensionContractNumber(value);\r\n          } else {\r\n            result = attrValue == Validation.isPensionContractNumber(value);\r\n          }\r\n          setTimeout(() => {\r\n            //\r\n          });\r\n          return result;\r\n        } );\r\n     }\r\n\r\n    /**\r\n     * Integer validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"intger\" type=\"text\" ng-model=\"integer\" sxy-integer>\r\n     * ```\r\n     */\r\n    public static sxyInteger() {\r\n        return () => ValidatorFunctions.directive(\"sxyInteger\", Validation.isInteger);\r\n    }\r\n\r\n    /**\r\n     * Maximum value validator\r\n     * <input name=\"number\" type=\"text\" ng-model=\"number\" sxy-min=\"$ctrl.maximum\">\r\n     */\r\n    public static sxyMin() {\r\n      return () => ValidatorFunctions.directive(\"sxyMin\", (value: string, attrValue: any) => {\r\n        if(!Validation.isNumber(value) || !Validation.isNumber(attrValue)){\r\n          return true;\r\n        }\r\n        return Numeric.parseNumber(value) >= Numeric.parseNumber(attrValue);\r\n      } );\r\n    }\r\n\r\n    /**\r\n     * Maximum value validator\r\n     * <input name=\"number\" type=\"text\" ng-model=\"number\" sxy-max=\"$ctrl.maximum\">\r\n     */\r\n    public static sxyMax() {\r\n      return () => ValidatorFunctions.directive(\"sxyMax\", (value: string, attrValue: any) => {\r\n        if(!Validation.isNumber(value) || !Validation.isNumber(attrValue) ){\r\n          return true;\r\n        }\r\n        return Numeric.parseNumber(value) <= Numeric.parseNumber(attrValue);\r\n      } );\r\n    }\r\n\r\n    /**\r\n     * Multiple of value validator\r\n     * <input name=\"number\" type=\"text\" ng-model=\"number\" sxy-multiple-of=\"$ctrl.multipleOf\">\r\n     */\r\n    public static sxyMultipleOf() {\r\n      return () => ValidatorFunctions.directive(\"sxyMultipleOf\", (value: string, attrValue: any) => {\r\n        if(!Validation.isNumber(value) || !Validation.isNumber(attrValue)){\r\n          return true;\r\n        }\r\n        if(Numeric.parseNumber(attrValue) <= 0){\r\n          return false;\r\n        }\r\n        return Numeric.parseNumber(value) % Numeric.parseNumber(attrValue) === 0;\r\n      } );\r\n    }\r\n\r\n    /**\r\n     * Finnish bank reference number validator.\r\n     * @example\r\n     * ```html\r\n     * <input name=\"bankRefNumber\" type=\"text\" ng-model=\"bankRefNumber\" sxy-bank-reference-fi>\r\n     * ```\r\n     */\r\n     public static sxyBankReferenceFi() {\r\n      return () => ValidatorFunctions.directive(\"sxyBankReferenceFi\", Validation.isFinnishBankReferenceNumber);\r\n    }\r\n    /**\r\n     * Validator for values which should not be considered as valid in the UI (i.e. unknown, none)\r\n     */\r\n    public static sxyExcludeUnknowns() {\r\n      return () => ValidatorFunctions.directive(\"sxyExcludeUnknowns\", (value: string, attrValue: any) => {\r\n        const invalidValues = Arrays.assureArray(attrValue);\r\n        return !(invalidValues.indexOf(value) >= 0);\r\n      } );\r\n    }\r\n    private static directive(name: string, validationFunction: (input: string, attrValue: any) => boolean): any {\r\n        return {\r\n            restrict: \"A\",\r\n            require: \"ngModel\",\r\n            link: ValidatorFunctions.setValidator(name, validationFunction),\r\n        };\r\n    }\r\n\r\n    private static parserAndFormatterDirective(names: string[], validationFunctions: ((input: string) => boolean)[]): any {\r\n        return {\r\n            restrict: \"A\",\r\n            require: \"ngModel\",\r\n            link: ValidatorFunctions.setParserAndFormatter(names, validationFunctions),\r\n        };\r\n    }\r\n    private static setValidator(name: string, validationFunction: (input: string, attrValue: any) => boolean): any {\r\n        return (scope: any, element: any, attrs: any, ctrl: any) => {\r\n            ctrl.$validators[name] = (modelValue, viewValue) => {\r\n                if (ctrl.$isEmpty(modelValue)) {\r\n                    // consider empty models to be valid\r\n                    return true;\r\n                }\r\n                return validationFunction(viewValue,  scope.$eval(attrs[name]));\r\n            };\r\n        };\r\n    }\r\n\r\n    private static setParserAndFormatter(names: string[], validationFunctions: ((input: string) => boolean)[]): any {\r\n        return (scope: any, element: any, attrs: any, ctrl: any) => {\r\n\r\n                ctrl.$parsers.unshift( (value) => {\r\n                    let allValid = true;\r\n                    for ( let i = 0; i < names.length; i++) {\r\n                    // test and set the validity after update.\r\n                        const valid = validationFunctions[i](value);\r\n                        ctrl.$setValidity(names[i], valid);\r\n                        if (!valid) {\r\n                            allValid = false;\r\n                        }\r\n                    }\r\n\r\n                    // if it's valid, return the value to the model,\r\n                    // otherwise return undefined.\r\n                    return allValid ? value : undefined;\r\n                });\r\n            };\r\n        }\r\n    }\r\n","import angular from \"angular\";\r\n\r\nimport { Dates } from \"@salaxy/core\";\r\n\r\n/**\r\n * Validates the datepicker manual input using the same rules\r\n * as the actual calendar selection control.\r\n * Currently this directive is used internally in salaxy-datepicker-popup only.\r\n *\r\n */\r\nexport class DatepickerInputValidationDirective implements angular.IDirective {\r\n\r\n  /**\r\n   * Factory for directive registration.\r\n   * @ignore\r\n   */\r\n  public static salaxyDatepickerInputValidation() {\r\n    const factory = () => new DatepickerInputValidationDirective();\r\n    factory.$inject = [];\r\n    return factory;\r\n  }\r\n\r\n  /**\r\n   * Applies to attributes only.\r\n   * @ignore\r\n   */\r\n  public restrict = \"A\";\r\n\r\n  /**\r\n   * Requires model.\r\n   * @ignore\r\n   */\r\n  public require = \"ngModel\";\r\n\r\n  /**\r\n   * Creates a new instance of the directive.\r\n   */\r\n  constructor() {\r\n    // initialization\r\n  }\r\n\r\n  /**\r\n   * Validates the datepicker manual input using the same rules\r\n   * as the actual calendar selection control.\r\n   * @ignore\r\n   */\r\n  public link(scope: any, element: any, attrs: any, ngModel: any) {\r\n\r\n    // Validates date if it has a value:\r\n    // - within minDate and maxDate of datepicker options\r\n    // - not disabled according to datepicker options' dateDisabled function\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    ngModel.$validators.invalidDate = (modelValue, viewValue) => {\r\n      if (!modelValue) {\r\n        return true;\r\n      }\r\n\r\n      const datepickerOptions = scope.$eval(attrs.datepickerOptions);\r\n      if (!datepickerOptions) {\r\n        return true;\r\n      }\r\n\r\n      if (datepickerOptions.minDate || datepickerOptions.maxDate) {\r\n        const modelValueDay = Dates.asDate(modelValue);\r\n\r\n        if (datepickerOptions.minDate) {\r\n          const minDateDay = Dates.asDate(datepickerOptions.minDate);\r\n          if (modelValueDay < minDateDay) {\r\n            return false;\r\n          }\r\n        }\r\n\r\n        if (datepickerOptions.maxDate) {\r\n          const maxDateDay = Dates.asDate(datepickerOptions.maxDate);\r\n          if (modelValueDay > maxDateDay) {\r\n            return false;\r\n          }\r\n        }\r\n      }\r\n\r\n      if (datepickerOptions.dateDisabled && datepickerOptions.dateDisabled({ date: Dates.asJSDate(modelValue) })) {\r\n        return false;\r\n      }\r\n\r\n      return true;\r\n    };\r\n  }\r\n}\r\n","/**\n * marked v12.0.2 - a markdown parser\n * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/markedjs/marked\n */\n\n/**\n * DO NOT EDIT THIS FILE\n * The code in this file is generated from files in ./src/\n */\n\n/**\n * Gets the original marked default options.\n */\nfunction _getDefaults() {\n    return {\n        async: false,\n        breaks: false,\n        extensions: null,\n        gfm: true,\n        hooks: null,\n        pedantic: false,\n        renderer: null,\n        silent: false,\n        tokenizer: null,\n        walkTokens: null\n    };\n}\nlet _defaults = _getDefaults();\nfunction changeDefaults(newDefaults) {\n    _defaults = newDefaults;\n}\n\n/**\n * Helpers\n */\nconst escapeTest = /[&<>\"']/;\nconst escapeReplace = new RegExp(escapeTest.source, 'g');\nconst escapeTestNoEncode = /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/;\nconst escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g');\nconst escapeReplacements = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#39;'\n};\nconst getEscapeReplacement = (ch) => escapeReplacements[ch];\nfunction escape$1(html, encode) {\n    if (encode) {\n        if (escapeTest.test(html)) {\n            return html.replace(escapeReplace, getEscapeReplacement);\n        }\n    }\n    else {\n        if (escapeTestNoEncode.test(html)) {\n            return html.replace(escapeReplaceNoEncode, getEscapeReplacement);\n        }\n    }\n    return html;\n}\nconst unescapeTest = /&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig;\nfunction unescape(html) {\n    // explicitly match decimal, hex, and named HTML entities\n    return html.replace(unescapeTest, (_, n) => {\n        n = n.toLowerCase();\n        if (n === 'colon')\n            return ':';\n        if (n.charAt(0) === '#') {\n            return n.charAt(1) === 'x'\n                ? String.fromCharCode(parseInt(n.substring(2), 16))\n                : String.fromCharCode(+n.substring(1));\n        }\n        return '';\n    });\n}\nconst caret = /(^|[^\\[])\\^/g;\nfunction edit(regex, opt) {\n    let source = typeof regex === 'string' ? regex : regex.source;\n    opt = opt || '';\n    const obj = {\n        replace: (name, val) => {\n            let valSource = typeof val === 'string' ? val : val.source;\n            valSource = valSource.replace(caret, '$1');\n            source = source.replace(name, valSource);\n            return obj;\n        },\n        getRegex: () => {\n            return new RegExp(source, opt);\n        }\n    };\n    return obj;\n}\nfunction cleanUrl(href) {\n    try {\n        href = encodeURI(href).replace(/%25/g, '%');\n    }\n    catch (e) {\n        return null;\n    }\n    return href;\n}\nconst noopTest = { exec: () => null };\nfunction splitCells(tableRow, count) {\n    // ensure that every cell-delimiting pipe has a space\n    // before it to distinguish it from an escaped pipe\n    const row = tableRow.replace(/\\|/g, (match, offset, str) => {\n        let escaped = false;\n        let curr = offset;\n        while (--curr >= 0 && str[curr] === '\\\\')\n            escaped = !escaped;\n        if (escaped) {\n            // odd number of slashes means | is escaped\n            // so we leave it alone\n            return '|';\n        }\n        else {\n            // add space before unescaped |\n            return ' |';\n        }\n    }), cells = row.split(/ \\|/);\n    let i = 0;\n    // First/last cell in a row cannot be empty if it has no leading/trailing pipe\n    if (!cells[0].trim()) {\n        cells.shift();\n    }\n    if (cells.length > 0 && !cells[cells.length - 1].trim()) {\n        cells.pop();\n    }\n    if (count) {\n        if (cells.length > count) {\n            cells.splice(count);\n        }\n        else {\n            while (cells.length < count)\n                cells.push('');\n        }\n    }\n    for (; i < cells.length; i++) {\n        // leading or trailing whitespace is ignored per the gfm spec\n        cells[i] = cells[i].trim().replace(/\\\\\\|/g, '|');\n    }\n    return cells;\n}\n/**\n * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').\n * /c*$/ is vulnerable to REDOS.\n *\n * @param str\n * @param c\n * @param invert Remove suffix of non-c chars instead. Default falsey.\n */\nfunction rtrim(str, c, invert) {\n    const l = str.length;\n    if (l === 0) {\n        return '';\n    }\n    // Length of suffix matching the invert condition.\n    let suffLen = 0;\n    // Step left until we fail to match the invert condition.\n    while (suffLen < l) {\n        const currChar = str.charAt(l - suffLen - 1);\n        if (currChar === c && !invert) {\n            suffLen++;\n        }\n        else if (currChar !== c && invert) {\n            suffLen++;\n        }\n        else {\n            break;\n        }\n    }\n    return str.slice(0, l - suffLen);\n}\nfunction findClosingBracket(str, b) {\n    if (str.indexOf(b[1]) === -1) {\n        return -1;\n    }\n    let level = 0;\n    for (let i = 0; i < str.length; i++) {\n        if (str[i] === '\\\\') {\n            i++;\n        }\n        else if (str[i] === b[0]) {\n            level++;\n        }\n        else if (str[i] === b[1]) {\n            level--;\n            if (level < 0) {\n                return i;\n            }\n        }\n    }\n    return -1;\n}\n\nfunction outputLink(cap, link, raw, lexer) {\n    const href = link.href;\n    const title = link.title ? escape$1(link.title) : null;\n    const text = cap[1].replace(/\\\\([\\[\\]])/g, '$1');\n    if (cap[0].charAt(0) !== '!') {\n        lexer.state.inLink = true;\n        const token = {\n            type: 'link',\n            raw,\n            href,\n            title,\n            text,\n            tokens: lexer.inlineTokens(text)\n        };\n        lexer.state.inLink = false;\n        return token;\n    }\n    return {\n        type: 'image',\n        raw,\n        href,\n        title,\n        text: escape$1(text)\n    };\n}\nfunction indentCodeCompensation(raw, text) {\n    const matchIndentToCode = raw.match(/^(\\s+)(?:```)/);\n    if (matchIndentToCode === null) {\n        return text;\n    }\n    const indentToCode = matchIndentToCode[1];\n    return text\n        .split('\\n')\n        .map(node => {\n        const matchIndentInNode = node.match(/^\\s+/);\n        if (matchIndentInNode === null) {\n            return node;\n        }\n        const [indentInNode] = matchIndentInNode;\n        if (indentInNode.length >= indentToCode.length) {\n            return node.slice(indentToCode.length);\n        }\n        return node;\n    })\n        .join('\\n');\n}\n/**\n * Tokenizer\n */\nclass _Tokenizer {\n    options;\n    rules; // set by the lexer\n    lexer; // set by the lexer\n    constructor(options) {\n        this.options = options || _defaults;\n    }\n    space(src) {\n        const cap = this.rules.block.newline.exec(src);\n        if (cap && cap[0].length > 0) {\n            return {\n                type: 'space',\n                raw: cap[0]\n            };\n        }\n    }\n    code(src) {\n        const cap = this.rules.block.code.exec(src);\n        if (cap) {\n            const text = cap[0].replace(/^ {1,4}/gm, '');\n            return {\n                type: 'code',\n                raw: cap[0],\n                codeBlockStyle: 'indented',\n                text: !this.options.pedantic\n                    ? rtrim(text, '\\n')\n                    : text\n            };\n        }\n    }\n    fences(src) {\n        const cap = this.rules.block.fences.exec(src);\n        if (cap) {\n            const raw = cap[0];\n            const text = indentCodeCompensation(raw, cap[3] || '');\n            return {\n                type: 'code',\n                raw,\n                lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],\n                text\n            };\n        }\n    }\n    heading(src) {\n        const cap = this.rules.block.heading.exec(src);\n        if (cap) {\n            let text = cap[2].trim();\n            // remove trailing #s\n            if (/#$/.test(text)) {\n                const trimmed = rtrim(text, '#');\n                if (this.options.pedantic) {\n                    text = trimmed.trim();\n                }\n                else if (!trimmed || / $/.test(trimmed)) {\n                    // CommonMark requires space before trailing #s\n                    text = trimmed.trim();\n                }\n            }\n            return {\n                type: 'heading',\n                raw: cap[0],\n                depth: cap[1].length,\n                text,\n                tokens: this.lexer.inline(text)\n            };\n        }\n    }\n    hr(src) {\n        const cap = this.rules.block.hr.exec(src);\n        if (cap) {\n            return {\n                type: 'hr',\n                raw: cap[0]\n            };\n        }\n    }\n    blockquote(src) {\n        const cap = this.rules.block.blockquote.exec(src);\n        if (cap) {\n            // precede setext continuation with 4 spaces so it isn't a setext\n            let text = cap[0].replace(/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g, '\\n    $1');\n            text = rtrim(text.replace(/^ *>[ \\t]?/gm, ''), '\\n');\n            const top = this.lexer.state.top;\n            this.lexer.state.top = true;\n            const tokens = this.lexer.blockTokens(text);\n            this.lexer.state.top = top;\n            return {\n                type: 'blockquote',\n                raw: cap[0],\n                tokens,\n                text\n            };\n        }\n    }\n    list(src) {\n        let cap = this.rules.block.list.exec(src);\n        if (cap) {\n            let bull = cap[1].trim();\n            const isordered = bull.length > 1;\n            const list = {\n                type: 'list',\n                raw: '',\n                ordered: isordered,\n                start: isordered ? +bull.slice(0, -1) : '',\n                loose: false,\n                items: []\n            };\n            bull = isordered ? `\\\\d{1,9}\\\\${bull.slice(-1)}` : `\\\\${bull}`;\n            if (this.options.pedantic) {\n                bull = isordered ? bull : '[*+-]';\n            }\n            // Get next list item\n            const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\\t ][^\\\\n]*)?(?:\\\\n|$))`);\n            let raw = '';\n            let itemContents = '';\n            let endsWithBlankLine = false;\n            // Check if current bullet point can start a new List Item\n            while (src) {\n                let endEarly = false;\n                if (!(cap = itemRegex.exec(src))) {\n                    break;\n                }\n                if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)\n                    break;\n                }\n                raw = cap[0];\n                src = src.substring(raw.length);\n                let line = cap[2].split('\\n', 1)[0].replace(/^\\t+/, (t) => ' '.repeat(3 * t.length));\n                let nextLine = src.split('\\n', 1)[0];\n                let indent = 0;\n                if (this.options.pedantic) {\n                    indent = 2;\n                    itemContents = line.trimStart();\n                }\n                else {\n                    indent = cap[2].search(/[^ ]/); // Find first non-space char\n                    indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent\n                    itemContents = line.slice(indent);\n                    indent += cap[1].length;\n                }\n                let blankLine = false;\n                if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line\n                    raw += nextLine + '\\n';\n                    src = src.substring(nextLine.length + 1);\n                    endEarly = true;\n                }\n                if (!endEarly) {\n                    const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \\t][^\\\\n]*)?(?:\\\\n|$))`);\n                    const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`);\n                    const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\\`\\`\\`|~~~)`);\n                    const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);\n                    // Check if following lines should be included in List Item\n                    while (src) {\n                        const rawLine = src.split('\\n', 1)[0];\n                        nextLine = rawLine;\n                        // Re-align to follow commonmark nesting rules\n                        if (this.options.pedantic) {\n                            nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, '  ');\n                        }\n                        // End list item if found code fences\n                        if (fencesBeginRegex.test(nextLine)) {\n                            break;\n                        }\n                        // End list item if found start of new heading\n                        if (headingBeginRegex.test(nextLine)) {\n                            break;\n                        }\n                        // End list item if found start of new bullet\n                        if (nextBulletRegex.test(nextLine)) {\n                            break;\n                        }\n                        // Horizontal rule found\n                        if (hrRegex.test(src)) {\n                            break;\n                        }\n                        if (nextLine.search(/[^ ]/) >= indent || !nextLine.trim()) { // Dedent if possible\n                            itemContents += '\\n' + nextLine.slice(indent);\n                        }\n                        else {\n                            // not enough indentation\n                            if (blankLine) {\n                                break;\n                            }\n                            // paragraph continuation unless last line was a different block level element\n                            if (line.search(/[^ ]/) >= 4) { // indented code block\n                                break;\n                            }\n                            if (fencesBeginRegex.test(line)) {\n                                break;\n                            }\n                            if (headingBeginRegex.test(line)) {\n                                break;\n                            }\n                            if (hrRegex.test(line)) {\n                                break;\n                            }\n                            itemContents += '\\n' + nextLine;\n                        }\n                        if (!blankLine && !nextLine.trim()) { // Check if current line is blank\n                            blankLine = true;\n                        }\n                        raw += rawLine + '\\n';\n                        src = src.substring(rawLine.length + 1);\n                        line = nextLine.slice(indent);\n                    }\n                }\n                if (!list.loose) {\n                    // If the previous item ended with a blank line, the list is loose\n                    if (endsWithBlankLine) {\n                        list.loose = true;\n                    }\n                    else if (/\\n *\\n *$/.test(raw)) {\n                        endsWithBlankLine = true;\n                    }\n                }\n                let istask = null;\n                let ischecked;\n                // Check for task list items\n                if (this.options.gfm) {\n                    istask = /^\\[[ xX]\\] /.exec(itemContents);\n                    if (istask) {\n                        ischecked = istask[0] !== '[ ] ';\n                        itemContents = itemContents.replace(/^\\[[ xX]\\] +/, '');\n                    }\n                }\n                list.items.push({\n                    type: 'list_item',\n                    raw,\n                    task: !!istask,\n                    checked: ischecked,\n                    loose: false,\n                    text: itemContents,\n                    tokens: []\n                });\n                list.raw += raw;\n            }\n            // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic\n            list.items[list.items.length - 1].raw = raw.trimEnd();\n            (list.items[list.items.length - 1]).text = itemContents.trimEnd();\n            list.raw = list.raw.trimEnd();\n            // Item child tokens handled here at end because we needed to have the final item to trim it first\n            for (let i = 0; i < list.items.length; i++) {\n                this.lexer.state.top = false;\n                list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);\n                if (!list.loose) {\n                    // Check if list should be loose\n                    const spacers = list.items[i].tokens.filter(t => t.type === 'space');\n                    const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => /\\n.*\\n/.test(t.raw));\n                    list.loose = hasMultipleLineBreaks;\n                }\n            }\n            // Set all items to loose if list is loose\n            if (list.loose) {\n                for (let i = 0; i < list.items.length; i++) {\n                    list.items[i].loose = true;\n                }\n            }\n            return list;\n        }\n    }\n    html(src) {\n        const cap = this.rules.block.html.exec(src);\n        if (cap) {\n            const token = {\n                type: 'html',\n                block: true,\n                raw: cap[0],\n                pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',\n                text: cap[0]\n            };\n            return token;\n        }\n    }\n    def(src) {\n        const cap = this.rules.block.def.exec(src);\n        if (cap) {\n            const tag = cap[1].toLowerCase().replace(/\\s+/g, ' ');\n            const href = cap[2] ? cap[2].replace(/^<(.*)>$/, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';\n            const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];\n            return {\n                type: 'def',\n                tag,\n                raw: cap[0],\n                href,\n                title\n            };\n        }\n    }\n    table(src) {\n        const cap = this.rules.block.table.exec(src);\n        if (!cap) {\n            return;\n        }\n        if (!/[:|]/.test(cap[2])) {\n            // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading\n            return;\n        }\n        const headers = splitCells(cap[1]);\n        const aligns = cap[2].replace(/^\\||\\| *$/g, '').split('|');\n        const rows = cap[3] && cap[3].trim() ? cap[3].replace(/\\n[ \\t]*$/, '').split('\\n') : [];\n        const item = {\n            type: 'table',\n            raw: cap[0],\n            header: [],\n            align: [],\n            rows: []\n        };\n        if (headers.length !== aligns.length) {\n            // header and align columns must be equal, rows can be different.\n            return;\n        }\n        for (const align of aligns) {\n            if (/^ *-+: *$/.test(align)) {\n                item.align.push('right');\n            }\n            else if (/^ *:-+: *$/.test(align)) {\n                item.align.push('center');\n            }\n            else if (/^ *:-+ *$/.test(align)) {\n                item.align.push('left');\n            }\n            else {\n                item.align.push(null);\n            }\n        }\n        for (const header of headers) {\n            item.header.push({\n                text: header,\n                tokens: this.lexer.inline(header)\n            });\n        }\n        for (const row of rows) {\n            item.rows.push(splitCells(row, item.header.length).map(cell => {\n                return {\n                    text: cell,\n                    tokens: this.lexer.inline(cell)\n                };\n            }));\n        }\n        return item;\n    }\n    lheading(src) {\n        const cap = this.rules.block.lheading.exec(src);\n        if (cap) {\n            return {\n                type: 'heading',\n                raw: cap[0],\n                depth: cap[2].charAt(0) === '=' ? 1 : 2,\n                text: cap[1],\n                tokens: this.lexer.inline(cap[1])\n            };\n        }\n    }\n    paragraph(src) {\n        const cap = this.rules.block.paragraph.exec(src);\n        if (cap) {\n            const text = cap[1].charAt(cap[1].length - 1) === '\\n'\n                ? cap[1].slice(0, -1)\n                : cap[1];\n            return {\n                type: 'paragraph',\n                raw: cap[0],\n                text,\n                tokens: this.lexer.inline(text)\n            };\n        }\n    }\n    text(src) {\n        const cap = this.rules.block.text.exec(src);\n        if (cap) {\n            return {\n                type: 'text',\n                raw: cap[0],\n                text: cap[0],\n                tokens: this.lexer.inline(cap[0])\n            };\n        }\n    }\n    escape(src) {\n        const cap = this.rules.inline.escape.exec(src);\n        if (cap) {\n            return {\n                type: 'escape',\n                raw: cap[0],\n                text: escape$1(cap[1])\n            };\n        }\n    }\n    tag(src) {\n        const cap = this.rules.inline.tag.exec(src);\n        if (cap) {\n            if (!this.lexer.state.inLink && /^<a /i.test(cap[0])) {\n                this.lexer.state.inLink = true;\n            }\n            else if (this.lexer.state.inLink && /^<\\/a>/i.test(cap[0])) {\n                this.lexer.state.inLink = false;\n            }\n            if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\\s|>)/i.test(cap[0])) {\n                this.lexer.state.inRawBlock = true;\n            }\n            else if (this.lexer.state.inRawBlock && /^<\\/(pre|code|kbd|script)(\\s|>)/i.test(cap[0])) {\n                this.lexer.state.inRawBlock = false;\n            }\n            return {\n                type: 'html',\n                raw: cap[0],\n                inLink: this.lexer.state.inLink,\n                inRawBlock: this.lexer.state.inRawBlock,\n                block: false,\n                text: cap[0]\n            };\n        }\n    }\n    link(src) {\n        const cap = this.rules.inline.link.exec(src);\n        if (cap) {\n            const trimmedUrl = cap[2].trim();\n            if (!this.options.pedantic && /^</.test(trimmedUrl)) {\n                // commonmark requires matching angle brackets\n                if (!(/>$/.test(trimmedUrl))) {\n                    return;\n                }\n                // ending angle bracket cannot be escaped\n                const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\\\');\n                if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {\n                    return;\n                }\n            }\n            else {\n                // find closing parenthesis\n                const lastParenIndex = findClosingBracket(cap[2], '()');\n                if (lastParenIndex > -1) {\n                    const start = cap[0].indexOf('!') === 0 ? 5 : 4;\n                    const linkLen = start + cap[1].length + lastParenIndex;\n                    cap[2] = cap[2].substring(0, lastParenIndex);\n                    cap[0] = cap[0].substring(0, linkLen).trim();\n                    cap[3] = '';\n                }\n            }\n            let href = cap[2];\n            let title = '';\n            if (this.options.pedantic) {\n                // split pedantic href and title\n                const link = /^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/.exec(href);\n                if (link) {\n                    href = link[1];\n                    title = link[3];\n                }\n            }\n            else {\n                title = cap[3] ? cap[3].slice(1, -1) : '';\n            }\n            href = href.trim();\n            if (/^</.test(href)) {\n                if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {\n                    // pedantic allows starting angle bracket without ending angle bracket\n                    href = href.slice(1);\n                }\n                else {\n                    href = href.slice(1, -1);\n                }\n            }\n            return outputLink(cap, {\n                href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,\n                title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title\n            }, cap[0], this.lexer);\n        }\n    }\n    reflink(src, links) {\n        let cap;\n        if ((cap = this.rules.inline.reflink.exec(src))\n            || (cap = this.rules.inline.nolink.exec(src))) {\n            const linkString = (cap[2] || cap[1]).replace(/\\s+/g, ' ');\n            const link = links[linkString.toLowerCase()];\n            if (!link) {\n                const text = cap[0].charAt(0);\n                return {\n                    type: 'text',\n                    raw: text,\n                    text\n                };\n            }\n            return outputLink(cap, link, cap[0], this.lexer);\n        }\n    }\n    emStrong(src, maskedSrc, prevChar = '') {\n        let match = this.rules.inline.emStrongLDelim.exec(src);\n        if (!match)\n            return;\n        // _ can't be between two alphanumerics. \\p{L}\\p{N} includes non-english alphabet/numbers as well\n        if (match[3] && prevChar.match(/[\\p{L}\\p{N}]/u))\n            return;\n        const nextChar = match[1] || match[2] || '';\n        if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {\n            // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)\n            const lLength = [...match[0]].length - 1;\n            let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;\n            const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;\n            endReg.lastIndex = 0;\n            // Clip maskedSrc to same section of string as src (move to lexer?)\n            maskedSrc = maskedSrc.slice(-1 * src.length + lLength);\n            while ((match = endReg.exec(maskedSrc)) != null) {\n                rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];\n                if (!rDelim)\n                    continue; // skip single * in __abc*abc__\n                rLength = [...rDelim].length;\n                if (match[3] || match[4]) { // found another Left Delim\n                    delimTotal += rLength;\n                    continue;\n                }\n                else if (match[5] || match[6]) { // either Left or Right Delim\n                    if (lLength % 3 && !((lLength + rLength) % 3)) {\n                        midDelimTotal += rLength;\n                        continue; // CommonMark Emphasis Rules 9-10\n                    }\n                }\n                delimTotal -= rLength;\n                if (delimTotal > 0)\n                    continue; // Haven't found enough closing delimiters\n                // Remove extra characters. *a*** -> *a*\n                rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);\n                // char length can be >1 for unicode characters;\n                const lastCharLength = [...match[0]][0].length;\n                const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);\n                // Create `em` if smallest delimiter has odd char count. *a***\n                if (Math.min(lLength, rLength) % 2) {\n                    const text = raw.slice(1, -1);\n                    return {\n                        type: 'em',\n                        raw,\n                        text,\n                        tokens: this.lexer.inlineTokens(text)\n                    };\n                }\n                // Create 'strong' if smallest delimiter has even char count. **a***\n                const text = raw.slice(2, -2);\n                return {\n                    type: 'strong',\n                    raw,\n                    text,\n                    tokens: this.lexer.inlineTokens(text)\n                };\n            }\n        }\n    }\n    codespan(src) {\n        const cap = this.rules.inline.code.exec(src);\n        if (cap) {\n            let text = cap[2].replace(/\\n/g, ' ');\n            const hasNonSpaceChars = /[^ ]/.test(text);\n            const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);\n            if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {\n                text = text.substring(1, text.length - 1);\n            }\n            text = escape$1(text, true);\n            return {\n                type: 'codespan',\n                raw: cap[0],\n                text\n            };\n        }\n    }\n    br(src) {\n        const cap = this.rules.inline.br.exec(src);\n        if (cap) {\n            return {\n                type: 'br',\n                raw: cap[0]\n            };\n        }\n    }\n    del(src) {\n        const cap = this.rules.inline.del.exec(src);\n        if (cap) {\n            return {\n                type: 'del',\n                raw: cap[0],\n                text: cap[2],\n                tokens: this.lexer.inlineTokens(cap[2])\n            };\n        }\n    }\n    autolink(src) {\n        const cap = this.rules.inline.autolink.exec(src);\n        if (cap) {\n            let text, href;\n            if (cap[2] === '@') {\n                text = escape$1(cap[1]);\n                href = 'mailto:' + text;\n            }\n            else {\n                text = escape$1(cap[1]);\n                href = text;\n            }\n            return {\n                type: 'link',\n                raw: cap[0],\n                text,\n                href,\n                tokens: [\n                    {\n                        type: 'text',\n                        raw: text,\n                        text\n                    }\n                ]\n            };\n        }\n    }\n    url(src) {\n        let cap;\n        if (cap = this.rules.inline.url.exec(src)) {\n            let text, href;\n            if (cap[2] === '@') {\n                text = escape$1(cap[0]);\n                href = 'mailto:' + text;\n            }\n            else {\n                // do extended autolink path validation\n                let prevCapZero;\n                do {\n                    prevCapZero = cap[0];\n                    cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';\n                } while (prevCapZero !== cap[0]);\n                text = escape$1(cap[0]);\n                if (cap[1] === 'www.') {\n                    href = 'http://' + cap[0];\n                }\n                else {\n                    href = cap[0];\n                }\n            }\n            return {\n                type: 'link',\n                raw: cap[0],\n                text,\n                href,\n                tokens: [\n                    {\n                        type: 'text',\n                        raw: text,\n                        text\n                    }\n                ]\n            };\n        }\n    }\n    inlineText(src) {\n        const cap = this.rules.inline.text.exec(src);\n        if (cap) {\n            let text;\n            if (this.lexer.state.inRawBlock) {\n                text = cap[0];\n            }\n            else {\n                text = escape$1(cap[0]);\n            }\n            return {\n                type: 'text',\n                raw: cap[0],\n                text\n            };\n        }\n    }\n}\n\n/**\n * Block-Level Grammar\n */\nconst newline = /^(?: *(?:\\n|$))+/;\nconst blockCode = /^( {4}[^\\n]+(?:\\n(?: *(?:\\n|$))*)?)+/;\nconst fences = /^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/;\nconst hr = /^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/;\nconst heading = /^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/;\nconst bullet = /(?:[*+-]|\\d{1,9}[.)])/;\nconst lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/)\n    .replace(/bull/g, bullet) // lists can interrupt\n    .replace(/blockCode/g, / {4}/) // indented code blocks can interrupt\n    .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n    .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n    .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n    .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n    .getRegex();\nconst _paragraph = /^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/;\nconst blockText = /^[^\\n]+/;\nconst _blockLabel = /(?!\\s*\\])(?:\\\\.|[^\\[\\]\\\\])+/;\nconst def = edit(/^ {0,3}\\[(label)\\]: *(?:\\n *)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n *)?| *\\n *)(title))? *(?:\\n+|$)/)\n    .replace('label', _blockLabel)\n    .replace('title', /(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/)\n    .getRegex();\nconst list = edit(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/)\n    .replace(/bull/g, bullet)\n    .getRegex();\nconst _tag = 'address|article|aside|base|basefont|blockquote|body|caption'\n    + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'\n    + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'\n    + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'\n    + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title'\n    + '|tr|track|ul';\nconst _comment = /<!--(?:-?>|[\\s\\S]*?(?:-->|$))/;\nconst html = edit('^ {0,3}(?:' // optional indentation\n    + '<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n+|$)' // (1)\n    + '|comment[^\\\\n]*(\\\\n+|$)' // (2)\n    + '|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)' // (3)\n    + '|<![A-Z][\\\\s\\\\S]*?(?:>\\\\n*|$)' // (4)\n    + '|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>\\\\n*|$)' // (5)\n    + '|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n *)+\\\\n|$)' // (6)\n    + '|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n *)+\\\\n|$)' // (7) open tag\n    + '|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n *)+\\\\n|$)' // (7) closing tag\n    + ')', 'i')\n    .replace('comment', _comment)\n    .replace('tag', _tag)\n    .replace('attribute', / +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/)\n    .getRegex();\nconst paragraph = edit(_paragraph)\n    .replace('hr', hr)\n    .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n    .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n    .replace('|table', '')\n    .replace('blockquote', ' {0,3}>')\n    .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n    .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n    .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n    .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n    .getRegex();\nconst blockquote = edit(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/)\n    .replace('paragraph', paragraph)\n    .getRegex();\n/**\n * Normal Block Grammar\n */\nconst blockNormal = {\n    blockquote,\n    code: blockCode,\n    def,\n    fences,\n    heading,\n    hr,\n    html,\n    lheading,\n    list,\n    newline,\n    paragraph,\n    table: noopTest,\n    text: blockText\n};\n/**\n * GFM Block Grammar\n */\nconst gfmTable = edit('^ *([^\\\\n ].*)\\\\n' // Header\n    + ' {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)' // Align\n    + '(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)') // Cells\n    .replace('hr', hr)\n    .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n    .replace('blockquote', ' {0,3}>')\n    .replace('code', ' {4}[^\\\\n]')\n    .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n    .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n    .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n    .replace('tag', _tag) // tables can be interrupted by type (6) html blocks\n    .getRegex();\nconst blockGfm = {\n    ...blockNormal,\n    table: gfmTable,\n    paragraph: edit(_paragraph)\n        .replace('hr', hr)\n        .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n        .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n        .replace('table', gfmTable) // interrupt paragraphs with table\n        .replace('blockquote', ' {0,3}>')\n        .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n        .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n        .replace('html', '</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)')\n        .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n        .getRegex()\n};\n/**\n * Pedantic grammar (original John Gruber's loose markdown specification)\n */\nconst blockPedantic = {\n    ...blockNormal,\n    html: edit('^ *(?:comment *(?:\\\\n|\\\\s*$)'\n        + '|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)' // closed tag\n        + '|<tag(?:\"[^\"]*\"|\\'[^\\']*\\'|\\\\s[^\\'\"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))')\n        .replace('comment', _comment)\n        .replace(/tag/g, '(?!(?:'\n        + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'\n        + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'\n        + '\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b')\n        .getRegex(),\n    def: /^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,\n    heading: /^(#{1,6})(.*)(?:\\n+|$)/,\n    fences: noopTest, // fences not supported\n    lheading: /^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,\n    paragraph: edit(_paragraph)\n        .replace('hr', hr)\n        .replace('heading', ' *#{1,6} *[^\\n]')\n        .replace('lheading', lheading)\n        .replace('|table', '')\n        .replace('blockquote', ' {0,3}>')\n        .replace('|fences', '')\n        .replace('|list', '')\n        .replace('|html', '')\n        .replace('|tag', '')\n        .getRegex()\n};\n/**\n * Inline-Level Grammar\n */\nconst escape = /^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/;\nconst inlineCode = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst br = /^( {2,}|\\\\)\\n(?!\\s*$)/;\nconst inlineText = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/;\n// list of unicode punctuation marks, plus any missing characters from CommonMark spec\nconst _punctuation = '\\\\p{P}\\\\p{S}';\nconst punctuation = edit(/^((?![*_])[\\spunctuation])/, 'u')\n    .replace(/punctuation/g, _punctuation).getRegex();\n// sequences em should skip over [title](link), `code`, <html>\nconst blockSkip = /\\[[^[\\]]*?\\]\\([^\\(\\)]*?\\)|`[^`]*?`|<[^<>]*?>/g;\nconst emStrongLDelim = edit(/^(?:\\*+(?:((?!\\*)[punct])|[^\\s*]))|^_+(?:((?!_)[punct])|([^\\s_]))/, 'u')\n    .replace(/punct/g, _punctuation)\n    .getRegex();\nconst emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)' // Skip orphan inside strong\n    + '|[^*]+(?=[^*])' // Consume to delim\n    + '|(?!\\\\*)[punct](\\\\*+)(?=[\\\\s]|$)' // (1) #*** can only be a Right Delimiter\n    + '|[^punct\\\\s](\\\\*+)(?!\\\\*)(?=[punct\\\\s]|$)' // (2) a***#, a*** can only be a Right Delimiter\n    + '|(?!\\\\*)[punct\\\\s](\\\\*+)(?=[^punct\\\\s])' // (3) #***a, ***a can only be Left Delimiter\n    + '|[\\\\s](\\\\*+)(?!\\\\*)(?=[punct])' // (4) ***# can only be Left Delimiter\n    + '|(?!\\\\*)[punct](\\\\*+)(?!\\\\*)(?=[punct])' // (5) #***# can be either Left or Right Delimiter\n    + '|[^punct\\\\s](\\\\*+)(?=[^punct\\\\s])', 'gu') // (6) a***a can be either Left or Right Delimiter\n    .replace(/punct/g, _punctuation)\n    .getRegex();\n// (6) Not allowed for _\nconst emStrongRDelimUnd = edit('^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)' // Skip orphan inside strong\n    + '|[^_]+(?=[^_])' // Consume to delim\n    + '|(?!_)[punct](_+)(?=[\\\\s]|$)' // (1) #___ can only be a Right Delimiter\n    + '|[^punct\\\\s](_+)(?!_)(?=[punct\\\\s]|$)' // (2) a___#, a___ can only be a Right Delimiter\n    + '|(?!_)[punct\\\\s](_+)(?=[^punct\\\\s])' // (3) #___a, ___a can only be Left Delimiter\n    + '|[\\\\s](_+)(?!_)(?=[punct])' // (4) ___# can only be Left Delimiter\n    + '|(?!_)[punct](_+)(?!_)(?=[punct])', 'gu') // (5) #___# can be either Left or Right Delimiter\n    .replace(/punct/g, _punctuation)\n    .getRegex();\nconst anyPunctuation = edit(/\\\\([punct])/, 'gu')\n    .replace(/punct/g, _punctuation)\n    .getRegex();\nconst autolink = edit(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/)\n    .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/)\n    .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/)\n    .getRegex();\nconst _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();\nconst tag = edit('^comment'\n    + '|^</[a-zA-Z][\\\\w:-]*\\\\s*>' // self-closing tag\n    + '|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>' // open tag\n    + '|^<\\\\?[\\\\s\\\\S]*?\\\\?>' // processing instruction, e.g. <?php ?>\n    + '|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>' // declaration, e.g. <!DOCTYPE html>\n    + '|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>') // CDATA section\n    .replace('comment', _inlineComment)\n    .replace('attribute', /\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/)\n    .getRegex();\nconst _inlineLabel = /(?:\\[(?:\\\\.|[^\\[\\]\\\\])*\\]|\\\\.|`[^`]*`|[^\\[\\]\\\\`])*?/;\nconst link = edit(/^!?\\[(label)\\]\\(\\s*(href)(?:\\s+(title))?\\s*\\)/)\n    .replace('label', _inlineLabel)\n    .replace('href', /<(?:\\\\.|[^\\n<>\\\\])+>|[^\\s\\x00-\\x1f]*/)\n    .replace('title', /\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/)\n    .getRegex();\nconst reflink = edit(/^!?\\[(label)\\]\\[(ref)\\]/)\n    .replace('label', _inlineLabel)\n    .replace('ref', _blockLabel)\n    .getRegex();\nconst nolink = edit(/^!?\\[(ref)\\](?:\\[\\])?/)\n    .replace('ref', _blockLabel)\n    .getRegex();\nconst reflinkSearch = edit('reflink|nolink(?!\\\\()', 'g')\n    .replace('reflink', reflink)\n    .replace('nolink', nolink)\n    .getRegex();\n/**\n * Normal Inline Grammar\n */\nconst inlineNormal = {\n    _backpedal: noopTest, // only used for GFM url\n    anyPunctuation,\n    autolink,\n    blockSkip,\n    br,\n    code: inlineCode,\n    del: noopTest,\n    emStrongLDelim,\n    emStrongRDelimAst,\n    emStrongRDelimUnd,\n    escape,\n    link,\n    nolink,\n    punctuation,\n    reflink,\n    reflinkSearch,\n    tag,\n    text: inlineText,\n    url: noopTest\n};\n/**\n * Pedantic Inline Grammar\n */\nconst inlinePedantic = {\n    ...inlineNormal,\n    link: edit(/^!?\\[(label)\\]\\((.*?)\\)/)\n        .replace('label', _inlineLabel)\n        .getRegex(),\n    reflink: edit(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/)\n        .replace('label', _inlineLabel)\n        .getRegex()\n};\n/**\n * GFM Inline Grammar\n */\nconst inlineGfm = {\n    ...inlineNormal,\n    escape: edit(escape).replace('])', '~|])').getRegex(),\n    url: edit(/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/, 'i')\n        .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)\n        .getRegex(),\n    _backpedal: /(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,\n    del: /^(~~?)(?=[^\\s~])([\\s\\S]*?[^\\s~])\\1(?=[^~]|$)/,\n    text: /^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|https?:\\/\\/|ftp:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)))/\n};\n/**\n * GFM + Line Breaks Inline Grammar\n */\nconst inlineBreaks = {\n    ...inlineGfm,\n    br: edit(br).replace('{2,}', '*').getRegex(),\n    text: edit(inlineGfm.text)\n        .replace('\\\\b_', '\\\\b_| {2,}\\\\n')\n        .replace(/\\{2,\\}/g, '*')\n        .getRegex()\n};\n/**\n * exports\n */\nconst block = {\n    normal: blockNormal,\n    gfm: blockGfm,\n    pedantic: blockPedantic\n};\nconst inline = {\n    normal: inlineNormal,\n    gfm: inlineGfm,\n    breaks: inlineBreaks,\n    pedantic: inlinePedantic\n};\n\n/**\n * Block Lexer\n */\nclass _Lexer {\n    tokens;\n    options;\n    state;\n    tokenizer;\n    inlineQueue;\n    constructor(options) {\n        // TokenList cannot be created in one go\n        this.tokens = [];\n        this.tokens.links = Object.create(null);\n        this.options = options || _defaults;\n        this.options.tokenizer = this.options.tokenizer || new _Tokenizer();\n        this.tokenizer = this.options.tokenizer;\n        this.tokenizer.options = this.options;\n        this.tokenizer.lexer = this;\n        this.inlineQueue = [];\n        this.state = {\n            inLink: false,\n            inRawBlock: false,\n            top: true\n        };\n        const rules = {\n            block: block.normal,\n            inline: inline.normal\n        };\n        if (this.options.pedantic) {\n            rules.block = block.pedantic;\n            rules.inline = inline.pedantic;\n        }\n        else if (this.options.gfm) {\n            rules.block = block.gfm;\n            if (this.options.breaks) {\n                rules.inline = inline.breaks;\n            }\n            else {\n                rules.inline = inline.gfm;\n            }\n        }\n        this.tokenizer.rules = rules;\n    }\n    /**\n     * Expose Rules\n     */\n    static get rules() {\n        return {\n            block,\n            inline\n        };\n    }\n    /**\n     * Static Lex Method\n     */\n    static lex(src, options) {\n        const lexer = new _Lexer(options);\n        return lexer.lex(src);\n    }\n    /**\n     * Static Lex Inline Method\n     */\n    static lexInline(src, options) {\n        const lexer = new _Lexer(options);\n        return lexer.inlineTokens(src);\n    }\n    /**\n     * Preprocessing\n     */\n    lex(src) {\n        src = src\n            .replace(/\\r\\n|\\r/g, '\\n');\n        this.blockTokens(src, this.tokens);\n        for (let i = 0; i < this.inlineQueue.length; i++) {\n            const next = this.inlineQueue[i];\n            this.inlineTokens(next.src, next.tokens);\n        }\n        this.inlineQueue = [];\n        return this.tokens;\n    }\n    blockTokens(src, tokens = []) {\n        if (this.options.pedantic) {\n            src = src.replace(/\\t/g, '    ').replace(/^ +$/gm, '');\n        }\n        else {\n            src = src.replace(/^( *)(\\t+)/gm, (_, leading, tabs) => {\n                return leading + '    '.repeat(tabs.length);\n            });\n        }\n        let token;\n        let lastToken;\n        let cutSrc;\n        let lastParagraphClipped;\n        while (src) {\n            if (this.options.extensions\n                && this.options.extensions.block\n                && this.options.extensions.block.some((extTokenizer) => {\n                    if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n                        src = src.substring(token.raw.length);\n                        tokens.push(token);\n                        return true;\n                    }\n                    return false;\n                })) {\n                continue;\n            }\n            // newline\n            if (token = this.tokenizer.space(src)) {\n                src = src.substring(token.raw.length);\n                if (token.raw.length === 1 && tokens.length > 0) {\n                    // if there's a single \\n as a spacer, it's terminating the last line,\n                    // so move it there so that we don't get unnecessary paragraph tags\n                    tokens[tokens.length - 1].raw += '\\n';\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            // code\n            if (token = this.tokenizer.code(src)) {\n                src = src.substring(token.raw.length);\n                lastToken = tokens[tokens.length - 1];\n                // An indented code block cannot interrupt a paragraph.\n                if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {\n                    lastToken.raw += '\\n' + token.raw;\n                    lastToken.text += '\\n' + token.text;\n                    this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            // fences\n            if (token = this.tokenizer.fences(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // heading\n            if (token = this.tokenizer.heading(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // hr\n            if (token = this.tokenizer.hr(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // blockquote\n            if (token = this.tokenizer.blockquote(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // list\n            if (token = this.tokenizer.list(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // html\n            if (token = this.tokenizer.html(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // def\n            if (token = this.tokenizer.def(src)) {\n                src = src.substring(token.raw.length);\n                lastToken = tokens[tokens.length - 1];\n                if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {\n                    lastToken.raw += '\\n' + token.raw;\n                    lastToken.text += '\\n' + token.raw;\n                    this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;\n                }\n                else if (!this.tokens.links[token.tag]) {\n                    this.tokens.links[token.tag] = {\n                        href: token.href,\n                        title: token.title\n                    };\n                }\n                continue;\n            }\n            // table (gfm)\n            if (token = this.tokenizer.table(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // lheading\n            if (token = this.tokenizer.lheading(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // top-level paragraph\n            // prevent paragraph consuming extensions by clipping 'src' to extension start\n            cutSrc = src;\n            if (this.options.extensions && this.options.extensions.startBlock) {\n                let startIndex = Infinity;\n                const tempSrc = src.slice(1);\n                let tempStart;\n                this.options.extensions.startBlock.forEach((getStartIndex) => {\n                    tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n                    if (typeof tempStart === 'number' && tempStart >= 0) {\n                        startIndex = Math.min(startIndex, tempStart);\n                    }\n                });\n                if (startIndex < Infinity && startIndex >= 0) {\n                    cutSrc = src.substring(0, startIndex + 1);\n                }\n            }\n            if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {\n                lastToken = tokens[tokens.length - 1];\n                if (lastParagraphClipped && lastToken.type === 'paragraph') {\n                    lastToken.raw += '\\n' + token.raw;\n                    lastToken.text += '\\n' + token.text;\n                    this.inlineQueue.pop();\n                    this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                lastParagraphClipped = (cutSrc.length !== src.length);\n                src = src.substring(token.raw.length);\n                continue;\n            }\n            // text\n            if (token = this.tokenizer.text(src)) {\n                src = src.substring(token.raw.length);\n                lastToken = tokens[tokens.length - 1];\n                if (lastToken && lastToken.type === 'text') {\n                    lastToken.raw += '\\n' + token.raw;\n                    lastToken.text += '\\n' + token.text;\n                    this.inlineQueue.pop();\n                    this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            if (src) {\n                const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n                if (this.options.silent) {\n                    console.error(errMsg);\n                    break;\n                }\n                else {\n                    throw new Error(errMsg);\n                }\n            }\n        }\n        this.state.top = true;\n        return tokens;\n    }\n    inline(src, tokens = []) {\n        this.inlineQueue.push({ src, tokens });\n        return tokens;\n    }\n    /**\n     * Lexing/Compiling\n     */\n    inlineTokens(src, tokens = []) {\n        let token, lastToken, cutSrc;\n        // String with links masked to avoid interference with em and strong\n        let maskedSrc = src;\n        let match;\n        let keepPrevChar, prevChar;\n        // Mask out reflinks\n        if (this.tokens.links) {\n            const links = Object.keys(this.tokens.links);\n            if (links.length > 0) {\n                while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {\n                    if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {\n                        maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);\n                    }\n                }\n            }\n        }\n        // Mask out other blocks\n        while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {\n            maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);\n        }\n        // Mask out escaped characters\n        while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {\n            maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);\n        }\n        while (src) {\n            if (!keepPrevChar) {\n                prevChar = '';\n            }\n            keepPrevChar = false;\n            // extensions\n            if (this.options.extensions\n                && this.options.extensions.inline\n                && this.options.extensions.inline.some((extTokenizer) => {\n                    if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n                        src = src.substring(token.raw.length);\n                        tokens.push(token);\n                        return true;\n                    }\n                    return false;\n                })) {\n                continue;\n            }\n            // escape\n            if (token = this.tokenizer.escape(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // tag\n            if (token = this.tokenizer.tag(src)) {\n                src = src.substring(token.raw.length);\n                lastToken = tokens[tokens.length - 1];\n                if (lastToken && token.type === 'text' && lastToken.type === 'text') {\n                    lastToken.raw += token.raw;\n                    lastToken.text += token.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            // link\n            if (token = this.tokenizer.link(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // reflink, nolink\n            if (token = this.tokenizer.reflink(src, this.tokens.links)) {\n                src = src.substring(token.raw.length);\n                lastToken = tokens[tokens.length - 1];\n                if (lastToken && token.type === 'text' && lastToken.type === 'text') {\n                    lastToken.raw += token.raw;\n                    lastToken.text += token.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            // em & strong\n            if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // code\n            if (token = this.tokenizer.codespan(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // br\n            if (token = this.tokenizer.br(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // del (gfm)\n            if (token = this.tokenizer.del(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // autolink\n            if (token = this.tokenizer.autolink(src)) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // url (gfm)\n            if (!this.state.inLink && (token = this.tokenizer.url(src))) {\n                src = src.substring(token.raw.length);\n                tokens.push(token);\n                continue;\n            }\n            // text\n            // prevent inlineText consuming extensions by clipping 'src' to extension start\n            cutSrc = src;\n            if (this.options.extensions && this.options.extensions.startInline) {\n                let startIndex = Infinity;\n                const tempSrc = src.slice(1);\n                let tempStart;\n                this.options.extensions.startInline.forEach((getStartIndex) => {\n                    tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n                    if (typeof tempStart === 'number' && tempStart >= 0) {\n                        startIndex = Math.min(startIndex, tempStart);\n                    }\n                });\n                if (startIndex < Infinity && startIndex >= 0) {\n                    cutSrc = src.substring(0, startIndex + 1);\n                }\n            }\n            if (token = this.tokenizer.inlineText(cutSrc)) {\n                src = src.substring(token.raw.length);\n                if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started\n                    prevChar = token.raw.slice(-1);\n                }\n                keepPrevChar = true;\n                lastToken = tokens[tokens.length - 1];\n                if (lastToken && lastToken.type === 'text') {\n                    lastToken.raw += token.raw;\n                    lastToken.text += token.text;\n                }\n                else {\n                    tokens.push(token);\n                }\n                continue;\n            }\n            if (src) {\n                const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n                if (this.options.silent) {\n                    console.error(errMsg);\n                    break;\n                }\n                else {\n                    throw new Error(errMsg);\n                }\n            }\n        }\n        return tokens;\n    }\n}\n\n/**\n * Renderer\n */\nclass _Renderer {\n    options;\n    constructor(options) {\n        this.options = options || _defaults;\n    }\n    code(code, infostring, escaped) {\n        const lang = (infostring || '').match(/^\\S*/)?.[0];\n        code = code.replace(/\\n$/, '') + '\\n';\n        if (!lang) {\n            return '<pre><code>'\n                + (escaped ? code : escape$1(code, true))\n                + '</code></pre>\\n';\n        }\n        return '<pre><code class=\"language-'\n            + escape$1(lang)\n            + '\">'\n            + (escaped ? code : escape$1(code, true))\n            + '</code></pre>\\n';\n    }\n    blockquote(quote) {\n        return `<blockquote>\\n${quote}</blockquote>\\n`;\n    }\n    html(html, block) {\n        return html;\n    }\n    heading(text, level, raw) {\n        // ignore IDs\n        return `<h${level}>${text}</h${level}>\\n`;\n    }\n    hr() {\n        return '<hr>\\n';\n    }\n    list(body, ordered, start) {\n        const type = ordered ? 'ol' : 'ul';\n        const startatt = (ordered && start !== 1) ? (' start=\"' + start + '\"') : '';\n        return '<' + type + startatt + '>\\n' + body + '</' + type + '>\\n';\n    }\n    listitem(text, task, checked) {\n        return `<li>${text}</li>\\n`;\n    }\n    checkbox(checked) {\n        return '<input '\n            + (checked ? 'checked=\"\" ' : '')\n            + 'disabled=\"\" type=\"checkbox\">';\n    }\n    paragraph(text) {\n        return `<p>${text}</p>\\n`;\n    }\n    table(header, body) {\n        if (body)\n            body = `<tbody>${body}</tbody>`;\n        return '<table>\\n'\n            + '<thead>\\n'\n            + header\n            + '</thead>\\n'\n            + body\n            + '</table>\\n';\n    }\n    tablerow(content) {\n        return `<tr>\\n${content}</tr>\\n`;\n    }\n    tablecell(content, flags) {\n        const type = flags.header ? 'th' : 'td';\n        const tag = flags.align\n            ? `<${type} align=\"${flags.align}\">`\n            : `<${type}>`;\n        return tag + content + `</${type}>\\n`;\n    }\n    /**\n     * span level renderer\n     */\n    strong(text) {\n        return `<strong>${text}</strong>`;\n    }\n    em(text) {\n        return `<em>${text}</em>`;\n    }\n    codespan(text) {\n        return `<code>${text}</code>`;\n    }\n    br() {\n        return '<br>';\n    }\n    del(text) {\n        return `<del>${text}</del>`;\n    }\n    link(href, title, text) {\n        const cleanHref = cleanUrl(href);\n        if (cleanHref === null) {\n            return text;\n        }\n        href = cleanHref;\n        let out = '<a href=\"' + href + '\"';\n        if (title) {\n            out += ' title=\"' + title + '\"';\n        }\n        out += '>' + text + '</a>';\n        return out;\n    }\n    image(href, title, text) {\n        const cleanHref = cleanUrl(href);\n        if (cleanHref === null) {\n            return text;\n        }\n        href = cleanHref;\n        let out = `<img src=\"${href}\" alt=\"${text}\"`;\n        if (title) {\n            out += ` title=\"${title}\"`;\n        }\n        out += '>';\n        return out;\n    }\n    text(text) {\n        return text;\n    }\n}\n\n/**\n * TextRenderer\n * returns only the textual part of the token\n */\nclass _TextRenderer {\n    // no need for block level renderers\n    strong(text) {\n        return text;\n    }\n    em(text) {\n        return text;\n    }\n    codespan(text) {\n        return text;\n    }\n    del(text) {\n        return text;\n    }\n    html(text) {\n        return text;\n    }\n    text(text) {\n        return text;\n    }\n    link(href, title, text) {\n        return '' + text;\n    }\n    image(href, title, text) {\n        return '' + text;\n    }\n    br() {\n        return '';\n    }\n}\n\n/**\n * Parsing & Compiling\n */\nclass _Parser {\n    options;\n    renderer;\n    textRenderer;\n    constructor(options) {\n        this.options = options || _defaults;\n        this.options.renderer = this.options.renderer || new _Renderer();\n        this.renderer = this.options.renderer;\n        this.renderer.options = this.options;\n        this.textRenderer = new _TextRenderer();\n    }\n    /**\n     * Static Parse Method\n     */\n    static parse(tokens, options) {\n        const parser = new _Parser(options);\n        return parser.parse(tokens);\n    }\n    /**\n     * Static Parse Inline Method\n     */\n    static parseInline(tokens, options) {\n        const parser = new _Parser(options);\n        return parser.parseInline(tokens);\n    }\n    /**\n     * Parse Loop\n     */\n    parse(tokens, top = true) {\n        let out = '';\n        for (let i = 0; i < tokens.length; i++) {\n            const token = tokens[i];\n            // Run any renderer extensions\n            if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {\n                const genericToken = token;\n                const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);\n                if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {\n                    out += ret || '';\n                    continue;\n                }\n            }\n            switch (token.type) {\n                case 'space': {\n                    continue;\n                }\n                case 'hr': {\n                    out += this.renderer.hr();\n                    continue;\n                }\n                case 'heading': {\n                    const headingToken = token;\n                    out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));\n                    continue;\n                }\n                case 'code': {\n                    const codeToken = token;\n                    out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped);\n                    continue;\n                }\n                case 'table': {\n                    const tableToken = token;\n                    let header = '';\n                    // header\n                    let cell = '';\n                    for (let j = 0; j < tableToken.header.length; j++) {\n                        cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });\n                    }\n                    header += this.renderer.tablerow(cell);\n                    let body = '';\n                    for (let j = 0; j < tableToken.rows.length; j++) {\n                        const row = tableToken.rows[j];\n                        cell = '';\n                        for (let k = 0; k < row.length; k++) {\n                            cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });\n                        }\n                        body += this.renderer.tablerow(cell);\n                    }\n                    out += this.renderer.table(header, body);\n                    continue;\n                }\n                case 'blockquote': {\n                    const blockquoteToken = token;\n                    const body = this.parse(blockquoteToken.tokens);\n                    out += this.renderer.blockquote(body);\n                    continue;\n                }\n                case 'list': {\n                    const listToken = token;\n                    const ordered = listToken.ordered;\n                    const start = listToken.start;\n                    const loose = listToken.loose;\n                    let body = '';\n                    for (let j = 0; j < listToken.items.length; j++) {\n                        const item = listToken.items[j];\n                        const checked = item.checked;\n                        const task = item.task;\n                        let itemBody = '';\n                        if (item.task) {\n                            const checkbox = this.renderer.checkbox(!!checked);\n                            if (loose) {\n                                if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {\n                                    item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;\n                                    if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {\n                                        item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;\n                                    }\n                                }\n                                else {\n                                    item.tokens.unshift({\n                                        type: 'text',\n                                        text: checkbox + ' '\n                                    });\n                                }\n                            }\n                            else {\n                                itemBody += checkbox + ' ';\n                            }\n                        }\n                        itemBody += this.parse(item.tokens, loose);\n                        body += this.renderer.listitem(itemBody, task, !!checked);\n                    }\n                    out += this.renderer.list(body, ordered, start);\n                    continue;\n                }\n                case 'html': {\n                    const htmlToken = token;\n                    out += this.renderer.html(htmlToken.text, htmlToken.block);\n                    continue;\n                }\n                case 'paragraph': {\n                    const paragraphToken = token;\n                    out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));\n                    continue;\n                }\n                case 'text': {\n                    let textToken = token;\n                    let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;\n                    while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {\n                        textToken = tokens[++i];\n                        body += '\\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);\n                    }\n                    out += top ? this.renderer.paragraph(body) : body;\n                    continue;\n                }\n                default: {\n                    const errMsg = 'Token with \"' + token.type + '\" type was not found.';\n                    if (this.options.silent) {\n                        console.error(errMsg);\n                        return '';\n                    }\n                    else {\n                        throw new Error(errMsg);\n                    }\n                }\n            }\n        }\n        return out;\n    }\n    /**\n     * Parse Inline Tokens\n     */\n    parseInline(tokens, renderer) {\n        renderer = renderer || this.renderer;\n        let out = '';\n        for (let i = 0; i < tokens.length; i++) {\n            const token = tokens[i];\n            // Run any renderer extensions\n            if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {\n                const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);\n                if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {\n                    out += ret || '';\n                    continue;\n                }\n            }\n            switch (token.type) {\n                case 'escape': {\n                    const escapeToken = token;\n                    out += renderer.text(escapeToken.text);\n                    break;\n                }\n                case 'html': {\n                    const tagToken = token;\n                    out += renderer.html(tagToken.text);\n                    break;\n                }\n                case 'link': {\n                    const linkToken = token;\n                    out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));\n                    break;\n                }\n                case 'image': {\n                    const imageToken = token;\n                    out += renderer.image(imageToken.href, imageToken.title, imageToken.text);\n                    break;\n                }\n                case 'strong': {\n                    const strongToken = token;\n                    out += renderer.strong(this.parseInline(strongToken.tokens, renderer));\n                    break;\n                }\n                case 'em': {\n                    const emToken = token;\n                    out += renderer.em(this.parseInline(emToken.tokens, renderer));\n                    break;\n                }\n                case 'codespan': {\n                    const codespanToken = token;\n                    out += renderer.codespan(codespanToken.text);\n                    break;\n                }\n                case 'br': {\n                    out += renderer.br();\n                    break;\n                }\n                case 'del': {\n                    const delToken = token;\n                    out += renderer.del(this.parseInline(delToken.tokens, renderer));\n                    break;\n                }\n                case 'text': {\n                    const textToken = token;\n                    out += renderer.text(textToken.text);\n                    break;\n                }\n                default: {\n                    const errMsg = 'Token with \"' + token.type + '\" type was not found.';\n                    if (this.options.silent) {\n                        console.error(errMsg);\n                        return '';\n                    }\n                    else {\n                        throw new Error(errMsg);\n                    }\n                }\n            }\n        }\n        return out;\n    }\n}\n\nclass _Hooks {\n    options;\n    constructor(options) {\n        this.options = options || _defaults;\n    }\n    static passThroughHooks = new Set([\n        'preprocess',\n        'postprocess',\n        'processAllTokens'\n    ]);\n    /**\n     * Process markdown before marked\n     */\n    preprocess(markdown) {\n        return markdown;\n    }\n    /**\n     * Process HTML after marked is finished\n     */\n    postprocess(html) {\n        return html;\n    }\n    /**\n     * Process all tokens before walk tokens\n     */\n    processAllTokens(tokens) {\n        return tokens;\n    }\n}\n\nclass Marked {\n    defaults = _getDefaults();\n    options = this.setOptions;\n    parse = this.#parseMarkdown(_Lexer.lex, _Parser.parse);\n    parseInline = this.#parseMarkdown(_Lexer.lexInline, _Parser.parseInline);\n    Parser = _Parser;\n    Renderer = _Renderer;\n    TextRenderer = _TextRenderer;\n    Lexer = _Lexer;\n    Tokenizer = _Tokenizer;\n    Hooks = _Hooks;\n    constructor(...args) {\n        this.use(...args);\n    }\n    /**\n     * Run callback for every token\n     */\n    walkTokens(tokens, callback) {\n        let values = [];\n        for (const token of tokens) {\n            values = values.concat(callback.call(this, token));\n            switch (token.type) {\n                case 'table': {\n                    const tableToken = token;\n                    for (const cell of tableToken.header) {\n                        values = values.concat(this.walkTokens(cell.tokens, callback));\n                    }\n                    for (const row of tableToken.rows) {\n                        for (const cell of row) {\n                            values = values.concat(this.walkTokens(cell.tokens, callback));\n                        }\n                    }\n                    break;\n                }\n                case 'list': {\n                    const listToken = token;\n                    values = values.concat(this.walkTokens(listToken.items, callback));\n                    break;\n                }\n                default: {\n                    const genericToken = token;\n                    if (this.defaults.extensions?.childTokens?.[genericToken.type]) {\n                        this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {\n                            const tokens = genericToken[childTokens].flat(Infinity);\n                            values = values.concat(this.walkTokens(tokens, callback));\n                        });\n                    }\n                    else if (genericToken.tokens) {\n                        values = values.concat(this.walkTokens(genericToken.tokens, callback));\n                    }\n                }\n            }\n        }\n        return values;\n    }\n    use(...args) {\n        const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };\n        args.forEach((pack) => {\n            // copy options to new object\n            const opts = { ...pack };\n            // set async to true if it was set to true before\n            opts.async = this.defaults.async || opts.async || false;\n            // ==-- Parse \"addon\" extensions --== //\n            if (pack.extensions) {\n                pack.extensions.forEach((ext) => {\n                    if (!ext.name) {\n                        throw new Error('extension name required');\n                    }\n                    if ('renderer' in ext) { // Renderer extensions\n                        const prevRenderer = extensions.renderers[ext.name];\n                        if (prevRenderer) {\n                            // Replace extension with func to run new extension but fall back if false\n                            extensions.renderers[ext.name] = function (...args) {\n                                let ret = ext.renderer.apply(this, args);\n                                if (ret === false) {\n                                    ret = prevRenderer.apply(this, args);\n                                }\n                                return ret;\n                            };\n                        }\n                        else {\n                            extensions.renderers[ext.name] = ext.renderer;\n                        }\n                    }\n                    if ('tokenizer' in ext) { // Tokenizer Extensions\n                        if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {\n                            throw new Error(\"extension level must be 'block' or 'inline'\");\n                        }\n                        const extLevel = extensions[ext.level];\n                        if (extLevel) {\n                            extLevel.unshift(ext.tokenizer);\n                        }\n                        else {\n                            extensions[ext.level] = [ext.tokenizer];\n                        }\n                        if (ext.start) { // Function to check for start of token\n                            if (ext.level === 'block') {\n                                if (extensions.startBlock) {\n                                    extensions.startBlock.push(ext.start);\n                                }\n                                else {\n                                    extensions.startBlock = [ext.start];\n                                }\n                            }\n                            else if (ext.level === 'inline') {\n                                if (extensions.startInline) {\n                                    extensions.startInline.push(ext.start);\n                                }\n                                else {\n                                    extensions.startInline = [ext.start];\n                                }\n                            }\n                        }\n                    }\n                    if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens\n                        extensions.childTokens[ext.name] = ext.childTokens;\n                    }\n                });\n                opts.extensions = extensions;\n            }\n            // ==-- Parse \"overwrite\" extensions --== //\n            if (pack.renderer) {\n                const renderer = this.defaults.renderer || new _Renderer(this.defaults);\n                for (const prop in pack.renderer) {\n                    if (!(prop in renderer)) {\n                        throw new Error(`renderer '${prop}' does not exist`);\n                    }\n                    if (prop === 'options') {\n                        // ignore options property\n                        continue;\n                    }\n                    const rendererProp = prop;\n                    const rendererFunc = pack.renderer[rendererProp];\n                    const prevRenderer = renderer[rendererProp];\n                    // Replace renderer with func to run extension, but fall back if false\n                    renderer[rendererProp] = (...args) => {\n                        let ret = rendererFunc.apply(renderer, args);\n                        if (ret === false) {\n                            ret = prevRenderer.apply(renderer, args);\n                        }\n                        return ret || '';\n                    };\n                }\n                opts.renderer = renderer;\n            }\n            if (pack.tokenizer) {\n                const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);\n                for (const prop in pack.tokenizer) {\n                    if (!(prop in tokenizer)) {\n                        throw new Error(`tokenizer '${prop}' does not exist`);\n                    }\n                    if (['options', 'rules', 'lexer'].includes(prop)) {\n                        // ignore options, rules, and lexer properties\n                        continue;\n                    }\n                    const tokenizerProp = prop;\n                    const tokenizerFunc = pack.tokenizer[tokenizerProp];\n                    const prevTokenizer = tokenizer[tokenizerProp];\n                    // Replace tokenizer with func to run extension, but fall back if false\n                    // @ts-expect-error cannot type tokenizer function dynamically\n                    tokenizer[tokenizerProp] = (...args) => {\n                        let ret = tokenizerFunc.apply(tokenizer, args);\n                        if (ret === false) {\n                            ret = prevTokenizer.apply(tokenizer, args);\n                        }\n                        return ret;\n                    };\n                }\n                opts.tokenizer = tokenizer;\n            }\n            // ==-- Parse Hooks extensions --== //\n            if (pack.hooks) {\n                const hooks = this.defaults.hooks || new _Hooks();\n                for (const prop in pack.hooks) {\n                    if (!(prop in hooks)) {\n                        throw new Error(`hook '${prop}' does not exist`);\n                    }\n                    if (prop === 'options') {\n                        // ignore options property\n                        continue;\n                    }\n                    const hooksProp = prop;\n                    const hooksFunc = pack.hooks[hooksProp];\n                    const prevHook = hooks[hooksProp];\n                    if (_Hooks.passThroughHooks.has(prop)) {\n                        // @ts-expect-error cannot type hook function dynamically\n                        hooks[hooksProp] = (arg) => {\n                            if (this.defaults.async) {\n                                return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {\n                                    return prevHook.call(hooks, ret);\n                                });\n                            }\n                            const ret = hooksFunc.call(hooks, arg);\n                            return prevHook.call(hooks, ret);\n                        };\n                    }\n                    else {\n                        // @ts-expect-error cannot type hook function dynamically\n                        hooks[hooksProp] = (...args) => {\n                            let ret = hooksFunc.apply(hooks, args);\n                            if (ret === false) {\n                                ret = prevHook.apply(hooks, args);\n                            }\n                            return ret;\n                        };\n                    }\n                }\n                opts.hooks = hooks;\n            }\n            // ==-- Parse WalkTokens extensions --== //\n            if (pack.walkTokens) {\n                const walkTokens = this.defaults.walkTokens;\n                const packWalktokens = pack.walkTokens;\n                opts.walkTokens = function (token) {\n                    let values = [];\n                    values.push(packWalktokens.call(this, token));\n                    if (walkTokens) {\n                        values = values.concat(walkTokens.call(this, token));\n                    }\n                    return values;\n                };\n            }\n            this.defaults = { ...this.defaults, ...opts };\n        });\n        return this;\n    }\n    setOptions(opt) {\n        this.defaults = { ...this.defaults, ...opt };\n        return this;\n    }\n    lexer(src, options) {\n        return _Lexer.lex(src, options ?? this.defaults);\n    }\n    parser(tokens, options) {\n        return _Parser.parse(tokens, options ?? this.defaults);\n    }\n    #parseMarkdown(lexer, parser) {\n        return (src, options) => {\n            const origOpt = { ...options };\n            const opt = { ...this.defaults, ...origOpt };\n            // Show warning if an extension set async to true but the parse was called with async: false\n            if (this.defaults.async === true && origOpt.async === false) {\n                if (!opt.silent) {\n                    console.warn('marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored.');\n                }\n                opt.async = true;\n            }\n            const throwError = this.#onError(!!opt.silent, !!opt.async);\n            // throw error in case of non string input\n            if (typeof src === 'undefined' || src === null) {\n                return throwError(new Error('marked(): input parameter is undefined or null'));\n            }\n            if (typeof src !== 'string') {\n                return throwError(new Error('marked(): input parameter is of type '\n                    + Object.prototype.toString.call(src) + ', string expected'));\n            }\n            if (opt.hooks) {\n                opt.hooks.options = opt;\n            }\n            if (opt.async) {\n                return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)\n                    .then(src => lexer(src, opt))\n                    .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens)\n                    .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)\n                    .then(tokens => parser(tokens, opt))\n                    .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)\n                    .catch(throwError);\n            }\n            try {\n                if (opt.hooks) {\n                    src = opt.hooks.preprocess(src);\n                }\n                let tokens = lexer(src, opt);\n                if (opt.hooks) {\n                    tokens = opt.hooks.processAllTokens(tokens);\n                }\n                if (opt.walkTokens) {\n                    this.walkTokens(tokens, opt.walkTokens);\n                }\n                let html = parser(tokens, opt);\n                if (opt.hooks) {\n                    html = opt.hooks.postprocess(html);\n                }\n                return html;\n            }\n            catch (e) {\n                return throwError(e);\n            }\n        };\n    }\n    #onError(silent, async) {\n        return (e) => {\n            e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n            if (silent) {\n                const msg = '<p>An error occurred:</p><pre>'\n                    + escape$1(e.message + '', true)\n                    + '</pre>';\n                if (async) {\n                    return Promise.resolve(msg);\n                }\n                return msg;\n            }\n            if (async) {\n                return Promise.reject(e);\n            }\n            throw e;\n        };\n    }\n}\n\nconst markedInstance = new Marked();\nfunction marked(src, opt) {\n    return markedInstance.parse(src, opt);\n}\n/**\n * Sets the default options.\n *\n * @param options Hash of options\n */\nmarked.options =\n    marked.setOptions = function (options) {\n        markedInstance.setOptions(options);\n        marked.defaults = markedInstance.defaults;\n        changeDefaults(marked.defaults);\n        return marked;\n    };\n/**\n * Gets the original marked default options.\n */\nmarked.getDefaults = _getDefaults;\nmarked.defaults = _defaults;\n/**\n * Use Extension\n */\nmarked.use = function (...args) {\n    markedInstance.use(...args);\n    marked.defaults = markedInstance.defaults;\n    changeDefaults(marked.defaults);\n    return marked;\n};\n/**\n * Run callback for every token\n */\nmarked.walkTokens = function (tokens, callback) {\n    return markedInstance.walkTokens(tokens, callback);\n};\n/**\n * Compiles markdown to HTML without enclosing `p` tag.\n *\n * @param src String of markdown source to be compiled\n * @param options Hash of options\n * @return String of compiled HTML\n */\nmarked.parseInline = markedInstance.parseInline;\n/**\n * Expose\n */\nmarked.Parser = _Parser;\nmarked.parser = _Parser.parse;\nmarked.Renderer = _Renderer;\nmarked.TextRenderer = _TextRenderer;\nmarked.Lexer = _Lexer;\nmarked.lexer = _Lexer.lex;\nmarked.Tokenizer = _Tokenizer;\nmarked.Hooks = _Hooks;\nmarked.parse = marked;\nconst options = marked.options;\nconst setOptions = marked.setOptions;\nconst use = marked.use;\nconst walkTokens = marked.walkTokens;\nconst parseInline = marked.parseInline;\nconst parse = marked;\nconst parser = _Parser.parse;\nconst lexer = _Lexer.lex;\n\nexport { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };\n//# sourceMappingURL=marked.esm.js.map\n","import angular from \"angular\";\r\nimport { marked } from \"marked\";\r\nimport { Translations } from \"@salaxy/core\";\r\n\r\n/**\r\n * Directive for binding html for the element.\r\n * The attribute sxy-html should contain the translation key for the html content.\r\n * This directive should be used instead of the AngularJs ng-bind-html element.\r\n * Interpolation parameters for translation can be given using params -attribute.\r\n * @example\r\n * ```html\r\n * <p class=\"lead\" sxy-html=\"SALAXY.NG1.UserInfoComponent.description.html\" ></p>\r\n * ```\r\n */\r\nexport class HtmlDirective implements angular.IDirective {\r\n\r\n    /**\r\n     * Factory method for the directive creation.\r\n     * @ignore\r\n     */\r\n    public static sxyHtml(): any {\r\n        const factory = ($sce: angular.ISCEService) => new HtmlDirective($sce);\r\n        factory.$inject = [\"$sce\"];\r\n        return factory;\r\n    }\r\n\r\n    /**\r\n     * Directive restrictions.\r\n     * @ignore\r\n     */\r\n    public restrict = \"A\";\r\n\r\n   /**\r\n    * Creates a new instance of the directive.\r\n    */\r\n    constructor(private $sce: angular.ISCEService) {\r\n    }\r\n\r\n   /**\r\n    * Compile function for the directive.\r\n    * @ignore\r\n    */\r\n    public compile(cElement: any, cAttr: any): any { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n      return  (scope: any, element: any, attr: any) => {\r\n\r\n        const endsWith = (str1: string, str2: string) => {\r\n          return str1.substring(str1.length - str2.length, str1.length) === str2;\r\n        };\r\n\r\n        const params = () => scope.$eval(attr.params);\r\n        const sxyHtml = () => attr.sxyHtml;\r\n\r\n        scope.$watch( () => sxyHtml() + JSON.stringify(params()), () => {\r\n          let html = Translations.get(sxyHtml(), params());\r\n          if (endsWith(sxyHtml(), \".md\")) {\r\n            html = marked(html) as string;\r\n          }\r\n          element.html(this.$sce.getTrustedHtml(html));\r\n        });\r\n      };\r\n    }\r\n}\r\n","import angular from \"angular\";\r\nimport { Translations } from \"@salaxy/core\";\r\n\r\n/**\r\n * Directive for binding text for the element.\r\n * The attribute sxy-text should contain the translation key for the text content.\r\n * This directive should be used to replace AngularJS expression and translation pipe filter.\r\n * Small additions to the beginning and end can be added with pre and ps attributes.\r\n * Interpolation parameters for translation can be given using params -attribute.\r\n * @example\r\n * ```html\r\n * <div sxy-text=\"SALAXY.NG1.UserInfoComponent.authType\" ps=\":\" pre=\"HUOM: \"></div>\r\n * ```\r\n */\r\nexport class TextDirective implements angular.IDirective {\r\n\r\n  /**\r\n   * Factory method for the directive creation.\r\n   * @ignore\r\n   */\r\n  public static sxyText(): any {\r\n    const factory = () => new TextDirective();\r\n    return factory;\r\n  }\r\n\r\n  /**\r\n   * Directive restrictions.\r\n   * @ignore\r\n   */\r\n  public restrict = \"A\";\r\n\r\n\r\n  /**\r\n   * Compile function for the directive.\r\n   * @ignore\r\n   */\r\n  public compile(cElement: any, cAttr: any): any { // eslint-disable-line @typescript-eslint/no-unused-vars\r\n    return (scope: any, element: any, attr: any) => {\r\n      // Translation which preserver whitespace\r\n      const wsTranslate = (key: string, interpolateParams?: any) => {\r\n        const text = Translations.get(key, interpolateParams);\r\n        if (key.trim() ===  text) {\r\n          return key;\r\n        }\r\n        return text;\r\n      };\r\n\r\n      // Returns the untrimmed attribute value (as opposite to attr)\r\n      const getUntrimmedAttributeValue = (name: string) => {\r\n        return (element[0].attributes[name] || {value: \"\"} ).value;\r\n      };\r\n\r\n      const params = () => scope.$eval(attr.params);\r\n\r\n      scope.$watch(() => getUntrimmedAttributeValue(\"pre\") + getUntrimmedAttributeValue(\"sxy-text\") + JSON.stringify(params()) + getUntrimmedAttributeValue(\"ps\"), () => {\r\n        element.text(wsTranslate(getUntrimmedAttributeValue(\"pre\")) + wsTranslate( getUntrimmedAttributeValue(\"sxy-text\"), params()) + wsTranslate(getUntrimmedAttributeValue(\"ps\")));\r\n      });\r\n    };\r\n  }\r\n}\r\n","import {\r\n  AppendNodeDirective,\r\n  Bs5,\r\n  DatepickerInputValidationDirective,\r\n  EnumParserFunctions,\r\n  HtmlDirective,\r\n  IfRoleDirective,\r\n  IfSitemapDirective,\r\n  LoaderDirective,\r\n  OrderbyDirective,\r\n  TextDirective,\r\n  ValidatorFunctions,\r\n} from \".\";\r\n\r\n/**\r\n * Provides methods for registering the Directives to module\r\n * (and other related metadata in the future).\r\n */\r\nexport class DirectivesRegistration {\r\n\r\n  /** Gets the directives for Module registration. */\r\n  public static getDirectives() {\r\n    return {\r\n      // TODO: Remove depency to directives starting with \"salaxy-\" => \"sxy-\".\r\n      salaxyIfRole: IfRoleDirective.sxyIfRole(),\r\n      // TODO: Go through: are these needed? If so => \"sxy-\"\r\n      salaxyAppendNode: AppendNodeDirective.salaxyAppendNode(), // Useful? Used in tabs, are tabs really used?\r\n      salaxyDatepickerInputValidation: DatepickerInputValidationDirective.salaxyDatepickerInputValidation(), // Could this be in ValidatorFunctions or is there special functionality? This is used only in date picker.\r\n      // TODO: Move as <salaxy-loader> component instead of directive (removes unnecessary HTML from the views).\r\n      //       Also evaluate relation to salaxy-spinner: There should be only one if possible with different layout options.\r\n      salaxyLoader: LoaderDirective.salaxyLoader(),\r\n\r\n      // All new directives should start with \"sxy-\"\r\n      sxyBs5: Bs5.salaxyBs5(),\r\n      sxyIfRole: IfRoleDirective.sxyIfRole(),\r\n      sxyIfSitemap: IfSitemapDirective.sxyIfSitemap(),\r\n      sxyOrderby: OrderbyDirective.sxyOrderby(),\r\n      // Validator functions\r\n      sxyTaxPercent: ValidatorFunctions.sxyTaxPercent(),\r\n      sxyCurrency: ValidatorFunctions.sxyCurrency(),\r\n      sxyIban: ValidatorFunctions.sxyIban(),\r\n      sxyEmail: ValidatorFunctions.sxyEmail(),\r\n      sxyEnumAsBoolean: EnumParserFunctions.sxyEnumAsBoolean(),\r\n      sxyMobilePhone: ValidatorFunctions.sxyMobilePhone(),\r\n      sxyExcludeUnknowns: ValidatorFunctions.sxyExcludeUnknowns(),\r\n      sxyBankReferenceFi: ValidatorFunctions.sxyBankReferenceFi(),\r\n      sxyPersonalIdFi: ValidatorFunctions.sxyPersonalIdFi(),\r\n      sxyCompanyIdFi: ValidatorFunctions.sxyCompanyIdFi(),\r\n      sxyOfficialIdFi: ValidatorFunctions.sxyOfficialIdFi(),\r\n      sxyPostalCodeFi: ValidatorFunctions.sxyPostalCodeFi(),\r\n      sxyNumber: ValidatorFunctions.sxyNumber(),\r\n      sxyInteger: ValidatorFunctions.sxyInteger(),\r\n      sxyMax: ValidatorFunctions.sxyMax(),\r\n      sxyMin: ValidatorFunctions.sxyMin(),\r\n      sxyMultipleOf: ValidatorFunctions.sxyMultipleOf(),\r\n      sxyPensionContractNumber: ValidatorFunctions.sxyPensionContractNumber(),\r\n      sxyHtml: HtmlDirective.sxyHtml(),\r\n      sxyText: TextDirective.sxyText(),\r\n    };\r\n  }\r\n}\r\n","\r\nimport { marked } from \"marked\";\r\n\r\nimport {\r\n  ApiListItem,\r\n  CalcInfo,\r\n  CalcRowsLogic,\r\n  DatelyObject,\r\n  DateRange,\r\n  Dates,\r\n  DateTimes,\r\n  EmploymentData,\r\n  EnumerationsLogic,\r\n  Iban,\r\n  Numeric,\r\n  Occupations,\r\n  Role,\r\n  SitemapNode,\r\n  SystemRole,\r\n  Translations,\r\n  Unit\r\n} from \"@salaxy/core\";\r\n\r\nimport { NaviService, SessionService } from \"../services\";\r\nimport { SitemapHelper } from \"../helpers\";\r\n\r\n/**\r\n * Contains the simple filter functions where implementation\r\n * is in some other class (typically @salaxy/core) and thus the filter implementation is very small.\r\n * This should typically the case, but some filters may contain a lot of NG1 specific\r\n * implementation (e.g. SalaxyTranslateFilter) and/or dependency injection and thus deserve their own class.\r\n */\r\nexport class FilterFunctions {\r\n\r\n  /**\r\n   * Formats a Workflow message string from index.\r\n   * List of allowed message types can be given as a comma seprated list.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - messageString: Workflow message\r\n   * - types: Allowed message types.\r\n   */\r\n  public static sxyWorkflowMessage = [\"$sce\", ($sce: angular.ISCEService) => {\r\n    return (messageString: string, types: string) => {\r\n      if (!messageString) {\r\n        return $sce.getTrustedHtml(\"<span></span>\");\r\n      }\r\n      const messageTypes = (types || \"\").split(\",\");\r\n      const uiClassMarker = messageString.indexOf(\"(Ui\");\r\n      const uiClassEndMarker = messageString.indexOf(\"):\", uiClassMarker + 3);\r\n      const type = (messageString.substring(0, uiClassMarker - 1) || \"UnknownEvent\");\r\n\r\n      if (messageTypes.length > 0) {\r\n        if (!messageTypes.some((x) => x.trim() === type)) {\r\n          return $sce.getTrustedHtml(\"<span></span>\");\r\n        }\r\n      }\r\n\r\n      const uiClass = messageString.substring(uiClassMarker + 3, uiClassEndMarker).toLowerCase();\r\n      let fullMessage = messageString.substring(uiClassEndMarker + 3);\r\n      const dtReg = /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):([0-5][0-9])/g;\r\n      fullMessage = fullMessage.replace(dtReg, (match: string, year, month, day, hours, minutes) => {\r\n        const d = Date.UTC(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10), parseInt(hours, 10), parseInt(minutes, 10));\r\n        return Dates.format(d,\"D.M.YYYY HH:mm\");\r\n      });\r\n      const shortMessage = fullMessage.substring(0, fullMessage.lastIndexOf(\"(\"));\r\n      return $sce.getTrustedHtml(`<span class=\"badge bg-${uiClass}\" title=\"${fullMessage}\">${shortMessage}</span>`);\r\n    };\r\n  }];\r\n\r\n  public static sxyShow = [\"NaviService\", (naviService: NaviService) => {\r\n    return (sectionToCheck: string, sitemapPath: string): boolean => {\r\n      if(!sectionToCheck || !sitemapPath) {\r\n        return true;\r\n      }\r\n      const splitPaths = sitemapPath.split(\".\");\r\n      let sitemap: SitemapNode[] = naviService.getSitemap();\r\n      const companySite = sitemap.find(node => node.id === \"company-site\");\r\n      if (companySite) {\r\n          sitemap = [companySite];\r\n      }\r\n      let resultSitemapNode: SitemapNode;\r\n      if(splitPaths.length >= 3) {\r\n        let currentSection: SitemapNode[] = sitemap;\r\n        for (const path of splitPaths) {\r\n          const section = SitemapHelper.getSection(currentSection, path);\r\n          if (path === splitPaths[splitPaths.length - 1]) {\r\n              resultSitemapNode = section;\r\n          } else {\r\n              currentSection = section.children;\r\n          }\r\n      }\r\n      } else if(splitPaths.length === 2) {\r\n        resultSitemapNode = SitemapHelper.getNode(sitemap, splitPaths[0], splitPaths[1]);\r\n      } else {\r\n        resultSitemapNode = SitemapHelper.getSection(sitemap, splitPaths[0]);\r\n      }\r\n      if(resultSitemapNode) {\r\n        return !(resultSitemapNode?.hidden ?? []).includes(sectionToCheck);\r\n      }\r\n      return true;\r\n    };\r\n  }];\r\n\r\n  /**\r\n   * Translate filter with key and interpolation parameter.\r\n   * Converts content with translationId ending with '.html', to safe html.\r\n   * Converts content with translationId ending with '.md', first to html and then to safe html.\r\n   * If the text contains a variable placeholder like: 'Hello {{name}}!', it will be replaced by given parameter.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - translationId: Translation key\r\n   * - interpolateParams: Interpolation parameters applied if text had interpolation.\r\n   * @example\r\n   * ```html\r\n   * <p sxy-text=\"SALAXY.NG1.test1\"></p>\r\n   * <p>{{ 'SALAXY.NG1.hello' | sxyTranslate: { name: 'John'} }}</p>\r\n   * ```\r\n   */\r\n  public static sxyTranslate = [\"$sce\", ($sce: angular.ISCEService) => {\r\n    return (translationId: string, interpolateParams: any): string => {\r\n      const endsWith = (str1: string, str2: string) => {\r\n        return str1.substring(str1.length - str2.length, str1.length) === str2;\r\n      };\r\n      const str = Translations.get(translationId, interpolateParams) as string;\r\n      if (translationId) {\r\n        if (endsWith(translationId, \".html\")) {\r\n          return $sce.getTrustedHtml(str);\r\n        } else if (endsWith(translationId, \".md\")) {\r\n          return $sce.getTrustedHtml(marked(str));\r\n        }\r\n      }\r\n      return str;\r\n    };\r\n  }];\r\n\r\n  /**\r\n   * Formats a string using markdown and returns trusted HTML.\r\n   * Parameters of the filter are:\r\n   * - markdown: Markdown input to format as HTML.\r\n   * @example\r\n   * ```html\r\n   * <div ng-bind-html=\"$ctrl.current.example | sxyMarkdown\"></div>\r\n   * ```\r\n   */\r\n  public static sxyMarkdown = [\"$sce\", ($sce: angular.ISCEService) => {\r\n    return (markdown: string): string => {\r\n      if (markdown == null) {\r\n        return null;\r\n      }\r\n      return $sce.getTrustedHtml(marked(markdown));\r\n    };\r\n  }];\r\n\r\n  /**\r\n   * IsInRole filter returns true if the user is in any of the given roles.\r\n   * The input may be Array of roles or comma separated string containing role names.\r\n   * This can be used instead of sxy-if-role directive when the component requires transcusion\r\n   * and also in constructing other logic in expressions.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - commaSeparatedRolesList: Comma separated list of roles\r\n   *\r\n   * NOTE: Because the actual value is constant, the filter is not rerun after session check).\r\n   * Because of this, the method should only be used after the session has been checked.\r\n   * Typically, by making sure, the filters are inside `sxy-if-role=\"$ctrl.current\"`, `sxy-if-role=\"auth\"` or `sxy-if-role=\"!unknown\"`.\r\n   * @example\r\n   * ```html\r\n   * <div sxy-if-role=\"auth\">\r\n   *   <uib-tab index=\"'holidays'\" heading=\"Lomat\" ng-if=\"'company' | sxyIsInRole\">\r\n   *   <p>{{ 'company' | sxyIsInRole ? 'Company text' : 'Default text' }}</p>\r\n   * </div>\r\n   * ```\r\n   */\r\n  public static sxyIsInRole = [\"SessionService\", (sessionService: SessionService) => {\r\n    return (commaSeparatedRolesList: (SystemRole | Role | string)[] | string): boolean => {\r\n      return sessionService.isInSomeRole(commaSeparatedRolesList);\r\n    };\r\n  }];\r\n\r\n  /**\r\n   * IsVisibility filter returns true/false when evaluating the logical visibility of a sitemap,\r\n   * as used in the views an UI logic, i.e.:\r\n   *\r\n   * - hidden: Node is null or visibility is Hidden, HiddenReadOnly or Disabled.\r\n   * - readOnly: Node is null or visibility is ReadOnly, HiddenReadOnly or Disabled.\r\n   * - disabled: Visibility is Disabled.\r\n   * - Visible: Visibility is Visible or null, node is not null.\r\n   * - isFullWidth: The node has an isFullWidth boolean flag set to true.\r\n   *\r\n   * This can be used instead of sxy-if-sitemap directive when the component requires transcusion\r\n   * and also in constructing other logic in expressions.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - visibilityToEvaluate: The visibility value to evaluate for.\r\n   *\r\n   * NOTE: Because the actual value is constant, the filter is not rerun after session check).\r\n   * Because of this, the method should only be used after the session has been checked.\r\n   * Typically, by making sure, the filters are inside `sxy-if-role=\"$ctrl.current\"`, `sxy-if-role=\"auth\"` or `sxy-if-role=\"!unknown\"`.\r\n   * @example\r\n   * ```html\r\n   * <div sxy-if-role=\"auth\">\r\n   *   <uib-tab index=\"'holidaysReadOnly'\" heading=\"Lomat (Read-only)\" ng-if=\"'readOnly' | sxyIsVisibility\">\r\n   *   <p>{{ 'readOnly' | sxyIsVisibility ? 'Read-only text' : 'Default text' }}</p>\r\n   * </div>\r\n   * ```\r\n   */\r\n   public static sxyIsVisibility = [\"NaviService\", (naviService: NaviService) => {\r\n    return (visibilityToEvaluate: string): boolean => {\r\n      // TODO: For some reason Rollup fails in build if type is set to SitemapVisibility (from core).\r\n      return naviService.current.getVisibility(visibilityToEvaluate as any);\r\n    };\r\n  }];\r\n\r\n  /**\r\n   * Returns the label for an enumeration.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Enumeration in format \"[EnumType].[EnumName]\". First letter is case-insensitive so you can use lowerCamelCase or UpperCamelCase.\r\n   * - defaultValue: Optional default value when language version is not available.\r\n   * Special values \"name\" and \"#name\", may be used to return the enum member name either with hash or without it.\r\n   * Default is \"#name\", which returns \"#[MemberName]\" if the translation is not found.\r\n   * @example\r\n   * ```html\r\n   * <p>{{ 'CalculationStatus.Draft' | sxyEnum }} - The enum full name</p>\r\n   * <p>{{ 'CalculationStatus.paymentSucceeded' | sxyEnum }} - you may also use JSON value where first letter is lower-case.</p>\r\n   * <p>{{ 'CalculationStatus.' + calc.status | sxyEnum }} - ...which makes it easy to use with data.</p>\r\n   * ```\r\n   */\r\n  public static sxyEnum() {\r\n    return (input: string, defaultValue: null | string | \"name\" | \"#name\" = \"#name\") => {\r\n      const splitValues = (input || \"\").split(\".\");\r\n      if (splitValues.length !== 2) {\r\n        return \"#ERR: sxyEnum\";\r\n      }\r\n      if (!splitValues[1]) {\r\n        return null;\r\n      }\r\n      return EnumerationsLogic.getEnumLabel(splitValues[0], splitValues[1], defaultValue);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Returns the description for an enumeration value in current language.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Enumeration in format \"[EnumType].[EnumName]\". First letter is case-insensitive so you can use lowerCamelCase or UpperCamelCase.\r\n   * - defaultValue: Optional default value when language version is not available. Default is null\r\n   * Special values \"name\" and \"#name\", may be used to return the enum member name either with hash or without it.\r\n   * @example\r\n   * ```html\r\n   * <p>{{ 'CalculationStatus.Draft' | sxyEnumDescr }} - The enum full name</p>\r\n   * <p>{{ 'CalculationStatus.paymentSucceeded' | sxyEnumDescr }} - you may also use JSON value where first letter is lower-case.</p>\r\n   * <p>{{ 'CalculationStatus.' + calc.status | sxyEnumDescr }} - ...which makes it easy to use with data.</p>\r\n   * ```\r\n   */\r\n  public static sxyEnumDescr() {\r\n    return (input: string, defaultValue?: null | string | \"name\" | \"#name\") => {\r\n      const splitValues = (input || \"\").split(\".\");\r\n      if (splitValues.length !== 2) {\r\n        return \"#ERR: sxyEnumDescr\";\r\n      }\r\n      if (!splitValues[1]) {\r\n        return null;\r\n      }\r\n      return EnumerationsLogic.getEnumDescr(splitValues[0], splitValues[1], defaultValue);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Formats the date with Dates.getFormattedDate in core project.\r\n   * If the input is not recognized as date or if it is empty or less than year 1900, shows a dash.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Input to format\r\n   * @example\r\n   * ```html\r\n   * <p>{{ calc.workflow.paidAt | sxyDate }}</p>\r\n   * ```\r\n   */\r\n  public static sxyDate() {\r\n    return (input: string) => {\r\n      const year = Dates.getYear(input);\r\n      if (!year || year < 1900) {\r\n        return \"-\";\r\n      }\r\n      return Dates.getFormattedDate(input);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Formats a DateRange with Dates.getFormattedRange() in core project.\r\n   * If input is null, shows a dash.\r\n   * Also supports the ApiListItem (startAt, endAt), CalcInfo type in Calculation.info property (workStartDate and workEndDate) and EmploymentData (startDate and endDate)\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Input to format\r\n   *\r\n   */\r\n  public static sxyDateRange() {\r\n    return (input: DateRange) => {\r\n      if (!input) {\r\n        return \"-\";\r\n      }\r\n      const info = input as CalcInfo;\r\n      if (info.workStartDate || info.workEndDate) {\r\n        return Dates.getFormattedRange(info.workStartDate, info.workEndDate);\r\n      }\r\n      const listItem = input as ApiListItem;\r\n      if (listItem.startAt || listItem.endAt) {\r\n        return Dates.getFormattedRange(listItem.startAt, listItem.endAt);\r\n      }\r\n      const employmentData = input as EmploymentData;\r\n      if (employmentData.startDate || employmentData.endDate) {\r\n        return Dates.getFormattedRange(employmentData.startDate, employmentData.endDate);\r\n      }\r\n      return Dates.getFormattedRange(input.start, input.end);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Iban formatting filter.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Input text to format as IBAN.\r\n   *\r\n   */\r\n  public static sxyIban() {\r\n    return (input: string) => {\r\n      if (!input) {\r\n        return null;\r\n      }\r\n      return Iban.formatIban(input);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Formats a number as count optionally taking into account the related unit\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Input to format\r\n   * - unit: Unit that is used in formatting.\r\n   * - decimals: Number of decimals to show.\r\n   * - nullText: Text to show if the value is null / undefined. By default returns null, which can then be cought by another filter or logical or (\"||\").\r\n   * - zeroText: If specified, will use this text without the Unit formatting if the value is zero. By default zero is formatted as \"0 [unitText]\".\r\n   */\r\n  public static sxyCount() {\r\n    return (\r\n      input: number,\r\n      unit: Unit = null,\r\n      decimals: number = null,\r\n      nullText: string = null,\r\n      zeroText: string = null) => {\r\n      if (input == null) {\r\n        return nullText;\r\n      }\r\n      if (zeroText != null && input === 0) {\r\n        return zeroText;\r\n      }\r\n      const rounded = Numeric.round(input, decimals || 2);\r\n      switch (unit) {\r\n        case Unit.One:\r\n          return \"\";\r\n        case Unit.Period:\r\n          return rounded + Translations.get(\"SALAXY.NG1.FilterFunctions.sxyCount.period\" + (rounded === 1 ? \"\" : \"s\"));\r\n        case Unit.Percent:\r\n          return Numeric.round(input * 100, decimals || 2) + \"%\";\r\n        case Unit.Hours:\r\n        case Unit.Days:\r\n        case Unit.Weeks:\r\n        case Unit.Count:\r\n        case Unit.Kilometers:\r\n        case Unit.Undefined:\r\n        default:\r\n          return rounded + \" \" + (CalcRowsLogic.getUnitIndicator(unit) || \"\");\r\n      }\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Formats a datetime ISO string (or other DayJS-object compatible time)\r\n   * As time with texts \"Today\", \"Yesterday\", \"D.M. HH:mm\" for this year\r\n   * and \"D.M.YYYY\" for other years (if necessary, add option for adding time to previous years).\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - time: Input to format\r\n   *\r\n   */\r\n  public static sxyTime() {\r\n    // TODO: This is being rewritten in CalendarEventsCrudController. When ready, move to core and use the same function here.\r\n    return (time: string) => {\r\n      return DateTimes.format(time);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Calls the Salaxy standard Dates.asDate to convert a DatelyObject to ISO date string (without time).\r\n   * ISO dates can then be used in comparison and equality.\r\n   * Also note that, DatelyObject can be constants like \"today\" | \"yesterday\" | \"tomorrow\". See documentation for details.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: Input to format as DatelyObject\r\n   * - addWorkDays: If set, adds the number of workdays to the input.\r\n   * May also be zero (0) to return input if it is a workday or next workday if input is not a workday.\r\n   *\r\n   */\r\n  public static sxyAsDate() {\r\n    return (input: DatelyObject, addWorkDays: number) => {\r\n      if (addWorkDays != null) {\r\n        return Dates.addWorkdays(input, addWorkDays);\r\n      }\r\n      return Dates.asDate(input);\r\n    };\r\n  }\r\n  /**\r\n   * Formats a date/time range to an end-user friendly duration text.\r\n   * Input may be Duration as ISO duration string (e.g. P3Y6M4DT12H30M5S) or .Net timespan (e.g. '7.23:59:59.999').\r\n   */\r\n  public static sxyDuration() {\r\n    return (input: string) => {\r\n      return DateTimes.formatDuration(input);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Converts the occupation to a language versioned string.\r\n   *\r\n   * Parameters of the filter are:\r\n   *\r\n   * - input: The occupation code as stored / returned from the API.\r\n   * - format: Default is just the label for the occupation. \"code-label\" is in format \"[code]: [label]`\r\n   *\r\n   */\r\n  public static sxyOccupation() {\r\n    return (input: string, format: \"default\" | \"code-label\") => {\r\n      const occupation = Occupations.getById(input);\r\n      if (!occupation) {\r\n        return Translations.get(\"SALAXY.NG1.FilterFunctions.sxyOccupation.occupationMissing\");\r\n      }\r\n      if (format === \"code-label\") {\r\n        return `${occupation.code}: ${occupation.label}`;\r\n      }\r\n      return occupation.label;\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Formats a time (input) to an end-user friendly totaltime (12:34 or 12:34:56) text.\r\n   * Input may be Duration as ISO duration string (e.g. P3Y6M4DT12H30M5S) or .Net timespan (e.g. '7.23:59:59.999').\r\n   */\r\n  public static sxyTotalTime() {\r\n    return (input: number, format: \"minutes\" | \"seconds\") => {\r\n      const padTo2Digits = (num) => {\r\n        return num.toString().padStart(2, \"0\");\r\n      };\r\n      input = Numeric.isNumber(input) ? input : 0;\r\n      switch( format ) {\r\n        case \"minutes\": {\r\n          const hours = Math.floor(input / 60);\r\n          const minutes = input % 60;\r\n          return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}`;\r\n        }\r\n        case \"seconds\": {\r\n          const hours = Math.floor(input / 3600);\r\n          const minutes =  Math.floor((input % 3600) / 60);\r\n          const seconds = input % 60;\r\n          return `${padTo2Digits(hours)}:${padTo2Digits(minutes)}:${padTo2Digits(seconds)}`;\r\n        }\r\n      }\r\n    };\r\n  }\r\n\r\n}\r\n","import { FilterFunctions } from \"./FilterFunctions\";\r\n\r\n/**\r\n * Provides the method for registering filters to the module.\r\n */\r\nexport class FiltersRegistration {\r\n\r\n  /** Gets the filters for Module registration. */\r\n  public static getFilters() {\r\n    /* eslint-disable @typescript-eslint/unbound-method */\r\n    return {\r\n      sxyAsDate: FilterFunctions.sxyAsDate,\r\n      sxyCount: FilterFunctions.sxyCount,\r\n      sxyDate: FilterFunctions.sxyDate,\r\n      sxyDateRange: FilterFunctions.sxyDateRange,\r\n      sxyDuration: FilterFunctions.sxyDuration,\r\n      sxyEnum: FilterFunctions.sxyEnum,\r\n      sxyEnumDescr: FilterFunctions.sxyEnumDescr,\r\n      sxyIban: FilterFunctions.sxyIban,\r\n      sxyMarkdown: FilterFunctions.sxyMarkdown,\r\n      sxyOccupation: FilterFunctions.sxyOccupation,\r\n      sxyTime: FilterFunctions.sxyTime,\r\n      sxyTranslate: FilterFunctions.sxyTranslate,\r\n      sxyIsInRole: FilterFunctions.sxyIsInRole,\r\n      sxyIsVisibility: FilterFunctions.sxyIsVisibility,\r\n      sxyWorkflowMessage: FilterFunctions.sxyWorkflowMessage,\r\n      sxyTotalTime: FilterFunctions.sxyTotalTime,\r\n      sxyShow: FilterFunctions.sxyShow,\r\n    };\r\n    /* eslint-enable @typescript-eslint/unbound-method */\r\n  }\r\n}\r\n","import angular from \"angular\";\r\n\r\n/**\r\n * Interceptor for monitoring $http-service calls.\r\n */\r\nexport class LoaderInterceptor {\r\n\r\n    /**\r\n     * Factory method for creating the interceptor.\r\n     */\r\n    public static factory() {\r\n      const factory = ($q: angular.IQService, $rootScope: angular.IRootScopeService) => {\r\n        if (LoaderInterceptor.instance == null) {\r\n          LoaderInterceptor.instance = new LoaderInterceptor($q, $rootScope);\r\n        }\r\n        return LoaderInterceptor.instance;\r\n      };\r\n      factory.$inject = [\"$q\", \"$rootScope\"];\r\n      return factory;\r\n  }\r\n\r\n    /**\r\n     * Singleton\r\n     */\r\n    private static instance: LoaderInterceptor;\r\n\r\n    private loadingCount = 0;\r\n\r\n    /**\r\n     * Constructor creating a new interceptor.\r\n     * @param  $q - $q service.\r\n     * @param  $rootScope - Angular root scope.\r\n     */\r\n    private constructor(private $q: angular.IQService, private $rootScope: angular.IRootScopeService) {\r\n    }\r\n\r\n    /**\r\n     * Intercepting method for request.\r\n     * @param config - $http request.\r\n     */\r\n    public request = (config: angular.IRequestConfig) => {\r\n        this.loadingCount++;\r\n        this.$rootScope.$broadcast(\"salaxy-loader-show\");\r\n        return config || this.$q.when(config);\r\n    };\r\n\r\n    /**\r\n     * Intercepting method for response.\r\n     * @param response - $http response.\r\n     */\r\n    public response = (response: angular.IHttpPromiseCallbackArg<any>) => {\r\n        if ((--this.loadingCount) === 0) {\r\n            this.$rootScope.$broadcast(\"salaxy-loader-hide\");\r\n        }\r\n        return response || this.$q.when(response);\r\n    };\r\n\r\n    /**\r\n     * Intercepting method for response error.\r\n     * @param rejection - $http error.\r\n     */\r\n    public responseError = (rejection: any) => {\r\n        if ((--this.loadingCount) === 0) {\r\n            this.$rootScope.$broadcast(\"salaxy-loader-hide\");\r\n        }\r\n        return this.$q.reject(rejection);\r\n    };\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Dates } from \"@salaxy/core\";\r\n\r\n/**\r\n * Interceptor for enabling non-cached views.\r\n * The interceptor adds a 'v'-query parameter to the template path.\r\n * The value of the v-parameter is a timestamp formatted by the given format.\r\n */\r\nexport class TemplateInterceptor {\r\n\r\n    /**\r\n     * Factory method for creating the interceptor.\r\n     * Interceptor for enabling non-cached views.\r\n     * The interceptor adds a 'v'-query parameter to the template path.\r\n     * The value of the v-parameter is a timestamp formatted by the given format.\r\n     * @param views - Regex for views folders (template paths), default is /views\\//\r\n     * @param format - DayJs format for the current time based timestamp. default is \"YYYYMMDDHH\"\r\n     */\r\n    public static factory(views = /views\\//, format = \"YYYYMMDDHH\") {\r\n      const factory = () => {\r\n        return new TemplateInterceptor(views, format);\r\n      };\r\n      factory.$inject = [];\r\n      return factory;\r\n  }\r\n\r\n    /**\r\n     * Constructor for creating a new interceptor.\r\n     */\r\n    private constructor(private views: RegExp, private format: string) {\r\n    }\r\n\r\n    /**\r\n     * Intercepting method for request.\r\n     * @param config - $http request.\r\n     */\r\n    public request = (config: angular.IRequestConfig) => {\r\n      if (config && config.url) {\r\n        if (this.views.test(config.url)) {\r\n          config.url = `${config.url}${config.url.indexOf(\"?\") < 0 ? \"?\" : \"&\" }v=${Dates.format(new Date(),this.format)}`;\r\n        }\r\n      }\r\n      return config;\r\n    };\r\n}\r\n","// Services from this project.\r\nimport {\r\n  AlertService,\r\n  AuthorizedAccountService,\r\n  CacheService,\r\n  CertificateService,\r\n  CredentialService,\r\n  FileService,\r\n  InvoicesService,\r\n  JsonSchemaService,\r\n  NaviService,\r\n  OnboardingService,\r\n  PartnerService,\r\n  ReportsService,\r\n  RowTypeService,\r\n  SessionService,\r\n  SettingsService,\r\n  SignatureService,\r\n  UiCrudHelpers,\r\n  UiHelpers,\r\n  UiTranslatorService,\r\n  UploadService,\r\n  UsecasesService,\r\n  UserSettingsService,\r\n  VarmaPensionService,\r\n  WizardService,\r\n  WorkflowService,\r\n} from \".\";\r\n\r\nimport { AjaxNg1 } from \"../ajax/AjaxNg1\";\r\n\r\n// @salaxy/core services and interfaces\r\nimport {\r\n  Absences,\r\n  AccountingTargets,\r\n  Accounts,\r\n  AccountSettings,\r\n  AuthorizedAccounts,\r\n  BeneficialOwnersApi,\r\n  Calculations,\r\n  Calculator,\r\n  CalendarEvents,\r\n  Certificates,\r\n  Client,\r\n  Credentials,\r\n  CustomerInvoices,\r\n  Datasets,\r\n  Employments,\r\n  Files,\r\n  HolidayYears,\r\n  Imports,\r\n  Invoices,\r\n  IrEarningsPayments,\r\n  IrPayerSummaries,\r\n  MessageThreads,\r\n  OAuth2,\r\n  Onboardings,\r\n  Overview,\r\n  PartnerServices,\r\n  PaymentChannelApi,\r\n  Payrolls,\r\n  Payrolls4,\r\n  ProApi,\r\n  Records,\r\n  ReferenceObjects,\r\n  Reports,\r\n  Session,\r\n  Taxcards,\r\n  Test,\r\n  Usecases,\r\n  Workers,\r\n  ServiceModels,\r\n  HouseholdYears,\r\n} from \"@salaxy/core\";\r\n\r\n// @salaxy/report services\r\nimport {\r\n  Templates,\r\n} from \"@salaxy/reports\";\r\n\r\n/**\r\n * Provides methods for registering the Services to module\r\n * (and other related metadata in the future).\r\n */\r\nexport class ServicesRegistration {\r\n\r\n  /** Gets the services for Module registration. */\r\n  public static getServices () {\r\n    return {\r\n      AjaxNg1,\r\n      AlertService,\r\n      AuthorizedAccountService,\r\n      CacheService,\r\n      CertificateService,\r\n      CredentialService,\r\n      CustomerInvoices,\r\n      FileService,\r\n      InvoicesService,\r\n      JsonSchemaService,\r\n      NaviService,\r\n      OnboardingService,\r\n      PartnerService,\r\n      ReportsService,\r\n      RowTypeService,\r\n      SessionService,\r\n      SettingsService,\r\n      SignatureService,\r\n      UiCrudHelpers,\r\n      UiHelpers,\r\n      UiTranslatorService,\r\n      UploadService,\r\n      UsecasesService,\r\n      UserSettingsService,\r\n      VarmaPensionService,\r\n      WizardService,\r\n      WorkflowService,\r\n    };\r\n  }\r\n\r\n  /** Gets the services from the @salaxy/core project that need to be registered for NG1 dependency injection. */\r\n  public static getCoreServices () {\r\n    return {\r\n      Absences,\r\n      AccountingTargets,\r\n      Accounts,\r\n      AccountSettings,\r\n      AuthorizedAccounts,\r\n      BeneficialOwnersApi,\r\n      Calculations,\r\n      Calculator,\r\n      CalendarEvents,\r\n      Certificates,\r\n      Client,\r\n      Credentials,\r\n      Datasets,\r\n      Employments,\r\n      Files,\r\n      HolidayYears,\r\n      Imports,\r\n      Invoices,\r\n      IrEarningsPayments,\r\n      IrPayerSummaries,\r\n      MessageThreads,\r\n      OAuth2,\r\n      Onboardings,\r\n      Overview,\r\n      PartnerServices,\r\n      PaymentChannelApi,\r\n      Payrolls,\r\n      Payrolls4,\r\n      ProApi,\r\n      Records,\r\n      ReferenceObjects,\r\n      Reports,\r\n      Session,\r\n      Taxcards,\r\n      Templates,\r\n      Test,\r\n      Usecases,\r\n      Workers,\r\n      ServiceModels,\r\n      HouseholdYears,\r\n    };\r\n  }\r\n}\r\n","import angular from \"angular\";\r\nimport routes from \"angular-route\";\r\nimport \"angular-i18n/angular-locale_fi.js\";\r\nimport ngBs from \"angular-ui-bootstrap\";\r\nimport sco from \"angular-sanitize\";\r\nimport upload from \"ng-file-upload\";\r\nimport tx from \"angular-translate\";\r\n\r\nimport { ComponentsRegistration } from \"../components/_ComponentsRegistration\";\r\nimport { ControllersRegistration } from \"../controllers/_ControllersRegistration\";\r\nimport { DirectivesRegistration } from \"../directives/_DirectivesRegistration\";\r\nimport { FiltersRegistration } from \"../filters/_FiltersRegistration\";\r\nimport { PromisePolyfill, RouteHelperProvider } from \"../helpers\";\r\nimport { LoaderInterceptor } from \"../interceptors\";\r\nimport { ServicesRegistration } from \"../services/_ServicesRegistration\";\r\n\r\n/**\r\n * Components contain the user interface element (the view) on top of the controller logic.\r\n * This is the Angular2 compatible alternative to Directives introduced in Angular 1.5.\r\n *\r\n * Registers the salaxy.ng1.components.all module that contains the entire\r\n * Palkkaus.fi Angular stack\r\n * @example\r\n * angular.module(\"myAngularApplication\", [\"salaxy.ng1.components.all\"])\r\n * @ignore\r\n */\r\nexport const SalaxyNg1ComponentsModule = angular.module(\"salaxy.ng1.components.all\", [\r\n    \"salaxy.ng1.templates.bootstrap\",\r\n    \"ui.bootstrap\",\r\n    \"ngRoute\",\r\n    \"ngSanitize\",\r\n    \"ngFileUpload\",\r\n    \"pascalprecht.translate\",\r\n])\r\n    .config([() => {\r\n      const assureReg = [routes, ngBs, sco, upload, tx];\r\n      console.debug(`@salaxy/ng1 init with ${assureReg.length} modules.`);\r\n    }])\r\n    // Registrations\r\n    .provider(\"RouteHelper\", RouteHelperProvider)\r\n    .service(ServicesRegistration.getCoreServices())\r\n    .service(ServicesRegistration.getServices())\r\n    .controller(ControllersRegistration.getControllers())\r\n    .directive(DirectivesRegistration.getDirectives())\r\n    .component(ComponentsRegistration.getComponents())\r\n    .filter(FiltersRegistration.getFilters())\r\n    .constant(\"data\", { isNotDefined: true })\r\n    .constant(\"EditDialogParameters\", { isNotDefined: true })\r\n    // Interceptors\r\n    .config([\"$httpProvider\", ($httpProvider: ng.IHttpProvider) => {\r\n       $httpProvider.interceptors.push(LoaderInterceptor.factory());\r\n     }])\r\n\r\n    // Misc configurations\r\n    .config([\"$provide\", \"$translateProvider\", ($provide: any, $translateProvider: angular.translate.ITranslateProvider) => {\r\n        // Currently there is an issue with the sanitize mode, it will double encode UTF-8 characters or special characters.\r\n        // use the null strategy, until this is resolved.\r\n        $translateProvider.useSanitizeValueStrategy(null);\r\n        $provide.value(\"$translateProvider\", $translateProvider);\r\n    }])\r\n    // supporting the default empty hash-prefix after upgrade from 1.5 -> 1.6\r\n    .config([\"$locationProvider\", ($locationProvider) => {\r\n      $locationProvider.hashPrefix(\"\");\r\n    }])\r\n    .run(PromisePolyfill)\r\n\r\n    ;\r\n","/* eslint-disable */\n  import angular from \"angular\";\n  import { Configs } from \"@salaxy/core\";\n  /**\n   * Bootstrap templates compiled to JavaScript\n   * @ignore\n   */\n  export const SalaxyNg1BootstrapTemplatesModule = angular.module(\"salaxy.ng1.templates.bootstrap\", [])\n    .run([\"$templateCache\", function ($templateCache) {\n      const useCache = !((Configs.current as any)?.noCache);\n      if (useCache) {\n        \n $templateCache.put(\"salaxy-components/account/AccountAvatarEdit.html\",`<div class=\"salaxy-component salaxy-account-contact-edit\" ng-if=\"$ctrl.isAuthenticated\">\r\n  <div ng-if=\"$ctrl.session.currentAccount.entityType == 'company'\" ng-controller=\"CompanyAccountController as $accountCtrl\">\r\n    <ng-include src=\"'AvatarEditor.html'\"></ng-include>\r\n  </div>\r\n  <div ng-if=\"$ctrl.session.currentAccount.entityType != 'company'\" ng-controller=\"PersonAccountController as $accountCtrl\">\r\n    <ng-include src=\"'AvatarEditor.html'\"></ng-include>\r\n  </div>\r\n  <script type=\"text/ng-template\" id=\"AvatarEditor.html\">\r\n    <form name=\"avatarForm\" class=\"form-horizontal\" ng-if=\"$accountCtrl.current\">\r\n      <div class=\"form-group\">\r\n        <div class=\"col-xs-12 col-sm-4\">\r\n          <label for=\"avatarPreview\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarLabel\"></label>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-8\">\r\n          <div class=\"worker-avatar-col\">\r\n            <salaxy-avatar style=\"font-size: 200px\" avatar=\"$accountCtrl.current.avatar\"></salaxy-avatar>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"form-group\">\r\n        <div class=\"col-xs-12 col-sm-4\">\r\n          <label for=\"avatarPictureType\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarTypeLabel\"></label>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-8\">\r\n          <select class=\"form-control\" id=\"avatarPictureType\" ng-model=\"$accountCtrl.current.avatar.pictureType\" ng-change=\"$accountCtrl.typeForAvatarChanged()\">\r\n            <option value=\"\" disabled sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionChoose\"></option>\r\n            <option value=\"icon\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionIcon\"></option>\r\n            <option value=\"uploaded\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionUploaded\"></option>\r\n            <option value=\"gravatar\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionGravatar\"></option>\r\n          </select>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$accountCtrl.current.avatar.pictureType == 'gravatar'\" class=\"row\">\r\n        <div class=\"input-info col-sm-8 col-sm-offset-4\">\r\n          <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n          <p class=\"small input-info-text with-icon \" sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.gravatarInfo.html\"></p>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$accountCtrl.current.avatar.pictureType == 'icon'\">\r\n        <salaxy-input name=\"avatarInitials\" label=\"SALAXY.NG1.AccountAvatarEditPersonComponent.initialsLabel\" ng-model=\"$accountCtrl.current.avatar.initials\" max-length=\"2\"></salaxy-input>\r\n        <salaxy-input-enum ng-model=\"$accountCtrl.current.avatar.color\" name=\"avatarColor\" label=\"SALAXY.NG1.AccountAvatarEditPersonComponent.colorLabel\" options=\"{\r\n          '#009FD8': '#009FD8',\r\n          '#91D214': '#91D214',\r\n          '#D10074': '#D10074',\r\n          '#3C3C3C': '#3C3C3C',\r\n          '#61703B': '#61703B',\r\n          '#7F2C2A': '#7F2C2A',\r\n          '#FF911E': '#FF911E',\r\n          '#289548': '#289548',\r\n          'blue': 'blue',\r\n          'lime': 'lime',\r\n          'pink': 'pink',\r\n          'gray': 'gray',\r\n          'darkgreen': 'darkgreen',\r\n          'brown': 'brown',\r\n          'yellow': 'yellow',\r\n          'orange': 'orange',\r\n          'green': 'green',\r\n          'black': 'black'         \r\n          }\">\r\n        </salaxy-input-enum>\r\n      </div>\r\n      <div class=\"form-group\">\r\n        <div ng-if=\"$accountCtrl.current.avatar.pictureType == 'uploaded'\">\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <label for=\"avatarImageUpload\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImageLabel\"></label>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            <div name=\"avatarImageUpload\" ng-model=\"avatarImage\" ngf-drop=\"$accountCtrl.uploadAvatarImage($file)\" ngf-select=\"$accountCtrl.uploadAvatarImage($file)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" ngf-multiple=\"false\" ngf-min-size=\"5KB\" ngf-max-size=\"10MB\"\r\n              ngf-pattern=\"'image/*'\" ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\">\r\n              <span sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImage.html\"></span>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-right\">\r\n        <button ng-click=\"$accountCtrl.saveCurrent()\" ng-disabled=\"avatarForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n    </form>\r\n  </script>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AccountContactEdit.html\",`<div class=\"salaxy-component salaxy-account-contact-edit\" ng-if=\"$ctrl.isAuthenticated\">\r\n  <div ng-if=\"$ctrl.session.currentAccount.entityType == 'company'\" ng-controller=\"CompanyAccountController as $accountCtrl\">\r\n    <ng-include src=\"'ContactEditor.html'\"></ng-include>\r\n  </div>\r\n  <div ng-if=\"$ctrl.session.currentAccount.entityType != 'company'\" ng-controller=\"PersonAccountController as $accountCtrl\">\r\n    <ng-include src=\"'ContactEditor.html'\"></ng-include>\r\n  </div>\r\n  <script type=\"text/ng-template\" id=\"ContactEditor.html\">\r\n    <form name=\"contactForm\" class=\"form-horizontal\" ng-if=\"$accountCtrl.current\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <salaxy-input name=\"email\" label=\"SALAXY.MODEL.PersonAccount.contact.email.title\" sxy-email ng-model=\"$accountCtrl.current.contact.email\" ng-change=\"$accountCtrl.emailForAvatarChanged()\">\r\n          </salaxy-input>\r\n          <salaxy-input name=\"telephone\" label=\"SALAXY.MODEL.PersonAccount.contact.telephone.title\" sxy-mobile-phone ng-model=\"$accountCtrl.current.contact.telephone\"></salaxy-input>\r\n          <salaxy-input name=\"street\" label=\"SALAXY.MODEL.PersonAccount.contact.street.title\" ng-model=\"$accountCtrl.current.contact.street\" ng-required=\"('household' | sxyIsInRole) || ('company' | sxyIsInRole)\"></salaxy-input>\r\n          <salaxy-input name=\"postalCode\" label=\"SALAXY.MODEL.PersonAccount.contact.postalCode.title\" sxy-postal-code-fi ng-model=\"$accountCtrl.current.contact.postalCode\" ng-required=\"('household' | sxyIsInRole) | ('company' | sxyIsInRole)\"></salaxy-input>\r\n          <salaxy-input name=\"city\" label=\"SALAXY.MODEL.PersonAccount.contact.city.title\" ng-model=\"$accountCtrl.current.contact.city\" ng-required=\"('household' | sxyIsInRole) || ('company' | sxyIsInRole)\"></salaxy-input>\r\n          <salaxy-input-enum type=\"select\" label=\"SALAXY.MODEL.PersonAccount.contact.countryCode.title\" ng-model=\"$accountCtrl.current.contact.countryCode\"\r\n          name=\"country\" read-only=\"true\" enum=\"Country\"></salaxy-input-enum>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-right\">\r\n        <button ng-click=\"$accountCtrl.saveCurrent()\" ng-disabled=\"contactForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n    </form>\r\n  </script>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AccountInfo.html\",`﻿<div class=\"container-fixed salaxy-component salaxy-account-info\" ng-controller=\"CompanyAccountController as $companyCtrl\">\r\n  <table>\r\n    <tr>\r\n      <td>\r\n        <salaxy-avatar avatar=\"$ctrl.company.avatar\"></salaxy-avatar>\r\n        <button type=\"button\" style=\"margin-bottom: 5px;\" class=\"btn btn-sm btn-default\" ng-click=\"$companyCtrl.openEditDialog('avatar')\" sxy-text=\"SALAXY.NG1.AccountInfoComponent.changeAvatar\"></button>\r\n      </td>\r\n      <td>\r\n        <p class=\"lead\" ng-controller=\"CompanyOnboardingController as $onBoarding\">\r\n          {{'SALAXY.NG1.AccountInfoComponent.lead.infoText' | sxyTranslate}} <a ng-click=\"$onBoarding.openSigningWizardDialog()\">{{'SALAXY.NG1.AccountInfoComponent.lead.buttonText' | sxyTranslate}}</a> {{'SALAXY.NG1.AccountInfoComponent.lead.infoTextAlt' | sxyTranslate}}\r\n        </p>\r\n      </td>\r\n    </tr>\r\n  </table>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table\">\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.palkkausAccount\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.id | sxyIban }}</td>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.email\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.contact.email }}</td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.companyName\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.avatar.displayName }}</td>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.phone\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.contact.telephone }}</td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.officialId\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.identity.officialId }}</td>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.address\" ps=\":\"></th>\r\n        <td>\r\n          {{ $ctrl.company.contact.street }}<br /> {{ $ctrl.company.contact.postalCode }} {{ $ctrl.company.contact.city }}\r\n        </td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.companyType\" ps=\":\"></th>\r\n        <td>{{ 'CompanyType.' + $ctrl.company.companyType | sxyEnum }}</td>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.ibanNumber\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.identity.ibanNumber | sxyIban }}</td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountInfoComponent.authorizationType\" ps=\":\"></th>\r\n        <td>\r\n          {{ 'AuthorizationType.' + $ctrl.company.identity.contract.authorizationType | sxyEnum }}\r\n          <span ng-if=\"$ctrl.company.identity.contract.authorizationType == 'companyContract'\">\r\n            (<a class=\"\" ng-href=\"{{$ctrl.authorizationPdfUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.seePreview\"></a>)\r\n          </span>\r\n        </td>\r\n        <th><button type=\"button\" style=\"margin-bottom: 5px;\" class=\"btn btn-sm btn-default\" ng-click=\"$companyCtrl.openEditDialog('contactInfo')\" sxy-text=\"SALAXY.NG1.AccountInfoComponent.editContactInfo\"></button></th>\r\n        <td></td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"Asiakkaan tunnistaminen tehty\" ps=\":\"></th>\r\n        <td>{{ $ctrl.company.identity.kycUpdatedAt | sxyDate }}</td>\r\n        <th>\r\n          <a ng-href=\"{{('test' | sxyIsInRole) ? 'https://rc-iam.palkkaus.fi/wizard/index.html' : 'https://iam.palkkaus.fi/wizard/index.html'}}\" target=\"_blank\" class=\"btn btn-sm btn-default\" role=\"button\">Päivitä asiakkaan tunnistaminen</a>\r\n        </th>\r\n        <td></td>\r\n      </tr>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AssurePartner.html\",`<div class=\"salaxy-assure-partner salaxy-component\" ng-controller=\"SessionController as $sessionCtrl\">\r\n  <div ng-if=\"$sessionCtrl.session.settings.partner.accountId\">\r\n    <ng-transclude ng-transclude-slot=\"header\">\r\n      <!-- Further information of the partner etc. -->\r\n    </ng-transclude>\r\n    <ng-transclude ng-transclude-slot=\"main\">\r\n      <!-- Content to assure -->\r\n    </ng-transclude>\r\n  </div>\r\n  <div ng-if=\"!$sessionCtrl.session.settings.partner.accountId\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <div class=\"content settings\">\r\n          <salaxy-accountant></salaxy-accountant>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AuthCard.html\",`<div class=\"salaxy-component salaxy-product-card\">\r\n  <a href=\"\" ng-click=\"$ctrl.showPartnerSiteDialog($ctrl.authId)\" class=\"thumbnail salaxy-product-card\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-6\">\r\n          <i class=\"salaxy-avatar\" style=\"font-size: 74px;\"><img ng-src=\"{{$ctrl.getPartnerSite($ctrl.authId).img}}\" /></i>\r\n          \r\n        </div>\r\n        <div class=\"col-xs-6\">\r\n          <salaxy-input-boolean type=\"switch-xl\" ng-if=\"$ctrl.isInRole('auth') && !$ctrl.hideSwitch\" id=\"salaxyService\" name=\"salaxyService\" ng-model=\"$ctrl.getPartnerSite($ctrl.authId).enabled\" label-type=\"no-label\" label-true=\"on\" label-false=\"off\"></salaxy-input-boolean>\r\n        </div>\r\n      </div>\r\n      <div class=\"salaxy-product-title\">{{ $ctrl.getPartnerSite($ctrl.authId).title }}</div>\r\n      <div class=\"salaxy-product-descr\">{{ $ctrl.getPartnerSite($ctrl.authId).status }}</div>\r\n  </a>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AuthorizedAccounts.html\",`<div class=\"panel panel-default\" ng-controller=\"AccountAuthorizationController as $ctrl\">\r\n  <div class=\"panel-heading\">\r\n    <h2 sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorizeIntro\"></h2>\r\n    <p><small sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorizeDescription\"></small></p>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <div class=\"salaxy-component salaxy-authorized-accounts\">\r\n      <div class=\"table-responsive\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th colspan=\"2\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.palkkausAccount\"></th>\r\n              <th ng-if=\"('admin' | sxyIsInRole)\">Partnerin antama ID</th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.date\"></th>\r\n              <th class=\"right\">\r\n                <ng-transclude ng-transclude-slot=\"header\">\r\n                  <button class=\"btn btn-sm btn-default\" ng-click=\"$ctrl.showAuthorizedAccountAddDialog()\" sxy-text=\"SALAXY.UI_Terms.createNew\"></button>\r\n                </ng-transclude>\r\n              </th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"avatar in $ctrl.list\">\r\n              <td>\r\n                <salaxy-avatar style=\"font-size: 50px;\" avatar=\"avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td>\r\n                <strong>{{avatar.displayName}}</strong><br/>\r\n                <small>{{avatar.id | sxyIban}}</small>\r\n              </td>\r\n              <td  ng-if=\"('admin' | sxyIsInRole)\">{{avatar.partnerKey}}</td>\r\n              <td class=\"right\">{{avatar.createdAt | date}}</td>\r\n              <td class=\"text-right\">\r\n                <button ng-click=\"$ctrl.delete(avatar.id)\" class=\"btn btn-danger\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/AuthorizingAccounts.html\",`<div class=\"salaxy-component salaxy-authorizing-accounts\">\r\n  <div class=\"table-responsive\" ng-controller=\"CustomerOnboardingController as wizard\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.palkkausAccount\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.status\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.date\"></th>\r\n          <th class=\"right\" colspan=\"3\">\r\n            <ng-transclude ng-transclude-slot=\"header\">\r\n              <button class=\"btn btn-sm btn-default\" ng-click=\"wizard.launch()\" sxy-text=\"SALAXY.UI_Terms.createNew\"></button>\r\n            </ng-transclude>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"account in $ctrl.authorizingAccounts\">\r\n          <td>\r\n            <salaxy-avatar style=\"font-size: 50px;\" avatar=\"account.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{account.avatar.displayName}}</strong><br/>\r\n            <small>{{account.id | sxyIban }}</small>\r\n          </td>\r\n          <td>\r\n            <small class=\"text-success\" ng-if=\"account.identity.contract.isSigned\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.signeratureOk\"></small>\r\n            <small class=\"text-danger\" ng-if=\"!account.identity.contract.isSigned\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.signeratureNo\"></small>\r\n          </td>\r\n          <td class=\"right\">{{account.createdAt | date }}</td>\r\n          <td>\r\n            <button ng-if=\"!account.identity.contract.isSigned && account.entityType == 'company'\" ng-click=\"wizard.launch(account.id)\" class=\"btn btn-default btn-block\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.invite\"></button>\r\n          </td>\r\n          <td>\r\n            <a ng-href=\"{{$ctrl.getLoginAsUrl(account.id)}}\" target=\"_blank\" class=\"btn btn-primary btn-block\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.signIn\"></a>\r\n          </td>\r\n          <td>\r\n            <button salaxy-if-role=\"test\" ng-click=\"$ctrl.deleteAccount(account.id)\" class=\"btn btn-danger btn-block\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/Certificates.html\",`<div class=\"panel panel-default\">\r\n  <div class=\"panel-heading\">\r\n    <h2 sxy-text=\"SALAXY.NG1.CertificatesComponent.title\"></h2>    \r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <div class=\"salaxy-component salaxy-certificates\">\r\n      <div class=\"table-responsive\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CertificatesComponent.name\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.CertificatesComponent.id\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.date\"></th>\r\n              <th class=\"right\">\r\n                <ng-transclude ng-transclude-slot=\"header\">\r\n                  <button class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.showCertificateAddDialog()\" sxy-text=\"SALAXY.UI_Terms.createNew\"></button>\r\n                </ng-transclude>\r\n              </th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"certificate in $ctrl.list\">\r\n              <td>{{certificate.title || '-'}}</td>\r\n              <td>{{certificate.thumbprint}}</td>\r\n              <td class=\"right\">{{certificate.createdAt | date}}</td>\r\n              <td class=\"right\">\r\n                <button ng-click=\"$ctrl.delete(certificate.thumbprint)\" class=\"btn btn-danger btn-sm\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/Credentials.html\",`<div class=\"panel panel-default\">\r\n\r\n  <div class=\"panel-heading\">\r\n    <h2 sxy-text=\"SALAXY.NG1.CredentialsComponent.title\"></h2>\r\n    <p>\r\n      <!--<small sxy-text=\"SALAXY.NG1.CredentialsComponent.intro\"></small>--></p>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <div class=\"salaxy-component salaxy-credentials\">\r\n      <div class=\"table-responsive\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CredentialsComponent.userId\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.CredentialsComponent.authenticationMethod\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.date\"></th>\r\n              <th class=\"right\">\r\n                <ng-transclude ng-transclude-slot=\"header\"></ng-transclude>\r\n              </th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"credential in $ctrl.list\">\r\n              <td>{{credential.email}}</td>\r\n              <td>{{ 'AuthenticationMethod.' + credential.authenticationMethod | sxyEnum}}</td>\r\n              <td class=\"right\">{{credential.createdAt | date}}</td>\r\n              <td class=\"right\">\r\n\r\n                <button ng-if=\"$ctrl.showEdit\" ng-click=\"$ctrl.setCurrent(credential)\" class=\"btn btn-primary btn-sm\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n                <button ng-if=\"$ctrl.showEdit && !('admin' | sxyIsInRole)\" ng-disabled=\"$ctrl.list.length &lt;= 1\" ng-click=\"$ctrl.delete(credential.id)\" class=\"btn btn-danger btn-sm\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n                <button ng-if=\"$ctrl.showEdit && ('admin' | sxyIsInRole)\" ng-click=\"$ctrl.delete(credential.id)\" class=\"btn btn-danger btn-sm\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n      <form name=\"credentialsForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current && $ctrl.showEdit\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <salaxy-input name=\"firstName\" label=\"SALAXY.NG1.CredentialsComponent.firstName\" ng-model=\"$ctrl.current.avatar.firstName\"></salaxy-input>\r\n            <salaxy-input name=\"lastName\" label=\"SALAXY.NG1.CredentialsComponent.lastName\" ng-model=\"$ctrl.current.avatar.lastName\"></salaxy-input>\r\n            <salaxy-input name=\"email\" label=\"SALAXY.NG1.CredentialsComponent.email\" ng-model=\"$ctrl.current.email\" ng-change=\"$ctrl.emailForAvatarChanged()\"></salaxy-input>\r\n            <!-- <salaxy-input name=\"telephone\" label=\"SALAXY.NG1.CredentialsComponent.telephone\" ng-model=\"$ctrl.current.telephone\"></salaxy-input>-->\r\n            <div class=\"form-group\">\r\n              <div class=\"col-xs-12 col-sm-4\">\r\n                <strong sxy-text=\"SALAXY.NG1.CredentialsComponent.authenticationMethod\"></strong>\r\n              </div>\r\n              <div class=\"col-xs-12 col-sm-8\">\r\n                {{ 'AuthenticationMethod.' + $ctrl.current.authenticationMethod | sxyEnum}}\r\n              </div>\r\n            </div>\r\n\r\n          </div>\r\n        </div>\r\n\r\n        <div class=\"form-group\">\r\n\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <label for=\"avatarPictureType\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.label\"></label>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-6\">\r\n            <select class=\"form-control\" style=\"margin-bottom:15px;\" id=\"avatarPictureType\" ng-model=\"$ctrl.current.avatar.pictureType\" ng-change=\"$ctrl.typeForAvatarChanged()\">\r\n              <option value=\"\" disabled sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.optionChoose\"></option>\r\n              <option value=\"icon\" sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.optionIcon\"></option>\r\n              <option value=\"uploaded\" sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.optionUploaded\"></option>\r\n              <option value=\"gravatar\" sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.optionGravatar\"></option>\r\n            </select>\r\n            <div ng-if=\"$ctrl.current.avatar.pictureType == 'gravatar'\" class=\"input-info\">\r\n              <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n              <p class=\"small input-info-text with-icon \" sxy-html=\"SALAXY.NG1.CredentialsComponent.avatar.gravatarInfo.html\"></p>\r\n            </div>\r\n            <div ng-if=\"$ctrl.current.avatar.pictureType == 'icon'\">\r\n              <salaxy-input name=\"avatarInitials\" label=\"SALAXY.NG1.CredentialsComponent.avatar.labelInitials\" ng-model=\"$ctrl.current.avatar.initials\" max-length=\"2\"></salaxy-input>\r\n              <salaxy-input-enum name=\"avatarColor\" label=\"SALAXY.NG1.CredentialsComponent.avatar.labelColor\" ng-model=\"$ctrl.current.avatar.color\" options=\"$ctrl.colorOptions\">\r\n              </salaxy-input-enum>\r\n            </div>\r\n            <div ng-if=\"$ctrl.current.avatar.pictureType == 'uploaded'\" class=\"form-group\">\r\n              <div class=\"col-xs-12 col-sm-4\">\r\n                <label for=\"avatarImageUpload\" sxy-text=\"SALAXY.NG1.CredentialsComponent.avatar.labelUploadImage\"></label>\r\n              </div>\r\n              <div class=\"col-xs-12 col-sm-8\">\r\n                <div name=\"avatarImageUpload\" ng-model=\"avatarImage\" ngf-drop=\"$ctrl.uploadAvatarImage($file)\" ngf-select=\"$ctrl.uploadAvatarImage($file)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" ngf-multiple=\"false\" ngf-min-size=\"5KB\" ngf-max-size=\"10MB\"\r\n                  ngf-pattern=\"'image/*'\" ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\">\r\n                  <span sxy-html=\"SALAXY.NG1.CredentialsComponent.avatar.uploadImage.html\"></span>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div class=\"col-sm-2 col-xs-12 text-center\">\r\n            <salaxy-avatar avatar=\"$ctrl.current.avatar\" style=\"font-size:70px;\"></salaxy-avatar>\r\n          </div>\r\n        </div>\r\n\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12 text-right\">\r\n            <button ng-click=\"$ctrl.saveCurrent()\" ng-disabled=\"credentialsForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n          </div>\r\n        </div>\r\n      </form>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/LanguageSelector.html\",`<div class=\"salaxy-component salaxy-language-selector\" ng-controller=\"CompanyAccountController as $accountCtrl\">\r\n  <div class=\"panel language-selection panel-default\">\r\n    <div class=\"panel-heading\">\r\n      <h2>{{'SALAXY.NG1.LanguageSelectionComponent.panelTitle' | sxyTranslate}}</h2>\r\n\r\n    </div>\r\n    <div class=\"panel-body\">\r\n\r\n      <div class=\"row\">\r\n        <div class=\"col-sm-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.LanguageSelectionComponent.changeLanguage\"></legend>\r\n            <p sxy-text=\"SALAXY.NG1.LanguageSelectionComponent.changeLanguageInfo\"></p>\r\n            <div class=\"btn-group\">\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$ctrl.getLanguage() == 'fi' ? 'btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.setLanguage('fi')\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></button>\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$ctrl.getLanguage() == 'en' ? 'btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.setLanguage('en')\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></button>\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$ctrl.getLanguage() == 'sv' ? 'btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.setLanguage('sv')\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></button>\r\n            </div>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.LanguageSelectionComponent.changeCompanyDefaultLanguage\"></legend>\r\n            <p sxy-text=\"SALAXY.NG1.LanguageSelectionComponent.changeCompanyDefaultLanguageInfo\"></p>\r\n            <div class=\"btn-group\">\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$accountCtrl.getAccountLanguage() == 'fi' ? 'btn-primary active disabled' : 'btn-default'\" ng-click=\"$accountCtrl.current.language = 'fi'\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></button>\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$accountCtrl.getAccountLanguage() == 'en' ? 'btn-primary active disabled' : 'btn-default'\" ng-click=\"$accountCtrl.current.language = 'en'\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></button>\r\n              <button type=\"button\" class=\"btn\" ng-class=\"$accountCtrl.getAccountLanguage() == 'sv' ? 'btn-primary active disabled' : 'btn-default'\" ng-click=\"$accountCtrl.current.language = 'sv'\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></button>\r\n            </div>\r\n            <div>&nbsp;</div>\r\n            <div class=\"alert alert-warning\" sxy-html=\"SALAXY.NG1.LanguageSelectionComponent.warning.html\"></div>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 text-right\">\r\n          <button class=\"btn btn-primary\" ng-click=\"$accountCtrl.saveCurrent()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/LoginButton.html\",`<div class=\"salaxy-login-button salaxy-component\" sxy-if-role=\"!worker\">\r\n  <button ng-hide=\"$ctrl.isAuthenticated\" ng-click=\"$ctrl.signIn()\" class=\"btn salaxy-login-button-login\" ng-class=\"$ctrl.btnClass || 'btn-default'\">\r\n    <span class=\"glyphicon glyphicon-lock\"></span>\r\n    <span class=\"salaxy-login-button-text\">{{ $ctrl.isSessionChecking ?  ('SALAXY.NG1.LoginButtonComponent.searching' | sxyTranslate) : ($ctrl.loginText || 'SALAXY.UI_Terms.login' | sxyTranslate) }}</span>\r\n  </button>\r\n  <div ng-show=\"$ctrl.isAuthenticated\" class=\"btn-group salaxy-login-button-logout\" uib-dropdown>\r\n    <button type=\"button\" class=\"btn right\" ng-class=\"$ctrl.btnClass || 'btn-default'\" uib-dropdown-toggle>\r\n      <salaxy-avatar avatar=\"$ctrl.avatar\"></salaxy-avatar>\r\n      <span class=\"salaxy-login-button-text\">{{ $ctrl.isAuthenticated ? $ctrl.avatar.displayName : ('SALAXY.NG1.LoginButtonComponent.authenticating' | sxyTranslate) }}</span>\r\n      <span class=\"caret\"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"account-menu\" ng-controller=\"NaviController as $navi\">\r\n      <li>\r\n        <a href=\"#\" ng-click=\"$ctrl.signOut()\" sxy-text=\"SALAXY.UI_Terms.logout\"></a>\r\n      </li>\r\n      <li role=\"separator\" class=\"divider\"></li>\r\n      <li>\r\n        <a href=\"#/settings/service-settings\" sxy-text=\"SALAXY.NG1.LoginButtonComponent.accountSettings\" ng-click=\"$navi.toggleNavi()\"></a>\r\n      </li>\r\n      <li>\r\n        <a href=\"#/settings/authorizations\" sxy-text=\"SALAXY.NG1.LoginButtonComponent.authAndCerti\" ng-click=\"$navi.toggleNavi()\"></a>\r\n      </li>\r\n      <li ng-if=\"$ctrl.ownedPaymentChannel\">\r\n        <a href=\"#/payment-channel\" sxy-text=\"SALAXY.NG1.LoginButtonComponent.paymentChannel\" ng-click=\"$navi.toggleNavi()\"></a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n</div>\r\n<div class=\"salaxy-login-button\" sxy-if-role=\"worker\" ng-controller=\"NaviController as $navi\">\r\n  <div ng-show=\"$ctrl.isAuthenticated\" class=\"btn-group salaxy-login-button-logout\" uib-dropdown>\r\n    <button type=\"button\" class=\"btn btn-transparent right\" uib-dropdown-toggle>\r\n      <salaxy-avatar avatar=\"$ctrl.avatar\"></salaxy-avatar>\r\n      <span class=\"salaxy-login-button-text\">{{ $ctrl.isAuthenticated ? $ctrl.avatar.displayName : ('SALAXY.NG1.LoginButtonComponent.authenticating' | sxyTranslate) }}\r\n       \r\n      </span>\r\n      <span class=\"caret\"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"account-menu\">\r\n      <li>\r\n        <a href=\"#\" ng-click=\"$ctrl.signOut()\" sxy-text=\"SALAXY.UI_Terms.logout\"></a>\r\n      </li>\r\n      <li role=\"separator\" class=\"divider\"></li>\r\n      <li>\r\n        <a href=\"#/account/account-info\" sxy-text=\"SALAXY.NG1.LoginButtonComponent.accountSettings\" ng-click=\"$navi.toggleNavi()\"></a>\r\n      </li>\r\n      <li>\r\n        <a href=\"#/settings/authorizations\" sxy-text=\"SALAXY.NG1.LoginButtonComponent.authAndCerti\" ng-click=\"$navi.toggleNavi()\"></a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/Signing.html\",`<div class=\"salaxy-component salaxy-signing\">\r\n  <div salaxy-if-role=\"init\">\r\n    <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\"></salaxy-spinner>\r\n    <p>&nbsp;</p>\r\n  </div>\r\n  <div ng-if=\"$ctrl.isSigningRequired || $ctrl.showAlways\">\r\n    <form name=\"signingForm\" class=\"form-horizontal\">\r\n      <h2 sxy-text=\"SALAXY.NG1.SigningComponent.heading\"></h2>\r\n      <div class=\"row\">\r\n        <div class=\"col-md-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.SigningComponent.signerInformation\"></legend>\r\n            <salaxy-input name=\"sign_personName\" label=\"SALAXY.NG1.SigningComponent.name\" ng-model=\"$ctrl.model.signature.personName\" ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input name=\"sign_email\" label=\"SALAXY.NG1.SigningComponent.email\" sxy-email ng-model=\"$ctrl.model.signature.email\" ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input name=\"sign_telephone\" label=\"SALAXY.NG1.SigningComponent.tel\" sxy-mobile-phone ng-model=\"$ctrl.model.signature.telephone\" ng-required=\"true\">\r\n            </salaxy-input>\r\n            <salaxy-input name=\"sign_personalId\" label=\"SALAXY.NG1.SigningComponent.ssNumber\" sxy-personal-id-fi ng-model=\"$ctrl.model.signature.personalId\" ng-required=\"true\">\r\n            </salaxy-input>\r\n            <div class=\"text-right text-danger\" style=\"margin-top: -14px; font-weight: bold;\" sxy-if-role=\"test\"> TEST ONLY: Ota hetu täältä ==></div>\r\n            <salaxy-input-boolean type=\"checkbox\" name=\"isProcura\" required ng-model=\"$ctrl.model.signature.isProcura\" label=\"SALAXY.NG1.SigningComponent.isProcuraLabel\"\r\n              label-true=\"SALAXY.NG1.SigningComponent.isProcuraLabelTrue\"></salaxy-input-boolean>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-md-6\">\r\n          <legend sxy-text=\"SALAXY.NG1.SigningComponent.attorney.info\"></legend>\r\n          <p>\r\n            <span sxy-text=\"SALAXY.NG1.SigningComponent.attorney.infoText\"></span>\r\n\r\n            <a ng-href=\"{{ $ctrl.getPdfPreviewAddress() }}\" target=\"_blank\">{{'SALAXY.NG1.SigningComponent.attorney.linkText' | sxyTranslate}}</a>.\r\n            {{'SALAXY.NG1.SigningComponent.attorney.linkTextInfo' | sxyTranslate}}\r\n          </p>\r\n          <p sxy-text=\"SALAXY.NG1.SigningComponent.attorney.signingConfirmationInfo\"></p>\r\n          <div sxy-if-role=\"test\" class=\"alert alert-danger\">\r\n            <p>\r\n              Allekirjoitus ohjaa nyt testiympäristöön, jossa\r\n              <strong>HETU tarkistetaan</strong>.\r\n              Katso testiympäristön\r\n              <a href=\"https://gist.github.com/ykarikos/e43e567eb7b9e05432d4bd9d0b51ef35\" target=\"_blank\">HETU:t täältä</a>\r\n              (valitse validi hetu).\r\n            </p>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"row\">\r\n        <div class=\"col-md-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.SigningComponent.salaryPaymentContactInformation\"></legend>\r\n            <p sxy-text=\"SALAXY.NG1.SigningComponent.salaryPaymentContanctInformationToAuthoritiesInfo\"></p>\r\n            <salaxy-input-boolean type=\"checkbox\" name=\"isContactPersonSigner\" ng-model=\"$ctrl.isContactPersonSigner\" label=\"SALAXY.NG1.SigningComponent.contactPersonLabel\"\r\n              label-true=\"SALAXY.NG1.SigningComponent.contactPersonLabelTrue\"></salaxy-input-boolean>\r\n            <div ng-if=\"!$ctrl.isContactPersonSigner\">\r\n              <salaxy-input name=\"contact_email\" label=\"SALAXY.NG1.SigningComponent.email\" sxy-email ng-model=\"$ctrl.model.company.contact.email\" ng-required=\"true\">\r\n              </salaxy-input>\r\n              <salaxy-input name=\"contact_telephone\" label=\"SALAXY.NG1.SigningComponent.tel\" sxy-mobile-phone ng-model=\"$ctrl.model.company.contact.telephone\" ng-required=\"true\">\r\n              </salaxy-input>\r\n            </div>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-md-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.SigningComponent.postalAddress\"></legend>\r\n            <salaxy-input label=\"SALAXY.NG1.SigningComponent.streetAddress\" name=\"Katuosoite\" ng-model=\"$ctrl.model.company.contact.street\" ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input label=\"SALAXY.NG1.SigningComponent.postalNumber\" name=\"Postinumero\" sxy-postal-code-fi ng-model=\"$ctrl.model.company.contact.postalCode\"\r\n              ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input label=\"SALAXY.NG1.SigningComponent.postOffice\" name=\"Postitoimipaikka\" ng-model=\"$ctrl.model.company.contact.city\" ng-required=\"true\"></salaxy-input>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n      <p sxy-html=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.bySigningAcceptTermsOfUse.html\"></p>\r\n      <div>\r\n        <div>\r\n          <button class=\"btn btn-primary\" ng-disabled=\"!signingForm.$valid || $ctrl.isSigninStarted\" ng-click=\"signingForm.$valid ? $ctrl.startDigitalSignature() : null\"\r\n            sxy-text=\"SALAXY.NG1.SigningComponent.signBtn\"></button> &nbsp; &nbsp;\r\n          <span ng-if=\"!signingForm.$valid\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.error\"></span>\r\n        </div>\r\n      </div>\r\n      <p style=\"margin-top: 10px;\" sxy-text=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.usePersonalMobileBanking\"></p>\r\n      <hr />\r\n      <div>\r\n        <div class=\"pull-right\">\r\n          <small><a ng-href=\"{{ $ctrl.getPdfPreviewAddress() }}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.downloadPDF\"></a>&nbsp;&nbsp;</small>\r\n          <button ng-click=\"$ctrl.save()\" ng-disabled=\"!signingForm.$valid\" class=\"btn btn-primary\"\r\n            sxy-text=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.updateForPreview\"></button>\r\n        </div>\r\n        <h3 sxy-text=\"SALAXY.NG1.SigningComponent.authoritativeQuestions.previewAttorney\"></h3>\r\n        <iframe ng-src=\"{{ $ctrl.getPdfPreviewAddress() }}\" style=\"width: 100%; height: 800px\"></iframe>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/account/UserInfo.html\",`﻿<div class=\"salaxy-component salaxy-user-info\">\r\n  <div class=\"table\">\r\n    <table>\r\n      <tr>\r\n        <td>\r\n          <salaxy-avatar style=\"font-size: 102px; margin-right: 40px;\" avatar=\"$ctrl.session.currentCredential.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td>\r\n          <p class=\"lead\" sxy-html=\"SALAXY.NG1.UserInfoComponent.description.html\"></p>\r\n        </td>\r\n      </tr>\r\n    </table>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table\">\r\n      <tr>\r\n        <th colspan=\"2\">\r\n          <h3 sxy-text=\"SALAXY.NG1.UserInfoComponent.userNameTitle\"></h3>\r\n        </th>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.UserInfoComponent.authType\" ps=\":\"></th>\r\n        <td>{{ 'AuthenticationMethod.' + $ctrl.session.currentCredential.authenticationMethod | sxyEnum }}</td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.UserInfoComponent.userName\" ps=\":\"></th>\r\n        <td>{{ $ctrl.session.currentCredential.id }}</td>\r\n      </tr>\r\n      <tr ng-if=\"$ctrl.session.currentCredential.authenticationMethod != 'salaxy' && $ctrl.session.currentCredential.authenticationMethod != 'x509'\">\r\n        <th sxy-text=\"SALAXY.NG1.UserInfoComponent.email\" ps=\":\"></th>\r\n        <td>{{ $ctrl.session.currentCredential.email }}</td>\r\n      </tr>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.UserInfoComponent.name\" ps=\":\"></th>\r\n        <td>{{ $ctrl.session.currentCredential.avatar.displayName }}</td>\r\n      </tr>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/2022/CalcEmployment.html\",`<div class=\"salaxy-component salaxy-calc-employment\">\r\n  <div ng-if=\"!$ctrl.current.worker.employmentId\" class=\"alert alert-danger\">\r\n    <strong>Error: Not supported</strong>\r\n    <p>Tämä komponentti ei tue uuden Työntekijän valintaa (implement EmploymentSelect)</p>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.worker.employmentId\">\r\n    <salaxy-form-group class=\"select-worker\" name=\"worker\" label=\"SALAXY.NG1_Pages.Calc.History.workerLabel\">\r\n      <!--\r\n        TODO: Need to create Employment relation selection component!\r\n        <button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.current.worker=null;todo()\">Vaihda...</button>\r\n      -->\r\n      <div class=\"salaxy-worker-item\">\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"$ctrl.current.worker.avatar\"></salaxy-avatar>\r\n        <b>{{ $ctrl.current.worker.avatar.displayName }} ({{$ctrl.current.worker.paymentData.socialSecurityNumberValid}}) </b> <br />\r\n        <small>\r\n          <div>IBAN: {{ $ctrl.current.worker.paymentData.ibanNumber | sxyIban }}</div>\r\n        </small>\r\n      </div>\r\n    </salaxy-form-group>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/2022/CalcRowsEditor.html\",`<div class=\"salaxy-component salaxy-calc-rows-editor salaxy-calc-rows-2022-editor\" ng-switch=\"$ctrl.type\">\r\n  <div ng-switch-when=\"salary-defaults\" class=\"salaxy-calc-rows-editor-worktime-import\">\r\n    <!-- TODO: Will be replaced by new row type editors -->\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.action\"></th>\r\n          <th colspan=\"2\">{{ $ctrl.title | sxyTranslate }}</th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.DateRange.labelStartAndEndDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n          <td style=\"width: 25%;\">\r\n            <salaxy-input-enum type=\"select\" label-type=\"plain\" ng-model=\"row.source\"\r\n              filter=\"{{$ctrl.rowSources}}\" hidden-options=\"''\"\r\n              name=\"{{ 'source' + $index }}\" enum=\"CalculationRowSource\"></salaxy-input-enum>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td style=\"width: 40%;\">\r\n            <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div ng-if=\"row.count && row.count != 1\"><small class=\"text-muted\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small></div>\r\n            <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n              {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n            </small>\r\n            <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n              <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n              <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                <a href=\"\" ng-click=\"$ctrl.showEdit(row, 'auto')\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n              </small>\r\n            </span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ row.period | sxyDateRange }}&nbsp;&nbsp;</div>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <div class=\"pull-right\">{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <ng-transclude ng-transclude-slot=\"footer\">\r\n      <footer>\r\n        <p><b>{{'SALAXY.NG1.CalcRowsComponent.editor.addNewRow' | sxyTranslate}}:</b></p>\r\n        <table>\r\n          <tbody>\r\n            <tr>\r\n              <td style=\"width: 40%;\">\r\n                <salaxy-input-enum type=\"select\" label-type=\"plain\" ng-model=\"$ctrl.newRow.source\"\r\n                  filter=\"{{$ctrl.rowSources}}\" hidden-options=\"''\"\r\n                  name=\"newRowSource\" enum=\"CalculationRowSource\"></salaxy-input-enum>\r\n              </td>\r\n              <td style=\"width: 40%;\">\r\n                <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\"\r\n                  on-row-changed=\"$ctrl.commitNewRow(true)\" row-types=\"$ctrl.rowTypes\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n              </td>\r\n              <td>\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                    sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </footer>\r\n    </ng-transclude>\r\n  </div>\r\n  <div ng-switch-when=\"salary-defaults-temp2\" class=\"salaxy-calc-rows-editor-worktime-import\">\r\n    <!-- TODO: Will be replaced by new row type editors -->\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">{{ $ctrl.title | sxyTranslate }}</th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.DateRange.labelStartAndEndDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td style=\"width: 40%;\">\r\n            <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div ng-if=\"row.count && row.count != 1\"><small class=\"text-muted\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small></div>\r\n            <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n              {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n            </small>\r\n            <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n              <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n              <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                <a href=\"\" ng-click=\"$ctrl.showEdit(row, 'auto')\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n              </small>\r\n            </span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ row.period | sxyDateRange }}&nbsp;&nbsp;</div>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <div class=\"pull-right\">{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <ng-transclude ng-transclude-slot=\"footer\">\r\n      <footer>\r\n        <table>\r\n          <tbody>\r\n            <tr>\r\n              <td><b>{{'SALAXY.NG1.CalcRowsComponent.editor.addNewRow' | sxyTranslate}}:</b></td>\r\n              <td>\r\n                <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\"\r\n                  on-row-changed=\"$ctrl.commitNewRow(true)\" row-types=\"$ctrl.rowTypes\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n              </td>\r\n              <td>\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                    sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </footer>\r\n    </ng-transclude>\r\n  </div>\r\n  <div ng-switch-when=\"worktime-import\" class=\"salaxy-calc-rows-editor-worktime-import\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th>Validointi</th>\r\n          <th colspan=\"2\">\r\n            <div>Työsuhteen ID</div>\r\n            <div>Henkilötunnus</div>\r\n          </th>\r\n          <th colspan=\"2\">{{ $ctrl.title | sxyTranslate }}</th>\r\n          <th>\r\n            <div>Rivityyppi</div>\r\n            <div>Alalaji</div>\r\n          </th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n          <td ng-if=\"row.validation.isValid\">\r\n            <div class=\"text-success\"><b>OK</b></div>\r\n          </td>\r\n          <td ng-if=\"row.validation.isValid == null\">\r\n            <div class=\"text-muted\">Ei validointia</div>\r\n          </td>\r\n          <td ng-if=\"row.validation.isValid === false\">\r\n            <div class=\"text-danger\"><salaxy-validation-summary api-validation=\"row.validation\" layout=\"minimal\"></salaxy-validation-summary></div>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"row.$avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td ng-if=\"row.$avatar\">\r\n            <div>{{ row.$avatar.sortableName }}</div>\r\n            <div>{{ row.personalId || \"-\" }} ({{ row.employmentType || \"-\" }})</div>\r\n          </td>\r\n          <td ng-if=\"!row.$avatar\">\r\n            <div>{{ row.employmentId || \"-\" }}</div>\r\n            <div>{{ row.personalId || \"-\" }} ({{ row.employmentType || \"-\" }})</div>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div ng-if=\"row.count && row.count != 1\"><small class=\"text-muted\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small></div>\r\n            <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n              {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n            </small>\r\n            <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n              <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n              <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                <a href=\"\" ng-click=\"$ctrl.showEdit(row, 'auto')\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n              </small>\r\n            </span>\r\n          </td>\r\n          <td>\r\n            <div>{{ (\"CalculationRowType.\" + row.rowType | sxyEnum ) || \"-\" }}</div>\r\n            <div>{{ row.data.kind || \"-\" }}</div>\r\n          </td>\r\n          <td>\r\n            <div class=\"pull-right\">{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-switch-when=\"worktime-import-employment\" class=\"salaxy-calc-rows-editor-worktime-import\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th>Valiointi</th>\r\n          <th class=\"right\">\r\n            <div>Palkkakausi</div>\r\n            <div>Tila</div>\r\n          </th>\r\n          <th colspan=\"2\">{{ $ctrl.title | sxyTranslate }}</th>\r\n          <th>\r\n            <div>Rivityyppi</div>\r\n            <div>Alalaji</div>\r\n          </th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n          <td ng-if=\"row.validation.isValid\">\r\n            <div class=\"text-success\">\r\n              <b>OK</b>\r\n              <a ng-href=\"{{ '#/payroll/details/' + row.data.payrollId }}\" ng-if=\"row.data.payrollId\">Palkkalista</a>\r\n            </div>\r\n          </td>\r\n          <td ng-if=\"row.validation.isValid == null\">\r\n            <div class=\"text-muted\">Ei validointia</div>\r\n          </td>\r\n          <td ng-if=\"row.validation.isValid === false\">\r\n            <div class=\"text-danger\"><salaxy-validation-summary api-validation=\"row.validation\" layout=\"minimal\"></salaxy-validation-summary></div>\r\n          </td>\r\n          <td class=\"right\" ng-switch=\"row.status\">\r\n            <div>{{ row.period | sxyDateRange }}</div>\r\n            <div ng-switch-when=\"preview\" class=\"text-warning\"><b>Esikatselu</b></div>\r\n            <div ng-switch-when=\"new\" class=\"text-primary\"><b>Uusi (hyväksytty)</b></div>\r\n            <div ng-switch-when=\"deleted\" class=\"text-danger\"><s>Poistettu</s></div>\r\n            <div ng-switch-when=\"error\" class=\"text-danger\"><b>Virheitä</b></div>\r\n            <div ng-switch-when=\"committed\" class=\"text-success\"><b>Lähetetty</b></div>\r\n            <div ng-switch-when=\"ignored\" class=\"text-muted\"><s>Ei huomioida</s></div>\r\n            <div ng-switch-when=\"edited\" class=\"text-primary\">Käsin syötetty</div>\r\n            <div ng-switch-default>{{ row.status }}</div>\r\n          </td>\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div ng-if=\"row.count && row.count != 1\"><small class=\"text-muted\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small></div>\r\n            <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n              {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n            </small>\r\n            <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n              <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n              <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                <a href=\"\" ng-click=\"$ctrl.showEdit(row, 'auto')\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n              </small>\r\n            </span>\r\n          </td>\r\n          <td>\r\n            <div>{{ (row.rowType || 'unknown') == \"unknown\" ? \"-\" : (\"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div>{{ row.data.kind || \"-\" }}</div>\r\n          </td>\r\n          <td>\r\n            <div class=\"pull-right\">{{ $ctrl.getRowTotal(row) ? ($ctrl.getRowTotal(row) | currency) : \"-\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <input type=\"checkbox\" ng-model=\"row.data.isSelected\" style=\"margin-right: 8px;margin-top: 10px;\" />\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n            <salaxy-json-formatter key=\"'js'\" json=\"row\" open=\"2\" type=\"dialog\" btn-class=\"btn btn-default\" ></salaxy-json-formatter>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-switch-default class=\"row\">\r\n    <div class=\"col-sm-6\">\r\n      <table class=\"table table-condensed\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\" class=\"uppercase\">{{ $ctrl.title || ('SALAXY.NG1.CalcRowsComponent.editor.calcRow' | sxyTranslate) }}</th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n            <th></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n            <td width=\"42px\">\r\n              <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n                avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n            </td>\r\n            <td width=\"100%\">\r\n              <div class=\"pull-right\">{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n              <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n              <div ng-if=\"row.count && row.count != 1\"><small class=\"text-muted\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small></div>\r\n              <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n                {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n              </small>\r\n              <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n                <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n                <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                  <a href=\"\" ng-click=\"$ctrl.showEdit(row, 'auto')\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n                </small>\r\n              </span>\r\n            </td>\r\n            <td class=\"right\">\r\n              <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n                title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n                <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <ng-transclude ng-transclude-slot=\"footer\">\r\n        <footer>\r\n          <p><b>{{'SALAXY.NG1.CalcRowsComponent.editor.addNewRow' | sxyTranslate}}:</b></p>\r\n          <table>\r\n            <tbody>\r\n              <tr>\r\n                <td style=\"width: 100%;\">\r\n                  <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\"\r\n                    on-row-changed=\"$ctrl.commitNewRow(true)\" row-types=\"$ctrl.rowTypes\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n                </td>\r\n                <td>\r\n                  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                      sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </footer>\r\n      </ng-transclude>\r\n    </div>\r\n    <div class=\"col-sm-6 hidden-xs salaxy-calc-rows-editor-details-container\">\r\n      <ng-include ng-if=\"$ctrl.current\" src=\"'salaxy-components/calc/rows/CalcRows2019EditDialog.html'\"></ng-include>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/2022/CalcUsecase.html\",`<div class=\"salaxy-component salaxy-calc-usecase\" ng-controller=\"NaviController as $naviCtrl\">\r\n\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div class=\"toolbar calc-toolbar\" ng-if=\"$ctrl.current\">\r\n    <div class=\"btn-group\" uib-dropdown ng-if=\"$ctrl.current.worker.employmentId\">\r\n      <button id=\"workerBtn\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        <salaxy-avatar avatar=\"$ctrl.current.worker.avatar\" style=\"font-size: 2em; margin: -5px 0px -5px -10px\"></salaxy-avatar>  \r\n        {{ $ctrl.current.worker.avatar.displayName }}\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"workerBtn\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.isWorkerInfoOpen = true\" sxy-text=\"SALAXY.NG1.CalcUsecase.showAdditionalInfo\"></a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showWorkerEditDialog()\" sxy-text=\"SALAXY.NG1.CalcUsecase.editWorker\"></a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showRefreshAutoTaxcardDialog()\" sxy-text=\"SALAXY.NG1.CalcUsecase.checkAutomaticTaxCard\"></a></li>\r\n      </ul>\r\n    </div>\r\n   \r\n    <div class=\"pull-right\" ng-if=\"$ctrl.current.worker.employmentId && !$ctrl.usecases\">\r\n      <salaxy-calc-sharing-receipt-action ng-if=\"$ctrl.showAction('reject')\" button-class=\"btn btn-danger\" model=\"$ctrl\" type=\"'reject'\"></salaxy-calc-sharing-receipt-action>\r\n      <salaxy-calc-sharing-receipt-action ng-if=\"$ctrl.showAction('approve')\"  button-class=\"btn btn-success\" model=\"$ctrl\" type=\"'approve'\"></salaxy-calc-sharing-receipt-action>\r\n      <button ng-if=\"$ctrl.showAction('save')\" ng-disabled=\"$ctrl.isActionDisabled('save')\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      <salaxy-pay-button ng-if=\"$ctrl.showAction('pay')\" model=\"$ctrl.current\" mode=\"pay-button\" style=\"display: inline-block\" ng-ref=\"$payButton\" disabled=\"!$payButton.isChannelDefined\"></salaxy-pay-button>\r\n      <salaxy-pay-button ng-if=\"$ctrl.showAction('pay')\" model=\"$ctrl.current\" mode=\"channel-select\" style=\"display: inline-block\"></salaxy-pay-button>\r\n    \r\n      <div class=\"btn-group\" uib-dropdown>\r\n        <button id=\"actionsBtn\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n          ...\r\n        </button>\r\n        <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"actionsBtn\">\r\n          <li role=\"menuitem\" ng-if=\"$ctrl.showAction('recalculate')\">\r\n            <a href=\"\" ng-click=\"$ctrl.recalculate()\" sxy-text=\"SALAXY.NG1.CalcUsecase.recalculate\"></a>\r\n          </li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showReportDialog('salarySlip')\" sxy-text=\"SALAXY.NG1.CalcUsecase.reports\" ps=\"...\"></a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showUsecaseInfo()\" sxy-text=\"SALAXY.NG1.CalcUsecase.usecase\"></a></li>\r\n          \r\n          <li role=\"menuitem\" ng-if=\"$ctrl.showAction('cancel')\">\r\n            <a href=\"\" ng-click=\"$ctrl.cancel()\" sxy-text=\"SALAXY.NG1.CalcUsecase.cancelPayment\"></a>\r\n          </li>\r\n          <li role=\"menuitem\" ng-if=\"$ctrl.showAction('copyAsNew')\">\r\n            <a href=\"\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.NG1.CalcUsecase.copy\"></a>\r\n          </li>\r\n          <li role=\"menuitem\" ng-if=\"$ctrl.showAction('showPaymentDialog')\">\r\n            <a href=\"\" ng-click=\"$ctrl.showPaymentDialog()\" sxy-text=\"SALAXY.NG1.CalcUsecase.showPaymentInfo\">Näytä maksun tiedot</a>\r\n          </li>\r\n\r\n          <li role=\"menuitem\" ng-if=\"$ctrl.showAction('delete')\">\r\n            <a href=\"\" ng-click=\"$ctrl.delete()\" ng-disabled=\"$ctrl.isActionDisabled('delete')\" sxy-text=\"SALAXY.NG1.CalcUsecase.deleteCalc\"></a>\r\n          </li>\r\n          <li role=\"menuitem\" style=\"margin-left: 20px;\">\r\n            <salaxy-json-formatter key=\"'JSON Data'\" json=\"$ctrl.current\" open=\"2\" type=\"dialog\"></salaxy-json-formatter>\r\n          </li>\r\n        </ul>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"worker-info-wrapper\" uib-collapse=\"!$ctrl.isWorkerInfoOpen\">\r\n    <button class=\"btn btn-transparent close-btn btn-sm\" ng-click=\"$ctrl.isWorkerInfoOpen = false\"><i class=\"fa fa-times\"></i></button>\r\n    <salaxy-calc-worker-info model=\"$ctrl.current\"></salaxy-calc-worker-info>\r\n  </div>\r\n  <div ng-if=\"$ctrl.usecases\">\r\n    <h2 sxy-text=\"SALAXY.NG1.CalcUsecase.selectCalculationType\"></h2>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6 col-md-4\" ng-repeat=\"usecase in $ctrl.usecases\">\r\n        <div class=\"thumbnail\">\r\n          <div class=\"text-center thumbnail-pic-fixed clickable\" style=\"height: 150px;position: relative;\" ng-click=\"$ctrl.setUsecase(usecase.uri)\">\r\n            <img ng-if=\"usecase.data.icon[0] == 'h'\" ng-src=\"{{usecase.data.icon}}\">\r\n            <div ng-if=\"usecase.data.icon[0] != 'h'\" class=\"bg-primary thumbnail-pic-icon\">\r\n              <i class=\"fa\" ng-class=\"(usecase.data.icon || 'fa') == 'fa' ? 'fa-euro' : usecase.data.icon\" aria-hidden=\"true\"></i>\r\n            </div>\r\n            <span class=\"badge pull-right bg-info\" ng-if=\"usecase.status=='default'\" sxy-text=\"SALAXY.NG1.CalcUsecase.default\"></span>\r\n            <salaxy-avatar avatar=\"usecase.ownerInfo.avatar\" style=\"font-size: 2em; position: absolute; right: 10px; bottom: 10px\"></salaxy-avatar>\r\n          </div>\r\n          <div class=\"caption\">\r\n            <h3 class=\"truncate\">{{ usecase.shortText }}</h3>\r\n            <p style=\"height: 80px;overflow: hidden\">{{ usecase.data.description }}</p>\r\n            <p>\r\n              <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.setUsecase(usecase.uri)\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n            </p>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current && !$ctrl.usecases\">\r\n    \r\n    <div ng-if=\"!$ctrl.usecase.defaultView\" style=\"margin-top: 6px\">\r\n      <salaxy-calc model=\"$ctrl\"></salaxy-calc>\r\n    </div>\r\n    <div ng-if=\"$ctrl.usecase.defaultView\">\r\n      <div ng-if=\"!$ctrl.current.worker.employmentId\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12 col-sm-7\">\r\n            <div class=\"intro-text\">\r\n              <h1 sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.selectWorker\"></h1>\r\n              <p sxy-html=\"SALAXY.NG1.CalcDetailsWorkerComponent.myWorkers.description.html\"></p>\r\n            </div>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-5\">\r\n            <button type=\"button\" class=\"btn add-new-worker btn-primary pull-right-sm\" style=\"margin-bottom:5px;\" ng-click=\"$ctrl.showNewWorkerDialog()\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.newWorker.cta\"></button>\r\n          </div>\r\n          <div class=\"col-xs-12\">\r\n            <div class=\"table-responsive\">\r\n              <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id, true)\"></salaxy-employment-list>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div>\r\n        \r\n        <ng-include src=\"$ctrl.usecase.defaultView\"></ng-include>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/Calc.html\",`<div class=\"salaxy-component salaxy-calc\">\r\n  <div class=\"salaxy-calc-overview\" ng-if=\"!$ctrl.current\">\r\n    <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  </div>\r\n\r\n  <!--salaxy-varma-banner calc=\"$ctrl.current\" ng-if=\"('auth' | sxyIsInRole) && ('company' | sxyIsInRole) && $ctrl.current.workflow.status == 'draft'\"></salaxy-varma-banner-->\r\n  <div class=\"row\" sxy-if-role=\"worker\">\r\n    <div class=\"col-xs-12 spacer-bottom\" ng-if=\"$ctrl.current.workflow.status == 'draft' || $ctrl.current.id == null\">\r\n      <p class=\"lead text-center\" sxy-text=\"SALAXY.NG1.CalcComponent.introWorker\"></p>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isReadOnly && $ctrl.current\" class=\"btn-toolbar calc-toolbar\">\r\n    <div class=\"btn-group\" role=\"group\" ng-if=\"!$ctrl.isReadOnly\">\r\n      <div ng-if=\"'company' | sxyIsInRole\" ng-controller=\"CompanyAccountController as $company\" style=\"padding: 8px;\">\r\n        <salaxy-workflow-badge ng-if=\"$company.current\" mode=\"horizontal\" model=\"$company.current\" api-ctrl=\"$company\" wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"salaxy-calc-overview\" ng-if=\"$ctrl.current\">\r\n    <div sxy-if-role=\"worker\" class=\"visible-xxs\">\r\n      <div class=\"spacer-bottom\" ng-if=\"$ctrl.current.workflow.status == 'draft' || $ctrl.current.workflow.status == 'workerRequested' || $ctrl.current.workflow.status == 'workerRequestAccepted' || $ctrl.current.workflow.status == 'workerRequestDeclined' || $ctrl.current.workflow.status == 'paymentWorkerCopy'\">\r\n        <salaxy-calc-sharing-info model=\"$ctrl\"></salaxy-calc-sharing-info>\r\n      </div>\r\n    </div>\r\n    <div class=\"calc-container\" style=\"display:block;\">\r\n      <div class=\"salaxy-calc-step-container step1\" ng-class=\"{ 'active': $ctrl.calcSections.get('worker').isActive }\">\r\n        <div class=\"panel panel-info salaxy-calc-overview-panel\">\r\n          <div class=\"panel-heading\" ng-click=\"$ctrl.calcSections.toggleActive('worker')\">\r\n            <i class=\"fa fa-times fa-fw pull-right close\"></i> <span class=\"overview-title\" sxy-text=\"SALAXY.NG1.CalcComponent.panelWorker.heading\"></span>\r\n          </div>\r\n          <div class=\"panel-body\">\r\n            <div class=\"content-overview\" ng-click=\"$ctrl.calcSections.toggleActive('worker')\">\r\n              <div ng-if=\"!$ctrl.calcSections.get('worker').isSelectionDone\">\r\n                <a href=\"\">\r\n                  <h3 class=\"text-center\" sxy-html=\"SALAXY.NG1.CalcComponent.panelWorker.overview.html\"></h3>\r\n                </a>\r\n              </div>\r\n              <div class=\"salaxy-calc-overview-worker\" ng-if=\"$ctrl.calcSections.get('worker').isSelectionDone\">\r\n                <salaxy-avatar ng-if=\"$ctrl.current.worker.avatar.displayName\" avatar=\"$ctrl.current.worker.avatar\"></salaxy-avatar>\r\n                <strong>{{$ctrl.current.worker.avatar.displayName || (\"SALAXY.NG1.CalcComponent.panelWorker.noSelection\" | sxyTranslate) }}</strong><br />\r\n                <div ng-if=\"!$ctrl.isReadOnly\" ng-controller=\"EmploymentCrudController as $employment\"\r\n                  ng-init=\"$employment.queryResult={};$employment.getOData({ '$filter': 'id eq \\\\'' +  $ctrl.current.worker.employmentId + '\\\\''}, $employment.queryResult)\">\r\n                  <salaxy-workflow-badge mode=\"horizontal\" ng-if=\"$employment.queryResult.items.length > 0\" model=\"$employment.queryResult.items[0]\" api-ctrl=\"$employment\"\r\n                    wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n                </div>\r\n                <div class=\"salaxy-calc-worker-info-texts\" ng-if=\"$ctrl.current.worker.avatar.displayName\">\r\n                  <div class=\"text-danger\" ng-if=\"$ctrl.taxUi.status == 'missing'\">\r\n                    {{ $ctrl.taxUi.shortText }}\r\n\r\n                  </div>\r\n                  <div ng-if=\"$ctrl.taxUi.status == 'ok'\">{{ $ctrl.taxUi.shortText }}</div>\r\n                  <div>{{ $ctrl.current.worker.paymentData.ibanNumber ? ('SALAXY.NG1.WorkerInfo.ibanOk'|sxyTranslate) : ('SALAXY.NG1.WorkerInfo.noIbanNumber' | sxyTranslate) }}\r\n                  </div>\r\n                  <div class=\"truncate\">{{ $ctrl.current.info.occupationCode | sxyOccupation : \"code-label\" }}</div>\r\n                  <div class=\"truncate\">{{ $ctrl.getPensionText(true) }}</div>\r\n                </div>\r\n              </div>\r\n            </div>\r\n            <div class=\"content-details\">\r\n              <div ng-if=\"!$ctrl.isReadOnly\" ng-controller=\"EmploymentCrudController as $employment\" class=\"text-right\" style=\"padding: 8px;\"\r\n                ng-init=\"$employment.queryResult={};$employment.getOData({ '$filter': 'id eq \\\\'' +  $ctrl.current.worker.employmentId + '\\\\''}, $employment.queryResult)\">\r\n                <salaxy-workflow-badge mode=\"horizontal\" ng-if=\"$employment.queryResult.items.length > 0\" model=\"$employment.queryResult.items[0]\" api-ctrl=\"$employment\"\r\n                  wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n              </div>\r\n              <ng-include src=\"'salaxy-components/calc/details/worker.html'\"></ng-include>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.isHousehold\" class=\"salaxy-calc-step-container step2\" ng-class=\"{ 'active': $ctrl.calcSections.get('household-usecase').isActive }\">\r\n        <div class=\"panel panel-warning salaxy-calc-overview-panel\">\r\n          <div class=\"panel-heading\" ng-click=\"$ctrl.calcSections.toggleActive('household-usecase')\">\r\n            <i class=\"fa fa-times fa-fw pull-right close\"></i><span class=\"overview-title\" sxy-text=\"SALAXY.NG1.CalcComponent.panelHouseHold.heading\"></span>\r\n          </div>\r\n          <div class=\"panel-body\">\r\n            <div class=\"content-overview\" ng-click=\"$ctrl.calcSections.toggleActive('household-usecase')\">\r\n              <div ng-show=\"!$ctrl.calcSections.get('household-usecase').isSelectionDone\">\r\n                <a href=\"\">\r\n                  <h3 class=\"text-center\" sxy-html=\"SALAXY.NG1.CalcComponent.panelHouseHold.overview.html\"></h3>\r\n                </a>\r\n              </div>\r\n              <div ng-show=\"$ctrl.calcSections.get('household-usecase').isSelectionDone\">\r\n                <div>{{ $ctrl.getUsecaseText() | sxyTranslate}}</div>\r\n              </div>\r\n            </div>\r\n            <div class=\"content-details\">\r\n              <salaxy-calc-household-usecase ng-if=\"$ctrl.currentCalc\" calc=\"$ctrl.currentCalc\"></salaxy-calc-household-usecase>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"!$ctrl.isHousehold\" class=\"salaxy-calc-step-container step2\" ng-class=\"{ 'active': $ctrl.calcSections.get('worktime').isActive }\">\r\n        <div class=\"panel panel-warning salaxy-calc-overview-panel\">\r\n          <div class=\"panel-heading\" ng-click=\"$ctrl.calcSections.toggleActive('worktime');$ctrl.worktimeCtrl.loadEmployment()\">\r\n            <i class=\"fa fa-times fa-fw pull-right close\"></i><span class=\"overview-title\" sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.heading\"></span>\r\n          </div>\r\n          <div class=\"panel-body\">\r\n            <div class=\"content-overview\" ng-click=\"$ctrl.calcSections.toggleActive('worktime');$ctrl.worktimeCtrl.loadEmployment()\">\r\n              <div ng-show=\"!$ctrl.calcSections.get('worktime').isSelectionDone\">\r\n                <a href=\"\">\r\n                  <h3 class=\"text-center\" sxy-html=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.html\"></h3>\r\n                </a>\r\n              </div>\r\n              <div ng-show=\"$ctrl.calcSections.get('worktime').isSelectionDone\">\r\n                <div><strong>{{ $ctrl.getDatesRangeText() | sxyTranslate }}</strong></div>\r\n                <table>\r\n                  <tbody>\r\n                    <tr>\r\n                      <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.salaryDate\"></td>\r\n                      <td class=\"right\" ng-if=\"!$ctrl.currentCalc.workflow.requestedSalaryDate\" sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.now\"></td>\r\n                      <td class=\"right\" ng-if=\"$ctrl.currentCalc.workflow.requestedSalaryDate\">{{ $ctrl.currentCalc.workflow.salaryDate | sxyDate }}</td>\r\n                    </tr>\r\n                  </tbody>\r\n                </table>\r\n                <table>\r\n                  <tbody>\r\n                    <tr>\r\n                      <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.leavesDays\"></td>\r\n                      <td class=\"right\">{{ $ctrl.calculatePeriodDays('leavesDays') | sxyCount : 'day' }}</td>\r\n                    </tr>\r\n                    <tr>\r\n                      <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.absencesDays\"></td>\r\n                      <td class=\"right\">{{ $ctrl.calculatePeriodDays('absencesDays') | sxyCount : 'day' }}</td>\r\n                    </tr>\r\n                    <tr>\r\n                      <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.paidAbsencesDays\"></td>\r\n                      <td class=\"right\">{{ $ctrl.calculatePeriodDays('paidAbsencesDays') | sxyCount : 'day' }}</td>\r\n                    </tr>\r\n                  </tbody>\r\n                </table>\r\n              </div>\r\n            </div>\r\n            <div class=\"content-details\">\r\n              <salaxy-calc-worktime ng-ref=\"$ctrl.worktimeCtrl\" ng-if=\"$ctrl.currentCalc\" calc=\"$ctrl.currentCalc\"></salaxy-calc-worktime>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"salaxy-calc-step-container step3\" ng-class=\"{ 'active': $ctrl.calcSections.get('salary').isActive }\">\r\n        <div class=\"panel panel-success salaxy-calc-overview-panel\">\r\n          <div class=\"panel-heading\" ng-click=\"$ctrl.calcSections.toggleActive('salary')\">\r\n            <i class=\"fa fa-times fa-fw pull-right close\"></i><span class=\"overview-title\" sxy-text=\"SALAXY.NG1.CalcComponent.panelSalary.heading\"></span>\r\n          </div>\r\n          <div class=\"panel-body\">\r\n            <div class=\"content-overview\" ng-click=\"$ctrl.calcSections.toggleActive('salary')\">\r\n              <table>\r\n                <tbody>\r\n                  <tr>\r\n                    <td>\r\n                      {{ $ctrl.calcLogic.hasCompensation ? ('SALAXY.NG1.CalcDetailsExpensesComponent.foreclosurePayment.infoCompensation' | sxyTranslate) :\r\n                      ('SALAXY.NG1.CalcDetailsExpensesComponent.foreclosurePayment.infoSalary' | sxyTranslate) }}\r\n                    </td>\r\n                    <td class=\"right\">{{$ctrl.currentCalc.result.totals.totalBaseSalary || 0 | currency : \"\" : 2}} €</td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td sxy-text=\"SALAXY.NG1.CalcDetailsExpensesComponent.titleAdditions\"></td>\r\n                    <td class=\"right\">{{ ($ctrl.currentCalc.result.totals.totalGrossSalary - $ctrl.currentCalc.result.totals.totalBaseSalary) || 0 | currency : \"\" : 2}} €</td>\r\n                  </tr>\r\n                  <tr class=\"total\">\r\n                    <td sxy-text=\"SALAXY.NG1.GeneralCalcDetailLabels.total\"></td>\r\n                    <td class=\"right\">{{$ctrl.currentCalc.result.totals.totalGrossSalary || 0 | currency : \"\" : 2}} €</td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </div>\r\n            <div class=\"content-details\">\r\n              <ng-include src=\"'salaxy-components/calc/details/salary.html'\"></ng-include>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"salaxy-calc-step-container step4\" ng-class=\"{ 'active': $ctrl.calcSections.get('expenses').isActive }\">\r\n        <div class=\"panel panel-danger salaxy-calc-overview-panel\">\r\n          <div class=\"panel-heading\" ng-click=\"$ctrl.calcSections.toggleActive('expenses')\">\r\n            <i class=\"fa fa-times fa-fw pull-right close\"></i> <span class=\"overview-title\" sxy-text=\"SALAXY.NG1.CalcComponent.panelExpenses.heading\"></span>\r\n          </div>\r\n          <div class=\"panel-body\">\r\n            <div class=\"content-overview\" ng-click=\"$ctrl.calcSections.toggleActive('expenses')\">\r\n              <table>\r\n                <tbody>\r\n                  <tr>\r\n                    <td sxy-text=\"SALAXY.NG1.CalcDetailsExpensesComponent.compensations.title\"></td>\r\n                    <td class=\"right\">{{ $ctrl.currentCalc.result.totals.totalExpenses || 0 | currency : '' : 2}}€</td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td sxy-text=\"SALAXY.NG1.CalcDetailsExpensesComponent.benefits.title\"></td>\r\n                    <td class=\"right\">{{ $ctrl.currentCalc.result.workerCalc.benefits || 0 | currency : '' : 2}}€</td>\r\n                  </tr>\r\n                  <tr>\r\n                    <td sxy-text=\"SALAXY.NG1.CalcDetailsExpensesComponent.deductions\"></td>\r\n                    <td class=\"right\">{{ $ctrl.calcLogic.expensesTotal || 0 | currency : '' : 2}}€</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.isHousehold\">\r\n                    <td ng-if=\"$ctrl.calcLogic.childCareSubsidy\">Yks. hoid. tuki</td>\r\n                    <td ng-if=\"$ctrl.calcLogic.childCareSubsidy\" class=\"right\">{{ $ctrl.calcLogic.childCareSubsidy || 0 | currency : '' : 2}}€</td>\r\n                    <td colspan=\"2\" class=\"text-right\" ng-if=\"!$ctrl.calcLogic.childCareSubsidy\">\r\n                      <small>{{ $ctrl.isHouseholdDeductible ? (\"SALAXY.NG1.CalcComponent.panelExpenses.householdExpense\" | sxyTranslate) :\r\n                        (\"SALAXY.NG1.CalcComponent.panelExpenses.noHouseholdExpenses\" | sxyTranslate) }}</small>\r\n                    </td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </div>\r\n            <div class=\"content-details\">\r\n              <ng-include src=\"'salaxy-components/calc/details/expenses.html'\"></ng-include>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <salaxy-calc-new-intro model=\"$ctrl\"></salaxy-calc-new-intro>\r\n  <salaxy-calc-results model=\"$ctrl\"></salaxy-calc-results>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcChart.html\",`<!-- <div class=\"hidden\">{{$ctrl.refresh($ctrl.chart)}}</div> -->\r\n<div ng-if=\"$ctrl.calc\" ng-init=\"$ctrl.init()\" class=\"salaxy-component salaxy-calc-chart chart-container\" ng-class=\"'salaxy-calc-chart-' + $ctrl.role + 'salaxy-calc-chart-' + $ctrl.chartType\" style=\"width: 100%; height: 300px; position: relative; min-height: 300px;\">\r\n  <canvas class=\"chart\" ng-class=\"$ctrl.chartType ==='bar' ? 'chart-bar' : 'chart-pie'\"></canvas>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/calc/CalcCostAccounting.html\",`<div class=\"salaxy-component salaxy-calc-cost-accounting\">\r\n\r\n  <div ng-if=\"$ctrl.isLegacy\">\r\n\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.CalcCostAccountingComponent.title\"></legend>\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th>{{('SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}</th>\r\n            <th class=\"right\">{{\"SALAXY.NG1.CalcCostAccountingComponent.percent\" | sxyTranslate}}</th>\r\n            <th class=\"right\">\r\n              <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.isReadOnly\" ng-click=\"$ctrl.costCenter.push({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"item in $ctrl.costCenter\">\r\n            <td>\r\n              <salaxy-input-enum ng-if=\"$ctrl.getOptions('costCenter').length\" ng-model=\"item.id\" type=\"typeahead\" label-format=\"text-value\" options=\"$ctrl.getOptions('costCenter')\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\"></salaxy-input-enum>\r\n              <salaxy-input ng-if=\"!$ctrl.getOptions('costCenter').length\" ng-model=\"item.id\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\">\r\n              </salaxy-input>\r\n            </td>\r\n            <td>\r\n              <salaxy-input-number ng-model=\"item.percent\" name=\"{{ 'percent' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\" unit=\"percent\"></salaxy-input-number>\r\n            </td>\r\n            <td class=\"text-right\">\r\n              <button ng-if=\"!$ctrl.isReadOnly\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.costCenter.splice($index, 1)\">\r\n                <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n        <tfoot>\r\n          <tr class=\"total\">\r\n            <td>{{\"SALAXY.UI_Terms.total\" | sxyTranslate}}</td>\r\n            <td class=\"right\">{{ $ctrl.getLegacySum() | sxyCount : 'percent' }}</td>\r\n            <td class=\"right\"></td>\r\n          </tr>\r\n        </tfoot>\r\n      </table>\r\n    </fieldset>\r\n  </div>\r\n\r\n  <div ng-if=\"!$ctrl.isLegacy && ( $ctrl.calc.accounting.dimensions.length > 0 || $ctrl.definitions.length > 0 )\">\r\n\r\n    <salaxy-cost-accounting ng-init=\"$ctrl.calc.accounting = ($ctrl.calc.accounting  || $ctrl.isReadOnly) ? $ctrl.calc.accounting : { dimensions: []}\" current=\"$ctrl.calc.accounting.dimensions\" scope=\"calculation\" dimensions=\"$ctrl.dimensions\" read-only=\"$ctrl.isReadOnly\"\r\n      input-mode=\"{{$ctrl.inputMode}}\"></salaxy-cost-accounting>\r\n\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isLegacy && !( $ctrl.calc.accounting.dimensions.length > 0 || $ctrl.definitions.length > 0 )\">\r\n    <salaxy-input name=\"costCenter\" ng-model=\"$ctrl.calc.info.costCenter\" label=\"SALAXY.NG1.CalcDetailsWorkerComponent.costCenter\" read-only=\"$ctrl.isReadOnly\" input-mode=\"{{$ctrl.inputMode}}\"></salaxy-input>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcDashboard.html\",`<div class=\"salaxy-component salaxy-calc-dashboard\">\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12\" ng-if=\"!$ctrl.hideButton\">\r\n      <salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\"></salaxy-action-button>\r\n    </div>\r\n    <div class=\"col-sm-6 col-xs-12\">\r\n      <salaxy-calc-list category=\"paid\" mode=\"panel\" limit-to=\"5\" read-only=\"$ctrl.readOnly\"></salaxy-calc-list>\r\n    </div>\r\n    <div class=\"col-sm-6 col-xs-12\">\r\n      <salaxy-calc-list category=\"draft\" mode=\"panel\" limit-to=\"5\" read-only=\"$ctrl.readOnly\"></salaxy-calc-list>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcEditor.html\",`<div>\r\n  <salaxy-validation-summary api-validation=\"$ctrl.validation\"></salaxy-validation-summary>\r\n</div>\r\n<div style=\"margin-top:30px; margin-bottom:30px;\">\r\n  \r\n  <h2 class=\"spacer-bottom\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.title\"></h2>\r\n  <!-- spinning icon or similar?-->\r\n  <button class=\"btn btn-primary btn-labeled-right\" ng-click=\"$ctrl.saveEdited()\"><span sxy-text=\"SALAXY.UI_Terms.save\"></span><i class=\"fa fa-save\"></i></button>\r\n  <!-- spinning icon or similar?-->\r\n  <button class=\"btn btn-default btn-labeled-right\" ng-click=\"$ctrl.refresh()\"><span sxy-text=\"SALAXY.UI_Terms.refresh\"></span><i class=\"fa fa-refresh\" ng-class=\"{'fa-spin' : $ctrl.loaders['default'] }\"></i></button>\r\n\r\n  <div class=\"pull-right\">Alkuperäinen: {{$ctrl.base.updatedAt | date: 'd.M.yyyy HH:mm:ss'}} <button class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.changeBase()\">Vaihda...</button></div>\r\n</div>\r\n<div ng-if=\"$ctrl.current\" class=\"salaxy-component salaxy-calc-editor\">\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-6 \" style=\"margin-top:20px;\">\r\n      <div class=\"row spacer-bottom\">\r\n        <div class=\"col-md-6 col-xs-12 calc-editor-worker-details spacer-bottom\">\r\n          <legend>\r\n            <span sxy-text=\"SALAXY.NG1.CalcEditorComponent.workerTitle\"></span>\r\n            <button ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right\" ng-click=\"$ctrl.refresh('worker')\" title=\"Päivitä työntekijän tiedot\"><i class=\"\" ng-class=\"$ctrl.loaders['worker']  ? 'fa fa-refresh fa-spin' : 'glyphicon glyphicon-import'\"></i></button>\r\n            <a class=\"btn btn-xs btn-default pull-right btn-details\" href=\"#/employments/details/{{$ctrl.current.worker.employmentId}}\" ng-click=\"$ctrl.isRightSidebarOpen = true\" title=\"Tiedot / Muokkaa\" style=\"margin-right:2px;\"><i class=\"fa fa-info-circle\"></i></a>\r\n\r\n          </legend>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\">\r\n              <div class=\"avatar-container\">\r\n                <salaxy-avatar avatar=\"$ctrl.current.worker.avatar\"></salaxy-avatar>\r\n              </div>\r\n            </div>\r\n            <div class=\"col-xs-9\">\r\n              <strong>{{$ctrl.current.worker.avatar.displayName}}</strong>\r\n              <br>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"socialSecurityNumber\" ng-model=\"$ctrl.current.worker.paymentData.socialSecurityNumber\"></salaxy-input>\r\n              <div>&nbsp;</div>\r\n              <br>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-12\">\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"firstName\" ng-model=\"$ctrl.current.worker.avatar.firstName\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"lastName\" ng-model=\"$ctrl.current.worker.avatar.lastName\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"ibanNumber\" ng-model=\"$ctrl.current.worker.paymentData.ibanNumber\" sxy-iban></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"email\" ng-model=\"$ctrl.current.worker.contact.email\" sxy-email></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"telephone\" ng-model=\"$ctrl.current.worker.contact.telephone\" sxy-mobile-phone></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"street\" ng-model=\"$ctrl.current.worker.contact.street\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"postalCode\" ng-model=\"$ctrl.current.worker.contact.postalCode\" sxy-postal-code-fi></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"city\" ng-model=\"$ctrl.current.worker.contact.city\"></salaxy-input>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div class=\"col-md-6 col-xs-12 calc-editor-employer-details spacer-bottom\">\r\n          <legend>\r\n            <span sxy-text=\"SALAXY.NG1.CalcEditorComponent.employerTitle\"></span>\r\n            <button ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right\" ng-click=\"$ctrl.refresh('employer')\" title=\"Päivitä omat tiedot\"><i class=\"\"  ng-class=\"$ctrl.loaders['employer']  ? 'fa fa-refresh fa-spin' : 'glyphicon glyphicon-import'\"></i></button></legend>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\">\r\n              <div class=\"avatar-container\">\r\n                <salaxy-avatar avatar=\"$ctrl.current.employer.avatar\"></salaxy-avatar>\r\n              </div>\r\n            </div>\r\n            <div class=\"col-xs-9\">\r\n              <strong>{{$ctrl.current.employer.avatar.displayName}}</strong>\r\n              <br>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerOfficialId\" ng-model=\"$ctrl.current.employer.officialId\"></salaxy-input>\r\n              <div>&nbsp;</div>\r\n              <br>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-12\">       \r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerEmail\" ng-model=\"$ctrl.current.employer.contact.email\" sxy-email></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerTelephone\" ng-model=\"$ctrl.current.employer.contact.telephone\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerStreet\" ng-model=\"$ctrl.current.employer.contact.street\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerPostalCode\" ng-model=\"$ctrl.current.employer.contact.postalCode\"></salaxy-input>\r\n              <salaxy-input label-type=\"plain\" input-mode=\"openClose\" read-only=\"false\" name=\"employerCiy\" ng-model=\"$ctrl.current.employer.contact.city\"></salaxy-input>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"row spacer-bottom\">\r\n        <div class=\"col-md-6 col-xs-12 spacer-bottom\">\r\n          <form class=\"form-horizontal\" >\r\n            <fieldset>\r\n              <legend>\r\n                <span sxy-text=\"Työsuhteen tiedot\"></span>\r\n\r\n                <button ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right\" ng-click=\"$ctrl.refresh('employment')\" title=\"Päivitä työsuhdetiedot\"><i ng-class=\"$ctrl.loaders['employment']  ? 'fa fa-refresh fa-spin' : 'glyphicon glyphicon-import'\"></i></button>\r\n                <a class=\"btn btn-xs btn-default pull-right btn-details\" href=\"#/employments/details/{{$ctrl.current.worker.employmentId}}#employment\" ng-click=\"$ctrl.isRightSidebarOpen = true\" title=\"Tiedot / Muokkaa\" style=\"margin-right:2px;\"><i class=\"fa fa-info-circle\"></i></a>\r\n              </legend>\r\n              <salaxy-input-enum input-mode=\"openClose\"  enum=\"PensionCalculation\" name=\"PensionCalculation\" label=\"Sovellettava eläketurva\" ng-model=\"$ctrl.current.result.responsibilities.pensionCalculation\"></salaxy-input-enum>\r\n              <salaxy-input-enum input-mode=\"openClose\"  enum=\"PensionRule\" name=\"PensionRule\" label=\"Eläkemaksun laskentasääntö\" ng-model=\"$ctrl.current.result.responsibilities.pensionRule\"></salaxy-input-enum>\r\n              <salaxy-input-enum input-mode=\"openClose\"  enum=\"EmploymentRelationType\" name=\"EmploymentRelationType\" label=\"Työsuhde\" ng-model=\"$ctrl.current.result.responsibilities.employmentType\"></salaxy-input-enum>\r\n              \r\n              <salaxy-date-range input-mode=\"openClose\" ng-model=\"$ctrl.current.worktime.employmentPeriod\" label=\"Työsuhteen kesto\" name=\"employmentPeriod\"></salaxy-date-range>\r\n              <salaxy-input-enum input-mode=\"openClose\" ng-if=\"$ctrl.current.result.responsibilities.pensionCalculation == 'publicSector'\"  type=\"select\" name=\"employmentRegCodes\" disable-cache=\"true\"\r\n        options=\"$ctrl.getEmploymentRegCodeOptions()\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.employmentRegCode\" ng-model=\"$ctrl.current.result.responsibilities.employmentRegCode\"></salaxy-input-enum>\r\n              <salaxy-input-enum input-mode=\"openClose\" enum=\"TaxcardKind\" name=\"TaxcardKind\" label=\"Työsuhteessa käytettävä verokortti\" ng-model=\"$ctrl.current.result.responsibilities.employmentTaxcard\"></salaxy-input-enum>\r\n              <salaxy-input-enum input-mode=\"openClose\" enum=\"EmploymentRelationSalaryPaymentMethod\" name=\"SalaryPaymentMethod\" label=\"Palkanmaksutapa\" ng-model=\"$ctrl.current.result.responsibilities.salaryPaymentMethod\"></salaxy-input-enum>\r\n              <div ng-repeat=\"irIncomeEarnerType in $ctrl.current.result.responsibilities.irIncomeEarnerTypes\">\r\n                <salaxy-input-enum input-mode=\"openClose\"  enum=\"IncomeEarnerType\" name=\"IncomeEarnerType\" label=\"Tulonsaajan tyyppi\" ng-model=\"irIncomeEarnerType\"></salaxy-input-enum>\r\n              </div>\r\n\r\n              <salaxy-input-occupation-type  input-mode=\"openClose\" name=\"occupationCode\" ng-model=\"$ctrl.current.info.occupationCode\" label=\"Ammattiluokka vakuutukseen\" read-only=\"false\">\r\n              </salaxy-input-occupation-type>\r\n              <salaxy-input tooltip-html=\"&lt;a target=&#39;_blank&#39; href=&#39;https://www.keva.fi/tyonantajalle/elakemaksut/ammattinimikkeiden-haku/&#39;&gt;Info&lt;/a&gt;\" ng-if=\"$ctrl.current.result.responsibilities.pensionCalculation == 'publicSector'\"  input-mode=\"openClose\" name=\"occupationCode2\" ng-model=\"$ctrl.current.info.occupationCode2\" label=\"Keva:n ammattiluokka\" read-only=\"false\">\r\n              </salaxy-input>\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n        <div class=\"col-md-6 col-xs-12 spacer-bottom\">\r\n          <form class=\"form-horizontal\" ng-readonly=\"true\">\r\n            <fieldset>\r\n              <legend>\r\n                <span sxy-text=\"Verokortin tiedot\"></span>\r\n                <button ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right\" ng-click=\"$ctrl.refresh('taxcard')\" title=\"Päivitä verokortti\"><i  ng-class=\"$ctrl.loaders['taxcard']  ? 'fa fa-refresh fa-spin' : 'glyphicon glyphicon-import'\"></i></button>\r\n                <a ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right btn-details\" href=\"#/employments/details/{{$ctrl.current.worker.employmentId}}#taxcards\" ng-click=\"$ctrl.isRightSidebarOpen = true\" title=\"Tiedot / Muokkaa\" style=\"margin-right:2px;\"><i class=\"fa fa-info-circle\"></i></a>\r\n              </legend>\r\n\r\n              <salaxy-input-enum enum=\"TaxcardKind\" name=\"TaxcardKind\" label=\"Verokortti\" ng-model=\"$ctrl.current.worker.tax.snapshot.kind\"></salaxy-input-enum>\r\n              <salaxy-input name=\"forYear\" label=\"Vuodelle\" ng-model=\"$ctrl.current.worker.tax.snapshot.forYear\"></salaxy-input>\r\n           \r\n              <salaxy-form-group name=\"validity\" class=\"salaxy-read-only\" label=\"Voimassa\">\r\n                <div class=\"salaxy-read-only-value\">\r\n                  {{$ctrl.current.worker.tax.snapshot.validity.start | date}} - {{$ctrl.current.worker.tax.snapshot.validity.end | date}}\r\n                </div>\r\n              </salaxy-form-group>\r\n              <salaxy-input label=\"veroprosentti\" name=\"Veroprosentti\" unit=\"percent\" ng-model=\"$ctrl.current.worker.tax.snapshot.taxPercent\" require=\"true\"></salaxy-input>\r\n              <salaxy-input-number label=\"Tuloraja\" name=\"tuloraja\" unit=\"euro\" ng-model=\"$ctrl.current.worker.tax.snapshot.incomeLimit\" maxlength=\"10\"></salaxy-input-number>\r\n              <salaxy-input label=\"Lisäveroprosentti\" name=\"lisaveroprosentti\" unit=\"percent\" ng-model=\"$ctrl.current.worker.tax.snapshot.taxPercent2\"></salaxy-input>\r\n              <!--for admin, should be nullable-->\r\n              <salaxy-input-number input-mode=\"openClose\" name=\"fixedTaxAmount\" ng-model=\"$ctrl.current.worker.tax.fixedTaxAmount\" label=\"Kiinteä ennakonpidätyksen määrä\" read-only=\"'!admin' | sxyIsInRole\"></salaxy-input-number>\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n      </div>\r\n      <div class=\"row spacer-bottom\">\r\n        <div class=\"col-md-6 col-xs-12 spacer-bottom\">\r\n          <form class=\"form-horizontal\">\r\n            <fieldset>\r\n              <legend>\r\n                <span sxy-text=\"Vero, eläke- ja vakuutustiedot\"></span>\r\n                <button ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right\" ng-click=\"$ctrl.refresh('insurances')\" title=\"Päivitä vakuutustiedot\"><i  ng-class=\"$ctrl.loaders['insurances']  ? 'fa fa-refresh fa-spin' : 'glyphicon glyphicon-import'\"></i></button>\r\n\r\n                <a ng-if=\"'admin' | sxyIsInRole\" class=\"btn btn-xs btn-default pull-right btn-details\" href=\"#/settings/pro-settings\" title=\"Katso / Muokkaa\" ng-click=\"$ctrl.isRightSidebarOpen = true\" style=\"margin-right:2px;\"><i class=\"fa fa-info-circle\"></i></a>\r\n\r\n              </legend>\r\n\r\n              <salaxy-input-boolean input-mode=\"openClose\" label=\"Hoidan ennakonpidätyksen maksun itse\" name=\"taxAndSocialSecuritySelfPayment\" ng-model=\"$ctrl.current.result.responsibilities.taxAndSocialSecuritySelfPayment\"></salaxy-input-boolean>\r\n              \r\n              <salaxy-input-enum input-mode=\"openClose\" label=\"Työeläkeyhtiö\" enum=\"PensionCompany\" name=\"PensionCompany\" ng-model=\"$ctrl.current.result.responsibilities.pensionCompany\"></salaxy-input-enum>\r\n              <salaxy-input input-mode=\"openClose\" label=\"Sopimusnumero\" name=\"PensionContractNumber\" ng-model=\"$ctrl.current.result.responsibilities.pensionContractNumber\" sxy-pension-contract-number></salaxy-input>\r\n              <salaxy-input ng-if=\"$ctrl.current.result.responsibilities.pensionCalculation == 'publicSector'\" input-mode=\"openClose\" label=\"SALAXY.MODEL.PensionContract.subOrgCode.title\" name=\"SubOrgCode\" ng-model=\"$ctrl.current.result.responsibilities.subOrgCode\"></salaxy-input>\r\n              <salaxy-input-number input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.pensionPercent\" unit=\"percent\" name=\"PensionPercent\" label=\"SALAXY.MODEL.PensionContract.pensionPercent.title\"></salaxy-input-number>\r\n              <salaxy-input-number input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.pensionDiscountPercent\" unit=\"percent\" name=\"PensionDiscount\" label=\"SALAXY.MODEL.PensionContract.pensionDiscountPercent.title\"></salaxy-input-number>\r\n              <salaxy-input-boolean input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.pensionSelfPayment\" name=\"pensionSelfPayment\" label=\"Hoitaa TyEl-maksut itse\"></salaxy-input-boolean>\r\n\r\n              <salaxy-input-enum input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.insuranceCompany\" label=\"Vakuutusyhtiö\" enum=\"InsuranceCompany\" name=\"InsuranceCompany\"></salaxy-input-enum>\r\n              <salaxy-input input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.insuranceContractNumber\" name=\"insuranceContractNumber\" label=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\"></salaxy-input>\r\n              <salaxy-input-number input-mode=\"openClose\" label-cols=\"col-sm-6\" ng-model=\"$ctrl.current.result.responsibilities.insurancePercent\" label=\"Tapaturm.vak.maksun arvio-%\" unit=\"percent\" name=\"insurancePercent\"></salaxy-input-number>\r\n              <salaxy-input-number input-mode=\"openClose\" label-cols=\"col-sm-6\" ng-model=\"$ctrl.current.result.responsibilities.groupLifeInsurancePercent\" label=\"SALAXY.MODEL.InsuranceContract.groupLifeInsurancePercent.title\" unit=\"percent\" name=\"groupLifeInsurancePercent\"></salaxy-input-number>\r\n              \r\n              <salaxy-input-boolean input-mode=\"openClose\" read-only=\"true\" label-cols=\"col-sm-6\" ng-model=\"$ctrl.current.result.responsibilities.unemploymentSelfPayment\" name=\"unemploymentSelfPayment\" label=\"Hoitaa työt.vak.maksut itse\"></salaxy-input-boolean>\r\n              <salaxy-input-enum input-mode=\"openClose\" ng-model=\"$ctrl.current.result.responsibilities.unemploymentPayrollLimitStatus\" label=\"Työt.vak.maksun palkkasummaraja\" enum=\"UnemploymentPayrollLimitStatus\" name=\"unemploymentPayrollLimitStatus\">\r\n              </salaxy-input-enum>\r\n\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n        <div class=\"col-md-6 col-xs-12 calc-editor-payment-details spacer-bottom\">\r\n          <!-- todo fix readOnly-->\r\n          <form class=\"form-horizontal\">\r\n            <legend sxy-text=\"Palkanmaksu\"></legend>\r\n            <salaxy-input-boolean input-mode=\"openClose\"  label=\"Hoitaa nettopalkan maksun itse\" name=\"WorkerSelfPayment\" ng-model=\"$ctrl.current.result.responsibilities.workerSelfPayment\"></salaxy-input-boolean>\r\n            <salaxy-input-enum  input-mode=\"openClose\"  ng-model=\"$ctrl.current.workflow.salaryDateKind\" name=\"salaryDateKind\" enum=\"SalaryDateKind\"  label=\"SALAXY.MODEL.CalcWorkflow.salaryDateKind.title\"></salaxy-input-enum>\r\n            <salaxy-datepicker-popup input-mode=\"openClose\" name=\"salaryDate\" ng-model=\"$ctrl.current.workflow.salaryDate\" label=\"SALAXY.NG1.CalcEditorComponent.paymentInfo.salaryDateLabel\"></salaxy-datepicker-popup>\r\n            <salaxy-datepicker-popup input-mode=\"openClose\" name=\"salaryPaidAt\" ng-model=\"$ctrl.current.workflow.paidAt\" label=\"SALAXY.NG1.CalcEditorComponent.paymentInfo.paymentDateLabel\"></salaxy-datepicker-popup>  \r\n            <salaxy-date-range input-mode=\"openClose\" ng-model=\"$ctrl.dateRange\" class=\"condensed\" name=\"dateRange\" on-change=\"$ctrl.dateRangeChange()\" label=\"SALAXY.CORE.CalcWorktime.salaryPeriod\" label-days-count=\"SALAXY.MODEL.CalcWorktime.workDays.title\"></salaxy-date-range>            \r\n            <salaxy-input-enum  input-mode=\"openClose\"  ng-model=\"$ctrl.current.pricingModel\" name=\"pricingModel\" enum=\"PricingModel\"  label=\"SALAXY.MODEL.ServiceModelPricing.pricingModel.title\"></salaxy-input-enum>\r\n            <salaxy-input-number input-mode=\"openClose\" name=\"fixedFee\" ng-model=\"$ctrl.current.fixedFee\" label=\"SALAXY.MODEL.ServiceModelPricing.fixedFee.title\"></salaxy-input-number>\r\n            <salaxy-input-number input-mode=\"openClose\" read-only=\"true\" label=\"Maksu Palkkaus.fi-palvelulle\" name=\"palkkausFee\" ng-model=\"$ctrl.current.result.employerCalc.palkkaus\"></salaxy-input-number>\r\n            <salaxy-input-enum ng-if=\"'admin' | sxyIsInRole\"  input-mode=\"openClose\"  ng-model=\"$ctrl.current.info.paymentChannel\" name=\"paymentChannel\" enum=\"PaymentChannel\"  label=\"SALAXY.NG1.CalcEditorComponent.paymentInfo.paymentChannel\"></salaxy-input-enum>\r\n           </form>\r\n        </div>\r\n      </div>\r\n\r\n      <div class=\"row spacer-bottom\">\r\n        <div class=\"col-md-6 col-xs-12 spacer-bottom\">\r\n          <form class=\"form-horizontal\" ng-readonly=\"true\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.CalcEditorComponent.messages.title\"></legend>\r\n\r\n              <salaxy-input input-mode=\"openClose\" read-only=\"false\" name=\"workDescription\" ng-model=\"$ctrl.current.info.workDescription\" label=\"SALAXY.NG1.CalcEditorComponent.messages.workDescriptionLabel\"></salaxy-input>\r\n              <salaxy-textarea input-mode=\"openClose\" read-only=\"false\" name=\"salarySlipMessage\" ng-model=\"$ctrl.current.info.salarySlipMessage\" label=\"SALAXY.NG1.CalcEditorComponent.messages.salarySlipMessageLabel\"></salaxy-textarea>\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n        <div class=\"col-md-6 col-xs-12\" sxy-if-role=\"company\">\r\n          <div class=\"form-horizontal\">\r\n            <salaxy-calc-cost-accounting read-only=\"false\" input-mode=\"openClose\" calc=\"$ctrl.current\"></salaxy-calc-cost-accounting>\r\n          </div>\r\n        </div>\r\n        <div class=\"col-xs-6\" sxy-if-role=\"person\">\r\n          <legend sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.title\"></legend>\r\n          <div class=\"row form-horizontal\">\r\n            <div class=\"col-xs-6\">\r\n              <salaxy-input-boolean type=\"checkbox\" name=\"isHouseholdDeductible\" ng-model=\"$ctrl.current.usecase.data.isHouseholdDeductible\" label-type=\"no-label\" />\r\n            </div>\r\n            <div class=\"col-xs-6\">\r\n              <div ng-if=\"!$ctrl.current.usecase.data.isHouseholdDeductible\" class=\"text-danger\" style=\"padding-top:7px;\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.noDeduction\"></div>\r\n              <div ng-if=\"$ctrl.current.usecase.data.isHouseholdDeductible\">\r\n                <select class=\"form-control\" ng-model=\"$ctrl.current.usecase.data.taxDeductionCategories\">\r\n                  <option hidden value=\"\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.select\"></option>\r\n                  <option value=\"none\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.none\"></option>\r\n                  <option value=\"householdwork\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.householdwork\"></option>\r\n                  <option value=\"carework\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.carework\"></option>\r\n                  <option value=\"homeImprovement\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.homeImprovement\"></option>\r\n                  <option value=\"oilHeatingReplacementWork\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionCategory.oilHeatingReplacementWork\"></option>\r\n                </select>\r\n              </div>\r\n              <div ng-if=\"$ctrl.current.usecase.data.isHouseholdDeductible\">\r\n                <select class=\"form-control\" ng-model=\"$ctrl.current.usecase.data.taxDeductionProperty\">\r\n                  <option hidden value=\"\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionProperty.select\"></option>\r\n                  <option value=\"none\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionProperty.none\"></option>\r\n                  <option value=\"ownProperty\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionProperty.ownProperty\"></option>\r\n                  <option value=\"relativesProperty\" sxy-text=\"SALAXY.NG1.CalcEditorComponent.householdDeduction.deductionProperty.relativesProperty\"></option>\r\n                </select>\r\n              </div>\r\n            </div>\r\n          </div>\r\n\r\n        </div>\r\n      </div>\r\n      <div class=\"row calc-editor-calc-rows\">\r\n        <div class=\"col-xs-12\">\r\n          <fieldset>\r\n\r\n            <legend sxy-text=\"SALAXY.NG1.CalcEditorComponent.calcRowsTitle\"></legend>\r\n            <salaxy-calc-rows-2019-editor parent=\"$ctrl.current\" mode=\"read-edit\" show-edit-buttons=\"true\" show-gross-totals=\"false\">\r\n            </salaxy-calc-rows-2019-editor>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-12 col-md-12 col-lg-6\">\r\n      <uib-tabset active=\"$ctrl.currentTab\">\r\n        <uib-tab heading=\"{{'SALAXY.NG1.CalcEditorComponent.editedHeading' | sxyTranslate}}\" index=\"'edited'\">\r\n          <salaxy-calc-reports calcs=\"[$ctrl.current]\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1.CalcEditorComponent.originalHeading' | sxyTranslate}}\" index=\"'default'\">\r\n          <salaxy-calc-reports calcs=\"[$ctrl.base]\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1.CalcEditorComponent.diffHeading' | sxyTranslate}}\" index=\"'paymentReport'\">\r\n          <div class=\"payroll-report payroll-report-partial-container\">\r\n            <salaxy-calc-report calc=\"$ctrl.diffCalc\" report-type=\"'paymentReport'\" template-name=\"'paymentTablesV2'\" apply-site-styles=\"true\">\r\n          </div>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1.CalcEditorComponent.diffAccountingHeading' | sxyTranslate}}\" index=\"'accounting'\">\r\n          <salaxy-accounting-report-tools any-expanded=\"$reportRows.anyExpanded\" on-expand-change=\"$reportRows.expand(close)\" on-target-change=\"$ctrl.loadAccountingDiffData(targetId)\" reader=\"$ctrl.accountingDiffDataReader\"></salaxy-accounting-report-tools>\r\n          <salaxy-accounting-report-rows ng-ref=\"$reportRows\" data=\"$ctrl.accountingDiffData\"></salaxy-accounting-report-rows>\r\n        </uib-tab>\r\n        <uib-tab  ng-if=\"'admin' | sxyIsInRole\" heading=\"{{'SALAXY.NG1.CalcEditorComponent.diffCfa' | sxyTranslate}}\" index=\"'cfa'\">\r\n          <fieldset>\r\n            <legend>\r\n              <span sxy-text=\"Asiakasmaksut\"></span>\r\n            </legend>\r\n          </fieldset>\r\n          <table class=\"table\">\r\n            <tr>\r\n              <th>Erä</th>\r\n              <th class=\"text-right\">Nykyinen summa</th>\r\n              <th class=\"text-right\">Laskettu summa</th>\r\n              <th class=\"text-right\">Laskettu ero</th>\r\n              <th class=\"text-right\">Tallennettava summa</th>\r\n              <th class=\"text-right\">Tallennettava ero</th>\r\n            </tr>\r\n            <tr>\r\n              <td>Nettopalkka</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.net  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ ($ctrl.current.result.workerCalc.totalWorkerPayment - $ctrl.current.result.employerCalc.deductionWorkerSelfPayment) | currency}}</td>\r\n              <td class=\"text-right\">{{ (($ctrl.current.result.workerCalc.totalWorkerPayment - $ctrl.current.result.employerCalc.deductionWorkerSelfPayment) - ($ctrl.base.cfa ? $ctrl.base.cfa.net  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.net  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.net - $ctrl.base.cfa.net) | currency) : \" - \"}}</td>\r\n            </tr>\r\n            <tr>\r\n              <td>Eläke</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.pension  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ ($ctrl.current.result.totals.pension - $ctrl.current.result.employerCalc.deductionPensionSelfPayment) | currency}}</td>\r\n              <td class=\"text-right\">{{ (($ctrl.current.result.totals.pension - $ctrl.current.result.employerCalc.deductionPensionSelfPayment) - ($ctrl.base.cfa ? $ctrl.base.cfa.pension  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.pension  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.pension - $ctrl.base.cfa.pension) | currency) : \" - \"}}</td>\r\n            </tr>\r\n            <tr>\r\n              <td>Vero</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.tax  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ ($ctrl.current.result.workerCalc.tax + $ctrl.current.result.employerCalc.socialSecurity + $ctrl.current.result.workerCalc.taxAtSource +  $ctrl.current.result.workerCalc.socialSecurity - $ctrl.current.result.employerCalc.deductionTaxAndSocialSecuritySelfPayment) | currency}}</td>\r\n              <td class=\"text-right\">{{ (($ctrl.current.result.workerCalc.tax + $ctrl.current.result.employerCalc.socialSecurity + $ctrl.current.result.workerCalc.taxAtSource +  $ctrl.current.result.workerCalc.socialSecurity - $ctrl.current.result.employerCalc.deductionTaxAndSocialSecuritySelfPayment) - ($ctrl.base.cfa ? $ctrl.base.cfa.tax  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.tax  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.tax - $ctrl.base.cfa.tax) | currency) : \" - \"}}</td>\r\n            </tr>\r\n            <tr>\r\n              <td>Palvelumaksu</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.service  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ ($ctrl.current.result.employerCalc.service) | currency}}</td>\r\n              <td class=\"text-right\">{{ (($ctrl.current.result.employerCalc.service) - ($ctrl.base.cfa ? $ctrl.base.cfa.service  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.service  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.service - $ctrl.base.cfa.service) | currency) : \" - \"}}</td>\r\n            </tr>\r\n            <tr>\r\n              <td>Palkkio</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.fee  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ ($ctrl.current.result.employerCalc.palkkaus) | currency}}</td>\r\n              <td class=\"text-right\">{{ (($ctrl.current.result.employerCalc.palkkaus) - ($ctrl.base.cfa ? $ctrl.base.cfa.fee  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.fee  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.fee - $ctrl.base.cfa.fee) | currency) : \" - \"}}</td>\r\n            </tr>\r\n            <tr class=\"total\">\r\n              <td>Yhteensä</td>\r\n              <td class=\"text-right\">{{ $ctrl.base.cfa ? ($ctrl.base.cfa.total  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ (\r\n                $ctrl.current.result.workerCalc.totalWorkerPayment - $ctrl.current.result.employerCalc.deductionWorkerSelfPayment +\r\n                $ctrl.current.result.totals.pension - $ctrl.current.result.employerCalc.deductionPensionSelfPayment +\r\n                $ctrl.current.result.workerCalc.tax + $ctrl.current.result.employerCalc.socialSecurity + $ctrl.current.result.workerCalc.taxAtSource +  $ctrl.current.result.workerCalc.socialSecurity - $ctrl.current.result.employerCalc.deductionTaxAndSocialSecuritySelfPayment +\r\n                $ctrl.current.result.employerCalc.service +\r\n                $ctrl.current.result.employerCalc.palkkaus\r\n                ) | currency}}</td>\r\n              <td class=\"text-right\">{{ ((\r\n                $ctrl.current.result.workerCalc.totalWorkerPayment - $ctrl.current.result.employerCalc.deductionWorkerSelfPayment +\r\n                $ctrl.current.result.totals.pension - $ctrl.current.result.employerCalc.deductionPensionSelfPayment +\r\n                $ctrl.current.result.workerCalc.tax + $ctrl.current.result.employerCalc.socialSecurity + $ctrl.current.result.workerCalc.taxAtSource +  $ctrl.current.result.workerCalc.socialSecurity - $ctrl.current.result.employerCalc.deductionTaxAndSocialSecuritySelfPayment +\r\n                $ctrl.current.result.employerCalc.service +\r\n                $ctrl.current.result.employerCalc.palkkaus\r\n                ) - ($ctrl.base.cfa ? $ctrl.base.cfa.total  : 0)) | currency }}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ($ctrl.current.cfa.total  | currency) : \" - \"}}</td>\r\n              <td class=\"text-right\">{{ $ctrl.current.cfa ? ( ($ctrl.current.cfa.total - $ctrl.base.cfa.total) | currency) : \" - \"}}</td>\r\n            </tr>\r\n          </table>\r\n        </uib-tab>\r\n        <uib-tab heading=\"Laskut ja ilmoitukset\" index=\"documentFlow\">\r\n          <div ng-if=\"$ctrl.documentFlow.children\">\r\n            <table class=\"table table-striped\">\r\n              <tr ng-repeat=\"doc in $ctrl.documentFlow.children\">\r\n                <td>\r\n                  <salaxy-avatar ng-if=\"doc.item.type != 'payerSummary' && doc.item.type != 'payrollDetails'\" class=\"salaxy-calc-row-type-avatar\" avatar=\"doc.item.otherPartyInfo.avatar\"></salaxy-avatar>\r\n                  <salaxy-avatar ng-if=\"doc.item.type == 'payerSummary' || doc.item.type == 'payrollDetails'\" class=\"salaxy-calc-row-type-avatar\" avatar=\"doc.item.ownerInfo.avatar\"></salaxy-avatar>\r\n                </td>\r\n                <td class=\"middle\">\r\n                  <strong ng-if=\"doc.item.type == 'invoice'\">{{doc.item.shortText}}</strong>\r\n                  <strong ng-if=\"doc.item.type == 'earningsPayment'\">{{'Palkkatietoilmoitus' |sxyTranslate}}</strong>\r\n                  <strong ng-if=\"doc.item.type == 'payrollDetails'\">{{'Palkkalista' |sxyTranslate}}</strong>\r\n                  <strong ng-if=\"doc.item.type == 'payerSummary'\">{{'Erillisilmoitus' |sxyTranslate}}</strong>\r\n                </td>\r\n                <td>\r\n                  <a ng-if=\"doc.item.type == 'earningsPayment'\" class=\"btn btn-default btn-sm\" ng-href=\"#/irepr/details/{{doc.item.id}}\">Näytä</a>\r\n                  <a ng-if=\"doc.item.type == 'invoice'\" class=\"btn btn-default btn-sm\" ng-href=\"#/invoices/details/{{doc.item.id}}\">\r\n                    {{ 'SALAXY.UI_Terms.show' | sxyTranslate}}</a>\r\n                  <a ng-if=\"doc.item.type == 'payerSummary'\" class=\"btn btn-default btn-sm\" ng-href=\"#/irpsr/details/{{doc.item.id}}\">Näytä</a>\r\n                  <a ng-if=\"doc.item.type == 'payrollDetails'\" class=\"btn btn-default btn-sm\" ng-href=\"#/payroll/details/{{doc.item.id}}\">Näytä</a>\r\n                </td>\r\n              </tr>\r\n            </table>\r\n          </div>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n    </div>\r\n    <div ng-if=\"'admin' | sxyIsInRole\" class=\"right-sidebar\"  ng-class=\"{'is-open' : $ctrl.isRightSidebarOpen}\">\r\n      <button class=\"btn btn-transparent custom-close\" ng-click=\"$ctrl.isRightSidebarOpen = false\">\r\n        <i class=\"fa fa-times\"></i>\r\n      </button>\r\n      <div ng-view></div>\r\n    </div>\r\n  </div>\r\n \r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcLeaves.html\",`<div class=\"row\">\r\n  <div class=\"col-12\">\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.details.lead\"></p>\r\n  </div>\r\n</div>\r\n<div class=\"row\">\r\n  <div class=\"col-sm-12\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <th></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.holidaySalariesAndCompensations\"></th>\r\n        <th ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.bonuses\"></th>\r\n      </thead>\r\n      <tbody>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.accrualRemaining\"></td>\r\n          <td class=\"right\">{{$ctrl.worktime.holidayPayAccrualRemaining}}</td>\r\n          <td ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\">{{$ctrl.worktime.holidayBonusAccrualRemaining}}</td>\r\n        </tr>\r\n        <tr> \r\n          <td sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.paidInThisSalary\"></td>\r\n          <td class=\"right\">{{$ctrl.getAccrualRemaningsToBePaid('holidayPay')}}</td>\r\n          <td ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\">{{$ctrl.getAccrualRemaningsToBePaid('holidayBonus')}}</td>\r\n        </tr>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.newAccrualRemaining\"></td>\r\n          <td class=\"right\">{{$ctrl.worktime.holidayPayAccrualRemaining - $ctrl.getAccrualRemaningsToBePaid('holidayPay')}}</td>\r\n          <td ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\">{{$ctrl.worktime.holidayBonusAccrualRemaining - $ctrl.getAccrualRemaningsToBePaid('holidayBonus')}}</td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>\r\n<div class=\"row\">\r\n  <div class=\"col-sm-6\">\r\n    <h4 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.paidInThisSalary\"></h4>\r\n    <table class=\"table table-condensed\" ng-if=\"$ctrl.annualLeavestoBePaid.length\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"60%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.holidayPeriod\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.days\"></th>\r\n          <th ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.bonusDays\"></th>\r\n          <th></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.annualLeavestoBePaid\">\r\n          <td width=\"60%\">\r\n            {{row.period | sxyDateRange}}\r\n          </td>\r\n          <td class=\"right\">\r\n            <salaxy-input-number name=\"daysCount\" ng-model=\"row.period.daysCount\" label-type=\"plain\"></salaxy-input-number>\r\n          </td>\r\n          <td ng-if=\"$ctrl.logic.worktime.holidaySpec.bonusMethod != 'none'\" class=\"right\">\r\n            <salaxy-input-number name=\"bonusDaysCount\" ng-model=\"row.bonusDaysCount\" label-type=\"plain\"></salaxy-input-number>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showEditDialog(row)\">\r\n              <span><i class=\"glyphicon glyphicon-calendar\"></i></span>\r\n            </button>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"delete btn btn-danger\" ng-click=\"$ctrl.moveItem(row, 'annualLeavesWaitingForPayment')\">\r\n              <span></span><i class=\"fa fa-trash\"></i>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div class=\"col-sm-6\">\r\n    <h4 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.plannedHolidays\"></h4>\r\n    <table class=\"table table-condensed\" ng-if=\"$ctrl.annualLeavesWaitingForPayment.length\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"40%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.startDate\"></th>\r\n          <th width=\"40%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.endDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.days\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.annualLeavesWaitingForPayment\" ng-style=\"$ctrl.getDisabledStyle(row)\">\r\n          <td width=\"40%\">\r\n            <span>{{row.period.start | sxyDate}}</span>\r\n          </td>\r\n          <td width=\"40%\">\r\n            <span>{{row.period.end | sxyDate}}</span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <span>{{row.period.daysCount}}</span>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.moveItem(row,'annualLeavestoBePaid')\" ng-disabled=\"$ctrl.isSelectedToBePaid(row)\" sxy-text=\"SALAXY.UI_Terms.select\">\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>\r\n<div class=\"row\">\r\n  <div class=\"col-sm-6\">\r\n    <h4 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.absencesToUse\"></h4>\r\n    <table class=\"table table-condensed\" ng-if=\"$ctrl.absencesToUse.length\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"60%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.absenceTime\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.cause\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.days\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.absencesToUse\">\r\n          <td width=\"60%\">\r\n            {{row.period | sxyDateRange}}\r\n          </td>\r\n          <td>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</td>\r\n          <td class=\"right\">{{row.period.daysCount}}</td>\r\n          <td>\r\n            <button type=\"button\" class=\"delete btn btn-danger\" ng-click=\"$ctrl.moveAbsenceItem(row, 'absencesToReject')\">\r\n              <span></span><i class=\"fa fa-trash\"></i>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div class=\"col-sm-6\">\r\n    <h4 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.absencesToReject\"></h4>\r\n    <table class=\"table table-condensed\" ng-if=\"$ctrl.absencesToReject.length\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"40%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.startDate\"></th>\r\n          <th width=\"40%\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.endDate\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.cause\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.days\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.absencesToReject\" ng-style=\"$ctrl.getAbsenceDisabledStyle(row)\">\r\n          <td width=\"40%\">\r\n            <span>{{row.period.start | sxyDate}}</span>\r\n          </td>\r\n          <td width=\"40%\">\r\n            <span>{{row.period.end | sxyDate}}</span>\r\n          </td>\r\n          <td>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</td>\r\n          <td class=\"right\">\r\n            <span>{{row.period.daysCount}}</span>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.moveAbsenceItem(row,'absencesToUse')\" ng-disabled=\"$ctrl.isAbsenceSelectedToUse(row)\" sxy-text=\"SALAXY.UI_Terms.select\">\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcList.html\",`<div class=\"salaxy-component salaxy-calc-list\">\r\n  <div ng-if=\"($ctrl.mode || 'default') == 'default'\">\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='draft'\" url=\"/v03/api/calculations/category/editable\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top:$ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsDrafts.html\" read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='paid'\" url=\"/v03/api/calculations/category/readonly\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top:$ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsPaid.html\" read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='shared'\" url=\"/v03/api/calculations/category/shared\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo, $orderby:'createdAt desc'}\" template-url=\"salaxy-components/odata/lists/CalculationsShared.html\"\r\n      read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='sent'\" url=\"/v03/api/calculations/category/sent\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsSent.html\" read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='received'\" url=\"/v03/api/calculations/category/received\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsReceived.html\"\r\n      read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='all'\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsAll.html\" read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='error'\" url=\"/v03/api/calculations/category/error\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo}\" template-url=\"salaxy-components/odata/lists/CalculationsAll.html\" read-only=\"$ctrl.readOnly\">\r\n    </salaxy-odata-table>\r\n\r\n    <salaxy-odata-table ng-if=\"$ctrl.category=='allEmployer'\" url=\"/v03/api/calculations/category/all\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $top: $ctrl.limitTo, $filter: 'status eq \\\\'paymentWorkerCopy\\\\' or status eq \\\\'draft\\\\' or status eq \\\\'workerRequested\\\\' or status eq \\\\'workerRequestAccepted\\\\' or status eq \\\\'workerRequestDeclined\\\\' ' }\"\r\n      template-url=\"salaxy-components/odata/lists/CalculationsEmployerAll.html\">\r\n    </salaxy-odata-table>\r\n  </div>\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode == 'panel'\" url=\"{{ $ctrl.category == 'paid' ? '/v03/api/calculations/category/readonly' : $ctrl.category == 'sent' ? '/v03/api/calculations/category/sent' : $ctrl.category == 'received' ? '/v03/api/calculations/category/received' : $ctrl.category == 'shared' ? '/v03/api/calculations/category/shared' : '/v03/api/calculations/category/editable'}}\"\r\n    crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: $ctrl.limitTo, $filter: $ctrl.filter, $orderby: $ctrl.category == 'shared' ? 'createdAt desc' : null}\" data=\"{ category: $ctrl.category }\" template-url=\"salaxy-components/odata/lists/CalculationsPanel.html\"\r\n    read-only=\"$ctrl.readOnly\">\r\n  </salaxy-odata-table>\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode == 'select'\" url=\"{{ $ctrl.category == 'paid' ? '/v03/api/calculations/category/readonly' : $ctrl.category == 'shared' ? '/v03/api/calculations/category/shared' : '/v03/api/calculations/category/editable'}}\" template-url=\"salaxy-components/odata/lists/Calculations-select.html\" options=\"$ctrl.options\"\r\n    selected-items=\"$ctrl.selectedItems\" on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\" crud-controller=\"CalculationCrudController as $crud\"></salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcNewIntro.html\",`<div class=\"calc-start-instructions\" ng-if=\"!$ctrl.calcSections.get('result').isSelectionDone\">\r\n  <h1 style=\"margin-top: 10px; margin-bottom: 40px; font-size: 2em\" class=\"text-center\" sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.title\"></h1>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-6 col-sm-3 text-center\" style=\"min-height: 200px; cursor: pointer;\" ng-click=\"$ctrl.calcSections.toggle('worker');\">\r\n      <div style=\"margin-bottom: 20px;\">\r\n        <span class=\"fa-stack fa-4x\"><i class=\"fa fa-circle fa-stack-2x text-info\"></i><span class=\"fa-stack-1x fa-inverse\">1</span></span>\r\n      </div>\r\n      <p style=\"margin-bottom: 0px;\"><strong class=\"uppercase\" sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepOne.title\"></strong></p>\r\n      <p sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepOne.description\"></p>\r\n    </div>\r\n    <div class=\"col-xs-6 col-sm-3 text-center\" style=\"min-height: 200px; cursor: pointer;\" ng-click=\"$ctrl.calcSections.toggle('worktime');\">\r\n      <div style=\"margin-bottom: 20px;\">\r\n        <span class=\"fa-stack fa-4x\"><i class=\"fa fa-circle fa-stack-2x text-warning\"></i><span class=\"fa-stack-1x fa-inverse\">2</span></span>\r\n      </div>\r\n      <p style=\"margin-bottom: 0px;\"><strong class=\"uppercase\" sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepTwo.title\"></strong></p>\r\n      <p sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepTwo.description\"></p>\r\n    </div>\r\n    <div class=\"col-xs-6 col-sm-3 text-center\" style=\"min-height: 200px;  cursor: pointer;\" ng-click=\"$ctrl.calcSections.toggle('salary');\">\r\n      <div style=\"margin-bottom: 20px;\">\r\n        <span class=\"fa-stack fa-4x\"><i class=\"fa fa-circle fa-stack-2x text-success\"></i><span class=\"fa-stack-1x fa-inverse\">3</span></span>\r\n      </div>\r\n      <p style=\"margin-bottom: 0px;\"><strong class=\"uppercase\" sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepThree.title\"></strong></p>\r\n      <p sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepThree.description\"></p>\r\n    </div>\r\n    <div class=\"col-xs-6 col-sm-3 text-center\" style=\"min-height: 200px;  cursor: pointer;\" ng-click=\"$ctrl.calcSections.toggle('expenses');\">\r\n      <div style=\"margin-bottom: 20px;\">\r\n        <span class=\"fa-stack fa-4x\"><i class=\"fa fa-circle fa-stack-2x text-danger\"></i><span class=\"fa-stack-1x fa-inverse\">4</span></span>\r\n      </div>\r\n      <p style=\"margin-bottom: 0px;\"><strong class=\"uppercase\" sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepFour.title\"></strong></p>\r\n      <p sxy-text=\"SALAXY.NG1.CalcNewIntroComponent.stepFour.description\"></p>\r\n    </div>\r\n  </div>\r\n  <p>&nbsp;</p>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcReport.html\",`<div ng-if=\"$ctrl.reportType != 'totalsReport'\" class=\"salaxy-component salaxy-calc-report\">\r\n  <div ng-class=\"{'report-table-html': $ctrl.applySiteStyles}\">\r\n    <div ng-bind-html=\"$ctrl.html\" class=\"report-binder table-responsive\"></div>\r\n  </div>\r\n  <p ng-if=\"('person' | sxyIsInRole) && $ctrl.calc.workflow.status !== 'paymentWorkerCopy'\">{{'SALAXY.NG1.CalcReportComponent.palkkausFeeInfo' | sxyTranslate}}</p>\r\n</div>\r\n<div ng-if=\"$ctrl.reportType == 'totalsReport'\" class=\"salaxy-component\">\r\n  <sxy-table ng-ref=\"$ctrl.$sxyTable\" options=\"$ctrl.tableConfig.options\" include=\"$ctrl.tableConfig.include\" data=\"$ctrl.tableConfig.data\"></sxy-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcReports.html\",`<div class=\"salaxy-component salaxy-calc-reports\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Report options\">\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n        <span ng-if=\"!($ctrl.reportType == 'irRows' || $ctrl.reportType == 'irFull' || $ctrl.reportType == 'rowsReport')\">\r\n          <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportType\" ps=\":\"></span>\r\n          {{ \"ReportType.\" + $ctrl.reportType | sxyEnum }}\r\n          <span class=\"caret\"></span>\r\n        </span>\r\n        <span ng-if=\"$ctrl.reportType == 'irRows'\">\r\n          <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportType\" ps=\":\"></span> {{\"SALAXY.NG1.CalcReportsComponent.irRows\" | sxyTranslate}} <span class=\"caret\"></span>\r\n        </span>\r\n        <span ng-if=\"$ctrl.reportType == 'irFull'\">\r\n          <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportType\" ps=\":\"></span> {{\"SALAXY.NG1.CalcReportsComponent.irFull\" | sxyTranslate}} <span class=\"caret\"></span>\r\n        </span>\r\n        <span ng-if=\"$ctrl.reportType == 'rowsReport'\">\r\n          <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportType\" ps=\":\"></span> {{\"SALAXY.NG1.CalcReportsComponent.rowsReport\" | sxyTranslate}} <span class=\"caret\"></span>\r\n        </span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'salarySlip'\">{{ \"ReportType.salarySlip\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'employerReport'\">{{ \"ReportType.employerReport\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'paymentReport'\">{{ \"ReportType.paymentReport\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'paymentSummaryReport'\">{{ \"ReportType.paymentSummaryReport\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'accountingReport'\">{{ \"ReportType.accountingReport\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'totalsReport'\">{{ \"ReportType.totalsReport\" | sxyEnum }}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'rowsReport'\">{{\"SALAXY.NG1.CalcReportsComponent.rowsReport\" | sxyTranslate}}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'irRows'\">{{\"SALAXY.NG1.CalcReportsComponent.irRows\" | sxyTranslate}}</a></li>\r\n        <li ng-if=\"$ctrl.calcs[0].workflow.status == 'paymentSucceeded'\" role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.reportType = 'irFull'\">{{\"SALAXY.NG1.CalcReportsComponent.irFull\" | sxyTranslate}}</a></li>\r\n      </ul>\r\n    </div>\r\n    <!-- \r\n      TODO: When implementing, use <salaxy-input-enum type=\"ui-dropdown\">\r\n      Needs some fixes to the component (e.g. btn-group-sm support)\r\n    -->\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n        <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguage\" ps=\":\"></span> {{$ctrl.languageText | sxyTranslate}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n        <li ng-if=\"$ctrl.reportType == 'salarySlip' || $ctrl.reportType == 'employerReport' || $ctrl.reportType == 'paymentReport'\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setReportLang('default')\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageWorker\"></a>\r\n        </li>\r\n        <li ng-if=\"!($ctrl.reportType == 'salarySlip' || $ctrl.reportType == 'employerReport' || $ctrl.reportType == 'paymentReport')\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setReportLang('default')\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setReportLang('fi')\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setReportLang('en')\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setReportLang('sv')\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div ng-show=\"$ctrl.reportType !== 'eSalarySpecification' && $ctrl.reportType !== 'totalsReport' && $ctrl.reportType !== 'irRows' && $ctrl.reportType !== 'rowsReport'\"\r\n      class=\"btn-group btn-group-sm\">\r\n      <button class=\"btn btn-default\" ng-model=\"$ctrl.view\" uib-btn-radio=\"'partial'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportViewPartial\"></button>\r\n      <button class=\"btn btn-default\" ng-model=\"$ctrl.view\" uib-btn-radio=\"'page1'\" ng-disabled=\"$ctrl.reportType == 'accountingReport'\"\r\n        sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportViewPage1\"></button>\r\n      <button class=\"btn btn-default\" ng-model=\"$ctrl.view\" uib-btn-radio=\"'full'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportViewFull\"></button>\r\n    </div>\r\n    <button ng-show=\"$ctrl.reportType !== 'eSalarySpecification' && $ctrl.reportType !== 'totalsReport' && $ctrl.reportType !== 'irRows' && $ctrl.reportType !== 'rowsReport'\"\r\n      class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.reload()\"><i class=\"fa fa-refresh\" aria-hidden=\"true\"></i></button>\r\n\r\n    <div\r\n      ng-show=\"$ctrl.reportType !== 'eSalarySpecification' && $ctrl.reportType !== 'totalsReport' && $ctrl.reportType !== 'irRows' && $ctrl.reportType !== 'rowsReport' && $ctrl.reportType !== 'accountingReport'\"\r\n      class=\"btn-group btn-group-sm pull-right-xs\" role=\"group\" aria-label=\"Pdf\">\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(true)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.print\"></span>\r\n        <i class=\"fa fa-print\" aria-hidden=\"true\"></i>\r\n      </button>\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(false)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></span>\r\n        <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n      </button>\r\n    </div>\r\n    <div ng-show=\"$ctrl.reportType == 'totalsReport' || $ctrl.reportType == 'irRows' || $ctrl.reportType == 'rowsReport'\" class=\"btn-group btn-group-sm pull-right-xs\" role=\"group\"\r\n      aria-label=\"Excel\">\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.downloadExcel()\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadExcel\"></span>\r\n        <i class=\"fa fa-file-excel-o\" aria-hidden=\"true\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n\r\n  <!-- Results view -->\r\n  <div ng-switch=\"$ctrl.reportType || 'none'\">\r\n    <div ng-switch-when=\"accountingReport\">\r\n      <div class=\"payroll-report\" ng-class=\"{'payroll-accounting-report-partial-container': $ctrl.view == 'partial'}\">\r\n        <salaxy-accounting-report-query ng-if=\"$ctrl.getEmployerLang() && $ctrl.getEmployerLang() !== 'default'\" lang=\"$ctrl.getEmployerLang()\" calcs=\"$ctrl.calcs\"\r\n          view=\"$ctrl.view\">\r\n          </salaxy-accouting-report-query>\r\n      </div>\r\n    </div>\r\n    <div ng-switch-when=\"paymentSummaryReport\">\r\n      <!-- TODO: Below development of new summary report, cleaned/moved later -->\r\n      <div class=\"payroll-report\" ng-class=\"{'payroll-report-partial-container': $ctrl.view == 'partial'}\">\r\n        <salaxy-calc-report ng-if=\"$ctrl.getEmployerLang() && $ctrl.getEmployerLang() !== 'default'\" lang=\"$ctrl.getEmployerLang()\" calc=\"$ctrl.calcs\"\r\n          apply-site-styles=\"$ctrl.view == 'partial'\" report-type=\"$ctrl.reportType\" preview=\"$ctrl.preview\" template-name=\"$ctrl.reports[$ctrl.reportType][$ctrl.view]\">\r\n        </salaxy-calc-report>\r\n      </div>\r\n    </div>\r\n    <div ng-switch-when=\"totalsReport\">\r\n      <salaxy-calc-report ng-ref=\"$ctrl.$calcReports\" ng-if=\"$ctrl.getEmployerLang() && $ctrl.getEmployerLang() !== 'default'\" lang=\"$ctrl.getEmployerLang()\" calc=\"$ctrl.calcs\"\r\n        apply-site-styles=\"$ctrl.view == 'partial'\" report-type=\"$ctrl.reportType\" preview=\"$ctrl.preview\" template-name=\"$ctrl.reports[$ctrl.reportType][$ctrl.view]\">\r\n      </salaxy-calc-report>\r\n    </div>\r\n    <div ng-switch-when=\"rowsReport\">\r\n      <sxy-table ng-ref=\"$ctrl.$sxyTable\" options=\"$ctrl.rowsReportTableConfig.options\" include=\"$ctrl.rowsReportTableConfig.include\"\r\n        data=\"$ctrl.rowsReportTableConfig.data\"></sxy-table>\r\n    </div>\r\n    <div ng-switch-when=\"irRows\">\r\n      <salaxy-calcs-ir-rows ng-ref=\"$ctrl.$calcsIrRows\" calcs=\"$ctrl.calcs\" lang=\"$ctrl.getEmployerLang()\"></salaxy-calcs-ir-rows>\r\n    </div>\r\n    <div ng-switch-when=\"irFull\">\r\n      <div ng-repeat=\"calc in $ctrl.calcs\">\r\n        <salaxy-ir-earnings-payment calculation=\"calc\"></salaxy-ir-earnings-payment>\r\n      </div>\r\n    </div>\r\n    <div ng-switch-when=\"none\">\r\n      <!-- Report type not selected -->\r\n    </div>\r\n    <div ng-switch-default=\"\">\r\n      <div ng-repeat=\"calc in $ctrl.calcs\" class=\"payroll-report\" ng-class=\"{'payroll-report-partial-container': $ctrl.view == 'partial'}\">\r\n        <salaxy-calc-worker-info model=\"calc\" ng-if=\"$ctrl.view == 'partial'\"></salaxy-calc-worker-info>\r\n        <salaxy-calc-report ng-if=\"$ctrl.getWorkerLang(calc) && $ctrl.getWorkerLang(calc) !== 'default'\" lang=\"$ctrl.getWorkerLang(calc)\" calc=\"calc\"\r\n          apply-site-styles=\"$ctrl.view == 'partial'\" report-type=\"$ctrl.reportType\" preview=\"$ctrl.preview\" template-name=\"$ctrl.reports[$ctrl.reportType][$ctrl.view]\">\r\n        </salaxy-calc-report>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcResults.html\",`<div class=\"result-area\" ng-if=\"$ctrl.currentCalc && $ctrl.calcSections.get('result').isSelectionDone\">\r\n  <div class=\"panel panel-primary\" style=\"padding: 10px\">\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-md-4 col-md-push-4\">\r\n          <h2 class=\"text-center uppercase\"> {{ $ctrl.calcLogic.hasCompensation ? (\"SALAXY.NG1.CalcResultsComponent.calculation\" | sxyTranslate) : (\"SALAXY.NG1.CalcResultsComponent.calculationSalary\" | sxyTranslate) }}</h2>\r\n          <div salaxy-if-role=\"anon\">\r\n            <button type=\"button\" ng-click=\"$ctrl.register()\" class=\"btn btn-info btn-block spacer-bottom\" sxy-text=\"SALAXY.UI_Terms.register\"></button>\r\n            <button type=\"button\" ng-click=\"$ctrl.signIn()\" class=\"btn btn-success btn-block spacer-bottom\" sxy-text=\"SALAXY.UI_Terms.login\"></button>\r\n          </div>\r\n          \r\n          <salaxy-validation-summary ng-if=\"$ctrl.currentCalc.workflow.status != 'sharedWaiting'\" api-validation=\"$ctrl.validation\"></salaxy-validation-summary>\r\n            \r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'payrollDraft'\" class=\"text-center\">\r\n            <strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.payrollDraft\"></strong><br>\r\n            <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.payrollDraftInfo\"></span>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'sharedWaiting'\" class=\"text-center\">\r\n            <strong class=\"text-warning\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.sharedWaiting\"></strong>\r\n            <br> <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.sharedWaitingInfo\"></span>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'sharedApproved'\" class=\"text-center\">\r\n            <strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.sharedApproved\"></strong>\r\n            <br>\r\n            <span ng-if=\"$ctrl.validation.isValid\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.draftInfo\"></span>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'sharedRejected'\" class=\"text-center\">\r\n            <strong class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.sharedRejected\"></strong>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentStarted'\" class=\"text-center\">\r\n            <strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentStarted\"></strong>\r\n            <br>{{ $ctrl.currentCalc.workflow.paidAt | date }}\r\n            <span ng-if=\"$ctrl.currentCalc.info.paymentChannel != 'undefined'\">, <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentChannelTextPartial\"></span> {{ \"PaymentChannel.\" + $ctrl.currentCalc.info.paymentChannel | sxyEnum }}</span>.\r\n            <span ng-if=\"$ctrl.currentCalc.workflow.salaryDateKind == 'inPast'\">\r\n              {{\"SALAXY.ENUM.SalaryDateKind.\" + ($ctrl.currentCalc.workflow.salaryDateKind) + \".label\" | sxyTranslate  }}.\r\n            </span>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentSucceeded' || $ctrl.currentCalc.workflow.status == 'paymentCanceled' || $ctrl.currentCalc.workflow.status == 'paymentRefunded' || $ctrl.currentCalc.workflow.status == 'paymentError'\" class=\"text-center\">\r\n            <strong ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentSucceeded'\" class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.isPaidDate\"></strong>\r\n            <strong ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentError'\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentError\"></strong>\r\n            <strong ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentRefunded'\" class=\"\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentRefunded\"></strong>\r\n            <strong  ng-if=\"$ctrl.currentCalc.workflow.status == 'paymentCanceled'\" class=\"\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentCanceled\"></strong>\r\n           \r\n            <br>{{ $ctrl.currentCalc.workflow.paidAt | date }}\r\n            <span ng-if=\"$ctrl.currentCalc.info.paymentChannel != 'undefined'\">, <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.paymentChannelTextPartial\"></span> {{ \"PaymentChannel.\" + $ctrl.currentCalc.info.paymentChannel | sxyEnum }}</span>.\r\n            <span ng-if=\"$ctrl.currentCalc.workflow.salaryDateKind == 'inPast'\">\r\n              {{\"SALAXY.ENUM.SalaryDateKind.\" + ($ctrl.currentCalc.workflow.salaryDateKind) + \".label\" | sxyTranslate  }}.\r\n            </span>\r\n          </p>\r\n          <p ng-if=\"$ctrl.currentCalc.workflow.status == 'draft'\" class=\"text-center\">\r\n            <span ng-if=\"$ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.draft\"></span>\r\n            <br>\r\n            <span ng-if=\"$ctrl.validation.isValid  && ('!worker' | sxyIsInRole) && !$ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.draftInfo\"></span>\r\n          </p>\r\n          <div ng-if=\"('auth' | sxyIsInRole) && ('!worker' | sxyIsInRole)\">\r\n            <div ng-if=\"$ctrl.showAction('sendToPro')\">\r\n              <p  class=\"text-center\">\r\n                <strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.waitingApproval\"></strong>\r\n                <br>\r\n                <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.waitingApprovalInfo\"></span>\r\n              </p>\r\n              <div class=\"form-horizontal spacer-bottom\">\r\n                <salaxy-textarea  name=\"workflowMessage\" ng-model=\"$ctrl.workflowMessage\" label=\"SALAXY.NG1.CalcResultsComponent.messageToAccountant\" label-type=\"basic\"></salaxy-textarea>\r\n              </div>\r\n              <div class=\"text-center\">\r\n                <button type=\"button\" class=\"btn btn-primary  spacer-bottom\" ng-click=\"$ctrl.sendToPro($ctrl.workflowMessage)\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.sendToProBtn\" ps=\"»\"></button>\r\n              </div>\r\n            </div>\r\n            <div ng-if=\"$ctrl.showAction('showPaymentDialog')\" class=\"text-center spacer-bottom\">\r\n              <a href=\"\" ng-click=\"$ctrl.showPaymentDialog()\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.showPaymentDialog\"></a>.\r\n            </div>\r\n            <div ng-if=\"!$ctrl.validation.isValid\">\r\n              <salaxy-pay-button ng-if=\"$ctrl.showAction('allowForcePay')\" label=\"SALAXY.UI_Terms.payAllShort\" model=\"$ctrl.currentCalc\" mode=\"button-and-channel\" button-class=\"spacer-bottom uppercase\" ng-ref=\"$payButton\" disabled=\"!$payButton.isChannelDefined\" on-payment-channel-change=\"$ctrl.recalculate()\"></salaxy-pay-button>\r\n            </div>\r\n            <div ng-if=\"$ctrl.validation.isValid\">\r\n              <div ng-if=\"$ctrl.showAction('pay')\" class=\"spacer-bottom\">\r\n                <salaxy-pay-button model=\"$ctrl.currentCalc\" mode=\"button-and-channel\" salaxy-if-role=\"employer\" button-class=\"spacer-bottom uppercase\" ng-ref=\"$payButton\" disabled=\"!$payButton.isChannelDefined\" on-payment-channel-change=\"$ctrl.recalculate()\"></salaxy-pay-button>\r\n                <salaxy-salary-date-kind-button ng-if=\"$ctrl.showAction('setSalaryDateKind') && ('test,setSalaryDateKind' | sxyIsInRole) && ('employer' | sxyIsInRole)\" button-class=\"btn-block\" model=\"$ctrl.currentCalc\" disabled=\"$ctrl.currentCalc.isReadOnly || $ctrl.isReadOnlyForced\" on-salary-date-kind-change=\"$ctrl.recalculate()\"></salaxy-salary-date-kind-button>\r\n              </div>\r\n            </div> \r\n            <div ng-if=\"$ctrl.showAction('save')\" class=\"spacer-bottom\">\r\n              <button type=\"button\" ng-click=\"$ctrl.save()\" class=\"btn btn-success btn-block spacer-bottom\" ng-disabled=\"$ctrl.isActionDisabled('save')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n            </div>\r\n            <div ng-if=\"$ctrl.showAction('reject')\" class=\"spacer-bottom\">\r\n              <salaxy-calc-sharing-receipt-action button-class=\"btn btn-danger btn-block\" model=\"$ctrl\" type=\"'reject'\"></salaxy-calc-sharing-receipt-action>\r\n            </div>\r\n            <div ng-if=\"$ctrl.showAction('approve')\" class=\"spacer-bottom\">\r\n              <salaxy-calc-sharing-receipt-action button-class=\"btn btn-success btn-block\" model=\"$ctrl\" type=\"'approve'\"></salaxy-calc-sharing-receipt-action>\r\n            </div>\r\n            <button ng-if=\"$ctrl.showAction('delete')\" type=\"button\" ng-click=\"$ctrl.deleteCalc()\" ng-disabled=\"$ctrl.isActionDisabled('delete')\" class=\"btn btn-danger btn-block spacer-bottom\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n            <button ng-if=\"$ctrl.showAction('cancel')\" class=\"btn btn-default btn-sm btn-block spacer-bottom\" ng-click=\"$ctrl.cancel()\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.cancelPaymentOrChangeChannelBtn\"></button>\r\n            \r\n            <button ng-if=\"$ctrl.showAction('copyAsNew')\" type=\"button\" ng-click=\"$ctrl.copyAsNew()\" class=\"btn btn-primary btn-block spacer-bottom\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\" ps=\" »\"></button>\r\n          </div>\r\n          <div sxy-if-role=\"worker\" class=\"row hidden-xxs\">\r\n            <div ng-if=\"$ctrl.showAction('save')\" class=\"col-xs-12\">\r\n              <button type=\"button\" ng-click=\"$ctrl.save()\" class=\"btn btn-success btn-block spacer-bottom\" ng-disabled=\"$ctrl.isActionDisabled('save')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n            </div>\r\n            <div ng-if=\"$ctrl.currentCalc.workflow.status == 'draft' || $ctrl.currentCalc.workflow.status == 'workerRequested' || $ctrl.currentCalc.workflow.status == 'workerRequestAccepted' || $ctrl.currentCalc.workflow.status == 'workerRequestDeclined' || $ctrl.currentCalc.workflow.status == 'paymentWorkerCopy'\" class=\"col-xs-12 spacer-bottom\">\r\n              <salaxy-calc-sharing-info model=\"$ctrl\"></salaxy-calc-sharing-info>\r\n            </div>\r\n            <div ng-if=\"$ctrl.showAction('delete')\" class=\"col-xs-12\">\r\n              <button ng-if=\"$ctrl.showAction('delete')\" type=\"button\" ng-click=\"$ctrl.deleteCalc()\" ng-disabled=\"$ctrl.isActionDisabled('delete')\" class=\"btn btn-danger btn-block spacer-bottom\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n            </div>\r\n          </div>\r\n         \r\n          <div class=\"text-center btn-group-chart\">\r\n            <a ng-click=\"$ctrl.chartType = 'bar'\" class=\"btn-chart\" ng-class=\"{'active' : $ctrl.chartType == 'bar'}\"><i class=\"fa fa-lg fa-bar-chart\"></i></a>\r\n            <a ng-click=\"$ctrl.chartType = 'pie'\" class=\"btn-chart\" ng-class=\"{'active' : $ctrl.chartType == 'pie'}\"><i class=\"fa fa-lg fa-pie-chart\"></i></a>\r\n          </div>\r\n        </div>\r\n\r\n        <div class=\"col-xs-6 col-md-4 col-md-pull-4\">\r\n          <h3 class=\"text-center\" sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></h3>\r\n          <salaxy-calc-chart role=\"employer\" scale-y-axis=\"true\" chart-type=\"$ctrl.chartType\" calc=\"$ctrl.currentCalc\"></salaxy-calc-chart>\r\n          <p class=\"text-center\" ng-if=\"$ctrl.isHouseholdDeductible\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.nowPaying\" ps=\":\"></span> {{ $ctrl.currentCalc.result.employerCalc.totalPayment | currency: \"\":2 }} €\r\n            <br />\r\n            <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.finalCost\" ps=\":\"></span> {{ $ctrl.currentCalc.result.employerCalc.finalCost | currency: \"\":2 }} €\r\n          </p>\r\n          <p class=\"text-center\" ng-if=\"!$ctrl.isHouseholdDeductible\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcDetailsSalaryComponent.paymentTotal.title\" ps=\":\"></span> {{ $ctrl.currentCalc.result.employerCalc.finalCost | currency: \"\":2 }} €\r\n          </p>\r\n        </div>\r\n        <div class=\"col-xs-6 col-md-4\">\r\n          <h3 class=\"text-center\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></h3>\r\n          <salaxy-calc-chart role=\"worker\" scale-y-axis=\"true\" chart-type=\"$ctrl.chartType\" calc=\"$ctrl.currentCalc\"></salaxy-calc-chart>\r\n          <p class=\"text-center\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcResultsComponent.workerGetsPaid\" ps=\":\"></span> {{ $ctrl.currentCalc.result.workerCalc.totalWorkerPayment | currency: \"\":2 }} €\r\n          </p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <a class=\"action-link\" ng-click=\"$ctrl.showReportDialog('employerReport')\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.employerReport\"></a>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <a class=\"action-link\" ng-click=\"$ctrl.showReportDialog('paymentReport')\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.societyReport\"></a>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <a class=\"action-link\" ng-click=\"$ctrl.showReportDialog('salarySlip')\" sxy-text=\"SALAXY.NG1.CalcResultsComponent.workerReport\"></a>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcRowType.html\",`<div class=\"salaxy-component salaxy-calc-row-type\">\r\n  <div ng-if=\"$ctrl.type == 'read-only'\" class=\"salaxy-calc-row-type-read-only\">\r\n    {{ $ctrl.getRowLabel() | sxyTranslate }}\r\n  </div>\r\n  <div ng-if=\"$ctrl.type == 'typehead'\" class=\"salaxy-calc-row-type-typehead\" style=\"position: relative\">\r\n    <input type=\"text\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.placeholder || 'SALAXY.UI_Terms.select' | sxyTranslate }}\" ng-require=\"$ctrl.require\" autocomplete=\"off\" ng-model=\"$ctrl.internalValue\" ng-model-options=\"{allowInvalid: true, debounce: 250}\"\r\n      class=\"form-control\" uib-typeahead=\"type as type.text for type in $ctrl.search($viewValue)\" typeahead-template-url=\"salaxy-components/calc/CalcRowTypeItem.html\" typeahead-show-hint=\"true\" typeahead-append-to-body=\"true\" typeahead-min-length=\"0\" typeahead-editable=\"false\">\r\n    <button type=\"button\" class=\"close\" aria-label=\"Close\" ng-if=\"$ctrl.internalValue\" ng-click=\"$ctrl.internalValue = null\" style=\"font-size: 2em; position: absolute; right: 10px; top: 3px\">\r\n      <span aria-hidden=\"true\">&times;</span>\r\n    </button>\r\n  </div>\r\n  <div ng-if=\"$ctrl.type == 'list'\" class=\"salaxy-calc-row-type-list\">\r\n    <div class=\"list-group\">\r\n      <div ng-repeat=\"item in $ctrl.getCachedSearch($ctrl.searchText, true)\">\r\n        <a ng-if=\"item.ui.iconText\" class=\"list-group-item clickable\" ng-click=\"$ctrl.internalValue = item\" ng-class=\"{ 'active': $ctrl.internalValue == item }\">\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: item.ui.color, initials: item.ui.iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          <b class=\"salaxy-highlight\" ng-bind-html=\"item.text | uibTypeaheadHighlight:$ctrl.searchText\"></b><br />\r\n          <small class=\"salaxy-highlight\">\r\n            <div ng-bind-html=\"item.title | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </small>\r\n        </a>\r\n        <a ng-if=\"!item.ui.iconText\" class=\"list-group-item clickable salaxy-highlight\" ng-click=\"$ctrl.internalValue = item\" ng-class=\"{ 'active': $ctrl.internalValue == item }\" title=\"{{ enum.title }}\" style=\"display: list-item; list-style-type: disc; list-style-position: inside; padding: 2px 2px 2px 60px\">\r\n          <span ng-bind-html=\"item.text | uibTypeaheadHighlight:query\"></span>\r\n        </a>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.type == 'table'\" class=\"salaxy-calc-row-type-table\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr class=\"active\">\r\n          <td>\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: 'rgb(79, 205, 196)', initials: 'type', entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <div><b sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowType\" ps=\" (type)\"></b></div>\r\n            <div sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowDescription\"></div>\r\n          </td>\r\n          <td><b sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowTypeEn\"></b></td>\r\n        </tr>\r\n        <tr class=\"active\">\r\n          <td></td>\r\n          <td sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowKind\" ps=\" (kind)\"></td>\r\n          <td sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowKindEn\"></td>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat-start=\"item in $ctrl.getCachedSearch($ctrl.searchText, true)\" ng-if=\"item.ui.iconText\">\r\n          <th rowspan=\"2\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: item.ui.color, initials: item.ui.iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </th>\r\n          <th>\r\n            <div>\r\n              <b class=\"salaxy-highlight\" ng-bind-html=\"item.text | uibTypeaheadHighlight:$ctrl.searchText\"></b>\r\n              <button type=\"button\" class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.showInfoScreen(item)\" style=\"margin-left: 5px\">edit</button>\r\n            </div>\r\n          </th>\r\n          <th>\r\n            <div class=\"salaxy-highlight\" ng-bind-html=\"item.value | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </th>\r\n        </tr>\r\n        <tr ng-if=\"item.ui.iconText\" class=\"no-border\">\r\n          <td colspan=\"2\" style=\"padding-top: 0;\">\r\n            <div style=\"padding-top: 0;\" class=\"salaxy-highlight\" ng-bind-html=\"item.title | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </td>\r\n        </tr>\r\n        <tr ng-if=\"!item.ui.iconText\">\r\n          <td></td>\r\n          <td>\r\n            <div class=\"salaxy-highlight\" ng-bind-html=\"item.text | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </td>\r\n          <td>\r\n            <div class=\"salaxy-highlight\" ng-bind-html=\"item.value.split('.')[1] | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </td>\r\n        </tr>\r\n        <tr ng-repeat-end=\"item in $ctrl.getList()\" ng-if=\"!item.ui.iconText\" class=\"no-border\">\r\n          <td></td>\r\n          <td colspan=\"2\" style=\"padding-top: 0;\">\r\n            <div class=\"salaxy-highlight\" ng-bind-html=\"item.title | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcRowTypeItem.html\",`<a class=\"clickable\" ng-if=\"match.model.ui.iconText\">\r\n    <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" \r\n    avatar=\"{ color: match.model.ui.color, initials: match.model.ui.iconText, entityType: 'company' }\"></salaxy-avatar>\r\n    <b class=\"salaxy-highlight\" ng-bind-html=\"match.model.text | uibTypeaheadHighlight:query\"></b><br />\r\n    <small class=\"salaxy-highlight\"><div ng-bind-html=\"match.model.title | uibTypeaheadHighlight:query\"></div></small>\r\n</a>\r\n<a class=\"clickable\" ng-if=\"!match.model.ui.iconText\"\r\nstyle=\"display: list-item; list-style-type: disc; list-style-position: inside; padding: 2px 2px 2px 60px\">\r\n  <b class=\"salaxy-highlight\" ng-bind-html=\"match.model.text | uibTypeaheadHighlight:query\"></b> \r\n  <small class=\"salaxy-highlight\"><span ng-bind-html=\"match.model.title || '' | uibTypeaheadHighlight:query\"></span></small>\r\n</a>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcSharingReceiptAction.html\",`<span ng-switch=\"$ctrl.type\">\r\n  <button ng-switch-when=\"approve\" class=\"btn {{$ctrl.buttonClass || 'btn-success btn-block btn-sm' }}\" type=\"button\" id=\"approve\" ng-disabled=\"$ctrl.disabled\"\r\n    ng-click=\"$ctrl.approve()\" title=\"{{'SALAXY.NG1.CalcSharingReceiptActionComponent.approveBtnTitle' | sxyTranslate}}\">\r\n    <span ng-if=\"!$ctrl.iconOnly\">{{'SALAXY.NG1.CalcSharingReceiptActionComponent.approveBtn' | sxyTranslate}}&nbsp;</span>\r\n<span ng-show=\"!$ctrl.isLoading\"><i class=\"fa fa-thumbs-o-up\"></i></span>\r\n<span ng-show=\"$ctrl.isLoading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n</button>\r\n<button ng-switch-when=\"reject\" class=\"btn {{$ctrl.buttonClass || 'btn-danger btn-block btn-sm' }}\" type=\"button\" id=\"reject\" ng-disabled=\"$ctrl.disabled\" ng-click=\"$ctrl.reject()\" title=\"{{'SALAXY.NG1.CalcSharingReceiptActionComponent.rejectBtnTitle' | sxyTranslate}}\">\r\n    <span ng-if=\"!$ctrl.iconOnly\"> {{'SALAXY.NG1.CalcSharingReceiptActionComponent.rejectBtn' | sxyTranslate}}&nbsp;</span>\r\n    <span ng-show=\"!$ctrl.isLoading\"><i class=\"fa fa-thumbs-o-down\"></i></span>\r\n    <span ng-show=\"$ctrl.isLoading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n  </button>\r\n<span ng-switch-default class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.CalcSharingReceiptActionComponent.alertUnknown\"></span>\r\n</span>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcWorkerInfo.html\",`<div class=\"salaxy-component salaxy-calc-worker-info\">\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-3 col-sm-2 col-xxs-3 worker-info-avatar-container\">\r\n      <salaxy-avatar avatar=\"$ctrl.current.worker.avatar\"></salaxy-avatar>\r\n    </div>\r\n    <div class=\"col-xs-9 col-sm-10 col-xxs-9 worker-info-col\">\r\n      <h2>{{ $ctrl.current.worker.avatar.displayName || (\"SALAXY.NG1.WorkerInfo.noSelection\" | sxyTranslate) }}</h2>\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          <div ng-class=\"{'text-danger': $ctrl.taxUi.status != 'ok'}\">{{ $ctrl.taxUi.text || \"&nbsp;\" }}</div>\r\n          <div ng-if=\"!$ctrl.current.worker.paymentData.ibanNumber\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.WorkerInfo.noIbanNumber\"></div>\r\n          <div ng-if=\"$ctrl.current.worker.paymentData.ibanNumber\">{{ $ctrl.current.worker.paymentData.ibanNumber | sxyIban }}</div>\r\n          <div>{{ $ctrl.getPensionText() || \"&nbsp;\" }}</div>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          <div ng-if=\"!$ctrl.current.worker.paymentData.socialSecurityNumberValid\" class=\"text-danger\">\r\n            <span sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noSSNumber\"></span>\r\n            <br />\r\n          </div>\r\n          <div ng-if=\"$ctrl.current.worker.paymentData.socialSecurityNumberValid\">{{ $ctrl.current.worker.paymentData.socialSecurityNumberValid }}<br /></div>\r\n          <span ng-if=\"$ctrl.current.worker.paymentData.telephone\">\r\n            {{ $ctrl.current.worker.paymentData.telephone ||  ('SALAXY.NG1.PaymentDialogComponent.noTel' | sxyTranslate) }}\r\n          </span>\r\n          <br />\r\n          <a href=\"{{ 'mailto:' + $ctrl.current.worker.paymentData.email }}\" ng-if=\"$ctrl.current.worker.paymentData.email\">{{ $ctrl.current.worker.paymentData.email }}</a>\r\n          <div ng-if=\"$ctrl.current && !$ctrl.current.worker.paymentData.email\">\r\n            <span sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noEmail\"></span> &nbsp;\r\n            <span class=\"text-warning\" sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noEmailInfo\"></span>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CalcWorktime.html\",`<style type=\"text/css\">\r\n  .form-condensed .form-group {\r\n    margin-bottom: 1px\r\n  }\r\n\r\n  .form-condensed .form-horizontal .control-label {\r\n    padding-top: 0px;\r\n  }\r\n</style>\r\n<div class=\"salaxy-component salaxy-calc-worktime\" ng-if=\"$ctrl.currentCalc\">\r\n  <form ng-submit=\"$ctrl.submitWorktime()\" name=\"detailsWork2\" class=\"form-horizontal\">\r\n    <div class=\"salaxy-calc-dialog-body\">\r\n      <div class=\"salaxy-calc-dialog-container\">\r\n        <div class=\"row\">\r\n          <div class=\"col-md-6\">\r\n            <h1 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.salaryDateTitle\"></h1>\r\n            <p sxy-html=\"SALAXY.NG1.CalcWorktimeComponent.salaryDateDescription.html\"></p>\r\n            <div class=\"form-horizontal\">\r\n              <salaxy-form-group ng-if=\"$ctrl.currentCalc.workflow.salaryDateKind == 'inPast'\" name=\"salaryDateKind\" class=\"salaxy-component salaxy-read-only\" label-cols=\"col-sm-6\"\r\n                label=\"SALAXY.MODEL.CalcWorkflow.salaryDateKind.title\">\r\n                <div class=\"salaxy-read-only-value\">{{\"SALAXY.ENUM.SalaryDateKind.\" + ($ctrl.currentCalc.workflow.salaryDateKind) + \".label\" | sxyTranslate }}</div>\r\n              </salaxy-form-group>\r\n              <salaxy-datepicker-popup name=\"requestedSalaryDate\" ng-model=\"$ctrl.requestedSalaryDate\" label=\"SALAXY.NG1.CalcWorktimeComponent.salaryDateLabel\"\r\n                label-cols=\"col-sm-6\" date-disabled=\"disable-function\" disable-function=\"$ctrl.isDisabledSalaryDate\"\r\n                placeholder=\"SALAXY.NG1.CalcWorktimeComponent.salaryDatePlaceholder\"></salaxy-datepicker-popup>\r\n            </div>\r\n            <h1 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.worktime.title\"></h1>\r\n            <p ng-if=\"!$ctrl.dateRange.start || !$ctrl.dateRange.start\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.worktime.description\"></p>\r\n            <div class=\"form-horizontal\">\r\n              <salaxy-input-enum ng-model=\"$ctrl.periodShortcut\" require=\"!!$ctrl.isWorkerHolidaysActive\" name=\"periodShortcut\" ng-if=\"!$ctrl.periodShortcut\"\r\n                label=\"SALAXY.CORE.CalcWorktime.salaryPeriod\" label-cols=\"col-sm-6\" type=\"radio\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n              <salaxy-input-enum ng-model=\"$ctrl.periodShortcut\" require=\"!!$ctrl.isWorkerHolidaysActive\" name=\"periodShortcut\" ng-if=\"$ctrl.periodShortcut\"\r\n                label=\"SALAXY.CORE.CalcWorktime.salaryPeriod\" label-cols=\"col-sm-6\" type=\"select\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n              <salaxy-date-range ng-model=\"$ctrl.dateRange\" require=\"!!$ctrl.isWorkerHolidaysActive\" class=\"condensed\" name=\"dateRange\" ng-if=\"$ctrl.periodShortcut == 'other'\"\r\n                on-change=\"$ctrl.dateRangeChange()\" label=\"SALAXY.CORE.CalcWorktime.salaryPeriod\" label-days-count=\"SALAXY.MODEL.CalcWorktime.workDays.title\" label-cols=\"col-sm-6\"\r\n                read-only=\"$ctrl.isReadOnly\"></salaxy-date-range>\r\n              <div ng-if=\"$ctrl.periodShortcut && $ctrl.periodShortcut != 'other'\">\r\n                <salaxy-form-group name=\"periodStartDate\" label=\"SALAXY.MODEL.DateRange.start.title\" label-cols=\"col-sm-6\">\r\n                  <input type=\"text\" class=\"form-control\" autocomplete=\"off\" id=\"periodStartDate\" name=\"periodStartDate\"\r\n                    placeholder=\"{{'SALAXY.UI_Terms.dateFormats.dm' | sxyTranslate}}\" ng-model=\"$ctrl.periodStartDate\"\r\n                    ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" />\r\n                  <div ng-if=\"$ctrl.periodStartDateError\" class=\"salaxy-read-only-value text-danger\">{{ $ctrl.periodStartDateError |sxyTranslate}}</div>\r\n                </salaxy-form-group>\r\n                <salaxy-form-group name=\"formattedRange\" label=\"SALAXY.CORE.CalcWorktime.startAndEndDates\" label-cols=\"col-sm-6\" class=\"salaxy-read-only\">\r\n                  <div class=\"salaxy-read-only-value\">{{ $ctrl.dateRange | sxyDateRange }}</div>\r\n                </salaxy-form-group>\r\n                <salaxy-input-number name=\"labelDaysCount\" ng-model=\"$ctrl.dateRange.daysCount\" ng-change=\"$ctrl.dateRangeChange()\" require=\"!!$ctrl.isWorkerHolidaysActive\"\r\n                  label=\"SALAXY.MODEL.DateRange.daysCount.title\" label-cols=\"col-sm-6\">\r\n                </salaxy-input-number>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div class=\"col-md-6\" ng-if=\"!(('worker' | sxyIsInRole) || ('disableHolidays' | sxyIsInRole))\">\r\n            <h1 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.title\"></h1>\r\n            <div ng-switch=\"$ctrl.getHolidaysStatus()\">\r\n              <div ng-switch-when=\"noWorker\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.descriptionNoWorker\"></div>\r\n              <div ng-switch-when=\"noPeriod\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.descriptionNoPeriod\"></div>\r\n              <div ng-switch-when=\"loading\">\r\n                <salaxy-spinner full-screen=\"false\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.NG1.CalcWorktimeComponent.absences.loadingText\"></salaxy-spinner>\r\n              </div>\r\n              <div ng-switch-when=\"ok\">\r\n                <button class=\"btn btn-default pull-right salaxy-button-pro\" ng-click=\"$ctrl.showPeriodDetails()\" type=\"button\"\r\n                  title=\"{{'SALAXY.NG1.CalcWorktimeComponent.absences.proTabTitle' | sxyTranslate}}\">Pro</button>\r\n                <uib-tabset active=\"$ctrl.currentTab\">\r\n                  <uib-tab index=\"'default'\" heading=\"{{'SALAXY.NG1.CalcWorktimeComponent.absences.calculationTabHeading' | sxyTranslate}}\">\r\n                    <fieldset ng-if=\"$ctrl.accruesHolidays\">\r\n                      <table class=\"table table-striped table-condensed\">\r\n                        <thead>\r\n                          <tr>\r\n                            <th sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.holidays.headerHolidays\"></th>\r\n                            <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.holidays.headerDays\"></th>\r\n                          </tr>\r\n                        </thead>\r\n                        <tbody>\r\n                          <tr ng-repeat=\"month in $ctrl.worktime.accruals\">\r\n                            <td>\r\n                              <strong>{{ $ctrl.getAccrualMonthText('header', month) | sxyTranslate}}</strong><br>\r\n                              <small>\r\n                                <div>\r\n                                  <a href=\"\" ng-click=\"$ctrl.currentTab = 'absences'\">\r\n                                    <span sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.link\"></span> {{ month.absencesDays | sxyCount : 'day' }}\r\n                                  </a>\r\n                                </div>\r\n                              </small>\r\n                            </td>\r\n                            <td class=\"right\">\r\n                              <strong>{{ month.daysAccrued | sxyCount : 'day' }}</strong><br>\r\n                            </td>\r\n                          </tr>\r\n                        </tbody>\r\n                      </table>\r\n                      <small>\r\n                        <p>{{ $ctrl.getAccrualMonthText(\"description\") | sxyTranslate }}</p>\r\n                      </small>\r\n                    </fieldset>\r\n                    <legend sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationLegend\"></legend>\r\n                    <div>\r\n                      <fieldset>\r\n                        <table class=\"table table-striped table-condensed\" ng-if=\"$ctrl.getLogicForLists().getAbcencesForPeriod().length\">\r\n                          <thead>\r\n                            <tr>\r\n                              <th sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerAbsence\"></th>\r\n                              <th class=\"right\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerDays\"></th>\r\n                            </tr>\r\n                          </thead>\r\n                          <tbody>\r\n                            <tr ng-repeat=\"row in $ctrl.getLogicForLists().getAbcencesForPeriod()\">\r\n                              <td>\r\n                                <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\"\r\n                                  avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n                                <strong>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</strong><br />\r\n                                <div class=\"pull-left\" style=\"padding: 0px;\">\r\n                                  {{ row.isPaid ? ('SALAXY.NG1.AbsencePeriodsComponent.isPaid' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notPaid' |sxyTranslate) }}\r\n                                  <span ng-if=\"row.isPaid != row.isHolidayAccrual\"> {{ row.isHolidayAccrual ? ('SALAXY.NG1.AbsencePeriodsComponent.isAccrual' | sxyTranslate) :\r\n                                    ('SALAXY.NG1.AbsencePeriodsComponent.notAccrual' | sxyTranslate) }}</span>\r\n                                </div>\r\n                                <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n                                  &nbsp;{{ row.notes }}\r\n                                </div>\r\n                              </td>\r\n                              <td class=\"right\">\r\n                                <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong><br /> {{ row.period | sxyDateRange }}\r\n                              </td>\r\n                            </tr>\r\n                            <tr class=\"total\">\r\n                              <td>\r\n                                <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" style=\"margin-bottom: 20px\"\r\n                                  avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n                                <strong>\r\n                                  <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalUnpaid\"></span><br />\r\n                                  <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalPaid\"></span><br />\r\n                                  <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalNoHolidayAccrual\"></span><br />\r\n                                  <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalAll\"></span><br />\r\n                                </strong>\r\n                              </td>\r\n                              <td class=\"right\">\r\n                                <strong>\r\n                                  {{ $ctrl.getLogicForLists().getAbcensePeriodsTotalDays(\"absencesUnpaid\") | sxyCount : \"day\" }}<br />\r\n                                  {{ $ctrl.getLogicForLists().getAbcensePeriodsTotalDays(\"absencesPaid\") | sxyCount : \"day\" }}<br />\r\n                                  {{ $ctrl.getLogicForLists().getAbcensePeriodsTotalDays(\"absencesNoHolidayAccrual\") | sxyCount : \"day\" }}<br />\r\n                                  {{ $ctrl.getLogicForLists().getAbcensePeriodsTotalDays(\"all\") | sxyCount : \"day\" }}<br />\r\n                                </strong>\r\n                              </td>\r\n                            </tr>\r\n                          </tbody>\r\n                        </table>\r\n                        <p ng-if=\"!$ctrl.getLogicForLists().getAbcencesForPeriod().length\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.noAbsences\"></p>\r\n                      </fieldset>\r\n                    </div>\r\n                    <div ng-if=\"$ctrl.worktime.holidaySpec.code == 'noHolidays'\">\r\n                      <strong sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationDescriptionNoHolidays\"></strong>\r\n                    </div>\r\n                    <div ng-if=\"$ctrl.worktime.holidaySpec.code == 'holidayCompensation'\">\r\n\r\n                      <div style=\"margin-bottom: 8px; margin-right: 10px;\">\r\n                        <div class=\"pull-right\">{{ $ctrl.worktime.holidaySpec.compensation | sxyCount : 'percent' }}</div>\r\n                        <strong sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationDescriptionHolidayCompensation\"></strong>\r\n                      </div>\r\n                      <div style=\"margin-bottom: 8px; margin-right: 10px;\" ng-if=\"$ctrl.worktime.holidaySpec.bonus > 0\">\r\n\r\n                        <div class=\"pull-right\">{{ $ctrl.worktime.holidaySpec.bonus | sxyCount : 'percent' }}</div>\r\n                        <strong sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationDescriptionHolidayBonus\" pre=\"+ \"></strong>\r\n                      </div>\r\n                      <div ng-if=\"!$ctrl.worktime.holidaySpec.bonus\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationDescriptionNoHolidayBonus\"></div>\r\n                    </div>\r\n                    <div ng-if=\"$ctrl.isHolidayAccrual\">\r\n                      <button ng-if=\"!$ctrl.currentCalc.isReadOnly\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.openCalcLeavesDialog()\">{{\"SALAXY.UI_Terms.edit\" | sxyTranslate}}...</button>\r\n                      <fieldset>\r\n                        <table class=\"table table-striped table-condensed\" ng-if=\"$ctrl.getLogicForLists().getAnnualLeavesForPeriod().length\">\r\n                          <thead>\r\n                            <tr>\r\n                              <th sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.period\"></th>\r\n                              <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.daysCount\"></th>\r\n                            </tr>\r\n                          </thead>\r\n                          <tr ng-repeat=\"row in $ctrl.getLogicForLists().getAnnualLeavesForPeriod()\">\r\n                            <td>\r\n                              <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\"\r\n                                avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n                              <strong>{{ row.period | sxyDateRange }}</strong>\r\n                              <br />\r\n                              <small>\r\n                                <div class=\"truncate\" style=\"max-width: 250px;\">{{ $ctrl.getLogicForLists().getAnnualLeaveDescription(row) }}</div>\r\n                              </small>\r\n                            </td>\r\n                            <td class=\"right\">\r\n                              <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong>\r\n                            </td>\r\n                          </tr>\r\n                          <tr class=\"total\">\r\n                            <td>\r\n                              <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n                              <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.total\"></strong>\r\n                              <br />\r\n                              <small>\r\n                                <div class=\"truncate\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.totalMore\"></div>\r\n                              </small>\r\n                            </td>\r\n                            <td class=\"right\">\r\n                              <strong>{{ $ctrl.getLogicForLists().getAnnualLeavesTotalDays() | sxyCount : \"day\" }}</strong>\r\n                            </td>\r\n                          </tr>\r\n                        </table>\r\n                        <p ng-if=\"!$ctrl.getLogicForLists().getAnnualLeavesForPeriod().length\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.noAnnualLeaves\"></p>\r\n                      </fieldset>\r\n                    </div>\r\n                  </uib-tab>\r\n                  <uib-tab index=\"'absences'\" heading=\"{{'SALAXY.NG1.CalcWorktimeComponent.absences.absencesTabHeading' |sxyTranslate}}\">\r\n                    <div sxy-if-role=\"auth\" ng-controller=\"WorkerAbsencesCrudController as $absencesCtrl\"\r\n                      ng-init=\"$absencesCtrl.employmentId=$ctrl.currentCalc.worker.employmentId\">\r\n                      <salaxy-absence-periods parent=\"$absencesCtrl.current\" condensed=\"true\" on-commit=\"$ctrl.absencesChanged($absencesCtrl)\"\r\n                        ng-if=\"$absencesCtrl.current\"></salaxy-absence-periods>\r\n                    </div>\r\n                    <div sxy-if-role=\"!auth\">\r\n                      <p sxy-html=\"SALAXY.NG1.CalcWorktimeComponent.anonDemoText.html\"></p>\r\n                      <salaxy-absence-periods parent=\"$ctrl.demoData.absences\" condensed=\"true\" on-commit=\"$ctrl.reloadHolidays()\"></salaxy-absence-periods>\r\n                    </div>\r\n                    <p>&nbsp;</p>\r\n                    <small>\r\n                      <p sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.absencesAttention\"></p>\r\n                    </small>\r\n                  </uib-tab>\r\n                  <uib-tab index=\"'leaves'\" heading=\"{{'SALAXY.NG1.CalcWorktimeComponent.absences.leavesTabHeading' | sxyTranslate}}\" ng-if=\"$ctrl.isHolidayAccrual\">\r\n                    <div ng-controller=\"HolidayYearCrudController as $holidaysCtrl\"\r\n                      ng-init=\"$holidaysCtrl.employmentId=$ctrl.currentCalc.worker.employmentId;$holidaysCtrl.forDate=$ctrl.currentCalc.info.workStartDate\">\r\n                      <salaxy-holiday-year-holidays parent=\"$holidaysCtrl.current\" condensed=\"true\" on-commit=\"$ctrl.holidaysChanged($holidaysCtrl)\"\r\n                        ng-if=\"$holidaysCtrl.current\"></salaxy-holiday-year-holidays>\r\n                    </div>\r\n                    <p>&nbsp;</p>\r\n                    <small>\r\n                      <p sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.absencesAttention\"></p>\r\n                    </small>\r\n                  </uib-tab>\r\n                </uib-tabset>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n\r\n    <button ng-show=\"!$ctrl.currentCalc.isReadOnly\" class=\"btn btn-warning btn-lg salaxy-calc-btn-recalculate\" type=\"submit\">{{ $ctrl.hasHolidaysOrAbsences() ?\r\n      ('SALAXY.NG1.CalcWorktimeComponent.absences.calculateButtonText' | sxyTranslate) : ('SALAXY.UI_Terms.updateCalculation' |sxyTranslate) }}</button>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/CostAccounting.html\",`<div class=\"salaxy-component salaxy-cost-accounting\">\r\n\r\n\r\n  <div ng-if=\"$ctrl.current.length > 0 || $ctrl.definitions.length > 0\">\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.CalcCostAccountingComponent.title\"></legend>\r\n      <div ng-repeat=\"dimension in $ctrl.definitions\">\r\n        <div ng-if=\"!dimension.allowCostSharing\">\r\n          <div class=\"form-horizontal\">\r\n            <div class=\"row\">\r\n              <div class=\"col-md-11\">     \r\n                  <salaxy-input-enum class=\"text-muted\" ng-if=\"$ctrl.isInherited(dimension.id) && $ctrl.hasOptions(dimension.id, $ctrl.getInheritedSingleValue(dimension.id).value)\" label=\"{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" ng-model=\"$ctrl.getInheritedSingleValue(dimension.id).value\"\r\n            label-format=\"text-value\" type=\"typeahead\" options=\"$ctrl.getOptions(dimension.id)\" name=\"single\" read-only=\"true\">\r\n                </salaxy-input-enum>\r\n                <salaxy-input class=\"text-muted\" ng-if=\"$ctrl.isInherited(dimension.id) && !$ctrl.hasOptions(dimension.id, $ctrl.getInheritedSingleValue(dimension.id).value)\" label=\"{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" ng-model=\"$ctrl.getInheritedSingleValue(dimension.id).value\" name=\"single\"\r\n                  read-only=\"true\">\r\n                  </salaxy-input>\r\n\r\n                  <salaxy-input-enum ng-if=\"!$ctrl.isInherited(dimension.id) && $ctrl.hasOptions(dimension.id, $ctrl.getSingleValue(dimension.id).value)\" label=\"{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" ng-model=\"$ctrl.getSingleValue(dimension.id).value\"\r\n                  label-format=\"text-value\" type=\"typeahead\" options=\"$ctrl.getOptions(dimension.id)\" name=\"single\" read-only=\"$ctrl.readOnly\" input-mode=\"{{$ctrl.inputMode}}\" ng-change=\"$ctrl.setSingleValue(dimension.id, $ctrl.getSingleValue(dimension.id).value)\"></salaxy-input-enum>\r\n  \r\n                  <salaxy-input ng-if=\"!$ctrl.isInherited(dimension.id) && !$ctrl.hasOptions(dimension.id, $ctrl.getSingleValue(dimension.id).value)\" label=\"{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" ng-model=\"$ctrl.getSingleValue(dimension.id).value\" name=\"single\"\r\n                  read-only=\"$ctrl.readOnly\" input-mode=\"{{$ctrl.inputMode}}\" ng-change=\"$ctrl.setSingleValue(dimension.id, $ctrl.getSingleValue(dimension.id).value)\">\r\n                  </salaxy-input>\r\n              </div>\r\n              <div class=\"col-md-1\">\r\n                <div class=\"btn\">\r\n                  <span ng-if=\"!$ctrl.readOnly && $ctrl.isInherited(dimension.id)\" class=\"btn-padding-right\"> <i ng-click=\"$ctrl.setSingleValue(dimension.id, $ctrl.getInheritedSingleValue(dimension.id).value)\" class=\"fa fa-pencil clickable\"></i></span>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"dimension.allowCostSharing\">\r\n          <div class=\"form-horizontal\">\r\n            <div class=\"row\">\r\n              <div class=\"col-md-11\">    \r\n                <table ng-if=\"$ctrl.isInherited(dimension.id)\" class=\"table\">\r\n                  <thead>\r\n                    <tr>\r\n                      <th class=\"text-muted\">{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}</th>\r\n                      <th class=\"right text-muted\">{{\"SALAXY.NG1.CalcCostAccountingComponent.percent\" | sxyTranslate}}</th>\r\n                      <th class=\"right\">\r\n                      </th>\r\n                    </tr>\r\n                  </thead>\r\n                  <tbody>\r\n                    <tr ng-repeat=\"item in $ctrl.getInheritedValues(dimension.id)\">\r\n                      <td>\r\n                        <salaxy-input-enum class=\"text-muted\" ng-if=\"$ctrl.hasOptions(item.id, item.value)\" ng-model=\"item.value\" type=\"typeahead\" label-format=\"text-value\" options=\"$ctrl.getOptions(dimension.id)\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"true\"></salaxy-input-enum>\r\n                        <salaxy-input class=\"text-muted\" ng-if=\"!$ctrl.hasOptions(item.id, item.value)\" ng-model=\"item.value\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"true\"></salaxy-input>\r\n                      </td>\r\n                      <td class=\"right\">\r\n                        <salaxy-input-number class=\"text-muted\" ng-model=\"item.percent\" name=\"{{ 'percent' + $index }}\" label-type=\"plain\" read-only=\"true\" unit=\"percent\"></salaxy-input-number>\r\n                      </td>\r\n                      <td class=\"text-right\">\r\n                      </td>\r\n                    </tr>\r\n                  </tbody>\r\n                  <tfoot>\r\n                    <tr class=\"total\">\r\n                      <td class=\"text-muted\">{{\"SALAXY.UI_Terms.total\" | sxyTranslate}}</td>\r\n                      <td class=\"right text-muted\">{{ $ctrl.getInheritedSum(dimension.id) | sxyCount : 'percent' }}</td>\r\n                      <td class=\"right\"></td>\r\n                    </tr>\r\n                  </tfoot>\r\n                </table>\r\n                <table ng-if=\"!$ctrl.isInherited(dimension.id)\" class=\"table\">\r\n                  <thead>\r\n                    <tr>\r\n                      <th>{{(dimension.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}</th>\r\n                      <th class=\"right\">{{\"SALAXY.NG1.CalcCostAccountingComponent.percent\" | sxyTranslate}}</th>\r\n                      <th class=\"right\">\r\n                        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.readOnly\" ng-click=\"$ctrl.current.push({'id': dimension.id})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n                      </th>\r\n                    </tr>\r\n                  </thead>\r\n                  <tbody>\r\n                    <tr ng-repeat=\"item in $ctrl.getValues(dimension.id)\">\r\n                      <td>\r\n                        <salaxy-input-enum ng-if=\"$ctrl.hasOptions(item.id, item.value)\" ng-model=\"item.value\" type=\"typeahead\" label-format=\"text-value\" options=\"$ctrl.getOptions(dimension.id)\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.readOnly\"></salaxy-input-enum>\r\n                        <salaxy-input ng-if=\"!$ctrl.hasOptions(item.id, item.value)\" ng-model=\"item.value\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.readOnly\"></salaxy-input>\r\n                      </td>\r\n                      <td class=\"right\">\r\n                        <salaxy-input-number ng-model=\"item.percent\" name=\"{{ 'percent' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.readOnly\" unit=\"percent\"></salaxy-input-number>\r\n                      </td>\r\n                      <td class=\"text-right\">\r\n                        <button ng-if=\"!$ctrl.readOnly\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.deleteValue(item)\">\r\n                          <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n                        </button>\r\n                      </td>\r\n                    </tr>\r\n                  </tbody>\r\n                  <tfoot>\r\n                    <tr class=\"total\">\r\n                      <td>{{\"SALAXY.UI_Terms.total\" | sxyTranslate}}</td>\r\n                      <td class=\"right\">{{ $ctrl.getSum(dimension.id) | sxyCount : 'percent' }}</td>\r\n                      <td class=\"right\"></td>\r\n                    </tr>\r\n                  </tfoot>\r\n                </table>\r\n              </div>\r\n              <div class=\"col-md-1\">\r\n                <div class=\"btn\">\r\n                  <span ng-if=\"!$ctrl.readOnly && $ctrl.isInherited(dimension.id)\" class=\"btn-padding-right\"> <i ng-click=\"$ctrl.setValues($ctrl.getInheritedValues(dimension.id))\" class=\"fa fa-pencil clickable\"></i></span>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.hasObsoleteValues\">\r\n        <table class=\"table\">\r\n          <thead>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.MODEL.CostAccountingDimensionDefinition.id.title\"></th>\r\n              <th sxy-text=\"SALAXY.MODEL.CostAccountingDimensionOption.value.title\"></th>\r\n              <th class=\"right\">{{\"SALAXY.NG1.CalcCostAccountingComponent.percent\" | sxyTranslate}}</th>\r\n              <th class=\"right\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"item in $ctrl.obsoleteValues\">\r\n              <td>\r\n                <salaxy-input ng-model=\"item.id\" name=\"{{ 'nameObsolete' + $index }}\" label-type=\"plain\" read-only=\"true\"></salaxy-input>\r\n              </td>\r\n              <td>\r\n                <salaxy-input ng-model=\"item.value\" name=\"{{ 'idObsolete' + $index }}\" label-type=\"plain\" read-only=\"true\"></salaxy-input-enum>\r\n              </td>\r\n              <td>\r\n                <salaxy-input-number ng-if=\"item.percent\" ng-model=\"item.percent\" name=\"{{ 'percentObsolete' + $index }}\" label-type=\"plain\" read-only=\"true\" unit=\"percent\"></salaxy-input-number>\r\n              </td>\r\n              <td class=\"text-right\">\r\n                <button ng-if=\"!$ctrl.readOnly\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.deleteValue(item)\">\r\n                    <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n                  </button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/details/expenses.html\",`<form ng-submit=\"$ctrl.recalculate()\" name=\"detailsExpenses\">\r\n  <div class=\"salaxy-calc-dialog-body\">\r\n    <div class=\"salaxy-calc-dialog-container\">\r\n      <h1 sxy-text=\"SALAXY.NG1.CalcDetailsDialogComponent.allExpenses.title\"></h1>\r\n      <div class=\"form-horizontal\" ng-if=\"$ctrl.isHousehold\">\r\n        <salaxy-input-boolean type=\"checkbox\" name=\"isHouseholdDeductible\" ng-model=\"$ctrl.isHouseholdDeductible\" label=\"SALAXY.NG1.CalcDetailsDialogComponent.deductions.householdDetuction\" label-true=\"{{'SALAXY.NG1.CalcDetailsDialogComponent.deductions.label' | sxyTranslate}}\"></salaxy-input-boolean>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcDetailsDialogComponent.workType\" hidden-options=\"none\" name=\"taxDeductionCategory\" ng-if=\"$ctrl.isHouseholdDeductible\" ng-model=\"$ctrl.taxDeductionCategory\" enum=\"TaxDeductionWorkCategories\" type=\"select\" required></salaxy-input-enum>\r\n      </div>\r\n      <salaxy-calc-rows-2019-editor categories=\"['expenses']\" row-type-select-help=\"expenses\" parent=\"$ctrl.currentCalc\" mode=\"{{$ctrl.isReadOnly ? 'read-only' : 'edit'}}\" title=\"{{'SALAXY.NG1.CalcDetailsDialogComponent.expenses.title' | sxyTranslate}}\"></salaxy-calc-rows-2019-editor>\r\n      <salaxy-calc-rows-2019-editor categories=\"['benefits']\" row-type-select-help=\"benefits\" parent=\"$ctrl.currentCalc\" mode=\"{{$ctrl.isReadOnly ? 'read-only' : 'edit'}}\" title=\"{{ 'SALAXY.NG1.CalcDetailsDialogComponent.benefits.title2' | sxyTranslate}}\"></salaxy-calc-rows-2019-editor>\r\n      <salaxy-calc-rows-2019-editor categories=\"[ 'deductions']\" row-type-select-help=\"deductions\" parent=\"$ctrl.currentCalc\" mode=\"{{$ctrl.isReadOnly ? 'read-only' : 'edit'}}\" title=\"{{ 'SALAXY.NG1.CalcDetailsDialogComponent.deductions.title' |\r\n        sxyTranslate}}\"></salaxy-calc-rows-2019-editor>\r\n      <p>&nbsp;</p>\r\n    </div>\r\n  </div>\r\n  <button ng-if=\"!$ctrl.isReadOnly && $ctrl.currentCalc.workflow.status !='paymentStarted'\" class=\"btn btn-danger btn-lg salaxy-calc-btn-recalculate\" type=\"submit\" sxy-text=\"SALAXY.UI_Terms.recalculate\"></button>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/calc/details/salary.html\",`<form ng-submit=\"$ctrl.recalculate()\" name=\"detailsSalary\">\r\n  <div class=\"salaxy-calc-dialog-body\">\r\n    <div class=\"salaxy-calc-dialog-container\">\r\n      <h1 sxy-text=\"SALAXY.NG1.CalcDetailsDialogComponent.allSalaries.title\"></h1>\r\n      <salaxy-calc-rows-2019-editor row-type-select-help=\"salaries\" categories=\"['salary', 'salaryCalc', 'holidays', 'salaryAdditions']\" parent=\"$ctrl.currentCalc\" mode=\"{{$ctrl.isReadOnly ? 'read-only' : 'edit'}}\" title=\"{{'SALAXY.NG1.CalcDetailsDialogComponent.salaries.title2' | sxyTranslate}}\"></salaxy-calc-rows-2019-editor>\r\n      <p>&nbsp;</p>\r\n\r\n    </div>\r\n  </div>\r\n\r\n  <button ng-if=\"!$ctrl.isReadOnly && $ctrl.currentCalc.workflow.status != 'paymentStarted'\" class=\"btn btn-success btn-lg salaxy-calc-btn-recalculate\" type=\"submit\" sxy-text=\"SALAXY.UI_Terms.recalculate\"></button>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/calc/details/worker.html\",`<form ng-submit=\"$ctrl.recalculate()\" name=\"detailsWork\">\r\n  <div class=\"salaxy-calc-dialog-body\">\r\n    <div class=\"salaxy-calc-dialog-container\">\r\n      <div ng-if=\"!$ctrl.calcSections.get('worker').isSelectionDone\">\r\n\r\n        <div sxy-if-role=\"auth\">\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-12 col-sm-7\">\r\n              <div class=\"intro-text\">\r\n                <h1 sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.selectWorker\"></h1>\r\n                <p sxy-html=\"SALAXY.NG1.CalcDetailsWorkerComponent.myWorkers.description.html\"></p>\r\n              </div>\r\n            </div>\r\n            <div class=\"col-xs-12 col-sm-5\">\r\n              <button type=\"button\" class=\"btn add-new-worker btn-primary pull-right-sm\" style=\"margin-bottom:5px;\" ng-click=\"$ctrl.showNewWorkerDialog()\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.newWorker.cta\"></button>\r\n            </div>\r\n            <div class=\"col-xs-12\">\r\n              <div class=\"table-responsive\">\r\n                <salaxy-employment-list mode=\"select\" on-list-select=\"$ctrl.updateFromEmployment(item.id, true)\"></salaxy-employment-list>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div salaxy-if-role=\"anon\">\r\n          <h1 sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.selectWorker\" ps=\" (demo)\"></h1>\r\n          <p sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.notLoggedIn\"></p>\r\n          <p>Selecting an employment relation is not supported in the anonymous calculator. Implement if necessary.</p>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.calcSections.get('worker').isSelectionDone\">\r\n        <h1 sxy-translate=\"SALAXY.NG1.CalcDetailsWorkerComponent.workerInfo.title\"></h1>\r\n        <salaxy-calc-worker-info model=\"$ctrl.currentCalc\"></salaxy-calc-worker-info>\r\n        <div class=\"row\">\r\n          <div class=\"col-md-6 col-xs-12 form-horizontal\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.job\"></legend>\r\n              <salaxy-input-occupation-type name=\"occupationCode\" ng-model=\"$ctrl.currentCalc.info.occupationCode\" label=\"SALAXY.MODEL.CalcInfo.occupationCode.title\" read-only=\"$ctrl.isReadOnly\">\r\n              </salaxy-input-occupation-type>\r\n              <salaxy-input name=\"workDescription\" ng-model=\"$ctrl.currentCalc.info.workDescription\" label=\"SALAXY.MODEL.CalcInfo.workDescription.title\" read-only=\"$ctrl.isReadOnly\"></salaxy-input>\r\n              <salaxy-textarea sxy-if-role=\"!worker\" name=\"salarySlipMessage\" ng-model=\"$ctrl.currentCalc.info.salarySlipMessage\" label=\"SALAXY.MODEL.CalcInfo.salarySlipMessage.title\" read-only=\"$ctrl.isReadOnly\"></salaxy-textarea>\r\n            </fieldset>\r\n          </div>\r\n          <div class=\"col-md-6 col-xs-12 form-horizontal\">\r\n              <salaxy-calc-cost-accounting salaxy-if-role=\"company\" calc=\"$ctrl.current\" read-only=\"$ctrl.isReadOnly\"></salaxy-calc-cost-accounting>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\" sxy-if-role=\"worker\">\r\n          <div class=\"col-xs-12 form-horizontal\">\r\n            <a href=\"#/taxcards\" class=\"btn add-new-worker btn-info\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.addSharedTaxCard\"></a>\r\n            <a href=\"#/account\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.editAccount\"></a>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\" sxy-if-role=\"!worker\">\r\n          <div class=\"col-xs-12 form-horizontal\">\r\n            <span sxy-if-role=\"auth\">\r\n              <span ng-if=\"$ctrl.currentCalc.worker.tax.snapshot.kind == 'auto'\">\r\n                <span class=\"text-info\" ng-if=\"$ctrl.currentCalc.worker.tax.snapshot.lastChecked != '2000-01-01T00:00:00Z'\"><small>{{'SALAXY.NG1.CalcDetailsWorkerComponent.taxCardChecked' | sxyTranslate}} {{$ctrl.currentCalc.worker.tax.snapshot.lastChecked | date: \"dd.MM.yyyy HH:mm\"}}</small></span>\r\n                <br/>\r\n                <button type=\"button\" ng-disabled=\"$ctrl.loaders['showRefreshAutoTaxcardDialog']\" ng-click=\"$ctrl.showRefreshAutoTaxcardDialog()\" class=\"btn btn-info\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.checkAutomaticTaxcard\"></button>\r\n              </span>\r\n              <button type=\"button\" ng-click=\"$ctrl.showWorkerEditDialog()\" class=\"btn add-new-worker btn-default\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.workerEdit\"></button>\r\n            </span>\r\n            <button ng-if=\"!$ctrl.isReadOnly &&  $ctrl.currentCalc.workflow.status != 'paymentStarted'\" ng-click=\"$ctrl.resetWorker()\" type=\"button\" class=\"btn add-new-worker btn-default\" sxy-text=\"SALAXY.NG1.CalcDetailsWorkerComponent.resetWorker\"></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <button ng-if=\"!$ctrl.isReadOnly\" ng-disabled=\"!$ctrl.calcSections.get('worker').isSelectionDone\" class=\"btn btn-info btn-lg salaxy-calc-btn-recalculate\" type=\"submit\" sxy-text=\"SALAXY.UI_Terms.recalculate\"></button>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/calc/details/worktime-pro.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1><span class=\"label label-default\">Pro</span><span sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.proTabTitle\"></span></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <div class=\"form-horizontal form-condensed\">\r\n      <p class=\"lead\" sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.lead.text\"></p>\r\n      <div class=\"row\">\r\n        <div class=\"col-sm-6\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.basicInfo\"></legend>\r\n            <salaxy-date-range read-only=\"true\" ng-model=\"$ctrl.data.worktime.workDays\" name=\"workDays\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.workDays\"></salaxy-date-range>\r\n          </fieldset>\r\n          <fieldset>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.worktime.absencesDailySalary\" name=\"absencesDailySalary\" label=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.absencesDailySalary\" label-cols=\"col-sm-6\"></salaxy-input-number>\r\n            <table class=\"table table-striped table-condensed\" ng-if=\"$ctrl.data.logic.getAbcencesForPeriod().length\">\r\n              <thead>\r\n                <tr>\r\n                  <th sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerAbsence\"></th>\r\n                  <th class=\"right\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerDays\"></th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"row in $ctrl.data.logic.getAbcencesForPeriod()\">\r\n                  <td>\r\n                    <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n                    <strong>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</strong><br />\r\n                    <div class=\"pull-left\" style=\"padding: 0px;\">\r\n                      {{ row.isPaid ? ('SALAXY.NG1.AbsencePeriodsComponent.isPaid' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notPaid' |sxyTranslate) }}\r\n                      <span ng-if=\"row.isPaid != row.isHolidayAccrual\"> {{ row.isHolidayAccrual ? ('SALAXY.NG1.AbsencePeriodsComponent.isAccrual' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notAccrual' | sxyTranslate) }}</span>\r\n                    </div>\r\n                    <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n                      &nbsp;{{ row.notes }}\r\n                    </div>\r\n                  </td>\r\n                  <td class=\"right\">\r\n                    <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong><br /> {{ row.period | sxyDateRange }}\r\n                  </td>\r\n                </tr>\r\n                <tr class=\"total\">\r\n                  <td>\r\n                    <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" style=\"margin-bottom: 20px\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n                    <strong>\r\n                     <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalUnpaid\"></span><br />\r\n                                 <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalNoHolidayAccrual\"></span><br />\r\n                                   <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalAll\"></span><br />\r\n                    </strong>\r\n                  </td>\r\n                  <td class=\"right\">\r\n                    <strong>\r\n                      {{ $ctrl.data.logic.getAbcensePeriodsTotalDays(\"absencesUnpaid\") | sxyCount : \"day\" }}<br />\r\n                      {{ $ctrl.data.logic.getAbcensePeriodsTotalDays(\"absencesNoHolidayAccrual\") | sxyCount : \"day\" }}<br />\r\n                      {{ $ctrl.data.logic.getAbcensePeriodsTotalDays(\"all\") | sxyCount : \"day\" }}<br />\r\n                    </strong>\r\n                  </td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n            <p ng-if=\"!$ctrl.data.logic.getAbcencesForPeriod().length\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.absencePeriods.noAbsences\"></p>\r\n          </fieldset>\r\n          <fieldset  ng-if=\"$ctrl.data.worktime.holidaySpec.code == 'permanent14Days' || $ctrl.data.worktime.holidaySpec.code == 'permanent35Hours' || $ctrl.data.worktime.holidaySpec.code == 'temporaryTimeOff'\">\r\n            <table class=\"table table-striped table-condensed\" ng-if=\"$ctrl.data.logic.getAnnualLeavesForPeriod().length\">\r\n              <thead>\r\n                <tr>\r\n                  <th sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.period\"></th>\r\n                  <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.daysCount\"></th>\r\n                  <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.bonusDaysCount\"></th>\r\n                </tr>\r\n              </thead>\r\n              <tr ng-repeat=\"row in $ctrl.data.logic.getAnnualLeavesForPeriod()\">\r\n                <td>\r\n                  <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n                  <strong>{{ row.period | sxyDateRange }}</strong>\r\n                  <br />\r\n                  <small>\r\n                    <div class=\"truncate\" style=\"max-width: 250px;\">{{ $ctrl.data.logic.getAnnualLeaveDescription(row) }}</div>\r\n                  </small>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <strong>{{ row.period.daysCount | sxyCount : \"day\"  }}</strong>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <strong>{{ row.bonusDaysCount | sxyCount : \"day\"  }}</strong>\r\n                </td>\r\n              </tr>\r\n              <tr class=\"total\">\r\n                <td>\r\n                  <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n                  <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.total\"></strong>\r\n                  <br />\r\n                  <small>\r\n                    <div class=\"truncate\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.totalMore\"></div>\r\n                  </small>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <strong>{{ $ctrl.data.logic.getAnnualLeavesTotalDays() | sxyCount : \"day\" }}</strong>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <strong>{{ $ctrl.data.logic.getAnnualLeavesBonusTotalDays() | sxyCount : \"day\" }}</strong>\r\n                </td>\r\n              </tr>\r\n            </table>\r\n            <p ng-if=\"!$ctrl.data.logic.getAnnualLeavesForPeriod().length\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.lists.annualLeaves.noAnnualLeaves\"></p>\r\n          </fieldset>      \r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <fieldset ng-if=\"$ctrl.data.worktime.accrualSpec.code == 'permanent14Days' || $ctrl.data.worktime.accrualSpec.code == 'permanent35Hours' || $ctrl.data.worktime.accrualSpec.code == 'temporaryTimeOff'\">\r\n            <legend sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.holidays\"></legend>\r\n            <table class=\"table table-condensed\">\r\n              <thead>\r\n                <th sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.headerMonth\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.headerHolidays\" class=\"right\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.headerAway\" class=\"right\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.headerDate\" class=\"right\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.headerHours\" class=\"right\"></th>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"month in $ctrl.data.worktime.accruals\">\r\n                  <td>{{ month.month | sxyDate }}</td>\r\n                  <td class=\"right\">{{ month.daysAccrued | sxyCount : \"days\" }}</td>\r\n                  <td class=\"right\">{{ month.absencesDays | sxyCount : \"days\" }}</td>\r\n                  <td class=\"right\">{{ month.workDays | sxyCount : \"days\" }}</td>\r\n                  <td class=\"right\">{{ month.workHours | sxyCount : \"hours\" }}</td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </fieldset>\r\n          <fieldset ng-if=\"$ctrl.data.worktime.holidaySpec.code != 'undefined'\">\r\n            <legend sxy-text=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.holidayYearSettings\"></legend>\r\n            <salaxy-form-group name=\"employmentPeriod\" class=\"salaxy-read-only\" label-cols=\"col-sm-6\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.employmentPeriod\">\r\n              <div class=\"salaxy-read-only-value\">\r\n                {{$ctrl.data.worktime.holidaySpec.employmentPeriod | sxyDateRange }}\r\n              </div>\r\n            </salaxy-form-group>\r\n            <salaxy-input-enum disabled=\"true\" ng-model=\"$ctrl.data.worktime.holidaySpec.wageBasis\" name=\"wageBasis\" enum=\"WageBasis\" hidden-options=\"other\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.wageBasis\" label-cols=\"col-sm-6\"></salaxy-input-enum>\r\n            <salaxy-input-enum disabled=\"true\" name=\"holidayPayCalculation\" ng-model=\"$ctrl.data.worktime.holidaySpec.holidayPayCalculation\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayCalculation.title\" options=\"$ctrl.data.logic.getholidayPayCalculationOptions()\" disable-cache=\"true\" label-cols=\"col-sm-6\"></salaxy-input-enum>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.worktime.leavesDailySalary\" name=\"leavesDailySalary\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.leavesDailySalary\" label-cols=\"col-sm-6\"></salaxy-input-number>\r\n\r\n            <salaxy-input-number  ng-model=\"$ctrl.data.worktime.holidaySpec.compensation\" name=\"compensation\" ng-if=\"$ctrl.data.worktime.holidaySpec.code == 'holidayCompensation'\" label-cols=\"col-sm-6\" unit=\"percent\" required label=\"SALAXY.MODEL.HolidaySpecificationForYear.compensation.title\" ></salaxy-input-number>     \r\n            <salaxy-input-number  ng-model=\"$ctrl.data.worktime.holidaySpec.compensation\" name=\"compensation\" ng-if=\"$ctrl.data.worktime.holidaySpec.code == 'temporaryTimeOff' && $ctrl.data.worktime.holidaySpec.holidayPayCalculation == 'holidayCompensation'\" label-cols=\"col-sm-6\" unit=\"percent\" required label=\"SALAXY.MODEL.HolidaySpecificationForYear.compensation.title\" ></salaxy-input-number>\r\n         \r\n            <!-- accruals or compensation -->\r\n            <salaxy-input-enum ng-if=\"($ctrl.data.worktime.holidaySpec.code == 'permanent14Days' || $ctrl.data.worktime.holidaySpec.code == 'permanent35Hours' || $ctrl.data.worktime.holidaySpec.code == 'temporaryTimeOff')\" ng-model=\"$ctrl.data.worktime.holidaySpec.bonusMethod\" name=\"bonusMethod\" filter=\"none,payForHolidaySalary,paySelectedDays\" enum=\"HolidayBonusPaymentMethod\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.bonusMethod\" label-cols=\"col-sm-6\"></salaxy-input-enum>\r\n            <salaxy-input-enum ng-if=\"($ctrl.data.worktime.holidaySpec.code == 'holidayCompensation')\" ng-model=\"$ctrl.data.worktime.holidaySpec.bonusMethod\" name=\"bonusMethod\" filter=\"none,payForHolidaySalary\" enum=\"HolidayBonusPaymentMethod\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.bonusMethod\" label-cols=\"col-sm-6\"></salaxy-input-enum>\r\n \r\n            <salaxy-input-number ng-if=\"($ctrl.data.worktime.holidaySpec.code == 'holidayCompensation' || $ctrl.data.worktime.holidaySpec.code == 'permanent14Days' || $ctrl.data.worktime.holidaySpec.code == 'permanent35Hours' || $ctrl.data.worktime.holidaySpec.code == 'temporaryTimeOff')\" ng-model=\"$ctrl.data.worktime.holidaySpec.bonus\" name=\"bonus\" label=\"SALAXY.NG1.CalcDetailsWorktimeProComponent.bonus\" label-cols=\"col-sm-6\" unit=\"percent\"></salaxy-input-number>\r\n          </fieldset>\r\n          <fieldset ng-if=\"$ctrl.data.worktime.holidaySpec.code == 'permanent14Days' || $ctrl.data.worktime.holidaySpec.code == 'permanent35Hours' || $ctrl.data.worktime.holidaySpec.code == 'temporaryTimeOff'\">\r\n            <legend sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.availableHolidays.legend\"></legend>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.worktime.holidayPayAccrualRemaining\" name=\"holidayPayAccrualRemaining\" disabled=\"true\" label=\"SALAXY.NG1.CalcWorktimeComponent.availableHolidays.holidayPayAccrualRemaining\" label-cols=\"col-sm-7\"></salaxy-input-number>\r\n            <salaxy-input-number ng-if=\"$ctrl.data.worktime.holidaySpec.bonusMethod != 'none'\" ng-model=\"$ctrl.data.worktime.holidayBonusAccrualRemaining\" name=\"holidayBonusAccrualRemaining\" disabled=\"true\" label=\"SALAXY.NG1.CalcWorktimeComponent.availableHolidays.holidayBonusAccrualRemaining\" label-cols=\"col-sm-7\"></salaxy-input-number>\r\n          </fieldset>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/PayButton.html\",`<div class=\"salaxy-pay-button salaxy-component\">\r\n  <button ng-if=\"($ctrl.mode || 'pay-button') != 'channel-select'\" ng-disabled=\"$ctrl.disabled\" type=\"button\" ng-click=\"$ctrl.goToInvoices()\" class=\"btn btn-primary btn-labeled-right\" ng-class=\"$ctrl.buttonClass + ($ctrl.mode == 'button-and-channel' ? ' btn-block' : '')\">\r\n    {{ $ctrl.getPaymentButtonText() }} <i class=\"fa fa-eur\"></i>\r\n  </button>\r\n  <div ng-if=\"$ctrl.showPaymentChannelSelection()\">\r\n    <div ng-if=\"$ctrl.mode == 'button-and-channel'\" class=\"payment-channel-selection-label\" sxy-text=\"SALAXY.NG1.PayButtonComponent.paymentChannelLabel\" ps=\":\"></div>\r\n    <div ng-if=\"($ctrl.mode || 'pay-button') != 'pay-button'\" class=\"btn-group\" uib-dropdown ng-class=\"$ctrl.buttonClass + ($ctrl.mode == 'button-and-channel' ? ' btn-block' : '')\">\r\n      <button id=\"btnChannel\" type=\"button\" class=\"btn btn-default btn-block\" style=\"text-align: left\" uib-dropdown-toggle>\r\n        <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 8px -2px -2px;\" avatar=\"$ctrl.currentChannel\"></salaxy-avatar>\r\n        {{ $ctrl.currentChannel.displayName }}\r\n        <i class=\"fa fa-caret-down\" ></i>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnChannel\">\r\n        <li role=\"menuitem\" ng-class=\"{ 'disabled': channel.id == 'zeroPayment' }\" ng-repeat=\"channel in $ctrl.allChannels\">\r\n          <a href=\"\" ng-click=\"$ctrl.setPaymentChannel(channel.id)\" title=\"{{ channel.description }}\">\r\n            <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"channel\"></salaxy-avatar> {{ channel.displayName }}\r\n          </a>\r\n        </li>\r\n        <li>\r\n          <a href=\"#/settings/payment-channel-settings\" sxy-text=\"SALAXY.NG1.PayButtonComponent.moreOptionsLink\" ps=\"...\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollCalcs.html\",`<div class=\"salaxy-component salaxy-calc-group-edit\">\r\n  <div class=\"payroll-calculations-container\">\r\n\r\n    <div class=\"dropdown toolbar-top\" ng-if=\"$ctrl.hasCalculations\">\r\n      <ng-include src=\"'salaxy-components/calc/payroll/PayrollCalcs_toolbar.html'\"></ng-include>\r\n    </div>\r\n    \r\n\r\n    <div ng-if=\"!$ctrl.hasCalculations\">\r\n      <div class=\"salaxy-placeholder-empty placeholder-md placeholder-default text-center\">\r\n        <h4 sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.placeholder.title\"></h4>\r\n        <div ng-if=\"$ctrl.mode != 'service'\" class=\"btn-group dropdown\" uib-dropdown>\r\n          <button type=\"button\" class=\"btn btn-labeled-left btn-primary dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\"><i class=\"fa fa-plus\"></i>\r\n            <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCalculation\"></span> <span class=\"caret\"></span>\r\n          </button>\r\n          <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"addcalculation\">\r\n            <li role=\"menuitem\">\r\n              <a ng-click=\"$ctrl.createNewCalc()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addWorker\"></a>\r\n            </li>\r\n            <li role=\"menuitem\">\r\n              <a ng-click=\"$ctrl.addExistingCalc('draft')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addDraft\"></a>\r\n            </li>\r\n            <li role=\"menuitem\">\r\n              <a ng-click=\"$ctrl.addExistingCalc('paid')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCopy\"></a>\r\n            </li>\r\n            <li role=\"menuitem\">\r\n              <a ng-click=\"$ctrl.mergePayroll(true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addPayroll\"></a>\r\n            </li>\r\n          </ul>\r\n        </div>\r\n        <button ng-if=\"$ctrl.mode == 'service'\" type=\"button\" class=\"btn btn-labeled-right btn-primary\" ng-click=\"$ctrl.createNewCalc()\">\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCalculation\"></span><i class=\"fa fa-plus\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-repeat=\"calc in $ctrl.calcs | filter: {worker:{avatar:{displayName:$ctrl.searchByName}}}\">\r\n      \r\n      <div class=\"payroll-single-calculation col-padding\" ng-class=\"{'error-container': !$ctrl.getValidation(calc).isValid }\">\r\n        <div class=\"pull-right icon-container btn-group\">\r\n          <button class=\"btn btn-transparent btn-xs toggle-details\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\"><i class=\"fa\"\r\n              ng-class=\"{'fa-chevron-up' : !$ctrl.getUi(calc).isCollapsed,  'fa-chevron-down' : $ctrl.getUi(calc).isCollapsed}\"\r\n              title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.toggle' | sxyTranslate}}\"></i></button>\r\n          <div class=\"btn-group btn-group-sm dropdown salaxy-dropdown-menu-right\" uib-dropdown>\r\n            <button class=\"btn btn-transparent btn-xs options dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\" ng-if=\"!$ctrl.isReadOnly\"><i\r\n                class=\"fa fa-ellipsis-h\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.options' | sxyTranslate}}\"></i></button>\r\n            <ul class=\"dropdown-menu\" uib-dropdown-menu template-url=\"salaxy-components/calc/payroll/PayrollCalcs_edit_dropdown.html\"></ul>\r\n          </div>\r\n        </div>\r\n        <div class=\"payroll-worker-summary clickable\" ng-if=\"$ctrl.getUi(calc).isCollapsed\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\">\r\n          <div class=\"avatar-container\">\r\n            <salaxy-avatar avatar=\"calc.worker.avatar\"></salaxy-avatar>\r\n            <span class=\"worker-name\">{{calc.worker.avatar.displayName}}</span>\r\n            <span class=\"calculation-summary\">{{calc.result.totals.totalGrossSalary | currency }}</span>\r\n            <span ng-if=\"!$ctrl.getValidation(calc).isValid\" class=\"error-summary text-danger hidden-xs\" sxy-text=\"{{'SALAXY.VALIDATION.' + $ctrl.getValidation(calc).errors[0].code + '.label'}}\"></span>\r\n            <span ng-if=\"!$ctrl.isReadOnly\">\r\n              <span ng-controller=\"EmploymentCrudController as $employment\">\r\n                <salaxy-workflow-badge ng-if=\"$ctrl.employments[calc.worker.employmentId]\" mode=\"horizontal\" model=\"$ctrl.employments[calc.worker.employmentId]\" api-ctrl=\"$employment\" wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n              </span>\r\n            </span>\r\n          </div>\r\n        </div>\r\n        <div class=\"payroll-worker-details\" ng-if=\"!$ctrl.getUi(calc).isCollapsed\">\r\n          <div class=\"row payroll-worker-info\">\r\n            <div class=\"col-xs-2 col-sm-2 col-xxs-9\">\r\n              <div class=\"avatar-container\">\r\n                <salaxy-avatar avatar=\"calc.worker.avatar\"></salaxy-avatar>\r\n              </div>\r\n            </div>\r\n            <div class=\"col-xs-9 col-xxs-10\">\r\n              <h3 class=\"worker-name clickable\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\">{{calc.worker.avatar.displayName}}</h3>\r\n              <div class=\"row\">\r\n                <div class=\"col-xs-12 col-sm-5 worker-info-col\">\r\n                  {{calc.worker.paymentData.email}}<br> {{calc.worker.paymentData.telephone}}\r\n                  <br>\r\n                  <span ng-if=\"calc.worker.paymentData.ibanNumber\">{{calc.worker.paymentData.ibanNumber | sxyIban}}</span>\r\n                  <span ng-if=\"!calc.worker.paymentData.ibanNumber\"><span class=\"text-danger\"\r\n                      sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.noIban\"></span></span>\r\n                  <br>\r\n                  <button class=\"btn btn-secondary btn-xs btn-edit-worker\" ng-click=\"$ctrl.showEditWorkerDialog(calc)\" ng-class=\"{'btn-danger':!calc.worker.paymentData.ibanNumber}\" ng-if=\"!$ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.editWorker\"></button>\r\n                </div>\r\n                <div class=\"col-xs-12 col-sm-7 worker-info-col\">\r\n                  <span>\r\n                    <span ng-class=\"{'text-danger': $ctrl.getTaxUi(calc).status != 'ok'}\">{{ $ctrl.getTaxUi(calc).text }}</span>\r\n                    <button ng-if=\"!$ctrl.isReadOnly && $ctrl.getTaxUi(calc).status != 'ok'\" class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.commitCalc(calc, false, true)\"><i class=\"fa fa-refresh\"></i></button>\r\n                    <button ng-if=\"!$ctrl.isReadOnly && $ctrl.getTaxUi(calc).status == 'missing'\" class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.showAddNewTaxcard(calc)\"><i class=\"fa fa-plus\"></i></button>\r\n                  </span>\r\n                  <span ng-if=\"calc.worker.tax.snapshot.kind == 'auto'\">\r\n                    <br />\r\n                    <span class=\"text-info\" ng-if=\"calc.worker.tax.snapshot.lastChecked != '2000-01-01T00:00:00Z'\"><small>{{'SALAXY.NG1.PayrollComponent.payrollCalcs.taxCard.taxCardChecked' | sxyTranslate}} {{calc.worker.tax.snapshot.lastChecked | date: \"dd.MM.yyyy HH:mm\"}}</small></span>\r\n                  <br/>\r\n                  <button ng-if=\"!$ctrl.isReadOnly\" class=\"btn btn-xs btn-info\" ng-disabled=\"$ctrl.loaders['showRefreshAutoTaxcardDialog']\" ng-click=\"$ctrl.showRefreshAutoTaxcardDialog(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.taxCard.refreshAutoTaxCard\"></button>\r\n                  </span>\r\n                  <br> <strong sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.salaryPeriod\"></strong>\r\n                  <span>{{ calc.info | sxyDateRange }} ({{ calc.framework.numberOfDays }} <span\r\n                      sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.salaryPeriodDaysCount\"></span>)</span>\r\n                  <button class=\"btn btn-transparent btn-xs\" ng-click=\"$ctrl.showDateRangeForCalculation(calc)\" ng-if=\"!$ctrl.isReadOnly\"><i class=\"fa fa-pencil\"></i></button>\r\n                  <div ng-if=\"$ctrl.isDateDifferent(calc)\">\r\n                    <del class=\"small\">{{ $ctrl.current.input.period | sxyDateRange }} ({{ $ctrl.current.input.period.daysCount }} <span\r\n                        sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.salaryPeriodDaysCount\"></span>)</del>\r\n                  </div>\r\n                  <table ng-if=\"!('disableHolidays' | sxyIsInRole)\" class=\"text-small\">\r\n                    <tbody>\r\n                      <tr>\r\n                        <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.leavesDays\"></td>\r\n                        <td class=\"right\">{{ $ctrl.calculatePeriodDays(calc,'leavesDays') | sxyCount : 'day' }}</td>\r\n                      </tr>\r\n                      <tr>\r\n                        <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.absencesDays\"></td>\r\n                        <td class=\"right\">{{ $ctrl.calculatePeriodDays(calc,'absencesDays') | sxyCount : 'day' }}</td>\r\n                      </tr>\r\n                      <tr>\r\n                        <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.paidAbsencesDays\"></td>\r\n                        <td class=\"right\">{{ $ctrl.calculatePeriodDays(calc,'paidAbsencesDays') | sxyCount : 'day' }}</td>\r\n                      </tr>\r\n                      <tr ng-if=\"$ctrl.showAccruals(calc)\">\r\n                        <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.accruedDays\"></td>\r\n                        <td class=\"right\">{{ $ctrl.calculatePeriodDays(calc,'accruedDays') | sxyCount : 'day' }}</td>\r\n                      </tr>\r\n                    </tbody>\r\n                  </table>\r\n                </div>\r\n              </div>\r\n              <div ng-if=\"!$ctrl.isReadOnly\">\r\n                <span ng-controller=\"EmploymentCrudController as $employment\">\r\n                  <salaxy-workflow-badge ng-if=\"$ctrl.employments[calc.worker.employmentId]\" mode=\"horizontal\" model=\"$ctrl.employments[calc.worker.employmentId]\" api-ctrl=\"$employment\" wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n                </span>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"!$ctrl.getValidation(calc).isValid\" class=\"text-danger\">\r\n            <ul class=\"small\">\r\n              <li ng-if=\"!$ctrl.getValidation(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.validation.noValidationFound\"></li>\r\n              <li ng-repeat=\"error in $ctrl.getValidation(calc).errors\">\r\n                <strong>{{ 'ApiValidationErrorType.' + error.type | sxyEnum }}:</strong>\r\n                <span sxy-text=\"{{'SALAXY.VALIDATION.' + error.code + '.label'}}\"></span>\r\n              </li>\r\n            </ul>\r\n            <button ng-if=\"$ctrl.getValidation(calc)\" ng-controller=\"ValidationSummaryController as $validation\" class=\"btn btn-xs btn-danger pull-right\" ng-click=\"$validation.apiValidation=$ctrl.getValidation(calc);$validation.showDetails()\" sxy-text=\"SALAXY.UI_Terms.readMore\"\r\n              ps=\"...\"></button>\r\n          </div>\r\n          <div class=\"row worker-calculations-row\">\r\n            <div class=\"col-xs-12  table-responsive\">\r\n              <salaxy-calc-rows-2019-editor parent=\"calc\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calcRowEditor.title' | sxyTranslate}}\" mode=\"{{$ctrl.isReadOnly ? 'read-only' : 'read-edit'}}\" show-edit-buttons=\"true\" on-commit=\"$ctrl.commitCalc(calc)\" on-reset=\"$ctrl.resetCalc(calc)\"\r\n                on-start-edit=\"$ctrl.getUi(calc).isInEdit = true\" is-in-edit=\"$ctrl.getUi(calc).isInEdit\" show-gross-totals=\"true\">\r\n              </salaxy-calc-rows-2019-editor>\r\n\r\n            </div>\r\n            <div class=\"col-xs-12 payroll-calculation-footer\">\r\n              <div class=\"btn-group btn-group-sm dropup\" uib-dropdown ng-if=\"!$ctrl.isReadOnly\">\r\n                <button type=\"button\" class=\"btn btn-secondary dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\">\r\n                  <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.edit\"></span> <span class=\"caret\"></span>\r\n                </button>\r\n                <ul class=\"dropdown-menu dropdown-menu-left\" uib-dropdown-menu template-url=\"salaxy-components/calc/payroll/PayrollCalcs_edit_dropdown.html\"></ul>\r\n              </div>\r\n              <div ng-if=\"$ctrl.mode != 'service'\" class=\"btn-group btn-group-sm pull-right-xs dropup\" uib-dropdown>\r\n                <button id=\"reports\" type=\"button\" class=\"btn btn-transparent dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\">\r\n                  <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.viewReports\"></span> <span class=\"caret\"></span>\r\n                </button>\r\n                <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"reports\">\r\n                  <li role=\"menuitem\">\r\n                    <a href=\"\" ng-click=\"$ctrl.showReport('employerReport', calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.employerReport\"></a>\r\n                  </li>\r\n                  <li role=\"menuitem\">\r\n                    <a href=\"\" ng-click=\"$ctrl.showReport('paymentReport', calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.paymentReport\"></a>\r\n                  </li>\r\n                  <li role=\"menuitem\">\r\n                    <a href=\"\" ng-click=\"$ctrl.showReport('salarySlip', calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.salarySlip\"></a>\r\n                  </li>\r\n                </ul>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.hasCalculations\">\r\n      <div class=\"payroll-totals col-padding\">\r\n        <div class=\"totals-container \">\r\n          <span class=\"total-label\"><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.payrollTotals.finalCost\"></span><br>\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.payrollTotals.grossSalary\"></span><br>\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.payrollTotals.totalPayment\"></span>\r\n          </span>\r\n          <span class=\"amount\">{{ $ctrl.calcsResult.employerCalc.finalCost | currency }}<br>\r\n            {{ $ctrl.info.totalGrossSalary | currency}}<br>\r\n            {{ $ctrl.info.totalPayment | currency}}</span>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"dropup toolbar-bottom\" ng-if=\"$ctrl.hasCalculations\">\r\n      <ng-include src=\"'salaxy-components/calc/payroll/PayrollCalcs_toolbar.html'\"></ng-include>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollCalcs_edit_dropdown.html\",`<ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\">\r\n  <li class=\"dropdown-header\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.editCalculation\"></li>\r\n  <li role=\"menuitem\" ng-class=\"{ 'disabled': $ctrl.getUi(calc).isInEdit }\">\r\n    <a href=\"\" ng-click=\"$ctrl.setRowsEditable(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.editRows\"></a>\r\n  </li>\r\n  <li ng-if=\"$ctrl.mode != 'service'\" role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.showEditCalcDialog(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.openCalculator\"></a>\r\n  </li>\r\n  <li ng-if=\"$ctrl.mode != 'service'\" role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.showEditCalcDialog(calc, 'ir')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.openIrRows\"></a>\r\n  </li>\r\n  <li role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.commitCalc(calc, false, true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.save\"></a>\r\n  </li>\r\n  <li role=\"menuitem\" ng-class=\"{ 'disabled': !$ctrl.hasCalcChanges(calc) && !$ctrl.getUi(calc).isInEdit }\">\r\n    <a href=\"\" ng-click=\"$ctrl.resetCalc(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.cancel\"></a>\r\n  </li>\r\n  <li role=\"separator\" class=\"divider\"></li>\r\n  <li class=\"dropdown-header\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.rowsEmployment\"></li>\r\n  <li role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.importEmploymentData(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.import\"></a>\r\n  </li>\r\n  <li role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.exportEmploymentData(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.export\"></a>\r\n  </li>\r\n  <li role=\"separator\" class=\"divider\"></li>\r\n  <li role=\"menuitem\">\r\n    <a href=\"\" ng-click=\"$ctrl.deleteCalc(calc)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.delete\"></a>\r\n  </li>\r\n  <li role=\"menuitem\" ng-if=\"$ctrl.mode != 'service'\">\r\n    <a href=\"\" ng-click=\"$ctrl.deleteCalc(calc, true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.unlink\"></a>\r\n  </li>\r\n</ul>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollCalcs_toolbar.html\",`<div class=\"btn-toolbar\">\r\n  \r\n\r\n  <div class=\"btn-group dropdown\" uib-dropdown ng-if=\"!$ctrl.isReadOnly && $ctrl.mode != 'service'\">\r\n    <button type=\"button\" class=\"btn btn-sm btn-labeled-left btn-primary dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\"><i\r\n        class=\"fa fa-plus\"></i>\r\n      <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCalculation\"></span> <span class=\"caret\"></span></button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"addcalculation\">\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.createNewCalc()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addWorker\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addExistingCalc('draft')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addDraft\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addExistingCalc('paid')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCopy\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.mergePayroll(true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addPayroll\"></a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n  <input type=\"text\" class=\"form-control input-sm payroll-search-input\"  id=\"searchText\" name=\"searchText\" placeholder=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.searchByName' | sxyTranslate}}\" ng-model=\"$ctrl.searchByName\" />\r\n \r\n  <button ng-if=\"!$ctrl.isReadOnly && $ctrl.mode == 'service'\" type=\"button\" class=\"btn btn-sm btn-labeled-right btn-primary\" ng-click=\"$ctrl.createNewCalc()\">\r\n    <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCalculation\"></span><i class=\"fa fa-plus\"></i>\r\n  </button>\r\n  <div class=\"btn-group btn-group-sm toggle-all-buttons pull-right-xs\">\r\n    <button ng-if=\"!$ctrl.isReadOnly && !('disableHolidays' | sxyIsInRole)\" class=\"btn btn-secondary  toggle-all text-right\" ng-click=\"$ctrl.recalculateWorktimes()\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.saveWorktime\"></span> <i class=\"fa fa-refresh\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.saveWorktime' | sxyTranslate}}\"></i>\r\n    </button>\r\n    <button class=\"btn btn-secondary toggle-all text-right\" ng-click=\"$ctrl.setUiForAll('isCollapsed', false)\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.open\"></span> <i class=\"fa fa-chevron-down\"\r\n        title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.open' | sxyTranslate}}\"></i>\r\n    </button>\r\n    <button class=\"btn btn-secondary  toggle-all text-right\" ng-if=\"!$ctrl.isReadOnly\" ng-click=\"$ctrl.setRowsEditable('all')\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.edit\"></span> <i class=\"fa fa-pencil\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.edit' | sxyTranslate}}\"></i>\r\n    </button>\r\n    <button class=\"btn btn-secondary  toggle-all text-right\" ng-click=\"$ctrl.commitAllCalcs()\" ng-if=\"$ctrl.changedCalcCount && !$ctrl.isReadOnly\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.save\"></span> ({{ $ctrl.changedCalcCountCache }}) <i class=\"fa fa-save text-success\"\r\n        title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.save' | sxyTranslate}}\"></i>\r\n    </button>\r\n    <button class=\"btn btn-secondary toggle-all text-right\" ng-click=\"$ctrl.resetAllCalcs()\" ng-if=\"$ctrl.changedCalcCountCache && !$ctrl.isReadOnly\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.cancel\"></span> ({{ $ctrl.changedCalcCountCache }}) <i\r\n        class=\"fa fa-times text-danger\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.cancel' | sxyTranslate}}\"></i>\r\n    </button>\r\n    <button class=\"btn btn-secondary  toggle-all text-right\" ng-click=\"$ctrl.setUiForAll('isCollapsed', true);$ctrl.setUiForAll('isInEdit', false)\" ng-if=\"!$ctrl.changedCalcCountCache\">\r\n      <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.close\"></span> <i class=\"fa fa-chevron-up\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.close' | sxyTranslate}}\"></i>\r\n    </button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollEdit.html\",`<div class=\"salaxy-component salaxy-payroll\" ng-controller=\"NaviController as $naviCtrl\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div sxy-if-role=\"auth\">\r\n    <div class=\"dropdown\">\r\n      <ng-include ng-if=\"$ctrl.isNew()\" src=\"'salaxy-components/calc/payroll/PayrollNew.html'\"></ng-include>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.isNew() && $ctrl.current\">\r\n      <ng-include src=\"'salaxy-components/calc/payroll/PayrollEdit_toolbar.html'\"></ng-include>\r\n      <div class=\"row payroll-info-row\">\r\n        <div class=\"col-xs-3 col-sm-2 col-xxs-12\">\r\n\r\n          <salaxy-avatar-placeholder class=\"payroll-avatar\">\r\n            <i class=\"salaxy-avatar fa fa-square text-muted\" ng-class=\"{'draft-invalid' : $ctrl.current.info.status == 'draft' && !$ctrl.current.info.isReadyForPayment, 'text-success' : $ctrl.current.info.status == 'paymentSucceeded', 'text-warning' : ($ctrl.current.info.status == 'paymentStarted' || $ctrl.current.info.status == 'waitingApproval') , 'text-danger' : $ctrl.current.info.status == 'paymentCancelled'}\">\r\n              <span>\r\n                <strong>{{ $ctrl.calcs.length }}</strong>\r\n                <small>{{ $ctrl.current.info.salaryDate | date : \"d.M.\" }}</small>\r\n              </span>\r\n            </i>\r\n          </salaxy-avatar-placeholder>\r\n        </div>\r\n        <div class=\"col-xs-9 col-sm-10 col-xxs-12 payroll-info-col\">\r\n          <h3 class=\"payroll-title\">{{ $ctrl.current.input.title }}</h3>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-12 col-sm-6\">\r\n              <div>\r\n                <span>{{ 'PayrollStatus.' + $ctrl.current.info.status | sxyEnum }}</span>\r\n                <span ng-if=\"$ctrl.current.info.status == 'draft'\" ng-class=\"$ctrl.current.info.isReadyForPayment ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.current.info.isReadyForPayment ? (('SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.readyForPayment' | sxyTranslate)) :\r\n                  (('SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.notReadyForPayment' | sxyTranslate)) }}\r\n                </span>\r\n              </div>\r\n              <div>\r\n                <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryPeriod\" ps=\":\"></span> {{ $ctrl.current.input.period | sxyDateRange }} ({{$ctrl.current.input.period.daysCount}} <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryPeriodDaysCount\"></span>)\r\n              </div>\r\n              <div>\r\n                <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDate\" ps=\":\"></span> \r\n                {{ $ctrl.current.info.salaryDate | date }}\r\n                <span class=\"badge bg-info\" ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' && !$ctrl.current.input.salaryDate && $ctrl.current.info.salaryDate\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateEstimate' | sxyTranslate}}</span>\r\n                <span ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' &&  $ctrl.current.info.salaryDate && $ctrl.current.input.salaryDate && $ctrl.current.input.salaryDate != $ctrl.current.info.salaryDate\"><s>{{ $ctrl.current.input.salaryDate | date }}</s> <span class=\"badge bg-warning\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateNote' | sxyTranslate}}</span></span>    \r\n              </div>\r\n              <div ng-if=\"$ctrl.current.input.wageBasis != 'undefined'\">\r\n                <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.wageBasis\" ps=\":\"></span> {{ 'WageBasis.' + $ctrl.current.input.wageBasis | sxyEnum }}\r\n              </div>\r\n              <div>\r\n                <span ng-if=\"$ctrl.current.input.template\" sxy-html=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.template.html\" params=\"{template: ($ctrl.current.input.template)}\"></span>\r\n              </div>\r\n              <div>\r\n                <small>ID: <code>{{ $ctrl.currentId }}</code></small>\r\n              </div>\r\n            </div>\r\n            <div class=\"col-xs-12 col-sm-6\">\r\n              <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.calcCount\" ps=\":\"></span> {{$ctrl.calcs.length}} </span><br />\r\n              <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.finalCost\" ps=\":\"></span> {{ $ctrl.calcsResult.employerCalc.finalCost | currency }}\r\n              </span><br />\r\n              <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.grossSalary\" ps=\":\"></span> {{ $ctrl.info.totalGrossSalary | currency}}</span><br>\r\n              <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.totalPayment\" ps=\":\"></span> {{ $ctrl.info.totalPayment | currency}}</span>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <uib-tabset active=\"$ctrl.activeTab\">\r\n        <uib-tab index=\"'properties'\" heading=\"{{'SALAXY.NG1.PayrollComponent.payrollEdit.tabs.editProperties' | sxyTranslate}}\">\r\n          <div ng-if=\"$ctrl.activeTab == 'properties'\" class=\"row payroll-edit-properties-container\">\r\n            <form class=\"form-horizontal\" ng-disabled=\"$ctrl.isDisabled\" ng-readonly=\"$ctrl.isReadOnly\">\r\n              <div class=\"col-xs-12 payroll-edit-properties-col\">\r\n                <salaxy-input name=\"title\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.title\" ng-model=\"$ctrl.current.input.title\"></salaxy-input>\r\n                <div class=\"form-group\" ng-if=\"$ctrl.current.info.status == 'paymentSucceeded'\">\r\n                  <label for=\"status\" class=\"col-sm-4 text-left\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.status\"></label>\r\n                  <div class=\"col-sm-8\">{{ 'PayrollStatus.' + $ctrl.current.info.status | sxyEnum | sxyTranslate }}</div>\r\n                </div>\r\n                <salaxy-input-enum ng-if=\"$ctrl.current.info.status != 'paymentSucceeded'\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.wageBasis\" name=\"wageBasis\" ng-model=\"$ctrl.current.input.wageBasis\" enum=\"WageBasis\" required placeholder=\"SALAXY.UI_Terms.selectAlt\"></salaxy-input-enum>\r\n                <div  ng-if=\"(!$ctrl.isReadOnly || $ctrl.showAction('pay')) && ('test,setSalaryDateKind' | sxyIsInRole)\"  ng-switch=\"$ctrl.current.input.paymentChannel\">\r\n                  <div ng-switch-when=\"palkkausManual|palkkausInvoices|palkkausCfaTest|kitsas|briox|askelma|passeliMerit\" ng-switch-when-separator=\"|\">\r\n                    <salaxy-form-group name=\"salaryDateKind\" label=\"SALAXY.MODEL.PayrollInput.salaryDateKind.title\">       \r\n                      <salaxy-salary-date-kind-button button-class=\"btn-block\" model=\"$ctrl.current\" on-salary-date-kind-change=\"$ctrl.save()\"></salaxy-salary-date-kind-button>\r\n                    </salaxy-form-group>\r\n                  </div>\r\n                </div>\r\n                <salaxy-form-group ng-if=\"($ctrl.isReadOnly && !$ctrl.showAction('pay')) && $ctrl.current.input.salaryDateKind == 'inPast'\" name=\"salaryDateKind\" class=\"salaxy-component salaxy-read-only\" label=\"SALAXY.MODEL.CalcWorkflow.salaryDateKind.title\">\r\n                  <div class=\"salaxy-read-only-value\">{{\"SALAXY.ENUM.SalaryDateKind.\" + ($ctrl.current.input.salaryDateKind) + \".label\" | sxyTranslate  }}</div>\r\n                </salaxy-form-group>\r\n                <salaxy-datepicker-popup read-only=\"false\" ng-if=\"!$ctrl.isReadOnly || $ctrl.showAction('pay')\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryDate\" name=\"salaryDate\" ng-model=\"$ctrl.current.input.salaryDate\" date-disabled=\"disable-function\" disable-function=\"$ctrl.isDisabledSalaryDate\"></salaxy-datepicker-popup>       \r\n                <div class=\"form-group\" ng-if=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">\r\n                  <div class=\"col-sm-4\"><strong sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryDate\" ps=\":\"></strong> </div>\r\n                  <div class=\"col-sm-8\">\r\n                    {{ $ctrl.current.info.salaryDate | date }}\r\n                    <span class=\"badge bg-info\" ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' && !$ctrl.current.input.salaryDate && $ctrl.current.info.salaryDate\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateEstimate' | sxyTranslate}}</span>\r\n                    <span ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' &&  $ctrl.current.info.salaryDate && $ctrl.current.input.salaryDate && $ctrl.current.input.salaryDate != $ctrl.current.info.salaryDate\"><s>{{ $ctrl.current.input.salaryDate | date }}</s> <span class=\"badge bg-warning\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateNote' | sxyTranslate}}</span></span>    \r\n                  </div>\r\n                </div>\r\n                <div class=\"form-group\">\r\n                  <div class=\"col-sm-4\"><strong sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryPeriod\" ps=\":\"></strong> </div>\r\n                  <div class=\"col-sm-8\">\r\n                    {{ $ctrl.current.input.period | sxyDateRange }} ({{$ctrl.current.input.period.daysCount}} <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryPeriodDaysCount\"></span>)\r\n                    <button class=\"btn btn-transparent btn-xs\" ng-click=\"$ctrl.showDateRange()\" ng-if=\"!$ctrl.isReadOnly || $ctrl.showAction('pay')\"><i class=\"fa fa-pencil \"></i></button>\r\n                  </div>\r\n                </div>\r\n                <salaxy-form-group name=\"paymentChannel\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.paymentChannel\" ng-show=\"$ctrl.$payButton.showPaymentChannelSelection()\">\r\n                  <salaxy-pay-button ng-if=\"!$ctrl.isReadOnly || $ctrl.showAction('pay')\" model=\"$ctrl.current\" mode=\"channel-select\" ng-ref=\"$ctrl.$payButton\" disabled=\"!$ctrl.$payButton.isChannelDefined\" on-payment-channel-change=\"$ctrl.save()\" button-class=\"btn-block\"></salaxy-pay-button>\r\n                  <div ng-if=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">{{ \"PaymentChannel.\" + $ctrl.current.input.paymentChannel | sxyEnum }}</div>\r\n                </salaxy-form-group>\r\n                <salaxy-form-group name=\"paymentChannelReadonly\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.paymentChannel\" ng-show=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">\r\n                  <div>{{ \"PaymentChannel.\" + $ctrl.current.input.paymentChannel | sxyEnum }}</div>\r\n                </salaxy-form-group>\r\n              </div>\r\n            </form>\r\n          </div>\r\n        </uib-tab>\r\n        <uib-tab index=\"'calculations'\" heading=\"{{'SALAXY.NG1.PayrollComponent.payrollEdit.tabs.calculations' | sxyTranslate}}\">\r\n          <ng-include ng-if=\"$ctrl.activeTab == 'calculations'\" src=\"'salaxy-components/calc/payroll/PayrollCalcs.html'\"></ng-include>\r\n        </uib-tab>\r\n        <uib-tab index=\"'reports'\" heading=\"{{'SALAXY.NG1.PayrollComponent.payrollEdit.tabs.reports' | sxyTranslate}}\" disable=\"!$ctrl.hasCalculations\">\r\n          <salaxy-calc-reports calcs=\"$ctrl.calcs\" ng-if=\"$ctrl.activeTab == 'reports' && $ctrl.hasCalculations\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n        </uib-tab>\r\n        <uib-tab index=\"'additionalInformation'\" heading=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.additionalInformation' | sxyTranslate}}\" disable=\"!$ctrl.hasCalculations\">\r\n          <div class=\"dropdown toolbar-top\" ng-if=\"$ctrl.activeTab == 'additionalInformation' && $ctrl.hasCalculations\">\r\n            <ng-include src=\"'salaxy-components/calc/payroll/PayrollCalcs_toolbar.html'\"></ng-include>\r\n            <div ng-repeat=\"calc in $ctrl.calcs\">\r\n              <div class=\"payroll-single-calculation col-padding\" ng-class=\"{'error-container': !$ctrl.getValidation(calc).isValid }\">\r\n                <div class=\"pull-right icon-container btn-group\">\r\n                  <button class=\"btn btn-transparent btn-xs toggle-details\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\"><i class=\"fa\"\r\n                      ng-class=\"{'fa-chevron-up' : !$ctrl.getUi(calc).isCollapsed,  'fa-chevron-down' : $ctrl.getUi(calc).isCollapsed}\"\r\n                      title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.toggle' | sxyTranslate}}\"></i></button>\r\n                </div>\r\n                <div class=\"payroll-worker-summary clickable\" ng-if=\"$ctrl.getUi(calc).isCollapsed\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\">\r\n                  <div class=\"avatar-container\">\r\n                    <salaxy-avatar avatar=\"calc.worker.avatar\"></salaxy-avatar>\r\n                    <span class=\"worker-name\">{{calc.worker.avatar.displayName}}</span>\r\n                    <span class=\"calculation-summary\">{{calc.result.totals.total | currency }}</span>\r\n                  </div>\r\n                </div>\r\n                <div class=\"payroll-worker-details\" ng-if=\"!$ctrl.getUi(calc).isCollapsed\">\r\n                  <div class=\"row payroll-worker-info\">\r\n                    <div class=\"col-xs-2 col-sm-2 col-xxs-9\">\r\n                      <div class=\"avatar-container\">\r\n                        <salaxy-avatar avatar=\"calc.worker.avatar\"></salaxy-avatar>\r\n                      </div>\r\n                    </div>\r\n                    <div class=\"col-xs-9 col-xxs-10\">\r\n                      <h3 class=\"worker-name clickable\" ng-click=\"$ctrl.getUi(calc).isCollapsed = !$ctrl.getUi(calc).isCollapsed\">{{calc.worker.avatar.displayName}}</h3>\r\n                      <div class=\"row\">\r\n                        <div class=\"col-xs-12 col-sm-5 worker-info-col\">\r\n                          {{calc.worker.paymentData.email}}<br> {{calc.worker.paymentData.telephone}}\r\n                        </div>\r\n                        <div class=\"col-xs-12 col-sm-7 worker-info-col\">\r\n                          <!-- additional info -->\r\n                        </div>\r\n                      </div>\r\n                    </div>\r\n                  </div>\r\n                  <div class=\"row worker-calculations-row\">\r\n                    <div class=\"col-sm-6\">\r\n                      <salaxy-calc-cost-accounting salaxy-if-role=\"company\" calc=\"calc\" read-only=\"$ctrl.isReadOnly\"></salaxy-calc-cost-accounting>\r\n                    </div>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </uib-tab>\r\n        <uib-tab index=\"'msg'\" heading=\"Viestit / hyväksyntä\" ng-if=\"'partnerMessaging' | sxyIsInRole\">\r\n          <div ng-if=\"!$ctrl.current.info.messageThreadId\" ng-controller=\"MessageThreadCrudController as $msg\" ng-init=\"$msg.model='new'\" class=\"form-horizontal\" style=\"max-width: 600px;\">\r\n            <fieldset sxy-if-role=\"!pro\">\r\n              <p ng-if=\"!$ctrl.current.info.messageThreadId\">Tähän palkkalistaan ei liity viestiketjua / työnkulkua.</p>\r\n              <!--\r\n              <legend>Lähetä tilitoimistolle</legend>\r\n              <p>Luo tästä uusi viestiketju, jolla voit lähettää palkkalistan tilitoimiston käsittelyyn.</p>\r\n              <salaxy-input-enum name=\"action\" label=\"Pyydetään toimintaa\" type=\"radio\" ng-model=\"$msg.current.input.todoAction\" options=\"$ctrl.messageActions\"\r\n                ng-change=\"$msg.current.title = $ctrl.getTitle($msg.current.input.todoAction)\"></salaxy-input-enum>\r\n              <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" disabled=\"!$msg.current.input.todoAction\" ng-model=\"$msg.current.title\"></salaxy-input>\r\n              <salaxy-form-group name=\"msgSubmit\" label-type=\"empty-label\">\r\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.sendPayroll($msg)\">Lähetä</button>\r\n              </salaxy-form-group>\r\n              -->\r\n            </fieldset>\r\n            <fieldset sxy-if-role=\"pro\">\r\n              <legend>Lähetä yritykselle</legend>\r\n              <p>Luo tästä uusi viestiketju, jolla voit lähettää palkkalistan yritykselle hyväksyttäväksi / maksettavaksi.</p>\r\n              <salaxy-input-enum name=\"action\" label=\"Pyydetään toimintaa\" type=\"radio\" ng-model=\"$msg.current.input.todoAction\" options=\"$ctrl.messageActions\" ng-change=\"$msg.current.title = $ctrl.getTitle($msg.current.input.todoAction)\"></salaxy-input-enum>\r\n              <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" disabled=\"!$msg.current.input.todoAction\" ng-model=\"$msg.current.title\"></salaxy-input>\r\n              <salaxy-form-group name=\"msgSubmit\" label-type=\"empty-label\">\r\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.sendPayroll($msg)\">Lähetä</button>\r\n              </salaxy-form-group>\r\n            </fieldset>\r\n          </div>\r\n          <div ng-if=\"$ctrl.current.info.messageThreadId\">\r\n            <button type=\"button\" class=\"btn btn-danger pull-right\" ng-click=\"$ctrl.deleteMessage($ctrl.$msg)\"><i class=\"fa fa-trash\" aria-hidden=\"true\"></i></button>\r\n            <salaxy-message-thread model=\"$ctrl.current.info.messageThreadId\" ng-ref=\"$ctrl.$msg\" role=\"{{('pro' | sxyIsInRole) ? 'otherParty' : 'owner' }}\" other-party=\"'partner'\" mark-as-read=\"5\"></salaxy-message-thread>\r\n          </div>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n      <div class=\"dropup\">\r\n        <ng-include src=\"'salaxy-components/calc/payroll/PayrollEdit_toolbar.html'\"></ng-include>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollEdit_toolbar.html\",`<div>\r\n  <div ng-if=\"$ctrl.isReadOnly\" class=\"btn-toolbar\">\r\n    <button ng-if=\"$ctrl.showAction('pay')\" type=\"button\" class=\"btn\" ng-class=\"{ 'btn-primary': $ctrl.hasChanges, 'btn-default': !$ctrl.hasChanges }\" ng-disabled=\"!$ctrl.hasChanges\" ng-click=\"$ctrl.save()\">\r\n      {{ $ctrl.hasChanges ? ('SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.save' | sxyTranslate) : ('SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.saved' | sxyTranslate) }}\r\n    </button>\r\n    <button class=\"btn btn-secondary\" ng-if=\"$ctrl.showAction('copy')\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" ng-style=\"{ visibility: $ctrl.isDisabled ? 'hidden' : 'visible' }\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.copyAsNew\"></button>\r\n    <div class=\"pull-right\" >\r\n      <salaxy-pay-button ng-if=\"$ctrl.showAction('pay')\"\r\n        model=\"$ctrl.current\" mode=\"pay-button\" button-class=\"pull-right-xs\" label=\"SALAXY.NG1.PayrollComponent.payrollPayButton\" ng-ref=\"$payButton\" disabled=\"!$ctrl.current.info.isReadyForPayment || !$ctrl.calcs.length || !$payButton.isChannelDefined\"\r\n        on-payment-channel-change=\"$ctrl.save()\"></salaxy-pay-button>\r\n        <button ng-if=\"$ctrl.showAction('cancel') && ($ctrl.current.info.status == 'paymentStarted' && ($ctrl.current.input.paymentChannel == 'palkkausManual' || $ctrl.current.input.paymentChannel == 'palkkausInvoices' || $ctrl.current.input.paymentChannel == 'kitsas' || $ctrl.current.input.paymentChannel == 'palkkausPersonal' || $ctrl.current.input.paymentChannel == 'palkkausCfaPaytrail' || $ctrl.current.input.paymentChannel == 'palkkausEcfaPaytrail' || $ctrl.current.input.paymentChannel == 'palkkausCfaReference'|| $ctrl.current.input.paymentChannel == 'palkkausEcfaReference' || $ctrl.current.input.paymentChannel == 'palkkausCfaFinvoice' || $ctrl.current.input.paymentChannel == 'palkkausEcfaFinvoice' ||  $ctrl.current.input.paymentChannel == 'palkkausCfaTest'))\" class=\"btn btn-secondary  btn-labeled-right\" ng-click=\"$ctrl.cancel()\"><span sxy-text=\"SALAXY.NG1.CalcResultsComponent.cancelPaymentOrChangeChannelBtn\"></span><i class=\"fa fa-times-circle\"></i></button>\r\n        <button ng-if=\"$ctrl.current.info.status != 'waitingApproval' && $ctrl.current.info.status != 'draft'\" class=\"btn btn-secondary  btn-labeled-right\" ng-click=\"$ctrl.showPaymentDialog()\"><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.showPaymentInfo\"></span><i class=\"fa fa-info\"></i></button>\r\n    </div>\r\n    <button type=\"button\" ng-if=\"('partnerMessaging' | sxyIsInRole) && (!('pro' | sxyIsInRole) && $ctrl.current.info.messageThreadId )\"  class=\"btn btn-default pull-right\" ng-click=\"$ctrl.activeTab = 'msg'\">Kommentoi</button>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isReadOnly\" class=\"btn-toolbar calc-toolbar\">\r\n    <button type=\"button\" class=\"btn\" ng-class=\"{ 'btn-primary': $ctrl.hasChanges, 'btn-default': !$ctrl.hasChanges }\" ng-disabled=\"!$ctrl.hasChanges\" ng-click=\"$ctrl.save()\">\r\n      {{ $ctrl.hasChanges ? ('SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.save' | sxyTranslate) : ('SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.saved' | sxyTranslate) }}\r\n    </button>\r\n    <div class=\"btn-group\" uib-dropdown=\"\" ng-disabled=\"$ctrl.isDisabled\">\r\n      <button type=\"button\" class=\"btn btn-secondary dropdown-toggle\" uib-dropdown-toggle=\" \" aria-haspopup=\"true\" aria-expanded=\"false\">\r\n        <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.options\"></span>\r\n        <span class=\"caret \"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu=\"\" role=\"menu\" aria-labelledby=\"actions\">\r\n        <li role=\"menuitem\">\r\n          <a ng-click=\"$ctrl.importEmploymentDataAll()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.importEmploymentCalc\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a ng-click=\"$ctrl.exportEmploymentDataAll()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.exportEmploymentCalc\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.copyAsNew\"></a>\r\n        </li>\r\n        <li ng-class=\"{ disabled: !$ctrl.hasChanges }\" role=\"menuitem\">\r\n          <a ng-click=\"$ctrl.reset()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.cancel\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a class=\"text-danger\" ng-click=\"$ctrl.delete()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.delete\"></a>\r\n        </li>\r\n        <li role=\"menuitem\" ng-if=\"( $ctrl.current.owner == 'FI90PRYL0001975846') && ('pro, test' | sxyIsInRole)\">\r\n          <a ng-href=\"#/payroll/import/{{$ctrl.current.id}}\">Import (BETA)</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div sxy-if-role=\"pro\" class=\"btn-group\">\r\n      <div class=\"btn-group\" style=\"margin-left:5px;\" uib-dropdown>\r\n        <!-- HACK: Rewrite workflow buttons as components. Or make PRO calculator a component. -->\r\n        <button class=\"btn btn-default\" uib-dropdown-toggle type=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"font-weight: bold;\">\r\n          {{ \"PayrollStatus.\" + $ctrl.current.info.status | sxyEnum }} <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu>\r\n          <li ng-class=\"{ disabled: $ctrl.current.info.status=='draft' }\">\r\n            <a href=\"\" ng-click=\"$ctrl.current.info.status = 'draft';$ctrl.save()\">{{ \"PayrollStatus.draft\" | sxyEnum }}</a>\r\n          </li>\r\n          <li ng-class=\"{ disabled: $ctrl.current.info.status=='template' }\">\r\n            <a href=\"\" ng-click=\"$ctrl.current.info.status = 'template';$ctrl.save()\">{{ \"PayrollStatus.template\" | sxyEnum }}</a>\r\n          </li>\r\n          <li ng-class=\"{ disabled: $ctrl.current.info.status=='handled' }\">\r\n            <a href=\"\" ng-click=\"$ctrl.current.info.status = 'handled';$ctrl.save()\">{{ \"PayrollStatus.handled\" | sxyEnum }}</a>\r\n          </li>\r\n          <li ng-class=\"{ disabled: $ctrl.current.info.status=='waitingApproval' }\">\r\n            <a href=\"\" ng-click=\"$ctrl.current.info.status = 'waitingApproval';$ctrl.save()\">{{ \"PayrollStatus.waitingApproval\" | sxyEnum }}</a>\r\n          </li>\r\n        </ul>\r\n      </div>\r\n      <salaxy-workflow-buttons api-ctrl=\"$ctrl\"></salaxy-workflow-buttons>\r\n    </div>\r\n    <div class=\"btn-group pull-right\">\r\n      <salaxy-pay-button ng-if=\"$ctrl.current.info.status != 'template'\" model=\"$ctrl.current\" mode=\"pay-button\" button-class=\"pull-right-xs\" label=\"SALAXY.NG1.PayrollComponent.payrollPayButton\" ng-ref=\"$payButton\" disabled=\"!$ctrl.current.info.isReadyForPayment || !$ctrl.calcs.length || !$payButton.isChannelDefined\"\r\n        on-payment-channel-change=\"$ctrl.save()\"></salaxy-pay-button>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div>\r\n  <div ng-if=\"'company' | sxyIsInRole\" ng-controller=\"CompanyAccountController as $company\" style=\"padding: 8px\">\r\n    <salaxy-workflow-badge ng-if=\"$company.current\" model=\"$company.current\" mode=\"horizontal\" api-ctrl=\"$company\" wf-types=\"'EmployerMessageRecord'\" ></salaxy-workflow-badge>\r\n  </div>\r\n</div>\r\n<div class=\"row\" ng-if=\"$ctrl.showWorkflowMessage\" style=\"margin-top: 4px;margin-bottom: -50px\">\r\n  <div class=\"col-sm-offset-6 col-sm-6\">\r\n    <salaxy-textarea name=\"workflowMessage\" ng-model=\"$ctrl.workflowMessage\" placeholder=\"{{'SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.workFlowMessage'}}\" rows=\"2\" label-type=\"plain\"></salaxy-textarea>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollList.html\",`<div class=\"salaxy-component salaxy-payroll-list\">\r\n\r\n  <div class=\"row\" ng-if=\"!$ctrl.hideButton\">\r\n    <div class=\"col-xs-12 action-button-container\" style=\"margin-bottom:15px;\">\r\n      <salaxy-action-button action=\"'newPayroll'\" button-class=\"btn-primary\" style=\"margin-bottom:30px;\"></salaxy-action-button>\r\n    </div>\r\n  </div>\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.latest' | sxyTranslate}}\" index=\"'default'\">\r\n      <salaxy-odata-table crud-controller=\"PayrollCrudController as $crud\" options=\"{ $filter: 'status ne \\\\'paymentSucceeded\\\\' and status ne \\\\'paymentStarted\\\\' and status ne \\\\'template\\\\' and status ne \\\\'handled\\\\' and status ne \\\\'paymentCanceled\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.repeated' | sxyTranslate}}\" index=\"'templates'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'templates'\" crud-controller=\"PayrollCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'template\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.paid' | sxyTranslate}}\" index=\"'paid'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'paid'\" crud-controller=\"PayrollCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' or status eq \\\\'paymentStarted\\\\' or status eq \\\\'handled\\\\' or status eq \\\\'paymentCanceled\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.paidSalaries' | sxyTranslate}}\" index=\"'paidCalcs'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'paidCalcs'\" url=\"/v03/api/calculations/category/readonly\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' and data/payrollId ne null' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.draftCalcs' | sxyTranslate}}\" index=\"'draftCalcs'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'draftCalcs'\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'payrollDraft\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollNew.html\",`<div>\r\n  <div class=\"h2\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.heading\"></div>\r\n  <p class=\"lead\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.intro\"></p>\r\n  <div class=\"form-horizontal\" ng-controller=\"NaviController as $naviCtrl\">\r\n    <form name=\"newPayrollForm\">\r\n      <salaxy-input name=\"title\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.title\" require=\"true\" ng-model=\"$ctrl.current.input.title\"></salaxy-input>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.wageBasis\" name=\"wageBasis\" ng-model=\"$ctrl.current.input.wageBasis\" enum=\"WageBasis\" required placeholder=\"SALAXY.UI_Terms.choose\"></salaxy-input-enum>\r\n      <div  ng-if=\"('test,setSalaryDateKind' | sxyIsInRole)\" ng-switch=\"$ctrl.current.input.paymentChannel\">\r\n        <div ng-switch-when=\"palkkausManual|palkkausInvoices|palkkausCfaTest|kitsas|briox|askelma|passeliMerit\" ng-switch-when-separator=\"|\">\r\n          <salaxy-form-group name=\"salaryDateKind\" label=\"SALAXY.MODEL.PayrollInput.salaryDateKind.title\">       \r\n            <salaxy-salary-date-kind-button button-class=\"btn-block\" model=\"$ctrl.current\" disabled=\"$ctrl.isReadOnly\"></salaxy-salary-date-kind-button>\r\n          </salaxy-form-group>\r\n        </div>\r\n      </div>\r\n      <salaxy-datepicker-popup label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryDate\" name=\"salaryDate\" ng-model=\"$ctrl.current.input.salaryDate\" date-disabled=\"disable-function\" disable-function=\"$ctrl.isDisabledSalaryDate\"></salaxy-datepicker-popup>\r\n      <salaxy-date-range label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryPeriod\" name=\"period\" ng-model=\"$ctrl.current.input.period\" mode=\"calc\"></salaxy-date-range>      \r\n      <salaxy-form-group name=\"paymentChannel\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.paymentChannel\" ng-show=\"$ctrl.$payButton.showPaymentChannelSelection()\">\r\n        <salaxy-pay-button model=\"$ctrl.current\" mode=\"channel-select\" ng-ref=\"$ctrl.$payButton\" disabled=\"!$ctrl.$payButton.isChannelDefined\" button-class=\"btn-block\"></salaxy-pay-button>\r\n      </salaxy-form-group>\r\n      <div ng-if=\"$ctrl.current.calcs.length\">\r\n        <salaxy-form-group label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.copyingCalcs\" name=\"calcCount\">\r\n          {{ $ctrl.current.calcs.length }} kpl\r\n        </salaxy-form-group>\r\n        <salaxy-input-boolean type=\"select\" placeholder=\"SALAXY.UI_Terms.choose\" name=\"noUpdateFromEmployment\" ng-model=\"$ctrl.current.input.noUpdateFromEmployment\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcs\" label-false=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcsFalse\"\r\n          label-true=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcsTrue\"></salaxy-input-boolean>\r\n      </div>\r\n      <salaxy-form-group label=\"\" name=\"submit\" class=\"no-colon\">\r\n        <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!newPayrollForm.$valid || $ctrl.current.input.wageBasis == 'undefined'\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.createPayrollButton\"></button>\r\n      </salaxy-form-group>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payroll/PayrollSelectList.html\",`<div class=\"salaxy-component salaxy-payroll-select-list\">\r\n  <salaxy-odata-table ng-if=\"$ctrl.category=='paid'\"  ng-if=\"$ctrl.mode == 'select'\" template-url=\"salaxy-components/odata/lists/Payrolls-select.html\"  options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' or status eq \\\\'paymentStarted\\\\'' }\"\r\n    selected-items=\"$ctrl.selectedItems\" on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\" crud-controller=\"PayrollCrudController as $crud\"></salaxy-odata-table>\r\n  <salaxy-odata-table ng-if=\"$ctrl.category=='draft'\"  ng-if=\"$ctrl.mode == 'select'\" template-url=\"salaxy-components/odata/lists/Payrolls-select.html\"  options=\"{ $filter: 'status eq \\\\'draft\\\\'' }\"\r\n    selected-items=\"$ctrl.selectedItems\" on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\" crud-controller=\"PayrollCrudController as $crud\"></salaxy-odata-table>\r\n  </div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails.html\",`<div class=\"salaxy-component salaxy-payroll-details\" ng-if=\"$ctrl.current\">\r\n  <ng-include ng-show=\"!$ctrl.isNew()\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_info.html'\"></ng-include>\r\n  <ng-include ng-show=\"!$ctrl.isNew()\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_toolbar.html'\"></ng-include>\r\n  <uib-tabset ng-show=\"!$ctrl.isNew()\" active=\"$ctrl.headerView\">\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.headerViews.calculations' | sxyTranslate }}\" index=\"'calculations'\">\r\n      <ng-include src=\"'salaxy-components/calc/payrollV4/PayrollDetails_calcs.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.headerViews.rows' | sxyTranslate }}\" index=\"'rows'\">\r\n      <ng-include  ng-if=\"$ctrl.calcs && $ctrl.headerView == 'rows'\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_calcs_paged.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.headerViews.reports' | sxyTranslate }}\" index=\"'reports'\">\r\n      <div ng-show=\"false\" ng-if=\"$ctrl.headerView != 'reports'\" ng-init=\"$ctrl.clearReports()\"></div>\r\n      <ng-include  ng-if=\"$ctrl.calcs && $ctrl.headerView == 'reports'\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_reports.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab  ng-if=\"'partnerMessaging' | sxyIsInRole\" heading=\"{{'SALAXY.NG1.PayrollComponent.headerViews.messages' | sxyTranslate}}\" index=\"'messages'\">\r\n      <ng-include  ng-if=\"$ctrl.headerView == 'messages'\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_messages.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.headerViews.ports' | sxyTranslate}}\" disable=\"!$ctrl.$import.isSupported\" index=\"'ports'\">\r\n      <ng-include src=\"'salaxy-components/calc/payrollV4/PayrollDetails_ports.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab  ng-if=\"'test' | sxyIsInRole\" heading=\"Debug\" index=\"'debug'\">\r\n      <ng-include  ng-if=\"$ctrl.headerView == 'debug'\" src=\"'salaxy-components/calc/payrollV4/PayrollDetails_debug.html'\"></ng-include>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n\r\n  <ng-include src=\"'salaxy-components/calc/payrollV4/PayrollDetails_calc.html'\"></ng-include>\r\n  <ng-include src=\"'salaxy-components/calc/payrollV4/PayrollDetails_header.html'\"></ng-include>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetailsList.html\",`<div class=\"salaxy-component salaxy-payroll-details-list\">\r\n\r\n  <div class=\"row\" ng-if=\"!$ctrl.hideButton\">\r\n    <div class=\"col-xs-12 action-button-container\" style=\"margin-bottom:15px;\">\r\n      <salaxy-action-button action=\"'newPayroll'\" button-class=\"btn-primary\" style=\"margin-bottom:30px;\"></salaxy-action-button>\r\n    </div>\r\n  </div>\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.latest' | sxyTranslate}}\" index=\"'default'\">\r\n      <salaxy-odata-table crud-controller=\"Payroll4CrudController as $crud\" options=\"{ $filter: 'status ne \\\\'paymentSucceeded\\\\' and status ne \\\\'paymentStarted\\\\' and status ne \\\\'template\\\\' and status ne \\\\'handled\\\\' and status ne \\\\'paymentCanceled\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.repeated' | sxyTranslate}}\" index=\"'templates'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'templates'\" crud-controller=\"Payroll4CrudController as $crud\" options=\"{ $filter: 'status eq \\\\'template\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.paid' | sxyTranslate}}\" index=\"'paid'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'paid'\" crud-controller=\"Payroll4CrudController as $crud\" options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' or status eq \\\\'paymentStarted\\\\' or status eq \\\\'handled\\\\' or status eq \\\\'paymentCanceled\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.paidSalaries' | sxyTranslate}}\" index=\"'paidCalcs'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'paidCalcs'\" url=\"/v03/api/calculations/category/readonly\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' and data/payrollId ne null' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1.PayrollComponent.payrollList.tabs.draftCalcs' | sxyTranslate}}\" index=\"'draftCalcs'\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.currentTab == 'draftCalcs'\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $filter: 'status eq \\\\'payrollDraft\\\\'' }\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-odata-table>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetailsSelectList.html\",`<div class=\"salaxy-component salaxy-payroll-details-select-list\">\r\n  <salaxy-odata-table ng-if=\"$ctrl.category=='paid'\"  ng-if=\"$ctrl.mode == 'select'\" template-url=\"salaxy-components/odata/lists/Payrolls-select.html\"  options=\"{ $filter: 'status eq \\\\'paymentSucceeded\\\\' or status eq \\\\'paymentStarted\\\\'' }\"\r\n    selected-items=\"$ctrl.selectedItems\" on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\" crud-controller=\"Payroll4CrudController as $crud\"></salaxy-odata-table>\r\n  <salaxy-odata-table ng-if=\"$ctrl.category=='draft'\"  ng-if=\"$ctrl.mode == 'select'\" template-url=\"salaxy-components/odata/lists/Payrolls-select.html\"  options=\"{ $filter: 'status eq \\\\'draft\\\\'' }\"\r\n    selected-items=\"$ctrl.selectedItems\" on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\" crud-controller=\"Payroll4CrudController as $crud\"></salaxy-odata-table>\r\n  </div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_calc.html\",`<div class=\"salaxy-navi-page-container salaxy-payroll-details-calc salaxy-payroll-details-dialog\" ng-style=\"{'max-width': '100%','width': $ctrl.userSettings.ng1Binder('payroll.calcDialogSize').val || '75%'}\" ng-class=\"{ 'offcanvas-show': $ctrl.shouldShowCanvas('calc',$ctrl.calcId) }\">\r\n  <div class=\"modal-header\">\r\n    <span  class=\"pull-right\">\r\n      <button type=\"button\" class=\"btn btn-transparent\"  ng-click=\"$ctrl.userSettings.ng1Binder('payroll.calcDialogSize').val = ($ctrl.userSettings.ng1Binder('payroll.calcDialogSize').val == '100%' ? '75%' : '100%')\"><i ng-class=\"$ctrl.userSettings.ng1Binder('payroll.calcDialogSize').val == '100%' ? 'fa fa-compress' : 'fa fa-expand'\"></i></button>\r\n      <button type=\"button\" class=\"btn btn-primary\" aria-label=\"Close\" ng-click=\"$ctrl.setCalc()\"><span class=\"fa fa-times\"></span></button>\r\n    </span>\r\n    <h3 class=\"modal-title\">{{ $ctrl.calc ? ( $ctrl.calc.worker.avatar.displayName + \", \" + ($ctrl.calc.result.totals.totalGrossSalary | currency) ) : ('SALAXY.UI_Terms.loading' | sxyTranslate) }}</h3>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <uib-tabset active=\"$ctrl.calcView\">\r\n      <uib-tab  heading=\"{{'SALAXY.NG1.PayrollComponent.calcViews.rows' | sxyTranslate}}\" index=\"'rows'\"></uib-tab>\r\n      <uib-tab  heading=\"{{'SALAXY.NG1.PayrollComponent.calcViews.calculator' | sxyTranslate}}\" index=\"'calculator'\"></uib-tab>\r\n      <uib-tab  heading=\"{{'SALAXY.NG1.PayrollComponent.calcViews.costAccounting' | sxyTranslate}}\" index=\"'costAccounting'\"></uib-tab>\r\n      <uib-tab  heading=\"{{'SALAXY.NG1.PayrollComponent.calcViews.employment' | sxyTranslate}}\" index=\"'employment'\"></uib-tab>\r\n      <uib-tab  heading=\"{{'SALAXY.NG1.PayrollComponent.calcViews.reports' | sxyTranslate}}\" index=\"'reports'\"></uib-tab>\r\n      <uib-tab  ng-if=\"'test' | sxyIsInRole\" heading=\"Debug\" index=\"'debug'\"></uib-tab>\r\n    </uib-tabset>\r\n    <div ng-switch=\"$ctrl.calcView\">\r\n      <div ng-switch-when=\"rows\">\r\n        <salaxy-calc-worker-info ng-if=\"$ctrl.calc\"  model=\"$ctrl.calc\"></salaxy-calc-worker-info>\r\n        <salaxy-calc-rows-2019-editor ng-if=\"$ctrl.calc\" parent=\"$ctrl.calc\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calcRowEditor.title' | sxyTranslate}}\"\r\n          mode=\"edit\" show-edit-buttons=\"false\" \r\n          show-gross-totals=\"true\"></salaxy-calc-rows-2019-editor>\r\n        <salaxy-spinner ng-if=\"!$ctrl.calc\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-switch-when=\"calculator\">\r\n        <salaxy-calc ng-if=\"$ctrl.calc\" model=\"$ctrl.calc\"></salaxy-calc>\r\n        <salaxy-spinner ng-if=\"!$ctrl.calc\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-switch-when=\"costAccounting\">\r\n        <div ng-class=\"$ctrl.userSettings.ng1Binder('payroll.calcDialogSize').val == '100%' ? 'container' : ''\">\r\n            <salaxy-calc-cost-accounting ng-if=\"$ctrl.calc\" calc=\"$ctrl.calc\" read-only=\"$ctrl.isReadOnly || $ctrl.calc.isReadOnly\"></salaxy-calc-cost-accounting>\r\n            <salaxy-spinner ng-if=\"!$ctrl.calc\"></salaxy-spinner>\r\n        </div>\r\n      </div>\r\n      <div ng-switch-when=\"employment\">\r\n        <salaxy-employment-details ng-if=\"$ctrl.calc\" ng-ref=\"$ctrl.$employment\" model=\"$ctrl.calc.worker.employmentId\" is-modal=\"true\"></salaxy-employment-details>\r\n        <salaxy-spinner ng-if=\"!$ctrl.calc\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-switch-when=\"reports\">\r\n        <salaxy-calc-reports ng-if=\"$ctrl.calc\" calcs=\"[$ctrl.calc]\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n        <salaxy-spinner ng-if=\"!$ctrl.calc\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-switch-when=\"debug\" class=\"row\">\r\n        <div class=\"col-sm-6\">\r\n          <salaxy-json-formatter ng-if=\"$ctrl.calc\" key=\"'CALC'\" json=\"$ctrl.calc\"></salaxy-json-formatter>\r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <salaxy-json-formatter ng-if=\"$ctrl.calcListItem\" key=\"'List item'\" json=\"$ctrl.calcListItem\"></salaxy-json-formatter>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.setCalc()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n \r\n    <div ng-if=\"$ctrl.calcView=='rows' || $ctrl.calcView=='calculator' || $ctrl.calcView=='costAccounting'\" class=\"btn-group dropup\" uib-dropdown=\"\">\r\n      <button type=\"button\" ng-disabled=\"$ctrl.loaders[$ctrl.calc.id]\" class=\"btn btn-secondary dropdown-toggle\" uib-dropdown-toggle=\" \" aria-haspopup=\"true\" aria-expanded=\"false\">\r\n        <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.options\"></span>\r\n        <span class=\"caret \"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu=\"\" role=\"menu\" aria-labelledby=\"actions\">\r\n        <li role=\"menuitem\" ng-if=\"!$ctrl.isReadOnly && !$ctrl.calc.isReadOnly\">\r\n          <a href=\"\" ng-click=\"$ctrl.deleteCalc()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.delete\"></a>\r\n        </li>\r\n        <li role=\"menuitem\" ng-if=\"!$ctrl.isReadOnly && !$ctrl.calc.isReadOnly && $ctrl.mode != 'service'\">\r\n          <a href=\"\" ng-click=\"$ctrl.deleteCalc(true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.unlink\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.copyCalc()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.copyAsNew\"></a>\r\n        </li>\r\n        <li role=\"menuitem\" ng-if=\"$ctrl.isReadOnly && !$ctrl.calc.isReadOnly && !$ctrl.isCfa\">\r\n          <a href=\"\" ng-click=\"$ctrl.payCalc()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.pay\"></a>\r\n        </li>\r\n        <li role=\"separator\"  class=\"divider\"></li>\r\n        <li class=\"dropdown-header\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.rowsEmployment\"></li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.exportEmploymentData()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.export\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToCalc(true)\"><span><i class=\"fa fa-step-backward\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.previous\"></span></button>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToCalc(false)\"><span sxy-text=\"SALAXY.UI_Terms.next\"></span> <span><i class=\"fa fa-step-forward\"></i></span></button>\r\n    <button ng-if=\"$ctrl.calcView=='rows' || $ctrl.calcView=='calculator' || $ctrl.calcView=='costAccounting'\"  type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.saveCalc($ctrl.calc)\" ng-disabled=\"$ctrl.calc.isReadOnly || $ctrl.loaders[$ctrl.calc.id]\"><span ng-if=\"$ctrl.loaders[$ctrl.calc.id]\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.save\"></span><span ng-if=\"$ctrl.hasCalcChange\"> <span class=\"badge\">1<span></span></button>\r\n\r\n    <button ng-if=\"$ctrl.calcView=='employment'\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.saveEmployment($ctrl.$employment.current, true)\" ng-disabled=\"$ctrl.calc.isReadOnly || $ctrl.loaders[$ctrl.calc.id + '-employment-true']\"><span ng-if=\"$ctrl.loaders[$ctrl.calc.id + '-employment-true']\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.workerEdit.updateWorkerInfoAndSalaryRows\"></span></button>\r\n    <button  ng-if=\"$ctrl.calcView=='employment'\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.saveEmployment($ctrl.$employment.current)\" ng-disabled=\"$ctrl.calc.isReadOnly || $ctrl.loaders[$ctrl.calc.id + '-employment-false']\"><span ng-if=\"$ctrl.loaders[$ctrl.calc.id + '-employment-false']\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.workerEdit.updateWorkerInfo\"></span><span ng-if=\"$ctrl.hasEmploymentChange\"> <span class=\"badge\">1<span></span></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_calcs.html\",`<div class=\"table-responsive\">\r\n  <table class=\"table table-striped\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"4\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.net\"></th>\r\n        <th class=\"\" sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.salaryPeriod\"></th>\r\n      </tr class=\"right\">\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.calcs\" class=\"clickable\" ng-class=\"{ 'active': $ctrl.calcId == row.id }\"  ng-click=\"$ctrl.toggleCalc(row.id)\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"td-name middle\">\r\n          <div>\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n          </div>\r\n          <div>{{ row.otherPartyInfo.officialId }}</div>\r\n        </td>\r\n        <td colspan=\"2\" class=\"middle\">\r\n          <span ng-if=\"$ctrl.getCalcValidity(row)\" class=\"error-summary text-danger\" sxy-text=\"{{'SALAXY.VALIDATION.' + $ctrl.getCalcValidity(row).errors[0].code + '.label'}}\"></span>\r\n          <span ng-if=\"$ctrl.getCalcValidity(row) && $ctrl.getCalcValidity(row).errors[0].code == 'Payroll.Calc.TaxCardType'\">\r\n            <button class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.showAddNewTaxcard($event, row)\">{{ 'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.addTaxcard' | sxyTranslate}} <i class=\"fa fa-plus\"></i></button>\r\n          </span>\r\n        </td>\r\n        <td class=\"right middle\">{{ row.grossSalary | currency }}</td>\r\n        <td class=\"right middle\">{{ row.data.workerPayment | currency }}</td>\r\n        <td class=\"middle\"><span ng-class=\"$ctrl.rowStatusWarning(row) ? 'badge bg-danger': ''\">{{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}<span></td>\r\n        <td class=\"right middle\">\r\n          <span>{{ { start: row.data.workStartDate, end: row.data.workEndDate, } | sxyDateRange }}</span>\r\n          <div ng-if=\"$ctrl.isDateDifferent(row)\">\r\n            <del class=\"small\">{{ $ctrl.current.input.period | sxyDateRange }}</del>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_calcs_paged.html\",`<div class=\"text-right\">\r\n  <span class=\"pull-left\" ng-if=\"$ctrl.page.total > 1\">{{$ctrl.page.calcRange}}/{{$ctrl.page.totalCalcCount}}</span>\r\n  <button type=\"button\" ng-if=\"!('disableHolidays' | sxyIsInRole)\" class=\"btn btn-secondary\" ng-click=\"$ctrl.saveWorktimes()\" ng-disabled=\"$ctrl.isReadOnly || !$ctrl.current.id  || $ctrl.current.input.calculations.length == 0 || $ctrl.loaders['worktime' + $ctrl.current.id]\"><span ng-if=\"$ctrl.loaders['worktime' + $ctrl.current.id]\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.saveWorktime\"></span></button>\r\n  <div class=\"btn-group\">\r\n   <button ng-if=\"$ctrl.page.total > 1\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToPage(true)\"><span><i class=\"fa fa-step-backward\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.previous\"></span></button>\r\n   <button ng-if=\"$ctrl.page.total > 1\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToPage(false)\"><span sxy-text=\"SALAXY.UI_Terms.next\"></span> <span><i class=\"fa fa-step-forward\"></i></span></button>\r\n  </div>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.savePageCalcs()\" ng-disabled=\"$ctrl.numOfChangedPageCalcs == 0 || $ctrl.loaders['pageCalcs' + $ctrl.page.current]\"><span ng-if=\"$ctrl.loaders['pageCalcs' + $ctrl.page.current]\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.save\"></span><span ng-if=\"$ctrl.numOfChangedPageCalcs > 0\"> <span class=\"badge\">{{$ctrl.numOfChangedPageCalcs}}<span></span></span></button>\r\n</div>\r\n<div class=\"table-responsive\">\r\n  <table class=\"table table-striped\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"4\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.net\"></th>\r\n        <th class=\"\" sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></th>\r\n        <th ng-if=\"!('disableHolidays' | sxyIsInRole)\" class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.worktime\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcListComponent.salaryPeriod\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"row in $ctrl.page.items\" class=\"clickable\" ng-class=\"{ 'active': $ctrl.calcId == row.id }\" ng-click=\"$ctrl.toggleCalc(row.id)\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"td-name middle\">\r\n          <div>\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n          </div>\r\n          <div>{{ row.otherPartyInfo.officialId }}</div>\r\n        </td>\r\n        <td colspan=\"2\" class=\"middle\">\r\n          <span ng-if=\"$ctrl.getCalcValidity(row)\" class=\"error-summary text-danger\" sxy-text=\"{{'SALAXY.VALIDATION.' + $ctrl.getCalcValidity(row).errors[0].code + '.label'}}\"></span>\r\n          <span ng-if=\"$ctrl.getCalcValidity(row) && $ctrl.getCalcValidity(row).errors[0].code == 'Payroll.Calc.TaxCardType'\">\r\n            <button class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.showAddNewTaxcard($event, row)\">{{ 'SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.workerInfo.addTaxcard' | sxyTranslate}} <i class=\"fa fa-plus\"></i></button>\r\n          </span>\r\n        </td>\r\n        <td class=\"right middle\">{{ row.grossSalary | currency }}</td>\r\n        <td class=\"right middle\">{{ row.data.workerPayment | currency }}</td>\r\n        <td class=\"middle\"><span ng-class=\"$ctrl.rowStatusWarning(row) ? 'badge bg-danger': ''\">{{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}<span></td>\r\n        <td ng-if=\"!('disableHolidays' | sxyIsInRole)\" class=\"right\">\r\n          <table class=\"text-small\" ng-if=\"$ctrl.getPageCalc(row)\">\r\n            <tbody>\r\n              <tr>\r\n                <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.leavesDays\"></td>\r\n                <td class=\"right\">{{ $ctrl.calculatePeriodDays($ctrl.getPageCalc(row),'leavesDays') | sxyCount : 'day' }}</td>\r\n              </tr>\r\n              <tr>\r\n                <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.absencesDays\"></td>\r\n                <td class=\"right\">{{ $ctrl.calculatePeriodDays($ctrl.getPageCalc(row),'absencesDays') | sxyCount : 'day' }}</td>\r\n              </tr>\r\n              <tr>\r\n                <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.paidAbsencesDays\"></td>\r\n                <td class=\"right\">{{ $ctrl.calculatePeriodDays($ctrl.getPageCalc(row),'paidAbsencesDays') | sxyCount : 'day' }}</td>\r\n              </tr>\r\n              <tr ng-if=\"$ctrl.showAccruals($ctrl.getPageCalc(row))\">\r\n                <td sxy-text=\"SALAXY.NG1.CalcComponent.panelWorkTime.overview.accruedDays\"></td>\r\n                <td class=\"right\">{{ $ctrl.calculatePeriodDays($ctrl.getPageCalc(row),'accruedDays') | sxyCount : 'day' }}</td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </td>\r\n        <td class=\"right middle\">\r\n          <span>{{ { start: row.data.workStartDate, end: row.data.workEndDate, } | sxyDateRange }}</span>\r\n          <div ng-if=\"$ctrl.isDateDifferent(row)\">\r\n            <del class=\"small\">{{ $ctrl.current.input.period | sxyDateRange }}</del>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end>\r\n        <td colspan=\"12\">\r\n          <salaxy-spinner ng-if=\"!$ctrl.getPageCalc(row)\"></salaxy-spinner>\r\n          <salaxy-calc-rows-2019-editor ng-if=\"$ctrl.getPageCalc(row)\" parent=\"$ctrl.getPageCalc(row)\" title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calcRowEditor.title' | sxyTranslate}}\" mode=\"{{$ctrl.getPageCalc(row).isReadOnly ? 'read-only' : 'read-edit'}}\" show-edit-buttons=\"false\" is-in-edit=\"!$ctrl.getPageCalc(row).isReadOnly\" show-gross-totals=\"true\" dimension-count=\"2\"></salaxy-calc-rows-2019-editor>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>\r\n<div class=\"text-right\">\r\n  <span>{{$ctrl.page.current}}/{{$ctrl.page.total}}</span>\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToPage(true)\"><span><i class=\"fa fa-step-backward\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.previous\"></span></button>\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.goToPage(false)\"><span sxy-text=\"SALAXY.UI_Terms.next\"></span> <span><i class=\"fa fa-step-forward\"></i></span></button>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.savePageCalcs()\" ng-disabled=\"$ctrl.numOfChangedPageCalcs == 0 || $ctrl.loaders['pageCalcs' + $ctrl.page.current]\"><span ng-if=\"$ctrl.loaders['pageCalcs' + $ctrl.page.current]\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.calculation.actions.save\"></span><span ng-if=\"$ctrl.numOfChangedPageCalcs > 0\"> <span class=\"badge\">{{$ctrl.numOfChangedPageCalcs}}<span></span></span></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_debug.html\",`<salaxy-json-formatter ng-if=\"$ctrl.current\" key=\"'PAYROLL'\" json=\"$ctrl.current\"></salaxy-json-formatter>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_header.html\",`<div class=\"salaxy-navi-page-container salaxy-payroll-details-header salaxy-payroll-details-dialog\" ng-style=\"{'max-width': '100%','width': $ctrl.userSettings.ng1Binder('payroll.headerDialogSize').val || '75%'}\" ng-class=\"{ 'offcanvas-show': $ctrl.shouldShowCanvas('header',$ctrl.showHeader || $ctrl.isNew())}\">\r\n  <div class=\"modal-header\">\r\n    <span  class=\"pull-right\">\r\n      <button type=\"button\" class=\"btn btn-transparent\"  ng-click=\"$ctrl.userSettings.ng1Binder('payroll.headerDialogSize').val = ($ctrl.userSettings.ng1Binder('payroll.headerDialogSize').val == '100%' ? '75%' : '100%')\"><i ng-class=\"$ctrl.userSettings.ng1Binder('payroll.headerDialogSize').val == '100%' ? 'fa fa-compress' : 'fa fa-expand'\"></i></button>\r\n      <button type=\"button\" class=\"btn btn-primary\" aria-label=\"Close\" ng-click=\"$ctrl.closeHeader()\"><span class=\"fa fa-times\"></span></button>\r\n    </span>\r\n    <h3 ng-if=\"$ctrl.isNew()\"  class=\"modal-title\">{{$ctrl.current.input.title || ('SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.heading' | sxyTranslate)}}</h3>\r\n    <h3 ng-if=\"!$ctrl.isNew()\"  class=\"modal-title\">{{$ctrl.current.input.title}}</h3>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div ng-class=\"$ctrl.userSettings.ng1Binder('payroll.headerDialogSize').val == '100%' ? 'container' : ''\">\r\n      <ng-form name=\"$ctrl.payrollDetailsForm\" class=\"form-horizontal\" ng-readonly=\"$ctrl.isReadOnly\">\r\n        <p ng-if=\"$ctrl.isNew()\" class=\"lead\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.intro\"></p>\r\n        <div class=\"col-xs-12 payroll-edit-properties-col\">\r\n          <salaxy-input name=\"title\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.title\" required ng-model=\"$ctrl.current.input.title\"></salaxy-input>\r\n    \r\n    \r\n          <salaxy-input-enum label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.wageBasis\" name=\"wageBasis\" ng-model=\"$ctrl.current.input.wageBasis\" enum=\"WageBasis\" required placeholder=\"SALAXY.UI_Terms.selectAlt\"></salaxy-input-enum>\r\n          <salaxy-form-group name=\"paymentChannel\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.paymentChannel\" ng-show=\"$ctrl.$payButton.showPaymentChannelSelection()\">\r\n            <salaxy-pay-button ng-if=\"!$ctrl.isReadOnly || $ctrl.showAction('pay')\" ng-ref=\"$ctrl.$payButton\" model=\"$ctrl.current\" mode=\"channel-select\" button-class=\"btn-block\"></salaxy-pay-button>\r\n            <div ng-if=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">{{ \"PaymentChannel.\" + $ctrl.current.input.paymentChannel | sxyEnum }}</div>\r\n          </salaxy-form-group>\r\n          <salaxy-form-group name=\"paymentChannelReadonly\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.paymentChannel\" ng-if=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">\r\n            <div>{{ \"PaymentChannel.\" + $ctrl.current.input.paymentChannel | sxyEnum }}</div>\r\n          </salaxy-form-group>\r\n          <div  ng-if=\"(!$ctrl.isReadOnly || $ctrl.showAction('pay')) && ('test,setSalaryDateKind' | sxyIsInRole)\"  ng-switch=\"$ctrl.current.input.paymentChannel\">\r\n            <div ng-switch-when=\"palkkausManual|palkkausInvoices|palkkausCfaTest|kitsas|briox|askelma|passeliMerit\" ng-switch-when-separator=\"|\">\r\n              <salaxy-form-group name=\"salaryDateKind\" label=\"SALAXY.MODEL.PayrollInput.salaryDateKind.title\">       \r\n                <salaxy-salary-date-kind-button button-class=\"btn-block\" model=\"$ctrl.current\" ></salaxy-salary-date-kind-button>\r\n              </salaxy-form-group>\r\n            </div>\r\n          </div>\r\n          <salaxy-form-group ng-if=\"($ctrl.isReadOnly && !$ctrl.showAction('pay')) && $ctrl.current.input.salaryDateKind == 'inPast'\" name=\"salaryDateKind\" class=\"salaxy-component salaxy-read-only\" label=\"SALAXY.MODEL.CalcWorkflow.salaryDateKind.title\">\r\n            <div class=\"salaxy-read-only-value\">{{\"SALAXY.ENUM.SalaryDateKind.\" + ($ctrl.current.input.salaryDateKind) + \".label\" | sxyTranslate  }}</div>\r\n          </salaxy-form-group>\r\n    \r\n          <salaxy-datepicker-popup read-only=\"false\" ng-if=\"!$ctrl.isReadOnly || $ctrl.showAction('pay')\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryDate\" name=\"salaryDate\" ng-model=\"$ctrl.current.input.salaryDate\" date-disabled=\"disable-function\" disable-function=\"$ctrl.isDisabledSalaryDate\"></salaxy-datepicker-popup>\r\n          <div class=\"form-group\" ng-if=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\">\r\n            <div class=\"col-sm-4\"><strong sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryDate\" ps=\":\"></strong> </div>\r\n            <div class=\"col-sm-8\">\r\n              {{ $ctrl.current.info.salaryDate | date }}\r\n              <span class=\"badge bg-info\" ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' && !$ctrl.current.input.salaryDate && $ctrl.current.info.salaryDate\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateEstimate' | sxyTranslate}}</span>\r\n              <span ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' &&  $ctrl.current.info.salaryDate && $ctrl.current.input.salaryDate && $ctrl.current.input.salaryDate != $ctrl.current.info.salaryDate\"><s>{{ $ctrl.current.input.salaryDate | date }}</s> <span class=\"badge bg-warning\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateNote' | sxyTranslate}}</span></span>    \r\n            </div>\r\n          </div>\r\n\r\n          <salaxy-date-range read-only=\"$ctrl.isReadOnly && !$ctrl.showAction('pay')\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.salaryPeriod\" name=\"period\" ng-model=\"$ctrl.current.input.period\" mode=\"calc\"></salaxy-date-range>\r\n\r\n          <salaxy-input name=\"sourceId\" label=\"Source ID (import)\" ng-model=\"$ctrl.current.input.sourceId\"></salaxy-input>\r\n          \r\n          <salaxy-form-group ng-if=\"$ctrl.isNew() && $ctrl.current.input.calculations.length\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.copyingCalcs\" name=\"calcCount\">\r\n            {{ $ctrl.current.input.calculations.length }} {{ 'SALAXY.UI_Terms.units.pce' | sxyTranslate}}\r\n          </salaxy-form-group>\r\n          <salaxy-input-boolean ng-if=\"$ctrl.isNew() && $ctrl.current.input.calculations.length\" type=\"select\" required placeholder=\"SALAXY.UI_Terms.choose\" name=\"updateCalcsInCopy\" ng-model=\"$ctrl.updateCalcsInCopy\" label=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcs\" label-false=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcsFalse\"\r\n            label-true=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.updateCalcsTrue\"></salaxy-input-boolean>\r\n        </div>\r\n      </ng-form>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.closeHeader()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n\r\n    <button type=\"button\" ng-if=\"!$ctrl.isNew()\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\" ng-disabled=\"($ctrl.isReadOnly && !$ctrl.showAction('pay')) || (!$ctrl.payrollDetailsForm.$valid || $ctrl.current.input.wageBasis == 'undefined' || !$ctrl.current.input.paymentChannel || $ctrl.current.input.paymentChannel == 'undefined' )  || $ctrl.loaders[$ctrl.current.id || 'new']\"><span\r\n      ng-if=\"$ctrl.loaders[$ctrl.current.id || 'new']\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.save\"></span></button>\r\n    <button type=\"button\" ng-if=\"$ctrl.isNew()\" class=\"btn btn-primary\" ng-click=\"$ctrl.save({ 'applyEmploymentDefaultRows' : !$ctrl.updateCalcsInCopy})\" ng-disabled=\"(!$ctrl.payrollDetailsForm.$valid || $ctrl.current.input.wageBasis == 'undefined'  || !$ctrl.current.input.paymentChannel || $ctrl.current.input.paymentChannel == 'undefined') || $ctrl.loaders[$ctrl.current.id || 'new']\"><span\r\n        ng-if=\"$ctrl.loaders[$ctrl.current.id || 'new']\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.editProperties.new.createPayrollButton\"></span></button>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_info.html\",`\r\n<div class=\"row\">\r\n  <!-- TODO: In BS5 rewrite this with grid / flex helpers -->\r\n  <div class=\"col-xs-2\" style=\"width: 120px\">\r\n    <salaxy-avatar-placeholder class=\"payroll-avatar\">\r\n      <i class=\"salaxy-avatar fa fa-square text-muted\" ng-class=\"{'draft-invalid' : $ctrl.current.info.status == 'draft' && !$ctrl.current.info.isReadyForPayment, 'text-success' : $ctrl.current.info.status == 'paymentSucceeded', 'text-warning' : ($ctrl.current.info.status == 'paymentStarted' || $ctrl.current.info.status == 'waitingApproval') , 'text-danger' : $ctrl.current.info.status == 'paymentCancelled'}\">\r\n        <span>\r\n          <strong>{{ $ctrl.current.info.calcCount }}</strong>\r\n          <small>{{ $ctrl.current.info.salaryDate | date : \"d.M.\" }}</small>\r\n        </span>\r\n      </i>\r\n    </salaxy-avatar-placeholder>\r\n  </div>\r\n  <div class=\"col-xs-9 col-sm-6\">\r\n    <h3 class=\"payroll-title\">{{ $ctrl.current.input.title }}</h3>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 col-sm-6\">\r\n        <div>\r\n          <span>{{ 'PayrollStatus.' + $ctrl.current.info.status | sxyEnum }}</span>\r\n          <span ng-if=\"$ctrl.current.info.status == 'draft'\" ng-class=\"$ctrl.current.info.isReadyForPayment ? 'text-success' : 'text-danger'\">\r\n            {{ $ctrl.current.info.isReadyForPayment ? (('SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.readyForPayment' | sxyTranslate)) :\r\n            (('SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.notReadyForPayment' | sxyTranslate)) }}\r\n          </span>\r\n        </div>\r\n        <div>\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryPeriod\" ps=\":\"></span> {{ $ctrl.current.input.period | sxyDateRange }} ({{$ctrl.current.input.period.daysCount}} <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryPeriodDaysCount\"></span>)\r\n        </div>\r\n        <div>\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDate\" ps=\":\"></span> \r\n          {{ $ctrl.current.info.salaryDate | date }}\r\n          <span class=\"badge bg-info\" ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' && !$ctrl.current.input.salaryDate && $ctrl.current.info.salaryDate\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateEstimate' | sxyTranslate}}</span>\r\n          <span ng-if=\"$ctrl.current.info.status != 'paymentSucceeded' &&  $ctrl.current.info.salaryDate && $ctrl.current.input.salaryDate && $ctrl.current.input.salaryDate != $ctrl.current.info.salaryDate\"><s>{{ $ctrl.current.input.salaryDate | date }}</s> <span class=\"badge bg-warning\">{{'SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.salaryDateNote' | sxyTranslate}}</span></span>    \r\n        </div>\r\n        <div ng-if=\"$ctrl.current.input.wageBasis != 'undefined'\">\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.wageBasis\" ps=\":\"></span> {{ 'WageBasis.' + $ctrl.current.input.wageBasis | sxyEnum }}\r\n        </div>\r\n        <div>\r\n          <span ng-if=\"$ctrl.current.input.template\" sxy-html=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.template.html\" params=\"{template: ($ctrl.current.input.template)}\"></span>\r\n        </div>\r\n        <div>\r\n          <small>ID: <code>{{ $ctrl.currentId }}</code></small>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-6\">\r\n        <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.calcCount\" ps=\":\"></span><span ng-style=\"$ctrl.getExceptionStyle($ctrl.info.calcCount.exception)\"> {{ $ctrl.info.calcCount.original }}</span><span ng-if=\"$ctrl.info.calcCount.exception\"> {{ $ctrl.info.calcCount.actual }}</span></span><br />\r\n        <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.grossSalary\" ps=\":\"></span><span ng-style=\"$ctrl.getExceptionStyle($ctrl.info.totalGrossSalary.exception)\"> {{ $ctrl.info.totalGrossSalary.original | currency }}</span><span ng-if=\"$ctrl.info.totalGrossSalary.exception\"> {{ $ctrl.info.totalGrossSalary.actual | currency }}</span></span><br />\r\n        <span><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.payrollInfo.totalPayment\" ps=\":\"><span ng-style=\"$ctrl.getExceptionStyle($ctrl.info.totalPayment.exception)\"> {{ $ctrl.info.totalPayment.original | currency }}</span><span ng-if=\"$ctrl.info.totalPayment.exception\"> {{ $ctrl.info.totalGrossSalary.actual | currency }}</span></span><br />\r\n        <button type=\"button\" class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.showHeader = !$ctrl.showHeader\" ><span sxy-text=\"{{$ctrl.isReadOnly ? 'SALAXY.UI_Terms.show' : 'SALAXY.UI_Terms.edit'}}\"></span> <i ng-class=\"$ctrl.isReadOnly ? 'fa fa-info' : 'fa fa-pencil'\"></i></button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"'company' | sxyIsInRole\" ng-controller=\"CompanyAccountController as $company\" style=\"padding: 8px\">\r\n      <salaxy-workflow-badge ng-if=\"$company.current\" model=\"$company.current\" mode=\"horizontal\" api-ctrl=\"$company\" wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n    </div>\r\n    <div ng-if=\"$ctrl.showWorkflowMessage\" style=\"margin-bottom: 4px;\">\r\n      <!-- Only shown in Accountor / Finago -->\r\n      <salaxy-textarea name=\"workflowMessage\" ng-model=\"$ctrl.workflowMessage\" placeholder=\"{{'SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.workFlowMessage'}}\" rows=\"2\"\r\n        label-type=\"plain\"></salaxy-textarea>\r\n    </div>\r\n  </div>\r\n  <div class=\"hidden-sm col-md-4\" ng-if=\"$ctrl.$import.isSupported && $ctrl.$import.worktimeApi.list\">\r\n    <div class=\"\" style=\"max-width: 400px;\">\r\n      <button type=\"button\" class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.headerView = 'ports'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.payrollView.btnMoreInfo\"></button>\r\n      <h3 sxy-text=\"SALAXY.NG1.ImportStagingComponent.payrollView.title\" style=\"margin-top: 0\"></h3>\r\n      <table style=\"width: 100%; \">\r\n        <colgroup>\r\n          <col style=\"width: 40%;\">\r\n          <col style=\"width: 10%;\">\r\n          <col style=\"width: 40%;\">\r\n          <col style=\"width: 10%;\">\r\n        </colgroup>\r\n        <tbody>\r\n          <tr>\r\n            <td><div class=\"text-muted\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.preview\"></div></td>\r\n            <td class=\"right\"><div class=\"text-muted\">{{ $ctrl.$import.getTotals(\"all\").rows.preview }}</div></td>\r\n            <td style=\"padding-left: 6px;\"><div class=\"\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.calcCount\"></div></td>\r\n            <td class=\"right\">{{ $ctrl.$import.getTotals(\"all\").rows.count }}</td>\r\n          </tr>\r\n          <tr>\r\n            <td><div class=\"text-primary\"><b sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.new\"></b></div></td>\r\n            <td ng-if=\"$ctrl.$import.getTotals('all').rows.new\" class=\"right\"><div class=\"bg-primary badge\">&nbsp;&nbsp;{{ $ctrl.$import.getTotals(\"all\").rows.new }}&nbsp;</div></td>\r\n            <td ng-if=\"!$ctrl.$import.getTotals('all').rows.new\" class=\"right\"><div class=\"text-primary\">0</div></td>\r\n            <td style=\"padding-left: 6px;\"><div class=\"\"><b sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.committed\"></b></div></td>\r\n            <td class=\"right\"><b>{{ $ctrl.$import.getTotals(\"all\").rows.committed }}</b></td>\r\n          </tr>\r\n          <tr>\r\n            <td><div class=\"\"><s sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.deleted\"></s></div></td>\r\n            <td class=\"right\"><s>{{ $ctrl.$import.getTotals(\"all\").rows.deleted }}</s></td>\r\n            <td style=\"padding-left: 6px;\"><div class=\"text-muted\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.ignored\"></div></td>\r\n            <td class=\"right\"><div class=\"text-muted\">{{ $ctrl.$import.getTotals(\"all\").rows.ignored }}</div></td>\r\n          </tr>\r\n          <tr>\r\n            <td><div class=\"text-danger\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.error\"></div></td>\r\n            <td ng-if=\"$ctrl.$import.getTotals('all').rows.error\" class=\"right\"><div class=\"bg-danger badge\">&nbsp;&nbsp;{{ $ctrl.$import.getTotals(\"all\").rows.error }}&nbsp;</div></td>\r\n            <td ng-if=\"!$ctrl.$import.getTotals('all').rows.error\" class=\"right\"><div class=\"text-danger\">0</div></td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_messages.html\",`<div ng-if=\"!$ctrl.current.info.messageThreadId\" ng-controller=\"MessageThreadCrudController as $msg\" ng-init=\"$msg.model='new'\" class=\"form-horizontal\" style=\"max-width: 600px;\">\r\n  <fieldset sxy-if-role=\"!pro\">\r\n    <p ng-if=\"!$ctrl.current.info.messageThreadId\">Tähän palkkalistaan ei liity viestiketjua / työnkulkua.</p>\r\n    <!--\r\n    <legend>Lähetä tilitoimistolle</legend>\r\n    <p>Luo tästä uusi viestiketju, jolla voit lähettää palkkalistan tilitoimiston käsittelyyn.</p>\r\n    <salaxy-input-enum name=\"action\" label=\"Pyydetään toimintaa\" type=\"radio\" ng-model=\"$msg.current.input.todoAction\" options=\"$ctrl.messageActions\"\r\n      ng-change=\"$msg.current.title = $ctrl.getMessageTitle($msg.current.input.todoAction)\"></salaxy-input-enum>\r\n    <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" disabled=\"!$msg.current.input.todoAction\" ng-model=\"$msg.current.title\"></salaxy-input>\r\n    <salaxy-form-group name=\"msgSubmit\" label-type=\"empty-label\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.sendPayrollMessage($msg)\">Lähetä</button>\r\n    </salaxy-form-group>\r\n    -->\r\n  </fieldset>\r\n  <fieldset sxy-if-role=\"pro\">\r\n    <legend>Lähetä yritykselle</legend>\r\n    <p>Luo tästä uusi viestiketju, jolla voit lähettää palkkalistan yritykselle hyväksyttäväksi / maksettavaksi.</p>\r\n    <salaxy-input-enum name=\"action\" label=\"Pyydetään toimintaa\" type=\"radio\" ng-model=\"$msg.current.input.todoAction\" options=\"$ctrl.messageActions\"\r\n      ng-change=\"$msg.current.title = $ctrl.getMessageTitle($msg.current.input.todoAction)\"></salaxy-input-enum>\r\n    <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" disabled=\"!$msg.current.input.todoAction\"\r\n      ng-model=\"$msg.current.title\"></salaxy-input>\r\n    <salaxy-form-group name=\"msgSubmit\" label-type=\"empty-label\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.sendPayrollMessage($msg)\">Lähetä</button>\r\n    </salaxy-form-group>\r\n  </fieldset>\r\n</div>\r\n<div ng-if=\"$ctrl.current.info.messageThreadId\">\r\n  <button type=\"button\" class=\"btn btn-danger pull-right\" ng-click=\"$ctrl.deleteMessage($ctrl.$msg)\"><i class=\"fa fa-trash\" aria-hidden=\"true\"></i></button>\r\n  <salaxy-message-thread model=\"$ctrl.current.info.messageThreadId\" ng-ref=\"$ctrl.$msg\" role=\"{{('pro' | sxyIsInRole) ? 'otherParty' : 'owner' }}\" other-party=\"'partner'\"\r\n    mark-as-read=\"5\"></salaxy-message-thread>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_ports.html\",`<div> \r\n  <salaxy-import-staging ng-ref=\"$ctrl.$import\" payroll=\"$ctrl.current\" payroll-calcs=\"$ctrl.calcs\"></salaxy-import-staging>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_reports.html\",`<div ng-if=\"$ctrl.calcs.length\" ng-init=\"$ctrl.refreshReports()\">\r\n  <salaxy-calc-reports ng-if=\"$ctrl.reportCalcs.length\" calcs=\"$ctrl.reportCalcs\"  report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/calc/payrollV4/PayrollDetails_toolbar.html\",`<div ng-if=\"$ctrl.isReadOnly\" class=\"btn-toolbar\">\r\n  <button class=\"btn btn-secondary\" ng-if=\"$ctrl.showAction('copy')\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.copyAsNew\"></button>\r\n  <div class=\"pull-right\">\r\n    <salaxy-pay-button ng-ref=\"$ctrl.$payButton\" ng-if=\"$ctrl.showAction('pay')\" model=\"$ctrl.current\" mode=\"pay-button\" button-class=\"pull-right-xs\"\r\n      label=\"SALAXY.NG1.PayrollComponent.payrollPayButton\" \r\n      disabled=\"!$ctrl.current.info.isReadyForPayment || !$ctrl.current.input.calculations.length || !$ctrl.$payButton.isChannelDefined\" ></salaxy-pay-button>\r\n    <button ng-if=\"$ctrl.showAction('cancel') && ($ctrl.current.info.status == 'paymentStarted' && ($ctrl.current.input.paymentChannel == 'palkkausManual' || $ctrl.current.input.paymentChannel == 'palkkausInvoices' || $ctrl.current.input.paymentChannel == 'kitsas' || $ctrl.current.input.paymentChannel == 'palkkausPersonal' || $ctrl.current.input.paymentChannel == 'palkkausCfaPaytrail' || $ctrl.current.input.paymentChannel == 'palkkausEcfaPaytrail' || $ctrl.current.input.paymentChannel == 'palkkausCfaReference' || $ctrl.current.input.paymentChannel == 'palkkausEcfaReference' || $ctrl.current.input.paymentChannel == 'palkkausCfaFinvoice' || $ctrl.current.input.paymentChannel == 'palkkausEcfaFinvoice' ||  $ctrl.current.input.paymentChannel == 'palkkausCfaTest'))\"\r\n      class=\"btn btn-secondary  btn-labeled-right\" ng-click=\"$ctrl.cancelInvoices()\"><span sxy-text=\"SALAXY.NG1.CalcResultsComponent.cancelPaymentOrChangeChannelBtn\"></span><i\r\n        class=\"fa fa-times-circle\"></i></button>\r\n    <button ng-if=\"$ctrl.current.info.status != 'waitingApproval' && $ctrl.current.info.status != 'draft'\" class=\"btn btn-secondary  btn-labeled-right\"\r\n      ng-click=\"$ctrl.showPaymentDialog()\"><span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.showPaymentInfo\"></span><i class=\"fa fa-info\"></i></button>\r\n  </div>\r\n</div>\r\n<div ng-if=\"!$ctrl.isReadOnly\" class=\"btn-toolbar calc-toolbar\">\r\n  <div class=\"btn-group dropdown\" uib-dropdown>\r\n    <button type=\"button\" class=\"btn btn-labeled-left btn-primary dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\"><i class=\"fa fa-plus\"></i>\r\n      <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCalculation\"></span> <span class=\"caret\"></span></button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"addcalculation\">\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addEmployments()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addWorker\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addCalcs('draft')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addDraft\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addCalcs('shared')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addShared\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addCalcs('draft', true, true, true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.mergeDraft\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addCalcs('shared', true, true, true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.mergeShared\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.addCalcs('paid')\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addCopy\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.mergePayroll(true, true)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollCalcs.toolbar.addPayroll\"></a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n  <div class=\"btn-group\" uib-dropdown=\"\">\r\n    <button type=\"button\" class=\"btn btn-secondary dropdown-toggle\" uib-dropdown-toggle=\" \" aria-haspopup=\"true\" aria-expanded=\"false\">\r\n      <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.options\"></span>\r\n      <span class=\"caret \"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu=\"\" role=\"menu\" aria-labelledby=\"actions\">\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.importEmploymentDataAll()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.importEmploymentCalc\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.exportEmploymentDataAll()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.exportEmploymentCalc\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.copyAsNew\"></a>\r\n      </li>\r\n      <li role=\"menuitem\">\r\n        <a class=\"text-danger\" ng-click=\"$ctrl.delete()\" sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.delete\"></a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n  <div sxy-if-role=\"pro\" class=\"btn-group\">\r\n    <div class=\"btn-group\" style=\"margin-left:5px;\" uib-dropdown>\r\n      <!-- HACK: Rewrite workflow buttons as components. Or make PRO calculator a component. -->\r\n      <button class=\"btn btn-default\" uib-dropdown-toggle type=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"font-weight: bold;\">\r\n        {{ \"PayrollStatus.\" + $ctrl.current.info.status | sxyEnum }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu>\r\n        <li ng-class=\"{ disabled: $ctrl.current.info.status=='draft' }\">\r\n          <a href=\"\" ng-click=\"$ctrl.current.info.status = 'draft';$ctrl.save()\">{{ \"PayrollStatus.draft\" | sxyEnum }}</a>\r\n        </li>\r\n        <li ng-class=\"{ disabled: $ctrl.current.info.status=='template' }\">\r\n          <a href=\"\" ng-click=\"$ctrl.current.info.status = 'template';$ctrl.save()\">{{ \"PayrollStatus.template\" | sxyEnum }}</a>\r\n        </li>\r\n        <li ng-class=\"{ disabled: $ctrl.current.info.status=='handled' }\">\r\n          <a href=\"\" ng-click=\"$ctrl.current.info.status = 'handled';$ctrl.save()\">{{ \"PayrollStatus.handled\" | sxyEnum }}</a>\r\n        </li>\r\n        <li ng-class=\"{ disabled: $ctrl.current.info.status=='waitingApproval' }\">\r\n          <a href=\"\" ng-click=\"$ctrl.current.info.status = 'waitingApproval';$ctrl.save()\">{{ \"PayrollStatus.waitingApproval\" | sxyEnum }}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <salaxy-workflow-buttons api-ctrl=\"$ctrl\"></salaxy-workflow-buttons>\r\n  </div>\r\n  <div class=\"btn-group pull-right\">\r\n     <salaxy-pay-button ng-ref=\"$ctrl.$payButton\" ng-if=\"$ctrl.current.info.status != 'template'\" model=\"$ctrl.current\" mode=\"pay-button\" button-class=\"pull-right-xs\"\r\n      label=\"SALAXY.NG1.PayrollComponent.payrollPayButton\" \r\n      disabled=\"!$ctrl.current.info.isReadyForPayment || !$ctrl.current.input.calculations.length || !$ctrl.$payButton.isChannelDefined\" ></salaxy-pay-button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcIrRows.html\",`<div class=\"salaxy-calc-ir-rows salaxy-component\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.headerIrCode\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.headerRowDescription\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.headerCalc\" class=\"right\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.headerSum\" class=\"right\"></th>\r\n        <th></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.irRows\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: row.irData.code, entityType: 'company' }\"></salaxy-avatar>\r\n          <b>{{ $ctrl.getIncomeType(row).label }}</b><br />\r\n          <small>\r\n            <div class=\"truncate\" style=\"max-width: 250px;\">\r\n              {{$ctrl.getIncomeType(row).description}}\r\n            </div>\r\n          </small>\r\n        </td>\r\n        <td>{{ row.message }}</td>\r\n        <td class=\"right\">\r\n          <span ng-if=\"row.unit != 'one'\">\r\n            {{ row.count | sxyCount : row.unit }} *\r\n          </span> {{ row.price | currency }} =\r\n        </td>\r\n        <td class=\"right\">{{ row.total | currency }}\r\n        </td>\r\n        <td class=\"salaxy-calc-rows-editor-btns\" ng-if=\"row.type=='manual'\">\r\n          <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.setCurrentIrRow(row)\"><i class=\"fa fa-edit\"></i></button>\r\n          <button type=\"button\" class=\"delete btn btn-danger\" ng-click=\"$ctrl.deleteIrRow(row)\"><i class=\"fa fa-trash\"></i></button>\r\n        </td>\r\n        <td class=\"salaxy-calc-rows-editor-btns\" ng-if=\"row.type!='manual'\">\r\n          <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.setCurrentIrRow(row)\"><i class=\"fa fa-info\"></i></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n    <tfoot ng-if=\"!$ctrl.isReadOnly\">\r\n      <tr>\r\n        <th colspan=\"6\" class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculate()\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.updateCalc\"></button>\r\n          <button type=\"button\" class=\"btn btn-info\" ng-click=\"$ctrl.addIrRow()\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.addNewRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </tfoot>\r\n  </table>\r\n  <h4 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.chosenRowInfo\"></h4>\r\n  <div ng-if=\"!$ctrl.currentRow\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.chooseRowOrAddNew\"></div>\r\n  <uib-tabset active=\"$ctrl.currentTab\" ng-if=\"$ctrl.currentRow\">\r\n    <uib-tab index=\"'basic'\" heading=\"{{'SALAXY.NG1.CalcRowsComponent.irRows.basicInfo' | sxyTranslate}}\">\r\n      <div class=\"form-horizontal\">\r\n        <div class=\"row\">\r\n          <div class=\"col col-md-12 col-lg-6\">\r\n            <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.textAndType\"></h2>\r\n            <salaxy-input-income-type name=\"code\" ng-model=\"$ctrl.currentRow.irData.code\" hidden-codes=\"[1]\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.typeLabel\" disabled=\"$ctrl.isIrRowReadOnly\" ng-change=\"$ctrl.updateCurrentRowType()\">\r\n            </salaxy-input-income-type>\r\n            <salaxy-input name=\"message\" ng-model=\"$ctrl.currentRow.message\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.messageLabel\" disabled=\"$ctrl.isIrRowReadOnly\"></salaxy-input>\r\n            <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.groupingLabel\" disabled=\"$ctrl.isIrRowReadOnly\"\r\n              options=\"$ctrl.groupingOptions\"\r\n              name=\"calcGrouping\" ng-model=\"$ctrl.currentRow.calcData.grouping\" type=\"select\"></salaxy-input-enum>\r\n            <salaxy-form-group label=\"SALAXY.NG1.CalcRowsComponent.irRows.creditTransferLabel\" name=\"paymentDefault\">\r\n              <div ng-if=\"$ctrl.currentRowType.paymentDefault == 1\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.payment\"></div>\r\n              <div ng-if=\"$ctrl.currentRowType.paymentDefault == -1\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.deduction\"></div>\r\n              <div ng-if=\"$ctrl.currentRowType.paymentDefault == 0\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.noPayment\"></div>\r\n            </salaxy-form-group>\r\n          </div>\r\n          <div class=\"col col-md-12 col-lg-6\">\r\n            <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.calc\"></h2>\r\n            <salaxy-input-number name=\"count\" ng-model=\"$ctrl.currentRow.count\" disabled=\"$ctrl.isIrRowReadOnly\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.countLabel\"></salaxy-input-number>\r\n            <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.unitLabel\" enum=\"Unit\" name=\"Unit\" disabled=\"$ctrl.isIrRowReadOnly\" ng-model=\"$ctrl.currentRow.unit\" type=\"select\"></salaxy-input-enum>\r\n            <salaxy-input-number name=\"price\" ng-model=\"$ctrl.currentRow.price\" disabled=\"$ctrl.isIrRowReadOnly\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.priceLabel\"></salaxy-input-number>\r\n            <salaxy-form-group name=\"total\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.totalLabel\">\r\n              <p>{{ $ctrl.currentRow.count * $ctrl.currentRow.price | currency }}</p>\r\n            </salaxy-form-group>\r\n          </div>\r\n          <div class=\"col col-md-12 col-lg-6\" ng-if=\"$ctrl.currentRow.irData.code == 304\">\r\n            <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitInfo\"></h2>\r\n            <p sxy-html=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitInfoHtml\"></p>\r\n            <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitTypeLabel\" disabled=\"$ctrl.isIrRowReadOnly\" enum=\"CarBenefitCode\" name=\"carBenefitCode\"\r\n              ng-model=\"$ctrl.currentRow.irData.carBenefit.carBenefitCode\" disabled=\"$ctrl.isIrRowReadOnly\" type=\"select\"></salaxy-input-enum>\r\n            <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitAgeGroupLabel\" enum=\"AgeGroupCode\" name=\"ageGroupCode\" disabled=\"$ctrl.isIrRowReadOnly\" ng-model=\"$ctrl.currentRow.irData.carBenefit.ageGroupCode\" type=\"select\">\r\n            </salaxy-input-enum>\r\n            <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitEmissionsValueLabel\" name=\"emissionsValue\" disabled=\"$ctrl.isIrRowReadOnly\" minimum=\"0\" maximum=\"100\" ng-model=\"$ctrl.currentRow.irData.carBenefit.emissionsValue\">\r\n            </salaxy-input-number>\r\n            <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitKilometersLabel\" name=\"kilometers\" disabled=\"$ctrl.isIrRowReadOnly\" ng-model=\"$ctrl.currentRow.irData.carBenefit.kilometers\">\r\n            </salaxy-input-number>\r\n          </div>\r\n          <div class=\"col col-md-12 col-lg-6\" ng-if=\"$ctrl.currentRow.irData.code == 331\">\r\n            <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.dailyAllowanceAdditionalSelections\"></h2>\r\n            <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.dailyAllowanceTypeLabel\" disabled=\"$ctrl.isIrRowReadOnly\" enum=\"AllowanceCode\" name=\"dailyAllowance\" type=\"multi-select\"\r\n              ng-model=\"$ctrl.currentRow.irData.dailyAllowance\"></salaxy-input-enum>\r\n          </div>\r\n          <div class=\"col col-md-12 col-lg-6\" ng-if=\"$ctrl.currentRow.irData.code == 334\">\r\n\r\n            <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitAdditionalSelections\"></h2>\r\n            <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitTaxInfo\"></p>\r\n\r\n            <salaxy-input-boolean type=\"checkbox\" name=\"mealBenefitIsTaxValue\" ng-model=\"$ctrl.currentRow.irData.mealBenefitIsTaxValue\" label-type=\"plain\"\r\n              label-true=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitIsTaxValueLabel\" disabled=\"$ctrl.isIrRowReadOnly\"></salaxy-input-boolean>\r\n\r\n          </div>\r\n        </div>\r\n        <div class=\"text-right\" ng-if=\"!$ctrl.isIrRowReadOnly\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculate()\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.updateCalc\"></button>\r\n          <button type=\"button\" class=\"btn btn-info\" ng-click=\"$ctrl.addIrRow()\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.addNewRow\"></button>\r\n        </div>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'incomeType'\" heading=\"{{'SALAXY.NG1.CalcRowsComponent.irRows.irFlagsInfo' | sxyTranslate}}\">\r\n      <div class=\"form-horizontal\">\r\n        <h2>{{ $ctrl.currentRowType.label }} ({{ $ctrl.currentRowType.code }})</h2>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.irFlagsLabel\" enum=\"IrFlags\" name=\"flags\" type=\"multi-select\" disabled=\"$ctrl.isIrRowReadOnly\" ng-model=\"$ctrl.currentRow.irData.flags\">\r\n        </salaxy-input-enum>\r\n        <salaxy-form-group label=\"SALAXY.NG1.CalcRowsComponent.irRows.negativeSupportedLabel\" name=\"isNegativeSupported\">\r\n          <div ng-if=\"$ctrl.currentRowType.isNegativeSupported\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.allowed\"></div>\r\n          <div ng-if=\"!$ctrl.currentRowType.isNegativeSupported\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.notAllowed\"></div>\r\n        </salaxy-form-group>\r\n        <div style=\"white-space: pre-wrap\">{{ $ctrl.currentRowType.description }}</div>\r\n\r\n        <h2 sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriod\"></h2>\r\n        <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodInfo\"></p>\r\n        <salaxy-datepicker-popup name=\"startDate\" disabled=\"$ctrl.isIrRowReadOnly\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodStartDateLabel\" ng-model=\"$ctrl.currentRow.earningPeriod.start\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"endDate\" disabled=\"$ctrl.isIrRowReadOnly\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodEndDateLabel\" ng-model=\"$ctrl.currentRow.earningPeriod.end\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'sideCosts'\" heading=\"{{'SALAXY.NG1.CalcRowsComponent.irRows.taxAndSideCosts' | sxyTranslate}}\">\r\n      <div class=\"form-horizontal\">\r\n        <h2>{{ $ctrl.currentRowType.label }}</h2>\r\n        <div style=\"white-space: pre-wrap\">{{ $ctrl.currentRowType.taxAndSidecostsDescr }}</div>\r\n        <table class=\"table\">\r\n          <tbody>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.tax\"></th>\r\n              <td>\r\n                <div ng-if=\"$ctrl.currentRowType.taxDefault == 1\" class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.withheld\"></div>\r\n                <div ng-if=\"$ctrl.currentRowType.taxDefault == -1\" class=\"text-warning\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.deductionAlt\"></div>\r\n                <div ng-if=\"$ctrl.currentRowType.taxDefault == 0\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.notwithheld\"></div>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.socialSecurityPayment\"></th><th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.socialSecurityPayment\">\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.toBePaid\"></th>\r\n              <th>\r\n                <!-- TODO: Lisää tähän srakkeeseen tieto poikkeuksen jälkeen-->\r\n              </th>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.occupationPension\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.currentRowType.pensionInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.currentRowType.pensionInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td>\r\n              </td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.insurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.currentRowType.accidentInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.currentRowType.accidentInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.unemploymentInsurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.currentRowType.unemploymentInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.currentRowType.unemploymentInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.healtInsurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.currentRowType.healthInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.currentRowType.healthInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n        <div ng-if=\"!$ctrl.currentRowType.insuranceInformationAllowed\">\r\n          <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.insuranceInformationAllowed\"></p>\r\n        </div>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.IrInsuranceExceptions\" enum=\"IrInsuranceExceptions\" name=\"dailyAllowance\" disabled=\"$ctrl.isIrRowReadOnly\"\r\n          ng-if=\"$ctrl.currentRowType.insuranceInformationAllowed\" ng-model=\"$ctrl.currentRow.irData.insuranceExceptions\" type=\"multi-select\"></salaxy-input-enum>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'json'\" heading=\"JSON\">\r\n      <salaxy-json-formatter json=\"$ctrl.currentRow\" open=\"2\"></salaxy-json-formatter>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcRowCostAccounting.html\",`<div class=\"salaxy-component salaxy-calc-cost-accounting\">\r\n  <div ng-if=\"$ctrl.isLegacy\">\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.CalcCostAccountingComponent.title\"></legend>\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th>{{('SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}</th>\r\n            <th class=\"right\">{{\"SALAXY.NG1.CalcCostAccountingComponent.percent\" | sxyTranslate}}</th>\r\n            <th class=\"right\">\r\n              <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.isReadOnly\" ng-click=\"$ctrl.costCenter.push({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"item in $ctrl.costCenter\">\r\n            <td>\r\n              <salaxy-input-enum ng-if=\"$ctrl.getOptions('costCenter').length\" ng-model=\"item.id\" type=\"typeahead\" label-format=\"text-value\"\r\n                options=\"$ctrl.getOptions('costCenter')\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\"></salaxy-input-enum>\r\n              <salaxy-input ng-if=\"!$ctrl.getOptions('costCenter').length\" ng-model=\"item.id\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\">\r\n              </salaxy-input>\r\n            </td>\r\n            <td>\r\n              <salaxy-input-number ng-model=\"item.percent\" name=\"{{ 'percent' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.isReadOnly\" unit=\"percent\"></salaxy-input-number>\r\n            </td>\r\n            <td class=\"text-right\" >\r\n              <button ng-if=\"!$ctrl.isReadOnly\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.costCenter.splice($index, 1)\">\r\n                <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n        <tfoot>\r\n          <tr class=\"total\">\r\n            <td>{{\"SALAXY.UI_Terms.total\" | sxyTranslate}}</td>\r\n            <td class=\"right\">{{ $ctrl.getLegacySum() | sxyCount : 'percent' }}</td>\r\n            <td class=\"right\"></td>\r\n          </tr>\r\n        </tfoot>\r\n      </table>\r\n    </fieldset>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isLegacy && ($ctrl.row.accounting.dimensions.length > 0 || $ctrl.definitions.length > 0)\">\r\n    <salaxy-cost-accounting ng-init=\"$ctrl.row.accounting = ($ctrl.row.accounting || $ctrl.isReadOnly)  ? $ctrl.row.accounting : { dimensions: []}\" current=\"$ctrl.row.accounting.dimensions\" inherited=\"$ctrl.calc.accounting.dimensions\" scope=\"row\" dimensions=\"$ctrl.dimensions\" read-only=\"$ctrl.isReadOnly\" ></salaxy-cost-accounting>\r\n  </div>\r\n  <div style=\"margin-bottom: 10px;\" sxy-if-role=\"test\">\r\n    <salaxy-json-formatter key=\"'All dimensions'\" json=\"$ctrl.row.accounting.dimensions\" open=\"0\" xx-type=\"dialog\" btn-class=\"btn btn-default\" ></salaxy-json-formatter>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcRowDimensionInput.html\",`\r\n\r\n<div style=\"display: flex; align-items: left;\">\r\n  <salaxy-input-enum \r\n    class=\"text-muted\" \r\n    ng-if=\"$ctrl.isInherited() && $ctrl.hasOptions() && !$ctrl.isCostSharingEnabled()\" \r\n    label-type=\"plain\"\r\n    ng-model=\"$ctrl.getInheritedSingleValue().value\"\r\n    label-format=\"text-value\" \r\n    type=\"typeahead\" \r\n    options=\"$ctrl.getOptions()\" \r\n    name=\"single\" \r\n    read-only=\"true\">\r\n  </salaxy-input-enum>\r\n  <salaxy-input \r\n    class=\"text-muted\"\r\n    ng-if=\"$ctrl.isInherited() && !$ctrl.hasOptions() && !$ctrl.isCostSharingEnabled()\"\r\n    label-type=\"plain\"\r\n    ng-model=\"$ctrl.getInheritedSingleValue().value\"\r\n    name=\"single\"\r\n    read-only=\"true\">\r\n  </salaxy-input>\r\n  <salaxy-input-enum \r\n    ng-if=\"!$ctrl.isInherited() && $ctrl.hasOptions() && !$ctrl.isCostSharingEnabled()\"\r\n    label-type=\"plain\"\r\n    ng-model=\"$ctrl.getSingleValue().value\"\r\n    ng-change=\"$ctrl.setSingleValue($ctrl.getSingleValue().value)\"\r\n    label-format=\"text-value\"\r\n    type=\"typeahead\"\r\n    options=\"$ctrl.getOptions()\"\r\n    name=\"single\"\r\n    read-only=\"$ctrl.readOnly\"\r\n    input-mode=\"{{$ctrl.inputMode}}\">\r\n  </salaxy-input-enum>\r\n  <salaxy-input \r\n    ng-if=\"!$ctrl.isInherited() && !$ctrl.hasOptions() && !$ctrl.isCostSharingEnabled()\"\r\n    label-type=\"plain\"\r\n    ng-model=\"$ctrl.getSingleValue().value\" \r\n    ng-change=\"$ctrl.setSingleValue($ctrl.getSingleValue().value)\"\r\n    name=\"single\"\r\n    read-only=\"$ctrl.readOnly\" \r\n    input-mode=\"{{$ctrl.inputMode}}\">\r\n  </salaxy-input>\r\n  <div class=\"btn\" ng-if=\"!$ctrl.readOnly && $ctrl.isInherited() && !$ctrl.isCostSharingEnabled()\">\r\n    <span> <i ng-click=\"$ctrl.setSingleValue($ctrl.getInheritedSingleValue().value)\" class=\"fa fa-pencil clickable\"></i></span>\r\n  </div>\r\n  <table ng-if=\"$ctrl.isCostSharingEnabled()\" class=\"text-small\">\r\n    <tbody>\r\n      <tr ng-repeat=\"costCenter in $ctrl.getCostSharingValues()\" ng-class=\"$ctrl.isInherited() ? 'text-muted' : ''\" class=\"\" style=\"line-height: 0.9em;\">\r\n        <td>{{costCenter.text}}</td>\r\n        <td>{{costCenter.value | sxyCount: 'percent'}}</td>\r\n      </tr>    \r\n    </tbody>\r\n  </table>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcRows2019EditDialog-irIncomeType.html\",`<uib-tabset>\r\n  <uib-tab index=\"'basic'\" heading=\"Perustiedot\">\r\n    <div class=\"col\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.textAndIncomeType\"></legend>\r\n        <salaxy-input-income-type name=\"code\" ng-model=\"$ctrl.current.data.irData.code\"  hidden-codes=\"[1]\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.incomeTypeLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n        </salaxy-input-income-type>\r\n        <salaxy-input name=\"message\" ng-model=\"$ctrl.current.message\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.messageLabel\" placeholder=\"{{$ctrl.getMessagePlaceholderText($ctrl.current)}}\"></salaxy-input>\r\n\r\n        <salaxy-form-group label=\"SALAXY.NG1.CalcRowsComponent.irRows.paymentToCreditTransferLabel\" name=\"paymentDefault\">\r\n          <!--TODO -->\r\n          <div ng-if=\"$ctrl.getIrCodeData().paymentDefault == 1\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.payment\"></div>\r\n          <div ng-if=\"$ctrl.getIrCodeData().paymentDefault == -1\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.deduction\"></div>\r\n          <div ng-if=\"$ctrl.getIrCodeData().paymentDefault == 0\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.noPayment\"></div>\r\n        </salaxy-form-group>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.calc\"></legend>\r\n        <salaxy-input-number name=\"count\" ng-model=\"$ctrl.current.count\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.countLabel\"></salaxy-input-number>\r\n        <salaxy-input-enum name=\"unit\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.unitLabel\" enum=\"Unit\" ng-model=\"$ctrl.current.data.unit\" type=\"select\"></salaxy-input-enum>\r\n        <salaxy-input-number name=\"price\" ng-model=\"$ctrl.current.price\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.priceLabel\"></salaxy-input-number>\r\n        <salaxy-form-group name=\"total\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.totalLabel\">\r\n          <p>{{ $ctrl.current.count * $ctrl.current.price | currency }}</p>\r\n        </salaxy-form-group>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col\" ng-if=\"$ctrl.current.data.irData.code == 304\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitInfo\"></legend>\r\n        <p sxy-html=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitInfoHtml\"></p>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitTypeLabel\" enum=\"CarBenefitCode\" name=\"carBenefitCode\" ng-model=\"$ctrl.current.data.irData.carBenefit.carBenefitCode\"\r\n          type=\"select\"></salaxy-input-enum>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitAgeGroupLabel\" enum=\"AgeGroupCode\" name=\"ageGroupCode\" ng-model=\"$ctrl.current.data.irData.carBenefit.ageGroupCode\" type=\"select\">\r\n        </salaxy-input-enum>\r\n        <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitEmissionsValueLabel\" name=\"emissionsValue\" minimum=\"0\" maximum=\"100\" ng-model=\"$ctrl.current.data.irData.carBenefit.emissionsValue\"></salaxy-input-number>\r\n        <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.irRows.carBenefitKilometersLabel\" name=\"kilometers\" ng-model=\"$ctrl.current.data.irData.carBenefit.kilometers\"></salaxy-input-number>     \r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col\" ng-if=\"$ctrl.current.data.irData.code == 331\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.dailyAllowanceAdditionalSelections\"></legend>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.dailyAllowanceTypeLabel\" enum=\"AllowanceCode\" name=\"dailyAllowance\" type=\"multi-select\"\r\n          ng-model=\"$ctrl.current.data.irData.dailyAllowance\" require=\"true\"></salaxy-input-enum>\r\n      </fieldset>\r\n    </div>\r\n\r\n    <div class=\"col\" ng-if=\"$ctrl.current.data.irData.code == 334\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitAdditionalSelections\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitTaxInfo\"></p>\r\n        <salaxy-input-boolean type=\"checkbox\" name=\"mealBenefitIsTaxValue\" ng-model=\"$ctrl.current.data.irData.mealBenefitIsTaxValue\" label-type=\"plain\"\r\n          label-true=\"SALAXY.NG1.CalcRowsComponent.irRows.mealBenefitIsTaxValueLabel\"></salaxy-input-boolean>\r\n      </fieldset>\r\n    </div>\r\n  </uib-tab>\r\n  <uib-tab index=\"'incomeType'\" heading=\"{{'SALAXY.NG1.CalcRowsComponent.irRows.irFlagsInfo' | sxyTranslate}}\">\r\n    <div class=\"col\">\r\n      <fieldset>\r\n        <legend>{{ $ctrl.getMessagePlaceholderText($ctrl.current) }} ({{ $ctrl.current.data.irData.code }})</legend>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.irFlagsLabel\" enum=\"IrFlags\" name=\"flags\" type=\"multi-select\" ng-model=\"$ctrl.current.data.irData.flags\"></salaxy-input-enum>\r\n        <salaxy-form-group label=\"SALAXY.NG1.CalcRowsComponent.irRows.negativeSupportedLabel\" name=\"isNegativeSupported\">\r\n          <div ng-if=\"$ctrl.getIrCodeData().isNegativeSupported\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.allowed\"></div>\r\n          <div ng-if=\"!$ctrl.getIrCodeData().isNegativeSupported\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.notAllowed\"></div>\r\n        </salaxy-form-group>\r\n        <div style=\"white-space: pre-wrap\">{{ $ctrl.getIrCodeData().description }}</div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriod\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodInfo\"></p>\r\n        <salaxy-datepicker-popup name=\"startDate\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodStartDateLabel\" ng-model=\"$ctrl.current.data.earningPeriod.start\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"endDate\" label=\"SALAXY.NG1.CalcRowsComponent.irRows.earningPeriodEndDateLabel\" ng-model=\"$ctrl.current.data.earningPeriod.end\"></salaxy-datepicker-popup>\r\n      </fieldset>\r\n    </div>\r\n  </uib-tab>\r\n  <uib-tab index=\"'sideCosts'\" heading=\"{{'SALAXY.NG1.CalcRowsComponent.irRows.taxAndSideCosts' | sxyTranslate}}\">\r\n    <div class=\"col\">\r\n      <fieldset>\r\n        <legend>{{ $ctrl.getMessagePlaceholderText($ctrl.current) }}</legend>\r\n        <div style=\"white-space: pre-wrap\">{{ $ctrl.getIrCodeData().taxAndSidecostsDescr }}</div>\r\n        <table class=\"table\">\r\n          <tbody>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.tax\"></th>\r\n              <td>\r\n                <div ng-if=\"$ctrl.getIrCodeData().taxDefault == 1\" class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.withheld\"></div>\r\n                <div ng-if=\"$ctrl.getIrCodeData().taxDefault == -1\" class=\"text-warning\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.deductionAlt\"></div>\r\n                <div ng-if=\"$ctrl.getIrCodeData().taxDefault == 0\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.notwithheld\"></div>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.socialSecurityPayment\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.toBePaid\"></th>\r\n              <th>\r\n                <!-- TODO: Lisää tähän srakkeeseen tieto poikkeuksen jälkeen-->\r\n              </th>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.occupationPension\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.getIrCodeData().pensionInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.getIrCodeData().pensionInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td>\r\n              </td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.insurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.getIrCodeData().accidentInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.getIrCodeData().accidentInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.unemploymentInsurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.getIrCodeData().unemploymentInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.getIrCodeData().unemploymentInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.healtInsurancePayment\"></th>\r\n              <td>\r\n                <span ng-class=\"$ctrl.getIrCodeData().healthInsurance ? 'text-success' : 'text-danger'\">\r\n                  {{ $ctrl.getIrCodeData().healthInsurance ? (\"SALAXY.UI_Terms.yes\" | sxyTranslate) : (\"SALAXY.UI_Terms.no\" | sxyTranslate) }}\r\n                </span>\r\n              </td>\r\n              <td></td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n        <div ng-if=\"!$ctrl.getIrCodeData().insuranceInformationAllowed\">\r\n          <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.irRows.insuranceInformationAllowed\"></p>\r\n        </div>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.irRows.IrInsuranceExceptions\" enum=\"IrInsuranceExceptions\" name=\"dailyAllowance\" disabled=\"$ctrl.isIrRowReadOnly\"\r\n          ng-if=\"$ctrl.getIrCodeData().insuranceInformationAllowed\" ng-model=\"$ctrl.current.data.irData.insuranceExceptions\" type=\"multi-select\">\r\n        </salaxy-input-enum>\r\n      </fieldset>\r\n    </div>\r\n  </uib-tab>\r\n</uib-tabset>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcRows2019EditDialog.html\",`<div class=\"salaxy-calc-details-dialog\" ng-style=\"{ 'position': $ctrl.isDialog ? 'absolute' : 'initial' }\">\r\n\r\n  <div class=\"panel panel-detail\" ng-style=\"{'border-color':$ctrl.getConfig().color}\">\r\n\r\n    <form class=\"form-horizontal\" ng-readonly=\"!$ctrl.isEditable\">\r\n      <div class=\"panel-heading\" ng-style=\"{'background-color':$ctrl.getConfig().color, 'border-color':$ctrl.getConfig().color}\">\r\n        <button type=\"button\" class=\"close pull-right\" ng-click=\"$ctrl.closeEditDialog('cancel', $close)\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n        <span class=\"pull-left avatar-container\">\r\n          <salaxy-avatar class=\"\" avatar=\"{ color: $ctrl.getConfig().color, initials: $ctrl.getConfig().iconText, entityType: 'company' }\">\r\n          </salaxy-avatar>\r\n        </span>\r\n        <h1 class=\"truncate\">{{ $ctrl.getConfig().label }}<span class=\"smaller\" ng-if=\"$ctrl.current.message\"> -\r\n            {{$ctrl.current.message}}</span></h1>\r\n        <p class=\"calc-text\">{{$ctrl.current.count}} <span ng-if=\"$ctrl.current.count\">&times;</span> {{$ctrl.current.price}}\r\n          <span class=\"result-text\">{{ $ctrl.getRowTotal($ctrl.current) | currency }}</span>\r\n        </p>\r\n        <a ng-show=\"$ctrl.getConfig().moreInfo || $ctrl.getConfig().incomeTypes.length > 0\" class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\">{{!showInfo ?\r\n          ('SALAXY.NG1.CalcRowsComponent.editDialog.showInfo' | sxyTranslate) : ('SALAXY.NG1.CalcRowsComponent.editDialog.hideInfo' | sxyTranslate)}}<i\r\n            class=\"fa fa-info-circle\"></i></a>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <p>{{ $ctrl.getConfig().descr }}\r\n          <!-- TODO: We should have full HTML formatting here instead of just white-space: pre-wrap -->\r\n          <span class=\"collapse\" ng-class=\"{show: showInfo}\" style=\"white-space: pre-wrap;\"><br>{{ $ctrl.getConfig().moreInfo }}</span>\r\n        </p>\r\n        <div ng-if=\"showInfo && $ctrl.getConfig().incomeTypes.length > 0\">\r\n          <p>{{'SALAXY.NG1.CalcRowsComponent.editDialog.incomeTypesInfo' | sxyTranslate}}:</p>\r\n          <uib-accordion close-others=\"true\" class=\"salaxy-accordion\">\r\n            <div uib-accordion-group class=\"\" is-open=\"status.open\" ng-repeat=\"type in $ctrl.getConfig().incomeTypes\">\r\n              <uib-accordion-heading>\r\n                {{$ctrl.getIrCodeDataWithCode(type).code}} {{$ctrl.getIrCodeDataWithCode(type).label}}<i class=\"pull-right fa\"\r\n                  ng-class=\"{'fa-chevron-up': status.open, 'fa-chevron-down': !status.open}\"></i>\r\n              </uib-accordion-heading>\r\n              <p>{{$ctrl.getIrCodeDataWithCode(type).description}}</p>\r\n            </div>\r\n          </uib-accordion>\r\n        </div>\r\n        <div>\r\n          <!-- TODO: The row specific UI's need to be refactored to a better structure soon. -->\r\n          <div ng-switch=\"$ctrl.current.rowType\">\r\n            <div ng-switch-when=\"salary|paidSickLeaveSalary|trainingSalary|monthlySalary|paidSickLeaveMonthlySalary|trainingMonthlySalary|compensation\"\r\n              ng-switch-when-separator=\"|\">\r\n              <!-- Row types that have count hidden, but should be shown in edit -->\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'amount') }}\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'price') }}\"  ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"irIncomeType\">\r\n              <ng-include src=\"'salaxy-components/calc/rows/CalcRows2019EditDialog-irIncomeType.html'\"></ng-include>\r\n            </div>\r\n            <div ng-switch-when=\"unionPayment\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionPaymentLabel\" label-type=\"horizontal\" enum=\"UnionPaymentKind\" hidden-options=\"other,undefined\"\r\n                require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"UnionPaymentKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <div class=\"alert alert-warning\" ng-if=\"$ctrl.current.data.kind == 'raksaNormal' ||  $ctrl.current.data.kind == 'raksaUnemploymentOnly'\">\r\n                <p sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.raksaInfo\"></p>\r\n              </div>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'percentage' || $ctrl.current.data.kind == 'raksaNormal' ||\r\n                $ctrl.current.data.kind == 'raksaUnemploymentOnly'\" required=\"true\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\" unit=\"percent\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.percentOfSalary\"\r\n                disabled=\"$ctrl.current.data.kind == 'raksaNormal' ||  $ctrl.current.data.kind == 'raksaUnemploymentOnly'\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind !='percentageAndLimits'\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.current.data.kind != 'fixed'\"\r\n                label=\"{{$ctrl.current.data.kind == 'fixed' ? ('SALAXY.NG1.CalcRowsComponent.editDialog.unionPaymentCount' | sxyTranslate) : ('SALAXY.NG1.CalcRowsComponent.editDialog.underTaxSalary' | sxyTranslate)}}\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'percentageAndLimits'\" required=\"true\" ng-model=\"$ctrl.current.data.paymentPercentage\" name=\"paymentPercentage\"\r\n                label-type=\"horizontal\" unit=\"percent\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.percentOfSalary\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind =='percentageAndLimits'\" ng-model=\"$ctrl.current.data.minimumPayment\" name=\"minimumPayment\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionPayment.minimumPayment\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind =='percentageAndLimits'\" ng-model=\"$ctrl.current.data.maximumPayment\" name=\"maximumPayment\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionPayment.maximumPayment\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n\r\n              <div class=\"row\">\r\n                <div class=\"input-info col-xs-offset-4 col-xs-8\">\r\n                  <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n                  <p class=\"small input-info-text with-icon\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.fillUnionPaymentInformation\"></p>\r\n                </div>\r\n              </div>\r\n              <salaxy-input ng-model=\"$ctrl.current.data.recipientFullName\" name=\"unionFullName\" label-type=\"horizontal\" require=\"false\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionLabel\"></salaxy-input>\r\n              <salaxy-input ng-model=\"$ctrl.current.data.iban\" name=\"unionIban\" label-type=\"horizontal\" require=\"false\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionIbanLabel\" sxy-iban>\r\n              </salaxy-input>\r\n              <salaxy-input ng-model=\"$ctrl.current.data.referenceNumber\" name=\"unionReferenceNumber\" label-type=\"horizontal\" require=\"false\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.unionReferenceNumberLabel\" sxy-bank-reference-fi></salaxy-input>\r\n            </div>\r\n            <div ng-switch-when=\"foreclosure\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureKindLabel\" label-type=\"horizontal\" enum=\"ForeclosureKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"ForeclosureKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-number ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\" unit=\"{{$ctrl.getConfig().amount.unit}}\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\" label=\"{{$ctrl.getConfig().amount.label}}\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.current.data.kind == 'periodic' || $ctrl.current.data.kind == 'nonPeriodic'\" label=\"{{$ctrl.getConfig().price.label}}\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" ng-model=\"$ctrl.current.data.periodLength\" name=\"periodLength\" label-type=\"horizontal\"\r\n                disabled=\"true\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosurePeriodLengthLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" ng-model=\"$ctrl.current.data.protectedPortionBase\" name=\"protectedPortionBase\"\r\n                label-type=\"horizontal\" require=\"true\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureprotectedPortionBaseLabel\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" ng-model=\"$ctrl.current.data.protectedPortionDependant\" name=\"protectedPortionDependant\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureprotectedPortionDependantLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" sxy-integer ng-model=\"$ctrl.current.data.dependantsCount\" name=\"dependantsCount\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosuredependantsCountLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" ng-model=\"$ctrl.current.data.incomeFromOtherSources\" name=\"incomeFromOtherSources\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureincomeFromOtherSourcesLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'periodic'\" ng-model=\"$ctrl.current.data.additionalAmountLeftToDebtor\" name=\"additionalAmountLeftToDebtor\"\r\n                label-type=\"horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureadditionalAmountLeftToDebtorLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n              </salaxy-input-number>\r\n              <div class=\"row\">\r\n                <div class=\"input-info col-xs-offset-4 col-xs-8\">\r\n                  <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n                  <p class=\"small input-info-text with-icon\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureReferenceNumberInfo\"></p>\r\n                </div>\r\n              </div>\r\n              <salaxy-input ng-model=\"$ctrl.current.data.referenceNumber\" name=\"referenceNumber\" label-type=\"horizontal\" require=\"false\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.foreclosureReferenceNumberLabel\" sxy-bank-reference-fi></salaxy-input>\r\n            </div>\r\n            <div ng-switch-when=\"totalWorkerPayment\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.totalWorkerPaymentKindLabel\" label-type=\"horizontal\" enum=\"TotalWorkerPaymentKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"TotalWorkerPaymentKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-number ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.totalWorkerSumLabel\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.totalWorkerCalculationRowTypeLabel\" label-type=\"horizontal\" enum=\"CalculationRowType\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"CalculationRowType\" ng-model=\"$ctrl.current.data.rowType\" filter=\"salary,monthlySalary\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <salaxy-input ng-model=\"$ctrl.current.data.message\" name=\"message\" label-type=\"horizontal\" require=\"false\"\r\n                label=\"SALAXY.NG1.CalcRowsComponent.editDialog.totalWorkerCalculationMessage\"></salaxy-input>\r\n            </div>\r\n            <div ng-switch-when=\"carBenefit\">\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.carBenefitCode\" label-type=\"horizontal\" enum=\"CarBenefitCode\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"CarBenefitCode\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.ageGroupCode\" label-type=\"horizontal\" enum=\"AgeGroupCode\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" hidden-options=\"undefined,u\" name=\"AgeGroupCode\" ng-model=\"$ctrl.current.data.ageGroup\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <salaxy-input-boolean type=\"checkbox\" name=\"isKilometersBased\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.kilometersBased\"\r\n                label-true=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.kilometersBasedTrue\" label-type=\"horizontal\" ng-model=\"$ctrl.current.data.isKilometersBased\">\r\n              </salaxy-input-boolean>\r\n              <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.kilometers\" ng-model=\"$ctrl.current.data.kilometers\" name=\"kilometers\"\r\n                label-type=\"horizontal\" require=\"true\" ng-if=\"$ctrl.current.data.isKilometersBased\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.deduction\" ng-model=\"$ctrl.current.data.deduction\" name=\"deduction\"\r\n                label-type=\"horizontal\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.carBenefit.emissionsValue\" ng-model=\"$ctrl.current.data.emissionsValue\" name=\"emissionsValue\"\r\n                label-type=\"horizontal\" minimum=\"0\" maximum=\"100\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"subsidisedCommute\">\r\n              <p sxy-html=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.info.html\"></p>\r\n              <div ng-init=\"$subsidisedCommute = $ctrl.getUsecaseLogic($ctrl.current)\">\r\n                <salaxy-input-number ng-change=\"$subsidisedCommute.updateUsecase()\" label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\"\r\n                  label-type=\"horizontal\" require=\"true\" disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\"\r\n                  ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n                <salaxy-input-enum ng-change=\"$subsidisedCommute.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.subsidisedCommuteKind\"\r\n                  label-type=\"horizontal\" enum=\"SubsidisedCommuteKind\" require=\"true\" name=\"SubsidisedCommuteKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n                </salaxy-input-enum>\r\n                <salaxy-input-number ng-change=\"$subsidisedCommute.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.deduction\"\r\n                  ng-model=\"$ctrl.current.data.deduction\" name=\"deduction\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-change=\"$subsidisedCommute.updateUsecase()\" ng-if=\"$ctrl.isEditable && !$subsidisedCommute.isBefore2021\"\r\n                  placeholder=\"{{$subsidisedCommute.calculatedTaxable | number : 2}}\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.taxable\"\r\n                  ng-model=\"$ctrl.current.data.taxable\" name=\"taxable\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"$ctrl.isEditable && !$subsidisedCommute.isBefore2021\" placeholder=\"{{$subsidisedCommute.calculatedTaxfree | number : 2}}\"\r\n                  disabled=\"true\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.taxfree\" ng-model=\"subsidisedCommuteForDisplayOnly\" name=\"taxfree\"\r\n                  label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"!$ctrl.isEditable && !$subsidisedCommute.isBefore2021\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.taxable\"\r\n                  ng-model=\"$subsidisedCommute.calculatedTaxable\" name=\"taxable\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"!$ctrl.isEditable && !$subsidisedCommute.isBefore2021\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.taxfree\"\r\n                  ng-model=\"$subsidisedCommute.calculatedTaxfree\" name=\"taxfree\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-change=\"$subsidisedCommute.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.subsidisedCommute.periodDivider\"\r\n                  ng-model=\"$ctrl.current.data.periodDivider\" name=\"periodDivider\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"bicycleBenefit\">\r\n              <div ng-init=\"$bicycleBenefit = $ctrl.getUsecaseLogic($ctrl.current)\">\r\n                <salaxy-input-number ng-change=\"$bicycleBenefit.updateUsecase()\" label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\"\r\n                  label-type=\"horizontal\" require=\"true\" disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\"\r\n                  ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n                <salaxy-input-enum ng-change=\"$bicycleBenefit.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.bicycleBenefitKind\"\r\n                  label-type=\"horizontal\" enum=\"BicycleBenefitKind\" require=\"true\" name=\"BicycleBenefitKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n                </salaxy-input-enum>\r\n                <salaxy-input-number ng-change=\"$bicycleBenefit.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.deduction\"\r\n                  ng-model=\"$ctrl.current.data.deduction\" name=\"deduction\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-change=\"$bicycleBenefit.updateUsecase()\" ng-if=\"$ctrl.isEditable\" placeholder=\"{{$bicycleBenefit.calculatedTaxable | number : 2}}\"\r\n                  label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.taxable\" ng-model=\"$ctrl.current.data.taxable\" name=\"taxable\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"$ctrl.isEditable\" placeholder=\"{{$bicycleBenefit.calculatedTaxfree | number : 2}}\" disabled=\"true\"\r\n                  label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.taxfree\" ng-model=\"bicycleBenefitForDisplayOnly\" name=\"taxfree\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"!$ctrl.isEditable\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.taxable\" ng-model=\"$bicycleBenefit.calculatedTaxable\"\r\n                  name=\"taxable\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-if=\"!$ctrl.isEditable\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.taxfree\" ng-model=\"$bicycleBenefit.calculatedTaxfree\"\r\n                  name=\"taxfree\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'noDeduction' || $ctrl.current.data.kind == 'singleDeduction' || $ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n                <salaxy-input-number ng-change=\"$bicycleBenefit.updateUsecase()\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.bicycleBenefit.periodDivider\"\r\n                  ng-model=\"$ctrl.current.data.periodDivider\" name=\"periodDivider\" label-type=\"horizontal\"\r\n                  ng-if=\"$ctrl.current.data.kind == 'periodicalDeduction'\"></salaxy-input-number>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"nonProfitOrg\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.nonProfitOrg.profitOrgKind\" label-type=\"horizontal\" enum=\"NonProfitOrgKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"NonProfitOrgKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"dailyAllowance\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.dailyAllowance.allowanceKind\" hidden-options=\"mealAllowance\" label-type=\"horizontal\"\r\n                enum=\"DailyAllowanceKind\" require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"DailyAllowanceKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.dailyAllowance.internationalDailyAllowanceCount\" label-type=\"horizontal\"\r\n                ng-if=\"$ctrl.current.data.kind === 'internationalDailyAllowance'\" options=\"$ctrl.dailyAllowanceRegions\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"\r\n                name=\"country\" ng-model=\"$ctrl.current.data.country\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"mealBenefit\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealBenefitKind\" label-type=\"horizontal\" enum=\"MealBenefitKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"MealBenefitKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <p ng-if=\"$ctrl.current.data.kind\" sxy-text=\"{{'SALAXY.ENUM.MealBenefitKind.' + $ctrl.current.data.kind + '.descriptionWithYearlyNumbers'}}\"\r\n                params=\"$ctrl.yearlySideCosts\"></p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <div ng-switch=\"$ctrl.current.data.kind\">\r\n                <div ng-switch-when=\"mealAllowance\">\r\n                  <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealPrice\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\"\r\n                    ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\" disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-number>\r\n                </div>\r\n                <div ng-switch-when=\"taxableAmount|collectedReimbursement|undefined\" ng-switch-when-separator=\"|\">\r\n                  <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealTaxablePrice\" ng-model=\"$ctrl.current.price\" name=\"price\"\r\n                    label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\" disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-number>\r\n                </div>\r\n                <div ng-switch-when=\"mealTicket\">\r\n                  <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealTicketPrice\" ng-model=\"$ctrl.current.price\" name=\"price\"\r\n                    label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\" disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-number>\r\n                </div>\r\n                <div ng-switch-when=\"cateringContract|institute|restaurantWorker|teacher\" ng-switch-when-separator=\"|\">\r\n                  <salaxy-input-number disabled=\"true\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealTaxablePrice\" ng-model=\"$ctrl.current.price\" name=\"price\"\r\n                    label-type=\"horizontal\"></salaxy-input-number>\r\n                </div>\r\n              </div>\r\n              <div ng-if=\"$ctrl.current.data.kind != 'mealAllowance'\">\r\n                <salaxy-form-group ng-if=\"$ctrl.current.data.kind != 'collectedReimbursement'\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.mealPriceAmount\"\r\n                  name=\"taxablePrice\" label-type=\"horizontal\">\r\n                  <label class=\"control-label\">{{ $ctrl.current.data.taxablePrice * ($ctrl.current.count || 1.0) | currency }}</label>\r\n                </salaxy-form-group>\r\n                <salaxy-input-boolean ng-if=\"$ctrl.current.data.kind != 'collectedReimbursement'\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.workerDeduction\"\r\n                  label-true=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.taxValueTrue\" label-false=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.taxValueFalse\"\r\n                  name=\"isTaxValue\" type=\"radio\" ng-model=\"$ctrl.current.data.isTaxValue\" label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\"\r\n                  disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-boolean>\r\n                <salaxy-input-boolean ng-if=\"$ctrl.current.data.kind != 'collectedReimbursement' && $ctrl.current.data.isTaxValue\"\r\n                  label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.isTaxValueDeductionDone\"\r\n                  label-true=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.isTaxValueDeductionDoneTrue\"\r\n                  label-false=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.isTaxValueDeductionDoneFalse\" name=\"isTaxValueDeductionDone\" type=\"radio\"\r\n                  ng-model=\"$ctrl.current.data.isTaxValueDeductionDone\" label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\"\r\n                  disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-boolean>\r\n                <salaxy-form-group ng-if=\"$ctrl.current.data.isTaxValue\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.deduction\" name=\"deductionWhenTaxValue\"\r\n                  label-type=\"horizontal\">\r\n                  <label class=\"control-label\">{{ $ctrl.current.data.taxablePrice * ($ctrl.current.count || 1.0) | currency }}</label>\r\n                </salaxy-form-group>\r\n                <salaxy-input-number ng-if=\"$ctrl.current.data.kind != 'collectedReimbursement' && !$ctrl.current.data.isTaxValue\"\r\n                  label=\"SALAXY.NG1.CalcRowsComponent.editDialog.mealBenefit.deduction\" ng-model=\"$ctrl.current.data.deduction\" name=\"deduction\" label-type=\"horizontal\"\r\n                  ng-change=\"$ctrl.updateUsecase($ctrl.current)\" disabled=\"$ctrl.isDisabled($ctrl.current)\"></salaxy-input-number>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"board\">\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"remuneration\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.remuneration.remunerationKind\" label-type=\"horizontal\" enum=\"RemunerationKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"RemunerationKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <p>{{ \"RemunerationKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number ng-if=\"$ctrl.getConfig().amount.units.length > 1\" on-unit-change=\"$ctrl.current.unit=unit\" label=\"{{$ctrl.getConfig().amount.label}}\"\r\n                ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\" unit=\"{{$ctrl.ensureUnit($ctrl.current)}}\" units=\"$ctrl.getConfig().amount.units\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"!($ctrl.getConfig().amount.units.length > 1)\" label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\"\r\n                label-type=\"horizontal\" unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\"\r\n                ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"otherCompensation\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.otherCompensation.compensationKind\" label-type=\"horizontal\" enum=\"OtherCompensationKind\"\r\n                require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"OtherCompensationKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <p>{{ \"OtherCompensationKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"workingTimeCompensation\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.workingTimeCompensation.compensationKind\" label-type=\"horizontal\" enum=\"WorkingTimeCompensationKind\"\r\n                require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"WorkingTimeCompensation\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <p>{{ \"WorkingTimeCompensationKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"employmentTermination\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.employmentTermination.employmentTerminationKind\" label-type=\"horizontal\"\r\n                enum=\"EmploymentTerminationKind\" require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"EmploymentTermination\" ng-model=\"$ctrl.current.data.kind\"\r\n                type=\"select\"></salaxy-input-enum>\r\n              <p>{{ \"EmploymentTerminationKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"paidSickLeave\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.paidSickLeave.paidSickLeaveKind\" label-type=\"horizontal\" enum=\"PaidSickLeaveKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"PaidSickLeaveKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <p>{{ \"PaidSickLeaveKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"training\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.training.trainingKind\" label-type=\"horizontal\" enum=\"TrainingKind\" require=\"true\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"TrainingKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <p>{{ \"TrainingKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"hourlySalaryWithWorkingTimeCompensation\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.WorkingTimeCompensationKind\" label-type=\"horizontal\" enum=\"WorkingTimeCompensationKind\"\r\n                require=\"true\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"HourlySalaryWithWorkingTimeCompensation\" ng-model=\"$ctrl.current.data.kind\" type=\"select\">\r\n              </salaxy-input-enum>\r\n              <p>{{ \"WorkingTimeCompensationKind.\" + $ctrl.current.data.kind | sxyEnumDescr }}</p>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"1\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"\r\n                ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <style>\r\n                div.input-group-addon {\r\n                  display: none;\r\n                }\r\n\r\n                div.input-group {\r\n                  width: 100%\r\n                }\r\n              </style>\r\n              <div>\r\n                <salaxy-input label=\"SALAXY.NG1.CalcRowsComponent.editDialog.additionalRows.description\" label-type=\"horizontal\" disabled=\"$ctrl.isDisabled($ctrl.current)\"\r\n                  ng-model=\"$ctrl.current.message\" name=\"message\" placeholder=\"{{$ctrl.getMessagePlaceholderText($ctrl.current)}}\"></salaxy-input>\r\n              </div>\r\n              <hr>\r\n              <div ng-repeat=\"cr in $ctrl.current.data.compensationRows\">\r\n                <salaxy-input-number label=\"SALAXY.NG1.CalcRowsComponent.editDialog.hourlySalaryWithWorkingTimeCompensationRowCountLabel\" ng-model=\"cr.count\" name=\"crCount\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"{{$ctrl.current.count || 1}}\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"\r\n                ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\"></salaxy-input-number>\r\n                <salaxy-form-group name=\"compensationRow\" label-type=\"form-horizontal\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.hourlySalaryWithWorkingTimeCompensationRowLabel\" required=\"true\">\r\n                  <div class=\"input-group\">\r\n                    <salaxy-input-number ng-if=\"$ctrl.current.data.pricing == 'percent'\" ng-model=\"cr.percent\" name=\"percent\" label-type=\"plain\" require=\"true\" unit=\"percent\"\r\n                      ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n                    <salaxy-input-number ng-if=\"$ctrl.current.data.pricing != 'percent'\" ng-model=\"cr.price\" name=\"price\" label-type=\"plain\" require=\"true\"\r\n                      ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n                    <div class=\"input-group-btn\" uib-dropdown>\r\n                      <button id=\"compUnit\" type=\"button\" class=\"btn btn-primary\" uib-dropdown-toggle>\r\n                        {{ $ctrl.current.data.pricing == 'percent'? \"%\": \"€\" }} <span class=\"caret\"></span>\r\n                      </button>\r\n                      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"compUnit\">\r\n                        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.current.data.pricing = 'percent';$ctrl.updateUsecase($ctrl.current)\">%</a></li>\r\n                        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.current.data.pricing = 'fixed';$ctrl.updateUsecase($ctrl.current)\">€</a></li>\r\n                      </ul>\r\n                    </div>\r\n                  </div>\r\n                </salaxy-form-group>\r\n                <salaxy-input label=\"SALAXY.NG1.CalcRowsComponent.editDialog.hourlySalaryWithWorkingTimeCompensationRowMessageLabel\" label-type=\"horizontal\" disabled=\"$ctrl.isDisabled($ctrl.current)\"\r\n                  ng-model=\"cr.message\" name=\"crMessage\" placeholder=\"{{ 'WorkingTimeCompensationKind.' + $ctrl.current.data.kind | sxyEnum }}\"></salaxy-input>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"milageOwnCar\">\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.milageOwnCar.vehicleType\" label-type=\"horizontal\" options=\"$ctrl.getVehicleTypeSelection()\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"vehicleType\" ng-model=\"$ctrl.current.data.vehicleType\" type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-enum ng-if=\"$ctrl.current.data.additionsAllowed\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.milageOwnCar.additions\" label-type=\"horizontal\"\r\n                options=\"$ctrl.getVehicleAdditions()\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"additions\" ng-model=\"$ctrl.current.data.additions\"\r\n                type=\"select\"></salaxy-input-enum>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.passengersAllowed\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.milageOwnCar.passangerCount\" unit=\"count\"\r\n                label-type=\"horizontal\" ng-model=\"$ctrl.current.data.passengerCount\" name=\"passengerCount\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\"\r\n                disabled=\"$ctrl.current.data.vehicleType != 'custom'\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n            </div>\r\n            <div ng-switch-when=\"taxAtSource\">\r\n              <salaxy-input-number label=\"Palkkasumma ennen vähennystä\" ng-model=\"$ctrl.current.data.totalTaxable\" name=\"totalTaxable\" label-type=\"horizontal\"\r\n                disabled=\"true\"></salaxy-input-number>\r\n              <salaxy-input-enum label=\"Vähennyksen tyyppi\" filter=\"{{ $ctrl.current.data.allowedKinds }}\" label-type=\"horizontal\" enum=\"TaxAtSourceKind\"\r\n                ng-change=\"$ctrl.updateUsecase($ctrl.current)\" name=\"taxAtSourceKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <div ng-if=\"$ctrl.current.data.kind == 'monthlyDeduction' || $ctrl.current.data.kind == 'dailyDeduction'\" class=\"input-info col-xs-offset-4 col-xs-8\">\r\n                <p>{{ $ctrl.current.data.deductionCount | sxyCount }} * {{ $ctrl.current.data.deductionPrice | currency }} = {{ $ctrl.current.data.deduction | currency }}</p>\r\n              </div>\r\n              <div ng-if=\"$ctrl.current.data.kind == 'fixedValues'\">\r\n                <salaxy-input-number label=\"Kiinteä vähennys\" ng-model=\"$ctrl.current.data.deduction\" name=\"deduction\" unit=\"eur\" label-type=\"horizontal\"\r\n                  ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n                <salaxy-input-number label=\"Kiinteä lähdevero\" ng-model=\"$ctrl.current.data.taxValue\" name=\"taxValue\" unit=\"eur\" label-type=\"horizontal\"\r\n                  ng-change=\"$ctrl.updateUsecase($ctrl.current)\"></salaxy-input-number>\r\n              </div>\r\n              <div ng-if=\"$ctrl.current.data.kind != 'fixedValues'\">\r\n                <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\"\r\n                  ng-change=\"$ctrl.updateUsecase($ctrl.current)\" disabled=\"true\"></salaxy-input-number>\r\n                <salaxy-input-number label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                  unit=\"{{$ctrl.getConfig().amount.unit}}\" disabled=\"true\"></salaxy-input-number>\r\n                <salaxy-input-number label=\"Lähdevero\" ng-model=\"$ctrl.current.data.taxValue\" name=\"taxValue\" label-type=\"horizontal\" unit=\"eur\"\r\n                  disabled=\"true\"></salaxy-input-number>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"taxWithholding\">\r\n              <salaxy-input-enum label=\"SALAXY.ENUM.TaxWithholdingKind.label\" label-type=\"horizontal\" enum=\"TaxWithholdingKind\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\"\r\n                name=\"taxWithholdingKind\" ng-model=\"$ctrl.current.data.kind\" type=\"select\"></salaxy-input-enum>\r\n              <div ng-switch=\"$ctrl.current.data.kind\">\r\n                <salaxy-input-number ng-switch-when=\"percentage\" label=\"SALAXY.ENUM.TaxWithholdingKind.percentage.label\" ng-model=\"$ctrl.current.data.taxValue\" name=\"percentage\"\r\n                  label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\" unit=\"percent\"></salaxy-input-number>\r\n                <salaxy-input-number ng-switch-when=\"fixedValue\" label=\"SALAXY.ENUM.TaxWithholdingKind.fixedValue.label\" ng-model=\"$ctrl.current.data.taxValue\" name=\"fixedvalue\"\r\n                  label-type=\"horizontal\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\" require=\"true\" unit=\"eur\"></salaxy-input-number>\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"absencePeriod\" ng-init=\"$absencesLogic = $ctrl.getUsecaseLogic($ctrl.current)\">\r\n              <salaxy-input-enum name=\"causeCode\" ng-model=\"$ctrl.current.data.kind\" enum=\"AbsenceCauseCode\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.absencesId.title\"\r\n                type=\"typeahead\" ng-change=\"$absencesLogic.updateIsPaid($ctrl.current)\" require=\"true\"></salaxy-input-enum>\r\n              <salaxy-datepicker-popup name=\"start\" ng-model=\"$ctrl.current.period.start\" ng-change=\"$absencesLogic.updatePeriodDays($ctrl.current)\"\r\n                label=\"SALAXY.MODEL.DateRange.start.title\"></salaxy-datepicker-popup>\r\n              <salaxy-datepicker-popup name=\"end\" ng-model=\"$ctrl.current.period.end\" ng-change=\"$absencesLogic.updatePeriodDays($ctrl.current)\"\r\n                label=\"SALAXY.MODEL.DateRange.end.title\"></salaxy-datepicker-popup>\r\n              <salaxy-form-group name=\"daysCount\" label=\"SALAXY.MODEL.DateRange.daysCount.title\" ng-if=\"$ctrl.current.period.days == null\">\r\n                <div class=\"input-group\">\r\n                  <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"daysCount\" name=\"daysCount\" ng-model=\"$ctrl.current.period.daysCount\" disabled>\r\n                  <span class=\"input-group-btn\">\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$absencesLogic.setDaysSelection($ctrl.current)\"\r\n                      sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.editDatesButtonText\"></button>\r\n                  </span>\r\n                </div>\r\n              </salaxy-form-group>\r\n              <salaxy-date-range ng-model=\"$ctrl.current.period\" name=\"days\" mode=\"multiple\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.period.title\"\r\n                min-date=\"$ctrl.current.period.start\" max-date=\"$ctrl.current.period.end\" ng-if=\"$ctrl.current.period.days != null\"></salaxy-date-range>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.kind == 'annualLeave'\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.bonusDaysCount.title\" ng-model=\"$ctrl.current.data.bonusDaysCount\" name=\"bonusDaysCount\" label-type=\"horizontal\">\r\n                </salaxy-input-number>\r\n              <salaxy-input-boolean ng-init=\"$ctrl.current.data.applyPricing = ($ctrl.current.data.applyPricing || false)\" type=\"radio\" name=\"applyPricing\" label=\"SALAXY.MODEL.AbsencePeriodUsecase.applyPricing.title\"\r\n              label-true=\"SALAXY.MODEL.AbsencePeriodUsecase.applyPricing.labelTrue\"\r\n              label-false=\"SALAXY.MODEL.AbsencePeriodUsecase.applyPricing.labelFalse\"\r\n              ng-model=\"$ctrl.current.data.applyPricing\"></salaxy-input-boolean>\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n               placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'price') }}\"  ng-if=\"!$ctrl.current.data.applyPricing\"></salaxy-input-number>\r\n              \r\n              <salaxy-input-boolean type=\"checkbox\" name=\"isPaid\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.isPaid.title\"\r\n                label-true=\"SALAXY.NG1.AbsencePeriodsEditDialog.label.isPaidLabelTrue\" disabled=\"!$absencesLogic.canSelectIsPaid($ctrl.current)\" ng-model=\"$ctrl.current.data.isPaid\"\r\n                ng-change=\"$ctrl.logic.updateIsHolidayAccrual($ctrl.current)\"></salaxy-input-boolean>\r\n\r\n              <salaxy-input-boolean type=\"checkbox\" name=\"isHolidayAccrual\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.isHolidayAccrual.title\"\r\n                label-true=\"SALAXY.NG1.AbsencePeriodsEditDialog.label.isAccrualLabelTrue\" ng-model=\"$ctrl.current.data.isHolidayAccrual\"></salaxy-input-boolean>\r\n             \r\n            </div>\r\n            <div ng-switch-when=\"expenses\" ng-init=\"$expenseLogic = $ctrl.getUsecaseLogic($ctrl.current)\">\r\n              <salaxy-input-number label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\"\r\n                require=\"true\"></salaxy-input-number>\r\n              <salaxy-input-enum label=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercent.label\" label-type=\"horizontal\" enum=\"ExpensesVatRate\"\r\n                hidden-options=\"undefined\" require=\"true\" ng-change=\"$expenseLogic.updateUsecase($ctrl.current)\" name=\"ExpensesVatRate\" ng-model=\"$ctrl.current.data.vatRate\"\r\n                type=\"select\"></salaxy-input-enum>\r\n\r\n              <div ng-switch=\"$ctrl.current.data.vatRate\">\r\n                <span ng-switch-when=\"tax255\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p255.description\"></span>\r\n                <span ng-switch-when=\"tax24\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p24.description\"></span>\r\n                <span ng-switch-when=\"tax14\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p14.description\"></span>\r\n                <span ng-switch-when=\"tax10\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p10.description\"></span>\r\n                <span ng-switch-when=\"tax0\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p0.description\"></span>\r\n              </div>\r\n              <div ng-if=\"$ctrl.current.data.vatRate == 'multiple'\">\r\n                <p class=\"mb-0\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercentsTable.taxableAmountInPercent\" ps=\":\"></p>\r\n                <div class=\"row\">\r\n                  <salaxy-input-number class=\"col-sm-3\" label=\"25,5%\" label-type=\"basic\" name=\"inpt5\" ng-model=\"$ctrl.current.accounting.vatEntries[4].gross\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n                  <salaxy-input-number class=\"col-sm-3\" label=\"24%\" label-type=\"basic\" name=\"inpt1\" ng-model=\"$ctrl.current.accounting.vatEntries[0].gross\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n                  <salaxy-input-number class=\"col-sm-3\" label=\"14%\" label-type=\"basic\" name=\"inpt2\" ng-model=\"$ctrl.current.accounting.vatEntries[1].gross\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n                  <salaxy-input-number class=\"col-sm-3\" label=\"10%\" label-type=\"basic\" name=\"inpt3\" ng-model=\"$ctrl.current.accounting.vatEntries[2].gross\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n                  <salaxy-input-number class=\"col-sm-3\" label=\"0%\" label-type=\"basic\" name=\"inpt4\" ng-model=\"$ctrl.current.accounting.vatEntries[3].gross\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n                </div>              \r\n              </div>\r\n              <salaxy-input-number ng-if=\"$ctrl.current.data.vatRate == 'other'\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercent.label\" label-type=\"horizontal\" name=\"vatRate\" ng-model=\"$ctrl.current.accounting.vatPercent\" unit=\"percent\" ng-change=\"$expenseLogic.updateUsecase()\"></salaxy-input-number>\r\n              <div ng-if=\"$expenseLogic.hasGrossVatEntries\">\r\n                <div class=\"row\">\r\n                  <div class=\"col-xs-12\">\r\n                    <table class=\"table table-sm table-striped\" style=\"font-size: 0.8em\">\r\n                      <thead>\r\n                        <tr>\r\n                          <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercentsTable.vatRate\"></th>\r\n                          <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercentsTable.exemptFromTaxation\" class=\"right\"></th>\r\n                          <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercentsTable.tax\" class=\"right\"></th>\r\n                          <th sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercentsTable.taxable\" class=\"right\"></th>\r\n                        </tr>\r\n                      </thead>\r\n                      <tbody>\r\n                        <tr ng-repeat=\"item in $ctrl.current.accounting.vatEntries\">\r\n                          <td ng-if=\"!!item.gross\">{{ \"VatRate.\" + item.vatRate | sxyEnum }}</td>\r\n                          <td ng-if=\"!!item.gross\" class=\"right\">{{ item.net | currency }}</td>\r\n                          <td ng-if=\"!!item.gross\" class=\"right\">{{ item.tax | currency }}</td>\r\n                          <td ng-if=\"!!item.gross\" class=\"right\">{{ item.gross | currency }}</td>\r\n                        </tr>\r\n                        <tr ng-if=\"$ctrl.current.data.total\" class=\"total\">\r\n                          <th sxy-text=\"SALAXY.UI_Terms.total\"></th>\r\n                          <td class=\"right\">{{ $ctrl.current.data.total.net | currency}}</td>\r\n                          <td class=\"right\">{{ $ctrl.current.data.total.tax | currency}}</td>\r\n                          <td class=\"right\">{{ $ctrl.current.data.total.gross | currency}}</td>\r\n                        </tr>\r\n                      </tbody>\r\n                    </table>\r\n\r\n                  </div>\r\n                </div>\r\n                <salaxy-datepicker-popup name=\"startDate\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.date\"\r\n                  ng-model=\"$ctrl.current.data.date\"></salaxy-datepicker-popup>\r\n              </div>\r\n              <salaxy-form-group name=\"receiptImage\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.receiptUrlAddress\">\r\n                <div class=\"input-group\">\r\n                  <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"file\" name=\"file\" ng-model=\"$ctrl.current.data.fileUrl\">\r\n                  <span class=\"input-group-btn\">\r\n                    <a class=\"btn btn-default\" ng-disabled=\"!$ctrl.showImagePreview()\" ng-href=\"{{$ctrl.current.data.fileUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.open\"></a>\r\n                  </span>\r\n                </div>\r\n              </salaxy-form-group>\r\n              <div class=\"text-center\" style=\"margin-bottom: 10px;\" ng-if=\"$ctrl.showImagePreview()\">\r\n                <img style=\"max-width: 560px; max-height: 200px;\" ng-src=\"{{$ctrl.current.data.fileUrl}}\">\r\n              </div>\r\n            </div>\r\n            <div ng-switch-when=\"holidayBonus|holidaySalary|holidayCompensation\" ng-switch-when-separator=\"|\" ng-init=\"$holidaysLogic = $ctrl.getUsecaseLogic($ctrl.current)\">\r\n              <salaxy-input-number ng-if=\"$ctrl.getConfig().amount.units.length > 1\" label=\"SALAXY.UI_Terms.amount\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.ensureUnit($ctrl.current)}}\" units=\"$ctrl.getConfig().amount.units\" on-unit-change=\"$ctrl.current.unit=unit\" \r\n                 disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number  ng-if=\"!($ctrl.getConfig().amount.units.length > 1)\" label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'price') }}\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n              <salaxy-input-number  ng-if=\"$ctrl.getConfig().amount.units.length > 1\" label=\"SALAXY.UI_Terms.price\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                  disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n              <salaxy-datepicker-popup name=\"start\" ng-model=\"$ctrl.current.period.start\" ng-change=\"$holidaysLogic.updatePeriodDays($ctrl.current)\"\r\n              label=\"SALAXY.MODEL.DateRange.start.title\"></salaxy-datepicker-popup>\r\n              <salaxy-datepicker-popup name=\"end\" ng-model=\"$ctrl.current.period.end\" ng-change=\"$holidaysLogic.updatePeriodDays($ctrl.current)\"\r\n                label=\"SALAXY.MODEL.DateRange.end.title\"></salaxy-datepicker-popup>\r\n              <salaxy-form-group name=\"daysCount\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelHolidaysCount\" ng-if=\"!$ctrl.current.period.days || $ctrl.current.period.days.length == 0\">\r\n                <div class=\"input-group\">\r\n                  <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"daysCount\" name=\"daysCount\" ng-model=\"$ctrl.current.period.daysCount\" disabled>\r\n                  <span class=\"input-group-btn\">\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$holidaysLogic.setDaysSelection($ctrl.current)\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.editDatesButtonText\"></button>\r\n                  </span>\r\n                </div>\r\n              </salaxy-form-group>\r\n              <salaxy-date-range ng-model=\"$ctrl.current.period\" name=\"days\" mode=\"multiple\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelHolidaysCount\" min-date=\"$ctrl.current.period.start\" max-date=\"$ctrl.current.period.end\" ng-if=\"$ctrl.current.period.days.length > 0\"></salaxy-date-range>\r\n            </div>\r\n            <div ng-switch-default>\r\n              <salaxy-input-number ng-if=\"!($ctrl.getConfig().amount.units.length > 1)\" label=\"{{$ctrl.getConfig().amount.label}}\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.getConfig().amount.unit}}\" placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'amount') }}\" disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number ng-if=\"$ctrl.getConfig().amount.units.length > 1\" label=\"SALAXY.UI_Terms.amount\" ng-model=\"$ctrl.current.count\" name=\"count\" label-type=\"horizontal\"\r\n                unit=\"{{$ctrl.ensureUnit($ctrl.current)}}\" units=\"$ctrl.getConfig().amount.units\" on-unit-change=\"$ctrl.current.unit=unit\" \r\n                 disabled=\"$ctrl.isDisabled($ctrl.current, 'amount')\" ng-if=\"$ctrl.getConfig().amount.input != 'hidden'\">\r\n              </salaxy-input-number>\r\n              <salaxy-input-number  ng-if=\"!($ctrl.getConfig().amount.units.length > 1)\" label=\"{{$ctrl.getConfig().price.label}}\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" placeholder=\"{{ $ctrl.getPlaceholderText($ctrl.current, 'price') }}\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n              <salaxy-input-number  ng-if=\"$ctrl.getConfig().amount.units.length > 1\" label=\"SALAXY.UI_Terms.price\" ng-model=\"$ctrl.current.price\" name=\"price\" label-type=\"horizontal\" require=\"true\"\r\n                  disabled=\"$ctrl.isDisabled($ctrl.current, 'price')\" ng-if=\"$ctrl.getConfig().price.input != 'hidden'\"></salaxy-input-number>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.current.rowType == 'prepaidExpenses'\">\r\n            <salaxy-form-group name=\"vatPercentGroup\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercent.label\" label-type=\"horizontal\">\r\n              <select id=\"vatPercent\" name=\"vatPercent\" ng-model=\"$ctrl.current.data.accounting.vatPercent\" class=\"form-control\" ng-change=\"$ctrl.updateUsecase($ctrl.current)\">\r\n                <option ng-value='' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.pempty.label\"></option>\r\n                <option ng-value='0.255' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p255.label\"></option>\r\n                <option ng-value='0.24' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p24.label\"></option>\r\n                <option ng-value='0.14' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p14.label\"></option>\r\n                <option ng-value='0.1' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p10.label\"></option>\r\n                <option ng-value='0' sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p0.label\"></option>\r\n              </select>\r\n              <div ng-switch=\"$ctrl.current.data.accounting.vatPercent\">\r\n                <span ng-switch-when=\"0.255\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p255.description\"></span>\r\n                <span ng-switch-when=\"0.24\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p24.description\"></span>\r\n                <span ng-switch-when=\"0.14\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p14.description\"></span>\r\n                <span ng-switch-when=\"0.1\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p10.description\"></span>\r\n                <span ng-switch-when=\"0\" class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.p0.description\"></span>\r\n                <span ng-switch-default class=\"text-success small\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.accounting.vatPercents.pempty.label\"></span>\r\n              </div>\r\n            </salaxy-form-group>\r\n          </div>\r\n          <div ng-if=\"$ctrl.current.rowType != 'irIncomeType'\">\r\n            <hr>\r\n            <salaxy-input ng-if=\"$ctrl.current.rowType != 'hourlySalaryWithWorkingTimeCompensation'\" label=\"SALAXY.NG1.CalcRowsComponent.editDialog.additionalRows.description\" label-type=\"horizontal\" disabled=\"$ctrl.isDisabled($ctrl.current)\"\r\n              ng-model=\"$ctrl.current.message\" name=\"message\" placeholder=\"{{$ctrl.getMessagePlaceholderText($ctrl.current)}}\"></salaxy-input>\r\n            <salaxy-input label=\"SALAXY.NG1.CalcRowsComponent.editDialog.additionalRows.additionalRow\" label-type=\"horizontal\" disabled=\"$ctrl.isDisabled($ctrl.current)\"\r\n              ng-model=\"$ctrl.current.data.sxySalarySlipRowComment\" name=\"sxySalarySlipRowComment\"></salaxy-input>\r\n          </div>\r\n          <div ng-if=\"$ctrl.isStandAlone && $ctrl.current.rowType != 'absencePeriod'\">\r\n             <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.DateRange.labelStartAndEndDate\"></legend>\r\n              <salaxy-datepicker-popup label=\"SALAXY.MODEL.DateRange.start.title\" name=\"salaryDate\" ng-model=\"$ctrl.current.period.start\"></salaxy-datepicker-popup>\r\n              <salaxy-datepicker-popup label=\"SALAXY.MODEL.DateRange.end.title\" name=\"salaryDate\" ng-model=\"$ctrl.current.period.end\"></salaxy-datepicker-popup>\r\n             </fieldset>\r\n          </div>\r\n          <div ng-if=\"$ctrl.current.rowType != 'taxAtSource'\">\r\n            <salaxy-calc-row-cost-accounting calc=\"$ctrl.parent\" row=\"$ctrl.current\" dimensions=\"$ctrl.dimensions\"></salaxy-calc-row-cost-accounting>\r\n          </div>\r\n        </div>        \r\n        <div class=\"text-right\" ng-if=\"$ctrl.isEditable && !$ctrl.definitionEditor.mode\">\r\n          <button type=\"button\" class=\"btn btn-danger pull-left\" ng-click=\"$ctrl.closeEditDialog('delete-no-save', $close)\"\r\n            sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.buttons.delete\"></button>\r\n          <button type=\"button\" ng-if=\"$ctrl.isDialog\" class=\"btn btn-default\" ng-click=\"$ctrl.closeEditDialog('cancel', $close)\"\r\n            sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.buttons.cancel\"></button>\r\n          <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$ctrl.closeEditDialog('ok-no-save', $close)\"\r\n            sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.buttons.save\"></button>\r\n        </div>\r\n        <div ng-if=\"!$ctrl.isEditable\" class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.closeEditDialog('cancel', $close)\"\r\n            sxy-text=\"SALAXY.NG1.CalcRowsComponent.editDialog.buttons.close\"></button>\r\n        </div>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcRows2019Editor.html\",`<div class=\"salaxy-component salaxy-calc-rows-editor salaxy-calc-rows-2019-editor\">\r\n\r\n  <div ng-if=\"$ctrl.isInEdit\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"42px\" class=\"hidden-xxs th-avatar\"></th>\r\n          <th width=\"40%\" class=\"uppercase th-calc-row-type\">{{ $ctrl.title }}</th>\r\n          <th ng-if=\"$ctrl.showDimension()\" colspan=\"{{$ctrl.dimensionsCountToShow() + 1}}\" sxy-text=\"SALAXY.MODEL.CostAccountingSettings.title\"></th>\r\n          <th class=\"right\" ng-if=\"$ctrl.hasRows\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.amount\"></th>\r\n          <th class=\"right\" ng-if=\"$ctrl.hasRows\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.price\"></th>\r\n          <th class=\"right th-row-total\" ng-if=\"$ctrl.hasRows\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.total\"></th>\r\n          <th colspan=\"3\" ng-if=\"!$ctrl.hasRows\">&nbsp;</th>\r\n          <th class=\"salaxy-calc-rows-editor-btns\">\r\n            <span ng-if=\"$ctrl.showEditButtons\">\r\n              <button class=\"btn btn-sm btn-transparent\" ng-click=\"$ctrl.commit()\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.okIcon' | sxyTranslate}}\">\r\n                <i class=\"fa fa-check text-success\"></i>\r\n              </button>\r\n              <button class=\"btn btn-sm btn-transparent\" ng-click=\"$ctrl.reset()\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.cancelIcon' | sxyTranslate}}\">\r\n                <i class=\"fa fa-times\"></i>\r\n              </button>\r\n            </span>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat-start=\"row in $ctrl.filteredList track by $index\" ng-class=\"$ctrl.getValidation(row).type ? 'row-before-validation' : ''\">\r\n          <td width=\"42px\" class=\"hidden-xxs td-avatar\" ng-class=\"{'td-no-avatar' : !row.rowType}\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td width=\"40%\" class=\"td-calc-row-type\" ng-class=\"{'td-add-new': !row.rowType}\">\r\n            <salaxy-calc-row-type ng-if=\"!row.rowType\" name=\"rowType\" model=\"row\" row-types=\"$ctrl.rowTypes\" categories=\"$ctrl.categories\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\" on-row-changed=\"$ctrl.rowTypeChanged(row)\"></salaxy-calc-row-type>\r\n            <input class=\"form-control\" ng-if=\"row.rowType\" name=\"message\" type=\"text\" ng-model=\"row.message\" ng-disabled=\"$ctrl.isDisabled(row, 'message')\" placeholder=\"{{$ctrl.getMessagePlaceholderText(row)}}\" />\r\n          </td>\r\n          <td  ng-if=\"$ctrl.showDimension()\" ng-repeat=\"definition in $ctrl.getDimensionsToShow(row)\">\r\n            <div style=\"min-width: 100px\" class=\"truncate\">\r\n              <salaxy-calc-row-dimension-input row=\"row\" definition=\"definition\" inherited=\"$ctrl.parent.accounting.dimensions\" read-only=\"$ctrl.mode == 'read-only'\"></salaxy-calc-row-dimension-input>\r\n            </div>\r\n          </td>\r\n          <td style=\"max-width: 40px;\" ng-if=\"$ctrl.showDimension()\">\r\n            <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!row.rowType\" ng-click=\"$ctrl.showEditDialog(row)\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.editIcon' | sxyTranslate}}\">...</button>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"right\">\r\n            <salaxy-input-number ng-if=\"$ctrl.getConfig(row).amount.units.length > 1\" on-unit-change=\"row.unit=unit\" name=\"{{ 'iptCount' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-model=\"row.count\" label-type=\"plain\" disabled=\"$ctrl.isDisabled(row, 'amount')\" unit=\"{{$ctrl.ensureUnit(row)}}\" units=\"$ctrl.getConfig(row).amount.units\">\r\n            </salaxy-input-number>\r\n            <salaxy-input-number ng-if=\"!($ctrl.getConfig(row).amount.units.length > 1)\" name=\"{{ 'iptCount' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-model=\"row.count\" label-type=\"plain\" placeholder=\"{{ $ctrl.getPlaceholderText(row, 'amount') }}\" disabled=\"$ctrl.isDisabled(row, 'amount')\" unit=\"{{$ctrl.getConfig(row).amount.unit}}\">\r\n            </salaxy-input-number>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"right\">\r\n            <salaxy-input-number ng-if=\"$ctrl.getConfig(row).amount.units.length > 1\" name=\"{{ 'iptPrice' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-model=\"row.price\" label-type=\"plain\"  disabled=\"$ctrl.isDisabled(row, 'price')\" require=\"true\"></salaxy-input-number>\r\n            <salaxy-input-number ng-if=\"!($ctrl.getConfig(row).amount.units.length > 1)\" name=\"{{ 'iptPrice' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-change=\"row.rowType == 'hourlySalaryWithWorkingTimeCompensation' ? $ctrl.updateUsecase(row) : null\" ng-model=\"row.price\" label-type=\"plain\" placeholder=\"{{ $ctrl.getPlaceholderText(row, 'price') }}\" disabled=\"$ctrl.isDisabled(row, 'price')\" require=\"true\"></salaxy-input-number>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"right td-row-total\">\r\n            <div>{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"salaxy-calc-rows-editor-btns\">\r\n            <button type=\"button\" class=\"edit btn btn-info btn-sm\" ng-disabled=\"!row.rowType\" ng-click=\"$ctrl.showEditDialog(row)\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.editIcon' | sxyTranslate}}\"><i class=\"fa fa-pencil\"></i></button>\r\n            <button type=\"button\" class=\"delete btn btn-danger btn-sm\" ng-if=\"row.rowIndex >= 0\" ng-click=\"$ctrl.delete(row)\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.deleteIcon' | sxyTranslate}}\"><i class=\"fa fa-trash\"></i></button>\r\n          </td>\r\n          <td ng-if=\"!row.rowType\" colspan=\"2\" class=\"td-add-new-btn\">\r\n            <div>\r\n              <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.createNew()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i><span\r\n                  sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n            </div>\r\n          </td>\r\n          <td ng-if=\"!row.rowType\" colspan=\"2\" class=\"td-no-btns\">&nbsp;</td>\r\n        </tr>\r\n        <tr ng-if=\"row.rowType == 'hourlySalaryWithWorkingTimeCompensation' && $ctrl.getValidation(row).type != 'error'\" ng-repeat=\"compensationRow in row.data.compensationRows track by $index\" class=\"no-border\">\r\n          <td width=\"42px\" class=\"hidden-xxs td-avatar\">\r\n          </td>\r\n          <td width=\"40%\" class=\"td-calc-row-type\">\r\n            <input class=\"form-control\" name=\"message\" type=\"text\" readonly=\"true\" value=\"{{ compensationRow.message || ('WorkingTimeCompensationKind.' + row.data.kind | sxyEnum) }}, {{ row.data.pricing == 'percent' ? (compensationRow.percent | sxyCount:'percent') : (compensationRow.price | currency) + ' / h' }}\" />\r\n          </td>\r\n          <td class=\"right\">\r\n            <salaxy-input-number name=\"{{ 'iptCount' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-if=\"compensationRow.count != null\" ng-model=\"compensationRow.count\" label-type=\"plain\" readonly=\"true\">\r\n            </salaxy-input-number>\r\n            <salaxy-input-number name=\"{{ 'iptCount' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-if=\"compensationRow.count == null\" ng-model=\"row.count\" label-type=\"plain\" readonly=\"true\"></salaxy-input-number>\r\n            </salaxy-input-number>\r\n          </td>\r\n          <td class=\"right\">\r\n            <salaxy-input-number name=\"{{ 'iptPrice' + (row.rowIndex < 0 ? 'Salary' : row.rowIndex) }}\" ng-model=\"compensationRow.price\" label-type=\"plain\" readonly=\"true\"></salaxy-input-number>\r\n          </td>\r\n          <td class=\"right td-row-total\">\r\n            <div>{{ (compensationRow.price * (compensationRow.count || row.count || 1)) | currency }}</div>\r\n          </td>\r\n          <td></td>\r\n        </tr>\r\n        <tr ng-repeat-end class=\"row-validation no-border\" ng-if=\"row.rowType != 'hourlySalaryWithWorkingTimeCompensation' || $ctrl.getValidation(row).type == 'error'\">\r\n          <td></td>\r\n          <td colspan=\"5\">\r\n            <small class=\"\" ng-if=\"$ctrl.getValidation(row).type == 'default'\">\r\n              {{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n              <a href=\"\" ng-click=\"$ctrl.showEditDialog(row)\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n            </small>\r\n            <span ng-if=\"$ctrl.getValidation(row).type == 'error'\">\r\n              <span class=\"label label-danger\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.note\"></span>\r\n            <small class=\"alert-danger\">{{ $ctrl.getValidation(row).msg | sxyTranslate }}\r\n                <a href=\"\" ng-click=\"$ctrl.showEditDialog(row)\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.validation.edit\" ps=\"...\"></a>\r\n              </small>\r\n            </span>\r\n          </td>\r\n        </tr>\r\n        <tr class=\"new-row\">\r\n          <td width=\"42px\" class=\"hidden-xxs td-avatar\" ng-class=\"{'td-no-avatar' : !row.rowType}\">\r\n          </td>\r\n          <td width=\"40%\">\r\n            <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\" on-row-changed=\"$ctrl.commitNewRow()\" row-types=\"$ctrl.rowTypes\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n          </td>\r\n          <td colspan=\"2\" class=\"td-add-new-btn\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n          </td>\r\n          <td colspan=\"2\" class=\"td-no-btns\">&nbsp;</td>\r\n        </tr>\r\n      </tbody>\r\n      <tfoot ng-if=\"$ctrl.hasRows\">\r\n        <tr class=\"total\">\r\n          <th width=\"42px\" class=\"hidden-xxs\"></th>\r\n          <td>\r\n            <strong sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.finalCost\"></strong>\r\n          </td>\r\n          <td colspan=\"3\" class=\"right\">\r\n            <strong>{{ $ctrl.getFinalCost() | currency }}\r\n              <!--{{ $ctrl.getTotal() | currency }}--></strong>\r\n          </td>\r\n          <td colspan=\"2\"></td>\r\n        </tr>\r\n      </tfoot>\r\n    </table>\r\n\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isInEdit\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th width=\"42px\" class=\"hidden-xxs\"></th>\r\n          <th width=\"40%\" class=\"uppercase\">{{ $ctrl.title || ('SALAXY.NG1.CalcRowsComponent.editor.calcRow' | sxyTranslate) }}</th>\r\n          <th></th>\r\n          <th class=\"right\" ng-if=\"$ctrl.hasRows\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th class=\"salaxy-calc-rows-editor-btns\">\r\n            <span ng-if=\"$ctrl.showEditButtons && $ctrl.mode != 'read-only'\">\r\n              <button ng-hide=\"$ctrl.parent.isReadOnly\" ng-disabled=\"!$ctrl.isEditable\" ng-click=\"$ctrl.startEdit()\" type=\"button\" class=\"edit btn btn-info btn-sm\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.editIcon' | sxyTranslate}}\">\r\n                <i class=\"fa fa-pencil\"></i>\r\n              </button>\r\n            </span>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.filteredList track by $index\">\r\n          <td width=\"42px\" class=\"hidden-xxs\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td width=\"50%\">{{$ctrl.getMessagePlaceholderText(row)}}</td>\r\n          <td ng-if=\"row.rowType\" class=\"right\">\r\n            <small class=\"text-muted\" ng-if=\"row.count && row.count != 1\">{{row.count | sxyCount : row.unit }} * {{ row.price | currency }}</small>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"right\">\r\n            <div>{{ $ctrl.getRowTotal(row) | currency }}</div>\r\n          </td>\r\n          <td ng-if=\"row.rowType\" class=\"salaxy-calc-rows-editor-btns\">\r\n            <button type=\"button\" class=\"edit btn btn-info btn-sm\" ng-disabled=\"!row.rowType\" ng-click=\"$ctrl.showEditDialog(row)\" title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\"><i class=\"fa fa-pencil\"></i></button>\r\n\r\n          </td>\r\n\r\n        </tr>\r\n\r\n      </tbody>\r\n      <tfoot ng-if=\"$ctrl.hasRows && $ctrl.hideFinalCostRow\">\r\n        <tr class=\"total\">\r\n          <td width=\"42px\" class=\"hidden-xxs\"></td>\r\n          <td>\r\n            <strong sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></strong>\r\n          </td>\r\n          <td></td>\r\n          <td class=\"right\">\r\n            <strong>\r\n              <!--{{ $ctrl.getTotal() | currency }}--></strong>\r\n          </td>\r\n          <td></td>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.showGrossTotals\">\r\n          <th width=\"42px\" class=\"hidden-xxs\"></th>\r\n          <td>\r\n            <span sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.grossTotal\"></span><br>\r\n            <small class=\"text-muted\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.netSalary\"></small>\r\n          </td>\r\n          <td>\r\n\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ $ctrl.getGrossTotal() | currency }}<br>\r\n            <small class=\"text-muted\">{{ $ctrl.getNetSalary() | currency }}</small>\r\n          </td>\r\n          <td></td>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.showGrossTotals\" class=\"total\">\r\n          <th width=\"42px\" class=\"hidden-xxs\"></th>\r\n          <td>\r\n            <strong sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.finalCost\"></strong>\r\n            <br>\r\n            <small class=\"text-muted\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.totalPayment\"></small>\r\n          </td>\r\n          <td>\r\n          </td>\r\n          <td class=\"right\">\r\n            <strong>{{ $ctrl.getFinalCost() | currency }}</strong><br>\r\n            <small class=\"text-muted\">{{ $ctrl.getTotalPayment() | currency }}</small>\r\n          </td>\r\n          <td></td>\r\n        </tr>\r\n      </tfoot>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/CalcsIrRows.html\",`<div class=\"salaxy-calc-ir-rows salaxy-component\">\r\n  <sxy-table ng-ref=\"$ctrl.$sxyTable\" options=\"$ctrl.tableConfig.options\" include=\"$ctrl.tableConfig.include\" data=\"$ctrl.tableConfig.data\"></sxy-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/rows/RowTypeEditDialog.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">Palkkalaji: {{ $ctrl.current.config.label }}</h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab index=\"'default'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.workerInfo' | sxyTranslate }}\">\r\n      <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"CalcRowConfig\" auto-gen=\"false\" debugger=\"false\"\r\n        model=\"$ctrl.current.config\" read-only=\"{{ $ctrl.definitionEditor.mode == 'builtIn' }}\">\r\n        <div>\r\n          <salaxy-form-group name=\"id\" class=\"salaxy-read-only\" label=\"Koodi\">\r\n            <div class=\"salaxy-read-only-value\">\r\n              <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.copyToClipboard($ctrl.current.config.type)\" title=\"Kopioi ID leikepöydälle\">\r\n                <i class=\"fa fa-clipboard fa-lg\" aria-hidden=\"true\"></i></button>\r\n              <code>{{ $ctrl.current.config.type }}</code>\r\n            </div>\r\n            <p>Kopioi tämä koodi esim. tuntiraportointijärjestelmään, jotta tiedot lähetetään Palkkaukseen oikealla koodilla.</p>\r\n          </salaxy-form-group>\r\n          <fieldset>\r\n            <legend>Rivityypin kuvaus</legend>\r\n            <sxy-input label=\"Teksti\" id=\"label\" model=\"form.label\"></sxy-input>\r\n            <sxy-input label=\"Kuvaus\" id=\"descr\" model=\"form.descr\"></sxy-input>\r\n            <sxy-input label=\"Kategoria\" id=\"category\" model=\"form.category\" options=\"CalculationRowCategory\"></sxy-input>\r\n            <sxy-input label=\"Suosikki\" id=\"favorite\" model=\"form.favorite\" type=\"integer\"></sxy-input>\r\n            <sxy-input label=\"Väri\" id=\"color\" model=\"form.color\"></sxy-input>\r\n            <sxy-input label=\"Ikonin teksti\" id=\"iconText\" model=\"form.iconText\" format=\"color\"></sxy-input>\r\n          </fieldset>\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-6\">\r\n              <fieldset>\r\n                <legend>Hinta</legend>\r\n                <sxy-input label=\"Teksti\" id=\"price.label\" model=\"form.price.label\"></sxy-input>\r\n                <!-- TODO: Fix options to be drop-down -->\r\n                <sxy-input label=\"Kentän tyyppi\" id=\"price.input\" model=\"form.price.input\" options=\"['number','hidden','readOnly']\" format=\"select\"></sxy-input>\r\n                <sxy-input label=\"Oletus\" id=\"price.default\" model=\"form.price.default\"></sxy-input>\r\n              </fieldset>\r\n            </div>\r\n            <div class=\"col-sm-6\">\r\n              <fieldset>\r\n                <legend>Määrä</legend>\r\n                <sxy-input label=\"Teksti\" id=\"amount.label\" model=\"form.amount.label\"></sxy-input>\r\n                <sxy-input label=\"Kentän tyyppi\" id=\"amount.input\" model=\"form.amount.input\" options=\"['number','hidden','readOnly']\" format=\"select\"></sxy-input>\r\n                <sxy-input label=\"Oletus\" id=\"amount.default\" model=\"form.amount.default\"></sxy-input>\r\n              </fieldset>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </sxy-form>\r\n    </uib-tab>\r\n    <uib-tab index=\"'editor'\" heading=\"Oletusarvot\" ng-if=\"$ctrl.definitionEditor.mode != 'builtIn'\">\r\n      <div>\r\n        <ng-include src=\"'salaxy-components/calc/rows/CalcRows2019EditDialog.html'\"></ng-include>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'kinds'\" heading=\"Alalajit\" disable=\"!$ctrl.current.config.kind.values.length\">\r\n      <table>\r\n        <thead>\r\n          <tr>\r\n            <th>Nro</th>\r\n            <th>Teksti</th>\r\n            <th>Kuvaus</th>\r\n            <th></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat-start=\"kind in $ctrl.current.config.kind.values\">\r\n            <td>{{ kind.order }}</td>\r\n            <td>{{ kind.label }}</td>\r\n            <td>{{ kind.descr }}</td>\r\n            <td rowspan=\"2\">\r\n              <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.copyToClipboard($ctrl.current.config.type + '/' + kind.name)\" title=\"Kopioi ID leikepöydälle\">\r\n                <i class=\"fa fa-clipboard fa-lg\" aria-hidden=\"true\"></i></button>\r\n            </td>\r\n          </tr>\r\n          <tr ng-repeat-end>\r\n            <td></td>\r\n            <td colspan=\"2\">\r\n              <code>{{ $ctrl.current.config.type }}/{{ kind.name }}</code>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </uib-tab>\r\n    <uib-tab index=\"'editor'\" ng-if=\"$ctrl.definitionEditor.mode == 'builtIn'\" heading=\"Esikatselu, UI\">\r\n      <div>\r\n        <div class=\"alert alert-warning\">\r\n          <strong>Huom!</strong> Tuotteen palkkalajeja ei voi muokata. Tämä näkymä on vain esikatselua varten.\r\n        </div>\r\n        <ng-include src=\"'salaxy-components/calc/rows/CalcRows2019EditDialog.html'\"></ng-include>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'json'\" heading=\"Esikatselu, data\">\r\n      <div ng-if=\"true || $ctrl.currentTab == 'json'\">\r\n        <salaxy-json-formatter key=\"'Data'\" json=\"$ctrl.current\" open=\"2\"></salaxy-json-formatter>\r\n      </div>\r\n    </uib-tab>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.definitionEditor.mode == 'custom'\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/SalaryDateKindButton.html\",`<div class=\"salaxy-date-kind-button salaxy-component\">\r\n  <div class=\"btn-group\" uib-dropdown ng-class=\"$ctrl.buttonClass\">\r\n    <button id=\"btnSalaryDateKind\" type=\"button\" ng-disabled=\"$ctrl.disabled\" class=\"btn btn-default btn-block\" style=\"text-align: left\" uib-dropdown-toggle>\r\n      <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 8px -2px -2px;\" avatar=\"$ctrl.currentSalaryDateKind.avatar\" template-url=\"iconAvatar.html\"></salaxy-avatar>\r\n      {{ $ctrl.currentSalaryDateKind.text | sxyTranslate}}\r\n      <i class=\"fa fa-caret-down\" ></i>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnSalaryDateKind\">\r\n      <li role=\"menuitem\" ng-class=\"{ 'disabled': $ctrl.disabled }\" ng-repeat=\"salaryDateKind in $ctrl.salaryDateKinds\">\r\n        <a href=\"\" ng-click=\"$ctrl.setSalaryDateKind(salaryDateKind.value)\">\r\n          <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"salaryDateKind.avatar\" template-url=\"iconAvatar.html\"></salaxy-avatar> {{ salaryDateKind.text | sxyTranslate }}\r\n        </a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n</div>\r\n<script type=\"text/ng-template\" id=\"iconAvatar.html\">\r\n  <i class=\"salaxy-avatar fa\" ng-class=\"$ctrl.avatar.icon\" ng-style=\"{color: $ctrl.avatar.color }\"></i>\r\n</script>`);\n\n $templateCache.put(\"salaxy-components/calc/usecases/household-childCare.html\",`<div>\r\n  <div ng-if=\"$ctrl.usecaseData.id == 'childCare/mll'\">\r\n    <div class=\"panel-heading childcare\">\r\n      <span class=\"pull-left\">\r\n        <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n          <div class=\"main-icon-wrapper\" ng-if=\"$ctrl.usecaseData.icon\">\r\n            <img ng-src=\"{{$ctrl.usecaseData.icon}}\">\r\n          </div>\r\n          <div ng-if=\"$ctrl.usecaseData.badge\" class=\"badge-image-wrapper\">\r\n            <img ng-src=\"{{$ctrl.usecaseData.badge}}\">\r\n          </div>\r\n        </div>\r\n      </span>\r\n      <h1>{{$ctrl.usecaseData.label}}</h1>\r\n      <p class=\"calc-text\">\r\n        {{$ctrl.salaryRow.count || 0}} h x {{$ctrl.salaryRow.price || '9,5'}} € <span ng-if=\"$ctrl.usecaseData.isSunday\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hoursPerPriceWithSunday\"></span>\r\n        <span class=\"result-text\" ng-if=\"!$ctrl.usecaseData.isSunday\">{{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price || 9.5) | currency }}</span>\r\n        <span class=\"result-text\" ng-if=\"$ctrl.usecaseData.isSunday\">{{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price || 9.5) * 2 | currency }}</span>\r\n      </p>\r\n      <a class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\"><span sxy-text=\"SALAXY.UI_Terms.showMore\"></span><i class=\"fa fa-info-circle\"></i></a>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <p sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.mll.shortInfoText.html\"></p>\r\n      <span class=\"collapse\" ng-class=\"{show: showInfo}\">\r\n        <p sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.mll.longInfoText.html\"></p>\r\n      </span>\r\n      <div class=\"form-horizontal\">\r\n        <salaxy-input-number name=\"hours\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hourCount\" ng-model=\"$ctrl.salaryRow.count\" label-cols=\"col-sm-6\" required>\r\n        </salaxy-input-number>\r\n        <salaxy-input-boolean name=\"isSunday\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.isSunday\" type=\"switch\" ng-model=\"$ctrl.usecaseData.isSunday\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" label-cols=\"col-sm-6\"></salaxy-input-boolean>\r\n        <salaxy-input-boolean name=\"useCustomPrice\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.mll.useCustomPrice\" type=\"switch\" ng-model=\"$ctrl.usecaseData.useCustomPrice\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" label-cols=\"col-sm-6\">\r\n        </salaxy-input-boolean>\r\n        <salaxy-input-number ng-if=\"$ctrl.usecaseData.useCustomPrice\" name=\"price\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.eurPerH\" ng-model=\"$ctrl.salaryRow.price\" label-cols=\"col-sm-6\"></salaxy-input-number>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.usecaseData.id != 'childCare/mll'\">\r\n    <div class=\"panel-heading childcare\">\r\n      <span class=\"pull-left\">\r\n        <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n          <div class=\"main-icon-wrapper\" ng-if=\"$ctrl.usecaseData.icon\">\r\n            <img ng-src=\"{{$ctrl.usecaseData.icon}}\" type=\"image/svg+xml\">\r\n          </div>\r\n          <div ng-if=\"$ctrl.usecaseData.badge\" class=\"badge-image-wrapper\">\r\n            <img ng-src=\"{{$ctrl.usecaseData.badge}}\">\r\n          </div>\r\n        </div>\r\n      </span>\r\n\r\n      <h1>{{$ctrl.usecaseData.label}}</h1>\r\n      <p class=\"calc-text\">\r\n        <span ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{$ctrl.salaryRow.count || 0}} h x\r\n          {{$ctrl.salaryRow.price || 0}} €</span>\r\n        <span ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\">{{$ctrl.salaryRow.price || 0}} <span sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.eurPerMonth\"></span></span>\r\n        <span ng-if=\"$ctrl.usecaseData.isChildcareSubsidy\">+ {{ $ctrl.usecaseData.subsidyAmount || 0 }} <span\r\n            sxy-test=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.isChildCareSubsidy\"></span></span>\r\n        <span ng-if=\"$ctrl.isHouseholdDeductible\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.isHouseholdDeductible\"></span>\r\n        <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price || 0) }}\r\n          €</span>\r\n        <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\">{{ $ctrl.salaryRow.price || 0}} €</span>\r\n      </p>\r\n      <a class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\"><span sxy-text=\"SALAXY.UI_Terms.showMore\"></span><i class=\"fa fa-info-circle\"></i></a>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <p sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.shortInfoText.html\"></p>\r\n      <span class=\"collapse\" ng-class=\"{show: showInfo}\">\r\n\r\n        <p ng-if=\"$ctrl.usecaseData.isChildcareSubsidy\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.longInfoTextIfchildCareSubsidy.html\"></p>\r\n        \r\n        <p ng-if=\"!$ctrl.usecaseData.isChildcareSubsidy\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.longInfoTextIfNotchildCareSubsidy.html\"></p>\r\n\r\n        \r\n      </span>\r\n      <div class=\"form-horizontal\">\r\n        <salaxy-input-number ng-show=\"$ctrl.usecaseData.isChildcareSubsidy\" name=\"subsidyAmount\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.childCareSubsidy\" ng-model=\"$ctrl.usecaseData.subsidyAmount\" label-cols=\"col-sm-6\">\r\n        </salaxy-input-number>\r\n        <salaxy-input-enum type=\"select\" name=\"mainRowType\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryKind\" ng-model=\"$ctrl.salaryRow.rowType\" options=\"{'hourlySalary': ('SALAXY.ENUM.SalaryKind.hourlySalary.label' | sxyTranslate),'monthlySalary':('SALAXY.ENUM.SalaryKind.monthlySalary.label'| sxyTranslate)}\"\r\n          ng-change=\"$ctrl.changeRowType()\" label-cols=\"col-sm-6\" required></salaxy-input-enum>\r\n        <salaxy-input-number name=\"price\" label=\"{{$ctrl.usecaseData.isChildcareSubsidy ? $ctrl.priceLabel + ( 'SALAXY.NG1.HouseholdUsecaseComponent.childCare.inAdditionToBenefits'|sxyTranslate) : $ctrl.priceLabel}}\" ng-model=\"$ctrl.salaryRow.price\" label-cols=\"col-sm-6\"></salaxy-input-number>\r\n        <salaxy-input-number ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary'\" name=\"amount\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hourCount\" ng-model=\"$ctrl.salaryRow.count\" required label-cols=\"col-sm-6\"></salaxy-input-number>\r\n\r\n        <salaxy-input-boolean ng-if=\"!$ctrl.usecaseData.isChildcareSubsidy\" name=\"isHouseholdDeductible\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeduction\" type=\"radio\" ng-model=\"$ctrl.isHouseholdDeductible\" label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionTrue\"\r\n          label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionFalse\" label-cols=\"col-sm-6\"></salaxy-input-boolean>\r\n        <div class=\"form-group\" ng-if=\"$ctrl.usecaseData.isChildcareSubsidy\">\r\n          <div class=\"col-sm-6\"><strong sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.childCare.workerTotalPayment\"></strong></div>\r\n          <div class=\"col-sm-6 text-right\" ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary'\">\r\n            {{ ($ctrl.salaryRow.price || 0) * ($ctrl.salaryRow.count || 0) + ($ctrl.usecaseData.subsidyAmount || 0) }}</div>\r\n          <div class=\"col-sm-6 text-right\" ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\">\r\n            {{ ($ctrl.salaryRow.price || 0) + ($ctrl.usecaseData.subsidyAmount || 0) }}</div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/usecases/household-cleaning.html\",`<div>\r\n  <div class=\"panel-heading cleaning\">\r\n    <span class=\"pull-left\">\r\n      <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n        <div class=\"main-icon-wrapper\">\r\n          <img ng-src=\"{{$ctrl.usecaseData.icon}}\">\r\n        </div>\r\n      </div>\r\n    </span>\r\n    <h1>{{$ctrl.usecaseData.label}}</h1>\r\n    <p class=\"calc-text\">\r\n\r\n      <span ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{$ctrl.salaryRow.count || 0}} h x {{$ctrl.salaryRow.price || 0}}\r\n        €</span>\r\n      <span ng-if=\"$ctrl.salaryRow.rowType=='salary' || $ctrl.salaryRow.rowType=='monthlySalary'\">{{$ctrl.salaryRow.price || 0}} € <span\r\n          ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.pricePerMonth\"></span></span>\r\n\r\n      <span ng-if=\"$ctrl.isHouseholdDeductible\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.isHouseholdDeductible\"></span>\r\n\r\n      <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price || 0) }}\r\n        €</span>\r\n      <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='salary' || $ctrl.salaryRow.rowType=='monthlySalary'\">{{ $ctrl.salaryRow.price || 0}} € </span>\r\n    </p>\r\n    <a class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\"><span sxy-text=\"SALAXY.UI_Terms.showMore\"></span><i class=\"fa fa-info-circle\"></i></a>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <p sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.cleaning.shortInfoText.html\"></p>\r\n    <span class=\"collapse\" ng-class=\"{show: showInfo}\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.cleaning.longInfoText.html\"></span>\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-textarea ng-if=\"$ctrl.usecaseData.subType == 'other'\" name=\"workTypeOtherMessage\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.workDescription\" ng-model=\"$ctrl.usecaseData.workTypeOtherMessage\" label-cols=\"col-sm-6\"></salaxy-textarea>\r\n      <salaxy-input-enum type=\"select\" name=\"mainRowType\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryKind\" ng-model=\"$ctrl.salaryRow.rowType\" options=\"{'salary':('SALAXY.ENUM.SalaryKind.salary.label'| sxyTranslate),'hourlySalary':('SALAXY.ENUM.SalaryKind.hourlySalary.label' | sxyTranslate),'monthlySalary':('SALAXY.ENUM.SalaryKind.monthlySalary.label' | sxyTranslate)}\"\r\n        ng-change=\"$ctrl.changeRowType()\" label-cols=\"col-sm-6\" required></salaxy-input-enum>\r\n      <salaxy-input-number name=\"price\" label=\"{{$ctrl.priceLabel}}\" ng-model=\"$ctrl.salaryRow.price\" label-cols=\"col-sm-6\" required></salaxy-input-number>\r\n      <salaxy-input-number ng-if=\"$ctrl.salaryRow.rowType == 'hourlySalary'\" name=\"hours\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hourCount\" ng-model=\"$ctrl.salaryRow.count\" required label-cols=\"col-sm-6\"></salaxy-input-number>\r\n\r\n      <salaxy-input-boolean name=\"isContractLessThanYear\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.cleaning.contractLastedLessThanYear\" type=\"switch\" ng-model=\"$ctrl.usecaseData.isContractLessThanYear\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\"\r\n        label-cols=\"col-sm-6\">\r\n      </salaxy-input-boolean>\r\n      <salaxy-input-boolean name=\"isFullTime\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.cleaning.fullTime\" type=\"switch\" ng-model=\"$ctrl.usecaseData.isFullTime\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" label-cols=\"col-sm-6\">\r\n      </salaxy-input-boolean>\r\n\r\n      <salaxy-input-boolean name=\"isHouseholdDeductible\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeduction\" type=\"radio\" ng-model=\"$ctrl.isHouseholdDeductible\" label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionTrue\" label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionFalse\"\r\n        label-cols=\"col-sm-6\"></salaxy-input-boolean>\r\n      <div ng-if=\"$ctrl.usecaseData.isFullTime\" class=\"text-danger\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.cleaning.footnote.html\"></div>\r\n    </div>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/usecases/household-construction.html\",`<div>\r\n  <div class=\"panel-heading construction\">\r\n    <span class=\"pull-left\">\r\n      <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n        <div class=\"main-icon-wrapper\">\r\n          <img ng-src=\"{{$ctrl.usecaseData.icon}}\">\r\n        </div>\r\n      </div>\r\n    </span>\r\n    <h1>{{$ctrl.usecaseData.label}}</h1>\r\n    <p class=\"calc-text\">\r\n      <span ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{$ctrl.salaryRow.count || 0}} h x {{$ctrl.salaryRow.price || 0}}\r\n        €</span>\r\n      <span ng-if=\"$ctrl.salaryRow.rowType=='salary' || $ctrl.salaryRow.rowType=='monthlySalary'\">{{$ctrl.salaryRow.price || 0}} € <span\r\n          ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\"></span></span>\r\n      <span sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.subtitlePlusExpenses\"></span>\r\n      <span ng-if=\"$ctrl.isHouseholdDeductible\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.isHouseholdDeductible\"></span>\r\n      <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">{{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price ||\r\n        0) }}\r\n        €</span>\r\n      <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='salary' || $ctrl.salaryRow.rowType=='monthlySalary'\">{{ $ctrl.salaryRow.price || 0}} €</span>\r\n    </p>\r\n    <a class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\"><span sxy-text=\"SALAXY.UI_Terms.showMore\"></span><i class=\"fa fa-info-circle\"></i></a>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <p sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.shortInfoText.html\"></p>\r\n    <span class=\"collapse\" ng-class=\"{show: showInfo}\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.longInfoText.html\"></span>\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-input-enum type=\"select\" name=\"mainRowType\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryKind\" ng-model=\"$ctrl.salaryRow.rowType\" options=\"{'salary':('SALAXY.ENUM.SalaryKind.salary.label'| sxyTranslate),'hourlySalary':('SALAXY.ENUM.CalculationRowType.hourlySalary.label' | sxyTranslate),'monthlySalary':('SALAXY.ENUM.CalculationRowType.monthlySalary.label' | sxyTranslate),'totalEmployerPayment':('SALAXY.ENUM.CalculationRowType.totalEmployerPayment.label' | sxyTranslate)}\"\r\n        ng-change=\"$ctrl.changeRowType()\" label-cols=\"col-sm-6\" required ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-enum>\r\n      <salaxy-input-number name=\"price\" label=\"{{$ctrl.priceLabel}}\" ng-model=\"$ctrl.salaryRow.price\" label-cols=\"col-sm-6\" required ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n      <salaxy-input-number ng-if=\"$ctrl.salaryRow.rowType == 'hourlySalary'\" name=\"hours\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hourCount\" ng-model=\"$ctrl.salaryRow.count\" required label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n      <salaxy-input-boolean name=\"isHouseholdDeductible\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeduction\" type=\"radio\" ng-model=\"$ctrl.isHouseholdDeductible\" label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionTrue\" label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionFalse\"\r\n        label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-boolean>\r\n      <div ng-if=\"$ctrl.salaryRow.rowType == 'totalEmployerPayment'\" class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.totalEmployerPaymentAlert\"></div>\r\n      <div ng-if=\"$ctrl.salaryRow.rowType == 'salary'\" class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryAlert\"></div>\r\n      <div ng-if=\"$ctrl.salaryRow.rowType != 'totalEmployerPayment'\">\r\n        <salaxy-input-boolean name=\"isTesIncludedInSalary\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.tesInclusions\" type=\"radio\" ng-model=\"$ctrl.usecaseData.isTesIncludedInSalary\" label-cols=\"col-sm-6\" label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.noCalcAuto\"\r\n          label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.yesAgreedTotalPayment\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-boolean>\r\n        <salaxy-input-boolean name=\"isExpensesCustom\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.expensesCustom\" type=\"radio\" ng-model=\"$ctrl.usecaseData.isExpensesCustom\" label-cols=\"col-sm-6\" label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.noByTes\"\r\n          label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.yesAgreedPerDay\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-boolean>\r\n        <salaxy-input-number ng-if=\"!$ctrl.usecaseData.isExpensesCustom\" name=\"dailyTravelExpensesKm\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.dailyTravelExpensesKm\" ng-model=\"$ctrl.usecaseData.dailyTravelExpensesKm\" label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\">\r\n        </salaxy-input-number>\r\n        <div ng-if=\"$ctrl.usecaseData.isExpensesCustom\">\r\n          <salaxy-input-number name=\"dailyExpenses\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.dailyExpenses\" ng-model=\"$ctrl.usecaseData.dailyExpenses\" label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n          <salaxy-input-number name=\"dailyTravelExpenses\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.dailyTravelExpenses\" ng-model=\"$ctrl.usecaseData.dailyTravelExpenses\" label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n          <div ng-if=\"!$ctrl.isReadOnly\" class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.construction.taxFreeMilageAlert\"></div>\r\n        </div>\r\n      </div>\r\n      <salaxy-textarea ng-if=\"$ctrl.usecaseData.id == 'construction/new' || $ctrl.usecaseData.id == 'construction/renovation'\" name=\"workTypeOtherMessage\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.workDescription\" ng-model=\"$ctrl.usecaseData.workTypeOtherMessage\"\r\n        label-cols=\"col-sm-6\">\r\n      </salaxy-textarea>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/calc/usecases/household-other.html\",`<div>\r\n  <div class=\"panel-heading cleaning\">\r\n    <span class=\"pull-left\">\r\n      <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n        <div class=\"main-icon-wrapper\">\r\n          <img ng-src=\"{{$ctrl.usecaseData.icon}}\">\r\n        </div>\r\n      </div>\r\n    </span>\r\n    <h1>{{$ctrl.usecaseData.label}}</h1>\r\n    <p class=\"calc-text\">\r\n      <span ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">\r\n        {{$ctrl.salaryRow.count || 0}} h x {{$ctrl.salaryRow.price || 0}} €</span>\r\n      <span ng-if=\"!($ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown')\">\r\n        {{$ctrl.salaryRow.price || 0}} €\r\n        <span ng-if=\"$ctrl.salaryRow.rowType=='monthlySalary'\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.pricePerMonth\"></span>\r\n      </span>\r\n      <span ng-if=\"$ctrl.isHouseholdDeductible\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.isHouseholdDeductible\"></span>\r\n      <span class=\"result-text\" ng-if=\"$ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown'\">\r\n        {{ ($ctrl.salaryRow.count || 0) * ($ctrl.salaryRow.price || 0) }} €\r\n      </span>\r\n      <span class=\"result-text\" ng-if=\"!($ctrl.salaryRow.rowType=='hourlySalary' || $ctrl.salaryRow.rowType == 'unknown')\">\r\n        {{ $ctrl.salaryRow.price || 0}} €\r\n      </span>\r\n    </p>\r\n    <a class=\"btn-link btn-showmore\" ng-click=\"showInfo = !showInfo\"><span sxy-text=\"SALAXY.UI_Terms.showMore\"></span><i class=\"fa fa-info-circle\"></i></a>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <p sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.base.shortInfoText.html\"></p>\r\n    <span class=\"collapse\" ng-class=\"{show: showInfo}\" sxy-html=\"SALAXY.NG1.HouseholdUsecaseComponent.base.longInfoText.html\"></span>\r\n    <div class=\"form-horizontal\">\r\n\r\n      <salaxy-input-enum type=\"select\" name=\"mainRowType\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryKind\" placeholder=\"SALAXY.UI_Terms.select\" ng-model=\"$ctrl.salaryRow.rowType\" options=\"{salary:('SALAXY.ENUM.SalaryKind.salary.label'| sxyTranslate),hourlySalary:('SALAXY.ENUM.CalculationRowType.hourlySalary.label' | sxyTranslate),monthlySalary:('SALAXY.ENUM.CalculationRowType.monthlySalary.label' | sxyTranslate),totalEmployerPayment:('SALAXY.ENUM.CalculationRowType.totalEmployerPayment.label' | sxyTranslate)}\"\r\n        ng-change=\"$ctrl.changeRowType()\" label-cols=\"col-sm-6\" hidden-options=\"unknown\" enum=\"CalculationRowType\" required ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-enum>\r\n\r\n\r\n      <salaxy-input-number name=\"price\" label=\"{{$ctrl.priceLabel}}\" ng-model=\"$ctrl.salaryRow.price\" label-cols=\"col-sm-6\" required ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n      <salaxy-input-number ng-if=\"$ctrl.salaryRow.rowType == 'hourlySalary'\" name=\"hours\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.hourCount\" ng-model=\"$ctrl.salaryRow.count\" required label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-number>\r\n      <salaxy-input-occupation-type name=\"occupationType\" ng-model=\"$ctrl.usecaseData.occupation\" label-cols=\"col-sm-6\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.work.occupationCode\" require=\"$ctrl.usecaseData.id == 'construction/other'\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-occupation-type>\r\n\r\n      <salaxy-input-boolean name=\"isHouseholdDeductible\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeduction\" type=\"radio\" ng-model=\"$ctrl.isHouseholdDeductible\" label-true=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionTrue\" label-false=\"SALAXY.NG1.HouseholdUsecaseComponent.base.householdDeductionFalse\"\r\n        label-cols=\"col-sm-6\" ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-boolean>\r\n      <div ng-if=\"$ctrl.salaryRow.rowType == 'totalEmployerPayment'\" class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.totalEmployerPaymentAlert\"></div>\r\n      <div ng-if=\"$ctrl.salaryRow.rowType == 'salary'\" class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryAlert\"></div>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.taxDeductionCategories\" hidden-options=\"none\" label-cols=\"col-sm-6\" name=\"taxDeductionCategories\" ng-if=\"$ctrl.isHouseholdDeductible\" ng-model=\"$ctrl.usecaseData.taxDeductionCategories\"\r\n        enum=\"TaxDeductionWorkCategories\" type=\"select\" required ng-change=\"$ctrl.submitHouseholdUsecase()\"></salaxy-input-enum>\r\n\r\n      <salaxy-textarea name=\"message\" label=\"SALAXY.NG1.HouseholdUsecaseComponent.base.salaryMessage\" ng-model=\"$ctrl.salaryRow.message\" label-cols=\"col-sm-6\">\r\n      </salaxy-textarea>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/ContactInfo.html\",`<div class=\"salaxy-component salaxy-contact-info\">\r\n  <div class=\"row contact-info-row\">\r\n    <div class=\"col-xs-12 \">\r\n      <div class=\"alert alert-primary\">\r\n        <div class=\"icon-container hidden-xxs\"><span class=\"icon\"><i class=\"fa fa-question\"></i></span>\r\n        </div>\r\n        <div class=\"contact-info-text\" ng-if=\"!$ctrl.showShortContent\">\r\n          <p ng-if=\"!$ctrl.hideContactInfo\" sxy-html=\"SALAXY.NG1.ContactInfoComponent.contactInfo.html\"></p>\r\n          <p sxy-html=\"SALAXY.NG1.ContactInfoComponent.defaultContent.html\"></p>\r\n        </div>\r\n        <div class=\"contact-info-text\" ng-if=\"$ctrl.showShortContent\">\r\n          <p sxy-html=\"SALAXY.NG1.ContactInfoComponent.shortContent.html\"></p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/message-types/ExpenseReport.html\",`<salaxy-calc-rows-editor dimensions=\"$ctrl.crudController.employingRelation.settings.costAccounting.dimensions\" row-types=\"$ctrl.getRowTypes()\" parent=\"$ctrl.getCalcRowMessage().contentData\"></salaxy-calc-rows-editor>\r\n<button type=\"button\" ng-disabled=\"$ctrl.crudController.isNew()\" class=\"btn btn-primary btn-labeled-left\" style=\"width: 20%; text-align: left; margin-bottom: 4px\" ngf-select=\"$ctrl.crudController.uploadFiles($files)\" ngf-multiple=\"true\" ngf-max-size=\"10MB\" xxngf-pattern=\"$ctrl.crudController.supportedFilesPattern\"><i class=\"fa fa-paperclip\" style=\"width: 38px\"></i>\r\n  <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.fileBtn\"></span>\r\n</button>\r\n<div class=\"row\" style=\"margin-top: 10px;\" ng-repeat=\"item in $ctrl.list\">\r\n  <div ng-switch=\"item.type\">\r\n    <div ng-switch-when=\"blobFile\" style=\"min-width: 600px\">\r\n      <div ng-if=\"item.showPreview\">\r\n        <div class=\"pull-right\">\r\n          <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"item.showPreview=false\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n          <a class=\"btn btn-default btn-xs\" ng-href=\"{{$ctrl.crudController.getFileInfo(item).downloadUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n        </div>\r\n        <div style=\"font-weight: bold;font-size: 1.5em;\">{{ item.content }}</div>\r\n        <img class=\"img-responsive img-thumbnail\" ng-src=\"{{$ctrl.crudController.getFileInfo(item).previewUrl}}\" />\r\n      </div>\r\n      <div ng-if=\"!item.showPreview\">\r\n        <div class=\"pull-left\" style=\"margin-right: 10px;max-height: 100px; overflow-y:hidden;\" ng-if=\"$ctrl.crudController.getFileInfo(item).previewUrl\">\r\n          <img ng-src=\"{{$ctrl.crudController.getFileInfo(item).previewUrl}}\" class=\"img-thumbnail\" style=\"max-width: 200px;\" />\r\n        </div>\r\n        <i ng-if=\"!$ctrl.crudController.getFileInfo(item).previewUrl\" class=\"fa {{ $ctrl.crudController.getFileInfo(item).icon }} text-primary pull-left\" aria-hidden=\"true\" style=\"font-size: 104px; font-weight: bold\"></i>\r\n        <div style=\"font-weight: bold; font-size: 1.5em;\">{{ item.content }}</div>\r\n        <div>\r\n          <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"item.showPreview=true\" ng-if=\"$ctrl.crudController.getFileInfo(item).previewUrl\" sxy-text=\"SALAXY.UI_Terms.seePreviewAlt\"></button>\r\n          <a class=\"btn btn-default btn-xs\" ng-href=\"{{$ctrl.crudController.getFileInfo(item).downloadUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  \r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/message-types/HourlyReport.html\",`<div class=\"salaxy-component salaxy-hourly-report\">\r\n  <div class=\"list-group\">\r\n    <div class=\"list-group-item bg-primary\">\r\n      <h4 class=\"list-group-item-heading text-center\">\r\n        <div ng-if=\"$ctrl.reportType === 'hourlyReport'\">Tuntiraportti</div>\r\n        <div ng-if=\"$ctrl.reportType === 'timeReport'\">Työaikaraportti</div>\r\n        <i ng-click=\"$ctrl.changeWeek(false)\" class=\"fa fa-2x fa-arrow-circle-left pull-left\" aria-hidden=\"true\"></i>\r\n        <i ng-click=\"$ctrl.changeWeek(true)\" class=\"fa fa-2x fa-arrow-circle-right pull-right\" aria-hidden=\"true\"></i>\r\n        <div>Viikko {{$ctrl.currentWeekNumber}}</div>\r\n        <div>{{$ctrl.firstDayOfCurrentWeekFormatted}} - {{$ctrl.lastDayOfCurrentWeekFormatted}}</div>\r\n      </h4>\r\n    </div>\r\n    <div class=\"list-group-item\" ng-repeat=\"day in $ctrl.currentWeek\">\r\n      <div class=\"text-center pull-left text-uppercase week-icon\" ng-class=\"$ctrl.getDateStyle(day.date)\">\r\n        {{ day.dayName }}<br> {{ day.displayDate }}\r\n      </div>\r\n      <div class=\"pull-right\" style=\"margin-top: 6px\">\r\n        <button ng-if=\"$ctrl.showExpandButton(day.date)\" ng-click=\"$ctrl.setHourlyRecordsVisible(day.date)\" type=\"button\" class=\"btn btn-default\">\r\n          <i class=\"fa\" ng-class=\"{'fa-chevron-up' : !day.isCollapsed,  'fa-chevron-down' : day.isCollapsed}\"></i>\r\n        </button>\r\n        <button ng-click=\"$ctrl.showEditDialog($ctrl.getEditDialogItem(day.date), true)\" type=\"button\" class=\"btn btn-default\"><i class=\"fa fa-plus\"></i></button>\r\n      </div>\r\n      <p class=\"list-group-item-text\">{{$ctrl.countDailyHours(day.date) | sxyTotalTime : \"minutes\"}}</p>\r\n      <div ng-if=\"!day.isCollapsed\">\r\n        <div ng-if=\"$ctrl.reportType == 'hourlyReport'\" style=\"margin-bottom: 5px;\" ng-repeat=\"message in $ctrl.list | filter: { contentData: {period: {start: day.date}} }\">\r\n          <div>\r\n            <span style=\"padding-top: 2px;\"><strong>{{$ctrl.getDimensionOptionText(message.contentData.project)}}</strong> ({{message.contentData.totalTime | sxyTotalTime : \"minutes\"}} h)</span><br>\r\n            <span class=\"small text-overflow-80pc\" style=\"padding-top: 2px;\">{{message.contentData.projectText}}</span>\r\n            <div class=\"pull-right\">\r\n              <button ng-click=\"$ctrl.showEditDialog(message, false)\" type=\"button\" class=\"btn btn-default btn-xs\"><i class=\"fa fa-pencil\"></i></button>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"$ctrl.reportType == 'timeReport'\" style=\"margin-bottom: 5px;\" ng-repeat=\"message in $ctrl.list | filter: { contentData: {period: {start: day.date}} }\">\r\n          <div>\r\n            <span style=\"padding-top: 2px;\"><strong>{{message.contentData.project}}</strong> ({{message.contentData.startTime | date:'HH:mm'}} - {{message.contentData.endTime | date:'HH:mm'}})</span><br>\r\n            <span class=\"small text-overflow-80pc\" style=\"padding-top: 2px;\">{{message.contentData.projectText}}</span>\r\n            <div class=\"pull-right\">\r\n              <button ng-click=\"$ctrl.showEditDialog(message, false)\" type=\"button\" class=\"btn btn-default btn-xs\"><i class=\"fa fa-pencil\"></i></button>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"list-group-item\">\r\n      <h4 class=\"list-group-item-heading\">\r\n        <div class=\"text-center pull-left text-uppercase btn btn-default week-icon\">\r\n          <small>Viikko</small><br> {{$ctrl.currentWeekNumber}}\r\n        </div>\r\n        <div class=\"pull-right\" style=\"margin-top: 10px\">Yhteensä</div>\r\n        <p class=\"list-group-item-text\" style=\"height: 40px; padding-left: 80px; padding-top: 10px;\">{{$ctrl.weeklyHours | sxyTotalTime : \"minutes\"}}</p>\r\n      </h4>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/message-types/Timer.html\",`<div class=\"salaxy-component salaxy-timer\">\r\n  <div ng-if=\"$ctrl.timerMode == 'mini'\">\r\n    <div class=\"panel card-panel panel-solid\" ng-class=\"$ctrl.isTimerOnFromDayBefore ? 'panel-warning' : 'panel-primary'\">\r\n      <div class=\"panel-heading\">\r\n        <div class=\"pull-left icon-container\" style=\"padding-left: 0;\">\r\n          <i class=\"fa \" ng-class=\"$ctrl.isTimerOn ? 'fa-exclamation' : 'fa-clock-o'\">\r\n          </i>\r\n        </div>\r\n        <h3 class=\"panel-title\">Olet leimannut sisään kellokorttiin</h3>\r\n        <div class=\"date\">{{$ctrl.getTimerMessage().contentData.period.start | date : \"d.M.yyyy\"}}</div>\r\n      </div>\r\n      <div class=\"panel-content panel-body\">\r\n        <div class=\"text-center\">\r\n          <div class=\"otherparty-container\">\r\n            <salaxy-avatar avatar=\"$ctrl.parent.ownerInfo\"></salaxy-avatar>\r\n            <span>{{$ctrl.parent.ownerInfo.displayName}}</span>\r\n          </div>\r\n          <div class=\"clock-text card-main text-white\">\r\n            <i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> {{ $ctrl.getTimerMessage().contentData.totalTimeInSeconds | sxyTotalTime : \"seconds\"}}\r\n          </div>\r\n          <div class=\"card-details-title\" ng-if=\"$ctrl.getTimerMessage().contentData.project\">\r\n            \r\n            {{$ctrl.getDimensionOptionText($ctrl.getTimerMessage().contentData.project)}}\r\n          </div>\r\n          <span ng-if=\"$ctrl.getTimerMessage().contentData.projectText\" class=\"card-details\">\r\n            {{$ctrl.getTimerMessage().contentData.projectText}}\r\n          </span>\r\n        </div>\r\n\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <button ng-click=\"$ctrl.crudController.showDetails($ctrl.parent)\" class=\"btn btn-sm btn-white\">Muokkaa</button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n  <div ng-if=\"$ctrl.timerMode != 'mini' && $ctrl.timerMode != 'edit'\">\r\n    <div class=\"thumbnail thumbnail-timer\">\r\n      <form name=\"timerForm\">\r\n\r\n        <div class=\"text-center timer-container\" ng-class=\"$ctrl.isTimerOnFromDayBefore ? 'bg-warning' : 'bg-primary'\">\r\n          <h3>Kellokortti</h3>\r\n          <div class=\"clock-text\">\r\n            <i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> {{$ctrl.getTimerMessage().contentData.totalTimeInSeconds | sxyTotalTime : \"seconds\"}}\r\n          </div>\r\n          <div class=\"text-center form-inline\">\r\n            Aloitus:\r\n            <span ng-if=\"!$ctrl.editStartTime\" class=\"timer-time-input-read-only\">{{ $ctrl.getTimerMessage().contentData.startTime}}</span>\r\n            <salaxy-input-time ng-if=\"$ctrl.editStartTime\" name=\"startTime\" label=\"Työaika\" type=\"time\" ng-model=\"$ctrl.getTimerMessage().contentData.startTime\"></salaxy-input-time>\r\n            <button type=\"button\" class=\"btn btn-sm btn-transparent\" ng-click=\"$ctrl.editStartTime=!$ctrl.editStartTime\"><i class=\"fa fa-pencil\"></i></button>\r\n          </div>\r\n          <div>Yhteensä tänään {{ $ctrl.getAndFormatTotal()}}</div>\r\n          <div style=\"padding: 10px;\">\r\n            <div ng-if=\"$ctrl.crudController.employingRelation.settings.costAccounting.dimensions\"  ng-controller=\"CostAccountingController as $cost\" ng-init=\"$cost.dimensions=$ctrl.crudController.employingRelation.settings.costAccounting.dimensions\">\r\n              <salaxy-input-enum ng-if=\"$cost.getDefinition('lk1')\"  label-type=\"plain\" placeholder=\"{{($cost.getDefinition('lk1').label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" type=\"typeahead\" label-format=\"text-value\" name=\"options_project\" ng-model=\"$ctrl.getTimerMessage().contentData.project\" options=\"$cost.getDefinition('lk1').options\" required=\"true\"></salaxy-input-enum>\r\n            </div>\r\n            <salaxy-input label-type=\"plain\" placeholder=\"Kommentti\"  name=\"comment\" ng-model=\"$ctrl.getTimerMessage().contentData.projectText\" class=\"timer-comment-input\"></salaxy-input>\r\n          </div>\r\n          <div>\r\n            <button ng-if=\"!$ctrl.isTimerOn\" class=\"btn btn-lg btn-primary btn-timer-start\" ng-click=\"$ctrl.startTimer()\">\r\n          <i class=\"fa fa-play fa-2x\"></i>\r\n        </button>\r\n            <button ng-if=\"$ctrl.isTimerOn\" class=\"btn btn-lg btn-danger btn-timer-stop\" ng-click=\"$ctrl.stopTimer()\">\r\n          <i class=\"fa fa-stop fa-2x\"></i>\r\n        </button>\r\n          </div>\r\n        </div>\r\n      </form>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.timerMode != 'mini' && $ctrl.list.length\" class=\"list-group list-group-timer\">\r\n    <div class=\"list-group-item item-today\">\r\n      <div class=\"list-group-item-heading\">\r\n        TÄNÄÄN, {{ \"today\" | sxyDate }}\r\n      </div>\r\n    </div>\r\n    <div class=\"list-group-item\" ng-repeat=\"message in $ctrl.list\">\r\n      <div class=\"list-group-item-heading\">\r\n        <div class=\"pull-right\">\r\n          {{ message.contentData.totalTime | sxyTotalTime : \"minutes\"}} h\r\n          <button type=\"button\" class=\"btn btn-xs btn-transparent\" ng-click=\"$ctrl.showEditDialog(message, false)\"><i class=\"fa fa-pencil\"></i></button>\r\n        </div>\r\n        {{ message.contentData.startTime}}-{{ message.contentData.endTime}}\r\n        <br>\r\n      </div>\r\n     <!--  <div class=\"pull-right\">\r\n        <button type=\"button\" class=\"btn btn-xs btn-transparent\" ng-click=\"$ctrl.showEditDialog(message, false)\"><i class=\"fa fa-pencil\"></i></button>\r\n      </div> -->\r\n      <p class=\"list-group-item-text\">{{ $ctrl.getDimensionOptionText(message.contentData.project) }}</p>\r\n      <p class=\"list-group-item-text\" ng-if=\"message.contentData.projectText\">{{ message.contentData.projectText }}</p>\r\n      <salaxy-validation-summary api-validation=\"message.validation\" layout=\"minimal\" class=\"text-danger\"></salaxy-validation-summary>\r\n    </div>\r\n    <div class=\"list-group-item list-group-item-footer text-right\">\r\n      <button class=\"btn btn-sm btn-primary\" ng-click=\"$ctrl.showEditDialog('new', true)\">Lisää uusi merkintä <span class=\"fa fa-plus\"></span></button>\r\n    </div>\r\n    <div class=\"list-group-item list-group-item-footer\">\r\n      <div class=\"pull-right\">{{ $ctrl.getAndFormatTotal() }}</div>\r\n      Yhteensä\r\n    </div>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/MessageContent.html\",`<div ng-switch=\"item.type\">\r\n  <div ng-switch-when=\"blobFile\" style=\"min-width: 600px\">\r\n    <div ng-if=\"item.showPreview\">\r\n      <div class=\"pull-right\">\r\n        <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"item.showPreview=false\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n        <a class=\"btn btn-default btn-xs\" ng-href=\"{{$ctrl.getFileInfo(item).downloadUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n      </div>\r\n      <div style=\"font-weight: bold;font-size: 1.5em;\">{{ item.content }}</div>\r\n      <img class=\"img-responsive img-thumbnail\" ng-src=\"{{$ctrl.getFileInfo(item).previewUrl}}\" />\r\n    </div>\r\n    <div ng-if=\"!item.showPreview\">\r\n      <div class=\"pull-left\" style=\"margin-right: 10px;max-height: 100px; overflow-y:hidden;\" ng-if=\"$ctrl.getFileInfo(item).previewUrl\">\r\n        <img ng-src=\"{{$ctrl.getFileInfo(item).previewUrl}}\" class=\"img-thumbnail\" style=\"max-width: 200px;\" />\r\n      </div>\r\n      <i ng-if=\"!$ctrl.getFileInfo(item).previewUrl\" class=\"fa {{ $ctrl.getFileInfo(item).icon }} text-primary pull-left\" aria-hidden=\"true\" style=\"font-size: 104px; font-weight: bold\"></i>\r\n      <div style=\"font-weight: bold; font-size: 1.5em;\">{{ item.content }}</div>\r\n      <div>\r\n        <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"item.showPreview=true\" ng-if=\"$ctrl.getFileInfo(item).previewUrl\" sxy-text=\"SALAXY.UI_Terms.seePreviewAlt\"></button>\r\n        <a class=\"btn btn-default btn-xs\" ng-href=\"{{$ctrl.getFileInfo(item).downloadUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-switch-when=\"calculation\" ng-controller=\"CalculationCrudController as $calcCtrl\" ng-init=\"$calcCtrl.model=(item.contentId || item.content)\">\r\n    <salaxy-spinner ng-if=\"$calcCtrl.isLoading\"></salaxy-spinner>\r\n    <div ng-if=\"$calcCtrl.current\">\r\n      <div>\r\n        <table class=\"table no-border\">\r\n          <tbody>\r\n            <tr>\r\n              <td class=\"td-avatar middle\">\r\n                <salaxy-avatar avatar=\"$calcCtrl.current.worker.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td class=\"td-name middle\">\r\n                <span ng-if=\"!$calcCtrl.current.worker.avatar.displayName\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.notSelected\"></span>\r\n                <strong>{{$calcCtrl.current.worker.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + $calcCtrl.current.workflow.status + \".label\" | sxyTranslate }} {{$calcCtrl.current.workflow.paidAt | date}}\r\n              </td>\r\n              <td class=\"right middle\">\r\n                <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.salary\" ps=\":\"></span> {{ $calcCtrl.current.result.totals.totalGrossSalary | currency }}<br /> <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.payment\" ps=\":\"></span>                {{ $calcCtrl.current.result.employerCalc.totalPayment | currency }}\r\n              </td>\r\n              <td class=\"middle\">\r\n                <a ng-href=\"{{$calcCtrl.getPdfUrl($calcCtrl.current)}}\" target=\"_blank\" class=\"btn btn-sm btn-primary btn-block\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.report\"></a>\r\n              </td>\r\n              <td class=\" middle\">\r\n                <a ng-href=\"#/calc/details/{{ $calcCtrl.current.id }}\" class=\"btn btn-sm btn-default btn-block\">\r\n                  {{ $calcCtrl.current.workflow.status == 'draft' ? ('SALAXY.NG1.MessageThreadComponent.messageContent.editPay' |sxyTranslate) : ('SALAXY.NG1.MessageThreadComponent.messageContent.showCalc' |sxyTranslate) }}\r\n                </a>\r\n                <a ng-if=\"$calcCtrl.current.data.payrollId\" class=\"btn btn-sm btn-primary btn-block\" ng-href=\"#/payroll/details/{{ $calcCtrl.current.data.payrollId }}\">\r\n                  <i class=\"fa fa-list visible-xs\"></i>\r\n                  <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.payroll\"></span>\r\n                </a>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <!-- TODO: change the preview to be based on index not on actual object -->\r\n  <div ng-switch-when=\"payroll\" ng-controller=\"PayrollCrudController as $payrollCtrl\" ng-init=\"$payrollCtrl.model=(item.contentId || item.content)\">\r\n    <salaxy-spinner ng-if=\"$payrollCtrl.isLoading\"></salaxy-spinner>\r\n    <div ng-if=\"$payrollCtrl.current\">\r\n      <div>\r\n        <table class=\"table no-border\">\r\n          <tbody>\r\n            <tr>\r\n              <td class=\"middle salaxy-component salaxy-payroll\">\r\n                <div class=\"payroll-info-row\" style=\"margin-top:0px\">\r\n                  <salaxy-avatar-placeholder class=\"payroll-avatar\">\r\n                    <i class=\"salaxy-avatar fa fa-square\" style=\"color:#FDC338;\">\r\n                      <span>\r\n                        <strong>{{ $payrollCtrl.calcs.length }}</strong>\r\n                        <small>{{ $payrollCtrl.current.info.salaryDate | date : \"d.M.\" }}</small>\r\n                      </span>\r\n                    </i>\r\n                  </salaxy-avatar-placeholder>\r\n                </div>\r\n              </td>\r\n              <td class=\"td-name middle\">\r\n                <strong>{{$payrollCtrl.current.input.title}}</strong><br /> {{ \"SALAXY.ENUM.PayrollStatus.\" + $payrollCtrl.current.info.status + \".label\" | sxyTranslate }}\r\n              </td>\r\n              <td class=\"right middle\">\r\n                <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.salary\" ps=\":\"></span> {{ $payrollCtrl.info.totalGrossSalary | currency }}<br /> <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.payment\" ps=\":\"></span>                {{ $payrollCtrl.info.totalPayment | currency }}\r\n              </td>\r\n              <td class=\"middle\">\r\n                <a ng-href=\"{{$payrollCtrl.getPdfUrl()}}\" target=\"_blank\" class=\"btn btn-sm btn-default btn-block\" sxy-text=\"PDF\"></a>\r\n              </td>\r\n              <td class=\" middle\">\r\n                <a ng-href=\"#/payroll/details/{{ $payrollCtrl.current.id }}\" class=\"btn btn-sm btn-primary btn-block\">\r\n                  {{ $payrollCtrl.current.info.status == 'draft' ? ('SALAXY.UI_Terms.edit' |sxyTranslate) : ('SALAXY.UI_Terms.show' |sxyTranslate) + \" &raquo;\"   }}\r\n                </a>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-switch-when=\"text\">\r\n    <div class=\"message-content\" ng-if=\"!$ctrl.isInEdit\">{{ item.content }}</div>\r\n    <div ng-if=\"$ctrl.isInEdit\">\r\n      <textarea ng-model=\"item.content\"></textarea>\r\n    </div>\r\n  </div>\r\n  <div ng-switch-when=\"email\">\r\n    <div class=\"message-content\">\r\n      <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.messageContent.toEmail\" ps=\":\"></span> <a href=\"mailto:{{ item.content }}\">{{ item.content }}</a>\r\n    </div>\r\n  </div>\r\n  <div ng-switch-when=\"absence\">\r\n    <salaxy-absence-periods parent=\"item.contentData\" condensed=\"true\"></salaxy-absence-periods>\r\n  </div>\r\n  <div ng-switch-default class=\"alert alert-danger\">\r\n    {{ item.type }}: {{ item.content }}\r\n  </div>\r\n  <div class=\"edit-toolbar btn-toolbar\" role=\"toolbar\" ng-if=\"$ctrl.isInEdit\">\r\n    <div class=\"btn-group\" role=\"group\">\r\n      <button class=\"btn btn-xs btn-danger\" ng-click=\"$ctrl.deleteMessage(item)\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n      <button class=\"btn btn-xs btn-primary\" ng-click=\"$ctrl.markItemAsRead(item, true)\" ng-if=\"!$ctrl.getReadTime(item)\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.markAsReadBtn\"></button>\r\n      <button class=\"btn btn-xs btn-primary\" ng-click=\"$ctrl.markItemAsRead(item, false)\" ng-if=\"$ctrl.getReadTime(item)\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.markAsUnreadBtn\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/calc.html\",`<h1>calc here</h1>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/default.html\",`<div ng-if=\"$ctrl.isNew()\">\r\n  <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" ng-model=\"$ctrl.current.title\"></salaxy-input>\r\n  <salaxy-form-group label=\"\" name=\"submit\" class=\"no-colon\">\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!newMessageThread.$valid\" ng-click=\"$ctrl.save()\"\r\n      sxy-text=\"SALAXY.NG1.MessageThreadComponent.ui.newMessageThreadBtn\"></button>\r\n  </salaxy-form-group>\r\n</div>\r\n<div ng-if=\"!$ctrl.isNew()\"> \r\n  <p ng-if=\"$ctrl.current.messages.length == 0\">&nbsp;</p>\r\n  <div class=\"messages-container\" ng-if=\"$ctrl.current.messages\">\r\n    <div ng-repeat=\"item in $ctrl.current.messages\" ng-switch=\"item.fromParty\">\r\n      <div ng-switch-when=\"owner,undefined\" ng-switch-when-separator=\",\">\r\n        <salaxy-avatar avatar=\"$ctrl.current.ownerInfo\" class=\"pull-left\"></salaxy-avatar>\r\n        <div class=\"message-bubble left\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item)  }\">\r\n          <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n          <span class=\"updated-at\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read' |sxyTranslate) + ' ' + ($ctrl.getReadTime(item) |\r\n            sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate) }}</span>\r\n        </div>\r\n      </div>\r\n      <div ng-switch-when=\"otherParty\" class=\"text-right\">\r\n        <salaxy-avatar avatar=\"$ctrl.current.otherPartyInfo\" class=\"pull-right\"></salaxy-avatar>\r\n        <div class=\"message-bubble right {{item.type}}\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item) }\">\r\n          <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n          <span class=\"updated-at\" ng-if=\"item.type != 'email'\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read' |sxyTranslate) + ' ' +\r\n            ($ctrl.getReadTime(item) | sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate)}}</span>\r\n          <span class=\"updated-at\" ng-if=\"item.type == 'email'\">{{ item.time | sxyTime }}</span>\r\n        </div>\r\n      </div>\r\n      <div ng-switch-default class=\"alert alert-danger\">\r\n        <ng-include src=\"'salaxy-components/communications/MessageThread_MessageContent.html'\"></ng-include>\r\n      </div>\r\n    </div>\r\n    <div class=\"padding\">\r\n      <div ng-if=\"$ctrl.isReadOnly\" class=\"alert alert-info\">\r\n        <p>\r\n          <strong>Viestiketju on suljettu</strong>\r\n          <!-- TODO: Onko reopen mahdollinen myös työntekijälle? -->\r\n        </p>\r\n      </div>\r\n      <div class=\"row\" ng-if=\"!$ctrl.isReadOnly\">\r\n        <div class=\"col-xs-8 col-sm-9\" ng-switch=\"$ctrl.newMessage.type\">\r\n          <div ng-switch-when=\"absence\">\r\n            <salaxy-absence-periods parent=\"$ctrl.newMessage.contentData\" condensed=\"true\"></salaxy-absence-periods>\r\n          </div>\r\n          <div ng-switch-when=\"annualLeave\">\r\n            <salaxy-holiday-year-holidays parent=\"$ctrl.newMessage.contentData\" condensed=\"true\"></salaxy-holiday-year-holidays>\r\n          </div>\r\n          <textarea ng-switch-default placeholder=\"{{'SALAXY.NG1.MessageThreadComponent.writeOrPaste' |sxyTranslate}}\" ng-model=\"$ctrl.newMessage.content\"></textarea>\r\n        </div>\r\n        <div class=\"col-xs-4 col-sm-3\" ng-if=\"!$ctrl.isReadOnly\">\r\n          <button type=\"button\" class=\"btn btn-primary btn-labeled-left\" style=\"width: 100%; text-align: left; margin-bottom: 4px\" ng-click=\"$ctrl.sendMessage()\"\r\n            ng-disabled=\"!$ctrl.newMessage.content\"><i class=\"fa fa-paper-plane\"></i>\r\n            <span sxy-text=\"SALAXY.UI_Terms.send\"></span>\r\n          </button>\r\n          <button type=\"button\" class=\"btn btn-primary btn-labeled-left\" style=\"width: 100%; text-align: left; margin-bottom: 4px\" ngf-select=\"$ctrl.uploadFiles($files)\"\r\n            ngf-multiple=\"true\" ngf-max-size=\"10MB\"><i class=\"fa fa-paperclip\" style=\"width: 38px\"></i>\r\n            <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.fileBtn\"></span>\r\n          </button>\r\n          <div class=\"btn-group btn-block dropup\" uib-dropdown>\r\n            <button type=\"button\" class=\"btn btn-secondary dropdown-toggle btn-labeled-left\" style=\"width: 100%; text-align: left; margin-top: 4px\" uib-dropdown-toggle\r\n              aria-haspopup=\"true\" aria-expanded=\"false\">\r\n              <i class=\"fa fa-chevron-up\"></i> <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.moreFeaturesBtn\"></span>\r\n            </button>\r\n            <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu role=\"menu\">\r\n              <li role=\"menuitem\">\r\n                <a ng-click=\"$ctrl.delete(null, ('SALAXY.NG1.MessageThreadComponent.deleteThreadAlert' | sxyTranslate ))\"\r\n                  sxy-text=\"SALAXY.NG1.MessageThreadComponent.deleteThread\"></a>\r\n              </li>\r\n              <li role=\"separator\" class=\"divider\"></li>\r\n              <li role=\"menuitem\">\r\n                <a ng-click=\"$ctrl.setType('absence')\">Lisää poissaoloja</a>\r\n              </li>\r\n              <li role=\"menuitem\">\r\n                <a ng-click=\"$ctrl.setType('annualLeave')\">Lisää lomapyyntö</a>\r\n              </li>\r\n              <li role=\"menuitem\">\r\n                <a ng-click=\"$ctrl.setType('calcRow')\">Lisää palkkarivejä</a>\r\n              </li>\r\n              <li role=\"menuitem\">\r\n                <a ng-click=\"$ctrl.setType('text')\">Teksti tai tiedosto (oletus)</a>\r\n              </li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div id=\"messageContainerBottom\">&nbsp;</div>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/expenses.html\",`<h1>Kulukorvaukset tänne</h1>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/timer.html\",`<div>\r\n  <h3>Kellokortti</h3>\r\n    <div class=\"thumbnail\" style=\"max-width:400px; height: 320px; margin: auto;\" >\r\n      <div style=\"width: 100%; height: 100%;\" class=\"bg-primary text-center\">\r\n        <div style=\"font-size: 3.5em; padding-top: 20px;\">\r\n          <i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i>\r\n          {{ $ctrl.currentEntry.total | date : \"HH:mm:ss\" : \"UTC\" }}\r\n        </div>\r\n        <div class=\"text-center form-inline\">\r\n          Aloitus: \r\n          <span ng-if=\"!$ctrl.editStartTime\">{{ $ctrl.currentEntry.start | date : \"HH:mm\" }}</span>\r\n          <input ng-if=\"$ctrl.editStartTime\" class=\"form-control input-sm\" style=\"display: inline;width: 100px;\" type=\"time\" id=\"appt\" name=\"appt\" ng-model=\"$ctrl.currentEntry.start\" ng-model-options=\"{allowInvalid: true, debounce: 1000}\" required>\r\n          <button type=\"button\" class=\"btn btn-xs btn-primary\" ng-click=\"$ctrl.editStartTime=!$ctrl.editStartTime\"><i class=\"fa fa-pencil\"></i></button>\r\n        </div>\r\n        <div>Yhteensä tänään 01:20</div>\r\n        <div style=\"padding: 10px;\">\r\n          <salaxy-input-enum label=\"Valitse projekti\" placeholder=\"Valitse projekti\" label-type=\"plain\" name=\"project\" ng-model=\"$ctrl.currentEntry.project\" options=\"$ctrl.projects\" type=\"typeahead\"></salaxy-input-enum>\r\n          <salaxy-input placeholder=\"Kommentti\" label-type=\"plain\" name=\"comment\" ng-model=\"$ctrl.currentEntry.comment\"></salaxy-input>\r\n        </div>\r\n        <div>\r\n          <a ng-if=\"!$ctrl.currentEntry.isStarted\" class=\"btn btn-lg btn-success\" href=\"\" ng-click=\"$ctrl.startTimer()\">\r\n            <i class=\"fa fa-play fa-2x\"></i>\r\n          </a>\r\n          <a ng-if=\"$ctrl.currentEntry.isStarted\" class=\"btn btn-lg btn-danger\" href=\"\" ng-click=\"$ctrl.stopTimer()\">\r\n            <i class=\"fa fa-stop fa-2x\"></i>\r\n          </a>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"list-group\">\r\n      <div class=\"list-group-item\" style=\"margin-top: 10px;padding-bottom: 0px\" ng-if=\"$ctrl.entries.length\">\r\n        <div class=\"list-group-item-heading\">\r\n          TÄNÄÄN, {{ \"today\" | sxyDate }}\r\n        </div>\r\n      </div>\r\n      <a href=\"\" class=\"list-group-item\" ng-repeat=\"entry in $ctrl.entries\">\r\n        <h4 class=\"list-group-item-heading\">\r\n          <div class=\"pull-right\">{{ entry.total | date : \"HH:mm\" : \"UTC\" }}</div>\r\n          {{ entry.start | date : \"HH:mm\" }}-{{ entry.end | date : \"HH:mm\" }}\r\n        </h4>\r\n        <div class=\"pull-right\">\r\n          <button type=\"button\" class=\"btn btn-xs btn-primary\"><i class=\"fa fa-pencil\"></i></button>\r\n          <button type=\"button\" class=\"btn btn-xs btn-danger\"><i class=\"fa fa-trash\"></i></button>\r\n        </div>\r\n        <p class=\"list-group-item-text\">{{ $ctrl.getProjectText(entry.project) }}</p>\r\n        <p class=\"list-group-item-text\" ng-if=\"entry.comment\">{{ entry.comment }}</p>\r\n      </a>\r\n      <div class=\"list-group-item\" style=\"\" ng-if=\"$ctrl.entries.length\">\r\n        <div class=\"list-group-item-footer\">\r\n          <div class=\"pull-right\">{{ $ctrl.getTotal() | date : \"HH:mm\" : \"UTC\" }}</div>\r\n          Yhteensä\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <pre>{{ $ctrl.current | json }}</pre>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/timesheet.html\",`<div>\r\n  <h3>Tuntiraportti</h3>\r\n  <div class=\"list-group\">\r\n    <div class=\"list-group-item bg-primary\">\r\n      <h4 class=\"list-group-item-heading text-center\">\r\n        <div>Viikko 18</div>\r\n        <i class=\"fa fa-arrow-circle-left pull-left\" aria-hidden=\"true\"></i>\r\n        <i class=\"fa fa-arrow-circle-right pull-right\" aria-hidden=\"true\"></i>\r\n        <div>2.-8.5.2022</div>\r\n      </h4>\r\n    </div>\r\n    <div class=\"list-group-item\" ng-repeat=\"day in $ctrl.calendarDemoData\">\r\n      <h4 class=\"list-group-item-heading\">\r\n        <div class=\"text-center pull-left text-uppercase\" ng-class=\"day.isHoliday ? 'btn btn-default' : 'bg-primary'\" style=\"margin-left: -10px;margin-top:-5px;height: 55px; padding-top: 10px;width: 60px;\">\r\n          {{ day.day }}<br>\r\n          {{ day.date }}\r\n        </div>\r\n        <div class=\"pull-right\" style=\"margin-top: 6px\">\r\n          <button type=\"button\" class=\"btn btn-default\"><i class=\"fa fa-pencil\"></i></button>\r\n          <button type=\"button\" class=\"btn btn-default\"><i class=\"fa fa-plus\"></i></button>\r\n        </div>\r\n        <p class=\"list-group-item-text\" style=\"height: 40px; padding-left: 80px; padding-top: 10px;\">{{ day.hours }}</p>\r\n      </h4>\r\n    </div>\r\n    <div class=\"list-group-item\">\r\n      <h4 class=\"list-group-item-heading\">\r\n        <div class=\"text-center pull-left text-uppercase btn btn-default\" style=\"margin-left: -10px;margin-top:-5px;height: 55px; padding-top: 10px;width: 60px;\">\r\n          <small>Viikko</small><br>\r\n          18\r\n        </div>\r\n        <div class=\"pull-right\" style=\"margin-top: 10px\">yhteensä</div>\r\n        <p class=\"list-group-item-text\" style=\"height: 40px; padding-left: 80px; padding-top: 10px;\">15:00 h</p>\r\n      </h4>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/messages/proto-usecase/travel.html\",`<h1>Travel here</h1>`);\n\n $templateCache.put(\"salaxy-components/communications/MessageThread.html\",`<div class=\"salaxy-component salaxy-message-thread\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div ng-if=\"$ctrl.status == 'loadError'\" class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.error\"></div>\r\n  <div>\r\n    <!-- ng-transclude does not work in include -->\r\n    <div ng-if=\"$ctrl.isNew()\">\r\n      <form name=\"newMessageThread\" ng-readonly=\"$ctrl.isReadOnly\" class=\"form-horizontal\">\r\n        <ng-transclude ng-transclude-slot=\"headerNew\">\r\n          <h1 sxy-text=\"SALAXY.NG1.MessageThreadComponent.newMessage.headerTitle\"></h1>\r\n          <p class=\"lead\" sxy-html=\"SALAXY.NG1.MessageThreadComponent.newMessage.headerDescription.html\"></p>\r\n        </ng-transclude>\r\n        <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" ng-model=\"$ctrl.current.title\"></salaxy-input>\r\n        <salaxy-input-enum name=\"otherParty\" ng-model=\"$ctrl.otherParty\" ng-if=\"$ctrl.otherPartyOptions\" label=\"SALAXY.NG1.MessageThreadComponent.receiver\" type=\"select\" placeholder=\"SALAXY.UI_Terms.choose\" required options=\"$ctrl.otherPartyOptions\"></salaxy-input-enum>\r\n        <salaxy-input-enum name=\"msgType\" ng-model=\"$ctrl.msgType\" label=\"SALAXY.NG1.MessageThreadComponent.subject\" type=\"radio\" ng-init=\"$ctrl.msgType = 'salary'\" options=\"{ salary: ('SALAXY.NG1.MessageThreadComponent.subjectOptionSalary' | sxyTranslate), other:  ('SALAXY.NG1.MessageThreadComponent.subjectOptionOther' | sxyTranslate) }\"></salaxy-input-enum>\r\n        <salaxy-datepicker name=\"salaryDate\" ng-model=\"$ctrl.current.ownerWorkflow.salaryDate\" label=\"{{ $ctrl.msgType == 'salary' ? 'SALAXY.NG1.MessageThreadComponent.salaryDate' : 'SALAXY.NG1.MessageThreadComponent.replyDate'}}\" date-disabled=\"next-weekday\"\r\n          ng-required=\"$ctrl.msgType == 'salary'\"></salaxy-datepicker>\r\n        <salaxy-form-group label=\"\" name=\"submit\" class=\"no-colon\">\r\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!newMessageThread.$valid\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.ui.newMessageThreadBtn\"></button>\r\n        </salaxy-form-group>\r\n      </form>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.isNew() && $ctrl.current\">\r\n      <ng-transclude ng-transclude-slot=\"header\">\r\n        <h2>\r\n          {{ $ctrl.current.title }}<small>, <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.salaryDate\"></span> {{ $ctrl.current.ownerWorkflow.salaryDate | sxyDate }}</small>\r\n        </h2>\r\n      </ng-transclude>\r\n      <p ng-if=\"$ctrl.current.messages.length == 0\">&nbsp;</p>\r\n      <div class=\"messages-container\" ng-if=\"$ctrl.current.messages\">\r\n        <div ng-repeat=\"item in $ctrl.current.messages\" ng-switch=\"item.fromParty\">\r\n          <div ng-switch-when=\"owner,undefined\" ng-switch-when-separator=\",\">\r\n            <salaxy-avatar avatar=\"$ctrl.current.ownerInfo\" class=\"pull-left\"></salaxy-avatar>\r\n            <div class=\"message-bubble left\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item)  }\">\r\n              <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n              <span class=\"updated-at\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read' |sxyTranslate) + ' ' + ($ctrl.getReadTime(item) | sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate) }}</span>\r\n            </div>\r\n          </div>\r\n          <div ng-switch-when=\"otherParty\" class=\"text-right\">\r\n            <salaxy-avatar avatar=\"$ctrl.current.otherPartyInfo\" class=\"pull-right\"></salaxy-avatar>\r\n            <div class=\"message-bubble right {{item.type}}\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item) }\">\r\n              <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n              <span class=\"updated-at\" ng-if=\"item.type != 'email'\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read' |sxyTranslate) + ' ' + ($ctrl.getReadTime(item) | sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate)}}</span>\r\n              <span class=\"updated-at\" ng-if=\"item.type == 'email'\">{{ item.time | sxyTime }}</span>\r\n            </div>\r\n          </div>\r\n          <div ng-switch-default class=\"alert alert-danger\">\r\n            <ng-include src=\"'salaxy-components/communications/MessageThread_MessageContent.html'\"></ng-include>\r\n          </div>\r\n        </div>\r\n        <div class=\"padding\">\r\n          <div class=\"btn-toolbar spacer-bottom\" role=\"toolbar\" ng-if=\"$ctrl.role == 'otherParty'\">\r\n            <salaxy-workflow-buttons api-ctrl=\"$ctrl\"></salaxy-workflow-buttons>\r\n            <div class=\"btn-group\" role=\"group\">\r\n              <button class=\"btn btn-primary\" ng-class=\"{ 'disabled': $ctrl.getReadTime()}\" ng-click=\"$ctrl.markAllAsRead()\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.markAsReadBtn\"></button>\r\n            </div>\r\n            <button ng-if=\"$ctrl.role == 'otherParty'\" ng-click=\"$ctrl.sendNotification()\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.sendtoEmailBtn\"></button>\r\n            <div class=\"btn-group\" role=\"group\">\r\n              <button class=\"btn btn-default\" ng-click=\"$ctrl.reload()\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.reloadBtn\"></button>\r\n              <button class=\"btn btn-default\" ng-click=\"$ctrl.isInEdit=true\" ng-class=\"{ 'disabled': $ctrl.isInEdit }\" sxy-text=\"SALAXY.UI_Terms.edit\"></button>\r\n              <button class=\"btn\" ng-click=\"$ctrl.save();$ctrl.isInEdit=false\" ng-class=\"{ 'btn-primary': $ctrl.hasChanges, 'btn-default': !$ctrl.hasChanges }\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n              <button class=\"btn btn-default\" ng-class=\"{ 'disabled': !$ctrl.isInEdit }\" ng-click=\"$ctrl.reset();$ctrl.isInEdit=false\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n            </div>\r\n            <div ng-if=\"$ctrl.current.status == 'active' || $ctrl.current.status == 'approved' || $ctrl.current.status == 'rejected'\" class=\"btn-group btn-group-sm\" role=\"group\" aria-label=\"Approval toolbar\">\r\n              <button type=\"button\" class=\"btn btn-success\" ng-click=\"$ctrl.current.status = 'approved';$ctrl.save()\"\r\n                ng-disabled=\"$ctrl.current.status == 'approved'\">Hyväksy</button>\r\n              <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.current.status = 'rejected';$ctrl.save()\"\r\n                ng-disabled=\"$ctrl.current.status == 'rejected'\">Hylkää</button>\r\n              <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.current.status = 'active';$ctrl.save()\"\r\n                ng-disabled=\"$ctrl.current.status == 'active'\">Poista hyväksyntä/hylkäys</button>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.isReadOnly\" class=\"alert alert-info\">\r\n            <p>\r\n              <strong sxy-text=\"SALAXY.NG1.MessageThreadComponent.handledInfo\"></strong>\r\n              <br>\r\n              <salaxy-workflow-reopen api-ctrl=\"$ctrl\"></salaxy-workflow-reopen>\r\n            </p>\r\n          </div>\r\n          <div class=\"row\" ng-if=\"!$ctrl.isReadOnly\">\r\n            <div class=\"col-xs-8 col-sm-9\">\r\n              <textarea placeholder=\"{{'SALAXY.NG1.MessageThreadComponent.writeOrPaste' |sxyTranslate}}\" ng-model=\"$ctrl.newMessage.content\"></textarea>\r\n            </div>\r\n            <div class=\"col-xs-4 col-sm-3\" ng-if=\"!$ctrl.isReadOnly\">\r\n              <button type=\"button\" class=\"btn btn-primary btn-labeled-left\" style=\"width: 100%; text-align: left; margin-bottom: 4px\" ng-click=\"$ctrl.sendMessage()\" ng-disabled=\"!$ctrl.newMessage.content\"><i class=\"fa fa-paper-plane\"></i>\r\n                <span sxy-text=\"SALAXY.UI_Terms.send\"></span>\r\n              </button>\r\n              <button type=\"button\" class=\"btn btn-primary btn-labeled-left\" ng-disabled=\"$ctrl.newMessage.content.length > 0\" style=\"width: 100%; text-align: left; margin-bottom: 4px\" ngf-select=\"$ctrl.uploadFiles($files)\" ngf-multiple=\"true\" ngf-max-size=\"10MB\" xxngf-pattern=\"$ctrl.supportedFilesPattern\"><i class=\"fa fa-paperclip\" style=\"width: 38px\"></i>\r\n                <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.fileBtn\"></span>\r\n              </button>\r\n              <div class=\"btn-group btn-block dropup\" uib-dropdown ng-if=\"$ctrl.role == 'otherParty'\">\r\n                <button type=\"button\" class=\"btn btn-secondary dropdown-toggle btn-labeled-left\" style=\"width: 100%; text-align: left; margin-top: 4px\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\">\r\n                  <i class=\"fa fa-chevron-up\"></i> <span sxy-text=\"SALAXY.NG1.MessageThreadComponent.moreFeaturesBtn\"></span>\r\n                </button>\r\n                <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu role=\"menu\">\r\n                  <li role=\"menuitem\">\r\n                    <a ng-click=\"$ctrl.delete(null, ('SALAXY.NG1.MessageThreadComponent.deleteThreadAlert' | sxyTranslate ))\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.deleteThread\"></a>\r\n                  </li>\r\n                  <li role=\"separator\" class=\"divider\"></li>\r\n                  <li role=\"menuitem\">\r\n                    <a ng-click=\"$ctrl.addExistingCalc('draft')\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.addDraft\"></a>\r\n                  </li>\r\n                  <li role=\"menuitem\">\r\n                    <a ng-click=\"$ctrl.addExistingCalc('paid')\" sxy-text=\"SALAXY.NG1.MessageThreadComponent.addPaid\"></a>\r\n                  </li>\r\n                  <li role=\"separator\" class=\"divider\"  salaxy-if-role=\"test\"></li>\r\n                  <li role=\"menuitem\" salaxy-if-role=\"test\">\r\n                    <a ng-click=\"$ctrl.addExistingPayroll('draft')\" sxy-text=\"Palkkalistaluonnos\"></a>\r\n                  </li>\r\n                  <li role=\"menuitem\"  salaxy-if-role=\"test\">\r\n                    <a ng-click=\"$ctrl.addExistingPayroll('paid')\" sxy-text=\"Maksettu palkkalista\"></a>\r\n                  </li>\r\n                </ul>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div id=\"messageContainerBottom\">&nbsp;</div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/MessageThreadList.html\",`<div class=\"salaxy-component salaxy-message-thread-list\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <div class=\"btn-group btn-group-sm\">\r\n      <button type=\"button\" class=\"btn btn-default\"\r\n        ng-click=\"$ctrl.$odata.options.$filter = 'status eq \\\\'active\\\\' or ( status eq \\\\'draft\\\\' and data/otherPartyUnreadCount gt 0 )';$ctrl.$odata.searchChanged()\"\r\n        ng-class=\"{ active: $ctrl.$odata.options.$filter == 'status eq \\\\'active\\\\' or ( status eq \\\\'draft\\\\' and data/otherPartyUnreadCount gt 0 )' }\">Aktiiviset</button>\r\n      <button type=\"button\" class=\"btn btn-default\"\r\n        ng-click=\"$ctrl.$odata.options.$filter = '(status eq \\\\'approved\\\\' or status eq \\\\'rejected\\\\' or status eq \\\\'active\\\\' or status eq \\\\'draft\\\\')';$ctrl.$odata.searchChanged()\"\r\n        ng-class=\"{ active: $ctrl.$odata.options.$filter == '(status eq \\\\'approved\\\\' or status eq \\\\'rejected\\\\' or status eq \\\\'active\\\\' or status eq \\\\'draft\\\\')' }\">Kaikki</button>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\" ng-if=\"!$ctrl.readOnly\" ng-controller=\"SessionController as $sessionCtrl\">\r\n        <salaxy-action-button button-class=\"btn-sm btn-primary\"  action=\"'newMessage'\" label=\"SALAXY.NG1.ActionButtonComponent.startNewMessage\" disabled=\"!$sessionCtrl.session.settings.partner.accountId\">\r\n        </salaxy-action-button>\r\n    </div>\r\n  </div>\r\n\r\n  <salaxy-odata-table crud-controller=\"MessageThreadCrudController as $crud\" ng-ref=\"$ctrl.$odata\"\r\n    options=\"{ $top: $ctrl.limitTo, $filter: 'status eq \\\\'active\\\\' or ( status eq \\\\'draft\\\\' and data/otherPartyUnreadCount gt 0 )' }\" template-url=\"salaxy-components/odata/lists/MessageThreads.html\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/VarmaBanner.html\",`<div class=\"salaxy-component salaxy-varma-banner\">\r\n  <div ng-if=\"$ctrl.varmaPensionBanners.isReady\" ng-init=\"$ctrl.showVarmaPopup()\">\r\n\r\n\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/communications/Welcome.html\",`<div class=\"salaxy-component salaxy-welcome\">\r\n  <div ng-controller=\"SessionController as $sessionCtrl\">\r\n    <div ng-if=\"$ctrl.hasSystemAlert\" class=\"salaxy-welcome-system-alert alert-has-system-alert\" ng-bind-html=\"$ctrl.systemAlertHtml\"></div>    \r\n    <salaxy-alert ng-if=\"$ctrl.tutorials.showAnon\" type=\"danger\" icon=\"fa-sign-in\" class=\"alert-anon\">\r\n      <main sxy-html=\"SALAXY.NG1.WelcomeComponent.showAnon.main.html\"></main>\r\n    </salaxy-alert>\r\n    <salaxy-alert ng-if=\"$ctrl.tutorials.showInsurance || $ctrl.tutorials.showPension\" type=\"warning\" class=\"alert-insurance-and-pension\">\r\n      <main>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-lg-9\">\r\n            <p class=\"lead lead-with-text\" sxy-html=\"SALAXY.NG1.WelcomeComponent.showSettings.lead.html\"></p>\r\n            <p sxy-html=\"SALAXY.NG1.WelcomeComponent.showSettings.main\"></p>\r\n          </div>\r\n          <div class=\"col-sm-4 col-lg-3\">\r\n            <a href=\"#/settings/insurances\" class=\"btn btn-warning pull-right-sm btn-block btn-edit-settings\" style=\"margin-bottom:10px;\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showSettings.settings.cta\"></a>\r\n          </div>\r\n        </div>\r\n      </main>\r\n    </salaxy-alert>\r\n    <salaxy-alert ng-if=\"$ctrl.tutorials.showSign\" class=\"alert-sign\" type=\"warning\">\r\n      <main>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-lg-9\">\r\n            <p class=\"lead lead-with-text\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showSign.lead\"></p>\r\n            <p sxy-html=\"SALAXY.NG1.WelcomeComponent.showSign.main.html\"></p>\r\n          </div>\r\n          <div class=\"col-sm-4 col-lg-3\">\r\n            <button sxy-if-role=\"person\" ng-controller=\"WorkerOnboardingController as wizard\" class=\"btn btn-warning btn-add-signature pull-right btn-block\" ng-click=\"wizard.launch()\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showSign.main.cta\"></button>\r\n            <button sxy-if-role=\"company\" ng-controller=\"CompanyOnboardingController as wizard\" class=\"btn btn-warning btn-add-signature pull-right btn-block\" ng-click=\"wizard.launch()\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showSign.main.cta\"></button>\r\n          </div>\r\n        </div>\r\n      </main>\r\n    </salaxy-alert>\r\n    <salaxy-invoice-alerts ng-if=\"'auth' | sxyIsInRole\" payment-channels=\"['palkkausManual', 'holvi', 'talenomOnline']\"></salaxy-invoice-alerts>    \r\n    <salaxy-alert ng-if=\"$ctrl.tutorials.showTryPayroll\" type=\"primary\" class=\"alert-try-payroll\">\r\n      <main>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-lg-9\">\r\n            <p class=\"lead\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showTryPayroll.main\"></p>\r\n          </div>\r\n          <div class=\"col-sm-4 col-lg-3\">\r\n            <a class=\"btn btn-info btn-block\" href=\"#/payroll\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showTryPayroll.cta\"></a>\r\n          </div>\r\n        </div>\r\n      </main>\r\n    </salaxy-alert>\r\n    <salaxy-alert ng-if=\"$ctrl.showAutoTaxcardInfobox()\" type=\"warning\">\r\n      <main>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-lg-9\">\r\n            <p class=\"lead\" sxy-html=\"SALAXY.NG1.WelcomeComponent.autoTaxcard.lead.html\"></p>\r\n          </div>\r\n          <div class=\"col-sm-4 col-lg-3\">\r\n            <a ng-href=\"#/workers\" class=\"btn btn-warning btn-add btn-add-taxcard btn-block\" title=\"{{'SALAXY.NG1.WorkerListComponent.activeAutoTaxcard' | sxyTranslate}}\" sxy-text=\"SALAXY.NG1.WorkerListComponent.autoTaxcard\"></a>\r\n          </div>\r\n        </div>\r\n      </main>\r\n    </salaxy-alert>\r\n    <salaxy-alert ng-if=\"$ctrl.tutorials.showAddCalculation\" type=\"primary\" class=\"alert-add-calculation\">\r\n      <main>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-lg-9\">\r\n            <p class=\"lead\" sxy-html=\"SALAXY.NG1.WelcomeComponent.showAddCalculation.main.html\"></p>\r\n            <salaxy-form-group class=\"select-worker\" name=\"worker\" label=\"SALAXY.NG1.WelcomeComponent.showAddCalculation.selectWorker\" label-type=\"plain\">\r\n              <input type=\"text\" class=\"form-control\" ng-model=\"$ctrl.employmentId\" id=\"worker\" name=\"worker\" placeholder=\"{{'SALAXY.NG1.WelcomeComponent.showAddCalculation.selectWorkerPlaceholder' | sxyTranslate}}\" autocomplete=\"off\" ng-model-options=\"{allowInvalid: true, debounce: 250}\"\r\n                typeahead-on-select=\"$ctrl.createNewCalculationFor($ctrl.employmentId)\" uib-typeahead=\"worker.id as worker.displayName for worker in $ctrl.filterWorkers($viewValue)\" typeahead-focus-first=\"false\" typeahead-template-url=\"salaxy-components/form-controls/InputWorkerItem.html\"\r\n                typeahead-show-hint=\"true\" typeahead-append-to-body=\"true\" typeahead-min-length=\"0\" typeahead-editable=\"false\" typeahead-input-formatter=\"$ctrl.getWorkerName($model)\">\r\n            </salaxy-form-group>\r\n          </div>\r\n          <div class=\"col-sm-4 col-lg-3\">\r\n            <button class=\"btn btn-info btn-add btn-add-worker btn-block\" ng-click=\"$ctrl.launchEmploymentWizard()\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showAddWorker.main.cta\"></button>\r\n            <a class=\"btn btn-default btn-block btn-try-payroll\" href=\"#/payroll\" sxy-text=\"SALAXY.NG1.WelcomeComponent.showAddWorker.tryPayroll.cta\"></a>\r\n          </div>\r\n        </div>\r\n      </main>\r\n    </salaxy-alert>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/form-controls/Datepicker.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value | date }} </div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-datepicker\" ng-if=\"!$ctrl.getReadOnly()\">\r\n  <salaxy-form-group ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div uib-datepicker ng-model=\"$ctrl.dtValue\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-change=\"$ctrl.onChange()\" datepicker-options=\"$ctrl.datepickerOptions\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\">\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/DatepickerPopup.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value | date }} </div>\r\n</salaxy-form-group>\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-datepicker-popup\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.value | date }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n        \r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n        \r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n\r\n  <salaxy-form-group ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"input-group\">\r\n      <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ 'SALAXY.NG1.DatepickerPopupComponent.placeholder' | sxyTranslate  }}\" ng-model=\"$ctrl.dtValue\" ng-change=\"$ctrl.onChange()\" ng-required=\"$ctrl.require\"\r\n        ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.disabled\" uib-datepicker-popup=\"{{ $ctrl.format || 'd.M.yyyy' }}\" is-open=\"$ctrl.popup.opened\" datepicker-append-to-body=\"!$ctrl.appendInline || $ctrl.appendInline == 'false'\" datepicker-options=\"$ctrl.datepickerOptions\"\r\n        popup-placement=\"{{$ctrl.popupPlacement}}\" datepicker-popup-template-url=\"salaxy-components/form-controls/DatePickerPopupPopup.html\" clear-text=\"{{ 'SALAXY.UI_Terms.clear' | sxyTranslate}}\" close-text=\"{{ 'SALAXY.UI_Terms.close' | sxyTranslate}}\"\r\n        current-text=\"{{ 'SALAXY.UI_Terms.today' | sxyTranslate}}\" salaxy-datepicker-input-validation />\r\n      <span class=\"input-group-btn\">\r\n        <button type=\"button\" ng-disabled=\"$ctrl.readonly || $ctrl.disabled\" class=\"btn btn-default\" ng-click=\"$ctrl.open()\"><i class=\"glyphicon glyphicon-calendar\"></i></button>\r\n        <button ng-if=\"$ctrl.getToolTipHtml()\" type=\"button\" class=\"btn btn-default\" aria-label=\"Info\" uib-popover-html=\"$ctrl.getToolTipHtml()\" popover-placement=\"{{$ctrl.tooltipPlacement}}\">\r\n          <span class=\"glyphicon glyphicon-question-sign\"></span>\r\n      </button>\r\n      <button ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </span>\r\n\r\n    </div>\r\n\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/DatePickerPopupPopup.html\",`<ul role=\"presentation\" class=\"salaxy-component salaxy-datepicker uib-datepicker-popup dropdown-menu uib-position-measure\" dropdown-nested ng-if=\"isOpen\" ng-keydown=\"keydown($event)\" ng-click=\"$event.stopPropagation()\">\r\n  <li ng-transclude></li>\r\n  <li ng-if=\"showButtonBar\" class=\"uib-button-bar\">\r\n    <span class=\"btn-group pull-left\">\r\n      <button type=\"button\" class=\"btn btn-sm btn-info uib-datepicker-current\" ng-click=\"select('today', $event)\" ng-disabled=\"isDisabled('today')\">{{ getText('current') }}</button>\r\n      <button type=\"button\" class=\"btn btn-sm btn-danger uib-clear\" ng-click=\"select(null, $event)\">{{ getText('clear') }}</button>\r\n    </span>\r\n    <button type=\"button\" class=\"btn btn-sm btn-success pull-right uib-close\" ng-click=\"close($event)\">{{ getText('close') }}</button>\r\n  </li>\r\n</ul>`);\n\n $templateCache.put(\"salaxy-components/form-controls/DateRange.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value.formattedRange || \"-\" }}</div>\r\n</salaxy-form-group>\r\n\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-date-range mode-{{ $ctrl.mode || 'range' }}\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.value.formattedRange || \"-\" }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n        <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n    </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n\r\n  <div ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\">\r\n    <salaxy-input-enum ng-if=\"$ctrl.mode == 'calc' && !$ctrl.periodShortcut\" ng-model=\"$ctrl.periodShortcut\" name=\"periodShortcut\" label=\"SALAXY.NG1.DateRange.salaryPeriod\" label-cols=\"{{$ctrl.labelCols}}\" type=\"radio\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n    <salaxy-input-enum ng-if=\"$ctrl.mode == 'calc' && $ctrl.periodShortcut\" ng-model=\"$ctrl.periodShortcut\" name=\"periodShortcut\" label=\"SALAXY.NG1.DateRange.salaryPeriod\" label-cols=\"{{$ctrl.labelCols}}\" type=\"select\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n    <salaxy-form-group ng-if=\"$ctrl.mode != 'calc' || $ctrl.periodShortcut == 'other'\" ng-init=\"$ctrl.selectedDates = []\" name=\"{{ $ctrl.name + '_datepicker' }}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n      <div ng-if=\"$ctrl.mode != 'multiple'\" class=\"salaxy-read-only\">\r\n        <div class=\"salaxy-read-only-value\">\r\n          {{ $ctrl.value.formattedRange || \"-\" }}\r\n          <span class=\"pull-right btn-padding-right\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n            <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n          </span>\r\n        </div>\r\n      </div>\r\n      <div uib-datepicker ng-model=\"$ctrl.latestDateSelection\" datepicker-options=\"$ctrl.getOptions()\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" on-change=\"$ctrl.dateRangeChange()\" ng-disabled=\"$ctrl.getDisabled()\" ng-model-options=\"{allowInvalid: true}\">\r\n      </div>\r\n    </salaxy-form-group>\r\n    <div ng-if=\"$ctrl.mode == 'calc' && $ctrl.periodShortcut && $ctrl.periodShortcut != 'other'\">\r\n      <salaxy-form-group name=\"{{$ctrl.name}}_periodStartDate\" label=\"SALAXY.NG1.DateRange.startDate\" label-cols=\"{{$ctrl.labelCols}}\">\r\n        <input type=\"text\" class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}_periodStartDate\" name=\"{{$ctrl.name}}_periodStartDate\" placeholder=\"{{'SALAXY.UI_Terms.dateFormats.dm' | sxyTranslate}}\" ng-model=\"$ctrl.periodStartDate\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\"\r\n        />\r\n        <div ng-if=\"$ctrl.periodStartDateError\" class=\"salaxy-read-only-value text-danger\">{{ $ctrl.periodStartDateError | sxyTranslate }}</div>\r\n      </salaxy-form-group>\r\n      <salaxy-form-group name=\"formattedRange\" label=\"SALAXY.NG1.DateRange.labelStartAndEndDate\" label-cols=\"{{$ctrl.labelCols}}\" class=\"salaxy-read-only\">\r\n        <div class=\"salaxy-read-only-value\">{{ $ctrl.dateRange | sxyDateRange }}</div>\r\n      </salaxy-form-group>\r\n    </div>\r\n\r\n  </div>\r\n  <div ng-if=\"$ctrl.mode != 'multiple'\">\r\n    <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' && !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" label=\"{{ $ctrl.labelDaysCount || 'SALAXY.NG1.DateRange.labelDaysCount' }}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" class=\"salaxy-read-only\">\r\n      <div class=\"salaxy-read-only-value\">{{ $ctrl.value.daysCount }}\r\n        <span class=\"pull-right btn-padding-right\">\r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n        </span>\r\n      </div>\r\n    </salaxy-form-group>\r\n\r\n    <salaxy-form-group ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{ $ctrl.labelDaysCount || 'SALAXY.NG1.DateRange.labelDaysCount' }}\" label-type=\"{{$ctrl.labelType}}\"\r\n      label-cols=\"{{$ctrl.labelCols}}\">\r\n      <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n        <input type=\"text\" class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate}}\" ng-model=\"$ctrl.value.daysCount\" ng-model-options=\"{allowInvalid: true, debounce: 250}\" ng-change=\"$ctrl.setModelValue()\"\r\n          ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" />\r\n        <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n          <button class=\"btn btn-transparent pull-right\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n            <i class=\"fa fa-pencil\"></i>\r\n          </button>\r\n        </div>\r\n      </div>\r\n    </salaxy-form-group>\r\n  </div>\r\n\r\n</ng-form>\r\n<salaxy-form-group ng-if=\"$ctrl.getReadOnly() || $ctrl.mode == 'multiple'\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{ $ctrl.labelDaysCount || 'SALAXY.NG1.DateRange.labelDaysCount' }}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value.daysCount }}</div>\r\n</salaxy-form-group>`);\n\n $templateCache.put(\"salaxy-components/form-controls/FormGroup.html\",`<div ng-if=\"$ctrl.getLabelType() == 'basic'\" class=\"form-group\">\r\n  <label for=\"{{$ctrl.name}}\" class=\"col-xs-12 control-label\"><span class=\"label-text\">{{$ctrl.label | sxyTranslate}}</span><span class=\"salaxy-form-group-required-indicator\"\r\n      ng-show=\"!!$ctrl.require\">*</span>\r\n    </label>\r\n  <div class=\"col-xs-12\">\r\n    <ng-transclude></ng-transclude>\r\n  </div>\r\n</div>\r\n<div ng-if=\"$ctrl.getLabelType() == 'empty-label'\" class=\"form-group\">\r\n  <div class=\"{{ $ctrl.getLabelCols('label') }} control-label\"></div>\r\n  <div class=\"{{ $ctrl.getLabelCols('value') }}\">\r\n    <ng-transclude></ng-transclude>\r\n  </div>\r\n</div>\r\n<div ng-if=\"$ctrl.getLabelType() == 'no-label'\" class=\"form-group\">\r\n  <div class=\"{{ $ctrl.getLabelCols('no-label') }}\">\r\n    <ng-transclude></ng-transclude>\r\n  </div>\r\n</div>\r\n<span ng-if=\"$ctrl.getLabelType() == 'plain'\" class=\"salaxy-form-group-plain\">\r\n  <ng-transclude></ng-transclude>\r\n</span>\r\n<div ng-if=\"$ctrl.getLabelType() == 'horizontal'\" class=\"form-group\">\r\n  <label for=\"{{$ctrl.name}}\" class=\"{{ $ctrl.getLabelCols('label') }} control-label\">\r\n    <span class=\"label-text\">{{$ctrl.label | sxyTranslate}}</span><span class=\"salaxy-form-group-required-indicator\"\r\n      ng-show=\"!!$ctrl.require\">*</span>\r\n  </label>\r\n  <div class=\"{{ $ctrl.getLabelCols('value') }}\">\r\n    <ng-transclude></ng-transclude>\r\n  </div>\r\n</div>\r\n<div ng-if=\"$ctrl.getLabelType() == 'inline'\" class=\"form-group\">\r\n  <label for=\"{{$ctrl.name}}\"><span class=\"label-text\">{{$ctrl.label | sxyTranslate}}</span><span\r\n      class=\"salaxy-form-group-required-indicator\" ng-show=\"!!$ctrl.require\">*</span></label>\r\n  <ng-transclude class=\"inline-salaxy-input\"></ng-transclude>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/form-controls/Input.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value }}\r\n\r\n  </div>\r\n\r\n</salaxy-form-group>\r\n\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.value }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n        \r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n        \r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n\r\n  <salaxy-form-group ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div ng-if=\"$ctrl.getToolTipHtml()\" class=\"input-group\">\r\n      <input type=\"{{$ctrl.type || 'text'}}\" class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\"\r\n        ng-change=\"$ctrl.onChange()\" ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" />\r\n      <div class=\"input-group-btn\">\r\n        <button type=\"button\" class=\"btn btn-default\" aria-label=\"Info\" uib-popover-html=\"$ctrl.getToolTipHtml()\" popover-placement=\"{{$ctrl.tooltipPlacement}}\">\r\n          <span class=\"glyphicon glyphicon-question-sign\"></span>\r\n        </button>\r\n        <button ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.getToolTipHtml()\" ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <input type=\"{{$ctrl.type || 'text'}}\" class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\"\r\n        ng-change=\"$ctrl.onChange()\" ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" />\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent pull-right\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputAccountingTarget.html\",`<ng-form name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input-accounting-target\">\r\n  <salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.value }}</div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" ng-init=\"refresher = [0]\">\r\n    <input ng-repeat=\"item in refresher\" label-type=\"basic\" type=\"text\" class=\"form-control\" ng-model=\"$ctrl.value\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" autocomplete=\"off\" ng-model-options=\"{allowInvalid: true, debounce: 250}\"\r\n    uib-typeahead=\"target.id as target.otherPartyInfo.avatar.displayName for target in $ctrl.queryAccountingTargets($viewValue)\" typeahead-focus-first=\"false\"\r\n    typeahead-template-url=\"salaxy-components/sxy-form/custom-templates/select-accounting-target-item.html\" typeahead-show-hint=\"true\" typeahead-append-to-body=\"true\" typeahead-on-select=\"$ctrl.onChange()\"\r\n    typeahead-min-length=\"0\" typeahead-editable=\"false\" typeahead-input-formatter=\"$ctrl.queryAccountingTargetDisplayName($model, refresher)\" />\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputBoolean.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">\r\n    <span ng-if=\"$ctrl.value==true\">{{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n    <span ng-if=\"$ctrl.value==false && $ctrl.labelType != 'no-label'\">{{$ctrl.labelFalse || 'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n  </div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" ng-if=\"!$ctrl.getReadOnly()\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen && $ctrl.type != 'switch'\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">\r\n      <span ng-if=\"$ctrl.value==true\">{{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n      <span ng-if=\"$ctrl.value==false\">{{$ctrl.labelFalse || 'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n      <span class=\"pull-right btn-padding-right\">\r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"($ctrl.type == 'radio' || !$ctrl.type) && (!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen))\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" require=\"$ctrl.require\" class=\"salaxy-component salaxy-input-boolean boolean-radio\">\r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <div class=\"radio\" ng-class=\"$ctrl.horizontal ? 'pull-left' : null\">\r\n        <label for=\"{{$ctrl.name}}True\">\r\n          <input type=\"radio\" ng-disabled=\"$ctrl.getDisabled()\" name=\"{{$ctrl.name}}Radio\" id=\"{{$ctrl.name}}True\" ng-change=\"$ctrl.onChange()\" ng-model=\"$ctrl.value\" value=\"true\" sxy-enum-as-boolean>\r\n          {{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}}\r\n        </label>\r\n      </div>\r\n      <div class=\"radio\">\r\n        <label for=\"{{$ctrl.name}}False\">\r\n          <input type=\"radio\" ng-disabled=\"$ctrl.getDisabled()\" name=\"{{$ctrl.name}}Radio\" id=\"{{$ctrl.name}}False\" ng-change=\"$ctrl.onChange()\" ng-model=\"$ctrl.value\" value=\"false\" sxy-enum-as-boolean>\r\n          {{$ctrl.labelFalse || 'SALAXY.UI_Terms.no' | sxyTranslate}}\r\n        </label>\r\n      </div>\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br />\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'checkbox' && (!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen))\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" class=\"salaxy-component salaxy-input-boolean boolean-checkbox\">\r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <div class=\"checkbox\">\r\n        <div class=\"{{$ctrl.offsetCols}}\" ng-class=\"{'col-offset' : $ctrl.offsetCols}\">\r\n          <label class=\"checkbox-label\">\r\n            <input type=\"checkbox\" ng-disabled=\"$ctrl.getDisabled()\" ng-required=\"$ctrl.require\" ng-model=\"$ctrl.value\" ng-change=\"$ctrl.onChange()\" name=\"{{$ctrl.name}}\"\r\n              id=\"{{$ctrl.name}}\" title=\"true\">\r\n            {{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}}\r\n          </label>\r\n        </div>\r\n       \r\n      </div>\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br />\r\n    </div>\r\n  </salaxy-form-group>\r\n  \r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'switch'\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" require=\"$ctrl.require\" class=\"salaxy-component salaxy-input-boolean boolean-switch\">\r\n    <span class=\"salaxy-switch\" ng-class=\"{checked: $ctrl.model.$viewValue, disabled: $ctrl.getDisabled()}\" ng-click=\"$ctrl.toggle()\">\r\n      <small></small>\r\n      <input type=\"checkbox\" id=\"{{$ctrl.id}}\" name=\"{{$ctrl.name}}\" ng-model=\"$ctrl.value\" style=\"display:none;\" />\r\n      \r\n    </span>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br />\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'switch-xl'\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" require=\"$ctrl.require\" class=\"salaxy-component salaxy-input-boolean boolean-switch\">\r\n    <span class=\"salaxy-switch switch-xl\" ng-class=\"{checked: $ctrl.model.$viewValue, disabled: $ctrl.getDisabled()}\" ng-click=\"$ctrl.toggle()\">\r\n      <small></small>\r\n      <input type=\"checkbox\" id=\"{{$ctrl.id}}\" name=\"{{$ctrl.name}}\" ng-model=\"$ctrl.value\" style=\"display:none;\" />\r\n      <span class=\"switch-text\">\r\n        <span class=\"on\" ng-if=\"$ctrl.labelTrue\"> {{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}}</span>\r\n        <span class=\"off\" ng-if=\"$ctrl.labelFalse\"> {{$ctrl.labelFalse || 'SALAXY.UI_Terms.no' | sxyTranslate}}</span>\r\n      </span>\r\n    </span>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br />\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='select'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" class=\"salaxy-component salaxy-input-boolean boolean-select\">\r\n    <select ng-disabled=\"$ctrl.getDisabled()\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-change=\"$ctrl.onChange()\" ng-model=\"$ctrl.value\" class=\"form-control\" sxy-enum-as-boolean>\r\n      <option ng-if=\"$ctrl.value == null\" value=\"{{$ctrl.value}}\" selected disabled>{{ $ctrl.placeholder || 'SALAXY.UI_Terms.select' | sxyTranslate }}</option>\r\n      <option value=\"true\" title=\"{{$ctrl.labelTrue}}\">{{$ctrl.labelTrue || 'SALAXY.UI_Terms.yes' | sxyTranslate}}</option>\r\n      <option value=\"false\" title=\"{{$ctrl.labelFalse}}\">{{$ctrl.labelFalse || 'SALAXY.UI_Terms.no' | sxyTranslate}}</option>\r\n    </select>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br />\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputDuration.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value | sxyDuration }} </div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input-duration\" ng-if=\"!$ctrl.getReadOnly()\">\r\n  <salaxy-form-group ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <salaxy-input-number name=\"{{$ctrl.name}}Days\" ng-model=\"$ctrl.innerValue.days\" ng-change=\"$ctrl.onChange()\" label-type=\"plain\" unit=\"days\"></salaxy-input-number>\r\n    <salaxy-input-boolean type=\"select\" name=\"{{$ctrl.name}}Negative\" ng-model=\"$ctrl.innerValue.isNegative\" ng-change=\"$ctrl.onChange()\" label-true=\"SALAXY.NG1.InputDurationComponent.labelTrue\" label-false=\"SALAXY.NG1.InputDurationComponent.labelFalse\" label-type=\"plain\"></salaxy-input-boolean>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputEnum.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly() && $ctrl.type != 'multi-select'\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.getEnumerationLabel($ctrl.value) }}</div>\r\n</salaxy-form-group>\r\n<salaxy-form-group ng-if=\"$ctrl.getReadOnly() && $ctrl.type == 'multi-select'\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div ng-repeat=\"x in $ctrl.value\" class=\"salaxy-read-only-value\">{{ $ctrl.getEnumerationLabel(x)}}</div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" ng-if=\"!$ctrl.getReadOnly()\" class=\"salaxy-input-enum\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.getEnumerationLabel($ctrl.value) }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"($ctrl.type || 'select')=='select' && (!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen))\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n\r\n      <select ng-disabled=\"$ctrl.getDisabled()\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-change=\"$ctrl.setStoredValue($ctrl.name, $ctrl.value);$ctrl.onChange()\" ng-model=\"$ctrl.value\" class=\"form-control\" ng-required=\"$ctrl.require\" sxy-exclude-unknowns=\"$ctrl.require ? $ctrl.invalidEnums : ''\">\r\n        <option ng-if=\"$ctrl.showPlaceholder\" value=\"{{$ctrl.value}}\" disabled selected>{{ $ctrl.placeholder || 'SALAXY.UI_Terms.select' | sxyTranslate }}</option>\r\n        \r\n        <option ng-repeat=\"x in $ctrl.getEnumerations()\" value=\"{{x.value}}\" title=\"{{x.title}}\">{{$ctrl.formatLabel(x)}}</option>\r\n      </select>\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='radio'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"radio\" ng-repeat=\"x in $ctrl.getEnumerations()\">\r\n      <label class=\"control-label radio-label\" for=\"{{x.value}}\">\r\n        <input ng-disabled=\"$ctrl.getDisabled()\" ng-required=\"$ctrl.require\" type=\"radio\" ng-model=\"$ctrl.value\" ng-change=\"$ctrl.onChange()\" class=\"\" name=\"{{$ctrl.label}}\" id=\"{{x.value}}\" value=\"{{x.value}}\"\r\n          title=\"{{x.title}}\">\r\n          {{$ctrl.formatLabel(x)}}\r\n      </label>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='multi-select'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <select ng-disabled=\"$ctrl.getDisabled()\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" multiple ng-change=\"$ctrl.onChange()\" ng-model=\"$ctrl.value\" class=\"form-control\">\r\n      <option ng-repeat=\"x in $ctrl.getEnumerations()\" value=\"{{x.value}}\" title=\"{{x.title}}\">{{$ctrl.formatLabel(x)}}</option>\r\n    </select>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='typeahead' && (!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen))\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n   \r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <input ng-ref=\"$inputEnum\" type=\"text\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" class=\"form-control\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250}\" placeholder=\"{{$ctrl.placeholder}}\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\"\r\n        ng-disabled=\"$ctrl.getDisabled()\" autocomplete=\"off\" uib-typeahead=\"x.value as ($ctrl.formatLabel(x)) for x in $ctrl.getEnumerations() | filter:($viewValue || '') | limitTo:50\" typeahead-on-select=\"$ctrl.onChange()\" typeahead-show-hint=\"true\" typeahead-template-url=\"salaxy-components/form-controls/InputEnumTypeaheadMatch.html\"\r\n        typeahead-append-to-body=\"true\" typeahead-min-length=\"0\" typeahead-editable=\"false\" typeahead-input-formatter=\"$ctrl.getEnumerationLabel($model)\">\r\n      <span class=\"clear clickable\" ng-if=\"$ctrl.value\"  ng-click=\"$ctrl.reset($inputEnum)\">\r\n        &times;\r\n      </span>\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='uib-dropdown'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"btn-group\" uib-dropdown role=\"group\">\r\n      <button id=\"{{$ctrl.name}}\" type=\"button\" class=\"btn btn-default dropdown-toggle\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\" ng-disabled=\"$ctrl.getDisabled()\">\r\n        {{ $ctrl.getEnumerationLabel($ctrl.value) || $ctrl.placeholder || 'SALAXY.UI_Terms.select' | sxyTranslate }}\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"{{$ctrl.name}}\">\r\n        <li><a href=\"\" ng-click=\"$ctrl.value=x.value;$ctrl.setStoredValue($ctrl.name, $ctrl.value);$ctrl.onChange()\" ng-repeat=\"x in $ctrl.getEnumerations()\">{{$ctrl.formatLabel(x)}}</a></li>\r\n      </ul>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputEnumTypeaheadMatch.html\",`<a ng-if=\"match.model.ui && match.model.ui.avatar\" class=\"clickable salaxy-component salaxy-worker-item\" style=\"padding: 10px 10px 5px 10px;\">\r\n  <salaxy-avatar style=\"font-size: 30px; vertical-align: middle; margin-right: 10px;\" avatar=\"match.model.ui.avatar\"></salaxy-avatar>\r\n  <b class=\"salaxy-highlight\" ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"></b><br />\r\n</a>\r\n<a ng-if=\"!match.model.ui\" href\r\n   tabindex=\"-1\"\r\n   ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"\r\n   ng-attr-title=\"{{match.model.title}}\">\r\n</a>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputHolidayMultipliers.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">\r\n    <table ng-if=\"$ctrl.value\" class=\"table table-condensed table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th class=\"right\" sxy-terms=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.days\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.multiplier\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"(key, value) in $ctrl.value track by $index\">\r\n          <td class=\"right\">{{key}}</td>\r\n          <td class=\"right\">{{value}}</td>\r\n        </tr>\r\n    </table>\r\n  </div>\r\n</salaxy-form-group>\r\n\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input form-condensed\">\r\n  <salaxy-form-group name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div>\r\n      <table class=\"table table-condensed table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th class=\"right\" sxy-terms=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.days\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.multiplier\"></th>\r\n            <th class=\"text-right\">\r\n              <button type=\"button\" class=\"btn btn-primary btn-xs\"  ng-click=\"$ctrl.createNew({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"(key, value) in $ctrl.value\">\r\n            <td ng-init=\"editableKey=key\" class=\"right\"><salaxy-input-number name=\"Key{{key}}\" label-type=\"no-label\" ng-model=\"editableKey\" ng-change=\"$ctrl.onKeyChanged(key, editableKey)\" sxy-integer></salaxy-input-number></td>\r\n            <td class=\"right\"><salaxy-input-number name=\"Value{{key}}\" label-type=\"no-label\" ng-model=\"$ctrl.value[key]\" ng-change=\"$ctrl.onChange()\"></salaxy-input-number></td>\r\n            <td class=\"text-right\">\r\n              <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(key)\">\r\n                <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputHolidayRowType.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">\r\n    <span class=\"badge bg-default\" ng-if=\"!$ctrl.isExclusive\">{{ $ctrl.text }}</span>\r\n    <span class=\"badge bg-danger\" ng-if=\"$ctrl.isExclusive\"><s>{{ $ctrl.text }}</s></span>\r\n  </div>\r\n</salaxy-form-group>\r\n\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input\">\r\n  <salaxy-form-group name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"clickable\" ng-click=\"$ctrl.edit()\">\r\n      <span class=\"badge bg-default\" ng-if=\"!$ctrl.isExclusive\">{{ $ctrl.text || ('SALAXY.UI_Terms.new' | sxyTranslate) }}</span> \r\n      <span class=\"badge bg-danger\" ng-if=\"$ctrl.isExclusive\"><s>{{ $ctrl.text || ('SALAXY.UI_Terms.new' | sxyTranslate)}}</s></span>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputIncomeType.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.getRowLabel($ctrl.value) }}</div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" ng-if=\"!$ctrl.getReadOnly()\">\r\n  <salaxy-form-group name=\"{{$ctrl.name}}\" ng-if=\"!$ctrl.type || $ctrl.type == 'typehead'\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <input type=\"text\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-required=\"$ctrl.require\" autocomplete=\"off\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250}\" class=\"form-control\"\r\n      ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" typeahead-on-select=\"$ctrl.onChange()\" uib-typeahead=\"type.code as type.label for type in $ctrl.getIncomeTypes($viewValue) | limitTo:50\" typeahead-template-url=\"salaxy-components/form-controls/InputIncomeTypeItem.html\"\r\n      typeahead-show-hint=\"true\" typeahead-append-to-body=\"true\" typeahead-min-length=\"0\" typeahead-editable=\"false\" typeahead-input-formatter=\"$ctrl.getRowLabel($model)\">\r\n    <div ng-show=\"{{$ctrl.name}}Form.{{$ctrl.name}}.$invalid && $ctrl.validationError && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted)\">\r\n      {{$ctrl.validationError | sxyTranslate}}\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group name=\"{{$ctrl.name}}\" ng-if=\"$ctrl.type == 'list'\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <input type=\"hidden\" ng-model=\"$ctrl.value\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-required=\"$ctrl.require\">\r\n    <div class=\"list-group\">\r\n      <a ng-repeat=\"type in $ctrl.getIncomeTypes()\" ng-click=\"$ctrl.selectionClicked(type.code)\" class=\"list-group-item clickable\" ng-class=\"{ 'active': $ctrl.value == type.code, 'clickable': !$ctrl.readonly && !$ctrl.disabled }\">\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: type.code, entityType: 'company' }\"></salaxy-avatar>\r\n        <b class=\"salaxy-highlight\" ng-bind-html=\"$ctrl.getRowLabel(type.code) | uibTypeaheadHighlight:$ctrl.searchText\"></b><br />\r\n        <small class=\"salaxy-highlight\">\r\n            <div ng-bind-html=\"type.description | uibTypeaheadHighlight:$ctrl.searchText\"\r\n              style=\"white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\"></div>\r\n          </small>\r\n      </a>\r\n    </div>\r\n    <div ng-show=\"{{$ctrl.name}}Form.{{$ctrl.name}}.$invalid && $ctrl.validationError && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted)\">\r\n      {{$ctrl.validationError | sxyTranslate}}\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputIncomeTypeItem.html\",`<a class=\"clickable\">\r\n    <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" \r\n    avatar=\"{ color: '#2b507c', initials: match.model.code, entityType: 'company' }\"></salaxy-avatar>\r\n    <b class=\"salaxy-highlight\" ng-bind-html=\"(match.label + ' (' + match.model.code + ')') | uibTypeaheadHighlight:query\"></b><br />\r\n    <small class=\"salaxy-highlight\"><div ng-bind-html=\"match.model.description | uibTypeaheadHighlight:query\"></div></small>\r\n</a>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputNumber.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.viewValue + ($ctrl.getUnitIndicator() ? \" \" + $ctrl.getUnitIndicator() : \"\") }}</div>\r\n</salaxy-form-group>\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-read-only salaxy-input-number salaxy-input\">\r\n  <salaxy-form-group ng-if=\"(!$ctrl.type || $ctrl.type == 'default') && $ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.value }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n\r\n  <salaxy-form-group ng-if=\"(!$ctrl.type || $ctrl.type == 'default') && !$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div ng-if=\"$ctrl.getUnitIndicator()\" class=\"input-group\">\r\n      <div ng-if=\"!$ctrl.units\" class=\"input-group-addon\">{{ $ctrl.getUnitIndicator() }}</div>\r\n      <div ng-if=\"$ctrl.units\" class=\"input-group-btn\" uib-dropdown>\r\n        <button id=\"units\" type=\"button\" class=\"btn btn-secondary\" uib-dropdown-toggle>\r\n          {{ $ctrl.getUnitIndicator() }} <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"units\">\r\n          <li ng-repeat=\"unit in $ctrl.units\" role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.changeUnit(unit)\">{{$ctrl.getUnitIndicator(unit)}}</a></li>\r\n        </ul>\r\n      </div>\r\n      <input type=\"text\" class=\"form-control text-right\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate}}\" ng-model=\"$ctrl.viewValue\" ng-model-options=\"{allowInvalid: true, updateOn: 'blur' }\"\r\n        ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" sxy-min=\"$ctrl.minimum\" sxy-max=\"$ctrl.maximum\" />\r\n      <div ng-if=\"$ctrl.getToolTipHtml() || $ctrl.inputMode == 'openClose'\" class=\"input-group-btn\">\r\n        <button ng-if=\"$ctrl.getToolTipHtml()\" type=\"button\" class=\"btn btn-default\" aria-label=\"Info\" uib-popover-html=\"$ctrl.getToolTipHtml()\" popover-placement=\"{{$ctrl.tooltipPlacement}}\">\r\n            <span class=\"glyphicon glyphicon-question-sign\"></span>\r\n        </button>\r\n        <button ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.getUnitIndicator() && !$ctrl.getToolTipHtml()\" ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n\r\n      <input type=\"text\" class=\"form-control text-right\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate}}\" ng-model=\"$ctrl.viewValue\" ng-model-options=\"{allowInvalid: true, updateOn: 'blur'}\"\r\n        ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" sxy-min=\"$ctrl.minimum\" sxy-max=\"$ctrl.maximum\" />\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n\r\n        <button class=\"btn btn-transparent pull-right\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.getUnitIndicator() && $ctrl.getToolTipHtml()\" class=\"input-group\">\r\n\r\n      <input type=\"text\" class=\"form-control text-right\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate}}\" ng-model=\"$ctrl.viewValue\" ng-model-options=\"{allowInvalid: true, updateOn: 'blur'}\"\r\n        ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" sxy-min=\"$ctrl.minimum\" sxy-max=\"$ctrl.maximum\" sxy-multiple-of=\"$ctrl.multipleOf\" />\r\n\r\n      <div class=\"input-group-btn\">\r\n        <button type=\"button\" class=\"btn btn-default\" aria-label=\"Info\" uib-popover-html=\"$ctrl.getToolTipHtml()\" popover-placement=\"{{$ctrl.tooltipPlacement}}\">\r\n            <span class=\"glyphicon glyphicon-question-sign\"></span>\r\n        </button>\r\n        <button ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i> \r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-show=\"$ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted)\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'slider'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n     <input type=\"range\" class=\"form-control text-right\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" min=\"{{$ctrl.minimum}}\" max=\"{{$ctrl.maximum}}\" step=\"{{$ctrl.sliderStep}}\" ng-model=\"$ctrl.value\" ng-change=\"$ctrl.onChange()\"/>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputOccupationType.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.getOccupationLabel($ctrl.value) }}</div>\r\n</salaxy-form-group>\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input-occupation-type\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"salaxy-read-only-value\">{{ $ctrl.getOccupationLabel($ctrl.value) }}\r\n      <span class=\"pull-right btn-padding-right\">\r\n          <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n      </span>\r\n    </div>\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <input ng-ref=\"$inputEnum\" type=\"text\" class=\"form-control\" ng-model=\"$ctrl.value\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" autocomplete=\"off\" ng-model-options=\"{allowInvalid: true, debounce: 250}\"\r\n        ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" typeahead-on-select=\"$ctrl.onChange()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" uib-typeahead=\"occupation.id as occupation.label for occupation in $ctrl.getOccupations($viewValue) | limitTo:50\"\r\n        typeahead-show-hint=\"true\" typeahead-append-to-body=\"true\" typeahead-min-length=\"0\" typeahead-editable=\"false\" typeahead-input-formatter=\"$ctrl.getOccupationLabel($model)\" sxy-exclude-unknowns=\"$ctrl.require ? $ctrl.invalidEnums : ''\">\r\n        <span class=\"clear clickable\" ng-if=\"$ctrl.value\"  ng-click=\"$ctrl.reset($inputEnum)\">\r\n          &times;\r\n        </span>\r\n        <div ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"input-group-btn\">\r\n        <button class=\"btn btn-transparent pull-right\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n            <i class=\"fa fa-pencil\"></i>\r\n          </button>\r\n      </div>\r\n      <div ng-show=\"{{$ctrl.name}}Form.{{$ctrl.name}}.$invalid && $ctrl.validationError && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted)\">\r\n        {{$ctrl.validationError | sxyTranslate}}\r\n      </div>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputProfileItem.html\",`<a class=\"clickable salaxy-component salaxy-avatar-item\">\r\n  <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" \r\n  avatar=\"match.model\"></salaxy-avatar>\r\n  <b class=\"salaxy-highlight\" ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"></b><br />\r\n  <small class=\"salaxy-highlight\"><div ng-bind-html=\"(match.model.description || '') | uibTypeaheadHighlight:query\"></div></small>\r\n</a>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputRrule.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.getRRuleText($ctrl.value) }} </div>\r\n</salaxy-form-group>\r\n<ng-form name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input-duration\" ng-if=\"!$ctrl.getReadOnly()\">\r\n  <salaxy-form-group ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\" class=\"salaxy-read-only\">\r\n    <!-- TODO: Better UI -->\r\n    <div class=\"salaxy-read-only-value\">\r\n      <a href=\"\" ng-click=\"$ctrl.showRRule = !$ctrl.showRRule\">{{ $ctrl.getRRuleText($ctrl.value) }}</a>\r\n      <salaxy-input ng-if=\"$ctrl.showRRule\" name=\"{{$ctrl.name}}Inner\" ng-model=\"$ctrl.value\" ng-change=\"$ctrl.onChange()\" label-type=\"plain\"></salaxy-input>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputTime.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.viewValue }}</div>\r\n</salaxy-form-group>\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-input  salaxy-input-number salaxy-input-time\">\r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'minutes'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <input type=\"time\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-model=\"$ctrl.viewValue\" ng-model-options=\"{allowInvalid: true, debounce: 1000}\" ng-required=\"$ctrl.require\" class=\"form-control\">\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"$ctrl.type == 'time'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <input type=\"time\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" ng-model=\"$ctrl.viewValue\" ng-model-options=\"{allowInvalid: true, debounce: 1000}\" ng-required=\"$ctrl.require\" class=\"form-control\">\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/InputWorkerItem.html\",`<a class=\"clickable salaxy-component salaxy-worker-item\">\r\n    <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" \r\n    avatar=\"match.model\"></salaxy-avatar>\r\n    <b class=\"salaxy-highlight\" ng-bind-html=\"match.label + ' (' + match.model.displayId + ')' | uibTypeaheadHighlight:query\"></b><br />\r\n    <small class=\"salaxy-highlight\"><div ng-bind-html=\"match.model.description | uibTypeaheadHighlight:query\"></div></small>\r\n</a>`);\n\n $templateCache.put(\"salaxy-components/form-controls/Textarea.html\",`<salaxy-form-group ng-if=\"$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value }}</div>\r\n</salaxy-form-group>\r\n<ng-form ng-if=\"!$ctrl.getReadOnly()\" name=\"{{$ctrl.name}}Form\" class=\"salaxy-component salaxy-textarea\">\r\n  <salaxy-form-group ng-if=\"$ctrl.inputMode == 'openClose' &&  !$ctrl.isOpen\" name=\"{{$ctrl.name}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"\">\r\n      <span class=\"salaxy-read-only-value\" style=\"max-width:90%; display:inline-block;\">{{ $ctrl.value }}</span>\r\n      <span class=\"pull-right btn-padding-right\" style=\"padding-top:7px;\">\r\n        <i ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\" class=\"fa fa-pencil clickable\"></i>\r\n      </span>\r\n    </div>\r\n\r\n  </salaxy-form-group>\r\n  <salaxy-form-group ng-if=\"!$ctrl.inputMode || ($ctrl.inputMode == 'openClose' && $ctrl.isOpen)\" name=\"{{$ctrl.name}}\" label=\"{{$ctrl.label}}\" require=\"$ctrl.require\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div ng-if=\"$ctrl.getToolTipHtml()\" class=\"input-group\">\r\n      <textarea class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" ng-change=\"$ctrl.onChange()\"\r\n        ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" rows=\"{{ $ctrl.rows || 3 }}\"></textarea>\r\n      <div class=\"input-group-btn\">\r\n        <button type=\"button\" class=\"btn btn-default\" aria-label=\"Info\" uib-popover-html=\"$ctrl.getToolTipHtml()\" popover-placement=\"{{$ctrl.tooltipPlacement}}\">\r\n          <span class=\"glyphicon glyphicon-question-sign\"></span>\r\n        </button>\r\n        <button ng-if=\"$ctrl.inputMode == 'openClose'\" class=\"btn btn-transparent\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-class=\"{'input-group': $ctrl.inputMode == 'openClose'}\">\r\n      <textarea ng-if=\"!$ctrl.getToolTipHtml()\" class=\"form-control\" autocomplete=\"off\" id=\"{{$ctrl.name}}\" name=\"{{$ctrl.name}}\" placeholder=\"{{ $ctrl.getPlaceholder() | sxyTranslate }}\" ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\"\r\n        ng-change=\"$ctrl.onChange()\" ng-pattern=\"$ctrl.pattern\" ng-required=\"$ctrl.require\" ng-readonly=\"$ctrl.readonly\" ng-disabled=\"$ctrl.getDisabled()\" ng-minlength=\"$ctrl.minlength\" ng-maxlength=\"$ctrl.maxlength\" maxlength=\"{{$ctrl.maxlength}}\" rows=\"{{ $ctrl.rows || 3 }}\"></textarea>\r\n      <div class=\"input-group-btn\" ng-if=\"$ctrl.inputMode == 'openClose'\">\r\n        <button class=\"btn btn-transparent pull-right\" ng-click=\"$ctrl.isOpen = !$ctrl.isOpen\">\r\n          <i class=\"fa fa-pencil\"></i>\r\n        </button>\r\n      </div>\r\n    </div>\r\n    <div ng-show=\"!$ctrl.disableValidationErrors && ($ctrl.validationErrors.length > 0 && ({{$ctrl.name}}Form.{{$ctrl.name}}.$touched || {{$ctrl.name}}Form.$$parentForm.$submitted))\" class=\"input-errors\">\r\n      <span class=\"salaxy-validation-error text-danger small\" ng-repeat=\"validationError in $ctrl.validationErrors\" sxy-text=\"{{ validationError}}\" params=\"{ minlength: $ctrl.minlength, maxlength: $ctrl.maxlength }\"></span><br/>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/form-controls/ValidationSummary.html\",`<div ng-if=\"!$ctrl.hasValidation\" ng-bind-html=\"$ctrl.loadingHtml\"></div>\r\n<div ng-if=\"$ctrl.hasValidation\" class=\"salaxy-component salaxy-validation-summary\">\r\n  <ng-transclude ng-if=\"$ctrl.isValid\"></ng-transclude>\r\n  <div ng-if=\"$ctrl.layout != 'minimal'\">\r\n    <div ng-if=\"!$ctrl.isValid\" class=\"alert alert-danger\">\r\n      <div ng-if=\"$ctrl.hasValidationOrGeneralErrors\">\r\n        <h4 sxy-text=\"SALAXY.NG1.ValidationSummaryComponent.checkForErrors\" ps=\":\"></h4>\r\n        <ul class=\"validation-error-list\">\r\n          <li ng-repeat=\"error in $ctrl.getErrors('!required') | limitTo:3\" ng-class=\"error.type\">{{ $ctrl.getLabel(error) }}</li>\r\n        </ul>\r\n      </div>\r\n      <div ng-if=\"!$ctrl.hasAllRequiredFields\">\r\n        <h4 sxy-text=\"SALAXY.NG1.ValidationSummaryComponent.missingRequired\" ps=\":\"></h4>\r\n        <ul class=\"validation-error-list\">\r\n          <li ng-repeat=\"error in $ctrl.getErrors('required') | limitTo:3\" class=\"warning\">{{ $ctrl.getLabel(error) }}</li>\r\n        </ul>\r\n      </div>\r\n      <button class=\"btn btn-xs btn-danger pull-right\" ng-click=\"$ctrl.showDetails()\" sxy-text=\"SALAXY.UI_Terms.readMore\" ps=\"...\"></button>\r\n    </div>\r\n    <div ng-if=\"$ctrl.hasWarningsOnly\" class=\"alert alert-warning\">\r\n      <h4>Varoituksia:</h4>\r\n      <ul>\r\n        <li ng-repeat=\"error in $ctrl.getErrors('warning') | limitTo:3\">{{ $ctrl.getLabel(error) }}</li>\r\n      </ul>\r\n      <button class=\"btn btn-xs btn-warning pull-right\" ng-click=\"$ctrl.showDetails()\" sxy-text=\"SALAXY.UI_Terms.readMore\" ps=\"...\"></button>\r\n    </div>\r\n  </div>\r\n  <span ng-if=\"$ctrl.layout == 'minimal' && (!$ctrl.isValid || $ctrl.hasWarningsOnly)\" class=\"validation-container\">\r\n    <span ng-if=\"$ctrl.hasValidationOrGeneralErrors\"><span ng-repeat=\"error in $ctrl.getErrors('!required') | limitTo:3\" class=\"validation-error-item\" ng-class=\"error.type\">{{ $ctrl.getLabel(error) }},&nbsp; </span></span>\r\n    <span ng-if=\"!$ctrl.hasAllRequiredFields\"><span ng-repeat=\"error in $ctrl.getErrors('required') | limitTo:3\" class=\"validation-error-item\" ng-class=\"error.type\">{{ $ctrl.getLabel(error) }},&nbsp; </span></span>\r\n    <span ng-if=\"!$ctrl.hasWarningsOnly\"><span ng-repeat=\"error in $ctrl.getErrors('warning') | limitTo:3\" class=\"validation-error-item\" ng-class=\"error.type\">{{ $ctrl.getLabel(error) }},&nbsp; </span></span>\r\n  </span>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/form-controls/ValidationSummaryDetails.html\",`<style type=\"text/css\">\r\n  .panel-validation {\r\n    border-color: var(--salaxy-brand-danger);\r\n  }\r\n  \r\n  .panel-heading-validation {\r\n    border-color: var(--salaxy-brand-danger);\r\n    background-color: var(--salaxy-brand-danger);\r\n  }\r\n</style>\r\n<div class=\"salaxy-component salaxy-calc-details-dialog\">\r\n  <div class=\"panel panel-detail panel-validation\">\r\n    <div class=\"panel-heading panel-heading-validation\">\r\n      <button type=\"button\" class=\"close pull-right\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h1 sxy-text=\"SALAXY.NG1.ValidationSummaryDetailsComponent.moreInfoTitle\"></h1>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div ng-repeat=\"error in $ctrl.data.controller().getErrors()\" class=\"alert\" ng-class=\"error.type=='warning' ? 'alert-warning' : 'alert-danger'\" role=\"alert\">\r\n        <b>{{$ctrl.data.controller().getLabel(error)}}</b>\r\n        <br/>{{$ctrl.data.controller().getDescription(error)}}\r\n      </div>\r\n      <button class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\">OK</button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/ActionButton.html\",`<span ng-switch=\"$ctrl.action\">\r\n  <a ng-switch-when=\"newCalc\" href=\"#/calc/details/new\" class=\"btn salaxy-action-button btn-new-calc btn-labeled-right\" ng-class=\"$ctrl.buttonClass\" ng-disabled=\"$ctrl.disabled\"\r\n    type=\"button\" id=\"new-calc\">\r\n    {{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.newCalculation' | sxyTranslate}}<i class=\"fa fa-plus\"></i>\r\n  </a>\r\n  <div ng-switch-when=\"newCalcForEmployment\" class=\"btn-group btn-new-calc-for-employment\" ng-class=\"$ctrl.buttonClass\" uib-dropdown id=\"new-calc-for-employment\">\r\n    <a class=\"btn btn-primary\" href=\"#/calc/details/{{$ctrl.options.id}}/new-for-employment\">{{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.newCalculation' | sxyTranslate}}</a>\r\n    <button type=\"button\" class=\"btn btn-primary\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\">\r\n      <span class=\"caret\"></span>\r\n      <span class=\"sr-only\"sxy-text=\"SALAXY.NG1.ActionButtonComponent.addCalcTypes\" ps=\"...\"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu>\r\n      <li><a href=\"#/calc/details/{{$ctrl.options.id}}/new-for-employment\" sxy-text=\"SALAXY.NG1.ActionButtonComponent.commonCalc\"></a></li>\r\n      <li><a href=\"#/calc/history/{{$ctrl.options.id}}/new-for-employment\" sxy-text=\"SALAXY.NG1.ActionButtonComponent.historicalCalc\"></a></li>\r\n    </ul>\r\n  </div>\r\n  <a ng-switch-when=\"newMessage\" href=\"#/messages/details/new\" class=\"btn salaxy-action-button btn-new-message btn-labeled-right\" ng-class=\"$ctrl.buttonClass\"\r\n    ng-disabled=\"$ctrl.disabled\" type=\"button\" id=\"new-message\">\r\n    {{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.startNewMessage' | sxyTranslate}}<i class=\"fa fa-plus\"></i>\r\n  </a>\r\n  <a ng-switch-when=\"newPayroll\" href=\"#/payroll/details/new\" class=\"btn salaxy-action-button btn-new-payroll btn-labeled-right\" ng-class=\"$ctrl.buttonClass\"\r\n    ng-disabled=\"$ctrl.disabled\" type=\"button\" id=\"new-payroll\">\r\n    {{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.newPayroll' | sxyTranslate}}<i class=\"fa fa-plus\"></i>\r\n  </a>\r\n  <span ng-switch-when=\"newWorker\" ng-controller=\"EmploymentCrudController as $employmentCtrl\">\r\n    <button ng-click=\"$employmentCtrl.launchCreateEmploymentWizard()\" class=\"btn salaxy-action-button btn-new-worker btn-labeled-right\" ng-class=\"$ctrl.buttonClass\"\r\n      ng-disabled=\"$ctrl.disabled\" type=\"button\" id=\"new-worker\">\r\n      {{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.newWorker' | sxyTranslate}}<i class=\"fa fa-plus\"></i>\r\n    </button>\r\n  </span>\r\n  <span ng-switch-when=\"newTaxcard\">\r\n    <a href=\"#/taxcards\" class=\"btn salaxy-action-button btn-new-payroll btn-labeled-right\" ng-class=\"$ctrl.buttonClass\" ng-disabled=\"$ctrl.disabled\" type=\"button\"\r\n      id=\"new-taxcard\">\r\n      {{$ctrl.label || 'SALAXY.NG1.ActionButtonComponent.sendTaxCard' | sxyTranslate}}<i class=\"fa fa-plus\"></i>\r\n    </a>\r\n  </span>\r\n  <span ng-switch-default class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.ActionButtonComponent.error\"></span>\r\n</span>`);\n\n $templateCache.put(\"salaxy-components/helpers/Alert.html\",`<div class=\"salaxy-component salaxy-alert\">\r\n  <div ng-class=\"'alert alert-' + $ctrl.type\">\r\n    <div>\r\n      <table style=\"width: 100%; border-collapse:separate;\">\r\n        <!-- TODO: Switch this to position:absolute & margins or flex-grid -->\r\n        <tr>\r\n          <td class=\"icon-container hidden-xxs\" ng-if=\"$ctrl.getIcon()\">\r\n            <span class=\"icon\"><i class=\"fa {{ $ctrl.getIcon() }}\"></i></span>\r\n          </td>\r\n          <td>\r\n            <div class=\"main\">\r\n              <ng-transclude ng-transclude-slot=\"main\">\r\n                <p>{{ $ctrl.text }}</p>\r\n              </ng-transclude>\r\n            </div>\r\n          </td>\r\n          <td ng-if=\"$ctrl.hasMoreInfo && !$ctrl.forceMoreInfo\" class=\"text-right\">\r\n            <button class=\"btn btn-info btn-main\" ng-click=\"$ctrl.showMoreInfo = !$ctrl.showMoreInfo\" sxy-text=\"SALAXY.UI_Terms.learnMore\"></button>\r\n          </td>\r\n        </tr>\r\n      </table>\r\n      <div class=\"collapse\" ng-if=\"$ctrl.hasMoreInfo\" ng-class=\"{ show: ($ctrl.showMoreInfo || $ctrl.forceMoreInfo) }\">\r\n        <ng-transclude ng-transclude-slot=\"aside\"></ng-transclude>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/Avatar.html\",`<i class=\"salaxy-avatar fa\" ng-class=\"{'fa-user': $ctrl.isPersonIcon, 'fa-square': $ctrl.isCompanyIcon }\" ng-style=\"{color: $ctrl.color }\">\r\n    <img ng-src=\"{{ $ctrl.avatar.url }}\" ng-show=\"$ctrl.isImage\" />\r\n    <strong ng-show=\"!$ctrl.isImage\">{{ $ctrl.initials }}</strong>\r\n</i>`);\n\n $templateCache.put(\"salaxy-components/helpers/Calendar.html\",`<div class=\"salaxy-component salaxy-calendar\">\r\n  <button ng-if=\"$ctrl.showExport\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.exportCalendarPdf()\">\r\n    <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></span>\r\n    <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n  </button>\r\n  <button ng-if=\"$ctrl.showExport\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.exportCalendarExcel()\">\r\n    <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadExcel\"></span>\r\n    <i class=\"fa fa-file-excel-o\" aria-hidden=\"true\"></i>\r\n  </button>\r\n  <div ng-if=\"$ctrl.mode == 'align-weekdays'\">\r\n    <table class=\"calendar\">\r\n      <thead>\r\n        <tr>\r\n          <th class=\"calendar-title\">\r\n            {{ $ctrl.start | date : \"yyyy\" }}\r\n            <span ng-if=\"($ctrl.start | date : 'yyyy') != ($ctrl.end | date : 'yyyy')\">- {{ $ctrl.end | date : \"yyyy\" }}</span>\r\n          </th>\r\n          <th class=\"day day-of-week-{{ day.weekday }}\" ng-repeat=\"day in $ctrl.weekdaysForMonth track by $index\">{{ day.text }}</th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"month in $ctrl.months\">\r\n          <td class=\"month-title\">{{ month.title }}</td>\r\n          <td class=\"beginning-spacer\" ng-if=\"month.firstDayDayOfWeek > 1\" colspan=\"{{ month.firstDayDayOfWeek - 1}}\"></td>\r\n          <td class=\"day day-of-week-{{ day.weekday }} day-type-{{ day.dayType }} clickable\" ng-repeat=\"day in month.days\" ng-click=\"$ctrl.dateClicked(day, $ctrl.series[0], $event)\">\r\n            <div ng-repeat=\"ev in day.periods[0]\" ng-class=\"$ctrl.getCssClass(ev)\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, null, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"\r\n              ng-style=\"$ctrl.getEventStyle(ev, day.periods[0])\" ></div>\r\n            <i ng-repeat=\"ev in day.singleDays[0]\" ng-class=\"$ctrl.getCssClass(ev)\" ng-style=\"$ctrl.getEventStyle(ev, day.singleDays[0])\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, null, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"></i>\r\n            <span class=\"day-number\">{{ day.day }}</span><br />\r\n          </td>\r\n          <td class=\"day end-spacer\" ng-if=\"(38 - month.firstDayDayOfWeek - month.daysInMonth) > 0\" colspan=\"{{ 38 - month.firstDayDayOfWeek - month.daysInMonth  }}\"></td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-if=\"$ctrl.mode == 'align-left'\">\r\n    <table class=\"calendar\">\r\n      <thead>\r\n        <tr>\r\n          <th class=\"calendar-title\">\r\n            {{ $ctrl.start | date : \"yyyy\" }}\r\n            <span ng-if=\"($ctrl.start | date : 'yyyy') != ($ctrl.end | date : 'yyyy')\">- {{ $ctrl.end | date : \"yyyy\" }}</span>\r\n          </th>\r\n          <th class=\"day\" ng-repeat=\"day in $ctrl.weekdaysForMonth track by $index\">{{ day.text }}</th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"month in $ctrl.months\">\r\n          <td class=\"month-title\">{{ month.title }}</td>\r\n          <td class=\"day day-of-week-{{ day.weekday }} day-type-{{ day.dayType }} clickable\" ng-repeat=\"day in month.days\" ng-click=\"$ctrl.dateClicked(day, $ctrl.series[0], $event)\">\r\n            <div ng-repeat=\"ev in day.periods[0]\" ng-class=\"$ctrl.getCssClass(ev)\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, null, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"\r\n              ng-style=\"$ctrl.getEventStyle(ev, day.periods[0])\" ></div>\r\n            <i ng-repeat=\"ev in day.singleDays[0]\" ng-class=\"$ctrl.getCssClass(ev)\" ng-style=\"$ctrl.getEventStyle(ev, day.singleDays[0])\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, null, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"></i>\r\n            <span class=\"day-number\">{{ day.weekdayText }}</span><br />\r\n          </td>\r\n          <td class=\"day end-spacer\" ng-if=\"(31 - month.daysInMonth) > 0\" colspan=\"{{ 31 - month.daysInMonth }}\"></td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-if=\"$ctrl.mode == 'horizontal'\" class=\"calendar-horizontal\">\r\n    <table class=\"calendar\" style=\"width: max-content;margin-bottom: 10px;\">\r\n      <thead>\r\n        <tr>\r\n          <th class=\"calendar-title\" rowspan=\"2\">\r\n            {{ $ctrl.start | date : \"yyyy\" }}\r\n            <span ng-if=\"($ctrl.start | date : 'yyyy') != ($ctrl.end | date : 'yyyy')\">- {{ $ctrl.end | date : \"yyyy\" }}</span>\r\n          </th>\r\n          <th class=\"month-title\" ng-repeat=\"month in $ctrl.months\" colspan=\"{{ month.daysInMonth }}\">{{ month.title }} {{ month.year }}</th>\r\n        </tr>\r\n        <tr>\r\n          <th class=\"day day-of-week-{{ day.weekday }} day-type-{{ day.dayType }}\" ng-click=\"$ctrl.dateClicked(day, null, $event)\" ng-repeat=\"day in $ctrl.allDays\">\r\n            {{ day.weekdayText }}<br />\r\n            {{ day.day }}\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"series in $ctrl.series\" ng-init=\"seriesIndex = $index\">\r\n          <td class=\"series-title clickable\" ng-class=\"{ 'has-avatar': series.avatar }\" ng-click=\"$ctrl.seriesClicked(series, $event)\">\r\n            <salaxy-avatar avatar=\"series.avatar\" ng-if=\"series.avatar\"\r\n              style=\"font-size: 30px;left: 2px;position: absolute;top: 2px;\"></salaxy-avatar>\r\n            <div><strong>{{ series.title }}</strong></div>\r\n            <div>{{ series.description }}</div>\r\n          </td>\r\n          <td class=\"day day-of-week-{{ day.weekday }} day-type-{{ day.dayType }} clickable\"\r\n            ng-repeat=\"day in $ctrl.allDays\" ng-click=\"$ctrl.dateClicked(day, series, $event)\">\r\n            <div ng-repeat=\"ev in day.periods[seriesIndex]\" ng-class=\"$ctrl.getCssClass(ev)\" ng-style=\"$ctrl.getEventStyle(ev, day.periods[seriesIndex])\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, series, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"></div>\r\n            <i ng-repeat=\"ev in day.singleDays[seriesIndex]\" ng-class=\"$ctrl.getCssClass(ev)\" ng-style=\"$ctrl.getEventStyle(ev, day.singleDays[seriesIndex])\"\r\n              ng-click=\"$ctrl.eventClicked(ev, day, series, $event)\" uib-tooltip=\"{{ ev.summary }}\" tooltip-append-to-body=\"true\"></i>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-if=\"$ctrl.mode == 'list'\">\r\n    <h3>TODO: List layout</h3>\r\n    <p>Period: {{ { start: $ctrl.start, end: $ctrl.end } | sxyDateRange }}</p>\r\n    <fieldset ng-repeat=\"month in $ctrl.monthlyList\">\r\n      <legend>{{ month.title }} / {{ month.year }}</legend>\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th>Date</th>\r\n            <th>Weekday</th>\r\n            <th>Events</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"day in month.days\">\r\n            <td>{{ day.day }}</td>\r\n            <td>\r\n              {{ day.weekdayText }}\r\n              <span ng-if=\"day.dayType != 'normal'\">{{ day.dayType }}</span>\r\n            </td>\r\n            <td>\r\n              <ul ng-repeat=\"eventArr in day.events\" ng-init=\"seriesIndex = $index\">\r\n                <li ng-repeat=\"period in eventArr\"><strong>{{ $ctrl.series[$index].title || $ctrl.series[$index].key }}: {{ period | sxyDateRange }}</strong> {{ period.title }}: {{ period.description }}</li>\r\n              </ul>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/Chart.html\",`\r\n<div ng-if=\"$ctrl.config\" ng-init=\"$ctrl.init()\" class=\"salaxy-component salaxy-chart\" ng-class=\"$ctrl.customClass\" ng-style=\"{width: $ctrl.customWidth, height: $ctrl.customHeight}\">\r\n  <canvas class=\"chart\" ng-class=\"$ctrl.chart.config.type ==='line' ? 'chart-line' : 'chart-pie'\"></canvas>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/DataMapper.html\",`<div class=\"salaxy-component salaxy-data-mapper\">\r\n  <div ng-if=\"!$ctrl.model\" class=\"alert alert-danger\">Data mapper not found</div>\r\n  <div ng-if=\"$ctrl.model\" ng-switch=\"$ctrl.type || 'value-map'\">\r\n    <div ng-switch-when=\"value-map\">\r\n      <table class=\"table table-condensed\">\r\n        <thead>\r\n          <tr>\r\n            <th ng-repeat=\"selector in $ctrl.model.map\" style=\"padding: 0;\">\r\n              <salaxy-input readonly=\"true\" label=\"header\" label-type=\"plain\" name=\"header\" ng-model=\"selector.source\"></salaxy-input>\r\n            </th>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.model\">\r\n            <th ng-repeat=\"selector in $ctrl.model.map\" style=\"padding: 0;\">\r\n              <salaxy-input-enum name=\"parserMapperSource\" label-type=\"plain\" options=\"$ctrl.model.target.allKeys\" ng-model=\"selector.target\" type=\"select\"\r\n                  ng-change=\"selector.resolve($ctrl.model.source.getSchema(), $ctrl.model.target.getSchema())\"></salaxy-input-enum>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.model.source.value\">\r\n            <td ng-repeat=\"selector in $ctrl.model.map\">{{row[selector.source]}}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div ng-switch-when=\"debug\">\r\n      <uib-tabset>\r\n        <uib-tab index=\"'info'\" heading=\"Basic info\">\r\n          <fieldset class=\"form-horizontal\" style=\"max-width: 800px;\">\r\n            <salaxy-input name=\"title\" ng-model=\"$ctrl.model.title\" label=\"Title\"></salaxy-input>\r\n            <salaxy-input name=\"uri\" ng-model=\"$ctrl.model.uri\" label=\"Uri\"></salaxy-input>\r\n            <salaxy-input-boolean name=\"isSourceAList\" ng-model=\"$ctrl.model.isSourceAList\" label=\"Source is a list\"></salaxy-input-boolean>\r\n            <button type=\"button\" ng-click=\"$ctrl.model.doMap()\" class=\"btn btn-default\">Do map</button>\r\n          </fieldset>\r\n        </uib-tab>\r\n        <uib-tab index=\"'mapping'\" heading=\"Mapping\">\r\n          <table class=\"table table-striped\">\r\n            <thead>\r\n              <th>{{$ctrl.model.source.name || \"Source unknown\"}} ({{$ctrl.model.source.schema.format || \"format unknown\"}})</th>\r\n              <th>Type / format</th>\r\n              <th class=\"text-center\">Mapping</th>\r\n              <th>{{$ctrl.model.target.name || \"Target unknown\"}} ({{$ctrl.model.target.schema.format || \"format unknown\"}})</th>\r\n              <th>Type / format</th>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"selector in $ctrl.model.map\">\r\n                <td>\r\n                  <salaxy-input-enum name=\"parserMapperSource\" label-type=\"plain\" options=\"$ctrl.model.source.allKeys\" ng-model=\"selector.source\" type=\"select\"\r\n                    ng-change=\"selector.resolve($ctrl.model.source.getSchema(), $ctrl.model.target.getSchema())\"></salaxy-input-enum>\r\n                </td>\r\n                <td ng-if=\"selector.sourceProp\">\r\n                  <span>{{ selector.sourceProp.schema.type }} / {{ selector.sourceProp.schema.format || \"-\" }}</span>\r\n                  <salaxy-json-formatter json=\"selector.sourceProp\" key=\"'...'\" type=\"dialog\"></salaxy-json-formatter>\r\n                </td>\r\n                <td ng-if=\"!selector.sourceProp\" class=\"text-danger\">Not found!</td>\r\n                <td class=\"text-center middle\">\r\n                  <i ng-if=\"selector.flatten.length\" class=\"fa fa-lg text-primary fa-sitemap\" aria-hidden=\"true\"></i>\r\n                  <i ng-if=\"!selector.flatten.length && !selector.func\" class=\"fa fa-lg text-primary fa-arrow-circle-right\" aria-hidden=\"true\"></i>\r\n                  <i ng-if=\"!selector.flatten.length && selector.func\" class=\"fa fa-cog fa-spin fa-lg fa-fw text-primary\" aria-hidden=\"true\"></i>\r\n                </td>\r\n                <td ng-if=\"!selector.flatten.length\">\r\n                  <salaxy-input-enum name=\"parserMapperTarget\" label-type=\"plain\" options=\"$ctrl.model.target.allKeys\" ng-model=\"selector.target\" type=\"select\"\r\n                    ng-change=\"selector.resolve($ctrl.model.source.getSchema(), $ctrl.model.target.getSchema())\"></salaxy-input-enum>\r\n                </td>\r\n                <td ng-if=\"!selector.flatten.length && selector.targetProp\">\r\n                  <span>{{ selector.targetProp.schema.type }} / {{ selector.targetProp.schema.format || \"-\" }}</span>\r\n                  <salaxy-json-formatter json=\"selector.targetProp\" key=\"'...'\" type=\"dialog\"></salaxy-json-formatter>\r\n                </td>\r\n                <td ng-if=\"!selector.flatten.length && !selector.targetProp\" class=\"text-danger\">Not found!</td>\r\n                <td ng-if=\"selector.flatten.length\" colspan=\"2\">\r\n                  <table>\r\n                    <tr ng-repeat=\"flattenSelector in selector.flatten\">\r\n                      <td>\r\n                        <salaxy-input-enum name=\"parserMapperTarget\" label-type=\"plain\" options=\"$ctrl.model.target.allKeys\" ng-model=\"flattenSelector.target\" type=\"select\"\r\n                          ng-change=\"flattenSelector.resolve(flattenSelector.sourceProp.schema.items, $ctrl.model.target.getSchema())\"></salaxy-input-enum>\r\n                      </td>\r\n                      <td>\r\n                        <span>{{ flattenSelector.targetProp.schema.type }} / {{ flattenSelector.targetProp.schema.format || \"-\" }}</span>\r\n                        <salaxy-json-formatter json=\"flattenSelector.targetProp\" key=\"'...'\" type=\"dialog\"></salaxy-json-formatter>\r\n                      </td>\r\n                    </tr>\r\n                  </table>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </uib-tab>\r\n        <uib-tab index=\"'source'\" heading=\"Source data\">\r\n          <salaxy-data-mapper model=\"$ctrl.model\" type=\"source-value\"></salaxy-data-mapper>\r\n        </uib-tab>\r\n        <uib-tab index=\"'target'\" heading=\"Target data\">\r\n          <salaxy-data-mapper model=\"$ctrl.model\" type=\"target-value\"></salaxy-data-mapper>\r\n        </uib-tab>\r\n        <uib-tab index=\"'json'\" heading=\"JSON\">\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-4\">\r\n              <h3>Source</h3>\r\n              <salaxy-json-formatter json=\"$ctrl.model.source\" open=\"3\"></salaxy-json-formatter>\r\n            </div>\r\n            <div class=\"col-sm-4\">\r\n              <h3>Mapper</h3>\r\n              <salaxy-json-formatter json=\"$ctrl.model.map\" open=\"3\"></salaxy-json-formatter>\r\n            </div>\r\n            <div class=\"col-sm-4\">\r\n              <h3>Target</h3>\r\n              <salaxy-json-formatter json=\"$ctrl.model.target\" open=\"3\"></salaxy-json-formatter>\r\n            </div>\r\n          </div>\r\n        </uib-tab>\r\n      </uib-tabset>      \r\n    </div>\r\n    <div ng-switch-when=\"source-value\">\r\n      <table class=\"table table-condensed\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.ODataImportComponent.step3.okey\"></th>\r\n            <th ng-repeat=\"header in $ctrl.model.source.keys\">\r\n              {{header}}\r\n              (<span>{{ $ctrl.model.source.schema.properties[header].type || \"-\" }} / {{ $ctrl.model.source.schema.properties[header].format || \"-\" }}</span>\r\n              <salaxy-json-formatter json=\"$ctrl.model.source.schema.properties[header]\" key=\"'...'\" type=\"dialog\"></salaxy-json-formatter>)\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.model.source.value\">\r\n            <td>\r\n              <div ng-if=\"row.validation && row.validation.errors && row.validation.errors.length\" ng-repeat=\"error in row.validation.errors\">\r\n                <button uib-popover=\"{{ error.msg }}\" popover-title=\"{{ error.code }}\" type=\"button\" class=\"btn btn-danger\">{{ error.type }}</button><br>\r\n              </div>\r\n              <div ng-if=\"row.validation && row.validation.isValid\">\r\n                <span class=\"text-success\" sxy-text=\"SALAXY.NG1.ODataImportComponent.step3.okey\"></span>\r\n              </div>\r\n            </td>\r\n            <td ng-repeat=\"header in $ctrl.model.source.keys\">{{row[header]}}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div ng-switch-when=\"target-value\">\r\n      <table class=\"table table-condensed\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.ODataImportComponent.step3.okey\"></th>\r\n            <th ng-repeat=\"header in $ctrl.model.target.keys\">\r\n              {{header}}\r\n              (<span>{{ $ctrl.model.target.schema.properties[header].type || \"-\" }} / {{ $ctrl.model.target.schema.properties[header].format || \"-\" }}</span>\r\n              <salaxy-json-formatter json=\"$ctrl.model.target.schema.properties[header]\" key=\"'...'\" type=\"dialog\"></salaxy-json-formatter>)\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.model.target.value\">\r\n            <td>\r\n              <div ng-if=\"row.validation.errors.length\" ng-repeat=\"error in row.validation.errors\">\r\n                <button uib-popover=\"{{ error.msg }}\" popover-title=\"{{ error.code }}\" type=\"button\" class=\"btn btn-danger\">{{ error.type }}</button><br>\r\n              </div>\r\n              <div ng-if=\"row.validation && row.validation.isValid\">\r\n                <span class=\"text-success\" sxy-text=\"SALAXY.NG1.ODataImportComponent.step3.okey\"></span>\r\n              </div>\r\n            </td>\r\n            <td ng-repeat=\"header in $ctrl.model.target.keys\">{{row[header]}}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/DataImport.html\",`<div class=\"salaxy-component salaxy-data-import\">\r\n  <div class=\"salaxy-wizard\">\r\n    <div class=\"row wizard-icon-row\">\r\n      <div class=\"col-sm-4\">\r\n        <span class=\"salaxy-avatar\">\r\n          <i class=\"fa\" ng-class=\"$ctrl.action == 'upload' ? 'fa-circle' : 'fa-circle-o'\"><strong>1</strong></i>\r\n        </span>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <span class=\"salaxy-avatar\">\r\n          <i class=\"fa\" ng-class=\"$ctrl.action == 'validate' ? 'fa-circle' : 'fa-circle-o'\"><strong>2</strong></i>\r\n        </span>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <span class=\"salaxy-avatar\">\r\n          <i class=\"fa\" ng-class=\"$ctrl.action == 'import' ? 'fa-circle' : 'fa-circle-o'\"><strong>3</strong></i>\r\n        </span>\r\n      </div>\r\n    </div>\r\n    <div class=\"row wizard-text-row\">\r\n      <div class=\"col-sm-4\">\r\n        <span sxy-text=\"SALAXY.NG1.DataImport.stepUpload.title\"></span>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <span sxy-text=\"SALAXY.NG1.DataImport.stepValidate.title\"></span>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <span sxy-text=\"SALAXY.NG1.DataImport.stepImport.title\"></span>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-switch=\"$ctrl.action\">\r\n    <div ng-switch-when=\"upload\">\r\n      <p sxy-text=\"SALAXY.NG1.DataImport.stepUpload.intro\"></p>\r\n      <p>\r\n        <span class=\"badge bg-primary\" ng-if=\"$ctrl.sourceData.length\">{{'SALAXY.NG1.DataImport.badgeUploadedLabel' | sxyTranslate }} {{$ctrl.sourceData.length}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span>\r\n      </p>\r\n      <div class=\"modal-footer text-left\">\r\n        <button id=\"info\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.help()\">\r\n          <span>{{'SALAXY.NG1.DataImport.stepUpload.buttonHelp' | sxyTranslate}} <i class=\"fa fa-info-circle\"></i></span>\r\n        </button>\r\n        <button id=\"upload\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\" ngf-select=\"$ctrl.upload($files)\" ngf-multiple=\"false\" ngf-max-size=\"10MB\">\r\n          <span>{{'SALAXY.NG1.DataImport.stepUpload.buttonUpload' | sxyTranslate}} <i class=\"fa fa-file-excel-o\"></i></span>\r\n        </button>\r\n        <button id=\"paste\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.paste()\">\r\n          <span>{{'SALAXY.NG1.DataImport.stepUpload.buttonPaste' | sxyTranslate}} <i class=\"fa fa-clipboard\"></i></span>\r\n        </button>\r\n        <button id=\"reset\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.reset(true)\">\r\n          {{'SALAXY.NG1.DataImport.stepUpload.buttonReset' | sxyTranslate}}\r\n        </button>\r\n        <button class=\"btn btn-primary pull-right\" sxy-text=\"SALAXY.UI_Terms.next\" ng-click=\"$ctrl.action='validate';$ctrl.validate()\"></button>\r\n      </div>\r\n    </div>\r\n    <div ng-switch-when=\"validate\">\r\n      <p sxy-text=\"SALAXY.NG1.DataImport.stepValidate.intro\"></p>\r\n      <p>\r\n        <span ng-if=\"$ctrl.validationUndoneRows\"><span class=\"badge bg-default\">{{'SALAXY.NG1.DataImport.badgeUndoneLabel' | sxyTranslate }} {{$ctrl.validationUndoneRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n        <span ng-if=\"$ctrl.validationErrorRows\"><span class=\"badge bg-danger\">{{'SALAXY.NG1.DataImport.badgeErrorLabel' | sxyTranslate }} {{$ctrl.validationErrorRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n        <span ng-if=\"$ctrl.validationSuccessRows\"><span class=\"badge bg-success\">{{'SALAXY.NG1.DataImport.badgeSuccessLabel' | sxyTranslate }} {{$ctrl.validationSuccessRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n      </p>\r\n      <div class=\"modal-footer text-left\">\r\n        <button class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\" ng-click=\"$ctrl.action='upload'\"></button>\r\n        <button id=\"validate\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.validate()\">\r\n          {{'SALAXY.NG1.DataImport.stepValidate.buttonValidate' | sxyTranslate}}\r\n        </button>\r\n        <button  ng-repeat=\"validator in $ctrl.getExtraValidators()\"  ng-disabled=\"$ctrl.isImporting || $ctrl.isValidating\" type=\"button\" class=\"btn btn-default\"\r\n          ng-click=\"validator.validate()\">\r\n          {{ validator.buttonLabel }}\r\n        </button>\r\n        <button  ng-repeat=\"enricher in $ctrl.getDataEnrichers()\"  ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-default\"\r\n        ng-click=\"enricher.enrich()\">\r\n        {{ enricher.buttonLabel }}\r\n       </button>\r\n        <button class=\"btn btn-primary pull-right\" sxy-text=\"SALAXY.UI_Terms.next\" ng-click=\"$ctrl.action='import'\"></button>\r\n      </div>\r\n    </div>\r\n    <div ng-switch-when=\"import\">\r\n      <p sxy-text=\"SALAXY.NG1.DataImport.stepImport.intro\"></p>\r\n      <p>\r\n      <div class=\"progress\" ng-if=\"$ctrl.importTotal\">\r\n        <div style=\"min-width: 10em;\" ng-style=\"{'width': ($ctrl.importCurrent * 100 / $ctrl.importTotal) + '%' }\" class=\"progress-bar\" role=\"progressbar\"\r\n          aria-valuenow=\"{{$ctrl.importCurrent}}\" aria-valuemin=\"0\" aria-valuemax=\"{{$ctrl.importTotal}}\">\r\n          <span><span ng-if=\"$ctrl.importCurrent != $ctrl.importTotal\"><span ng-if=\"$ctrl.isImporting\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></span>\r\n            {{$ctrl.importCurrent}}/{{$ctrl.importTotal}}</span>\r\n        </div>\r\n      </div>\r\n      <span ng-if=\"$ctrl.importIgnoredRows\"><span class=\"badge bg-default\">{{'SALAXY.NG1.DataImport.badgeIgnoredLabel' | sxyTranslate }} {{$ctrl.importIgnoredRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n      <span ng-if=\"$ctrl.importSuccessRows\"><span class=\"badge bg-success\">{{'SALAXY.NG1.DataImport.badgeSuccessLabel' | sxyTranslate }} {{$ctrl.importSuccessRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n      <span ng-if=\"$ctrl.importWarningRows\"><span class=\"badge bg-warning\">{{'SALAXY.NG1.DataImport.badgeWarningLabel' | sxyTranslate }} {{$ctrl.importWarningRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n      <span ng-if=\"$ctrl.importErrorRows\"><span class=\"badge bg-danger\">{{'SALAXY.NG1.DataImport.badgeErrorLabel' | sxyTranslate }} {{$ctrl.importErrorRows}} {{'SALAXY.NG1.DataImport.badgeUnit' | sxyTranslate }}</span></span>\r\n      </p>\r\n      <div class=\"modal-footer text-left\">\r\n        <button class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\" ng-click=\"$ctrl.action='validate';$ctrl.validate()\"></button>\r\n        <div class=\"pull-right\">\r\n          <button id=\"cancel\" ng-disabled=\"!$ctrl.isImporting\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.cancel()\">\r\n            {{'SALAXY.NG1.DataImport.stepImport.buttonCancel' | sxyTranslate}}\r\n          </button>\r\n          <button id=\"import\" ng-disabled=\"$ctrl.isImporting\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.import()\">\r\n            {{'SALAXY.NG1.DataImport.stepImport.buttonImport' | sxyTranslate}}\r\n          </button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div id=\"import-table\"></div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/EInvoiceAddressSelect.html\",`<div class=\"modal-eInvoiceAddress-select\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CompanyImport.enrichEInvoiceAddressesSelectionMessage\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.name\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.receiver\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.intermediator\"></th>\r\n            <th class=\"right\">              \r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.logic.addresses\">\r\n            <td>\r\n              <span>{{row.receiverName}}</span><br>\r\n              <small>{{row.receiverOfficialId}}</small>\r\n            </td>\r\n            <td>\r\n              <span>{{row.receiver}}</span><br>\r\n            </td>\r\n            <td>\r\n              <span>{{row.intermediatorName}}</span><br>\r\n              <small>{{row.intermediator}}</small>\r\n            </td>\r\n            <td class=\"right middle\">\r\n              <button class=\"btn btn-sm btn-default\" type=\"button\"\r\n                ng-click=\"$ctrl.logic.select($ctrl.current, row, $close)\">{{ 'SALAXY.UI_Terms.select' | sxyTranslate }}\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging.html\",`<div class=\"salaxy-component salaxy-import-staging\">\r\n  <div class=\"pull-right\"><small>{{ $ctrl.serverUrl }}</small></div>\r\n  <div class=\"toolbar\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.reloadUi()\"><i class=\"fa fa-refresh\" aria-hidden=\"true\"></i></button>\r\n    <div class=\"btn-group\" uib-dropdown role=\"group\">\r\n      <button type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle data-toggle=\"dropdown\" aria-haspopup=\"true\" ng-class=\"{ disabled: !$ctrl.worktimeApi.payrolls }\"\r\n        aria-expanded=\"false\" style=\"max-width: 280px; overflow: hidden; text-overflow: ellipsis;\">\r\n        {{ $ctrl.worktimeApi.payroll ? $ctrl.worktimeApi.payroll.input.title : (\"SALAXY.NG1.ImportStagingComponent.toolbar.selectPayroll\" | sxyTranslate) }}\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu>\r\n        <li><a href=\"\" ng-click=\"$ctrl.selectPayroll(null)\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.toolbar.removeFilter\"></a></li>\r\n        <li ng-repeat=\"payroll in $ctrl.worktimeApi.payrolls\"><a href=\"\" ng-click=\"$ctrl.selectPayroll(payroll.id)\">{{ payroll.shortText }}</a></li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.worktimeApi.payroll\" ng-click=\"$ctrl.commitPayroll('payroll')\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.toolbar.commitPayroll\"></button>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculateAllWorktimes()\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.toolbar.recalculateAll\"></button>\r\n  </div>\r\n  <ng-include src=\"'salaxy-components/helpers/import/staging/ImportStaging_list.html'\"></ng-include>\r\n  <!-- TODO: Move to a dialog -->\r\n  <ng-include src=\"'salaxy-components/helpers/import/staging/ImportStaging_test_data.html'\"></ng-include>\r\n</div>\r\n<ng-include ng-if=\"$ctrl.worktimeApi.current\" src=\"'salaxy-components/helpers/import/staging/ImportStaging_details.html'\"></ng-include>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging_details.html\",`<div class=\"salaxy-payroll-details-calc salaxy-payroll-details-dialog\"\r\n  ng-style=\"{'max-width': 'calc(100vw - 260px)','width': $ctrl.userSettings.ng1Binder('worktimeImport.calcDialogSize').val || '60%'}\"\r\n  ng-class=\"{ 'offcanvas-show': $ctrl.showOffcanvas }\">\r\n  <div class=\"modal-header\">\r\n    <span class=\"pull-right\">\r\n      <button type=\"button\" class=\"btn btn-transparent\"\r\n        ng-click=\"$ctrl.userSettings.ng1Binder('worktimeImport.calcDialogSize').val = ($ctrl.userSettings.ng1Binder('worktimeImport.calcDialogSize').val == '100%' ? '60%' : '100%')\"><i\r\n          ng-class=\"$ctrl.userSettings.ng1Binder('worktimeImport.calcDialogSize').val == '100%' ? 'fa fa-compress' : 'fa fa-expand'\"></i></button>\r\n      <button type=\"button\" class=\"btn btn-primary\" aria-label=\"Close\" ng-click=\"$ctrl.showDetails()\"><span class=\"fa fa-times\"></span></button>\r\n    </span>\r\n    <div ng-if=\"$ctrl.worktimeApi.current\">\r\n      <salaxy-avatar class=\"\" avatar=\"$ctrl.worktimeApi.current.preview.employments[0].personalInfo.avatar\"></salaxy-avatar>\r\n      <div style=\"margin-left: 100px;margin-top: -14px;\">\r\n        <h3 class=\"modal-title\">{{ $ctrl.worktimeApi.current.preview.employments[0].personalInfo.avatar.displayName }}</h3>\r\n        <div>{{ $ctrl.worktimeApi.current.preview.employments[0].identity.personalId }} ({{ \"EmploymentRelationType.\" + $ctrl.worktimeApi.current.preview.employments[0].info.type | sxyEnum }})</div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <table style=\"width: 100%\">\r\n          <tr>\r\n            <td class=\"middle\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.details.period\"></td>\r\n            <td>\r\n              <select class=\"form-control\" ng-model=\"$ctrl.worktimeApi.currentCalcId\">\r\n                <option ng-repeat=\"item in $ctrl.worktimeApi.calculations\" value=\"{{ item.value }}\">{{ item.text }}</option>\r\n              </select>\r\n            </td>\r\n          </tr>\r\n          <tr>\r\n            <td sxy-text=\"SALAXY.NG1.ImportStagingComponent.details.payroll\"></td>\r\n            <td>\r\n              <div>{{ $ctrl.worktimeApi.getPayrollForCurrentCalc().shortText || $ctrl.worktimeApi.currentCalc.info.payrollId || (\"SALAXY.NG1.ImportStagingComponent.details.noPayroll\" | sxyTranslate) }}</div>\r\n              <div class=\"text-danger\" ng-if=\"$ctrl.worktimeApi.payrollId && $ctrl.worktimeApi.payrollId != $ctrl.worktimeApi.currentCalc.info.payrollId\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.details.notTheSameAsSelectedPayroll\"></div>\r\n            </td>\r\n          </tr>\r\n        </table>\r\n      </div>\r\n      <div class=\"col-sm-6 text-danger text-right\" ng-if=\"$ctrl.worktimeApi.rowsOutsidePayrollCount\">\r\n        Työntekijällä on {{ $ctrl.worktimeApi.rowsOutsidePayrollCount }} riviä palkkalistojen ulkopuolella.\r\n        <a href=\"\" ng-click=\"$ctrl.worktimeApi.currentCalcId = undefined\">Näytä</a>\r\n      </div>\r\n    </div>\r\n    <uib-tabset active=\"$ctrl.calcView\">\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.rawRows' | sxyTranslate}}\" index=\"'rawRows'\"></uib-tab>\r\n      <uib-tab heading=\"Käsin syötetyt rivit\" index=\"'manual'\"></uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.reports' | sxyTranslate}}\" index=\"'reports'\" disabled=\"\"></uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.rows' | sxyTranslate}}\" index=\"'rows'\"></uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.calculator' | sxyTranslate}}\" index=\"'calculator'\"></uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.salarySlips' | sxyTranslate}}\" index=\"'salarySlips'\"></uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.ImportStagingComponent.details.debug' | sxyTranslate}}\" index=\"'debug'\"></uib-tab>\r\n    </uib-tabset>\r\n    <div ng-switch=\"$ctrl.calcView\">\r\n      <div ng-switch-when=\"manual\">\r\n        <salaxy-calc-rows-2019-editor ng-if=\"$ctrl.worktimeApi.current\" rows=\"$ctrl.worktimeApi.editableRows\" mode=\"edit\"\r\n          title=\"Käsin muokattavat rivit\"></salaxy-calc-rows-2019-editor>\r\n        <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.saveManualRows()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n      <div ng-switch-when=\"rawRows\">\r\n        <div class=\"btn-toolbar\">\r\n          <div class=\"btn-group\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'preview,new,error,deleted,edited'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'preview,new,error,deleted,edited'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.statusGroup.todo\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'committed'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'committed'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.committed\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'deleted,new'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'deleted,new'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.statusGroup.waitingCommit\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = undefined\" ng-disabled=\"!$ctrl.$ctrlRows.statuses\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.undefined\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'ignored'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'ignored'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.ignored\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'error'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'error'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.error\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$ctrlRows.statuses = 'preview'\" ng-disabled=\"$ctrl.$ctrlRows.statuses == 'preview'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.preview\"></button>\r\n          </div>\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculateWorktime()\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.details.recalculate\"></button>\r\n          <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.worktimeApi.currentCalc.info.payrollId\" ng-click=\"$ctrl.commitPayroll('employment')\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.details.commitPayroll\"></button>\r\n          <div class=\"btn-group\" uib-dropdown>\r\n            <button id=\"single-button\" type=\"button\" class=\"btn\" ng-class=\"$ctrl.$ctrlRows.getSelectedRows().length ? 'btn-primary' : 'btn-default'\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n              Valitut ({{ $ctrl.$ctrlRows.getSelectedRows().length }}) <span class=\"caret\"></span>\r\n            </button>\r\n            <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n              <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.$ctrlRows.toggleSelectedRow('all', true)\">Valitse kaikki</a></li>\r\n              <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.$ctrlRows.toggleSelectedRow('all', false)\">Poista valinnat</a></li>\r\n              <li class=\"divider\"></li>\r\n              <li class=\"dropdown-header\">Aseta valitut tilaan...</li>\r\n              <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.setStatus($ctrl.$ctrlRows.getSelectedRows(), 'ignored')\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.ignored\"></a></li>\r\n              <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.setStatus($ctrl.$ctrlRows.getSelectedRows(), 'new')\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.statusGroup.todo\"></a></li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n        <salaxy-calc-rows-editor ng-if=\"$ctrl.worktimeApi.current\" type=\"worktime-import-employment\" rows=\"$ctrl.worktimeApi.filteredRows\"\r\n          title=\"Rivit importissa\" ng-ref=\"$ctrl.$ctrlRows\" mode=\"read-only\" statuses=\"'preview,new,error,deleted,edited'\"></salaxy-calc-rows-editor>\r\n      </div>\r\n      <div ng-switch-when=\"rows\">\r\n        <div class=\"alert alert-warning\">\r\n          HUOM: Tämän välilehti on vain laskelman esikatselua varten. Rivejä ei voi muokata / et voi tallentaa muutoksia.\r\n          Tee muutokset \"Käsin syötetyt rivit\"-välilehdellä.\r\n        </div>\r\n        <salaxy-calc-rows-2019-editor parent=\"$ctrl.worktimeApi.currentCalc\"\r\n          title=\"{{'SALAXY.NG1.PayrollComponent.payrollCalcs.calcRowEditor.title' | sxyTranslate}}\" mode=\"edit\" show-edit-buttons=\"false\"\r\n          show-gross-totals=\"true\"></salaxy-calc-rows-2019-editor>\r\n      </div>\r\n      <div ng-switch-when=\"calculator\">\r\n        <div class=\"alert alert-warning\">\r\n          HUOM: Tämän välilehti on vain laskelman esikatselua varten. Rivejä ei voi muokata / et voi tallentaa muutoksia.\r\n          Tee muutokset \"Käsin syötetyt rivit\"-välilehdellä.\r\n        </div>\r\n        <salaxy-calc ng-if=\"$ctrl.worktimeApi.currentCalc\" model=\"$ctrl.worktimeApi.currentCalc\"></salaxy-calc>\r\n      </div>\r\n      <div ng-switch-when=\"salarySlips\">\r\n        <ng-include src=\"'salaxy-components/helpers/import/staging/ImportStaging_salarySlipsList.html'\"></ng-include>\r\n      </div>\r\n      <div ng-switch-when=\"reports\">\r\n        <salaxy-calc-reports ng-if=\"$ctrl.worktimeApi.currentCalc\" calcs=\"[$ctrl.worktimeApi.currentCalc]\" preview=\"true\" view=\"page1\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n      </div>\r\n      <div ng-switch-when=\"debug\" class=\"row\">\r\n        <div ng-if=\"$ctrl.worktimeApi.currentJson\">\r\n          <div class=\"toolbar\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.worktimeApi.saveJson()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.deleteWorktime()\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n          </div>\r\n          <div ng-if=\"$ctrl.worktimeApi.error\">\r\n            <h2 sxy-text=\"SALAXY.UI_Terms.error\"></h2>\r\n            <salaxy-json-formatter json=\"$ctrl.worktimeApi.error\"></salaxy-json-formatter>\r\n            <textarea style=\"width: 100%; height: 400px;\">{{ $ctrl.worktimeApi.error | json }}</textarea>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.worktimeApi.error = ''\" sxy-text=\"SALAXY.UI_Terms.clear\"></button>\r\n          </div>\r\n          <sxy-code-editor ng-model=\"$ctrl.worktimeApi.currentJson\" lang=\"json\" height=\"calc(100vh - 372px)\"></sxy-code-editor>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDetails()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging_list.html\",`<div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th></th>\r\n        <th>\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.title\"></div>\r\n          <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.id\"></div>\r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.grossSalary\"></div>\r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.netSalary\"></div>\r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n          <div sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n        </th>\r\n        <th class=\"right\">\r\n          <small>\r\n            <div class=\"text-muted\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.preview\"></div>\r\n            <div class=\"text-primary\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.new\"><b></b></div>\r\n            <div class=\"\"><s sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.deleted\"></s></div>\r\n            <div class=\"text-danger\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.error\"></div>\r\n          </small>\r\n        </th>\r\n        <th class=\"right\">\r\n          <small>\r\n            <div class=\"\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.total\"></div>\r\n            <div class=\"\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.committed\"><b></b></div>\r\n            <div class=\"text-muted\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.status.ignored\"></div>\r\n          </small>\r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.list.calcCount\"></div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"emp in $ctrl.worktimeApi.filteredList\" class=\"clickable\" ng-click=\"$ctrl.showDetails(emp.id)\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"emp.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td>\r\n          <div><b>{{ emp.sortableName }}</b></div>\r\n          <div>{{ emp.personalId }} ({{ \"EmploymentRelationType.\" + emp.employmentType | sxyEnum }})</div>\r\n          <div ng-if=\"emp.payrolls.unknown\" class=\"text-danger\"><small>Palkkalistojen ulkopuolella {{ emp.payrolls.unknown.rows.count }} riviä.</small></div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ $ctrl.getTotals(emp).calcs.gross | currency }}</div>\r\n          <div><s>{{ $ctrl.getTotals(emp).committed.gross | currency }}</s></div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ $ctrl.getTotals(emp).calcs.net | currency }}</div>\r\n          <div><s>{{ $ctrl.getTotals(emp).committed.net | currency }}</s></div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ emp.createdAt | sxyTime }}</div>\r\n          <div>{{ emp.updatedAt | sxyTime }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <small>\r\n            <div class=\"text-muted\">{{ $ctrl.getTotals(emp).rows.preview }}</div>\r\n            <div ng-if=\"$ctrl.getTotals(emp).rows.new\" class=\"bg-primary badge\">&nbsp;&nbsp;<b>{{ $ctrl.getTotals(emp).rows.new }}</b>&nbsp;</div>\r\n            <div ng-if=\"!$ctrl.getTotals(emp).rows.new\" class=\"text-primary\"><b>0</b></div>\r\n            <div class=\"\"><s>{{ $ctrl.getTotals(emp).rows.deleted || \"&nbsp;\" }}</s></div>\r\n            <div ng-if=\"$ctrl.getTotals(emp).rows.error\" class=\"bg-danger badge\">&nbsp;&nbsp;<b>{{ $ctrl.getTotals(emp).rows.error }}</b>&nbsp;</div>\r\n            <div ng-if=\"!$ctrl.getTotals(emp).rows.error\" class=\"text-danger\"><b>0</b></div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <small>\r\n            <div class=\"\">{{ $ctrl.getTotals(emp).rows.count }}</div>\r\n            <div class=\"\"><b>{{ $ctrl.getTotals(emp).rows.committed }}</b></div>\r\n            <div class=\"text-muted\">{{ $ctrl.getTotals(emp).rows.ignored }}</div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ $ctrl.getTotals(emp).calcs.count }}</div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging_overview.html\",`<div>\r\n  <div ng-if=\"$ctrl.serverUrl\">\r\n    <uib-tabset active=\"$ctrl.overviewView\">\r\n      <uib-tab heading=\"Overview\" index=\"'default'\"></uib-tab>\r\n      <uib-tab heading=\"Tests\" index=\"'tests'\"></uib-tab>\r\n    </uib-tabset>\r\n    <div ng-switch=\"$ctrl.overviewView\">\r\n      <div ng-switch-when=\"default\">\r\n        <div>Current staging server: <a ng-href=\"{{ $ctrl.serverUrl }}\" target=\"_blank\">{{ $ctrl.serverUrl }}</a></div>\r\n      </div>\r\n      <div ng-switch-when=\"tests\">\r\n        <fieldset>\r\n          <legend>Upload test data</legend>\r\n          <p class=\"lead\">\r\n            Upload a test file to the staging server.\r\n            The file should be a JSON file with employment relations or rows: The same structure that an integration sends.\r\n          </p>\r\n          <div class=\"row\">\r\n            <div class=\"col-md-6\">\r\n              <form ng-submit=\"$ctrl.uploadTestFile($event)\">\r\n                <input type=\"file\" class=\"form-control\" />\r\n                <button type=\"submit\" class=\"btn btn-primary\">Process uploaded file</button>\r\n              </form>\r\n            </div>\r\n            <div class=\"col-md-6\">\r\n              <p>Get demo files:</p>\r\n              <ul>\r\n                <li>Rows: check the personal ID before processing</li>\r\n                <ul>\r\n                  <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/rows_2023-09-01_2023-12-22.json' }}\" target=\"_blank\">2023-09-01 - 2023-12-22</a></li>\r\n                  <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/rows_2023-11-01_2023-11-30.json' }}\" target=\"_blank\">2023-11-01 - 2023-11-30</a></li>\r\n                </ul>\r\n                <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/employment-190372-942M.json' }}\" target=\"_blank\">Employment, Pauliina Palkkanen, 190372-942M</a>.</li>\r\n              </ul>\r\n            </div>\r\n          </div>\r\n          <salaxy-json-formatter json=\"$ctrl.uploadResults\" key=\"'result'\" open=\"0\"></salaxy-json-formatter>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend>Create a Payroll / Nepton Payment Period</legend>\r\n          <div class=\"btn-toolbar\">\r\n            <div class=\"btn-goup\">\r\n              <p>TODO: Add possibility for setting the values and creating the Payroll</p>\r\n              <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.runTest('createUpdatePaymentPeriod')\">Demo button (fixed ID)</button>\r\n            </div>\r\n          </div>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.serverUrl\" class=\"container\">\r\n    <div class=\"alert alert-info\">\r\n      Integrations has not been set up for this environment.\r\n      Please specify the integration server in the settings (PRO settings => other)\r\n      or contact customer services.\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging_salarySlipsList.html\",`<div ng-if=\"!$ctrl.currentEmploymentPdf\">\r\n  <div class=\"btn-toolbar\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.salarySlipListType = 'all'\" ng-disabled=\"$ctrl.salarySlipListType == 'all'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.type.all\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.salarySlipListType = 'preview'\" ng-disabled=\"$ctrl.salarySlipListType == 'preview'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.type.preview\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.salarySlipListType = 'committed'\" ng-disabled=\"$ctrl.salarySlipListType == 'committed'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.type.committed\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.salarySlipListType = 'distinct'\" ng-disabled=\"$ctrl.salarySlipListType == 'distinct'\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.type.distinct\"></button>\r\n    </div>\r\n  </div>\r\n  <table class=\"table table-condenced\">\r\n    <thead>\r\n      <tr>\r\n        <th>\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.status\"></div>\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.id\"></div>\r\n        </th>\r\n        <th class=\"right\" style=\"font-size: 0.75em;\">\r\n          <div sxy-text=\"SALAXY.ENUM.CalcGroup.baseSalary.label\"></div>\r\n          <div sxy-text=\"SALAXY.ENUM.CalcGroup.salaryAdditions.label\"></div>\r\n          <div sxy-text=\"SALAXY.ENUM.CalcGroup.benefits.label\"></div>\r\n          <div sxy-text=\"SALAXY.ENUM.CalcGroup.deductions.label\"></div>\r\n          <div sxy-text=\"SALAXY.ENUM.CalcGroup.expenses.label\"></div> \r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.grossSalary\"></div>\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.netSalary\"></div>\r\n        </th>\r\n        <th class=\"right\">\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.salaryDate\"></div>\r\n          <div sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.period\"></div>\r\n        </th>\r\n        <th></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"calc in $ctrl.currentEmploymentCalcs\">\r\n        <td>\r\n          <div>\r\n            {{ \"CalculationStatus.\" + calc.status | sxyEnum }}\r\n            <span ng-if=\"calc.status == 'payrollDraft'\"><a ng-href=\"{{ '#/payroll/details/' + calc.data.payrollId }}\" sxy-text=\"SALAXY.NG1.ImportStagingComponent.salarySlipList.payrollLink\"></a></span>\r\n            <!-- TODO: Add links when paid etc. -->\r\n          </div>\r\n          <div class=\"small truncate\" style=\"max-width: 256px;\"><code>{{ calc.id }}</code></div>\r\n        </td>\r\n        <td class=\"right\" style=\"font-size: 0.75em;\">\r\n          <div>{{ calc.data.salary | currency }}</div>\r\n          <div>{{ calc.data.allowances | currency }}</div>\r\n          <div>{{ calc.data.benefits | currency }}</div>\r\n          <div>{{ calc.data.deductions | currency }}</div>\r\n          <div>{{ calc.data.expenses | currency }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ calc.grossSalary | currency }}</div>\r\n          <div>{{ calc.data.workerPayment | currency }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ calc.salaryDate | sxyDate }}</div>\r\n          <div>{{ calc.data | sxyDateRange }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <button class=\"btn btn-primary\" ng-click=\"$ctrl.showReportDialog(calc.id)\"><i class=\"fa  fa-search\"></i> <span sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n          <button class=\"btn btn-default\" ng-click=\"$ctrl.showSalarySlipPdf(calc.id)\"><i class=\"fa  fa-file-pdf-o\"></i> <span sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></span></button>\r\n          <button class=\"btn btn-default\" sxy-if-role=\"test\" ng-click=\"$ctrl.showSalarySlipHtml(calc.id)\">TEST: html</span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>\r\n\r\n<div ng-if=\"$ctrl.currentEmploymentPdf\">\r\n  <div class=\"btn-toolbar\">\r\n    <button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.showSalarySlipPdf(undefined)\"><i class=\"fa fa-times\"></i> <span sxy-text=\"SALAXY.UI_Terms.close\"></span></button>\r\n  </div>\r\n  <salaxy-spinner ng-if=\"$ctrl.currentEmploymentPdf == 'loading'\"></salaxy-spinner>\r\n  <iframe ng-if=\"$ctrl.currentEmploymentPdf != 'loading'\" style=\"width:100%;height:200vh\" ng-src=\"{{ $ctrl.currentEmploymentPdf }}\"></iframe>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/staging/ImportStaging_test_data.html\",`<div sxy-if-role=\"test\">\r\n  <p>&nbsp;</p>\r\n  <hr />\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDebug = !$ctrl.showDebug\">TEST ONLY: show/hide debug upload</button>\r\n  <div style=\"max-width: 800px;\">\r\n    <fieldset ng-if=\"$ctrl.showDebug\">\r\n      <legend>Upload test data</legend>\r\n      <p class=\"lead\">\r\n        Upload a test file to the staging server.\r\n        The file should be a JSON file with employment relations or rows: The same structure that an integration sends.\r\n      </p>\r\n      <div class=\"row\">\r\n        <div class=\"col-md-6\">\r\n          <form ng-submit=\"$ctrl.uploadTestFile($event)\">\r\n            <input type=\"file\" class=\"form-control\" />\r\n            <button type=\"submit\" class=\"btn btn-primary\">Process uploaded file</button>\r\n          </form>\r\n        </div>\r\n        <div class=\"col-md-6\">\r\n          <p>Get demo files:</p>\r\n          <ul>\r\n            <li>Rows: check the personal ID before processing</li>\r\n            <ul>\r\n              <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/rows_2023-09-01_2023-12-22.json' }}\" target=\"_blank\">2023-09-01 - 2023-12-22</a></li>\r\n              <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/rows_2023-11-01_2023-11-30.json' }}\" target=\"_blank\">2023-11-01 - 2023-11-30</a></li>\r\n            </ul>\r\n            <li><a ng-href=\"{{ $ctrl.serverUrl + '/test-data/employment-190372-942M.json' }}\" target=\"_blank\">Employment, Pauliina Palkkanen, 190372-942M</a>.</li>\r\n          </ul>\r\n        </div>\r\n      </div>\r\n      <salaxy-json-formatter json=\"$ctrl.uploadResults\" key=\"'result'\" open=\"0\"></salaxy-json-formatter>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/import/WorktimeImport.html\",`<div class=\"salaxy-component salaxy-worktime-import\">\r\n  <h1 sxy-text=\"SALAXY.NG1_Sitemap.pro-service.worktime-imports.details\"></h1>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <div class=\"btn-toolbar\" role=\"toolbar\">\r\n      <div class=\"btn-group\" role=\"group\">\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.process('parse')\">Parse</button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.process('validate')\">Validate</button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.process('preview')\">Preview</button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.process('previewWithEmployments')\">Preview (commit employments)</button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.process('import')\">Import</button>\r\n      </div>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.save()\">Save</button>\r\n      <a href=\"#/worktime-imports\" class=\"btn btn-default\">Back to list</a>\r\n    </div>\r\n    <sxy-form ng-ref=\"$frm\" open-api=\"http://localhost:82/schemas/v02.json\" xx-open-api=\"salaxy-secure/schemas/v02.json\" type=\"WorktimeImport\" model=\"$ctrl.current\">\r\n      <div>\r\n        <salaxy-tabs active=\"active\">\r\n          <salaxy-tab heading=\"Perustiedot\">\r\n            <salaxy-tab-content>\r\n              <div class=\"row\">\r\n                <div class=\"col-sm-6\">\r\n                  <fieldset>\r\n                    <legend>Basic data</legend>\r\n                    <sxy-input model=\"form.id\"></sxy-input>\r\n                    <sxy-input model=\"form.createdAt\"></sxy-input>\r\n                    <sxy-input model=\"form.updatedAt\"></sxy-input>\r\n                    <sxy-input model=\"form.header.status\"></sxy-input>\r\n                  </fieldset>\r\n                </div>\r\n                <div class=\"col-sm-6\">\r\n                  <fieldset>\r\n                    <legend>Control data</legend>\r\n                    <sxy-input model=\"form.header.payrollId\" label=\"Palkkalistan ID\"></sxy-input>\r\n                    <sxy-input model=\"form.header.sourceId\" label=\"ID (lähde)\"></sxy-input>\r\n                    <sxy-input model=\"form.header.salaryDate\" format=\"date\" label=\"Palkkapäivä\"></sxy-input>\r\n                    <sxy-input model=\"form.header.period\" label=\"Palkkausi\"></sxy-input>\r\n                  </fieldset>\r\n                </div>\r\n              </div>\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Tiedostot\">\r\n            <salaxy-tab-content>\r\n              <table class=\"table\">\r\n                <thead>\r\n                  <tr>\r\n                    <th>\r\n                      File<br />\r\n                      File type (mime type)\r\n                    </th>\r\n                    <th>Data</th>\r\n                  </tr>\r\n                </thead>\r\n                <tbody>\r\n                  <tr ng-repeat=\"file in $ctrl.current.files\">\r\n                    <td style=\"width: 50%;\">\r\n                      <salaxy-input name=\"fileName\" ng-model=\"file.name\" label-type=\"plain\"></salaxy-input>\r\n                      <salaxy-input name=\"fileMimeType\" ng-model=\"file.mimeType\" label-type=\"plain\"></salaxy-input>\r\n                      <salaxy-input name=\"fileUsecaseUri\" label=\"Usecase\" ng-model=\"file.usecase.uri\"></salaxy-input>\r\n                    </td>\r\n                    <td style=\"width: 50%;\">\r\n                      <salaxy-textarea name=\"fileData\" ng-model=\"file.data\" rows=\"5\" label-type=\"plain\"></salaxy-textarea>\r\n                    </td>\r\n                  </tr>\r\n                </tbody>\r\n              </table>\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Employment relations\">\r\n            <salaxy-tab-content>\r\n              <sxy-table ng-if=\"!$ctrl.isLoading\" doc=\"http://localhost:82/schemas/v02.json\" schema=\"WorktimeImportEmployment\"\r\n                data=\"$ctrl.current.employments\" include=\"$ctrl.employmentsCols\"></sxy-table>\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Salary rows\">\r\n            <salaxy-tab-content>\r\n              <salaxy-calc-rows-editor ng-if=\"!$ctrl.isLoading\" rows=\"$ctrl.current.rows\" title=\"Import rows\" type=\"worktime-import\"></salaxy-calc-rows-editor>\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Preview: Employment\">\r\n            <salaxy-tab-content>\r\n              TODO: Employment preview UI here\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Preview\">\r\n            <salaxy-tab-content>\r\n              TODO: Calc preview (also absences & holidays?)\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n          <salaxy-tab heading=\"Debugger\">\r\n            <salaxy-tab-content>\r\n              <salaxy-json-formatter json=\"$ctrl.current\"></salaxy-json-formatter>\r\n            </salaxy-tab-content>\r\n          </salaxy-tab>\r\n        </salaxy-tabs>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/JsonFormatter.html\",`<button ng-class=\"$ctrl.btnClass ? $ctrl.btnClass : 'btn btn-default btn-xs'\" ng-if=\"$ctrl.type == 'dialog'\" ng-click=\"$ctrl.showDialog()\">\r\n  <span ng-if=\"$ctrl.hasKey\"><span class=\"key-text\">{{ $ctrl.key }}</span></span>\r\n  <span ng-if=\"!$ctrl.hasKey && $ctrl.isArray()\"><span class=\"bracket\">[</span><span class=\"number\">{{$ctrl.json.length}}</span><span class=\"bracket\">]</span></span>\r\n  <span ng-if=\"!$ctrl.hasKey && !$ctrl.isArray()\"><span class=\"bracket\">{</span><span class=\"number\">{{$ctrl.getKeys().length}}</span><span class=\"bracket\">}</span></span>\r\n</button>\r\n<div class=\"json-formatter-row\" ng-if=\"$ctrl.type != 'dialog'\">\r\n  <a ng-click=\"$ctrl.toggleOpen()\">\r\n    <span class=\"toggler {{ $ctrl.isOpen ? 'open' : ''}}\" ng-if=\"$ctrl.isObject()\"></span>\r\n    <span class=\"key {{$ctrl.changes.type}}\" ng-if=\"$ctrl.hasKey\"><span class=\"key-text\">{{ $ctrl.key }}</span><span ng-if=\"$ctrl.changes\"> ({{ $ctrl.changes.icon }})</span><span class=\"colon\">:</span></span>\r\n    <span class=\"value\">\r\n      <span ng-if=\"$ctrl.isObject()\">\r\n        <span ng-if=\"$ctrl.isArray()\"><span class=\"bracket\">[</span><span class=\"number\">{{$ctrl.json.length}}</span><span class=\"bracket\">]</span></span>\r\n        <span ng-if=\"!$ctrl.isArray()\"><span class=\"bracket\">{</span><span class=\"number\">{{$ctrl.getKeys().length}}</span><span class=\"bracket\">}</span></span>\r\n      </span>\r\n      <span ng-if=\"!$ctrl.isObject()\" ng-click=\"$ctrl.openLink($ctrl.isUrl)\" class=\"{{ $ctrl.jsonType }}\"\r\n        ng-class=\"{ date: $ctrl.isDate, url: $ctrl.isUrl }\">{{$ctrl.parseValue($ctrl.json)}}<del\r\n        ng-if=\"$ctrl.changes\">{{$ctrl.changes.oldValue}}</del></span>\r\n    </span>\r\n    <span ng-if=\"$ctrl.showThumbnail()\" class=\"thumbnail-text\">{{$ctrl.getThumbnail()}}</span>\r\n  </a>\r\n  <div class=\"children\" ng-if=\"$ctrl.getKeys().length && $ctrl.isOpen\">\r\n    <salaxy-json-formatter ng-repeat=\"key in $ctrl.getKeys() track by $index\" key=\"key\" open=\"$ctrl.childrenOpen()\"\r\n      json=\"$ctrl.json[key]\" compare=\"$ctrl.compare\" compare-to=\"$ctrl.compareTo[key]\"></salaxy-json-formatter>\r\n    <salaxy-json-formatter ng-repeat=\"key in $ctrl.deletedKeys track by $index\" key=\"key\" open=\"$ctrl.childrenOpen()\"\r\n      json=\"$ctrl.json[key]\" compare=\"$ctrl.compare\" compare-to=\"$ctrl.compareTo[key]\"></salaxy-json-formatter>\r\n  </div>\r\n  <div class=\"children empty object\" ng-if=\"$ctrl.isEmptyObject()\"></div>\r\n  <div class=\"children empty array\" ng-if=\"$ctrl.getKeys() && !$ctrl.getKeys().length && $ctrl.isOpen && $ctrl.isArray()\"></div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/JsonFormatterDialog.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{ $ctrl.logic.title }}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-json-formatter json=\"$ctrl.current\" type=\"{{ $ctrl.logic.type }}\" open=\"$ctrl.logic.open\" compare=\"$ctrl.logic.compare\" compare-to=\"$ctrl.logic.compareTo\" key=\"$ctrl.logic.key\"></salaxy-json-formatter>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/NaviSitemap.html\",`<div class=\"salaxy-component salaxy-navi-sitemap\" ng-if=\"$ctrl.mode != 'horizontal'\">\r\n\r\n  <ul class=\"list-group\" ng-class=\"{'salaxy-navi-3-level': $ctrl.mode == '3-level'}\">\r\n    <li ng-repeat=\"section in $ctrl.filterHidden($ctrl.sitemap)\" class=\"list-group-item\">\r\n      <a ng-href=\"{{section.url}}\" ng-click=\"!$ctrl.hasChildren(section) ? $ctrl.toggleNavi() : return\" ng-class=\"{ 'active' : $ctrl.isCurrent(section)}\">\r\n        <span ng-if=\"$ctrl.mode != 'default' && $ctrl.hasChildren(section)\">\r\n          <i aria-hidden=\"true\" class=\"fa pull-right\" ng-class=\"$ctrl.isCurrent(section) ? 'fa-chevron-up' : 'fa-chevron-down' \"></i>\r\n        </span> {{section.title | sxyTranslate}} <span ng-if=\"$ctrl.isTest(section)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span>\r\n      </a>\r\n      <ul ng-if=\"$ctrl.hasChildren(section) && ($ctrl.mode == 'default' || $ctrl.isCurrent(section))\">\r\n        <li ng-repeat=\"subNavi in $ctrl.filterHidden(section.children)\">\r\n          <a ng-href=\"{{ $ctrl.getUrl(subNavi) }}\" ng-click=\"$ctrl.toggleNavi()\" ng-class=\"{ 'active' : $ctrl.isCurrent(subNavi)}\">{{subNavi.title | sxyTranslate}} <span ng-if=\"$ctrl.isTest(subNavi)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span></a>\r\n\r\n          <ul ng-if=\"$ctrl.mode == '3-level' && $ctrl.isCurrent(subNavi) && $ctrl.hasChildren(subNavi)\">\r\n            <li ng-repeat=\"naviLevel3 in $ctrl.filterHidden(subNavi.children)\">\r\n              <a ng-href=\"{{ $ctrl.getUrl(naviLevel3) }}\" ng-click=\"$ctrl.toggleNavi()\" ng-class=\"{'active' : $ctrl.isCurrent(naviLevel3)}\">{{naviLevel3.title | sxyTranslate}} <span ng-if=\"$ctrl.isTest(naviLevel3)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span></a>\r\n            </li>\r\n          </ul>\r\n        </li>\r\n      </ul>\r\n    </li>\r\n  </ul>\r\n  <div class=\"poweredby\">\r\n    <span class=\"poweredby-image\"></span>\r\n  </div>\r\n</div>\r\n\r\n<div class=\"salaxy-component salaxy-navi-sitemap\" ng-if=\"$ctrl.mode == 'horizontal'\">\r\n\r\n  <header class=\"salaxy-navi-header-horizontal\">\r\n    <div class=\"container-fluid\">\r\n      <div class=\"visible-xs\">\r\n        <span class=\"pull-left page-title-sm\"><span class=\"uppercase\"><strong>{{ $ctrl.currentPath[0].title | sxyTranslate }}</strong></span> <span class=\"small\" ng-if=\"$ctrl.hasChildren($ctrl.currentPath[0])\">/ {{$ctrl.current.title | sxyTranslate}}</span></span>\r\n        <button type=\"button\" class=\"navbar-toggle btn pull-right btn-lg\" ng-click=\"$ctrl.toggleNavi()\">\r\n          <i class=\"fa  fa-bars\" aria-hidden=\"true\"></i>\r\n        </button>\r\n      </div>\r\n      <div class=\"collapse navbar-collapse\" uib-collapse=\"!$ctrl.isNaviOpen\">\r\n        <ul class=\"nav navbar-nav\">\r\n          <li ng-repeat=\"section in $ctrl.filterHidden($ctrl.sitemap)\" ng-class=\"{ 'active' : $ctrl.isCurrentSection(section)}\" uib-dropdown>\r\n            <a ng-if=\"!$ctrl.hasChildren(section)\" ng-href=\"{{section.url}}\">{{section.title | sxyTranslate}}</a>\r\n            <a ng-if=\"$ctrl.hasChildren(section)\" role=\"button\" uib-dropdown-toggle>{{section.title | sxyTranslate}}<span class=\"caret\"></span></a>\r\n            <ul ng-if=\"$ctrl.hasChildren(section)\" class=\"dropdown-menu\" role=\"menu\" uib-dropdown-menu>\r\n              <li ng-repeat=\"subNavi in $ctrl.filterHidden(section.children)\">\r\n                <a ng-href=\"{{ $ctrl.getUrl(subNavi) }}\" ng-click=\"$ctrl.toggleNavi()\" ng-class=\"{'active' : $ctrl.isCurrent(subNavi)}\">\r\n                  {{subNavi.title | sxyTranslate}} <span ng-if=\"$ctrl.isTest(subNavi)\" class=\"badge bg-info\"><span class=\"small\">test</span></span>\r\n                </a>\r\n              </li>\r\n            </ul>\r\n          </li>\r\n        </ul>\r\n      </div>\r\n    </div>\r\n  </header>\r\n  <div class=\"hidden-xs breadcrumb-container\">\r\n    <span class=\"text-primary\"><span class=\"uppercase\"><strong>{{ $ctrl.currentPath[0].title | sxyTranslate }}</strong></span> <span class=\"small\" ng-if=\"$ctrl.hasChildren($ctrl.currentPath[0])\">/ {{$ctrl.current.title | sxyTranslate}}</span></span>\r\n\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/NaviStarterLayout.html\",`<salaxy-spinner ng-if=\"$ctrl.showFullPageLoader\" full-screen=\"true\" heading=\"SALAXY.UI_Terms.loading\"></salaxy-spinner>\r\n<div ng-if=\"!$ctrl.showFullPageLoader && (!$ctrl.layout || $ctrl.layout == 'default')\" ng-cloak class=\"salaxy-component salaxy-navi-page-container\" ng-class=\"{ 'salaxy-navi-sm-opened': $ctrl.isNaviOpen }\">\r\n\r\n  <ng-transclude ng-transclude-slot=\"nav\">\r\n    <nav class=\"salaxy-navi-sidebar hidden-print\">\r\n      <div class=\"salaxy-logo-container\">\r\n        <a href=\"/#/\"></a>\r\n      </div>\r\n      <div class=\"visible-sm visible-xs mobile-login-container text-center\">\r\n        <salaxy-login-button></salaxy-login-button>\r\n      </div>\r\n      <salaxy-navi-sitemap mode=\"accordion\"></salaxy-navi-sitemap>\r\n    </nav>\r\n  </ng-transclude>\r\n  <header class=\"salaxy-navi-header-mobile\">\r\n    <button type=\"button\" class=\"salaxy-navi-hamburger hidden-print btn btn-default pull-right\" ng-click=\"$ctrl.toggleNavi()\">\r\n      <span class=\"sr-only\" sxy-text=\"SALAXY.UI_Terms.navigation\"></span>\r\n      <i class=\"fa  fa-bars\" aria-hidden=\"true\"></i>\r\n    </button>\r\n    <h1>{{ $ctrl.title | sxyTranslate }}</h1>\r\n  </header>\r\n  <div class=\"salaxy-navi-main-container\">\r\n    <content>\r\n      <ng-transclude ng-transclude-slot=\"header\">\r\n        <header class=\"salaxy-navi-header-default\">\r\n          <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' : 'container'\">\r\n            <div class=\"row\">\r\n              <div class=\"col-xs-12\">\r\n                <h1 class=\"page-title\">\r\n                  {{ $ctrl.title | sxyTranslate }}\r\n                </h1>\r\n                <div class=\"pull-right  hidden-print\">\r\n                  <salaxy-login-button class='pull-right'></salaxy-login-button>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </header>\r\n      </ng-transclude>\r\n      <div id=\"salaxy-alert-container\"></div>\r\n      <ng-transclude ng-transclude-slot=\"main\">\r\n        <main>\r\n          <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' : 'container'\" ng-if=\"!$ctrl.getDisabled()\" ng-view autoscroll=\"true\"></div>\r\n          <div class=\"container\" ng-if=\"$ctrl.getDisabled()\">\r\n            <div class=\"alert alert-info\" sxy-text=\"SALAXY.UI_Terms.pageDisabledAlert\"></div>\r\n          </div>\r\n        </main>\r\n      </ng-transclude>\r\n    </content>\r\n  </div>\r\n</div>\r\n\r\n<div ng-if=\"!$ctrl.showFullPageLoader && $ctrl.layout == 'iframe'\" ng-cloak class=\"salaxy-component salaxy-navi-page-container iframe-container\">\r\n  <div class=\"salaxy-navi-main-container\">\r\n    <content>\r\n      <ng-transclude ng-transclude-slot=\"header\" ng-if=\"$ctrl.mode != 'horizontal'\">\r\n\r\n        <header class=\"salaxy-navi-header-default\">\r\n          <div class=\"container-fluid\">\r\n            <div class=\"row\">\r\n              <div class=\"col-xs-12\">\r\n                <h1 class=\"page-title\">\r\n                  {{ $ctrl.title | sxyTranslate }}\r\n                </h1>\r\n                <div class=\"pull-right\" ng-if=\"$ctrl.hasChildren($ctrl.currentPath[0])\" style=\"margin-left:10px;\">\r\n                  <div class=\"btn-group dropdown\" uib-dropdown>\r\n                    <button class=\"btn btn-default dropdown-toggle btn-submenu\" uib-dropdown-toggle aria-haspopup=\"true\" aria-expanded=\"false\">\r\n                      <span class=\"hidden-xs\">{{ ($ctrl.currentPath[0].subMenuTitle || 'SALAXY.UI_Terms.menu') | sxyTranslate }}</span>\r\n                      <i class=\"fa fa-chevron-circle-down hidden-xs dropdown-icon\"></i>\r\n                      <i class=\"fa fa-bars visible-xs\" aria-hidden=\"true\"></i>\r\n                    </button>\r\n                    <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu role=\"menu\">\r\n                      <li class=\"dropdown-item\" ng-repeat=\"subNavi in $ctrl.filterHidden($ctrl.currentPath[0].children)\">\r\n                        <a class=\"\" ng-href=\"{{subNavi.url}}\">\r\n                          <span>{{ subNavi.title | sxyTranslate }}</span>\r\n                        </a>\r\n                      </li>\r\n                    </ul>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </header>\r\n      </ng-transclude>\r\n\r\n      <ng-transclude ng-transclude-slot=\"nav\" ng-if=\"$ctrl.mode == 'horizontal'\">\r\n\r\n        <salaxy-navi-sitemap mode=\"{{$ctrl.mode}}\"></salaxy-navi-sitemap>\r\n      </ng-transclude>\r\n\r\n\r\n      <div id=\"salaxy-alert-container\"></div>\r\n      <ng-transclude ng-transclude-slot=\"main\">\r\n        <main salaxy-if-role=\"company\">\r\n          <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' : 'container'\" ng-if=\"!$ctrl.getDisabled()\" ng-view autoscroll=\"true\"></div>\r\n          <div class=\"container\" ng-if=\"$ctrl.getDisabled()\">\r\n            <div class=\"alert alert-info\" sxy-text=\"SALAXY.UI_Terms.pageDisabledAlert\"></div>\r\n          </div>\r\n        </main>\r\n        <main salaxy-if-role=\"!company\">\r\n          <div class=\"salaxy-navi-page-container salaxy-component salaxy-tpl-iframe-anon\" style=\"padding-left: 0;\">\r\n            <div class=\"container\" style=\"max-width: 600px; margin-top: 10vh;\">\r\n              <div class=\"alert alert-danger\">\r\n                <h2 sxy-text=\"SALAXY.UI_Terms.sessionExpired\"></h2>\r\n                <p class=\"lead text-muted\" sxy-text=\"SALAXY.UI_Terms.sessionExpiredEmbedded\"></p>\r\n                <div sxy-if-role=\"person\">\r\n                  <p>&nbsp;</p>\r\n                  <pre><small>ERROR: Authenticated as personal, not supported.</small></pre>\r\n                </div>\r\n                <div sxy-if-role=\"test\">\r\n                  \r\n                  <small>Test only:</small> <salaxy-login-button></salaxy-login-button>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </main>\r\n      </ng-transclude>\r\n    </content>\r\n  </div>\r\n</div>\r\n<div ng-if=\"!$ctrl.showFullPageLoader && $ctrl.layout == 'pro-customer'\" ng-cloak class=\"salaxy-component salaxy-navi-page-container iframe-container\">\r\n  <div class=\"salaxy-navi-main-container\">\r\n    <content>\r\n      <ng-transclude ng-transclude-slot=\"header\">\r\n      </ng-transclude>\r\n      <div id=\"salaxy-alert-container\"></div>\r\n      <ng-transclude ng-transclude-slot=\"main\">\r\n        <main>\r\n          <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' : 'container'\" ng-if=\"!$ctrl.getDisabled()\" ng-view autoscroll=\"true\"></div>\r\n          <div class=\"container\" ng-if=\"$ctrl.getDisabled()\">\r\n            <div class=\"alert alert-info\" sxy-text=\"SALAXY.UI_Terms.pageDisabledAlert\"></div>\r\n          </div>\r\n        </main>\r\n      </ng-transclude>\r\n    </content>\r\n  </div>\r\n</div>\r\n</div>\r\n</main>\r\n</ng-transclude>\r\n</content>\r\n</div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/Spinner.html\",`<div ng-cloak ng-class=\"{'sxy-spinner-full-screen-container': $ctrl.fullScreen, 'salaxy-component': true, 'salaxy-spinner': true, }\">\r\n  <div class=\"sxy-spinner-container\">\r\n    <div class=\"sxy-spinner\">\r\n      <svg class=\"sxy-spinner-bg\" viewBox=\"0 0 64 64\"><circle cx=\"32\" cy=\"32\" r=\"26\"></circle></svg>\r\n      <svg class=\"sxy-spinner-spin\" viewBox=\"0 0 64 64\">\r\n        <circle transform=\"translate(32,32)\" r=\"26\"></circle>\r\n      </svg>\r\n    </div>\r\n    <h3 ng-if=\"$ctrl.heading\" class=\"spinner-heading\">{{$ctrl.getHeading()}}</h3>\r\n    <p style=\"white-space: pre;\" ng-if=\"$ctrl.text\" class=\"spinner-text\">{{$ctrl.text | sxyTranslate}}</p>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/Tab.html\",`<div class=\"tabpane\" ng-class=\"{ active: $ctrl.selected}\" ng-show=\"$ctrl.selected\" ng-transclude=\"content\"></div>\r\n<div ng-transclude=\"heading\"></div>\r\n`);\n\n $templateCache.put(\"salaxy-components/helpers/Tabs.html\",`<div>\r\n    <ul class=\"nav nav-tabs\">\r\n        <li ng-repeat=\"tab in $ctrl.tabs\" ng-class=\"{ active: tab.selected, disabled: tab.disable}\" class=\"nav-item\">\r\n            <a href class=\"nav-link\" ng-click=\"$ctrl.select(tab, $event)\" salaxy-append-node=\"tab.headingElement\">{{tab.heading}}</a>\r\n        </li>\r\n    </ul>\r\n    <div class=\"tab-content\">\r\n        <ng-transclude></ng-transclude>\r\n    </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/helpers/UiTranslator.html\",`<div class=\"salaxy-component salaxy-ui-translator\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.UI_Terms.pleaseWait\"></salaxy-spinner>\r\n  <div ng-if=\"!$ctrl.isLoading && $ctrl.allKeyValues.length &lt; 1\" class=\"alert alert-danger\">\r\n    No rows for filter: {{$ctrl.filter}}\r\n  </div>\r\n  <div ng-if=\"$ctrl.allKeyValues.length > 0\">\r\n    <div ng-if=\"$ctrl.mode == 'fieldset'\">\r\n      <fieldset class=\"form-horizontal\" ng-repeat=\"row in $ctrl.allKeyValues | limitTo: 10\">\r\n        <legend>\r\n          <button ng-if=\"$ctrl.canDeleteFromText(row.fullKey)\" ng-click=\"$ctrl.removeFromTexts(row.fullKey)\" class=\"btn btn-danger btn-xs pull-right\"><i class=\"fa fa-trash-o\"></i></button>\r\n          {{row.fullKey}}\r\n        </legend>\r\n        <salaxy-input ng-if=\"$ctrl.checkIfExistsInTexts(row.fullKey, 'fi')\" name=\"fi\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.fi}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).fi\" label=\"Suomi\"></salaxy-input>\r\n        <salaxy-input ng-if=\"!$ctrl.checkIfExistsInTexts(row.fullKey, 'fi')\" name=\"fi\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'fi')\" ng-model=\"row.fi\" read-only=\"true\" label=\"Suomi\"></salaxy-input>\r\n        <salaxy-input ng-if=\"$ctrl.checkIfExistsInTexts(row.fullKey, 'en')\" name=\"en\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.en}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).en\" label=\"English\"></salaxy-input>\r\n        <salaxy-input ng-if=\"!$ctrl.checkIfExistsInTexts(row.fullKey, 'en')\" name=\"en\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'en')\" ng-model=\"row.en\" read-only=\"true\" label=\"English\"></salaxy-input>\r\n        <salaxy-input ng-if=\"$ctrl.checkIfExistsInTexts(row.fullKey, 'sv')\" name=\"sv\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.sv}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).sv\" label=\"Svenska\"></salaxy-input>\r\n        <salaxy-input ng-if=\"!$ctrl.checkIfExistsInTexts(row.fullKey, 'sv')\" name=\"sv\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'sv')\" ng-model=\"row.sv\" read-only=\"true\" label=\"Svenska\"></salaxy-input>\r\n      </fieldset>\r\n      <div class=\"alert alert-warning\" ng-if=\"$ctrl.allKeyValues.length > 10\">ERR: More than 10 translation key values, showing max 10.</div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.mode != 'fieldset'\">\r\n      <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Report options\">\r\n        <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n          <button id=\"single-button\" type=\"button\" class=\"btn btn-secondary\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n            Avaimet: <span class=\"caret\"></span>\r\n          </button>\r\n          <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.fullKey = !$ctrl.showCols.fullKey\">\r\n                <i ng-if=\"$ctrl.showCols.fullKey\" class=\"fa fa-times\" aria-hidden=\"true\"></i>\r\n                Koko avain</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.shortKey = !$ctrl.showCols.shortKey\">\r\n                <i ng-if=\"$ctrl.showCols.shortKey\" class=\"fa fa-times\" aria-hidden=\"true\"></i>\r\n                Lyhyt avain</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.fileName = !$ctrl.showCols.fileName\">\r\n                <i ng-if=\"$ctrl.showCols.fileName\" class=\"fa fa-times\" aria-hidden=\"true\"></i>\r\n                Käännöstiedosto / pääryhmä</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.keyComponent = !$ctrl.showCols.keyComponent\">\r\n                <i ng-if=\"$ctrl.showCols.keyComponent\" class=\"fa fa-times\" aria-hidden=\"true\"></i>\r\n                Komponentti / tiedoston ryhmittely</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.keyValue = !$ctrl.showCols.keyValue\">\r\n                <i ng-if=\"$ctrl.showCols.keyValue\" class=\"fa fa-times\" aria-hidden=\"true\"></i>\r\n                3. taso (1. avain)</a></li>\r\n          </ul>\r\n        </div>\r\n        <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n          <button id=\"single-button\" type=\"button\" class=\"btn btn-secondary\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n            Kieli: <span class=\"caret\"></span>\r\n          </button>\r\n          <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.fi = !$ctrl.showCols.fi\"><i ng-if=\"$ctrl.showCols.fi\" class=\"fa fa-times\" aria-hidden=\"true\"></i> Suomi</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.en = !$ctrl.showCols.en\"><i ng-if=\"$ctrl.showCols.en\" class=\"fa fa-times\" aria-hidden=\"true\"></i> Englanti</a></li>\r\n            <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.showCols.sv = !$ctrl.showCols.sv\"><i ng-if=\"$ctrl.showCols.sv\" class=\"fa fa-times\" aria-hidden=\"true\"></i> Ruotsi</a></li>\r\n          </ul>\r\n        </div>\r\n        <div class=\"btn-group btn-group-sm pull-right-xs\" role=\"group\" aria-label=\"Json\">\r\n          <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-secondary\" ng-click=\"$ctrl.downloadTexts()\">\r\n            <span class=\"hidden-sm hidden-xs\">Lataa muutos JSON</span>\r\n            <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i>\r\n          </button>\r\n        </div>\r\n      </div>\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th ng-if=\"$ctrl.showCols.fullKey\">\r\n              <salaxy-input label-type=\"basic\" name=\"fullKey\" label=\"Koko avain\" ng-model=\"$ctrl.listFilter.fullKey\"></salaxy-input>\r\n            </th>\r\n            <th ng-if=\"$ctrl.showCols.shortKey\">\r\n              <salaxy-input label-type=\"basic\" name=\"shortKey\" label=\"Lyhyt avain\" ng-model=\"$ctrl.listFilter.shortKey\"></salaxy-input>\r\n            </th>\r\n            <th ng-if=\"$ctrl.showCols.keyComponent\">\r\n              <salaxy-input label-type=\"basic\" name=\"keyComponent\" label=\"Komponenttiavain\" ng-model=\"$ctrl.listFilter.keyComponent\"></salaxy-input>\r\n            </th>\r\n            <th ng-if=\"$ctrl.showCols.fi\">\r\n              <salaxy-input label-type=\"basic\" name=\"fi\" label=\"Suomi\" ng-model=\"$ctrl.listFilter.fi\"></salaxy-input>\r\n            </th>\r\n            <th ng-if=\"$ctrl.showCols.en\">\r\n              <salaxy-input label-type=\"basic\" name=\"en\" label=\"Englanti\" ng-model=\"$ctrl.listFilter.en\"></salaxy-input>\r\n            </th>\r\n            <th ng-if=\"$ctrl.showCols.sv\">\r\n              <salaxy-input label-type=\"basic\" name=\"sv\" label=\"Ruotsi\" ng-model=\"$ctrl.listFilter.sv\"></salaxy-input>\r\n            </th>\r\n            <th></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.allKeyValues | filter: $ctrl.listFilter | limitTo: 100 \">\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.fullKey\">{{row.fullKey}}</td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.shortKey\">{{row.shortKey}}</td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.keyComponent\">{{row.keyComponent}}</td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.keyValue\">{{row.keyValue}}</td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.fi && $ctrl.checkIfExistsInTexts(row.fullKey, 'fi')\">\r\n              <salaxy-input name=\"fi\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.fi}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).fi\" label-type=\"plain\"></salaxy-input>\r\n            </td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.fi && !$ctrl.checkIfExistsInTexts(row.fullKey, 'fi')\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'fi')\">{{row.fi}}\r\n            </td>\r\n  \r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.en && $ctrl.checkIfExistsInTexts(row.fullKey, 'en')\">\r\n              <salaxy-input name=\"en\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.en}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).en\" label-type=\"plain\"></salaxy-input>\r\n            </td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.en && !$ctrl.checkIfExistsInTexts(row.fullKey, 'en')\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'en')\">{{row.en}}\r\n            </td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.sv && $ctrl.checkIfExistsInTexts(row.fullKey, 'sv')\">\r\n              <salaxy-input name=\"sv\" ng-change=\"$ctrl.updateTexts()\" placeholder=\"{{row.sv}}\" ng-model=\"$ctrl.getEditableText(row.fullKey).sv\" label-type=\"plain\"></salaxy-input>\r\n            </td>\r\n            <td style=\"word-break:break-word;\" ng-if=\"$ctrl.showCols.sv && !$ctrl.checkIfExistsInTexts(row.fullKey, 'sv')\" ng-click=\"$ctrl.addToTexts(row.fullKey, 'sv')\">{{row.sv}}\r\n            </td>\r\n            <td ng-if=\"$ctrl.canDeleteFromText(row.fullKey)\"><button ng-click=\"$ctrl.removeFromTexts(row.fullKey)\" class=\"btn btn-danger\"><i class=\"fa fa-trash-o\"></i></button>\r\n            </td>\r\n            <td ng-if=\"!$ctrl.canDeleteFromText(row.fullKey)\"></td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/CompanyInvoices.html\",`<div class=\"salaxy-component salaxy-company-invoices\">\r\n  <salaxy-odata-table crud-controller=\"CompanyInvoicesController as $crud\" options=\"$ctrl.getListOptions()\" crud-bindings=\"{ channel: $ctrl.channel }\"\r\n    template-url=\"salaxy-components/odata/lists/InvoicesCompany.html\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/CreditTransfer.html\",`<div class=\"salaxy-component salaxy-credit-transfer\">\r\n  <div class=\"salaxy-credit-transfer-official\" ng-if=\"$ctrl.mode != 'barcode-copy'\">\r\n    <div class=\"sct-row sct-row1\">\r\n      <div class=\"sct-col sct-col1\">\r\n        <div class=\"sct-row sct-row1\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.receiverIban.html\"></div>\r\n        <div class=\"sct-row sct-row2\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.receiver.html\"></div>\r\n        <div class=\"sct-row sct-row3\">\r\n          <div class=\"sct-label-payer\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.payerInfo.html\"></div>\r\n          <div class=\"sct-label-credit-transfer\" sxy-text=\"SALAXY.NG1.CreditTransferComponent.creditTransfer\"></div>\r\n          <div class=\"sct-label-signature\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.signature.html\"></div>\r\n        </div>\r\n        <div class=\"sct-row sct-row4\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.fromAccount.html\"></div>\r\n      </div>\r\n      <div class=\"sct-col sct-col2\">\r\n        <div class=\"sct-row sct-row1\">\r\n          <!-- Recipient account numbers (IBAN), max 4 lines -->\r\n          <div class=\"sct-label-iban\" sxy-text=\"SALAXY.NG1.CreditTransferComponent.iban\"></div>\r\n          <div class=\"sct-filled-content\">           \r\n            {{ $ctrl.invoice.recipient.iban | sxyIban }}\r\n          </div>\r\n          <div class=\"sct-label-iban\" sxy-text=\"BIC\"></div>\r\n          <div class=\"sct-filled-content\">\r\n            {{ $ctrl.getBicForIban($ctrl.invoice.recipient.iban) }}\r\n          </div>\r\n        </div>\r\n        <div class=\"sct-row sct-row2\">\r\n          <div class=\"sct-filled-content sct-filled-content-main\">\r\n            <!-- Recipient, max 3 lines -->\r\n            {{ $ctrl.invoice.recipient.fullName }}<br> {{ $ctrl.invoice.recipient.contact.street }} {{ $ctrl.invoice.recipient.contact.postalCode }} {{ $ctrl.invoice.recipient.contact.city }}\r\n          </div>\r\n        </div>\r\n        <div class=\"sct-row sct-row3\">\r\n          <div class=\"sct-filled-content sct-filled-content-main\">\r\n            <!-- Payer’s name and address -->\r\n            {{ $ctrl.invoice.payer.avatar.displayName }}<br> {{ $ctrl.invoice.payer.contact.street }}<br> {{ $ctrl.invoice.payer.contact.postalCode }} {{ $ctrl.invoice.payer.contact.city }}\r\n          </div>\r\n          <div class=\"sct-filled-content sct-signature\">\r\n            <!-- Signature -->\r\n          </div>\r\n          <div class=\"sct-guideline-signature\"></div>\r\n        </div>\r\n        <div class=\"sct-row sct-row4\">\r\n          <div class=\"sct-filled-content sct-filled-content-main\">\r\n            <!-- From account no. -->\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"sct-col sct-col3\">\r\n        <div class=\"sct-row sct-row1\" ng-if=\"$ctrl.getQrCode(row) !== 'loading' && $ctrl.getQrCode(row) !== 'error'\">\r\n          <div class=\"sct-qrcode\" >\r\n            <div ng-bind-html=\"$ctrl.getQrCode(row)\"></div>\r\n          </div>\r\n          <div class=\"sct-filled-content-message\">\r\n            <ng-transclude ng-transclude-slot=\"message\">\r\n              <span>{{ $ctrl.invoice.header.message }}</span>\r\n            </ng-transclude>\r\n          </div>\r\n        </div>\r\n        <div class=\"sct-row sct-row1\" ng-if=\"$ctrl.getQrCode(row) === 'error'\">\r\n          <div class=\"sct-filled-content sct-filled-content-main\">\r\n            <ng-transclude ng-transclude-slot=\"message\">\r\n              <span>{{ $ctrl.invoice.header.message }}</span>\r\n            </ng-transclude>\r\n          </div>\r\n        </div>\r\n        <div class=\"sct-row sct-row2\">\r\n          <div class=\"sct-col sct-col1\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.refNumber.html\"></div>\r\n          <div class=\"sct-col sct-col2\">\r\n            <div class=\"sct-filled-content sct-filled-content-main\">\r\n              <!-- Ref. nr -->\r\n              {{ $ctrl.invoice.header.referenceNumber | sxyIban }}\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div class=\"sct-row sct-row3\">\r\n          <div class=\"sct-col sct-col1\" sxy-html=\"SALAXY.NG1.CreditTransferComponent.dueDate.html\"></div>\r\n          <div class=\"sct-col sct-col2\">\r\n            <div class=\"sct-filled-content sct-filled-content-main\">\r\n              <!-- Due date -->\r\n              {{ $ctrl.invoice.header.dueDate | sxyDate }}\r\n            </div>\r\n          </div>\r\n          <div class=\"sct-col sct-col3\">\r\n            <div class=\"sct-label-euro\" sxy-text=\"SALAXY.NG1.CreditTransferComponent.euro\"></div>\r\n            <div class=\"sct-filled-content sct-filled-content-main\">\r\n              <!-- Euro amount -->\r\n              {{ $ctrl.invoice.header.total | currency }}\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"sct-row sct-row2\">\r\n      <div id=\"barcode\">\r\n        <!-- Barcode can be shown only with FI IBAN -->\r\n         <div ng-bind-html=\"$ctrl.getBarcode()\"></div>\r\n      </div>\r\n      <!--\r\n        NOTE: Terms of clearance is part of original specification: https://www.finanssiala.fi/wp-content/uploads/2021/03/Tilisiirto-opas.pdf.\r\n        It is removed because it has no real value today and it makes reading barcode difficult.\r\n      -->\r\n      <!--\r\n        <div id=\"terms-of-clearance\">\r\n          Maksu välitetään saajalle maksujenvälityksen ehtojen mukaisesti ja vain maksajan ilmoittaman tilinumeron perusteella.\r\n          <br> Betalningen förmedlas till mottagaren engligt villkoren för betalningsförmedling och endast till det kontonummer som betalaren angivit.\r\n        </div>\r\n      -->\r\n    </div>\r\n  </div>\r\n  <div class=\"barcodeform-container hidden-print\" ng-if=\"$ctrl.mode != 'official'\">\r\n    <form name=\"barcodeForm\" id=\"barcodeForm\" class=\"form-horizontal\">\r\n      <p sxy-text=\"SALAXY.NG1.CreditTransferComponent.transferDescription\" ng-if=\"$ctrl.mode != 'barcode-copy' && !$ctrl.isInternationalIban()\"></p>\r\n      <p ng-if=\"$ctrl.mode != 'barcode-copy' && $ctrl.isInternationalIban()\">&nbsp;</p>    \r\n      <div class=\"row\" ng-if=\"!$ctrl.isInternationalIban()\">\r\n        <div class=\"col-sm-10\">\r\n          <salaxy-input name=\"{{ 'barcode' + $ctrl.getId() }}\" label=\"SALAXY.NG1.CreditTransferComponent.barcodeLabel\" readonly=\"true\" label-cols=\"col-sm-4\" ng-model=\"$ctrl.bcValue\"></salaxy-input>\r\n        </div>\r\n        <div class=\"col-sm-2\">\r\n          <button class=\"btn btn-default btn-block\" ng-click=\"$ctrl.copyBarcode()\" sxy-text=\"SALAXY.UI_Terms.copyToClipboard\"></button>\r\n        </div>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoiceAlerts.html\",`<div class=\"row payment-started-alert\">\r\n  <div class=\"col-xs-12\">\r\n    <salaxy-alert type=\"warning\" ng-repeat=\"paymentChannel in $ctrl.groupedPaymentChannelResult\">\r\n      <main>\r\n        <div ng-bind-html=\"$ctrl.getpaymentChannelInfoHtml(paymentChannel)\"></div>\r\n      </main>\r\n    </salaxy-alert>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoiceEdit.html\",`<div class=\"salaxy-component salaxy-invoice-edit\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div class=\"alert alert-danger\" ng-if=\"!$ctrl.isLoading && !$ctrl.current\" sxy-text=\"SALAXY.NG1.InvoiceEditComponent.error\"></div>\r\n  <form name=\"statusForm\" ng-if=\"$ctrl.current\" ng-submit=\"$ctrl.requestStatusUpdate()\">\r\n    <div class=\"form-horizontal\">\r\n      <h2 sxy-text=\"SALAXY.NG1.InvoiceEditComponent.headingAlt\"></h2>\r\n      <p sxy-text=\"SALAXY.NG1.InvoiceEditComponent.headingInfoAlt\"></p>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.InvoiceEditComponent.channel\" read-only=\"true\" name=\"paymentChannel\" ng-model=\"$ctrl.current.header.channel\" enum=\"PaymentChannel\"></salaxy-input-enum>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.InvoiceEditComponent.invoiceStatus\" read-only=\"!( ( ('test' | sxyIsInRole) || ('pro' | sxyIsInRole) ) && ($ctrl.current.header.channel == 'palkkausManual' || $ctrl.current.header.channel == 'palkkausInvoices' || $ctrl.current.header.channel == 'kitsas' || $ctrl.current.header.channel == 'palkkausWS'))\" name=\"requestedStatus\" ng-model=\"$ctrl.requestedStatus\" enum=\"InvoiceStatus\" required></salaxy-input-enum>\r\n    </div>\r\n    <div>\r\n      <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"!statusForm.$valid || !( ( ('test' | sxyIsInRole) || ('pro' | sxyIsInRole) ) && ($ctrl.current.header.channel == 'palkkausManual' || $ctrl.current.header.channel == 'palkkausInvoices' || $ctrl.current.header.channel == 'kitsas' || $ctrl.current.header.channel == 'palkkausWS'))\" sxy-text=\"SALAXY.NG1.InvoiceEditComponent.updateStatusBtn\"></button>\r\n      <button ng-if=\"'test' | sxyIsInRole\" type=\"button\" ng-click=\"$ctrl.delete()\" class=\"btn btn-danger\" sxy-text=\"SALAXY.NG1.InvoiceEditComponent.deleteInvoice\" pre=\"(Test only): \"></button>\r\n      <button ng-if=\"'test' | sxyIsInRole\" type=\"button\" ng-click=\"$ctrl.deleteWithBusinessObjects()\" class=\"btn btn-danger\" sxy-text=\"SALAXY.NG1.InvoiceEditComponent.deleteInvoiceWithCals\" pre=\"(Test only): \"></button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoiceList.html\",`<div class=\"salaxy-component salaxy-invoice-list\" ng-switch=\"$ctrl.mode\">\r\n  <salaxy-odata-table ng-switch-when=\"panel\" crud-controller=\"InvoiceCrudController as $crud\" options=\"$ctrl.getListOptions()\"\r\n    template-url=\"salaxy-components/odata/lists/InvoicesPanel.html\">\r\n  </salaxy-odata-table>\r\n\r\n  <salaxy-odata-table ng-switch-when=\"sepa\" crud-controller=\"InvoiceSepaController as $crud\" crud-bindings=\"{ sepaChannel: $ctrl.sepaChannel }\"\r\n    template-url=\"salaxy-components/odata/lists/InvoicesSepa.html\">\r\n  </salaxy-odata-table>\r\n\r\n  <salaxy-odata-table ng-switch-when=\"person\" crud-controller=\"InvoiceCrudController as $crud\" options=\"$ctrl.getListOptions()\"\r\n    template-url=\"salaxy-components/odata/lists/InvoicesPerson.html\">\r\n  </salaxy-odata-table>\r\n  \r\n  <div ng-switch-default>\r\n    <salaxy-odata-table crud-controller=\"InvoiceCrudController as $crud\" options=\"$ctrl.getListOptions()\" template-url=\"salaxy-components/odata/lists/Invoices.html\">\r\n    </salaxy-odata-table>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoicePreview.html\",`<div ng-init=\"$ctrl.view = 'full'\">\r\n  <salaxy-spinner ng-if=\"!$ctrl.current && $ctrl.isLoading\"></salaxy-spinner>\r\n  <div class=\"alert alert-danger\" ng-if=\"!$ctrl.isLoading && !$ctrl.current\" sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.error\"></div>\r\n  \r\n  <div ng-if=\"$ctrl.current\">\r\n    <div>\r\n      <div class=\"btn-group btn-group-sm\">\r\n        <button class=\"btn btn-default\" ng-model=\"$ctrl.view\" uib-btn-radio=\"'full'\" sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.fullInvoice\"></button>\r\n        <button class=\"btn btn-default\" ng-model=\"$ctrl.view\" uib-btn-radio=\"'partial'\" sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.tableInvoice\"></button>\r\n      </div>\r\n      <a ng-href=\"{{$ctrl.getContentUrl($ctrl.current.id, true)}}\" target=\"_blank\"class=\"btn btn-primary pull-right\">\r\n        <i class=\"fa fa-file-pdf-o\"></i> <span sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.showFile\"></span>\r\n      </a>\r\n    </div>\r\n    <salaxy-invoice-report invoice=\"$ctrl.current\" apply-site-styles=\"$ctrl.view == 'partial'\"></salaxy-invoice-report>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoiceReport.html\",`<div class=\"salaxy-component salaxy-calc-report\">\r\n  <div class=\"row\" ng-if=\"$ctrl.applySiteStyles\">\r\n    <div class=\"col-sm-6\">\r\n      <table>\r\n        <tr>\r\n          <td colspan=\"2\"><small><strong sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.recipient\" ps=\":\"></strong></small></td>\r\n        </tr>\r\n        <tr>\r\n          <td>\r\n            <salaxy-avatar avatar=\"$ctrl.invoice.recipient.beneficiary.avatar\" style=\"font-size: 64px;\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <div><strong>{{ $ctrl.invoice.recipient.fullName }}</strong></div>\r\n            <div>\r\n              {{ $ctrl.invoice.recipient.contact.street }}<br /> {{ $ctrl.invoice.recipient.contact.postalCode }} {{ $ctrl.invoice.recipient.contact.city }}\r\n            </div>\r\n          </td>\r\n        </tr>\r\n        <tr>\r\n          <td>&nbsp;</td>\r\n        </tr>\r\n        <tr>\r\n          <td colspan=\"2\"><small><strong sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.payer\" ps=\":\"></strong></small></td>\r\n        </tr>\r\n        <tr>\r\n          <td>\r\n            <salaxy-avatar avatar=\"$ctrl.invoice.payer.avatar\" style=\"font-size: 64px;\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <div><strong>{{ $ctrl.invoice.payer.avatar.displayName }}</strong></div>\r\n            <div>\r\n              {{ $ctrl.invoice.payer.contact.street }}<br /> {{ $ctrl.invoice.payer.contact.postalCode }} {{ $ctrl.invoice.payer.contact.city }}\r\n            </div>\r\n          </td>\r\n        </tr>\r\n      </table>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <p style=\"font-size: 24px; font-weight: bold; text-transform: uppercase;\">{{ \"SALAXY.NG1.InvoiceReportComponent.invoice.title\" | sxyTranslate }}</p>\r\n      <p style=\"font-size: 16px; font-weight: bold; text-transform: uppercase;\">{{ (\"SALAXY.ENUM.InvoiceType.\" + $ctrl.invoice.header.type + \".label\") | sxyTranslate }}</p>\r\n      <div > </div>\r\n      <table>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.date\" ps=\":\"></td>\r\n          <td>{{ $ctrl.invoice.header.date | sxyDate }}</td>\r\n        </tr>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.dueDate\" ps=\":\"></td>\r\n          <td>{{ $ctrl.invoice.header.dueDate | sxyDate }}</td>\r\n        </tr>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.referenceNumber\" ps=\":\"></td>\r\n          <td>{{ $ctrl.invoice.header.referenceNumber || \"-\" }}</td>\r\n        </tr>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.iban\" ps=\":\"></td>\r\n          <td ng-if=\"!$ctrl.isPreviewInvoice()\">{{ $ctrl.invoice.recipient.iban | sxyIban }}</td>\r\n          <td ng-if=\"$ctrl.isPreviewInvoice()\">{{ 'SALAXY.REPORTS.invoice.heading.preview' | sxyTranslate }}</td>\r\n        </tr>\r\n        <tr>\r\n          <td sxy-text=\"SALAXY.NG1.InvoicePreviewComponent.status\" ps=\":\"></td>\r\n          <td>{{ \"InvoiceStatus.\" + $ctrl.invoice.header.status | sxyEnum }}</td>\r\n        </tr>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div ng-class=\"{'report-table-html': $ctrl.applySiteStyles}\"></div>\r\n    <div ng-bind-html=\"$ctrl.html\" class=\"report-binder table-responsive\" style=\"width: 100%;\"></div>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoicesCreate.html\",`<div class=\"salaxy-component salaxy-invoices-create\">\r\n  <div ng-if=\"!$ctrl.currentType\" class=\"alert alert-error\">Error: {{ $ctrl.current ? \"Invalid object\" : \"No object\" }} bound in InvoicesCreateController</div>\r\n  <div ng-if=\"$ctrl.currentType\">\r\n    <div ng-switch=\"$ctrl.uiStatus\">\r\n      <div ng-switch-when=\"invalid\">\r\n        <salaxy-validation-summary api-validation=\"$ctrl.current.result.validation\">\r\n          <div class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusInvalid\"></div>\r\n        </salaxy-validation-summary>\r\n      </div>\r\n      <div ng-switch-when=\"loading\">\r\n        <salaxy-spinner heading=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusLoading\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-switch-when=\"created\" ng-switch=\"$ctrl.paymentStatus\">\r\n        <p class=\"lead\" ng-switch-when=\"inProgress\" sxy-html=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusCreated.inProgress.html\"></p>\r\n        <div class=\"alert alert-success\" ng-switch-when=\"paid\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusCreated.paid\" ps=\".\"></div>\r\n        <div class=\"alert alert-danger\" ng-switch-when=\"exceptions\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusCreated.exceptions\"></div>\r\n        <div class=\"alert alert-danger\" ng-switch-when=\"canceled\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusCreated.canceled\"></div>\r\n        <ng-include src=\"'salaxy-components/invoices/InvoicesCreate_Table.html'\"></ng-include>\r\n      </div>\r\n      <div ng-switch-when=\"supportedChannel\">\r\n        <div sxy-html=\"{{$ctrl.intro}}\"></div>\r\n        <ng-include src=\"'salaxy-components/invoices/InvoicesCreate_Table.html'\"></ng-include>\r\n      </div>\r\n      <div ng-switch-when=\"undefined\">\r\n        <div class=\"alert alert-error\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusDefault\"></div>\r\n      </div>\r\n      <div ng-switch-when=\"userCanceled\">\r\n        <div class=\"alert alert-error\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusUserCanceled\"></div>\r\n      </div>\r\n      <div ng-switch-default>\r\n        <div class=\"alert alert-error\" sxy-text=\"SALAXY.NG1.InvoicesCreateComponent.uiStatusDefault\"></div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoicesCreate_Table.html\",`<table class=\"table\">\r\n  <thead>\r\n    <tr>\r\n      <th colspan=\"2\" sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.receiverInvoiceType\"></th>\r\n      <th sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.comingToPay\"></th>\r\n      <th class=\"right\" sxy-html=\"SALAXY.NG1.InvoicesCreateTableComponent.invoiceDate.html\"></th>\r\n      <th class=\"right\" sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.invoiceSum\"></th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"row in $ctrl.invoices\" ng-class=\"{ 'success': $ctrl.getDueDateType(row) == 'default' || $ctrl.getDueDateType(row) == 'paid' }\">\r\n      <td class=\"td-avatar middle\">\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.invoice.otherPartyInfo.avatar\"></salaxy-avatar>\r\n      </td>\r\n      <td class=\"middle\">\r\n        {{ row.invoice.otherPartyInfo.avatar.sortableName }}<br>\r\n        <small class=\"hidden-xxs\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.invoice.entityType + \".label\") | sxyTranslate}}</small>\r\n      </td class=\"middle\">\r\n      <td class=\"middle\">\r\n        <div ng-switch=\"$ctrl.getDueDateType(row)\">\r\n          <span ng-switch-when=\"preview\" class=\"disabled\">{{$ctrl.getPreviewText(row)}}</span>\r\n          <span ng-switch-when=\"zero\" class=\"disabled\" sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.dueDateTypeZero\" ps=\".\"></span>\r\n          <span ng-switch-when=\"estimation\">{{$ctrl.getEstimationText(row)}}</span>\r\n          <span ng-switch-when=\"forecast\">{{ row.invoice.otherPartyInfo.avatar.sortableName }} {{'SALAXY.NG1.InvoicesCreateTableComponent.sendsInvoice' | sxyTranslate}}</span>\r\n          <strong ng-switch-when=\"paid\" sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.dueDateTypePaid\"></strong>\r\n          <strong ng-switch-when=\"default\" sxy-text=\"SALAXY.NG1.InvoicesCreateTableComponent.dueDateTypeDefault\"></strong>\r\n          <span ng-switch-when=\"unknown\"></span>\r\n        </div>\r\n        <div ng-if=\"row.invoice.businessObjects.length > 1\">\r\n          {{'SALAXY.NG1.InvoicesCreateTableComponent.totalSalaries' | sxyTranslate}} {{ row.invoice.businessObjects.length }}\r\n        </div>\r\n      </td>\r\n      <td class=\"middle right\">\r\n        <div>{{ row.invoice.startAt | sxyDate }}</div>\r\n        <div ng-switch=\"$ctrl.getDueDateType(row)\">\r\n          <span ng-switch-when=\"estimation\">{{ \"SALAXY.ENUM.CalendarMonth.month\" + (row.invoice.endAt | date : 'M') + \".label\" | sxyTranslate }}</span>\r\n          <span ng-switch-when=\"zero\">-</span>\r\n          <span ng-switch-when=\"preview\">{{ row.invoice.endAt | sxyDate }}</span>\r\n          <span ng-switch-when=\"forecast\">{{ row.invoice.endAt | sxyDate }}</span>\r\n          <span ng-switch-when=\"paid\">{{ row.invoice.endAt | sxyDate }}</span>\r\n          <span ng-switch-when=\"default\">{{ row.invoice.endAt | sxyDate }}</span>\r\n          <span ng-switch-when=\"unknown\">{{ row.invoice.endAt | sxyDate }}</span>\r\n        </div>\r\n      </td>\r\n      <td class=\"middle right\">\r\n        <strong>{{ row.invoice.payment | currency }}</strong>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/invoices/InvoiceTools.html\",`<div class=\"salaxy-component salaxy-invoice-tools\">\r\n\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Invoice options\">\r\n    <div class=\"btn-group\">\r\n      <salaxy-input-enum type=\"uib-dropdown\" name=\"fileType\" label-type=\"plain\" ng-model=\"$ctrl.fileTypeId\" options=\"$ctrl.fileTypeOptions\" remember=\"invoice\"></salaxy-input-enum>\r\n\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <button ng-disabled=\"$ctrl.reader.disabled()\" id=\"reportExport\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.export()\">\r\n        {{ $ctrl.reader.exportLabel || ('SALAXY.NG1.AccountingReportToolsComponent.createExport' | sxyTranslate) }}\r\n      </button>\r\n    </div>\r\n\r\n    <div ng-if=\"'test' | sxyIsInRole\" class=\"btn-group\">\r\n      <salaxy-input-enum type=\"uib-dropdown\" name=\"channel\" label-type=\"plain\" ng-model=\"channel\" enum=\"PaymentChannel\" ></salaxy-input-enum>\r\n      <button ng-disabled=\"!channel || channel=='undefined'\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.createSingleInvoice(channel,'verification')\">Luo avauslasku</button>\r\n      <button ng-disabled=\"!channel || channel=='undefined'\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.createSingleInvoice(channel, 'tax')\">Luo verolasku kuluvalle kuulle</button>\r\n    </div>\r\n\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/AccountAvatarEdit.html\",`\r\n<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AccountInfoComponent.changeAvatar\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n<form name=\"avatarForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current\" >\r\n  <div class=\"form-group\">\r\n    <div class=\"col-xs-12 col-sm-4\">\r\n      <label for=\"avatarPreview\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarLabel\"></label>\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-8\">\r\n      <div class=\"worker-avatar-col\">\r\n        <salaxy-avatar style=\"font-size: 200px\" avatar=\"$ctrl.current.avatar\"></salaxy-avatar>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"form-group\">\r\n    <div class=\"col-xs-12 col-sm-4\">\r\n      <label for=\"avatarPictureType\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarTypeLabel\"></label>\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-8\">\r\n      <select class=\"form-control\" id=\"avatarPictureType\" ng-model=\"$ctrl.current.avatar.pictureType\" ng-change=\"$ctrl.logic.typeForAvatarChanged($ctrl.current)\">\r\n        <option value=\"\" disabled sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionChoose\"></option>\r\n        <option value=\"icon\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionIcon\"></option>\r\n        <option value=\"uploaded\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionUploaded\"></option>\r\n        <option hidden value=\"gravatar\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionGravatar\"></option>\r\n      </select>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.avatar.pictureType == 'gravatar'\" class=\"row\">\r\n    <div class=\"input-info col-sm-8 col-sm-offset-4\">\r\n      <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n      <p class=\"small input-info-text with-icon \" sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.gravatarInfo.html\"></p>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.avatar.pictureType == 'icon'\">\r\n    <salaxy-input name=\"avatarInitials\" label=\"SALAXY.NG1.AccountAvatarEditPersonComponent.initialsLabel\" ng-model=\"$ctrl.current.avatar.initials\" max-length=\"2\"></salaxy-input>\r\n    <div class=\"form-group\">\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <label for=\"avatarPictureColor\" class=\"input-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.colorLabel\"></label>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-8\">\r\n        <input type=\"color\" id=\"avatarPictureColor\" ng-model=\"$ctrl.current.avatar.color\" />\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"form-group\">\r\n    <div ng-if=\"$ctrl.current.avatar.pictureType == 'uploaded'\">\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <label for=\"avatarImageUpload\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImageLabel\"></label>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-8\">\r\n        <div name=\"avatarImageUpload\" ng-model=\"avatarImage\" ngf-drop=\"$ctrl.logic.uploadAvatarImage($file, $ctrl.current)\" ngf-select=\"$ctrl.logic.uploadAvatarImage($file, $ctrl.current)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" ngf-multiple=\"false\" ngf-min-size=\"5KB\" ngf-max-size=\"10MB\"\r\n          ngf-pattern=\"'image/*'\" ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\">\r\n          <span sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImage.html\"></span>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/AccountContactEdit.html\",`\r\n<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AccountInfoComponent.editContactInfo\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <form name=\"contactForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <salaxy-input name=\"email\" label=\"SALAXY.MODEL.PersonAccount.contact.email.title\" sxy-email ng-model=\"$ctrl.current.contact.email\" ng-change=\"$ctrl.logic.emailForAvatarChanged($ctrl.current)\">\r\n        </salaxy-input>\r\n        <salaxy-input name=\"telephone\" label=\"SALAXY.MODEL.PersonAccount.contact.telephone.title\" sxy-mobile-phone ng-model=\"$ctrl.current.contact.telephone\"></salaxy-input>\r\n        <salaxy-input name=\"street\" label=\"SALAXY.MODEL.PersonAccount.contact.street.title\" ng-model=\"$ctrl.current.contact.street\" ng-required=\"('household' | sxyIsInRole) || ('company' | sxyIsInRole)\"></salaxy-input>\r\n        <salaxy-input name=\"postalCode\" label=\"SALAXY.MODEL.PersonAccount.contact.postalCode.title\" sxy-postal-code-fi ng-model=\"$ctrl.current.contact.postalCode\" ng-required=\"('household' | sxyIsInRole) || ('company' | sxyIsInRole)\"></salaxy-input>\r\n        <salaxy-input name=\"city\" label=\"SALAXY.MODEL.PersonAccount.contact.city.title\" ng-model=\"$ctrl.current.contact.city\" ng-required=\"('household' | sxyIsInRole) || ('company' | sxyIsInRole)\"></salaxy-input>\r\n        <salaxy-input-enum type=\"select\" label=\"SALAXY.MODEL.PersonAccount.contact.countryCode.title\" ng-model=\"$ctrl.current.contact.countryCode\"\r\n        name=\"country\" read-only=\"true\" enum=\"Country\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/Authorization.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyProductDialogLabel\">{{ $ctrl.currentPartnerSite.title | sxyTranslate }}</h2>\r\n  <h4 class=\"subtitle\">{{ $ctrl.currentPartnerSite.status | sxyTranslate}}</h4>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <div class=\"form-horizontal\">\r\n    <div class=\"salaxy-product-info-headers\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-sm-4\">\r\n          <i class=\"salaxy-avatar\" style=\"font-size: 140px;\">\r\n            <img ng-src=\"{{$ctrl.currentPartnerSite.img}}\" />\r\n          </i>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-8\">\r\n          <div class=\"salaxy-product-description\">\r\n            <p>{{ 'SALAXY.NG1.AuthInfoHeadersComponent.' + $ctrl.currentPartnerSite.id + '.description' | sxyTranslate }}</p>\r\n            <a class=\"btn btn-primary\" target=\"_blank\" href=\"{{'SALAXY.NG1.AuthInfoHeadersComponent.' + $ctrl.currentPartnerSite.id + '.link' | sxyTranslate}}\">\r\n              {{ 'SALAXY.NG1.AuthInfoHeadersComponent.' + $ctrl.currentPartnerSite.id + '.cta' | sxyTranslate }} »</a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <br />\r\n    <div sxy-if-role=\"auth\">\r\n      <div ng-if=\"$ctrl.currentPartnerSite.id == 'holvi'\" sxy-html=\"SALAXY.NG1.AuthorizationDialogsComponent.holvi.html\"></div>\r\n      <div ng-if=\"$ctrl.currentPartnerSite.id == 'isolta'\" sxy-html=\"SALAXY.NG1.AuthorizationDialogsComponent.isolta.html\"></div>\r\n      <div ng-if=\"$ctrl.currentPartnerSite.id == 'accountor'\" sxy-html=\"SALAXY.NG1.AuthorizationDialogsComponent.accountor.html\"></div>\r\n      <div ng-if=\"$ctrl.currentPartnerSite.id == 'finago'\" sxy-html=\"SALAXY.NG1.AuthorizationDialogsComponent.finago.html\"></div>\r\n      <div ng-if=\"$ctrl.currentPartnerSite.id == 'briox'\" sxy-html=\"SALAXY.NG1.AuthorizationDialogsComponent.briox.html\"></div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 spacer-bottom\">\r\n        <div class=\"pull-right\">\r\n          <salaxy-input-boolean salaxy-if-role=\"auth\" ng-change=\"$ctrl.switchAuthorization()\" name=\"{{$ctrl.currentPartnerSite.id}}\" id=\"{{$ctrl.currentPartnerSite.id}}\" type=\"switch-xl\"  ng-model=\"$ctrl.currentPartnerSite.enabled\" label-type=\"no-label\" label-true=\"on\" label-false=\"off\"></salaxy-input-boolean>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer text-left\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/AuthorizedAccountAdd.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorize\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <form name=\"authorizedAccountAddDialogForm\">\r\n    <div class=\"form-horizontal\">\r\n      <legend sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorizeTitle\"></legend>\r\n      <p sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorizeDescription\"></p>\r\n      <salaxy-input name=\"accountId\" label=\"SALAXY.NG1.AuthoringAccountComponent.palkkausAccount\" ng-model=\"$ctrl.current.id\" require=\"true\"></salaxy-input>\r\n      <salaxy-input name=\"scope\" label=\"SALAXY.NG1.AuthoringAccountComponent.scope\" placeholder=\"SALAXY.NG1.AuthoringAccountComponent.defaultScope\" ng-model=\"$ctrl.current.scope\"></salaxy-input>\r\n      <salaxy-input  ng-if=\"('admin' | sxyIsInRole)\" name=\"partnerKey\" label=\"Partnerin antama ID\"  ng-model=\"$ctrl.current.partnerKey\"></salaxy-input>\r\n    </div>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!authorizedAccountAddDialogForm.$valid\" ng-click=\"$ctrl.saveCurrent($close)\" sxy-text=\"SALAXY.NG1.AuthoringAccountComponent.authorize\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/CertificateAdd.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CertificateAddComponent.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div sxy-html=\"SALAXY.NG1.CertificateAddComponent.html\"></div>\r\n  <form name=\"certificateAddDialogForm\">\r\n    <div ng-if=\"!$ctrl.result.thumbprint\" class=\"form-horizontal\">\r\n      <salaxy-input name=\"title\" label=\"SALAXY.NG1.CertificatesComponent.name\" ng-model=\"$ctrl.current.title\" require=\"true\"></salaxy-input>\r\n      <salaxy-input-enum name=\"certFormat\" ng-model=\"$ctrl.certFormat\" require=\"true\" label=\"Sertifikaatin tyyppi\"\r\n        options=\"$ctrl.certFormats\"></salaxy-input-enum>\r\n      <div class=\"form-group\" ng-if=\"$ctrl.certFormat == 'pfx'\">\r\n        <label for=\"salasana\" class=\"col-sm-4 control-label\" style=\"text-align:left\">\r\n          <span sxy-text=\"SALAXY.NG1.CertificateAddComponent.password\" ps=\"*\"></span>\r\n        </label>\r\n        <div class=\"col-sm-8\">\r\n          <input type=\"password\" class=\"form-control\" id=\"password\" name=\"password\" placeholder=\"{{'SALAXY.NG1.CertificateAddComponent.password' | sxyTranslate}}\"\r\n            ng-model=\"$ctrl.current.password\" ng-required=\"true\" autocomplete=\"off\" />\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </form>\r\n  <div ng-if=\"$ctrl.result.thumbprint\">\r\n    <strong sxy-text=\"SALAXY.NG1.CertificateAddComponent.createdSertificate\"></strong><br />\r\n    <a ng-click=\"$ctrl.downloadCertFile()\">{{ \"SALAXY.NG1.CertificateAddComponent.downloadBase64\" |sxyTranslate }} (.{{ $ctrl.certFormat == 'pem' ? 'zip' : $ctrl.certFormat }})</a><br />\r\n    <b></b>{{ \"SALAXY.NG1.CertificateAddComponent.base64\" |sxyTranslate }} ({{ $ctrl.certFormat }})<br />\r\n    <textarea readonly rows=\"15\" id=\"certificate-bytes\" style=\"width:100%;\">{{$ctrl.result.text }}</textarea>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"$ctrl.result.thumbprint\" type=\"button\" class=\"btn btn-info\" onclick='document.getElementById(\"certificate-bytes\").select(); document.execCommand(\"copy\");'\r\n    sxy-text=\"SALAXY.NG1.CertificateAddComponent.copyBase64\"></button>\r\n  <button ng-if=\"!$ctrl.result.thumbprint\" type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!certificateAddDialogForm.$valid\" ng-click=\"$ctrl.createCert()\"\r\n    sxy-text=\"SALAXY.NG1.CertificateAddComponent.createSertificate\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/EInvoiceAddressList.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.name\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.receiver\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.intermediator\"></th>\r\n            <th class=\"right\">\r\n              <form name=\"searchForm\">\r\n                <salaxy-form-group name=\"search\" label-type=\"plain\">\r\n                  <div class=\"input-group\">\r\n                    <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"searchAddress\" name=\"searchAddress\" ng-model=\"$ctrl.logic.officialId\" sxy-company-id-fi>\r\n                    <span class=\"input-group-btn\">\r\n                      <button type=\"submit\" ng-disabled=\"!searchForm.$valid\" class=\"btn btn-default\" ng-click=\"$ctrl.logic.search()\"><span ng-show=\"$ctrl.logic.isLoading\"><i\r\n                            class=\"fa fa-refresh fa-spin fa-fw\"></i></span><span ng-show=\"!$ctrl.logic.isLoading\"><i class=\"fa fa-search\"></i></span></button>\r\n                    </span>\r\n                  </div>\r\n              </form>\r\n              </salaxy-form-group>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.logic.addresses\">\r\n            <td>\r\n              <span>{{row.receiverName}}</span><br>\r\n              <small>{{row.receiverOfficialId}}</small>\r\n            </td>\r\n            <td>\r\n              <span>{{row.receiver}}</span><br>\r\n            </td>\r\n            <td>\r\n              <span>{{row.intermediatorName}}</span><br>\r\n              <small>{{row.intermediator}}</small>\r\n            </td>\r\n            <td class=\"right middle\">\r\n              <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.logic.isSelected($ctrl.current, row) ? 'btn-success' : 'btn-default'\"\r\n                ng-click=\"$ctrl.logic.setCurrent($ctrl.current, row)\">\r\n                {{ $ctrl.logic.isSelected($ctrl.current, row) ? ('SALAXY.UI_Terms.chosen' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n              </button>\r\n            </td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.logic.addresses.length == 0\">\r\n            <td colspan=\"4\" sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.receiverNotFound\"></td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('reset')\" sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.dontUseAnyAddress\"></button>\r\n    <button type=\"button\" ng-disabled=\"!$ctrl.logic.isAnySelected($ctrl.current)\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.EInvoiceAddressListComponent.useSelectedAddress\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/Insurance.html\",`<div class=\"localtapiola-modal-wrapper\">\r\n  <!-- Import LocalTapiola fonts -->\r\n  <link rel=\"stylesheet\" href=\"https://cdn.duetds.com/api/fonts/1.3.14/lib/localtapiola.css\" integrity=\"sha384-5JYmtSD7nykpUvSmTW1CHMoBDkBZUpUmG0vuh+NUVtZag3F75Kr7+/JU3J7JV6Wq\"\r\n    crossorigin=\"anonymous\" />\r\n  <div class=\"localtapiola-modal\">\r\n    <div class=\"modal-header\">\r\n      <div class=\"logo-wrapper\">\r\n        <img src=\"https://cdn.salaxy.com/ng1/localtapiola-modal/localtapiola-white-logo.png\" class=\"img-responsive logo-img\" alt=\"LähiTapiola\" />\r\n      </div>\r\n      <button class=\"close text-right\" ng-click=\"$close('cancel')\" aria-label=\"Close\">{{'SALAXY.UI_Terms.close' | sxyTranslate}} <span>&times;</span></button>\r\n    </div>\r\n    <div class=\"modal-body salaxy-wizard\">\r\n      <ng-include src=\"$ctrl.currentStep.view || 'salaxy-components/modals/localTapiola/Start.html'\"></ng-include>\r\n    </div>\r\n    <div class=\"modal-footer\" ng-if=\"$ctrl.currentStep.buttonsView\">\r\n      <div class=\"footer-content\">\r\n        <ng-include src=\"$ctrl.currentStep.buttonsView || 'salaxy-components/modals/localTapiola/buttons-default.html'\"></ng-include>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<style>\r\n  .uib-datepicker-popup .text-info {\r\n    color: #333;\r\n    font-weight: bold;\r\n  }\r\n\r\n  .uib-datepicker-popup .uib-day .btn.active {\r\n    background-color: #0077b3;\r\n    box-shadow: none;\r\n    color: #fff;\r\n  }\r\n\r\n  .uib-datepicker-popup .uib-day .btn.active .text-info {\r\n    color: #fff;\r\n  }\r\n\r\n  .uib-datepicker-popup .uib-button-bar .btn-info,\r\n  .uib-datepicker-popup .uib-button-bar .btn-info:hover,\r\n  .uib-datepicker-popup .uib-button-bar .btn-info:focus {\r\n    color: #009fd8;\r\n    border-color: transparent;\r\n    border-radius: 0;\r\n    font-weight: 600;\r\n    background-color: transparent;\r\n    font-family: \"localtapiola-sans\";\r\n    font-size: 14px;\r\n    outline: none;\r\n  }\r\n\r\n  .uib-datepicker-popup .uib-button-bar .btn-danger,\r\n  .uib-datepicker-popup .uib-button-bar .btn-danger:hover,\r\n  .uib-datepicker-popup .uib-button-bar .btn-danger:focus {\r\n    color: #009fd8;\r\n    border-color: transparent;\r\n    border-radius: 0;\r\n    font-weight: 600;\r\n    background-color: transparent;\r\n    font-family: \"localtapiola-sans\";\r\n    font-size: 14px;\r\n    outline: none;\r\n  }\r\n\r\n  .uib-datepicker-popup .uib-button-bar .btn-success,\r\n  .uib-datepicker-popup .uib-button-bar .btn-success:hover,\r\n  .uib-datepicker-popup .uib-button-bar .btn-success:focus {\r\n    color: #009fd8;\r\n    border-color: transparent;\r\n    background-color: transparent;\r\n    font-family: \"localtapiola-sans\";\r\n    font-size: 14px;\r\n    outline: none;\r\n    font-weight: 600;\r\n  }\r\n</style>`);\n\n $templateCache.put(\"salaxy-components/modals/account/PrimaryPartner.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyProductDialogLabel\">{{ $ctrl.current.name }}</h2>\r\n  <h4 class=\"subtitle\">{{ $ctrl.current.description }}</h4>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <div class=\"form-horizontal\">\r\n    <div class=\"salaxy-component salaxy-product-info-headers\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-sm-4\">\r\n          <i class=\"salaxy-avatar\" style=\"font-size: 140px;\">\r\n            <img ng-src=\"{{ $ctrl.current.branding.logo }}\" />\r\n          </i>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-8\">\r\n          <div class=\"salaxy-product-description\">\r\n            <p>\r\n              {{ $ctrl.current.branding.text }}\r\n            </p>\r\n            <a ng-if=\"$ctrl.current.branding.url\" class=\"btn btn-primary\" target=\"_blank\" ng-href=\"{{$ctrl.current.branding.url}}\">{{'SALAXY.NG1.PrimaryPartnerComponent.moreInfo' | sxyTranslate}} »</a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"row\" ng-if=\"!$ctrl.current.isAuthorized\">\r\n        <div class=\"col-xs-12 input-info\">\r\n          <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n          <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.PrimaryPartnerComponent.notAuthorized.html\"></p>\r\n        </div>\r\n      </div>\r\n      <div class=\"row\" ng-if=\"!$ctrl.current.isAuthorized\">\r\n        <div class=\"col-xs-12 input-info\">\r\n          <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n          <p class=\"small input-info-text with-icon\" sxy-text=\"SALAXY.NG1.PrimaryPartnerComponent.notAuthorized.text\"></p>\r\n        </div>\r\n      </div>\r\n\r\n      <div class=\"row\" ng-if=\"$ctrl.current.isAuthorized\">\r\n        <div class=\"col-xs-12 input-info\">\r\n          <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n          <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.PrimaryPartnerComponent.authorized.html\"></p>\r\n        </div>\r\n      </div>\r\n      <div class=\"row\" ng-if=\"$ctrl.current.isAuthorized\">\r\n        <div class=\"col-xs-12 input-info\">\r\n          <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n          <p class=\"small input-info-text with-icon\" sxy-text=\"SALAXY.NG1.PrimaryPartnerComponent.authorized.text\"></p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer text-right\">\r\n  <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"!$ctrl.current.isAuthorized\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.PrimaryPartnerComponent.setPrimaryPartner\"></button>\r\n  <button ng-if=\"$ctrl.current.isAuthorized\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.PrimaryPartnerComponent.removePrimaryPartnerCredential\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/account/VismaModal.html\",`<div id=\"salaxyDialog\" class=\"salaxy-component salaxy-dialog modal-dialog visma-modal {{size ? 'modal-' + size : ''}}\" aria-labelledby=\"salaxyDialogLabel\" role=\"dialog\">\r\n  <link href=\"https://fonts.googleapis.com/css?family=Exo:400,700\" rel=\"stylesheet\">\r\n  <div class=\"modal-content\" role=\"document\" uib-modal-transclude></div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/accounting-target/accounting-targets.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"shortText\" sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.exportDefinition\"></div>\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.targetChannel\"></div>\r\n          </th>\r\n          <th sxy-orderby=\"owner\" colspan=\"2\">\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.owner\"></div>\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.status\"></div>\r\n          </th>\r\n\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div title=\"{{ row.shortText }} ({{ row.id }})\">\r\n              <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.ownerInfo.avatar.displayName }}</div>\r\n            <div>{{ \"AccountingTargetStatus.\" + row.status | sxyEnum }}</div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/batch/default.html\",`﻿<div class=\"salaxy-batch-default\">\r\n  <button ng-if=\"!$ctrl.autoStart\" type=\"button\" class=\"btn btn-primary\" ng-disabled=\"$ctrl.isProcessStarted\" ng-click=\"$ctrl.startProcess()\">Aloita prosessi</button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/batch/dialog.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">{{ $ctrl.dialogHeader }}</h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"salaxy-batch-content\" ng-include=\"$ctrl.batchTemplateUrl\"></div>\r\n  <hr/>\r\n  <sxy-table ng-if=\"$ctrl.isReady\" data=\"$ctrl.list\" options=\"$ctrl.tableOptions\" include=\"$ctrl.columns\" ng-ref=\"$ctrl.$table\"></sxy-table>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <h2 class=\"pull-left\" style=\"margin: 0\" ng-if=\"$ctrl.processCounter.isProcessing || $ctrl.processCounter.isDone\">\r\n    {{ $ctrl.processCounter.isDone ? ('SALAXY.NG1.BatchProcessComponent.dialog.done' | sxyTranslate) : ('SALAXY.NG1.BatchProcessComponent.dialog.processing' | sxyTranslate) }}: {{ $ctrl.processCounter.processedCount }} / {{ $ctrl.processCounter.totalCount }}\r\n    <span class=\"bg-danger\" ng-if=\"$ctrl.processCounter.errorsCount\">{{'SALAXY.NG1.BatchProcessComponent.dialog.errors' | sxyTranslate}}: {{ $ctrl.processCounter.errorsCount }}</span>\r\n    <span class=\"bg-warning\" ng-if=\"$ctrl.processCounter.canceling\" sxy-text=\"SALAXY.NG1.BatchProcessComponent.dialog.canceling\"></span>\r\n  </h2>\r\n  <h2 class=\"pull-left\" style=\"margin: 0\" ng-if=\"!($ctrl.processCounter.isProcessing || $ctrl.processCounter.isDone)\">\r\n    {{'SALAXY.NG1.BatchProcessComponent.dialog.count' | sxyTranslate}}: {{ $ctrl.processCounter.totalCount }} ({{ $ctrl.list.length }})\r\n  </h2>\r\n  <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.cancelProcess()\" ng-if=\"$ctrl.processCounter.isProcessing\" sxy-text=\"SALAXY.NG1.BatchProcessComponent.dialog.stopProcessing\"></button>\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.close()\" ng-if=\"!$ctrl.processCounter.isProcessing\">{{'SALAXY.UI_Terms.close' | sxyTranslate}}</button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/Calc.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-calc model=\"$ctrl.current\"></salaxy-calc>\r\n  </div>\r\n  <div class=\"modal-footer text-left\">\r\n    <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/CalcIr.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-calc-ir-rows model=\"$ctrl.current\"></salaxy-calc-ir-rows>\r\n    <div>\r\n      <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/CalcLeaves.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close(null)\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.absences.calculationLegend\" ></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <salaxy-calc-leaves ng-ref=\"$calcLeaves\" calc=\"$ctrl.current.calc\" worktime=\"$ctrl.current.worktime\"></salaxy-calc-leaves>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$close(null)\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$close({absencesPeriods: $calcLeaves.getAbsencesPeriods()})\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/CalcList.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title | sxyTranslate}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <salaxy-calc-list category=\"{{ $ctrl.logic.category || 'draft' }}\" mode=\"select\" selected-items=\"$ctrl.current\"></salaxy-calc-list>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/CalcReports.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.calcReports\" ></h2>\r\n</div>\r\n<div class=\"modal-body \">\r\n  <salaxy-calc-reports calcs=\"$ctrl.data.calcs\" preview=\"$ctrl.data.preview\" view=\"{{ $ctrl.data.view || 'page1' }}\" report-type=\"$ctrl.data.reportType\"></salaxy-calc-reports>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/CfaPaymentOverview.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{ $ctrl.logic.title }}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n\r\n    <style type=\"text/css\">\r\n      .left.carousel-control {\r\n        background-image: none;\r\n      }\r\n      \r\n      .right.carousel-control {\r\n        background-image: none;\r\n      }\r\n      \r\n      .right.carousel-control>span.glyphicon.glyphicon-chevron-right {\r\n        color: var(--salaxy-brand-primary)\r\n      }\r\n      \r\n      .left.carousel-control>span.glyphicon.glyphicon-chevron-left {\r\n        color: var(--salaxy-brand-primary)\r\n      }\r\n      \r\n      .carousel-indicators .active {\r\n        background-color: var(--salaxy-brand-primary);\r\n      }\r\n      \r\n      .carousel-indicators li {\r\n        border-color: var(--salaxy-brand-primary);\r\n      }\r\n    </style>\r\n      \r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1.CfaPaymentOverviewComponent.lead\" ng-if=\"$ctrl.logic.isReadyForPayment\"></p>\r\n    <div class=\"alert alert-danger\" ng-if=\"!$ctrl.logic.isReadyForPayment()\">\r\n      <p class=\"lead\" sxy-html=\"SALAXY.NG1.PaymentDialogComponent.alert.html\"></p>\r\n    </div>\r\n    <p class=\"lead\" ng-if=\"$ctrl.logic.isReadyForPayment() && $ctrl.logic.instructions\">\r\n      {{ $ctrl.logic.instructions }}\r\n    </p>\r\n    <div ng-if=\"$ctrl.logic.type == 'calc'\">\r\n      <salaxy-calc-worker-info model=\"$ctrl.current\"></salaxy-calc-worker-info>\r\n      <p >\r\n        <strong sxy-text=\"SALAXY.NG1.CalcDetailsWorkComponent.workEndStartDate\" ps=\":\"></strong> {{$ctrl.current.info.workStartDate | date : 'dd.MM.yyyy'}}{{ $ctrl.current.info.workStartDate ? ' - ': ''}} {{$ctrl.current.info.workEndDate\r\n        | date: 'dd.MM.yyyy'}}, {{$ctrl.current.framework.numberOfDays > 0 ? $ctrl.current.framework.numberOfDays : '?' }} {{'SALAXY.NG1.CfaPaymentOverviewComponent.days' | sxyTranslate}}.\r\n      </p>\r\n      <hr />\r\n      <div class=\"table-responsive\"> \r\n        <salaxy-calc-report apply-site-styles=\"true\" calc=\"$ctrl.current\" report-type=\"'paymentReport'\" template-name=\"'paymentTablesV2'\"></salaxy-calc-report>\r\n      </div>\r\n      <p sxy-html=\"SALAXY.NG1.PaymentDialogComponent.afterPayment.html\" params=\"{totalPayment: ($ctrl.current.result.employerCalc.totalPayment | currency)}\"></p>\r\n      <p ng-if=\"$ctrl.current.result.employerCalc.householdDeduction > 0\" sxy-html=\"SALAXY.NG1.PaymentDialogComponent.household.html\" params=\"{householdDeduction: ($ctrl.current.result.employerCalc.householdDeduction | currency) }\">\r\n      </p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.logic.type != 'calc'\">\r\n      <strong>{{'SALAXY.NG1.CfaPaymentOverviewComponent.totalPayments' | sxyTranslate}}: {{$ctrl.current.info.totalPayment | currency}}</strong><br />\r\n      <strong>{{'SALAXY.NG1.CfaPaymentOverviewComponent.calculations' | sxyTranslate}}: {{$ctrl.current.calcs.length}}</strong><br />\r\n      <hr />\r\n      <div uib-carousel active=\"activeReport\">\r\n        <div uib-slide ng-repeat=\"calc in $ctrl.current.calcs track by $index\" index=\"$index\">\r\n          <strong>{{$index + 1}}/{{$ctrl.current.calcs.length}} {{calc.worker.avatar.sortableName}}</strong>\r\n          <salaxy-calc-report calc=\"calc\" apply-site-styles=\"true\" report-type=\"'paymentReport'\" template-name=\"'paymentTablesV2'\"></salaxy-calc-report>\r\n        </div>\r\n      </div>\r\n      <p sxy-html=\"SALAXY.NG1.PaymentDialogComponent.afterPayment.html\" params=\"{totalPayment: ($ctrl.current.info.totalPayment | currency)}\"></p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.logic.channel == 'palkkausCfaPaytrail' || $ctrl.logic.channel == 'palkkausEcfaPaytrail'\">\r\n      <p sxy-text=\"SALAXY.NG1.CfaPaymentOverviewComponent.palkkausCfaPaytrailInfo\"></p>\r\n      <p sxy-text=\"SALAXY.NG1.CfaPaymentOverviewComponent.palkkausCfaPaytrailInfoAlt\"></p>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer text-left\">\r\n    <button ng-if=\"$ctrl.logic.channel != 'palkkausCfaPaytrail' && $ctrl.logic.channel != 'palkkausEcfaPaytrail'\" type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"!$ctrl.logic.isReadyForPayment()\" ng-click=\"$close('ok')\">\r\n      {{ $ctrl.logic.okButtonText}}\r\n    </button>\r\n    <button ng-if=\"$ctrl.logic.channel == 'palkkausCfaPaytrail' || $ctrl.logic.channel == 'palkkausEcfaPaytrail'\" type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"!$ctrl.logic.isReadyForPayment()\" ng-click=\"$ctrl.logic.paymentFunc($ctrl.current);$close('ok')\">\r\n      {{ $ctrl.logic.okButtonText}}\r\n    </button>\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/EditorConfirm.html\",`<div class=\"modal-editor-confirm\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"Oletko varma?\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <p sxy-text=\"Hyväksynnän jälkeen päivitämme tulosteet ja raportoimme muutokset tulorekisteriin.\"></p>\r\n    <p>&nbsp;</p>\r\n    <form name=\"snapshotForm\" class=\"form-horizontal\">\r\n      <salaxy-input-enum label=\"Syykoodi\" name=\"reasonCode\" ng-model=\"$ctrl.current.reasonCode\" options=\"{\r\n        1: 'Asiakkaan korjauspyyntö',\r\n        2: 'Virheellinen laskelma',\r\n        3: 'Palkkaus ohjelmistovirhe',\r\n        4: 'Uusi ilmoitus/peruminen tulorekisteriin',\r\n        }\"></salaxy-input-enum>\r\n      <salaxy-input-enum label=\"Vakavuusaste\" name=\"severityCode\" type=\"radio\" ng-model=\"$ctrl.current.severityCode\" options=\"{ 1:'1', 2:'2', 3 :'3', 4 :'4', 5:'5' }\">\r\n      </salaxy-input-enum>\r\n      <div class=\"form-group\">\r\n        <label for=\"\" class=\"col-xs-4 control-label\">\r\n          <span class=\"label-text\">Kategoriat</span>\r\n        </label>\r\n        <div class=\"col-xs-8\">\r\n          <table>\r\n            <tr>\r\n              <td colspan=\"2\" class=\"text-right\"><button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.current.categories.push('')\">Uusi kategoria</button></td>\r\n            </tr>\r\n            <tr>\r\n              <td colspan=\"2\">&nbsp;</td>\r\n            </tr>\r\n            <tr ng-repeat=\"category in $ctrl.current.categories track by $index\">\r\n              <td>\r\n                  <salaxy-form-group name=\"category{{$index}}\" label-type=\"plain\">\r\n                      <div>\r\n                          <input type=\"text\" ng-model=\"$ctrl.current.categories[$index]\" uib-typeahead=\"categoryOption for categoryOption in  $ctrl.logic.categories | filter:$viewValue | limitTo:8\" class=\"form-control\">\r\n                      </div>\r\n                  </salaxy-form-group>\r\n              </td>\r\n              <td>\r\n                  <button type=\"button\" class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.categories.splice($index,1)\" title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\"><i class=\"fa fa-trash\"></i></button>\r\n              </td>\r\n          </tr>\r\n          </table>\r\n        </div>\r\n      </div>\r\n\r\n      <salaxy-textarea label=\"Kuvaus\" name=\"description\" ng-model=\"$ctrl.current.description\"></salaxy-textarea>\r\n    </form>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!snapshotForm.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/EmailSharing.html\",`<div class=\"modal-email-sharing\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.EmailSharingComponent.title\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <p sxy-html=\"SALAXY.NG1.EmailSharingComponent.body.html\"></p>\r\n    <form name=\"emailForm\" class=\"form-horizontal\">\r\n      <salaxy-input label=\"SALAXY.NG1.EmailSharingComponent.emailTo\" name=\"to\" type=\"text\" require=\"true\" ng-model=\"$ctrl.current.to\" sxy-email></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.EmailSharingComponent.emailCC\" name=\"cc\" type=\"text\" ng-model=\"$ctrl.current.cc\" sxy-email></salaxy-input>\r\n      <salaxy-textarea label=\"SALAXY.NG1.EmailSharingComponent.message\" name=\"message\" ng-model=\"$ctrl.current.message\"></salaxy-textarea>\r\n    </form>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!emailForm.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.EmailSharingComponent.sendEmail\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/PalkkausPersonalPaymentOverview.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">{{ $ctrl.editDialogParameters.logic.isInspectingPaidInvoices ? ('SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.titleInspect' | sxyTranslate) : ('SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.title' | sxyTranslate) }}</h2>\r\n</div>\r\n<div class=\"modal-body salaxy-wizard\" ng-controller=\"InvoicesCreateController as $invCreate\">\r\n\r\n  <div class=\"visible-xs visible-sm\" ng-init=\"$invCreate.model=$ctrl.model\">\r\n    <h4><span sxy-text=\"SALAXY.NG1.WorkerWizardComponent.wizard.step\"></span> {{$ctrl.currentStep.number}}/{{$ctrl.steps.length}}</h4>\r\n  </div>\r\n  <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n      <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n        <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n      </span>\r\n      <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n        <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n      </a>\r\n    </div>\r\n  </div>\r\n  <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n      <span>{{ step.title | sxyTranslate}}</span>\r\n    </div>\r\n  </div>\r\n  <div class=\"worker-wizard-content\">\r\n    <ng-include src=\"$ctrl.currentStep.view\"></ng-include>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button ng-if=\"$ctrl.step < 2 && !$ctrl.editDialogParameters.logic.isInspectingPaidInvoices\" ng-click=\"$close('cancel')\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"$ctrl.editDialogParameters.logic.isInspectingPaidInvoices && $ctrl.step == 3\" ng-click=\"$close('cancel')\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"$ctrl.step >= 2\" ng-click=\"$ctrl.goPrevious()\" ng-disabled=\"!$ctrl.canGoPrevious\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n  <button ng-if=\"$ctrl.step &lt; $ctrl.steps.length\" ng-click=\"$ctrl.goNext()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/modals/calc/PaymentOverview.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{ $ctrl.$invCreate.title }}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-invoices-create model=\"$ctrl.current\" ng-ref=\"$ctrl.$invCreate\"></salaxy-invoices-create>\r\n  </div>\r\n  <div class=\"modal-footer text-left\">\r\n    <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-if=\"$ctrl.$invCreate.getOkBtn()\" ng-click=\"$ctrl.$invCreate.createInvoices($close)\">\r\n      {{ $ctrl.$invCreate.getOkBtn() }}\r\n     \r\n    </button>\r\n\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <div ng-if=\"$ctrl.logic.channel == 'palkkausPersonal'\">\r\n      <div>\r\n        <b>Debug</b><br>\r\n        <salaxy-json-formatter json=\"$ctrl.$invCreate.invoices\" open=\"1\"></salaxy-json-formatter>\r\n      </div>\r\n      <div>\r\n      </div>\r\n    </div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/personal-payment/Approval.html\",`<div ng-controller=\"InvoicesCreateController as $invCreate\" ng-init=\"$invCreate.model=$ctrl.model\">\r\n  <section>\r\n    <h3 sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.title\"></h3>\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.text\"></p>      \r\n  </section>\r\n  <section>\r\n    <h3 sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.buttonInfoText\"></h3>\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.irInfo\"></p>\r\n  </section>\r\n  <section ng-if=\"$ctrl.eprPaymentWarning && $invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.invoice.status !== 'paid'\">\r\n    <p class=\"lead\">{{$ctrl.eprPaymentWarning}}</p>\r\n  </section>\r\n  <section ng-if=\"$ctrl.eprCancelWarning && $invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.invoice.status === 'paid'\">\r\n    <p class=\"lead\">{{$ctrl.eprCancelWarning}}</p>\r\n  </section>\r\n \r\n  <button ng-click=\"$close('paid')\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview && ( $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'unread' || $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'read' ||  $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'waitingConfirmation' )\"\r\n  type=\"button\" class=\"btn btn-success\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.acceptButton\"></button>\r\n  <button ng-click=\"$close('cancel')\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.exists == false\" type=\"button\" class=\"btn btn-danger\"  sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.notPaidInfo\"></button>\r\n  <button ng-click=\"$close('canceled')\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview &&  $invCreate.primaryCalcNetInvoicePreview.exists == true && ( $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'unread' || $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'read' ||  $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'waitingConfirmation' )\"\r\n    type=\"button\" class=\"btn btn-danger\"  sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step4.declineButton\"></button>\r\n  <button ng-click=\"$close('canceled')\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.invoice.status == 'paid'\" type=\"button\" class=\"btn btn-danger\"  sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.cancelInfo\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/personal-payment/SideCosts.html\",`<section>\r\n  <h3 sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.title\"></h3>\r\n  <p class=\"lead\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.text\"></p>   \r\n  <ul>\r\n    <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.listItem1\"></li>\r\n    <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.listItem2\"></li>\r\n    <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.listItem3\"></li>\r\n  </ul>\r\n  <p class=\"lead\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step3.textAlt\"></p>\r\n</section>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/personal-payment/Tax.html\",`<div ng-controller=\"InvoicesCreateController as $invCreate\" ng-init=\"$invCreate.model=$ctrl.model\">\r\n  <div class=\"hidden-print\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview.invoice.status == 'paid'\">\r\n    <p class=\"lead\">\r\n      <button type=\"button\" class=\"btn btn-primary pull-right\" onclick=\"window.print()\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.printInvoices\"></button> {{'SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.paid.paidInspectTax' |\r\n      sxyTranslate}}\r\n    </p>\r\n    <div ng-if=\"$invCreate.primaryCalcTaxInvoicePreview\" class=\"credit-transfer-container\">\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcTaxInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.tax\"></p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.taxInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n  <div class=\"hidden-print\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.invoice.status != 'paid'\">\r\n    <section>\r\n      <h3 sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step2.title\"></h3>\r\n      <button type=\"button\" class=\"btn btn-primary pull-right\" onclick=\"window.print()\" sxy-text=\"Tulosta\"></button>\r\n      <p class=\"lead\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step2.text.html\"></p>\r\n    </section>\r\n    <table class=\"table\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.receiver\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.iban\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.reference\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.dueDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.sum\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr>\r\n          <th rowspan=\"2\" style=\"font-size: 2em;\"></th>\r\n          <th>{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.otherPartyInfo.avatar.displayName }}</th>\r\n          <th>{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.otherPartyInfo.ibanNumber }}</th>\r\n          <th sxy-if-role=\"test\">{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.reference || \"RF02 TEST 1234\" }}</th>\r\n          <th sxy-if-role=\"!test\">{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.reference || ('SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.checkReference' | sxyTranslate) }}</th>\r\n          <th class=\"right\">{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.data.dueDate | sxyDate }}</th>\r\n          <th class=\"right\">{{ $invCreate.primaryCalcTaxInvoicePreview.invoice.payment | currency }}</th>\r\n        </tr>\r\n        <tr class=\"no-border\">\r\n          <td colspan=\"5\">\r\n            <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcTaxInvoicePreview\" mode=\"barcode-copy\">\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <div ng-if=\"$invCreate.primaryCalcTaxInvoicePreview\" class=\"credit-transfer-container\">\r\n\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcTaxInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.tax\"></p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.taxInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n  <div class=\"visible-print\">\r\n    <h1 ng-if=\"!$ctrl.editDialogParameters.logic.isInspectingPaidInvoices\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.heading\"></h1>\r\n    <div ng-if=\"$invCreate.primaryCalcTaxInvoicePreview\" class=\"credit-transfer-container\">\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcTaxInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p>Ennakonpidätys</p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.taxInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/personal-payment/TotalWorkerPayment.html\",`<div ng-controller=\"InvoicesCreateController as $invCreate\" ng-init=\"$invCreate.model=$ctrl.model\">\r\n  <div ng-if=\"!$invCreate.isValid\">\r\n    <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.invalidCalc\"></p>\r\n    <salaxy-validation-summary api-validation=\"$invCreate.current.result.validation\"></salaxy-validation-summary>\r\n  </div>\r\n  <div ng-if=\"$invCreate.paymentStatus == 'canceled'\">\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.lead\"></p>\r\n    <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.salaryAlreadyPaid\"></p>\r\n    <ul>\r\n      <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.salaryAlreadyPaidInfo1\"></li>\r\n      <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.salaryAlreadyPaidInfo2\"></li>\r\n      <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.salaryAlreadyPaidInfo3\"></li>\r\n      <li sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.canceled.salaryAlreadyPaidInfo4\"></li>\r\n    </ul>\r\n  </div>\r\n  <div class=\"hidden-print\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview.invoice.status == 'paid'\">\r\n    <p class=\"lead\">\r\n      <button type=\"button\" class=\"btn btn-primary pull-right\" onclick=\"window.print()\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.printInvoices\"></button> {{'SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.paid.paidInspectNet' |\r\n      sxyTranslate}}\r\n    </p>\r\n    <div ng-if=\"$invCreate.primaryCalcNetInvoicePreview\" class=\"credit-transfer-container\">\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcNetInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.salary\"></p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.salaryInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n  <div class=\"hidden-print\" ng-if=\"$invCreate.primaryCalcNetInvoicePreview && $invCreate.primaryCalcNetInvoicePreview.invoice.status != 'paid'\">\r\n    <section>\r\n      <h3 sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step1.title\"></h3>\r\n      <button type=\"button\" class=\"btn btn-primary pull-right\" onclick=\"window.print()\" sxy-text=\"Tulosta\"></button>\r\n      <p class=\"lead\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.steps.step1.text.html\"></p>\r\n    </section>\r\n    <table class=\"table\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.receiver\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.iban\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.reference\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.dueDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.sum\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr>\r\n          <th rowspan=\"2\" style=\"font-size: 2em;\"></th>\r\n          <th>{{ $invCreate.primaryCalcNetInvoicePreview.invoice.otherPartyInfo.avatar.displayName }}</th>\r\n          <th>{{ $invCreate.primaryCalcNetInvoicePreview.invoice.otherPartyInfo.ibanNumber }}</th>\r\n          <th sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.preview.salary\"></th>\r\n          <th class=\"right\">{{ $invCreate.primaryCalcNetInvoicePreview.invoice.data.dueDate | sxyDate }}</th>\r\n          <th class=\"right\">{{ $invCreate.primaryCalcNetInvoicePreview.invoice.payment | currency }}</th>\r\n        </tr>\r\n        <tr class=\"no-border\">\r\n          <td colspan=\"5\">\r\n            <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcNetInvoicePreview\" mode=\"barcode-copy\">\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <div ng-if=\"$invCreate.primaryCalcNetInvoicePreview\" class=\"credit-transfer-container\">\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcNetInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.salary\"></p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.salaryInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n  <div class=\"visible-print\">\r\n    <h1 ng-if=\"!$ctrl.editDialogParameters.logic.isInspectingPaidInvoices\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.heading\"></h1>\r\n    <div ng-if=\"$invCreate.primaryCalcNetInvoicePreview\" class=\"credit-transfer-container\">\r\n      <salaxy-credit-transfer invoice-preview=\"$invCreate.primaryCalcNetInvoicePreview\" mode=\"official\">\r\n        <message>\r\n          <p>Palkka</p>\r\n          <p style=\"text-transform: none;\" sxy-html=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.statuses.mobileBanking.salaryInfo.html\"></p>\r\n        </message>\r\n      </salaxy-credit-transfer>\r\n    </div>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/row-type-select.html\",`<div class=\"salaxy-component salaxy-calc-details-dialog\">\r\n  <div class=\"panel panel-list\" ng-class=\"'panel-' + ($ctrl.logic.rowTypeSelectHelp || 'primary')\">\r\n    <div class=\"panel-heading\">\r\n      <button type=\"button\" class=\"close pull-right\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h1>{{ \"SALAXY.NG1.CalcDetailsDialogComponent.\" + ($ctrl.logic.rowTypeSelectHelp || \"all\") + \".title\" | sxyTranslate }}</h1>\r\n    </div>\r\n    <div class=\"panel-body\" ng-if=\"$ctrl.logic.rowTypeSelectHelp\">\r\n      <p>{{ \"SALAXY.NG1.CalcDetailsDialogComponent.\" + ($ctrl.logic.rowTypeSelectHelp || \"all\") + \".intro\" | sxyTranslate }}</p>\r\n    </div>\r\n    <salaxy-calc-row-type name=\"rowType\" type=\"list\" model=\"$ctrl.current\"\r\n      categories=\"$ctrl.logic.categories\"\r\n      row-types=\"$ctrl.logic.rowTypes\"\r\n      on-row-changed=\"$close('ok')\" label-type=\"plain\"></salaxy-calc-row-type>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/SalaryDateKind.html\",`<div class=\"modal-body modal-salary-date-kind\">\r\n  <form class=\"spacer-bottom form-horizontal\">\r\n    <legend sxy-text=\"{{$ctrl.logic.text}}\"></legend>\r\n    <p sxy-html=\"{{$ctrl.logic.title}}\"></p>\r\n  </form>\r\n  <div class=\"text-right\">\r\n    <button class=\"btn btn-sm btn-default\" ng-click=\"$dismiss()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button class=\"btn btn-sm btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/SalaryDateKindInputEnum.html\",`<ng-form name=\"{{$ctrl.name}}Form\" class=\"salaxy-input-enum\">\r\n  <salaxy-form-group ng-if=\"$ctrl.type=='radio'\" name=\"{{$ctrl.name}}\" require=\"$ctrl.require\" label=\"{{$ctrl.label}}\" label-type=\"{{$ctrl.labelType}}\" label-cols=\"{{$ctrl.labelCols}}\">\r\n    <div class=\"radio\" ng-repeat=\"x in $ctrl.getEnumerations()\">\r\n      <label class=\"control-label radio-label\" for=\"{{x.value}}\">\r\n        <input ng-disabled=\"$ctrl.getDisabled()\" type=\"radio\" ng-model=\"$ctrl.value\" ng-change=\"$ctrl.onChange()\" class=\"\" name=\"{{$ctrl.label}}\" id=\"{{x.value}}\" value=\"{{x.value}}\"\r\n          title=\"{{x.title | sxyTranslate}}\">\r\n          <strong>{{$ctrl.formatLabel(x)}}</strong>\r\n          <p ng-if=\"x.title\" class=\"text-small\">{{ x.title | sxyTranslate }}</p>\r\n      </label>\r\n    </div>\r\n  </salaxy-form-group>\r\n</ng-form>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/SelectVersion.html\",`<div class=\"modal-version-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{\"Valitse versio\" | sxyTranslate}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <style>\r\n      .table-hover>tbody>tr:hover>td,\r\n      .table-hover>tbody>tr:hover>th {\r\n        background-color: var(--salaxy-brand-info);\r\n        ;\r\n        text-decoration: none;\r\n      }\r\n    </style>\r\n    <table class=\"table table-condensed table-hover\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-text=\"SALAXY.NG1.CalcComponent.versions.creator\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcComponent.versions.date\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.data.versions\" class=\"clickable\" ng-class=\"{ 'bg-success': $ctrl.data.versionId == row.versionId }\" ng-click=\"$close(row)\">\r\n          <td class=\"align-middle td-avatar\">\r\n            <salaxy-avatar avatar=\"row.userAccount\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name\">\r\n            {{row.userAccount.displayName}}\r\n          </td>\r\n          <td class=\"right\">\r\n            <span>{{row.date | date: 'd.M.yyyy HH:mm:ss' }}</span><br />\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <salaxy-spinner ng-if=\"!$ctrl.data.versions.length\"></salaxy-spinner>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/WorkerList.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title | sxyTranslate}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <span ng-if=\"$ctrl.logic.infoHtml\" sxy-html=\"{{$ctrl.logic.infoHtml}}\"></span>\r\n    <div class=\"list-content\">\r\n      <salaxy-employment-list mode=\"multiselect\" selected-items=\"$ctrl.current\"></salaxy-employment-list>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\">{{$ctrl.logic.okButtonText ? ($ctrl.logic.okButtonText | sxyTranslate) : ('SALAXY.UI_Terms.save' | sxyTranslate)}}</button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/calc/WorkerSelect.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title | sxyTranslate}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <span ng-if=\"$ctrl.logic.infoHtml\" sxy-html=\"{{$ctrl.logic.infoHtml}}\"></span>\r\n    <div class=\"list-content\">\r\n      <salaxy-employment-list mode=\"select\" selected-items=\"$ctrl.current\" ng-ref=\"$employmentsList\" on-list-select=\"$employmentsList.selectedItems.splice(0, $employmentsList.selectedItems.length);(value == true ? $employmentsList.selectedItems.push(item) : null);\"></salaxy-employment-list>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\">{{$ctrl.logic.okButtonText ? ($ctrl.logic.okButtonText | sxyTranslate) : ('SALAXY.UI_Terms.save' | sxyTranslate)}}</button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/communications/VarmaPopup.html\",`<div class=\"modal-ui-translation\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.current.title}}</h2>\r\n  </div>\r\n\r\n  <div class=\"modal-body\">\r\n    <p ng-bind-html=\"$ctrl.current.message\"></p>\r\n\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 spacer-top\">\r\n        <button class=\"btn btn-default pull-left\" sxy-text=\"SALAXY.UI_Terms.close\" ng-click=\"$close('cancel')\"></button>\r\n        <a class=\"btn btn-primary pull-right\" href=\"{{$ctrl.current.varmaShopLink}}\" target=\"_blank\" sxy-text=\"{{$ctrl.current.btnText}}\"></a>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/date-range/DateRange.html\",`<div class=\"modal-body modal-date-range\">\r\n  <form class=\"spacer-bottom form-horizontal\">\r\n    <salaxy-date-range ng-model=\"$ctrl.current\" label=\"{{ $ctrl.logic.title }}\" name=\"dateRange\" label-type=\"basic\" label-placement=\"top\"></salaxy-date-range>\r\n  </form>\r\n  <div class=\"text-right\">\r\n    <button class=\"btn btn-sm btn-default\" ng-click=\"$dismiss()\" sxy-text=\"{{ $ctrl.logic.cancelText }}\"></button>\r\n    <button class=\"btn btn-sm btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"{{ $ctrl.logic.okText }}\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/export/Export.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyODataExportTitle\">{{ 'SALAXY.NG1.ODataExportComponent.heading' | sxyTranslate }}</h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Export options\">\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"exportMapper\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{ $ctrl.data.$parent.mapper.title }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"exportMapper\">\r\n        <li role=\"menuitem\" ng-repeat=\"mapper in $ctrl.data.$parent.allMappers\"><a href=\"\" ng-click=\"$ctrl.data.$parent.setExportMapper(mapper)\">{{mapper.title}}</a></li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"exportFileType\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{ $ctrl.data.$parent.currentExporter.label }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"exportFileType\">\r\n        <li role=\"menuitem\" ng-repeat=\"exporter in $ctrl.data.$parent.exporters\">\r\n          <a href=\"\" ng-click=\"$ctrl.data.$parent.currentExporter = exporter\">{{ exporter.label }}</a></li>\r\n      </ul>\r\n    </div>\r\n    <salaxy-input-enum name=\"localeId\" type=\"uib-dropdown\" enum=\"Culture\" label-type=\"plain\" label-format=\"title\" ng-model=\"$ctrl.data.$parent.localeId\"\r\n      ng-if=\"$ctrl.data.$parent.currentExporter.hasLocales\"></salaxy-input-enum>\r\n    <salaxy-input-enum name=\"maxCount\" type=\"uib-dropdown\" label-type=\"plain\" label-format=\"title\" ng-model=\"$ctrl.data.$parent.maxCount\"\r\n      options=\"$ctrl.data.$parent.maxCountOptions\"></salaxy-input-enum>\r\n    <div class=\"btn-group pull-right\" sxy-if-role=\"test\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.data.$parent.toggleDebug()\">Debug <span class=\"badge\">test</span></button>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.data.$parent.isDebug\">\r\n    <salaxy-data-mapper model=\"$ctrl.data.$parent.mapper\" type=\"debug\"></salaxy-data-mapper>\r\n  </div>\r\n  <div class=\"table-responsive\" style=\"padding-top: 5vh; text-align:center\">\r\n    <button id=\"exportNonQuick\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.data.$parent.export()\">\r\n      <span ng-show=\"!$ctrl.data.$parent.isExporting\">{{ 'SALAXY.NG1.ODataExportComponent.createMaterial' | sxyTranslate }} <i class=\"fa fa-download\"></i></span>\r\n      <span ng-show=\"$ctrl.data.$parent.isExporting\">{{ 'SALAXY.NG1.ODataExportComponent.createMaterial' | sxyTranslate }} <i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n    </button>\r\n    <div ng-show=\"$ctrl.data.$parent.isExporting\"><small>&nbsp;{{$ctrl.data.$parent.exportMessage}}</small></div>\r\n  </div>\r\n</div>\r\n\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/form-controls/HolidayRowTypeEdit.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"holidayRowTypeHeader\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.type\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <form name=\"holidayRowType\" class=\"form-horizontal\" ng-readonly=\"$ctrl.logic.readOnly\">\r\n    <salaxy-input-enum label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.type\" name=\"baseType\" type=\"radio\" options=\"{'incomeType': 'SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.incomeType', 'rowType' : 'SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.rowType', 'type': 'SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.wageType'}\" ng-model=\"$ctrl.current.baseType\" require=\"true\"></salaxy-input-enum>\r\n    <salaxy-input-income-type ng-if=\"$ctrl.current.baseType == 'incomeType'\" label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.incomeType\" name=\"code\" ng-model=\"$ctrl.current.type\" hidden-codes=\"[1]\">\r\n    </salaxy-input-income-type>\r\n    <salaxy-form-group  ng-if=\"$ctrl.current.baseType == 'rowType'\"  name=\"rowTypeLabel\" label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.rowType\">\r\n      <salaxy-calc-row-type label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.rowType\"  name=\"rowType\" model=\"$ctrl.logic.asUserDefinedRow($ctrl.current)\" ></salaxy-calc-row-type>\r\n    </salaxy-form-group>\r\n    <salaxy-form-group  ng-if=\"$ctrl.current.baseType == 'type'\"  name=\"type\" label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.wageType\">\r\n      <salaxy-alert type=\"warning\"><main><p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.typeNotSupported\"></p></main></salaxy-alert>\r\n    </salaxy-form-group>\r\n    <salaxy-input-boolean label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.exclusive\" name=\"isExclusive\" ng-model=\"$ctrl.current.isExclusive\"></salaxy-input-boolean>\r\n    <salaxy-input-enum ng-if=\"$ctrl.current.baseType == 'incomeType' && $ctrl.current.type == '201' \" label=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.unit\" enum=\"CalculationRowUnit\" hidden-options=\"[]\" filter=\"undefined,hours\" name=\"unit\" ng-model=\"$ctrl.current.unit\"></salaxy-input-enum>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"reset\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-disabled=\"!holidayRowType.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/modals/import/Import.html\",`<div class=\"salaxy-wizard\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" id=\"salaxyODataExportTitle\">{{'SALAXY.NG1.ODataImportComponent.heading' | sxyTranslate}} {{$ctrl.currentStep.number}}/{{$ctrl.steps.length}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\" id=\"modal-body\">\r\n    <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n      <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n        <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n          <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n        </span>\r\n        <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n          <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n        </a>\r\n      </div>\r\n    </div>\r\n    <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n      <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n        <span>{{ step.title | sxyTranslate}}</span>\r\n      </div>\r\n    </div>\r\n    <div class=\"wizard-content\">\r\n      <ng-include src=\"$ctrl.currentStep.view\"></ng-include>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/import/ImportStep1.html\",`<div ng-if=\"!$ctrl.data.$parent.api\" class=\"alert alert-danger\">\r\n  ERROR: No API selected.\r\n</div>\r\n<div ng-if=\"$ctrl.data.$parent.api\">\r\n  <div ng-if=\"$ctrl.data.$parent.api\" class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Data options\">\r\n    <div class=\"btn-group\" role=\"group\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.data.$parent.pasteFromClipboard()\">\r\n        <span>{{'SALAXY.NG1.ODataImportComponent.step1.pasteFromDesktop' | sxyTranslate}} <i class=\"fa fa-clipboard\"></i></span></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ngf-select=\"$ctrl.data.$parent.readFile($file)\" ngf-multiple=\"false\" ngf-max-size=\"10MB\">\r\n        <span>{{'SALAXY.NG1.ODataImportComponent.step1.downloadFile' | sxyTranslate}}... <i class=\"fa fa-file-text-o\"></i></span>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <textarea ng-model=\"$ctrl.data.$parent.batch.rawData\" style=\"width: 100%; height: 300px;\" placeholder=\"{{'SALAXY.NG1.ODataImportComponent.step1.copyExcelFileFromClipboard' | sxyTranslate}}\"></textarea>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button ng-disabled=\"!$ctrl.data.$parent.batch.rawData\" ng-click=\"$ctrl.data.$parent.readBatch();$ctrl.goNext()\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/import/ImportStep2.html\",`<salaxy-validation-summary api-validation=\"$ctrl.data.$parent.lastResult\"></salaxy-validation-summary>\r\n<div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Read options\">\r\n  <div class=\"btn-group\" uib-dropdown>\r\n    <button id=\"importMapper\" type=\"button\" class=\"btn\" ng-class=\"$ctrl.data.$parent.mapper ? 'btn-primary' : 'btn-danger'\" uib-dropdown-toggle>\r\n      {{$ctrl.data.$parent.mapper ? $ctrl.data.$parent.mapper.title : ('SALAXY.NG1.ODataImportComponent.step2.chooseMaterial' | sxyTranslate) }} <span class=\"caret\"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"importMapper\">\r\n      <li role=\"menuitem\" ng-repeat=\"mapper in $ctrl.data.$parent.objectMappers\"><a href=\"\" ng-click=\"$ctrl.data.$parent.setMapper(mapper.value)\">{{mapper.text}}</a></li>\r\n    </ul>\r\n  </div>\r\n  <div class=\"btn-group\" uib-dropdown>\r\n    <button id=\"importFileType\" type=\"button\" class=\"btn\" ng-class=\"$ctrl.data.$parent.currentFileParser ? 'btn-primary' : 'btn-danger'\" uib-dropdown-toggle>\r\n      {{ $ctrl.data.$parent.currentFileParser.label || ('SALAXY.NG1.ODataImportComponent.step2.chooseFiletype' | sxyTranslate) }} <span class=\"caret\"></span>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"importFileType\">\r\n      <li role=\"menuitem\" ng-repeat=\"parser in $ctrl.data.$parent.fileParsers\"><a href=\"\" ng-click=\"$ctrl.data.$parent.currentFileParser = parser;$ctrl.data.$parent.readBatch()\">{{ parser.label }}</a></li>\r\n    </ul>\r\n  </div>\r\n  <salaxy-input-enum name=\"localeId\" type=\"uib-dropdown\" enum=\"Culture\" label-type=\"plain\" label-format=\"title\" ng-model=\"$ctrl.data.$parent.localeId\"\r\n    ng-change=\"$ctrl.data.$parent.readBatch()\"\r\n    ng-if=\"$ctrl.data.$parent.currentFileParser.hasLocales\"></salaxy-input-enum>\r\n  <div class=\"btn-group pull-right\" sxy-if-role=\"test\">\r\n    <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.data.$parent.toggleDebug()\">Debug <span class=\"badge\">test</span></button>\r\n  </div>\r\n</div>\r\n<div ng-if=\"!$ctrl.data.$parent.batch.unmappedData.data.length\" class=\"table-responsive\" style=\"padding-top: 5vh; padding-bottom: 10vh; text-align:center\">\r\n  <span></span>\r\n</div>\r\n<div ng-if=\"$ctrl.data.$parent.batch.unmappedData.data.length\" class=\"table-responsive\" style=\"width: 100%; min-height: 300px; max-height: calc(100vh - 450px);\">\r\n  <salaxy-data-mapper ng-if=\"!$ctrl.data.$parent.isDebug\" model=\"$ctrl.data.$parent.batch.parserMapper\"></salaxy-data-mapper>\r\n  <salaxy-data-mapper ng-if=\"$ctrl.data.$parent.isDebug\" model=\"$ctrl.data.$parent.batch.parserMapper\" type=\"debug\"></salaxy-data-mapper>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button ng-click=\"$ctrl.goPrevious()\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n  <button ng-click=\"$ctrl.data.$parent.mapBatch();$ctrl.goNext()\" ng-disabled=\"!$ctrl.data.$parent.batch.unmappedData.data.length || !$ctrl.data.$parent.mapper\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/import/ImportStep3.html\",`<div ng-init=\"$ctrl.data.$parent.validateBatch()\">\r\n  <div class=\"alert alert-danger\" ng-if=\"$ctrl.data.$parent.batch.hasDataValidationErrors\" sxy-text=\"SALAXY.NG1.ODataImportComponent.step3.error\"></div>\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Validation options\">\r\n    <div class=\"btn-group\" role=\"group\">\r\n      <button id=\"validate\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.data.$parent.validateBatch()\">\r\n        <span>{{ 'SALAXY.NG1.ODataImportComponent.step3.check' | sxyTranslate }}\r\n          <i class=\"fa\" ng-class=\"$ctrl.data.$parent.progress ? 'fa-refresh fa-spin fa-fw' : 'fa-check'\"></i></span>\r\n      </button>\r\n      <div ng-show=\"$ctrl.data.$parent.progress\"><small>&nbsp;{{$ctrl.data.$parent.progressMessage}}</small></div>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <button class=\"btn btn-default\" ng-click=\"$ctrl.showTarget = false\" ng-class=\"{ active: !$ctrl.showTarget }\">Lähdedata</button>\r\n      <button class=\"btn btn-default\" ng-click=\"$ctrl.showTarget = true\" ng-class=\"{ active: $ctrl.showTarget }\">Kohdedata</button>\r\n    </div>\r\n    <div class=\"btn-group pull-right\" sxy-if-role=\"test\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.data.$parent.toggleDebug()\">Debug <span class=\"badge\">test</span></button>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.data.$parent.isDebug\">\r\n    <salaxy-data-mapper model=\"$ctrl.data.$parent.batch.mapper\" type=\"debug\"></salaxy-data-mapper>\r\n  </div>\r\n  <div ng-if=\"$ctrl.showTarget && $ctrl.data.$parent.batch.data.length\" class=\"table-responsive\" style=\"width: 100%; min-height: 300px; max-height: calc(100vh - 450px);\">\r\n    <salaxy-data-mapper model=\"$ctrl.data.$parent.batch.mapper\" type=\"target-value\"></salaxy-data-mapper>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.showTarget && $ctrl.data.$parent.batch.data.length\" class=\"table-responsive\" style=\"width: 100%; min-height: 300px; max-height: calc(100vh - 450px);\">\r\n    <salaxy-data-mapper model=\"$ctrl.data.$parent.batch.mapper\" type=\"source-value\"></salaxy-data-mapper>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button ng-click=\"$ctrl.goPrevious()\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n    <button ng-click=\"$ctrl.data.$parent.clearLastResult();$ctrl.goNext()\" ng-disabled=\"!$ctrl.data.$parent.batch.isDataValid\" class=\"btn btn-primary\"\r\n      sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/import/ImportStep4.html\",`<div class=\"alert alert-danger\" ng-if=\"$ctrl.data.$parent.batch.hasDataValidationErrors\" sxy-text=\"SALAXY.NG1.ODataImportComponent.step4.error\"></div>\r\n<div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Import options\">\r\n  <div class=\"btn-group\" role=\"group\">\r\n    <div ng-show=\"$ctrl.data.$parent.progress\"><small>&nbsp;{{$ctrl.data.$parent.progressMessage}}</small></div>\r\n  </div>\r\n</div>\r\n<div ng-if=\"$ctrl.data.$parent.batch.data.length\" class=\"table-responsive\" style=\"width: 100%; min-height: 300px; max-height: calc(100vh - 450px);\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.ODataImportComponent.step4.okey\"></th>\r\n        <th ng-repeat=\"header in $ctrl.data.$parent.mapper.target.keys\">{{header}}</th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.data.$parent.batch.data\">\r\n        <td>\r\n          <div ng-if=\"row.validation && row.validation.errors && row.validation.errors.length\" ng-repeat=\"error in row.validation.errors\">\r\n            <button uib-popover=\"{{ error.msg }}\" popover-title=\"{{ error.code }}\" type=\"button\" class=\"btn btn-danger\">{{ error.code }}</button><br>\r\n          </div>\r\n          <div ng-if=\"row.validation && row.validation.isValid\">\r\n            <span class=\"text-success\" sxy-text=\"SALAXY.NG1.ODataImportComponent.step4.okey\"></span>\r\n          </div>\r\n        </td>\r\n        <td ng-repeat=\"header in $ctrl.data.$parent.mapper.target.keys\" ng-switch=\"header\">\r\n          <!-- HACK: use type information instead of field name to format (or use sxyGrid.) -->\r\n          <span ng-switch-when=\"employment\">\r\n            <salaxy-avatar style=\"font-size: 18px;\" avatar=\"row.employment.personalInfo.avatar\"></salaxy-avatar>\r\n            {{ row.employment.personalInfo.avatar.displayName }}\r\n          </span>\r\n          <span ng-switch-default>{{row[header]}}</span>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button id=\"import\" type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.data.$parent.importBatch($close)\">\r\n    <span>{{ 'SALAXY.UI_Terms.save' | sxyTranslate }}\r\n      <i class=\"fa\" ng-class=\"$ctrl.data.$parent.progress ? 'fa-refresh fa-spin fa-fw' : 'fa-upload'\"></i>\r\n    </span>\r\n  </button>\r\n  <button ng-click=\"$ctrl.data.$parent.clearLastResult();$ctrl.goPrevious()\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/invoices/company-invoice-dialog.html\",`<div class=\"modal-invoice-group-dialog\" ng-controller=\"InvoiceToolsController as $invoiceTools\" ng-init=\"$invoiceTools.setFileTypes(['pdfFile'])\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentInformation\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <h2 class=\"visible-print-block\" sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentInformation\"></h2>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentReceiver\"></legend>\r\n          <salaxy-avatar avatar=\"$ctrl.current.otherPartyInfo.avatar\" class=\"pull-left\" style=\"font-size: 64px; border-bottom: 32px; margin-right:15px;\"></salaxy-avatar>\r\n          <div><strong>{{ $ctrl.current.otherPartyInfo.avatar.displayName }}</strong></div>\r\n          <div>{{ $ctrl.current.otherPartyInfo.officialId }}</div>\r\n          <div ng-if=\"$ctrl.current.otherPartyInfo.ibanNumber\">{{ $ctrl.current.otherPartyInfo.ibanNumber | sxyIban }}</div>\r\n          <div ng-if=\"!$ctrl.current.otherPartyInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.InvoiceDialog.noIban\"></div>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.InvoiceDialog.payer\"></legend>\r\n          <salaxy-avatar avatar=\"$ctrl.current.ownerInfo.avatar\" class=\"pull-left\" style=\"font-size: 64px; border-bottom: 32px; margin-right:15px;\"></salaxy-avatar>\r\n          <div><strong>{{ $ctrl.current.ownerInfo.avatar.displayName }}</strong></div>\r\n          <div>{{ $ctrl.current.ownerInfo.officialId }}</div>\r\n          <div ng-if=\"$ctrl.current.ownerInfo.ibanNumber\">{{ $ctrl.current.ownerInfo.ibanNumber | sxyIban }}</div>\r\n          <div ng-if=\"!$ctrl.current.ownerInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.InvoiceDialog.noIban\"></div>\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"col-sm-6 form-horizontal\">\r\n        <fieldset>\r\n          <legend>\r\n            {{\"SALAXY.NG1.InvoiceDialog.invoiceStatus\" | sxyTranslate}}: {{ \"InvoiceStatus.\" + $ctrl.current.status | sxyEnum }}\r\n          </legend>\r\n            <button ng-if=\"$ctrl.logic.parent.showMarkAsPaidButton($ctrl.current)\" class=\"btn btn-primary\" ng-click=\"$ctrl.logic.parent.updateInvoiceStatus($ctrl.current,'paid')\">\r\n              <i class=\"fa fa-check visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.InvoicesCompany.setAsPaid\"></span>\r\n            </button> \r\n            <button class=\"btn btn-danger\" ng-if=\"$ctrl.logic.parent.showMarkAsCanceledButton($ctrl.current)\" ng-click=\"$ctrl.logic.parent.updateInvoiceStatus($ctrl.current,'canceled')\">\r\n              <i class=\"fa fa-times visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.InvoicesCompany.cancelPayment\"></span>\r\n            </button>\r\n            <p ng-if=\"$ctrl.logic.parent.showIrCancelInfoText($ctrl.current)\" class=\"text-center\" sxy-text=\"SALAXY.NG1.InvoicesCompany.cancelInfoText\"></p>\r\n        </fieldset>\r\n        <div class=\"pull-right\" style=\"width: 160px\" ng-if=\"$ctrl.current.status != 'paid' && $ctrl.current.status != 'canceled' && $ctrl.logic.parent.getQrCode($ctrl.current) !== 'loading' && $ctrl.logic.parent.getQrCode($ctrl.current) !== 'error'\">\r\n          <div height=\"160px\" ng-bind-html=\"$ctrl.logic.parent.getQrCode($ctrl.current)\" ></div>\r\n        </div>\r\n        <div ng-if=\"$ctrl.current.data.totalPaid && $ctrl.current.data.totalPaid != $ctrl.current.payment\">\r\n          \r\n            <h4 style=\"text-decoration: line-through;\">{{'SALAXY.NG1.InvoicesCompany.sum' | sxyTranslate}} {{ $ctrl.current.payment | currency }}</h4>\r\n            <h4>{{'SALAXY.NG1.InvoicesCompany.alreadyPaid' | sxyTranslate}} {{ $ctrl.current.data.totalPaid | currency }}</h4>\r\n            <h4 class=\"total\" style=\"font-weight: bold;\">{{'SALAXY.NG1.InvoicesCompany.payable' | sxyTranslate}} {{ ($ctrl.current.payment - $ctrl.current.data.totalPaid) | currency }}</h4>\r\n          \r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div ng-switch=\"$ctrl.current.status\">\r\n      <div class=\"alert alert-info\" ng-switch-when=\"paid|paymentStarted|read\" ng-switch-when-separator=\"|\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.paidPaymentStartedRead.html\"></div>\r\n      <div class=\"alert alert-info\" ng-switch-when=\"canceled\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.canceled.html\"></div>\r\n      <div class=\"alert alert-danger\" ng-switch-when=\"preview\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.preview.html\"></div>\r\n    </div>\r\n    <div class=\"table-responsive\" ng-if=\"$ctrl.current.status !== 'canceled'\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.receiver\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.receiverIban\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.reference\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.message\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.amount\" class=\"right\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.dueDate\" class=\"right\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.barcode\" class=\"hidden-print\"></th>\r\n            <th class=\"hidden-print\">PDF</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td>{{ $ctrl.current.otherPartyInfo.avatar.displayName }}</td>\r\n            <td>{{ $ctrl.current.otherPartyInfo.ibanNumber }}</td>\r\n            <td>{{ $ctrl.current.entityType == 'net' ? '' : $ctrl.current.reference }}</td>\r\n            <td>{{ (\"SALAXY.ENUM.InvoiceType.\" + $ctrl.current.entityType + \".label\") | sxyTranslate }}</td>\r\n            <td class=\"right\">{{ $ctrl.logic.parent.getInvoicePayment($ctrl.current) | currency }}</td>\r\n            <td class=\"right\">{{ $ctrl.current.data.dueDate | sxyDate }}</td>\r\n            <td class=\"hidden-print\">\r\n              <a type=\"button\" class=\"btn btn-default btn-block\" ng-href=\"{{$ctrl.logic.parent.getPdfUrl($ctrl.current)}}\"><i class=\"fa fa-file-pdf-o text-danger\" title=\"Lataa PDF\"></i> pdf</a>\r\n            </td>\r\n          </tr>\r\n          <tr>\r\n            <td colspan=\"6\" class=\"text-right\" style=\"border-top: 0;padding: 0px;\">\r\n              <div ng-init=\"$ctrl.current.barcode = $ctrl.logic.parent.getBarcodeValue($ctrl.current)\" ng-bind-html=\"$ctrl.logic.parent.getBarcode($ctrl.current)\"></div>\r\n            </td>\r\n            <td class=\"hidden-print\" style=\"border-top: 0;padding: 0px 8px;\">\r\n              <button type=\"button\" class=\"btn btn-default btn-block\" ng-click=\"$ctrl.logic.parent.copyBarcode($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyToClipboard\"></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/invoices/company-invoices-date-filter-dialog.html\",`\r\n<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.InvoicesCompany.dateFilterDialogHeading\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n<form name=\"dateFilterForm\" class=\"form-horizontal\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-12\">\r\n      <salaxy-datepicker-popup label=\"SALAXY.NG1.InvoicesCompany.dateFilterDialogStart\" name=\"startDate\" ng-model=\"$ctrl.logic.startDate\"></salaxy-datepicker-popup>\r\n      <salaxy-datepicker-popup label=\"SALAXY.NG1.InvoicesCompany.dateFilterDialogEnd\" name=\"endDate\" ng-model=\"$ctrl.logic.endDate\"></salaxy-datepicker-popup>\r\n    </div>\r\n  </div>\r\n</form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/invoices/invoice-dialog.html\",`<div class=\"modal-invoice-group-dialog\" ng-controller=\"InvoiceToolsController as $invoiceTools\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentInformation\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <h2 class=\"visible-print-block\" sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentInformation\"></h2>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.InvoiceDialog.paymentReceiver\"></legend>\r\n          <salaxy-avatar avatar=\"$ctrl.current.otherPartyInfo.avatar\" class=\"pull-left\" style=\"font-size: 64px; border-bottom: 32px; margin-right:15px;\"></salaxy-avatar>\r\n          <div><strong>{{ $ctrl.current.otherPartyInfo.avatar.displayName }}</strong></div>\r\n          <div>{{ $ctrl.current.otherPartyInfo.officialId }}</div>\r\n          <div ng-if=\"$ctrl.current.otherPartyInfo.ibanNumber\">{{ $ctrl.current.otherPartyInfo.ibanNumber | sxyIban }}</div>\r\n          <div ng-if=\"!$ctrl.current.otherPartyInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.InvoiceDialog.noIban\"></div>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend>Maksaja</legend>\r\n          <salaxy-avatar avatar=\"$ctrl.current.ownerInfo.avatar\" class=\"pull-left\" style=\"font-size: 64px; border-bottom: 32px; margin-right:15px;\"></salaxy-avatar>\r\n          <div><strong>{{ $ctrl.current.ownerInfo.avatar.displayName }}</strong></div>\r\n          <div>{{ $ctrl.current.ownerInfo.officialId }}</div>\r\n          <div ng-if=\"$ctrl.current.ownerInfo.ibanNumber\">{{ $ctrl.current.ownerInfo.ibanNumber | sxyIban }}</div>\r\n          <div ng-if=\"!$ctrl.current.ownerInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.InvoiceDialog.noIban\"></div>\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"col-sm-6 form-horizontal\">\r\n        <fieldset>\r\n          <legend>{{\"SALAXY.NG1.InvoiceDialog.invoiceStatus\" | sxyTranslate}}: {{ \"InvoiceStatus.\" + $ctrl.current.status | sxyEnum }}</legend>\r\n          <salaxy-form-group name=\"paymentChannel\" label=\"{{'SALAXY.NG1.InvoiceDialog.paymentChannel' | sxyTranslate}}\">\r\n            <div style=\"height:100%\">\r\n              <div style=\"display: inline-block;vertical-align: middle;\">\r\n                <salaxy-avatar style=\"font-size: 2.8em\" avatar=\"$ctrl.logic.parent.getChannelAvatar($ctrl.current.data.channel)\"></salaxy-avatar>\r\n              </div>\r\n              <div style=\"display: inline-block;vertical-align: middle;\">{{ $ctrl.logic.parent.getChannelAvatar($ctrl.current.data.channel).displayName }}</div>\r\n            </div>\r\n          </salaxy-form-group>\r\n          <div class=\"hidden-print\" ng-init=\"$ctrl.logic.newStatus = $ctrl.current.status\">\r\n            <salaxy-input-enum label=\"{{'SALAXY.NG1.InvoiceDialog.changeStatus' | sxyTranslate}}\" name=\"requestedStatus\" options=\"{'unread': ('SALAXY.ENUM.InvoiceStatus.unread.label' | sxyTranslate),'read': ('SALAXY.ENUM.InvoiceStatus.read.label' | sxyTranslate),'waitingConfirmation': ('SALAXY.ENUM.InvoiceStatus.waitingConfirmation.label' | sxyTranslate),'paid': ('SALAXY.ENUM.InvoiceStatus.paid.label' | sxyTranslate),'canceled': ('SALAXY.ENUM.InvoiceStatus.canceled.label' | sxyTranslate)}\" ng-model=\"$ctrl.logic.newStatus\" enum=\"InvoiceStatus\">\r\n            </salaxy-input-enum>\r\n            <salaxy-form-group name=\"statusButton\" label-type=\"empty-label\">\r\n              <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.logic.parent.updateInvoiceGroupItemStatus($ctrl.current,$ctrl.logic.newStatus)\" sxy-text=\"SALAXY.NG1.InvoiceDialog.change\"></button>\r\n            </salaxy-form-group>\r\n\r\n            <salaxy-input-enum name=\"fileType\" label=\"{{'SALAXY.NG1.InvoiceDialog.downloadInvoice' | sxyTranslate}}\" ng-model=\"$invoiceTools.fileTypeId\" options=\"$invoiceTools.fileTypeOptions\" remember=\"invoice\"></salaxy-input-enum>\r\n\r\n            <salaxy-form-group name=\"exportButton\" label-type=\"empty-label\">\r\n              <button type=\"button\" class=\"btn btn-default pull-right\" ng-disabled=\"!$invoiceTools.fileTypeId\" ng-click=\"$invoiceTools.export($ctrl.logic.parent.getGroupItemDataReader($ctrl.current,null),false)\" sxy-text=\"SALAXY.NG1.InvoiceDialog.download\"></button>\r\n            </salaxy-form-group>\r\n          </div>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n    <div ng-switch=\"$ctrl.current.status\">\r\n      <div class=\"alert alert-info\" ng-switch-when=\"paid|paymentStarted|read\" ng-switch-when-separator=\"|\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.paidPaymentStartedRead.html\"></div>\r\n      <div class=\"alert alert-info\" ng-switch-when=\"canceled\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.canceled.html\"></div>\r\n      <div class=\"alert alert-danger\" ng-switch-when=\"forecast\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.forecast.html\"></div>\r\n      <div class=\"alert alert-danger\" ng-switch-when=\"preview\" sxy-html=\"SALAXY.NG1.InvoiceDialog.statuses.preview.html\"></div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.receiver\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.receiverIban\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.reference\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.message\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.amount\" class=\"right\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.dueDate\" class=\"right\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.InvoiceDialog.table.barcode\" class=\"hidden-print\"></th>\r\n            <th class=\"hidden-print\">PDF</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td>{{ $ctrl.current.otherPartyInfo.avatar.displayName }}</td>\r\n            <td ng-if=\"$ctrl.logic.parent.hideBarCode($ctrl.current)\">{{ 'SALAXY.REPORTS.invoice.heading.preview' | sxyTranslate }}</td>\r\n            <td ng-if=\"!$ctrl.logic.parent.hideBarCode($ctrl.current)\">{{ $ctrl.current.otherPartyInfo.ibanNumber }}</td>\r\n            <td>{{ $ctrl.current.reference }}</td>\r\n            <td>{{ (\"SALAXY.ENUM.InvoiceType.\" + $ctrl.current.entityType + \".label\") | sxyTranslate }}</td>\r\n            <td class=\"right\">{{ $ctrl.current.payment | currency }}</td>\r\n            <td class=\"right\">{{ $ctrl.current.data.dueDate | sxyDate }}</td>\r\n            <td class=\"hidden-print\">\r\n              <a type=\"button\" class=\"btn btn-default btn-block\" ng-href=\"{{$ctrl.logic.parent.getPdfUrl($ctrl.current)}}\"><i class=\"fa fa-file-pdf-o text-danger\" title=\"Lataa PDF\"></i> pdf</a>\r\n            </td>\r\n          </tr>\r\n          <tr ng-if=\"!$ctrl.logic.parent.hideBarCode($ctrl.current)\">\r\n            <td colspan=\"1\" style=\"border-top: 0;padding: 0px;\">\r\n              <div class=\"text-right\"  ng-if=\"$ctrl.logic.parent.getQrCode($ctrl.current) !== 'loading' && $ctrl.logic.parent.getQrCode($ctrl.current) !== 'error'\">\r\n                <div ng-bind-html=\"$ctrl.logic.parent.getQrCode($ctrl.current)\" ></div>\r\n              </div>\r\n            </td>\r\n            <td colspan=\"5\" style=\"border-top: 0;padding: 0px;\" class=\"text-right\">\r\n              <span style=\"font-family: 'Courier New', Courier, monospace; font-size: 1.3em;\">{{$ctrl.logic.parent.getBarcodeValue($ctrl.current)}}</span>\r\n            </td>\r\n            <td class=\"hidden-print\" style=\"border-top: 0;padding: 0px 8px;\">\r\n              <button type=\"button\" class=\"btn btn-default btn-block\" ng-click=\"$ctrl.logic.parent.copyBarcode($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyToClipboard\"></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default pull-left\" onClick=\"window.print()\" sxy-text=\"SALAXY.UI_Terms.print\"></button>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/invoices/invoice-group-dialog.html\",`<div class=\"modal-invoice-group-dialog\" ng-controller=\"InvoiceToolsController as $invoiceTools\" ng-init=\"($ctrl.current.invoices[0].data.channel == 'palkkausInvoices' || $ctrl.current.invoices[0].data.channel == 'kitsas') ? $invoiceTools.setFileTypes(['pdfFile']) : null\">\r\n  <style>\r\n    @media print {\r\n      #launcher {\r\n        display: none;\r\n      }\r\n      @page {\r\n        margin-bottom: 20mm;\r\n      }\r\n    }\r\n  </style>\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">Maksuaineiston tiedot</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <h2 class=\"visible-print-block\">Maksuaineiston tiedot</h2>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <fieldset>\r\n          <legend>Maksaja</legend>\r\n          <salaxy-avatar avatar=\"$ctrl.current.ownerInfo.avatar\" class=\"pull-left\" style=\"font-size: 64px; border-bottom: 32px; margin-right:15px;\"></salaxy-avatar>\r\n          <div><strong>{{ $ctrl.current.ownerInfo.avatar.displayName }}</strong></div>\r\n          <div>{{ $ctrl.current.ownerInfo.officialId }}</div>\r\n          <div ng-if=\"$ctrl.current.ownerInfo.ibanNumber\">{{ $ctrl.current.ownerInfo.ibanNumber | sxyIban }}</div>\r\n          <div ng-if=\"!$ctrl.current.ownerInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.WorkerInfo.noIbanNumber\"></div>\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"col-sm-6 form-horizontal\">\r\n        <fieldset>\r\n          <legend>Aineiston tila: {{ \"InvoiceStatus.\" + $ctrl.current.status | sxyEnum }}</legend>\r\n          <salaxy-form-group name=\"paymentChannel\" label=\"Maksukanava\">\r\n            <div style=\"height:100%\">\r\n              <div style=\"display: inline-block;vertical-align: middle;\">\r\n                <salaxy-avatar style=\"font-size: 2.8em\" avatar=\"$ctrl.logic.parent.getChannelAvatar($ctrl.current.invoices[0].data.channel)\"></salaxy-avatar>\r\n              </div>\r\n              <div style=\"display: inline-block;vertical-align: middle;\">{{ $ctrl.logic.parent.getChannelAvatar($ctrl.current.invoices[0].data.channel).displayName }}</div>\r\n            </div>\r\n          </salaxy-form-group>\r\n          <div class=\"hidden-print\" ng-init=\"$ctrl.logic.newStatus = $ctrl.current.status\">\r\n            <salaxy-input-enum label=\"Vaihda tilaa\" name=\"requestedStatus\" hidden-options=\"undefined,forecast,preview,waitingPalkkaus\" ng-model=\"$ctrl.logic.newStatus\" enum=\"InvoiceStatus\">\r\n            </salaxy-input-enum>\r\n            <salaxy-form-group name=\"statusButton\" label-type=\"empty-label\">\r\n              <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.logic.parent.updateInvoiceGroupStatus($ctrl.current,$ctrl.logic.newStatus)\">Vaihda</button>\r\n            </salaxy-form-group>\r\n\r\n            <salaxy-input-enum name=\"fileType\" label=\"Lataa aineisto\" ng-model=\"$invoiceTools.fileTypeId\" options=\"$invoiceTools.fileTypeOptions\" remember=\"invoice\"></salaxy-input-enum>\r\n\r\n            <salaxy-form-group name=\"exportButton\" label-type=\"empty-label\">\r\n              <button type=\"button\" class=\"btn btn-default pull-right\" ng-disabled=\"!$invoiceTools.fileTypeId\" ng-click=\"$invoiceTools.export($ctrl.logic.parent.getGroupDataReader($ctrl.current,null),false)\">Lataa</button>\r\n            </salaxy-form-group>\r\n          </div>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n    <div ng-switch=\"$ctrl.current.status\">\r\n      <div class=\"alert alert-info\" ng-switch-when=\"paid|paymentStarted\" ng-switch-when-separator=\"|\">\r\n        <strong>HUOM</strong>: Aineisto on jo merkitty maksetuksi!<br /> Jos maksat tai lähetät aineiston / maksun uudelleen, varmistathan, ettei maksua makseta kahteen kertaan.\r\n      </div>\r\n      <div class=\"alert alert-info\" ng-switch-when=\"read\">\r\n        <strong>HUOM</strong>: Aineisto on jo merkitty lähetetyksi.<br /> Jos maksat tai lähetät aineiston / maksun uudelleen, varmistathan, ettei maksua makseta kahteen kertaan.\r\n      </div>\r\n      <div class=\"alert alert-info\" ng-switch-when=\"canceled\">\r\n        Aineisto maksut on merkitty perutuksi.<br />\r\n      </div>\r\n      <div class=\"alert alert-info\" ng-switch-when=\"canceled\">\r\n        Aineiston edellisessä maksussa on tapahtunut virheitä.<br />\r\n      </div>\r\n      <div class=\"alert alert-danger\" ng-switch-when=\"forecast\">\r\n        <strong>HUOM</strong>: Aineisto on <strong>Arvio</strong> (forecast).<br /> Tyypillisesti nämä ainestot ovat vain kassavirran suunnittelua varten. Niitä ei ole tarkoitus maksaa, vaan lopullinen lasku tulee laskuttajalta (esim. Työllisyysrahasto).\r\n      </div>\r\n      <div class=\"alert alert-danger\" ng-switch-when=\"preview\">\r\n        <strong>HUOM</strong>: Aineisto on <strong>Esikatselu</strong>-tilassa.<br /> Aineistoon (esim. ennakonpidätys) voi olla vielä tulossa muutoksia. Jos maksat aineiston, varmistathan ettei aineistoon tule enää muutoksia (esim. lisää palkkoja samassa\r\n        kuussa).\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th>Saajan nimi</th>\r\n            <th>Saajan IBAN</th>\r\n            <th>Viite</th>\r\n            <th>Viesti</th>\r\n            <th class=\"right\">Summa</th>\r\n            <th class=\"right\">Eräpäivä</th>\r\n            <th class=\"hidden-print\"></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat-start=\"invoice in $ctrl.current.invoices\">\r\n            <td>{{ invoice.otherPartyInfo.avatar.displayName }}</td>\r\n            <td>{{ invoice.otherPartyInfo.ibanNumber }}</td>\r\n            <td>{{ invoice.reference }}</td>\r\n            <td>{{ (\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate }}</td>\r\n            <td class=\"right\">{{ invoice.payment | currency }}</td>\r\n            <td class=\"right\">{{ invoice.data.dueDate | sxyDate }}</td>\r\n            <td class=\"hidden-print\"><a type=\"button\" class=\"btn btn-default btn-block\" ng-href=\"{{$ctrl.logic.parent.getPdfUrl(invoice)}}\"><i class=\"fa fa-file-pdf-o text-danger\" title=\"Lataa PDF\"></i> pdf</a></td>\r\n          </tr>\r\n          <tr ng-repeat-end>\r\n            <td colspan=\"1\" style=\"border-top: 0;padding: 0px;\">\r\n              <div class=\"text-right\"  ng-if=\"$ctrl.logic.parent.getQrCode(invoice) !== 'loading' && $ctrl.logic.parent.getQrCode(invoice) !== 'error'\">\r\n                <div ng-bind-html=\"$ctrl.logic.parent.getQrCode(invoice)\" ></div>\r\n              </div>\r\n            </td>\r\n            <td colspan=\"5\" style=\"border-top: 0;padding: 0px;\" class=\"text-right\">\r\n              <span style=\"font-family: 'Courier New', Courier, monospace; font-size: 1.3em;\">{{$ctrl.logic.parent.getBarcodeValue(invoice)}}</span>\r\n            </td>\r\n            <td class=\"hidden-print\" style=\"border-top: 0;padding: 0px 8px;\">\r\n              <button type=\"button\" class=\"btn btn-default btn-block\" ng-click=\"$ctrl.logic.parent.copyBarcode(invoice)\">Kopioi</button>\r\n            </td>\r\n          </tr>\r\n          <tr>\r\n            <td></td>\r\n            <td></td>\r\n            <td></td>\r\n            <td></td>\r\n            <td class=\"right\">{{ $ctrl.logic.parent.sumInvoicePayments($ctrl.current.invoices) | currency }}</td>\r\n            <td></td>\r\n            <td></td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" class=\"btn btn-default pull-left\" onClick=\"window.print()\" sxy-text=\"SALAXY.UI_Terms.print\"></button>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\">OK</button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/Beneficiary-info.html\",`<form name=\"currentForm\" class=\"form-horizontal\" model=\"temp\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}</h2>\r\n    <p class=\"intro\" ng-if=\"$ctrl.currentStep.intro != ''\">{{ $ctrl.currentStep.intro }}</p>\r\n  </div>\r\n\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.beneficiaryInfo.wizard.label\"></legend>\r\n    <div class=\"row\" ng-repeat=\"item in $ctrl.current.company.beneficiaries\">\r\n\r\n      <div class=\"col-sm-6\">\r\n        <salaxy-input ng-model=\"item.avatar.displayName\" name=\"beneficiaryName{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.common.name\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-3\">\r\n        <salaxy-input ng-model=\"item.officialId\" name=\"beneficiaryPersonalId{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.common.ssNumber\" sxy-personal-id-fi label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-3\">\r\n        <salaxy-input ng-model=\"item.nationality\" name=\"beneficiaryNationality{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.common.nationality\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-xs-12 text-right\">\r\n        <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.company.beneficiaries.splice($index,1)\"><i class=\"fa fa-trash\"></i> <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n      </div>\r\n      <div class=\"col-xs-12\">\r\n        <hr>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.company.beneficiaries.push({ avatar: {}})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i> {{'SALAXY.NG1.InsuranceComponent.beneficiaryInfo.beneficiariesAdd' | sxyTranslate}}</button>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/buttons-default.html\",`<div class=\"col-xs-6 col-sm-4 text-left\">\r\n  <button ng-click=\"$ctrl.goPrevious()\" class=\"btn btn-sm btn-link navi-link\"><i class=\"fa fa-angle-left\"></i> {{'SALAXY.UI_Terms.previous' | sxyTranslate}}</button>\r\n</div>\r\n<div class=\"col-sm-4 hidden-xs text-center txt-index\">\r\n  <div>{{$ctrl.currentStep.number-1}}/{{$ctrl.steps.length-1}}</div>\r\n</div>\r\n<div class=\"col-xs-6 col-sm-4 text-right\">\r\n\r\n  <button ng-click=\"$ctrl.goNext()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn btn-sm btn-link navi-link\">{{'SALAXY.UI_Terms.next' | sxyTranslate}} <i class=\"fa fa-angle-right\"></i></button>\r\n  <!--button ng-click=\"$ctrl.goNext()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn-link navi-link\">Seuraava <i class=\"fa fa-angle-right\"></i></button-->\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/buttons-send.html\",`<div class=\"col-xs-6 col-sm-4 text-left\">\r\n  <button ng-click=\"$ctrl.goPrevious()\" class=\"btn btn-sm btn-link navi-link\"><i class=\"fa fa-angle-left\"></i> {{'SALAXY.UI_Terms.previous' | sxyTranslate}}</button>\r\n</div>\r\n<div class=\"col-sm-4 hidden-xs text-center txt-index\">\r\n  <div>{{$ctrl.currentStep.number-1}}/{{$ctrl.steps.length-1}}</div>\r\n\r\n</div>\r\n<div class=\"col-xs-6 col-sm-4 text-right\">\r\n\r\n  <span>\r\n    <button ng-click=\"$ctrl.send()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn btn-sm btn-primary\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n  </span>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/ContactInfo-entrepreneur.html\",`<form name=\"currentForm\" class=\"form-horizontal\" ng-model=\"temp\">\r\n\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n    </h2>\r\n\r\n  </div>\r\n\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.common.insuranceContactPerson\"></legend>\r\n    <div class=\"content row\">\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.avatar.displayName\" name=\"contactName\" label=\"SALAXY.NG1.InsuranceComponent.common.name\" required label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.officialId\" name=\"contactSSNumber\" label=\"SALAXY.NG1.InsuranceComponent.common.ssNumber\" required sxy-personal-id-fi label-type=\"basic\"></salaxy-input>\r\n\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.telephone\" name=\"contactTelephone\" label=\"SALAXY.NG1.InsuranceComponent.common.telephone\" required sxy-mobile-phone label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.email\" name=\"contactEmail\" label=\"SALAXY.NG1.InsuranceComponent.common.email\" required sxy-email label-type=\"basic\"> </salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input-enum type=\"select\" ng-model=\"$ctrl.current.company.contactPerson.authorizationType\" options=\"{procuration: ('SALAXY.NG1.InsuranceComponent.enums.procurationEnum' | sxyTranslate), powerOfAttorney: ('SALAXY.NG1.InsuranceComponent.enums.powerOfAttorneyEnum' | sxyTranslate), apparentAuthority: ('SALAXY.NG1.InsuranceComponent.enums.apparentAuthorityEnum' | sxyTranslate), other: ('SALAXY.NG1.InsuranceComponent.enums.otherEnum' | sxyTranslate)}\"\r\n          name=\"DelegateType\" enum=\"DelegateType\" label=\"SALAXY.NG1.InsuranceComponent.enums.authorizationTypeLabel\" required label-type=\"basic\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n  <fieldset>\r\n    <legend sxy-html=\"SALAXY.NG1.InsuranceComponent.principalBusinessAddress.label.html\"></legend>\r\n    <button class=\"btn btn-xs btn-secondary\" ng-click=\"$ctrl.current.company.hasPrincipalBusinessAddress = !$ctrl.current.company.hasPrincipalBusinessAddress\"><i class=\"fa\" style=\"margin-right:5px\" ng-class=\"!$ctrl.current.company.hasPrincipalBusinessAddress ? 'fa-plus' : 'fa-times'\"></i> <span ng-if=\"!$ctrl.current.company.hasPrincipalBusinessAddress\" sxy-text=\"SALAXY.NG1.InsuranceComponent.common.addAddressBtn\"></span><span ng-if=\"$ctrl.current.company.hasPrincipalBusinessAddress\" sxy-text=\"SALAXY.UI_Terms.cancelAlt\">Peru</span></button>\r\n\r\n    <div class=\"content row\" ng-if=\"$ctrl.current.company.hasPrincipalBusinessAddress\">\r\n      <div class=\"col-sm-12\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.street\" name=\"streetAddress\" label=\"SALAXY.NG1.InsuranceComponent.common.streetAddress\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.postalCode\" name=\"postalCode\" label=\"SALAXY.NG1.InsuranceComponent.common.postalCode\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.city\" name=\"city\" label=\"SALAXY.NG1.InsuranceComponent.common.city\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input-enum enum=\"CountryCode\" type=\"typeahead\" options=\"$ctrl.countryCodes\" ng-model=\"$ctrl.current.company.principalBusinessAddress.countryCode\" name=\"country\" label=\"SALAXY.NG1.InsuranceComponent.common.country\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/ContactInfo.html\",`<form name=\"currentForm\" class=\"form-horizontal\" ng-model=\"temp\">\r\n\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n    </h2>\r\n    <p class=\"intro\">\r\n      <span ng-if=\"$ctrl.action == 'moveInsurance'\" sxy-text=\"SALAXY.NG1.InsuranceComponent.contactInfo.moveInsuranceInfo\"></span>\r\n    </p>\r\n  </div>\r\n\r\n\r\n  <div class=\"content row\">\r\n    <div class=\"col-xs-12 col-sm-6\">\r\n      <fieldset>\r\n        <legend>Yrityksen tiedot</legend>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.details.avatar.displayName\" name=\"companyName\" label=\"SALAXY.NG1.InsuranceComponent.common.companyName\" readonly=\"true\" label-type=\"basic\"> </salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.details.officialId\" name=\"vatNumber\" label=\"SALAXY.NG1.InsuranceComponent.common.vatNumber\" readonly=\"true\" label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.address.street\" name=\"streetAddress\" label=\"SALAXY.NG1.InsuranceComponent.common.streetAddress\" readonly=\"true\" label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.address.postalCode\" name=\"postalCode\" label=\"SALAXY.NG1.InsuranceComponent.common.postalCode\" readonly=\"true\" label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.address.city\" name=\"city\" label=\"SALAXY.NG1.InsuranceComponent.common.city\" readonly=\"true\" label-type=\"basic\"></salaxy-input>\r\n      </fieldset>\r\n      <fieldset>\r\n        <legend sxy-html=\"SALAXY.NG1.InsuranceComponent.principalBusinessAddress.label.html\"></legend>\r\n        <button class=\"btn btn-xs btn-secondary\" ng-click=\"$ctrl.current.company.hasPrincipalBusinessAddress = !$ctrl.current.company.hasPrincipalBusinessAddress\"><i class=\"fa\" style=\"margin-right:5px\" ng-class=\"!$ctrl.current.company.hasPrincipalBusinessAddress ? 'fa-plus' : 'fa-times'\"></i> <span ng-if=\"!$ctrl.current.company.hasPrincipalBusinessAddress\" sxy-text=\"SALAXY.NG1.InsuranceComponent.common.addAddressBtn\"></span><span ng-if=\"$ctrl.current.company.hasPrincipalBusinessAddress\"  sxy-text=\"SALAXY.UI_Terms.cancelAlt\">Peru</span></button>\r\n\r\n        <div ng-if=\"$ctrl.current.company.hasPrincipalBusinessAddress\">\r\n          <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.street\" name=\"streetAddress\" label=\"SALAXY.NG1.InsuranceComponent.common.streetAddress\" label-type=\"basic\"></salaxy-input>\r\n          <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.postalCode\" name=\"postalCode\" label=\"SALAXY.NG1.InsuranceComponent.common.postalCode\" label-type=\"basic\"></salaxy-input>\r\n          <salaxy-input ng-model=\"$ctrl.current.company.principalBusinessAddress.city\" name=\"city\" label=\"SALAXY.NG1.InsuranceComponent.common.city\" label-type=\"basic\"></salaxy-input>\r\n          <salaxy-input-enum enum=\"CountryCode\" type=\"typeahead\" options=\"$ctrl.countryCodes\" ng-model=\"$ctrl.current.company.principalBusinessAddress.countryCode\" name=\"country\" label=\"SALAXY.NG1.InsuranceComponent.common.country\" label-type=\"basic\"></salaxy-input>\r\n\r\n        </div>\r\n      </fieldset>\r\n\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.common.insuranceContactPerson\"></legend>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.avatar.displayName\" name=\"contactName\" label=\"SALAXY.NG1.InsuranceComponent.common.name\" required label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.officialId\" name=\"contactSSNumber\" label=\"SALAXY.NG1.InsuranceComponent.common.ssNumber\" required sxy-personal-id-fi label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.telephone\" name=\"contactTelephone\" label=\"SALAXY.NG1.InsuranceComponent.common.telephone\" required sxy-mobile-phone label-type=\"basic\"></salaxy-input>\r\n        <salaxy-input ng-model=\"$ctrl.current.company.contactPerson.email\" name=\"contactEmail\" label=\"SALAXY.NG1.InsuranceComponent.common.email\" required sxy-email label-type=\"basic\"> </salaxy-input>\r\n        <salaxy-input-enum type=\"select\" ng-model=\"$ctrl.current.company.contactPerson.authorizationType\" options=\"{procuration: ('SALAXY.NG1.InsuranceComponent.enums.procurationEnum' | sxyTranslate), powerOfAttorney: ('SALAXY.NG1.InsuranceComponent.enums.powerOfAttorneyEnum' | sxyTranslate), apparentAuthority: ('SALAXY.NG1.InsuranceComponent.enums.apparentAuthorityEnum' | sxyTranslate), other: ('SALAXY.NG1.InsuranceComponent.enums.otherEnum' | sxyTranslate)}\"\r\n          name=\"DelegateType\" enum=\"DelegateType\" label=\"SALAXY.NG1.InsuranceComponent.common.procura\" required label-type=\"basic\"></salaxy-input-enum>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/Entrepreneur.html\",`<form name=\"currentForm\" class=\"form-horizontal\" ng-model=\"temp\">\r\n\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n      </h23>\r\n      <p class=\"intro\" ng-if=\"$ctrl.currentStep.intro != ''\">{{ $ctrl.currentStep.intro }}\r\n      </p>\r\n  </div>\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.entrepreneur.companyInfo\"></legend>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.details.avatar.displayName\" name=\"companyName\" label=\"SALAXY.NG1.InsuranceComponent.common.companyName\" readonly=\"true\" label-type=\"basic\"> </salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"$ctrl.current.company.details.officialId\" name=\"vatNumber\" label=\"SALAXY.NG1.InsuranceComponent.common.vatNumber\" readonly=\"true\" label-type=\"basic\" sxy-company-id-fi></salaxy-input>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.entrepreneur.entrepreneurInsuranceInfo\"></legend>\r\n    <div class=\"row\" ng-repeat=\"item in $ctrl.current.items\">\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input ng-model=\"item.insuredName\" name=\"entrepreneurName{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.entrepreneur.entrepreneurName\" required label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"item.insuredOfficialId\" name=\"entrepreneurSSNumber{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.common.ssNumber\" required label-type=\"basic\" sxy-personal-id-fi></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input-enum type=\"select\" ng-model=\"item.orderType\" options=\"{newEntrepreneurInsurance: ('SALAXY.NG1.InsuranceComponent.entrepreneur.newEntrepreneurInsuranceEnum' | sxyTranslate), moveEntrepreneurInsurance: ('SALAXY.NG1.InsuranceComponent.entrepreneur.moveEntrepreneurInsuranceEnum' | sxyTranslate)}\"\r\n          name=\"InsuranceOrder{{$index}}\" enum=\"InsuranceOrder\" label=\"SALAXY.NG1.InsuranceComponent.entrepreneur.insuranceLabel\" required label-type=\"basic\"></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-if=\"item.orderType == 'moveEntrepreneurInsurance'\" ng-model=\"item.oldInsuranceCompany\" label=\"SALAXY.NG1.InsuranceComponent.common.oldInsuranceCompany\" name=\"insuranceCompany{{$index}}\" label-type=\"basic\" required></salaxy-input>\r\n      </div>\r\n\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-datepicker-popup ng-if=\"item.orderType == 'newEntrepreneurInsurance'\" ng-model=\"item.startDate\" name=\"insuranceForEntrepreneurStartDate{{$index}}\" format=\"d!.M!.yyyy\" placeholder=\"pp.kk.vvvv\" label=\"SALAXY.NG1.InsuranceComponent.common.startDate\"\r\n          datepicker-options=\"$ctrl.insuranceDateOptions\" min-date=\"$ctrl.today\" label-type=\"basic\" tooltip-html=\"{{'SALAXY.NG1.InsuranceComponent.common.startDateToolTip' | sxyTranslate}}\" tooltip-placement=\"top-right\" required></salaxy-datepicker-popup>\r\n        <salaxy-input-enum ng-if=\"item.orderType == 'moveEntrepreneurInsurance'\" label=\"SALAXY.NG1.InsuranceComponent.common.startDate\" type=\"select\" options=\"$ctrl.insuranceStartingPointDateOptions\" placeholder=\"SALAXY.UI_Terms.select\" ng-model=\"item.startDate\"\r\n          name=\"insuranceMoveForEntrepreneurStartDate{{$index}}\" label-type=\"basic\" required></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input-enum label=\"SALAXY.NG1.InsuranceComponent.common.billingInterval\" options=\"{1:'1', 2:'2', 3:'3', 4:'4'}\" ng-model=\"item.billingInterval\" name=\"billing{{$index}}\" label-type=\"basic\" required></salaxy-input-enum>\r\n      </div>\r\n\r\n\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input-occupation-type name=\"occupationType{{$index}}\" ng-model=\"item.occupations[0].occupationCode\" label=\"SALAXY.NG1.InsuranceComponent.common.occupationCode\" label-type=\"basic\" required></salaxy-input-occupation-type>\r\n      </div>\r\n      <div class=\"col-sm-4 \">\r\n        <salaxy-input ng-model=\"item.occupations[0].estimatedIncome\" name=\"YELincome{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.entrepreneur.estimatedIncome\" label-type=\"basic\" required></salaxy-input>\r\n      </div>\r\n      <div class=\"col-xs-12 text-right\">\r\n        <button class=\"btn btn-sm btn-danger\" ng-click=\"$ctrl.current.items.splice($index,1)\"><i class=\"fa fa-trash\"></i> <span sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n      </div>\r\n      <div class=\"col-xs-12\">\r\n        <hr>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 \">\r\n        <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.items.push({ occupations: [{}]})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i> {{'SALAXY.NG1.InsuranceComponent.entrepreneur.addEntrepreneur' | sxyTranslate}}</button>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/InsuranceInfo-move.html\",`<form name=\"currentForm\" class=\"form-horizontal\" ng-model=\"temp\">\r\n\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\" text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n    </h2>\r\n    <p class=\"intro\" sxy-text=\"SALAXY.NG1.InsuranceComponent.insuranceMove.intro\" ps=\".\"></p>\r\n  </div>\r\n\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input-enum label=\"SALAXY.NG1.InsuranceComponent.common.startDate\" type=\"select\" options=\"$ctrl.insuranceStartingPointDateOptions\" placeholder=\"SALAXY.UI_Terms.select\" ng-model=\"$ctrl.current.items[0].startDate\" name=\"insuranceStartDate\" label-type=\"basic\"\r\n        required></salaxy-input-enum>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input-enum label=\"SALAXY.NG1.InsuranceComponent.common.billingInterval\" options=\"{1:'1', 2:'2', 3:'3', 4:'4'}\" ng-model=\"$ctrl.current.items[0].billingInterval\" name=\"billing\" label-type=\"basic\" required></salaxy-input-enum>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input ng-model=\"$ctrl.current.items[0].oldInsuranceCompany\" label=\"SALAXY.NG1.InsuranceComponent.common.oldInsuranceCompany\" name=\"insuranceCompany\" label-type=\"basic\" required></salaxy-input>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input ng-model=\"$ctrl.current.items[0].industry\" name=\"industry\" label=\"SALAXY.NG1.InsuranceComponent.common.industry.label\" label-type=\"basic\" required tooltip-html=\"{{'SALAXY.NG1.InsuranceComponent.common.industry.html' | sxyTranslate}}\" tooltip-placement=\"top-right\"></salaxy-input>\r\n\r\n    </div>\r\n  </div>\r\n  <div class=\"row\" ng-repeat=\"item in $ctrl.current.items[0].occupations\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input-occupation-type name=\"occupationType\" ng-model=\"item.occupationCode\" label=\"SALAXY.NG1.InsuranceComponent.common.occupationCode\" label-type=\"basic\" required></salaxy-input-occupation-type>\r\n    </div>\r\n    <div class=\"col-sm-4 col-xs-9\">\r\n      <salaxy-input ng-model=\"item.estimatedIncome\" name=\"salary\" label=\"SALAXY.NG1.InsuranceComponent.common.salaryLabel\" sxy-currency label-type=\"basic\" required></salaxy-input>\r\n    </div>\r\n    <div class=\"col-sm-2 col-xs-3 text-right delete-row-col\">\r\n      <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.items[0].occupations.splice($index,1)\"><i class=\"fa fa-trash\"></i> <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12 \">\r\n      <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.items[0].occupations.push({})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i> {{'SALAXY.NG1.InsuranceComponent.common.addOccupation' | sxyTranslate}}</button>\r\n    </div>\r\n  </div>\r\n\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/InsuranceInfo-new.html\",`<form name=\"currentForm\" class=\"form-horizontal\" model=\"temp\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n    </h2>\r\n    <p class=\"intro\" ng-if=\"$ctrl.currentStep.intro != ''\">{{ $ctrl.currentStep.intro }}</p>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-4\">\r\n      <salaxy-datepicker-popup ng-model=\"$ctrl.current.items[0].startDate\" format=\"d!.M!.yyyy\" placeholder=\"pp.kk.vvvv\" name=\"insuranceStartDate\" label=\"SALAXY.NG1.InsuranceComponent.common.startDate\" datepicker-options=\"$ctrl.insuranceDateOptions\" min-date=\"$ctrl.today\"\r\n        label-type=\"basic\" required tooltip-html=\"{{'SALAXY.NG1.InsuranceComponent.common.startDateToolTip' | sxyTranslate}}\" tooltip-placement=\"top-right\" required></salaxy-datepicker-popup>\r\n\r\n    </div>\r\n    <div class=\"col-sm-5\">\r\n      <salaxy-input-enum label=\"SALAXY.NG1.InsuranceComponent.common.billingInterval\" options=\"{1:'1', 2:'2', 3:'3', 4:'4'}\" ng-model=\"$ctrl.current.items[0].billingInterval\" name=\"billing\" label-type=\"basic\" required></salaxy-input-enum>\r\n    </div>\r\n    <div class=\"col-sm-3\">\r\n      <salaxy-input ng-model=\"$ctrl.current.items[0].industry\" name=\"industry\" label=\"SALAXY.NG1.InsuranceComponent.common.industry.label\" label-type=\"basic\" required tooltip-html=\"{{'SALAXY.NG1.InsuranceComponent.common.industry.html' | sxyTranslate}}\" tooltip-placement=\"top-right\"></salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\" ng-repeat=\"item in $ctrl.current.items[0].occupations\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input-occupation-type name=\"occupationType\" ng-model=\"item.occupationCode\" label=\"SALAXY.NG1.InsuranceComponent.common.occupationCode\" label-type=\"basic\" required></salaxy-input-occupation-type>\r\n    </div>\r\n    <div class=\"col-sm-4 col-xs-9\">\r\n      <salaxy-input ng-model=\"item.estimatedIncome\" name=\"salary\" label=\"SALAXY.NG1.InsuranceComponent.common.salaryLabel\" sxy-currency label-type=\"basic\" required></salaxy-input>\r\n    </div>\r\n    <div class=\"col-sm-2 col-xs-3 text-right delete-row-col\">\r\n      <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.items[0].occupations.splice($index,1)\"><i class=\"fa fa-trash\" ></i> <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12\">\r\n      <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.items[0].occupations.push({})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i> {{'SALAXY.NG1.InsuranceComponent.common.addOccupation' | sxyTranslate}}</button>\r\n    </div>\r\n  </div>\r\n\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/Owner-info.html\",`<form name=\"currentForm\" class=\"form-horizontal\" model=\"temp\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <div class=\"text-center intro-col\">\r\n    <h1>{{ $ctrl.currentStep.title }}</h1>\r\n    <h2 class=\"subtitle\" ng-if=\"$ctrl.currentStep.heading != ''\">{{ $ctrl.currentStep.heading }}\r\n    </h2>\r\n    <p class=\"intro\" sxy-text=\"SALAXY.NG1.InsuranceComponent.ownerInfo.intro\" ps=\".\"></p>\r\n    <p sxy-text=\"SALAXY.NG1.InsuranceComponent.ownerInfo.introInfo\" ps=\".\"></p>\r\n  </div>\r\n\r\n\r\n\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.ownerInfo.ownerInfo\"></legend>\r\n\r\n    <div class=\"row\" ng-repeat=\"item in $ctrl.current.company.owners\">\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input ng-model=\"item.avatar.displayName\" name=\"ownerName{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.ownerInfo.displayName\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4\">\r\n        <salaxy-input ng-model=\"item.officialId\" name=\"ownerPersonalId{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.ownerInfo.officialId\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-8\">\r\n        <salaxy-input ng-model=\"item.address\" name=\"ownerAddress{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.ownerInfo.address\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-sm-4 \">\r\n        <salaxy-input ng-model=\"item.percentOfShares\" name=\"ownerShare{{$index}}\" label=\"SALAXY.NG1.InsuranceComponent.ownerInfo.percentOfShares\" label-type=\"basic\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-xs-12 text-right\">\r\n        <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.company.owners.splice($index,1)\"><i class=\"fa fa-trash\"></i> {{'SALAXY.UI_Terms.delete' | sxyTranslate}}</button>\r\n      </div>\r\n      <div class=\"col-xs-12\">\r\n        <hr>\r\n      </div>\r\n\r\n    </div>\r\n\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 \">\r\n        <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.company.owners.push({ avatar: {}})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i>{{'SALAXY.NG1.InsuranceComponent.ownerInfo.addOwner' | sxyTranslate}}</button>\r\n      </div>\r\n    </div>\r\n  </fieldset>\r\n  <fieldset>\r\n    <legend sxy-text=\"SALAXY.NG1.InsuranceComponent.ownerInfo.additionalOwnerInfo\"></legend>\r\n    <salaxy-input-boolean ng-model=\"$ctrl.current.company.complexOwnerStructure\" label-type=\"no-label\" name=\"additionalOwnerInfo\" type=\"checkbox\" label-true=\"SALAXY.NG1.InsuranceComponent.ownerInfo.additionalOwnerInfoLabel\"></salaxy-input-boolean>\r\n  </fieldset>\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/Start.html\",`<div class=\"row row-video\">\r\n  <div class=\"col-sm-6\">\r\n    <h1 class=\"text-center\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.wizard.title2\">\r\n\r\n    </h1>\r\n  </div>\r\n  <div class=\"col-sm-6\" class=\"text-center\">\r\n    <div class=\"video-wrapper\">\r\n      <div class=\"videoWrapper\">\r\n        <iframe src=\"https://www.youtube.com/embed/LDuzMEsPz4o\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen></iframe>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"row\">\r\n  <div class=\"col-xs-12 spacer-bottom\">\r\n    <h2 class=\"start-subtitle text-center\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.heading\"></h2>\r\n    <p class=\"text-center\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.infoText\" ps=\".\"></p>\r\n  </div>\r\n  <div class=\"col-xs-12 col-sm-6 text-center spacer-bottom\">\r\n    <button type=\"button\" class=\"btn btn-primary btn-sm xs-margin-top\" ng-click=\"$ctrl.setInsuranceAction('newInsurance'); $ctrl.goNext()\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.newInsurance\"></button>\r\n  </div>\r\n  <div class=\"col-xs-12 col-sm-6 text-center spacer-bottom\">\r\n    <button type=\"button\" class=\"btn btn-primary btn-sm xs-margin-top\" ng-click=\"$ctrl.setInsuranceAction('moveInsurance'); $ctrl.goNext()\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.moveInsurance\"></button>\r\n  </div>\r\n  <div class=\"col-xs-12 text-center spacer-bottom\">\r\n    <button type=\"button\" class=\"btn btn-primary btn-sm xs-margin-top\" ng-click=\"$ctrl.setInsuranceAction('newInsuranceForEntrepreneur'); $ctrl.goNext()\" sxy-text=\"SALAXY.NG1.InsuranceComponent.start.newInsuranceForEntrepreneur\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/localTapiola/ThankYou.html\",`<div class=\"text-center spacer-bottom\">\r\n  <h1>\r\n    {{ $ctrl.currentStep.title }}\r\n  </h1>\r\n\r\n\r\n  <p class=\"intro\" sxy-text=\"SALAXY.NG1.InsuranceComponent.thankYou.intro\" ps=\".\"></p>\r\n\r\n  <p ng-if=\"$ctrl.action == 'newInsurance' || $ctrl.action == 'moveInsurance'\" sxy-html=\"SALAXY.NG1.InsuranceComponent.thankYou.notNewInsuranceForEntrepreneur.html\"></p>\r\n  <p ng-if=\"$ctrl.action == 'newInsuranceForEntrepreneur'\" sxy-html=\"SALAXY.NG1.InsuranceComponent.thankYou.newInsuranceForEntrepreneur.html\"></p>\r\n</div>\r\n\r\n<div class=\"row\" ng-if=\"$ctrl.action == 'newInsurance' || $ctrl.action == 'moveInsurance'\" style=\"margin-top:30px;\">\r\n  <div class=\"col-sm-6 col-xs-12 spacer-bottom text-center\">\r\n    <button class=\"btn btn-primary btn-sm\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  </div>\r\n  <div class=\"col-sm-6 spacer-bottom text-center\">\r\n    <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.setInsuranceAction('newInsuranceForEntrepreneur');  $ctrl.goNext()\" sxy-text=\"SALAXY.NG1.InsuranceComponent.thankYou.newInsuranceForEntrepreneur.text\"></button>\r\n  </div>\r\n</div>\r\n\r\n<div class=\"row\" ng-if=\"$ctrl.action == 'newInsuranceForEntrepreneur'\" style=\"margin-top:30px;\">\r\n  <div class=\"col-xs-12 col-sm-6 spacer-bottom text-center\">\r\n    <button class=\"btn btn-primary btn-sm\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  </div>\r\n  <div class=\"col-sm-6 spacer-bottom text-center\">\r\n    <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.setInsuranceAction('newInsurance'); $ctrl.goNext()\" sxy-text=\"SALAXY.NG1.InsuranceComponent.thankYou.notNewInsuranceForEntrepreneur.text\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/company-legal.html\",`﻿<form name=\"companyLegalForm\" class=\"form-horizontal\">\r\n  <!-- Updating formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = companyLegalForm.$valid && (wizard.showCompanySelection || wizard.model.signature.isProcura)}}</span>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.legalLegend\"></legend>\r\n      <h5>\r\n        <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.pep\" ps=\"*\"></span>\r\n        <i class=\"fa fa-info-circle\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.pepTitle' | sxyTranslate}}\" uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.pepPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\"\r\n          popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i>\r\n      </h5>\r\n\r\n      <salaxy-input-boolean type=\"radio\" name=\"identityPep\" label=\"\" label-type=\"plain\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" ng-model=\"wizard.model.signature.isPep\" required></salaxy-input-boolean>\r\n\r\n      <div ng-if=\"wizard.model.company.companyType != 'fiRy'\">\r\n        <h5>\r\n          <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.owner\" ps=\"*\"></span>\r\n          <i class=\"fa fa-info-circle\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.ownerTitle' | sxyTranslate}}\" uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.ownerPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\"\r\n            popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i>\r\n        </h5>\r\n        <salaxy-input-boolean type=\"radio\" name=\"Ownership.IsRequiredTracking\" label=\"\" label-type=\"plain\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" ng-model=\"wizard.model.company.ownership.isRequiredTracking\" required></salaxy-input-boolean>\r\n\r\n      </div>\r\n      <div ng-if=\"!wizard.showCompanySelection\">\r\n        <h5>\r\n          <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.procura\" ps=\"*\"></span>\r\n          <i class=\"fa fa-info-circle\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.procuraTitle' | sxyTranslate}}\" uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.procuraPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\"\r\n            popover-placement=\"top\" popover-trigger=\"'mouseenter click'\"></i>\r\n        </h5>\r\n        <salaxy-input-boolean type=\"radio\" name=\"procuraOptions\" label=\"\" label-type=\"plain\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" ng-model=\"wizard.model.signature.isProcura\" required></salaxy-input-boolean>\r\n        <br />\r\n        <div ng-if=\"!wizard.model.signature.isProcura\" class=\"alert alert-danger\">\r\n          <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.procuraText\"></p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <div ng-if=\"!wizard.model.company.ownership.isRequiredTracking\">\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.fiva\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.fivaText\"></p>\r\n      </div>\r\n      <div ng-if=\"wizard.model.company.ownership.isRequiredTracking\">\r\n        <fieldset class=\"form-horizontal\">\r\n          <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolderTitle\"></legend>\r\n          <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolderText\" ps=\":\"></p>\r\n          <salaxy-input type=\"text\" name=\"shareholder1\" label=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolder' | sxyTranslate}} 1\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" ng-model=\"wizard.model.company.ownership.shareHolders[0].name\" require=\"true\"></salaxy-input>\r\n          <salaxy-input type=\"text\" name=\"shareholder2\" label=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolder' | sxyTranslate}} 2\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" ng-model=\"wizard.model.company.ownership.shareHolders[1].name\">\r\n          </salaxy-input>\r\n          <salaxy-input type=\"text\" name=\"shareholder3\" label=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolder' | sxyTranslate}} 3\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" ng-model=\"wizard.model.company.ownership.shareHolders[2].name\">\r\n          </salaxy-input>\r\n          <salaxy-input type=\"text\" name=\"shareholder4\" label=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyLegal.shareHolder' | sxyTranslate}} 4\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" ng-model=\"wizard.model.company.ownership.shareHolders[3].name\">\r\n          </salaxy-input>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/company.html\",`﻿<form name=\"companyForm\" class=\"form-horizontal\">\r\n  <!-- Updating formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = companyForm.$valid && ( wizard.showCompanySelection || (wizard.model.company.resolvedId == (sessionCtrl.session.hasCurrentAccount ? sessionCtrl.session.currentAccount.id:null)))}}</span>\r\n  <div class=\"\">\r\n    <br />\r\n    <p>{{wizard.currentStep.intro | sxyTranslate}}</p>\r\n    <br />\r\n  </div>\r\n  <div>\r\n    <div class=\"alert alert-danger\" ng-if=\"wizard.showCompanySelection && wizard.existingCompanyAlert\">\r\n      <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.existingCompanyAlert\"></p>\r\n      <p>\r\n        <a ng-href=\"{{wizard.model.ui.successUrl}}\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.loginLink\"></a>\r\n      </p>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!wizard.showCompanySelection && ( wizard.model.company.resolvedId != (sessionCtrl.session.hasCurrentAccount ? sessionCtrl.session.currentAccount.id:null))\">\r\n    <div class=\"alert alert-danger\">\r\n      <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.existingBusinessIdAlert\" params=\"{businessId: wizard.model.company.businessId}\"></p>\r\n      <p>\r\n        <a ng-href=\"{{wizard.model.ui.successUrl}}\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.loginLink2\"></a>\r\n      </p>\r\n      <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.existingBusinessIdAlert2\"></p>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div ng-if=\"wizard.showCompanySelection\" class=\"col-md-6\">\r\n      <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyInfo\"></legend>\r\n      <salaxy-input readonly=\"true\" label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyBusinessId\" name=\"businessId\" ng-model=\"wizard.model.company.businessId\" tooltip-html=\"Tarvitset käyttäjätilin luomiseen Y-tunnuksen. Jos käytät palveluamme yhdistyksen palkanmaksuun, yhdistyksellä on oltava Y-tunnus. Yhdistys voi hakea Y-tunnuksen tekemällä perustamisilmoituksen Verohallintoon (lomakkeella Y1).\"\r\n        ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input salaxy-if-role=\"!test\" readonly=\"true\" label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyName\" name=\"name\" ng-model=\"wizard.model.company.name\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input salaxy-if-role=\"test\" label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyName\" name=\"name\" ng-model=\"wizard.model.company.name\" ng-required=\"true\"></salaxy-input>\r\n      <div class=\"form-group\" salaxy-if-role=\"!test\">\r\n        <label for=\"Yritysmuoto\" class=\"col-sm-4 control-label\" style=\"text-align:left\">\r\n          <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType\" ps=\"*\"></span>\r\n        </label>\r\n        <div class=\"col-sm-8\">\r\n          <input type=\"text\" class=\"form-control\" id=\"Yritysmuoto\" name=\"Yritysmuoto\" placeholder=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType' | sxyTranslate | lowercase}}\" readonly=\"true\" autocomplete=\"off\" value=\"{{ !wizard.model.company.companyType ? '' : ('SALAXY.ENUM.CompanyType.' + wizard.model.company.companyType +'.label' | sxyTranslate) }}\"\r\n          />\r\n        </div>\r\n      </div>\r\n      <salaxy-input-enum salaxy-if-role=\"test\" label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType\" name=\"companyType\" ng-model=\"wizard.model.company.companyType\" enum=\"CompanyType\" type=\"select\" placeholder=\"SALAXY.UI_Terms.select\" ng-required=\"true\"></salaxy-input-enum>\r\n    </div>\r\n\r\n    <div ng-if=\"!wizard.showCompanySelection\" class=\"col-md-6\">\r\n      <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyInfo\"></legend>\r\n      <div class=\"form-group\">\r\n        <label for=\"businessId\" class=\"col-sm-4 col-md-3 col-lg-4 control-label\" style=\"text-align: left\">\r\n         <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyBusinessId\" ps=\"*\"></span>\r\n          <i class=\"fa fa-info-circle\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyBusinessId' | sxyTranslate}}\"\r\n            uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.businessIdPopOver' | sxyTranslate}}\"\r\n            popover-append-to-body=\"true\" popover-placement=\"top\" popover-trigger=\"'mouseenter click'\"></i>\r\n        </label>\r\n        <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n          <div class=\"input-group\">\r\n            <input ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" type=\"text\" id=\"businessId\" class=\"form-control\" ng-model=\"wizard.model.company.businessId\" sxy-company-id-fi ng-required=\"true\">\r\n            <div class=\"input-group-btn\">\r\n              <button ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" class=\"btn btn-default form-control\" type=\"button\" ng-click=\"wizard.searchYtj('businessId')\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchTitle' | sxyTranslate}}\"\r\n                uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\" popover-placement=\"auto\" popover-trigger=\"'mouseenter'\">\r\n                <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchBtn\"></span> <span class=\"hidden-sm\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchBtn2\"></span>\r\n              </button>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n      <div class=\"form-group\">\r\n        <label for=\"name\" class=\"col-sm-4 col-md-3 col-lg-4 control-label\" style=\"text-align: left\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyName\" ps=\"*\"></label>\r\n        <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n          <div class=\"input-group\">\r\n            <input ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" type=\"text\" class=\"form-control\" id=\"name\" ng-model=\"wizard.model.company.name\" ng-required=\"true\">\r\n            <div class=\"input-group-btn\">\r\n              <button ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" class=\"btn btn-default form-control\" type=\"button\" ng-click=\"wizard.searchYtj('name')\" popover-title=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchTitle' | sxyTranslate}}\"\r\n                uib-popover=\"{{'SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\" popover-placement=\"auto\" popover-trigger=\"'mouseenter'\">\r\n                <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchBtn\"></span> <span class=\"hidden-sm\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchBtn2\"></span>\r\n              </button>\r\n            </div>\r\n          </div>\r\n\r\n        </div>\r\n      </div>\r\n      <div class=\"hidden-xs\">\r\n        <!-- HUOM! Tästä kentästä on mobiiliversio edempänä koodissa -->\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType2\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" enum=\"CompanyType\" options=\"{'fiOy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiOy' | sxyTranslate),'fiTm':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiTm' | sxyTranslate),'fiRy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiRy' | sxyTranslate),'fiYy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiYy' | sxyTranslate)}\"\r\n          name=\"companyType\" ng-model=\"wizard.model.company.companyType\" disabled=\"sessionCtrl.session.hasCurrentAccount\" require=\"true\"></salaxy-input-enum>\r\n\r\n      </div>\r\n    </div>\r\n\r\n    <!-- MOBIILIVERSIO YTJ haun tulokset/virheet -->\r\n    <div ng-if=\"!wizard.showCompanySelection\" class=\"visible-xs col-md-12\">\r\n      <!--Näytetään y-tunnuksesta johtuvat virheet, jos niitä on -->\r\n      <div ng-if=\"wizard.getValidationError('Company.BusinessId') && wizard.getValidationError('Company.BusinessId').type=='invalid'\">\r\n        <h3 sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchResultTitle\" ps=\":\"></h3>\r\n        <p>{{ wizard.getValidationError('Company.BusinessId').msg | sxyTranslate}}</p>\r\n      </div>\r\n\r\n      <div ng-if=\"wizard.model.company.ytjSearch != null\">\r\n        <h3>\r\n          <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchResultTitle\" ps=\":\"></span>\r\n          <span ng-if=\"wizard.model.company.ytjSearch && wizard.model.company.ytjSearch.result.length != 0\">\r\n            ({{wizard.model.company.ytjSearch.result.length}} kpl)\r\n          </span>\r\n        </h3>\r\n        <!--Näytetään ytj-hausta johtuvat virheet, jos niitä on -->\r\n        <div ng-if=\"wizard.model.company.ytjSearch.userMessage != null\">\r\n          <p>{{ wizard.model.company.ytjSearch.userMessage }}</p>\r\n        </div>\r\n        <div ng-if=\"wizard.model.company.ytjSearch.isSuccess\">\r\n          <!--Näytetään että tiedot syötetty jos yrityksiä oli tasan yksi -->\r\n          <div ng-if=\"wizard.model.company.ytjSearch.result.length == 1\">\r\n            <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchResultText\"></p>\r\n          </div>\r\n          <!--Näytetään viestit jos yrityksiä on nolla-->\r\n          <div ng-if=\"wizard.model.company.ytjSearch.result.length == 0 && wizard.model.validation.isOfficialIdValid\">\r\n            <p>{{wizard.model.company.ytjSearch.userMessage}}</p>\r\n          </div>\r\n          <div ng-if=\"wizard.model.company.ytjSearch.result.length != 0\">\r\n            <uib-accordion>\r\n              <div uib-accordion-group class=\"panel-default\" ng-repeat=\"company in wizard.model.company.ytjSearch.result\">\r\n                <uib-accordion-heading>\r\n                  <h4>{{company.name}}</h4>\r\n                </uib-accordion-heading>\r\n                {{company.businessId}}<br /> {{company.type}} <br />\r\n                <br />\r\n                <button class=\"btn btn-primary\" ng-click=\"wizard.chooseBusinessId(company.businessId)\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n              </div>\r\n            </uib-accordion>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n\r\n    <div class=\"col-md-6\">\r\n      <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyContact\"></legend>\r\n      <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyStreet\" name=\"Katuosoite\" ng-model=\"wizard.model.company.contact.street\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyPostalCode\" name=\"Postinumero\" sxy-postal-code-fi ng-model=\"wizard.model.company.contact.postalCode\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyCity\" name=\"Postitoimipaikka\" ng-model=\"wizard.model.company.contact.city\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyEmail\" name=\"Sahkoposti\" ng-model=\"wizard.model.company.contact.email\" ng-required=\"true\" sxy-email></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyPhone\" name=\"Puhelinnumero\" ng-model=\"wizard.model.company.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n      <!-- HUOM! Tästä kentästä on mobiiliversio ylempänä koodissa -->\r\n      <div ng-if=\"!wizard.showCompanySelection\" class=\"visible-xs\">\r\n        <salaxy-input-enum label=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType2\" label-cols=\"col-sm-4 col-md-3 col-lg-4\" enum=\"CompanyType\" options=\"{'fiOy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiOy' | sxyTranslate),'fiTm':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiTm' | sxyTranslate),'fiRy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiRy' | sxyTranslate),'fiYy':('SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyTypeFiYy' | sxyTranslate)}\"\r\n          name=\"companyTypeMobile\" ng-model=\"wizard.model.company.companyType\" disabled=\"sessionCtrl.session.hasCurrentAccount\" require=\"true\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n\r\n    <!-- YTJ haun tulokset/virheet -->\r\n    <div ng-if=\"!wizard.showCompanySelection\" class=\"hidden-xs col-md-12\">\r\n      <!-- Näytetään y-tunnuksesta johtuvat virheet, jos niitä on -->\r\n      <div ng-if=\"wizard.getValidationError('Company.BusinessId') && wizard.getValidationError('Company.BusinessId').type=='invalid'\">\r\n        <h3 sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchResultTitle\" ps=\":\"></h3>\r\n        <p>{{ wizard.getValidationError('Company.BusinessId').msg | sxyTranslate}}</p>\r\n      </div>\r\n\r\n      <div ng-if=\"wizard.model.company.ytjSearch != null\">\r\n        <h3>\r\n          <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.ytjSearchResultTitle\" ps=\":\"></span>\r\n          <span ng-if=\"wizard.model.company.ytjSearch && wizard.model.company.ytjSearch.result.length != 0\">\r\n            ({{wizard.model.company.ytjSearch.result.length}} kpl)\r\n          </span>\r\n        </h3>\r\n        <!--Näytetään ytj-hausta johtuvat virheet, jos niitä on -->\r\n        <div ng-if=\"wizard.model.company.ytjSearch.userMessage != null\">\r\n          <p>{{ wizard.model.company.ytjSearch.userMessage }}</p>\r\n        </div>\r\n\r\n\r\n        <!-- Haku onnistui -->\r\n        <div ng-if=\"wizard.model.company.ytjSearch.isSuccess\">\r\n          <!--Näytetään viestit jos yrityksiä on nolla-->\r\n          <div ng-if=\"wizard.model.company.ytjSearch.result.length == 0 && wizard.model.validation.isOfficialIdValid\">\r\n            <p>{{wizard.model.company.ytjSearch.userMessage}}</p>\r\n          </div>\r\n          <div ng-if=\"wizard.model.company.ytjSearch.result.length != 0\" class=\"table-responsive\" style=\"max-height: 300px; overflow-y: auto;\">\r\n\r\n            <table class=\"table table-hover table-bordered\" style=\"overflow-wrap: break-word\">\r\n              <thead>\r\n                <tr>\r\n                  <th>\r\n                    <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyName2\"></span>\r\n                    <br />\r\n                    <span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyBusinessId\"></span>\r\n                  </th>\r\n                  <th class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepCompanyInfo.companyType\"></th>\r\n                  <th></th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"company in wizard.model.company.ytjSearch.result\">\r\n                  <td>\r\n                    {{company.name}}\r\n                    <br /> {{company.businessId}}\r\n                  </td>\r\n                  <td class=\"hidden-xs\">{{company.type}}</td>\r\n                  <td>\r\n                    <a class=\"btn btn-primary\" ng-click=\"wizard.chooseBusinessId(company.businessId)\" sxy-text=\"SALAXY.UI_Terms.select\"></a>\r\n                  </td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/contract.html\",`﻿<form name=\"contractForm\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = contractForm.$valid}}</span>\r\n  <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.signatureText\"></p>\r\n\r\n  <p ng-if=\"wizard.showCompanySelection\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.selectBankText\"></p>\r\n  </p>\r\n\r\n  <div class=\"row\" ng-controller=\"SignatureController as sign\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset ng-if=\"!wizard.showCompanySelection\">\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.yourPersonalId\"></legend>\r\n        <div>\r\n          <salaxy-input name=\"personalId\" label-type=\"plain\" type=\"text\" style=\"width:150px\" placeholder=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.personalIdExample\" ng-model=\"wizard.model.signature.personalId\" require=\"true\" sxy-personal-id-fi></salaxy-input>\r\n        </div>\r\n\r\n      </fieldset>\r\n      <div class=\"spacer-bottom\">\r\n        <input ng-init=\"wizard.model.signature.terms = false\" name=\"terms\" type=\"checkbox\" require=\"true\" ng-model=\"wizard.model.signature.terms\"></input>\r\n        <span sxy-html=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.termsText.html\"></span>\r\n        <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.termsText2\"></a> <span sxy-html=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.termsText3.html\"></span>\r\n      </div>\r\n\r\n      <fieldset>\r\n        <div ng-if=\"wizard.model.accountType == 'company'\">\r\n          <p sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.usePersonalBank\"></p>\r\n        </div>\r\n        <p sxy-html=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.privacyPolicy.html\"></p>\r\n        <div sxy-if-role=\"test\">\r\n          <h3>TEST: Huomaa HETU:sta!</h3>\r\n          <p class=\"text-warning\">\r\n            Allekirjoitus ohjaa nyt testiympäristöön, jossa\r\n            <strong>HETU tarkistetaan</strong>.\r\n            Katso testiympäristön\r\n            <a href=\"https://gist.github.com/ykarikos/e43e567eb7b9e05432d4bd9d0b51ef35\" target=\"_blank\">HETU:t täältä</a>\r\n            (valitse validi hetu).\r\n          </p>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n\r\n    <div class=\"col-md-6 hidden-xs\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.pdfPreviewTitle\"></legend>\r\n        <small><a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.downloadHereLink\"></a></small>\r\n\r\n        <iframe ng-src=\"{{ wizard.getPdfPreviewAddress() }}\" style=\"width: 100%; height: 300px\"></iframe>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6 visible-xs\">\r\n      <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.pdfPreviewLink\"></a>\r\n    </div>\r\n\r\n  </div>\r\n\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/contractButtons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n\r\n<button ng-if=\"wizard.model.signature.personalId == null || wizard.model.signature.terms == false\" ng-disabled=\"true\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.signBtn\"></button>\r\n<a ng-if=\"!(wizard.model.signature.personalId == null || wizard.model.signature.terms == false)\" ng-href=\"{{wizard.vismaSignUrl}}\" target=\"_top\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepContract.signBtn\"></a>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/defaultWizardButtons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goNext()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/firstPageButtons.html\",`﻿<!--a ng-if=\"wizard.model.ui.cancelUrl\" ng-href=\"{{wizard.model.ui.cancelUrl}}\"  class=\"btn btn-default\">Takaisin etusivulle</a-->\r\n<button class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.backToFront\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goNext()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/index.html\",`<div ng-controller=\"SessionController as sessionCtrl\" class=\"company-onboarding\">\r\n  <div ng-controller=\"CompanyOnboardingController as wizard\">\r\n    <div ng-controller=\"NaviController as $naviCtrl\">\r\n\r\n      <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n        <div class=\"modal-header \">\r\n          <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n          <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.modalTitle\"></h2>\r\n\r\n        </div>\r\n        <div class=\"modal-body salaxy-wizard\">\r\n\r\n          <div class=\"visible-xs visible-sm\">\r\n\r\n            <h4><span sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.step\"></span> {{wizard.currentStep.number}}/{{wizard.steps.length}}</h4>\r\n\r\n          </div>\r\n          <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n\r\n              </span>\r\n              <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n                <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n              </a>\r\n            </div>\r\n          </div>\r\n          <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span>{{ step.title | sxyTranslate }}</span>\r\n            </div>\r\n          </div>\r\n\r\n          <ng-include src=\"wizard.currentStep.view\"></ng-include>\r\n\r\n\r\n        </div>\r\n        <div class=\"modal-footer\">\r\n          <ng-include style=\"display: flex; flex-direction: row;justify-content: space-between; align-items: center;\" src=\"wizard.currentStep.buttonsView\"></ng-include>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/suomifi.html\",`<form name=\"currentForm\">\r\n  <!-- Hidden ariable formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"\">\r\n    <br />\r\n    <p>{{wizard.currentStep.intro | sxyTranslate}}</p>\r\n    <br />\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepSuomiFi.infoText\"></legend>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.stepSuomiFi.personalId\" name=\"personalId\" ng-model=\"wizard.model.signature.personalId\" ng-required=\"true\" sxy-personal-id-fi></salaxy-input>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <img src=\"https://cdn.salaxy.com/ng1/img/onboarding/suomifi.png\" class=\"img-responsive\" alt=\"suomi.fi\">\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/suomifiButtons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goToSuomifi()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.stepSuomiFi.goToSuomiFiBtn\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/company/wizard_index.html\",`﻿<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <!-- Hidden ariable formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"\">\r\n    <br />\r\n    <p>{{wizard.currentStep.intro | sxyTranslate}}</p>\r\n    <br />\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personInfo\"></legend>\r\n        <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personFirstName\" name=\"Etunimi\" ng-model=\"wizard.model.person.firstName\" ng-required=\"true\"></salaxy-input>\r\n        <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personLastName\" name=\"Sukunimi\" ng-model=\"wizard.model.person.lastName\" ng-required=\"true\"></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personContact\"></legend>\r\n        <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personEmail\" name=\"Sahkoposti\" ng-model=\"wizard.model.person.contact.email\" ng-required=\"true\" sxy-email></salaxy-input>\r\n        <salaxy-input label=\"SALAXY.NG1.CompanyOnboardingComponent.step1.personPhone\" name=\"Puhelinnumero\" ng-model=\"wizard.model.person.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/buttons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goNext()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/commit-buttons.html\",`<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-danger\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.commit()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/company-legal.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"col-md-6\">\r\n    <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.legalTitle\"></legend>\r\n    <h5><span sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.pep\" ps=\"*\"></span>\r\n      <i class=\"fa fa-info-circle\" popover-title=\"{{ 'SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.pepTitle' | sxyTranslate}}\" uib-popover=\"{{ 'SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.pepPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\"\r\n        popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i>\r\n    </h5>\r\n    <!-- TODO: test-->\r\n    <salaxy-input-boolean type=\"radio\" name=\"identityPep\" label=\"\" label-type=\"plain\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" ng-model=\"wizard.model.signature.isPep\" require=\"true\"></salaxy-input-boolean>\r\n    <div ng-hide=\"!(wizard.model.company.companyType == 'fiOy' || wizard.model.company.companyType == 'fiYy')\">\r\n      <h5>\r\n        <span sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.owner\" ps=\"*\"></span>\r\n        <i class=\"fa fa-info-circle\" popover-title=\"{{ 'SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.ownerTitle' | sxyTranslate}}\" uib-popover=\"{{ 'SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.ownerPopOver' | sxyTranslate}}\" popover-append-to-body=\"true\"\r\n          popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i>\r\n      </h5>\r\n      <div class=\"radio\">\r\n        <label class=\"radio-inline\" for=\"IsRequiredTracking-true\">\r\n          <input type=\"radio\" id=\"IsRequiredTracking-true\" name=\"Ownership.IsRequiredTracking\" ng-value=\"true\" ng-model=\"wizard.model.company.ownership.isRequiredTracking\" required> <span sxy-text=\"SALAXY.UI_Terms.yes\"></span>\r\n        </label>\r\n        <label class=\"radio-inline\" for=\"IsRequiredTracking-false\">\r\n          <input type=\"radio\" id=\"IsRequiredTracking-false\" name=\"Ownership.IsRequiredTracking\" ng-value=\"false\" ng-model=\"wizard.model.company.ownership.isRequiredTracking\" required><span sxy-text=\"SALAXY.UI_Terms.no\"></span>\r\n        </label>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"col-md-6\">\r\n    <div ng-hide=\"wizard.model.company.ownership.isRequiredTracking\">\r\n      <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.fiva\"></legend>\r\n      <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.fivaText\"></p>\r\n    </div>\r\n    <div ng-hide=\"!wizard.model.company.ownership.isRequiredTracking\">\r\n      <fieldset class=\"form-horizontal\">\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolderTitle\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolderText\"></p>\r\n        <div class=\"form-group\">\r\n          <label class=\"col-sm-4 col-md-3 col-lg-4 control-label\" for=\"shareholder1\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolder\" ps=\" 1*\"></label>\r\n          <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n            <input class=\"form-control\" id=\"shareholder1\" name=\"shareholder1\" type=\"text\" ng-model=\"wizard.model.company.ownership.shareHolders[0].name\" value=\"\" ng-required=\"wizard.model.company.ownership.isRequiredTracking == true\">\r\n          </div>\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label class=\"col-sm-4 col-md-3 col-lg-4 control-label\" for=\"shareholder2\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolder\" ps=\" 2 \"></label>\r\n          <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n            <input class=\"form-control\" id=\"shareholder2\" name=\"shareholder2\" type=\"text\" ng-model=\"wizard.model.company.ownership.shareHolders[1].name\" value=\"\">\r\n          </div>\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label class=\"col-sm-4 col-md-3 col-lg-4  control-label\" for=\"shareholder3\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolder\" ps=\" 3 \"></label>\r\n          <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n            <input class=\"form-control\" id=\"shareholder3\" name=\"shareholder3\" type=\"text\" ng-model=\"wizard.model.company.ownership.shareHolders[2].name\" value=\"\">\r\n          </div>\r\n        </div>\r\n        <div class=\"form-group\">\r\n          <label class=\"col-sm-4 col-md-3 col-lg-4 control-label\" for=\"shareholder4\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyLegal.shareHolder\" ps=\" 4 \"></label>\r\n          <div class=\"col-sm-8 col-md-9 col-lg-8\">\r\n            <input class=\"form-control\" id=\"shareholder4\" name=\"shareholder4\" type=\"text\" ng-model=\"wizard.model.company.ownership.shareHolders[3].name\" value=\"\">\r\n          </div>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/company.html\",`<form name=\"currentForm\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div>\r\n    <div class=\"alert alert-danger\" ng-if=\"wizard.existingCompanyAlert\">\r\n      <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.existingCompanyAlert\"></p>\r\n    </div>\r\n  </div>\r\n  <div class=\"col-md-6\">\r\n    <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyInfo\"></legend>\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-input salaxy-if-role=\"!test\" readonly=\"true\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyBusinessId\" name=\"Ytunnus\" ng-required=\"true\" ng-model=\"wizard.model.company.businessId\"></salaxy-input>\r\n      <salaxy-input salaxy-if-role=\"test\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyBusinessId\" name=\"Ytunnus\" ng-required=\"true\" ng-model=\"wizard.model.company.businessId\"></salaxy-input>\r\n      <salaxy-input salaxy-if-role=\"!test\" readonly=\"true\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyName\" name=\"Nimi\" ng-required=\"true\" ng-model=\"wizard.model.company.name\"></salaxy-input>\r\n      <salaxy-input salaxy-if-role=\"test\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyName\" name=\"Nimi\" ng-required=\"true\" ng-model=\"wizard.model.company.name\"></salaxy-input>\r\n      <div class=\"form-group\" salaxy-if-role=\"!test\">\r\n        <label for=\"Yritysmuoto\" class=\"col-sm-4 control-label\" style=\"text-align:left\">\r\n          <span sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyType\" ps=\"*\"></span>\r\n        </label>\r\n        <div class=\"col-sm-8\">\r\n          <input type=\"text\" class=\"form-control\" id=\"Yritysmuoto\" name=\"Yritysmuoto\" placeholder=\"{{'SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyType' | sxyTranslate | lowercase}}\" readonly=\"true\" autocomplete=\"off\" value=\"{{ !wizard.model.company.companyType ? '' : ('SALAXY.ENUM.CompanyType.' + wizard.model.company.companyType +'.label' | sxyTranslate) }}\"\r\n          />\r\n        </div>\r\n      </div>\r\n      <salaxy-input-enum sxy-if-role=\"test\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyType\" name=\"companyType\" ng-model=\"wizard.model.company.companyType\" enum=\"CompanyType\" type=\"select\" placeholder=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyType\"\r\n        required></salaxy-input-enum>\r\n    </div>\r\n  </div>\r\n  <div class=\"col-md-6\">\r\n    <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyContact\"></legend>\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyStreet\" name=\"Katuosoite\" ng-model=\"wizard.model.company.contact.street\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyPostalCode\" name=\"Postinumero\" sxy-postal-code-fi ng-model=\"wizard.model.company.contact.postalCode\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyCity\" name=\"Postitoimipaikka\" ng-model=\"wizard.model.company.contact.city\" ng-required=\"true\"></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyEmail\" name=\"Sahkoposti\" ng-model=\"wizard.model.company.contact.email\" ng-required=\"true\" sxy-email></salaxy-input>\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepCompanyInfo.companyPhone\" name=\"Puhelinnumero\" ng-model=\"wizard.model.company.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/finish-buttons.html\",`<div class=\"btn-group\" role=\"group\">\r\n  <button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-danger\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n</div>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<div class=\"btn-group\">\r\n  <button class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button class=\"btn btn-success\" ng-click=\"$close('ok');wizard.launch()\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.newAccountBtn\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/finish.html\",`﻿<form name=\"currentForm\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"col-md-12\" sxy-html=\"SALAXY.NG1.CustomerOnboardingComponent.stepInviteCompany.html\" params=\"{sharingLink :wizard.sharingLink, mailToLink : wizard.mailtoLink}\"></div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/index.html\",`<div ng-controller=\"SessionController as sessionCtrl\">\r\n  <div ng-controller=\"CustomerOnboardingController as wizard\">\r\n    <div ng-controller=\"NaviController as $naviCtrl\">\r\n\r\n      <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n        <div class=\"modal-header\">\r\n          <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n          <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.modalTitle\"></h2>\r\n        </div>\r\n        <div class=\"modal-body salaxy-wizard\">\r\n          <div class=\"container-fluid\">\r\n            <div class=\"row visible-xs visible-sm\">\r\n              <div class=\"col-xs-12\">\r\n                <h4><span sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.step\"></span> {{wizard.currentStep.number}}/{{wizard.steps.length}}</h4>\r\n              </div>\r\n            </div>\r\n            <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n              <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n                <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n                                        <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n                                    </span>\r\n                <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n                  <span class=\"salaxy-avatar\">\r\n                                            <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n                                        </span>\r\n                </a>\r\n              </div>\r\n            </div>\r\n            <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n              <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n                <span>{{ step.title | sxyTranslate }}</span>\r\n              </div>\r\n            </div>\r\n            <div class=\"row\">\r\n              <ng-include src=\"wizard.currentStep.view\"></ng-include>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div class=\"modal-footer\">\r\n          <ng-include style=\"display: flex; flex-direction: row;justify-content: space-between; align-items: center; \" src=\"wizard.currentStep.buttonsView\"></ng-include>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/insurance.html\",`<form name=\"currentForm\">\r\n\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid}}</span>\r\n\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionTitle\"></legend>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input-boolean label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionText\" type=\"radio\" name=\"isPensionContractDone\" ng-model=\"wizard.model.products.pension.isPensionContractDone\" label-type=\"basic\" label-true=\"SALAXY.UI_Terms.yes\"\r\n            label-false=\"SALAXY.UI_Terms.no\" ng-change=\"wizard.checkPensionCompanySelection()\"></salaxy-input-boolean>\r\n        </div>\r\n        <div ng-if=\"!wizard.model.products.pension.isPensionContractDone\">\r\n          <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.hasPension\"></p>\r\n        </div>\r\n        <div ng-if=\"wizard.model.products.pension.isPensionContractDone\" class=\"form-horizontal\">\r\n          <salaxy-input-enum label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionCompany\" name=\"pensionCompany\" enum=\"PensionCompany\" filter=\"varma,elo,ilmarinen,veritas,apteekkien,verso,valio,kevaMunicipal,kevaAland,kevaChurch,kevaKela,kevaState\" ng-model=\"wizard.model.products.pension.pensionCompany\"\r\n            ng-change=\"wizard.checkPensionCompanySelection(); wizard.model.products.pension.pensionContractNumber = null;\" require=\"true\"></salaxy-input-enum>\r\n\r\n          <main salaxy-if-role=\"test\" class=\"test-number\">\r\n            <div class=\"form-group\" ng-if=\"wizard.model.products.pension.pensionCompany != 'null' && wizard.model.products.pension.pensionCompany != 'none'\">\r\n              <div class=\"col-sm-8 col-sm-offset-4 text-right-sm\">\r\n                <span><span sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.testOnly\"></span>T <button class=\"btn btn-secondary  btn-xs\" ng-click=\"wizard.setPensionNumberForTest()\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.testGenerateNumberBtn\"></button></span>\r\n              </div>\r\n            </div>\r\n          </main>\r\n          <div ng-if=\"wizard.model.products.pension.pensionCompany != 'other'\">\r\n            <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionContractNumber\" require=\"true\" type=\"text\" name=\"pensionContractNumber\" id=\"pensionContractNumber\" ng-model=\"wizard.model.products.pension.pensionContractNumber\" tooltip-html=\"{{'SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionContractNumberToolTip.html' | sxyTranslate}}\"\r\n              tooltip-placement=\"top-right\" sxy-pension-contract-number=\"wizard.model.products.pension.pensionCompany\"></salaxy-input>\r\n\r\n            <div class=\"row\" ng-show=\"currentForm.pensionContractNumber.$error.sxyTemporaryPensionContractNumber\">\r\n              <div class=\"col-xs-12 input-info text-danger\">\r\n                <div class=\"input-info-icon\"><i class=\"fa fa-exclamation-triangle\"></i></div>\r\n                <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionContractNumberTemporaryToolTip.html\"></p>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-sm-6 col-xs-12\" ng-if=\"wizard.model.products.pension.isPensionContractDone\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionHandling\"></legend>\r\n        <div class=\"input-wrapper\">\r\n          <div class=\"form-group\">\r\n            <div>\r\n              <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.pensionSelfHandleDescription\"></p>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.insuranceTitle\"></legend>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input-boolean type=\"radio\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.insuranceText\" label-type=\"basic\" label-true=\"SALAXY.UI_Terms.yes\" label-false=\"SALAXY.UI_Terms.no\" ng-model=\"wizard.model.products.insurance.isInsuranceContractDone\"\r\n            name=\"isInsuranceContractDone\" ng-change=\"wizard.checkInsuranceCompanySelection()\"></salaxy-input-boolean>\r\n        </div>\r\n        <div ng-if=\"wizard.model.products.insurance.isInsuranceContractDone\" class=\"form-horizontal\">\r\n          <salaxy-input-enum enum=\"InsuranceCompany\" filter=\"if,fennia,lähiTapiola,pohjantähti,pohjola,turva,aVakuutus,folksam,alandia,ålands\" name=\"InsuranceCompany\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.insuranceCompany\" ng-model=\"wizard.model.products.insurance.insuranceCompany\"\r\n            require=\"true\"></salaxy-input-enum>\r\n          <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.insuranceContractNumber\" require=\"true\" name=\"insuranceContractNumber\" ng-model=\"wizard.model.products.insurance.insuranceContractNumber\"></salaxy-input>\r\n        </div>\r\n        <div ng-if=\"!wizard.model.products.insurance.isInsuranceContractDone && !wizard.model.products.insurance.isPartnerInsurance\">\r\n          <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.noInsuranceAlert\"></p>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.taxTitle\"></legend>\r\n\r\n        <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.taxText\"></p>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input-enum ng-model=\"wizard.model.products.tax.irReporting\" name=\"irReporting\" label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.irReporting\" options=\"{ default: ('SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.irReportingDefault' | sxyTranslate), noMonthlyReport: ('SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.irReportingNoMonthlyReport' | sxyTranslate), always: ('SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.irReportingAlways' | sxyTranslate)}\"></salaxy-input-enum>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.employmentTitle\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.employmentText\"></p>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.reportTitle\"></legend>\r\n        <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.reportText\"></p>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepInsurance.accountantEmail\" name=\"Sahkopostiosoite\" ng-model=\"wizard.model.products.accounting.accountantEmail\" sxy-email></salaxy-input>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/invitation.html\",`﻿\r\n\r\n<div ng-controller=\"SessionController as sessionCtrl\">\r\n  <div ng-controller=\"NaviController as $naviCtrl\">\r\n    <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n        <div class=\"modal-header\">\r\n          <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n          <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.invitation.title\"></h2>\r\n        </div>\r\n        <div class=\"modal-body salaxy-wizard\">\r\n          <div class=\"container-fluid\">\r\n            <div class=\"row\">\r\n              <form name=\"currentForm\">\r\n                <div class=\"col-md-12\" sxy-html=\"SALAXY.NG1.CustomerOnboardingComponent.invitation.html\" params=\"{signingLink : $ctrl.signingLink}\"></div>\r\n                <div class=\"col-md-12 text-right\">\r\n                  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.copyLink($ctrl.signingLink)\" uib-popover=\"{{ !!$ctrl.linkCopied ? ('SALAXY.UI_Terms.copiedToClipboard' | sxyTranslate) : ('SALAXY.UI_Terms.copyToClipboard' | sxyTranslate)}}\" popover-trigger=\"'mouseenter'\"><i class=\"fa fa-clipboard\"></i> <span sxy-text=\"SALAXY.UI_Terms.copyToClipboard\"></span></button>\r\n                </div>\r\n              </form>\r\n            </div>\r\n          </div>\r\n        </div>\r\n        <div class=\"modal-footer text-right\">\r\n            <button class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n        </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/user-buttons.html\",`<button ng-click=\"$close('cancel')\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.backToFront\"></button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-disabled=\"!wizard.canGoNext\" ng-click=\"wizard.goToCompanySelection()\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/customer/user.html\",`﻿<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"col-md-6\">\r\n    <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userInfo\"></legend>\r\n    <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userFirstName\" name=\"Etunimi\" ng-model=\"wizard.model.person.firstName\" ng-required=\"true\"></salaxy-input>\r\n    <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userLastName\" name=\"Sukunimi\" ng-model=\"wizard.model.person.lastName\" ng-required=\"true\"></salaxy-input>\r\n    <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userEmail\" name=\"Sahkoposti\" ng-model=\"wizard.model.person.contact.email\" ng-required=\"true\" sxy-email></salaxy-input>\r\n    <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userPhone\" name=\"Puhelinnumero\" ng-model=\"wizard.model.person.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n  </div>\r\n\r\n  <div class=\"col-md-6\">\r\n    <legend sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.signeratureTitle\"></legend>\r\n    <p sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.signeratureText\"></p>\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.userPersonalId\" name=\"Henkilotunnus\" sxy-personal-id-fi placeholder=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.personalIdExample\" ng-model=\"wizard.model.signature.personalId\"\r\n        ng-required=\"true\"></salaxy-input>\r\n    </div>\r\n    <div class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.checkSignatureAlert\"></div>\r\n\r\n    <div class=\"form-horizontal\">\r\n      <salaxy-input label=\"SALAXY.NG1.CustomerOnboardingComponent.stepUserInfo.businessId\" name=\"Ytunnus\" ng-model=\"wizard.model.company.businessId\" sxy-company-id-fi ng-required=\"true\"></salaxy-input>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/generic/index.html\",`<div ng-controller=\"SessionController as sessionCtrl\">\r\n  <div ng-controller=\"NaviController as $naviCtrl\">\r\n\r\n    <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n      <div class=\"modal-header\">\r\n        <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n        <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.GenericOnboardingComponent.modalTitle\"></h2>\r\n        <img src=\"https://cdn.salaxy.com/img/palkkaus/logo/palkkaus-www-logo-white-border.png\" class=\"img-responsive hidden-xs modal-logo\" />\r\n      </div>\r\n      <div class=\"modal-body salaxy-wizard\">\r\n        <div>\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.GenericOnboardingComponent.roleTitle\" ps=\"*\"></legend>\r\n            <div class=\"form-horizontal\">\r\n              <div class=\"radio\" ng-repeat=\"accountType in ['company', 'worker']\">\r\n                <label ng-if=\"accountType == 'company'\">\r\n              <input type=\"radio\" name=\"wizardType\" ng-model=\"$ctrl.data.model.accountType\" value=\"company\" ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" /> \r\n              <span sxy-text=\"SALAXY.NG1.GenericOnboardingComponent.roleCompany\"></span>\r\n            </label>\r\n\r\n                <label ng-if=\"accountType == 'worker'\">\r\n              <input type=\"radio\" name=\"wizardType\" ng-model=\"$ctrl.data.model.accountType\" value=\"worker\" ng-disabled=\"sessionCtrl.session.hasCurrentAccount\" />\r\n              <span sxy-text=\"SALAXY.NG1.GenericOnboardingComponent.roleWorker\"></span>\r\n            </label>\r\n              </div>\r\n            </div>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n      <div class=\"modal-footer\">\r\n        <button ng-click=\"$ctrl.data.launch($close)\" ng-disabled=\"!$ctrl.data.model.accountType || $ctrl.data.model.accountType == 'none'\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.GenericOnboardingComponent.launchBtn\"></button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/contract.html\",`﻿<form name=\"contractForm\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = contractForm.$valid}}</span>\r\n\r\n  <h3>Palvelusopimus ja valtuutus</h3>\r\n  <p>\r\n    Rakennusliitto tarjoaa Palkkamylly-palvelun jäsenilleen ja heidän työnantajilleen. Palvelun tuottaa Suomen Palkanlaskenta Oy (Palkkaus.fi).\r\n  </p>\r\n  <p>\r\n    Jotta Palkkamylly voi hoitaa puolestasi palkanmaksuun liittyviä velvoitteita, sinun täytyy allekirjoittaa <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\">oheinen valtakirja</a>. Se pitää allekirjoittaa vain kerran.\r\n  </p>\r\n  <p>\r\n    Kirjoita henkilötunnuksesi ja valitse pankkisi. Siirryt pankkisi verkkopalveluun, jossa varsinainen tunnistautuminen tapahtuu. Sen jälkeen palaat Palkkamylly-palveluun ja olet valmis aloittamaan käytön.\r\n  </p>\r\n\r\n\r\n  <div class=\"row\" ng-controller=\"SignatureController as sign\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend>Allekirjoita henkilötunnuksellasi</legend>\r\n        <div style=\"margin-bottom:15px;\">\r\n          <salaxy-input name=\"personalId\" label-type=\"plain\" type=\"text\" style=\"width:150px\" placeholder=\"PPKKVV-NNNX\" ng-model=\"wizard.model.signature.personalId\" require=\"true\" sxy-personal-id-fi></salaxy-input>\r\n        </div>\r\n      </fieldset>\r\n      <fieldset>\r\n        <legend>Valitse verkkopankkisi</legend>\r\n        <div ng-if=\"wizard.model.accountType == 'company'\">\r\n          <p>\r\n            Et voi käyttää yrityksen tai yhdistyksen verkkopankkitunnuksia valtakirjan allekirjoittamiseen. Sinun täytyy käyttää henkilökohtaisia verkkopankkitunnuksiasi\r\n          </p>\r\n        </div>\r\n        <div id=\"bankButtonRow\">\r\n          <div class=\"btn-group\" id=\"mostUsedBanks\">\r\n            <label ng-model=\"wizard.model.signature.method\" uib-btn-radio=\"signMethod.value\" ng-repeat=\"signMethod in sign.getMethods('telia') | filter: {isPopular:true}\" class=\"btn btn-default\" aria-label=\"{{signMethod.name}}\">\r\n                        <img ng-src=\"{{signMethod.img}}\" style=\"max-height: 20px; max-width: 85px\" />\r\n                            {{signMethod.title}}\r\n                    </label>\r\n          </div>\r\n          <div class=\"btn-group group-dropdown\" uib-dropdown>\r\n            <a class=\"btn btn-default dropdown-toggle\" id=\"other-banks-button\" uib-dropdown-toggle ng-class=\"(wizard.model.signature.method != null && sign.getMethod(wizard.model.signature.method).isPopular == false) ? 'bank-chosen': ''\">\r\n\r\n              <span ng-if=\"wizard.model.signature.method == null || sign.getMethod(wizard.model.signature.method).isPopular == true\">Muut verkkopankit</span>\r\n              <span ng-if=\"wizard.model.signature.method != null && sign.getMethod(wizard.model.signature.method).isPopular == false\">\r\n                                <img ng-src=\"{{ sign.getMethod(wizard.model.signature.method).img }}\"\r\n                                     style=\"max-height: 20px; max-width: 85px\"/> {{sign.getMethod(wizard.model.signature.method).title}}\r\n                            </span> &nbsp; <span class=\"caret\"></span>\r\n            </a>\r\n            <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"other-banks-button\">\r\n              <li ng-repeat=\"signMethod in sign.getMethods('telia') | filter: {isPopular:false}\" role=\"menuitem\" ng-class=\"wizard.model.signature.method == signMethod.value ? 'active' : ''\">\r\n                <a ng-click=\"wizard.model.signature.method = signMethod.value\">\r\n                  <img ng-src=\"{{signMethod.img}}\" style=\"max-height: 20px; max-width: 85px\" /> {{signMethod.title}}\r\n                </a>\r\n              </li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n      </fieldset>\r\n      <p style=\"margin-top:15px;\">\r\n\r\n        <strong>HUOM:</strong> Palkkamyllyn tarjoaa Rakennusliitto ry, joka toimii henkilötietojen käsittelijänä ja vastaa myös asiakaspalvelusta. Palvelun tuottajana ja teknisenä toteuttajana ja myös henkilötietojen käsittelijä toimii Suomen Palkanlaskenta\r\n        Oy (Palkkaus.fi).\r\n\r\n      </p>\r\n      <p>\r\n        Tunnistautumalla hyväksyt:<br>\r\n        <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Kayttoehdot_Oct2021.pdf?Expires=1795336880&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=dTZrDk4AgZv29ldlizR%2Bfe9uv5NgXtAU%2BZBr%2FgbO7p%2FWpoyc4rtUnbUyoRwqLE2OSJ2ZUIRvPucZt7jUhGiAmXEpsG7vsieoBHX9C1P%2F79VoJdIvLG9sqe4wOIQG0t0KUhNxv4I3dpymLV1F16T%2FKLN94vSGRLv6pNHblNqc3iGpoIw11d3dG3%2BhVL%2Fnajwcfirh7m7V7PLIn4fHNY6Q6PbfhbVRpeLprM37sUKTlCBLwdEihZJ7bNcoRvWG4CWfZMk9hRaV66YYadNxEEnBd6EOQZZ5%2B0S2%2F%2FSOLWT5d9amM%2F8S0IW7wOcwr3crCs%2BcroZ6aYSFrZ1H6TCTdRUkNA%3D%3D\"\r\n          target=\"_blank\">Palkkamyllyn käyttöehdot</a><br>\r\n        <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Sopimus_henkilotietojen_kasittelysta_Oct2021.pdf?Expires=1795336940&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=gcO62AB17YCjv5mVTtSP%2FtgG2RxGUSnaGpfK0GencENWGoq8FF1F5MlXEfyZ5pM6eW9tEubAWd8WkxP7WpmX63mtcvdnCViiz52TQjYiK%2BSjJw6ZD6QB%2F%2FPQRVQGsoKilFVJZ4HVshOWcsvOVrcR1ci6dlsFOQPnFQXQhalCaJHiFzGJzxsRtPEaD1GMtqANqzdcmZbqR6ULEE73G2WxYVJ4%2FeK1bpd0qAKlBvs%2Fh9DlDd8RDx5M3BSJj7q43KHP5kT8mOq2bky4xNnq7q31jgnub%2BVO1a4X7RAKzbKabW4D6y%2BlDKzK%2FJgnmbPsS8TzYFuSkH81aiqu5MGR2zfn9A%3D%3D\"\r\n          target=\"_blank\">Sopimuksen henkilötietojen käsittelystä</a><br>\r\n        <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Tietosuojaseloste_Oct2021.pdf?Expires=1793455095&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=dVqt3NenZZwBOPmmKz15jrIlgUOv2J2QE39Ltl7sK9t6iUC6YSXpnRifRoJLdcCrJpgt8KBpw%2FDXLm9olu5wzBFhSXKa1b4LRclyVjpzs27e9%2BMJceizLURvLWeKyZsyuYc%2BU3U7V0vkN0S%2B4nqkcDqskXCtvccmcBg0BgPYaslcSwLu4NUztiR2vA5qUj%2FL6hBelLqjKyqA%2FwDHahcTp07de6WqkEDud46W9Fv1oEJDioiho9W3%2F2W5kpVe2JxA3VB6D9j7Fwt45LBsDZC5opFiwnzWuahr7zEyn9UVuf4nLOJ83PcfYIsRo0pZWAPIgScsH%2BcAOXFgbnr5OkTu2A%3D%3D\"\r\n          target=\"_blank\">Tietosuojaselosteen</a>\r\n      </p>\r\n    </div>\r\n\r\n    <div class=\"col-md-6 hidden-xs\">\r\n      <fieldset>\r\n        <legend>Valtakirjan esikatselu</legend>\r\n\r\n        <small><a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\">Lataa tästä, jos et näe esikatselua</a></small>\r\n\r\n        <iframe ng-src=\"{{ wizard.getPdfPreviewAddress() }}\" style=\"width: 100%; height: 300px\"></iframe>\r\n      </fieldset>\r\n    </div>\r\n\r\n\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/contractButtons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\">Edellinen</button>\r\n<div salaxy-loader class=\"spinner\">\r\n    <div class=\"bounce1\"></div>\r\n    <div class=\"bounce2\"></div>\r\n    <div class=\"bounce3\"></div>\r\n</div>\r\n\r\n<button ng-if=\"wizard.model.signature.personalId == null || wizard.model.signature.method == null\"  ng-disabled=\"true\" class=\"btn btn-primary\">Allekirjoita valtakirja<span class=\"hidden-xs\" ng-if=\"wizard.model.accountType != 'worker'\"> ja voit maksaa palkkaa</span></button>\r\n<a ng-if=\"!(wizard.model.signature.personalId == null || wizard.model.signature.method == null)\" ng-href=\"{{wizard.vismaSignUrl}}\" target=\"_top\"  class=\"btn btn-primary\">Allekirjoita valtakirja<span class=\"hidden-xs\" ng-if=\"wizard.model.accountType != 'worker'\"> ja voit maksaa palkkaa</span></a>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/firstPageButtons.html\",`﻿<!--a ng-if=\"wizard.model.ui.cancelUrl\" ng-href=\"{{wizard.model.ui.cancelUrl}}\"  class=\"btn btn-default\">Takaisin etusivulle</a-->\r\n\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goNext()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\">Seuraava</button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/household.html\",`﻿<form name=\"householdForm\" class=\"form-horizontal\">\r\n  <!-- Hidden variable formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = householdForm.$valid}}</span>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend> Yhteystiedot <i class=\"fa fa-info-circle\" popover-title=\"Miksi kysymme osoitetietojasi?\" uib-popover=\"Lähetämme puolestasi tietoja ja erilaisia lomakkeita eri viranomaisille. Jotkut näistä viranomaisista vaativat joissain lomakkeissa osoitetiedot pakollisina tietoina.\"\r\n            popover-append-to-body=\"true\" popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i> </legend>\r\n        <div class=\"form-horizontal\">\r\n          <salaxy-input label=\"Katuosoite\" name=\"Katuosoite\" ng-model=\"wizard.model.person.contact.street\" require=\"true\"></salaxy-input>\r\n          <salaxy-input label=\"Postinumero\" name=\"Postinumero\" ng-model=\"wizard.model.person.contact.postalCode\" require=\"true\" sxy-postal-code-fi></salaxy-input>\r\n          <salaxy-input label=\"Postitoimipaikka\" name=\"Postitoimipaikka\" ng-model=\"wizard.model.person.contact.city\" require=\"true\"></salaxy-input>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend>Palkanmaksuun tarvittavat tiedot</legend>\r\n        <p>\r\n          Osoitetietojasi työnantajana tarvitaan tulorekisteri-ilmoitukseen, näin esim. työttömyysvakuutuslaskujen lähettäminen sinulle onnistuu.\r\n        </p>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/householdButtons.html\",`﻿\r\n<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\">Edellinen</button>\r\n<div salaxy-loader class=\"spinner\">\r\n    <div class=\"bounce1\"></div>\r\n    <div class=\"bounce2\"></div>\r\n    <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-click=\"wizard.goNext()\" ng-disabled=\"!wizard.canGoNext\" class=\"btn btn-primary\">Seuraava</button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/index.html\",`<div ng-controller=\"SessionController as sessionCtrl\">\r\n  <div ng-controller=\"HouseholdOnboardingController as wizard\">\r\n    <div ng-controller=\"NaviController as $naviCtrl\">\r\n\r\n      <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n        <div class=\"modal-header\">\r\n          <h2 class=\"modal-title\">Palkkamylly / Käyttöönotto</h2>\r\n          <!--\r\n        TODO: Consider adding back with skinning. But perhaps not needed?\r\n        <img src=\"https://cdn.salaxy.com/img/palkkaus/logo/palkkaus-www-logo-white-border.png\" class=\"img-responsive hidden-xs modal-logo\" />\r\n      -->\r\n        </div>\r\n        <div class=\"modal-body salaxy-wizard\">\r\n          <div class=\"visible-xs visible-sm\">\r\n            <h4>Vaihe {{wizard.currentStep.number}}/{{wizard.steps.length}}</h4>\r\n          </div>\r\n          <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n              <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n                <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n              </a>\r\n            </div>\r\n          </div>\r\n          <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span>{{ step.title }}</span>\r\n            </div>\r\n          </div>\r\n          <ng-include src=\"wizard.currentStep.view\"></ng-include>\r\n        </div>\r\n        <div class=\"modal-footer\">\r\n          <ng-include style=\"display: flex; flex-direction: row;justify-content: space-between; align-items: center;\" src=\"wizard.currentStep.buttonsView\"></ng-include>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/household/wizard_index.html\",`﻿<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <!-- Hidden ariable formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"\">\r\n    <br/>\r\n    <p>{{wizard.currentStep.intro | sxyTranslate}}</p>\r\n\r\n    <br/>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend>Henkilötiedot</legend>\r\n        <salaxy-input label=\"Etunimi\" name=\"Etunimi\" ng-model=\"wizard.model.person.firstName\" ng-required=\"true\"></salaxy-input>\r\n        <salaxy-input label=\"Sukunimi\" name=\"Sukunimi\" ng-model=\"wizard.model.person.lastName\" ng-required=\"true\"></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <fieldset>\r\n        <legend>Yhteystiedot</legend>\r\n        <salaxy-input label=\"Sähköposti\" name=\"Sahkoposti\" ng-model=\"wizard.model.person.contact.email\" ng-required=\"true\" sxy-email read-only=\"!!wizard.model.person.contact.email\"></salaxy-input>\r\n        <salaxy-input label=\"Puhelinnumero\" name=\"Puhelinnumero\" ng-model=\"wizard.model.person.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/palkkamylly/federate-sign.html\",`<div ng-controller=\"SessionController as sessionCtrl\" class=\"worker-onboarding-wizard\">\r\n  <div ng-controller=\"WorkerOnboardingController as wizard\">\r\n    <div class=\"modal-header\">\r\n      <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h2 class=\"modal-title\">Palkkamylly käyttöönotto</h2>\r\n    </div>\r\n    <div class=\"modal-body salaxy-wizard\">\r\n      <form name=\"contractForm\">\r\n        <span class=\"hidden\">{{ wizard.formDataValidity = contractForm.$valid && !wizard.model.signature.personalId && !wizard.model.signature.method}}</span>\r\n        <div ng-controller=\"SignatureController as sign\">\r\n          <h3>Palvelusopimus ja valtuutus</h3>\r\n          <p>\r\n            Rakennusliitto tarjoaa Palkkamylly-palvelun jäsenilleen ja heidän työnantajilleen. Palvelun tuottaa Suomen Palkanlaskenta Oy (Palkkaus.fi).\r\n          </p>\r\n          <p>\r\n            Jotta Palkkamylly voi hoitaa puolestasi palkanmaksuun liittyviä velvoitteita, sinun täytyy allekirjoittaa <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\">oheinen valtakirja</a>. Se pitää allekirjoittaa vain kerran.\r\n          </p>\r\n          <p>Kirjoita henkilötunnuksesi, valitse pankkisi ja paina Tunnistaudu-nappia. Siirryt pankkisi verkkopalveluun, jossa varsinainen tunnistautuminen tapahtuu. Sen jälkeen palaat Palkkamylly-palveluun ja olet valmis aloittamaan käytön.</p>\r\n          <div class=\"row form-horizontal\" ng-init=\"ui.telephone = wizard.model.person.contact.telephone\">\r\n            <div class=\"\" ng-init=\"wizard.model.signature.personalId = wizard.model.person.personalId\" ng-class=\"{'col-sm-6': ui.telephone, 'col-sm-8': !ui.telephone}\">\r\n              <salaxy-input label=\"Tarkista henkilötunnuksesi\" label-type=\"basic\" name=\"personalId\" placeholder=\"PPKKVV-NNNX\" ng-model=\"wizard.model.signature.personalId\" sxy-personal-id-fi ng-required=\"true\"></salaxy-input>\r\n            </div>\r\n            <div ng-if=\"ui.telephone\" class=\"col-sm-6\">\r\n              <salaxy-input label=\"Tarkista puhelinnumerosi\" name=\"telephone\" ng-model=\"wizard.model.person.contact.telephone\" sxy-mobile-phone label-type=\"basic\" ng-required=\"true\"></salaxy-input>\r\n            </div>\r\n            <div ng-if=\"!ui.telephone\" class=\"col-sm-4\">\r\n              <salaxy-input label=\"Puhelinnumero\" name=\"telephone\" ng-model=\"wizard.model.person.contact.telephone\" sxy-mobile-phone label-type=\"basic\" ng-required=\"true\"></salaxy-input>\r\n            </div>\r\n          </div>\r\n\r\n          <div class=\"row form-horizontal\">\r\n            <div class=\"col-sm-4\">\r\n              <salaxy-input label=\"Etunimi\" name=\"firstName\" ng-model=\"wizard.model.person.firstName\" label-type=\"basic\" readonly=\"true\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-sm-4\">\r\n              <salaxy-input label=\"Sukunimi\" name=\"lastName\" ng-model=\"wizard.model.person.lastName\" label-type=\"basic\" readonly=\"true\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-sm-4\">\r\n              <salaxy-input label=\"Sähköpostiosoite\" name=\"email\" ng-model=\"wizard.model.person.contact.email\" label-type=\"basic\" readonly=\"true\"></salaxy-input>\r\n            </div>\r\n          </div>\r\n\r\n          <div class=\"row spacer-bottom\" ng-if=\"wizard.isOtherIdentifier(wizard.model.signature.personalId)\">\r\n            <div class=\"col-xs-12\">\r\n              <h5><strong>Osoite</strong></h5>\r\n            </div>\r\n            <salaxy-input ng-model=\"wizard.model.person.contact.street\" placeholder=\"Katuosoite\" name=\"street\" class=\"col-sm-4\" label-type=\"plain\" ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input ng-model=\"wizard.model.person.contact.postalCode\" placeholder=\"Postinumero\" name=\"postalCode\" class=\"col-sm-4\" label-type=\"plain\" ng-required=\"true\"></salaxy-input>\r\n            <salaxy-input ng-model=\"wizard.model.person.contact.city\" placeholder=\"Toimipaikka\" name=\"city\" class=\"col-sm-4\" label-type=\"plain\" ng-required=\"true\"></salaxy-input>\r\n          </div>\r\n\r\n          <h4>\r\n            Ja valitse verkkopankkisi\r\n            <small>\r\n                          <i class=\"fa fa-info-circle\"\r\n                              uib-popover=\"Kun olet valinnut pankkisi ja painat 'Tunnistaudu'- nappia, siirryt tekemään sähköisen allekirjoituksen verkkopankkitunnuksillasi. Tunnistautumisen jälkeen palaat Palkkaus.fi-palveluun.\"\r\n                              popover-append-to-body=\"true\" popover-placement=\"auto\" popover-trigger=\"'mouseenter click'\"></i>\r\n                  </small>\r\n          </h4>\r\n          <div id=\"bankButtonRow\" class=\"row\">\r\n            <label class=\"col-sm-2 col-xs-4 btn-bank\" ng-model=\"wizard.model.signature.method\" uib-btn-radio=\"signMethod.value\" ng-repeat=\"signMethod in sign.getMethods('telia')\" class=\"btn btn-default\" aria-label=\"{{signMethod.name}}\">\r\n              <div class=\"btn-bank-inner\"> <img ng-src=\"{{signMethod.img}}\"/>\r\n                    <span class=\"bank-title\"> {{signMethod.title}}</span> \r\n                </div>\r\n            </label>\r\n          </div>\r\n          <br/>\r\n          <p style=\"margin-top:15px;\">\r\n            <strong>HUOM:</strong> Palkkamyllyn tarjoaa Rakennusliitto ry, joka toimii henkilötietojen käsittelijänä ja vastaa myös asiakaspalvelusta. Palvelun tuottajana ja teknisenä toteuttajana ja myös henkilötietojen käsittelijä toimii Suomen Palkanlaskenta\r\n            Oy (Palkkaus.fi).\r\n          </p>\r\n          <p>Tunnistautumalla hyväksyt:<br>\r\n            <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Kayttoehdot_Oct2021.pdf?Expires=1795336880&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=dTZrDk4AgZv29ldlizR%2Bfe9uv5NgXtAU%2BZBr%2FgbO7p%2FWpoyc4rtUnbUyoRwqLE2OSJ2ZUIRvPucZt7jUhGiAmXEpsG7vsieoBHX9C1P%2F79VoJdIvLG9sqe4wOIQG0t0KUhNxv4I3dpymLV1F16T%2FKLN94vSGRLv6pNHblNqc3iGpoIw11d3dG3%2BhVL%2Fnajwcfirh7m7V7PLIn4fHNY6Q6PbfhbVRpeLprM37sUKTlCBLwdEihZJ7bNcoRvWG4CWfZMk9hRaV66YYadNxEEnBd6EOQZZ5%2B0S2%2F%2FSOLWT5d9amM%2F8S0IW7wOcwr3crCs%2BcroZ6aYSFrZ1H6TCTdRUkNA%3D%3D\"\r\n              target=\"_blank\">Palkkamyllyn käyttöehdot</a><br>\r\n            <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Sopimus_henkilotietojen_kasittelysta_Oct2021.pdf?Expires=1795336940&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=gcO62AB17YCjv5mVTtSP%2FtgG2RxGUSnaGpfK0GencENWGoq8FF1F5MlXEfyZ5pM6eW9tEubAWd8WkxP7WpmX63mtcvdnCViiz52TQjYiK%2BSjJw6ZD6QB%2F%2FPQRVQGsoKilFVJZ4HVshOWcsvOVrcR1ci6dlsFOQPnFQXQhalCaJHiFzGJzxsRtPEaD1GMtqANqzdcmZbqR6ULEE73G2WxYVJ4%2FeK1bpd0qAKlBvs%2Fh9DlDd8RDx5M3BSJj7q43KHP5kT8mOq2bky4xNnq7q31jgnub%2BVO1a4X7RAKzbKabW4D6y%2BlDKzK%2FJgnmbPsS8TzYFuSkH81aiqu5MGR2zfn9A%3D%3D\"\r\n              target=\"_blank\">Sopimuksen henkilötietojen käsittelystä</a><br>\r\n            <a href=\"https://storage.googleapis.com/rakennusliitto-production-uploads/content_management/documents/Palkkamylly_Tietosuojaseloste_Oct2021.pdf?Expires=1793455095&GoogleAccessId=cloud-run-service-account%40rakennusliitto.iam.gserviceaccount.com&Signature=dVqt3NenZZwBOPmmKz15jrIlgUOv2J2QE39Ltl7sK9t6iUC6YSXpnRifRoJLdcCrJpgt8KBpw%2FDXLm9olu5wzBFhSXKa1b4LRclyVjpzs27e9%2BMJceizLURvLWeKyZsyuYc%2BU3U7V0vkN0S%2B4nqkcDqskXCtvccmcBg0BgPYaslcSwLu4NUztiR2vA5qUj%2FL6hBelLqjKyqA%2FwDHahcTp07de6WqkEDud46W9Fv1oEJDioiho9W3%2F2W5kpVe2JxA3VB6D9j7Fwt45LBsDZC5opFiwnzWuahr7zEyn9UVuf4nLOJ83PcfYIsRo0pZWAPIgScsH%2BcAOXFgbnr5OkTu2A%3D%3D\"\r\n              target=\"_blank\">Tietosuojaselosteen</a>\r\n          </p>\r\n        </div>\r\n      </form>\r\n    </div>\r\n    <div class=\"modal-footer\">\r\n      <div salaxy-loader class=\"spinner\">\r\n        <div class=\"bounce1\"></div>\r\n        <div class=\"bounce2\"></div>\r\n        <div class=\"bounce3\"></div>\r\n      </div>\r\n      <button ng-if=\"wizard.model.signature.personalId == null || wizard.model.signature.method == null\" ng-disabled=\"true\" class=\"btn btn-primary\">Tunnistaudu</button>\r\n      <a ng-if=\"!(wizard.model.signature.personalId == null || wizard.model.signature.method == null)\" ng-href=\"{{wizard.vismaSignUrl}}\" target=\"_top\" class=\"btn btn-primary\">Tunnistaudu</a>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/worker/contract-worker.html\",`﻿<form name=\"contractForm\">\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = contractForm.$valid && !wizard.model.signature.personalId && !wizard.model.signature.method}}</span>\r\n  <div ng-controller=\"SignatureController as sign\">\r\n\r\n    <h3 sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.title\"></h3>\r\n    <p sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.signatureText\"></p>\r\n    <p sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.signatureText2\"></p>\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.personalId\"></legend>\r\n      <div class=\"form-group\" style=\"max-width:150px;\">\r\n        <salaxy-input name=\"personalId\" label-type=\"plain\" type=\"text\" style=\"width:150px\" sxy-personal-id-fi ng-required=\"true\" placeholder=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.personalIdExample\" ng-model=\"wizard.model.signature.personalId\" sxy-personal-id-fi>\r\n      </div>\r\n      <div class=\"spacer-bottom\">\r\n        <input ng-init=\"wizard.model.signature.terms = false\" name=\"terms\" type=\"checkbox\" require=\"true\" ng-model=\"wizard.model.signature.terms\"></input>\r\n        <span style=\"margin-left: 5px;\" sxy-html=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.termsText.html\"></span> <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\"><span sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.termsText2\"></span></a>\r\n        <span sxy-html=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.termsText3.html\"></span>\r\n      </div>\r\n    </fieldset>\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.chooseBank\"></legend>\r\n      <div id=\"bankButtonRow\">\r\n        <label ng-repeat=\"signMethod in sign.getMethods('telia')\" ng-model=\"wizard.model.signature.method\" class=\"col-sm-2 col-xs-4 btn-bank\" uib-btn-radio=\"signMethod.value\" class=\"btn btn-default\" aria-label=\"{{signMethod.name}}\">\r\n            <div class=\"btn-bank-inner\"> <img ng-src=\"{{signMethod.img}}\"/><span class=\"bank-title\"> {{signMethod.title}}</span></div>\r\n        </label>\r\n      </div>\r\n    </fieldset>\r\n    <p sxy-html=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.privacyPolicy.html\"></p>\r\n\r\n    <p><span sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.savePdfText\"></span> <a ng-href=\"{{ wizard.getPdfPreviewAddress() }}\" target=\"_blank\"><span sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.savePdfLink\"></span></a>\r\n      <span sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepContract.savePdfText2\"></span>\r\n    </p>\r\n\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/worker/contractButtons.html\",`﻿<button ng-click=\"wizard.goPrevious()\" ng-disabled=\"!wizard.canGoPrevious\" class=\"btn btn-default\">{{'SALAXY.UI_Terms.previous' | sxyTranslate}}</button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n<button ng-if=\"wizard.model.signature.personalId == null || wizard.model.signature.method == null || wizard.model.signature.terms == false\" ng-disabled=\"true\" class=\"btn btn-primary\">{{'SALAXY.NG1.WorkerOnboardingComponent.signBtn' | sxyTranslate}}</button>\r\n<a ng-if=\"!(wizard.model.signature.personalId == null || wizard.model.signature.method == null || wizard.model.signature.terms == false)\" ng-href=\"{{wizard.vismaSignUrl}}\" target=\"_top\" class=\"btn btn-primary\">{{'SALAXY.NG1.WorkerOnboardingComponent.signBtn' | sxyTranslate}}</a>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/worker/firstPageButtons.html\",`﻿<button class=\"btn btn-default\" ng-click=\"$close('cancel')\">{{'SALAXY.UI_Terms.backToFront' | sxyTranslate}}</button>\r\n<div salaxy-loader class=\"spinner\">\r\n  <div class=\"bounce1\"></div>\r\n  <div class=\"bounce2\"></div>\r\n  <div class=\"bounce3\"></div>\r\n</div>\r\n\r\n<button ng-click=\"wizard.goNext()\" class=\"btn btn-primary\" ng-disabled=\"!wizard.canGoNext\">{{'SALAXY.UI_Terms.next' | sxyTranslate}}</button>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/worker/index.html\",`<div ng-controller=\"SessionController as sessionCtrl\" class=\"worker-onboarding-wizard\">\r\n  <div ng-controller=\"WorkerOnboardingController as wizard\">\r\n    <div ng-controller=\"NaviController as $naviCtrl\">\r\n      <div ng-if=\"!$naviCtrl.showFullPageLoader\">\r\n        <div class=\"modal-header\">\r\n          <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n          <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.title\"></h2>\r\n\r\n          <img src=\"https://cdn.salaxy.com/img/palkkaus/logo/palkkaus-www-logo-white-border.png\" class=\"img-responsive hidden-xs modal-logo\" />\r\n        </div>\r\n        <div class=\"modal-body salaxy-wizard\">\r\n          <div class=\"visible-xs visible-sm\">\r\n            <h4><span sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.step\"></span> {{wizard.currentStep.number}}/{{wizard.steps.length}}</h4>\r\n\r\n          </div>\r\n          <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n                            <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n                        </span>\r\n              <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n                <span class=\"salaxy-avatar\">\r\n                                <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n                            </span>\r\n              </a>\r\n            </div>\r\n          </div>\r\n          <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n            <div ng-class=\"wizard.style.colWidthClass\" ng-repeat=\"step in wizard.steps\">\r\n              <span>{{ step.title | sxyTranslate}}</span>\r\n            </div>\r\n          </div>\r\n\r\n          <ng-include src=\"wizard.currentStep.view\"></ng-include>\r\n\r\n\r\n        </div>\r\n        <div class=\"modal-footer\">\r\n          <ng-include style=\"display: flex; flex-direction: row;justify-content: space-between; align-items: center;\" src=\"wizard.currentStep.buttonsView\"></ng-include>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/onboarding/worker/user-info.html\",`﻿<form name=\"currentForm\">\r\n  <!-- Hidden ariable formDataValidity to use in controller -->\r\n  <span class=\"hidden\">{{ wizard.formDataValidity = currentForm.$valid }}</span>\r\n\r\n  <br/>\r\n  <p sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.registerText\"></p>\r\n  <br>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-6\">\r\n      <div class=\"form-horizontal\">\r\n        <salaxy-input label=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.firstName\" name=\"Etunimi\" ng-model=\"wizard.model.person.firstName\" ng-required=\"true\"></salaxy-input>\r\n        <salaxy-input label=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.lastName\" name=\"Sukunimi\" ng-model=\"wizard.model.person.lastName\" ng-required=\"true\"></salaxy-input>\r\n        <salaxy-input label=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.email\" name=\"Sahkoposti\" ng-model=\"wizard.model.person.contact.email\" ng-required=\"true\" sxy-email></salaxy-input>\r\n\r\n      </div>\r\n    </div>\r\n    <div class=\"col-md-6\">\r\n      <div class=\"row language-selection spacer-bottom\" ng-controller=\"SessionController as $session\">\r\n        <div class=\"col-xs-4 control-label\"><strong class=\"\" sxy-text=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.language\" ps=\":\"></strong></div>\r\n\r\n        <div class=\"col-xs-8\">\r\n          <div class=\"btn-group btn-group-sm pull-right\" role=\"group\">\r\n            <button class=\"btn btn-default\" ng-class=\"{'active btn-primary' : $session.getLanguage() == 'fi'}\" ng-click=\"$session.setLanguage('fi'); wizard.model.person.language = 'fi'\">{{'SALAXY.ENUM.Language.fi.label' | sxyTranslate}}</button>\r\n            <button class=\"btn btn-default \" ng-class=\"{'active btn-primary' : $session.getLanguage() == 'en'}\" ng-click=\"$session.setLanguage('en'); wizard.model.person.language = 'en'\">{{'SALAXY.ENUM.Language.en.label' | sxyTranslate}}</button>\r\n            <button class=\"btn btn-default\" ng-class=\"{'active btn-primary' : $session.getLanguage() == 'sv'}\" ng-click=\"$session.setLanguage('sv'); wizard.model.person.language = 'sv'\">{{'SALAXY.ENUM.Language.sv.label' | sxyTranslate}}</button>\r\n          </div>\r\n        </div>\r\n\r\n      </div>\r\n      <div class=\"form-horizontal\">\r\n        <salaxy-input label=\"SALAXY.NG1.WorkerOnboardingComponent.stepUserInfo.phoneNumber\" name=\"Puhelinnumero\" ng-model=\"wizard.model.person.contact.telephone\" ng-required=\"true\" sxy-mobile-phone></salaxy-input>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/payment/cfa/EInvoice.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyEInvoiceLabel\" sxy-text=\"SALAXY.NG1.NewPaymentComponent.einvoice.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <p sxy-text=\"SALAXY.NG1.NewPaymentComponent.einvoice.description\"></p>\r\n  <form name=\"address\" class=\"form-horizontal\">\r\n    <salaxy-form-group name=\"eInvoiceReceiver\" label=\"SALAXY.NG1.PaymentSettingsComponent.einvoice.invoiceAddress\">\r\n      <div class=\"input-group\">\r\n        <input required class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"eInvoiceReceiver\" name=\"eInvoiceReceiver\" ng-disabled=\"true\" ng-model=\"$ctrl.current.eInvoiceReceiver\" >\r\n        <span class=\"input-group-btn\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.logic.selectEInvoiceAddress($ctrl.current)\" sxy-text=\"Valitse...\"></button>\r\n        </span>\r\n      </div>\r\n    </salaxy-form-group>\r\n    <salaxy-input require=\"true\" disabled=\"true\" name=\"intermediator\" ng-model=\"$ctrl.current.eInvoiceIntermediator\" label=\"SALAXY.NG1.NewPaymentComponent.einvoice.intermediatorLabel\"></salaxy-input>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer text-left\">\r\n  <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"!address.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n  <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/payment/cfa/Transfer.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyTransferLabel\" sxy-text=\"SALAXY.NG1.NewPaymentComponent.selection.creditTransferTitle\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"credit-transfer-container\">\r\n    <div class=\"text-right\">\r\n      <button type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.logic.print('sxyFullPrint')\" sxy-text=\"SALAXY.UI_Terms.print\"></button>\r\n      <button type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.logic.print('sxySecurePrint')\" sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.securePrint\"></button>\r\n    </div>\r\n    <salaxy-credit-transfer invoice=\"$ctrl.current\">\r\n      <message>\r\n        <p sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.mainContent\"></p>\r\n      </message>\r\n    </salaxy-credit-transfer>\r\n    <div class=\"payment-per-worker-container table-responsive\" ng-class=\"$ctrl.logic.printClass\">\r\n      <h4 sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.calcsBreakdown\"></h4>\r\n      <table>\r\n        <thead>\r\n          <tr>\r\n            <th class=\"align-bottom\" sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.worker\"></th>\r\n            <th class=\"right\"><strong sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.totalGrossSalary\"></strong></th>\r\n            <th class=\"right\"> <strong sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.payNow\"></strong></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr class=\"payment-per-worker\" ng-repeat=\"calc in $ctrl.logic.calculations\">\r\n            <td class=\"align-middle\"> {{calc.worker.avatar.sortableName}}</td>\r\n            <td class=\"right\">{{calc.result.totals.totalGrossSalary | currency}}</td>\r\n            <td class=\"right\">\r\n              {{calc.result.employerCalc.totalPayment| currency}}\r\n            </td>\r\n          </tr>\r\n          <tr class=\"total\">\r\n            <td><strong sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.paymentPerWorkerTable.total\"></strong><br><span sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.paymentPerWorkerTable.palkkausFee\"></span></td>\r\n            <td class=\"right\">{{$ctrl.logic.totalResultCalculation.result.totals.totalGrossSalary | currency}}</td>\r\n            <td class=\"right\">\r\n              {{$ctrl.logic.totalResultCalculation.result.employerCalc.totalPayment | currency}}<br>{{$ctrl.logic.totalResultCalculation.result.employerCalc.palkkaus | currency}}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n\r\n    <div sxy-if-role=\"!household\" class=\"table-responsive\">\r\n      <h4 sxy-text=\"SALAXY.NG1.NewPaymentComponent.creditTransfer.paymentTable\"></h4>\r\n      <salaxy-calc-report apply-site-styles=\"true\" calc=\"$ctrl.logic.totalResultCalculation\" report-type=\"'paymentReport'\" template-name=\"'paymentTablesV2'\"></salaxy-calc-report>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer text-left\">\r\n  <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/payment/PaymentCancel.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyPaymentCancelDialogLabel\" sxy-text=\"SALAXY.NG1.PaymentCancelDialogComponent.paymentCancelled\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <p sxy-text=\"SALAXY.NG1.PaymentCancelDialogComponent.paymentCancelledBank\"></p>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/payment/PaymentConfirm.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyPaymentConfirmDialogLabel\" sxy-text=\"SALAXY.NG1.PaymentConfirmDialogComponent.paymentConfirmed\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <p sxy-text=\"SALAXY.NG1.PaymentConfirmDialogComponent.paymentConfirmedInfo\"></p>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/payroll/PayrollDetailsList.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <salaxy-payroll-details-select-list category=\"{{ $ctrl.logic.category || 'draft' }}\" mode=\"select\" selected-items=\"$ctrl.current\"></salaxy-payroll-details-select-list>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/payroll/PayrollList.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <salaxy-payroll-select-list category=\"{{ $ctrl.logic.category || 'draft' }}\" mode=\"select\" selected-items=\"$ctrl.current\"></salaxy-payroll-select-list>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/records/Record.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">{{ $ctrl.logic.title }}</h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <form class=\"form-horizontal\" name=\"record\" ng-readonly=\"$ctrl.logic.readOnly\">\r\n    <fieldset>\r\n      <salaxy-form-group ng-if=\"!$ctrl.logic.readOnly\" name=\"recordType\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.recordType\">\r\n        <div class=\"input-group\">\r\n          <input ng-model=\"$ctrl.current.record.recordType\" type=\"text\" class=\"form-control\">\r\n          <div class=\"input-group-btn\" uib-dropdown>\r\n            <button type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle><span class=\"caret\"></span></button>\r\n            <ul class=\"dropdown-menu dropdown-menu-right\" uib-dropdown-menu>\r\n              <li ng-repeat=\"recordType in $ctrl.logic.recordTypes\">\r\n                <a href=\"\" ng-click=\"$ctrl.current.record.recordType = recordType\">{{recordType}}</a>\r\n              </li>\r\n            </ul>\r\n          </div>\r\n        </div>\r\n      </salaxy-form-group>\r\n      <salaxy-input ng-if=\"$ctrl.logic.readOnly\" ng-model=\"$ctrl.current.record.recordType\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.recordType\" name=\"recordType\"></salaxy-input>\r\n      <salaxy-input ng-model=\"$ctrl.current.record.title\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.title\" name=\"title\"></salaxy-input>\r\n      <salaxy-textarea ng-model=\"$ctrl.current.record.text\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.text\" name=\"text\"></salaxy-textarea>\r\n      <salaxy-form-group name=\"attachments\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.attachments\">\r\n        <table>\r\n          <tr ng-repeat=\"attachment in $ctrl.current.record.attachments\">\r\n            <td><i class=\"fa {{ $ctrl.logic.getAttachmentIcon(attachment) }} text-primary pull-left\"></i> <a target=\"_blank\"\r\n                ng-href=\"{{$ctrl.logic.getAttachmentDownloadUrl(attachment)}}\">{{attachment.fileName}}</a></td>\r\n            <td class=\"text-right\">\r\n              <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-if=\"!$ctrl.logic.readOnly\" ng-click=\"$ctrl.current.record.attachments.splice($index, 1)\"><i class=\"fa fa-trash-o\"\r\n                  title=\"{{'SALAXY.UI_Terms.removeAttachment' | sxyTranslate}}\"></i></button>\r\n            </td>\r\n          </tr>\r\n          <tr>\r\n            <td></td>\r\n            <td class=\"text-right\">\r\n              <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.logic.readOnly\" ngf-select=\"$ctrl.logic.uploadAttachments($files, $ctrl.current.record.attachments)\"\r\n                ngf-multiple=\"true\" ngf-max-size=\"10MB\"><i class=\"fa fa-paperclip\" title=\"{{'SALAXY.UI_Terms.addAttachment' | sxyTranslate}}\"></i></button>\r\n            </td>\r\n          </tr>\r\n        </table>\r\n      </salaxy-form-group>\r\n      <salaxy-datepicker-popup ng-model=\"$ctrl.current.record.startDate\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.startDate\" name=\"startDate\"></salaxy-datepicker-popup>\r\n    </fieldset>\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.records.badge\"></legend>\r\n      <salaxy-input label=\"SALAXY.NG1.WorkFlowEventEditComponent.description\" name=\"message\" ng-model=\"$ctrl.current.wfEvent.message\"></salaxy-input>\r\n      <salaxy-input-enum type=\"select\" enum=\"BootstrapStyle\" label=\"SALAXY.NG1.WorkFlowEventEditComponent.ui\" name=\"ui\" require=\"$ctrl.current.wfEvent.message\"\r\n        ng-model=\"$ctrl.current.wfEvent.ui\"></salaxy-input-enum>\r\n    </fieldset>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"reset\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-disabled=\"!record.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/report/AccountingReport.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AccountingReportComponent.accountingReports\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <salaxy-accounting-report-tools any-expanded=\"$reportRows.anyExpanded\" on-expand-change=\"$reportRows.expand(close)\" on-target-change=\"$ctrl.data.loadCurrent(targetId)\"  reader=\"$ctrl.data.reader\"></salaxy-accounting-report-tools>\r\n  <salaxy-accounting-report-rows ng-show=\"!$ctrl.data.isLoading\" ng-ref=\"$reportRows\" data=\"$ctrl.data.accountingData\"></salaxy-accounting-report-rows>\r\n  <salaxy-spinner ng-if=\"$ctrl.data.isLoading\" full-screen=\"false\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.NG1.AccountingReportComponent.loadingReport\"></salaxy-spinner>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/report/SummaryReport.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.SummaryReportComponent.summaryReport\"></h2>\r\n</div>\r\n<div class=\"modal-body \">\r\n  <salaxy-spinner ng-if=\"$ctrl.data.isLoading\" full-screen=\"false\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.NG1.SummaryReportComponent.loadingReport\"></salaxy-spinner>\r\n  <salaxy-summary-report ng-if=\"!$ctrl.data.isLoading\" data=\"$ctrl.data.summaryReportData\"></salaxy-summary-report>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/report/WorkerSummaryReport.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.SummaryReportComponent.summaryReport\"></h2>\r\n</div>\r\n<div class=\"modal-body \">\r\n  <salaxy-spinner ng-if=\"$ctrl.data.isLoading\" full-screen=\"false\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.NG1.SummaryReportComponent.loadingReport\"></salaxy-spinner>\r\n  <salaxy-worker-summary-report ng-if=\"!$ctrl.data.isLoading\" data=\"$ctrl.data.workerSummaryReportData\"></salaxy-worker-summary-report>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/settings/AccountantSelection.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.heading\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n\r\n  <div ng-if=\"!$ctrl.logic.selected\" class=\"row\">\r\n    <div class=\"col-xs-12\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.accountantType\"></legend>\r\n        <salaxy-input-enum ng-model=\"$ctrl.logic.type\" type=\"radio\" name=\"logicType\" label=\"SALAXY.NG1.AccountantSelectionComponent.companyOrPerson\" options=\"{ \r\n                          company: ('SALAXY.NG1.AccountantSelectionComponent.companyEnum' | sxyTranslate),\r\n                          none: ('SALAXY.NG1.AccountantSelectionComponent.personEnum' | sxyTranslate)}\">\r\n        </salaxy-input-enum>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n\r\n  <form name=\"personAccountantForm\" class=\"form-horizontal\">\r\n    <div ng-if=\"$ctrl.logic.type == 'none'\" class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <fieldset>\r\n          <salaxy-input name=\"firstName\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.firstName\" ng-model=\"$ctrl.current.info.avatar.firstName\"></salaxy-input>\r\n          <salaxy-input name=\"lastName\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.lastName\"  ng-model=\"$ctrl.current.info.avatar.lastName\"></salaxy-input>\r\n          <salaxy-input name=\"email\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.email\"  sxy-email ng-model=\"$ctrl.current.info.email\"></salaxy-input>\r\n          <salaxy-input name=\"telephone\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.telephone\"  sxy-mobile-phone ng-model=\"$ctrl.current.info.telephone\"></salaxy-input>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n  </form>\r\n  <div ng-if=\"!$ctrl.logic.selected && $ctrl.logic.type == 'company'\" class=\"row\">\r\n    <div class=\"col-xs-12\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.searchAccountingFirm\"></legend>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.logic.selected && $ctrl.logic.type == 'company'\" class=\"table-responsive\" style=\"max-height: calc(100vh - 200px)\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.name\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.officialId\"></th>\r\n          <th class=\"right\">\r\n            <form name=\"searchForm\">\r\n              <salaxy-form-group name=\"search\" label-type=\"plain\">\r\n                <div class=\"input-group\">\r\n                  <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"searchAccountant\" name=\"searchAccountant\" ng-model=\"$ctrl.logic.searchInput\" require=\"true\" ng-minlength=\"3\">\r\n                  <span class=\"input-group-btn\">\r\n                    <button type=\"submit\" ng-disabled=\"!searchForm.$valid\" class=\"btn btn-default\"\r\n                      ng-click=\"$ctrl.logic.search($ctrl.logic.searchInput)\"><span ng-show=\"$ctrl.logic.isLoading\"><i\r\n                          class=\"fa fa-refresh fa-spin fa-fw\"></i></span><span ng-show=\"!$ctrl.logic.isLoading\"><i class=\"fa fa-search\"></i></span></button>\r\n                  </span>\r\n                </div>\r\n            </form>\r\n            </salaxy-form-group>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.logic.searchResult\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name  middle\">\r\n            <strong>{{row.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"td-name  middle\">\r\n            <strong>{{row.officialId}}</strong><br />\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm btn-default\" type=\"button\" ng-click=\"$ctrl.logic.select($ctrl.current, row)\">\r\n              {{ 'SALAXY.UI_Terms.select' | sxyTranslate }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.logic.searchResult.length == 0\">\r\n          <td colspan=\"4\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.noSearchResult\"></td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <form name=\"companyAccountantForm\" class=\"form-horizontal\">\r\n    <div ng-if=\"$ctrl.logic.selected && $ctrl.logic.type == 'company'\">\r\n      <div class=\"container-fixed salaxy-component salaxy-accoountant-info\">\r\n        <button ng-if=\"$ctrl.current.type != 'primaryPartner'\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.logic.reset($ctrl.current)\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.search\"></button>\r\n        <div class=\"table\">\r\n          <table>\r\n            <tr>\r\n              <td>\r\n                <salaxy-avatar style=\"font-size: 102px; margin-right: 40px;\" avatar=\"$ctrl.current.info.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td ng-if=\"$ctrl.current.type != 'primaryPartner'\">\r\n                <p class=\"lead\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.notPrimaryPartner.lead\" ps=\".\"></p>\r\n\r\n                <div class=\"input-info\">\r\n                  <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n                  <p ng-if=\"$ctrl.current.info.avatar.id\" class=\"input-info-text with-icon\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.notPrimaryPartner.partnerInfo\" ps=\".\"></p>\r\n                  <p ng-if=\"!$ctrl.current.info.avatar.id\" class=\"input-info-text with-icon\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.notPrimaryPartner.notPartnerInfo\" ps=\".\"></p>\r\n                </div>\r\n              </td>\r\n              <td ng-if=\"$ctrl.current.type == 'primaryPartner'\">\r\n                <p class=\"lead\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.primaryPartner.lead\" ps=\".\"></p>\r\n\r\n                <div class=\"input-info\">\r\n                  <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n                  <p ng-if=\"$ctrl.current.info.avatar.id\" class=\"input-info-text with-icon\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.primaryPartner.partnerInfo\" ps=\".\"></p>\r\n                </div>\r\n              </td>\r\n            </tr>\r\n          </table>\r\n        </div>\r\n        <div class=\"table-responsive\">\r\n          <table class=\"table\">\r\n            <tr>\r\n              <th sxy-text=\"Nimi\" ps=\":\"></th>\r\n              <td>{{ $ctrl.current.info.avatar.displayName}}</td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"Y-tunnus\" ps=\":\"></th>\r\n              <td>{{ $ctrl.current.info.officialId}}</td>\r\n            </tr>\r\n            <tr ng-if=\"!$ctrl.current.info.avatar.id\">\r\n              <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.accountantPermissions\" ps=\":\"></th>\r\n              <td>\r\n                <salaxy-input-enum disabled=\"true\" ng-model=\"$ctrl.current.type\" type=\"radio\" name=\"partnerType\" label=\"\" label-type=\"plain\" options=\"{ \r\n                unlinkedPrimaryPartner: ('SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.unlinkedPrimaryPartnerEnum' | sxyTranslate),\r\n                unlinkedAccountingOnly: ('SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.unlinkedAccountingOnlyEnum' | sxyTranslate)}\">\r\n                </salaxy-input-enum>\r\n              </td>\r\n            </tr>\r\n            <tr ng-if=\"$ctrl.current.info.avatar.id\">\r\n              <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.accountantPermissions\" ps=\":\"></th>\r\n              <td>\r\n                <salaxy-input-enum  ng-if=\"$ctrl.current.type != 'primaryPartner'\" ng-model=\"$ctrl.current.type\" type=\"radio\" name=\"partnerType\" label=\"\" label-type=\"plain\" options=\"{ \r\n                pendingPrimaryPartner: ('SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.pendingPrimaryPartnerEnum' | sxyTranslate),\r\n                unlinkedAccountingOnly: ('SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.unlinkedAccountingOnlyEnum' | sxyTranslate)}\">\r\n                </salaxy-input-enum>\r\n                <salaxy-input-enum ng-if=\"$ctrl.current.type == 'primaryPartner'\" read-only=\"true\" ng-model=\"$ctrl.current.type\" type=\"radio\" name=\"partnerType\" label=\"\" label-type=\"plain\" options=\"{ \r\n                  primaryPartner: ('SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.primaryPartnerEnum' | sxyTranslate)}\">\r\n                </salaxy-input-enum>\r\n              </td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.email\" ps=\":\"></th>\r\n              <td>\r\n                <salaxy-input name=\"email\" label=\"\"\r\n                  label-type=\"plain\" sxy-email ng-model=\"$ctrl.current.info.email\"></salaxy-input>\r\n              </td>\r\n            </tr>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.telephone\" ps=\":\"></th>\r\n              <td>\r\n                <salaxy-input name=\"telephone\" label=\"\"\r\n                  label-type=\"plain\" sxy-mobile-phone ng-model=\"$ctrl.current.info.telephone\"></salaxy-input>\r\n              </td>\r\n            </tr>\r\n          </table>\r\n        </div>\r\n\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>\r\n\r\n<div class=\"modal-footer text-right\">\r\n  <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.current.type != 'primaryPartner'\" class=\"btn btn-danger\" ng-click=\"$close('remove')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.current.type == 'primaryPartner' && !$ctrl.logic.removalDisabled\" class=\"btn btn-danger\" ng-click=\"$close('removePrimaryPartner')\" sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.deletePrimaryPartner\"></button>\r\n  <button type=\"button\" ng-disabled=\"(!$ctrl.logic.selected && $ctrl.logic.type == 'company') || personAccountantForm.$invalid || companyAccountantForm.$invalid\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/settings/BrandSelection.html\",`<form name=\"brandForm\" class=\"form-horizontal\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.BrandSelectionComponent.title\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <salaxy-odata-table \r\n        url=\"/v03/api/settings/brands\" \r\n        template-url=\"salaxy-components/odata/lists/BrandList.html\" \r\n        options=\"{ $filter: 'data/skin ne null and data/skin ne \\\\'\\\\'' }\"\r\n        selected-items=\"selectedItems\"\r\n        on-list-select=\"($ctrl.current.brand = value == true ? item : null);( selectedItems = value == true? [item ]: []);\">\r\n    </salaxy-odata-table>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('set-default')\" sxy-text=\"SALAXY.NG1.BrandSelectionComponent.useDefaultStyle\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current.brand\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/settings/PaymentChannel.html\",`<form name=\"periodForm\" class=\"form-horizontal\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{ $ctrl.logic.channelAvatar.displayName }}, asetukset</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"form-horizontal\">\r\n      <p class=\"lead\">\r\n        <strong>{{ $ctrl.logic.channelAvatar.displayName }}</strong>: {{ $ctrl.logic.channelAvatar.description }}\r\n      </p>\r\n      <div ng-switch=\"$ctrl.current.id\">\r\n        <fieldset ng-switch-when=\"palkkausCfaFinvoice|palkkausEcfaFinvoice\"  ng-switch-when-separator=\"|\">\r\n          <legend sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaFinvoice.legend\"></legend>\r\n          <salaxy-form-group name=\"eInvoiceReceiver\" label=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaFinvoice.eInvoiceAddress\">\r\n            <div class=\"input-group\">\r\n              <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"eInvoiceReceiver\" name=\"eInvoiceReceiver\" ng-disabled=\"true\" ng-model=\"$ctrl.current.invoiceSettings.eInvoiceReceiver\">\r\n              <span class=\"input-group-btn\">\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.logic.selectEInvoiceAddress($ctrl.current.invoiceSettings)\" sxy-text=\"SALAXY.UI_Terms.choose\"></button>\r\n              </span>\r\n            </div>\r\n          </salaxy-form-group>\r\n          <salaxy-input disabled=\"true\" name=\"intermediator\" ng-model=\"$ctrl.current.invoiceSettings.eInvoiceIntermediator\" label=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaFinvoice.intermediator\"></salaxy-input>\r\n        </fieldset>\r\n        <fieldset ng-switch-when=\"palkkausCfaPaytrail|palkkausEcfaPaytrail|palkkausCfaReference|palkkausEcfaReference|palkkausCfaFinvoice|palkkausEcfaFinvoice|palkkausCfaTest\" ng-switch-when-separator=\"|\">\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaPaytrail.legend\"></legend>\r\n            <p sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaPaytrail.infoText\"></p>\r\n            <salaxy-input-boolean type=\"checkbox\" name=\"isTaxAndSocialSecuritySelfHandling\" label-type=\"plain\" label-true=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaPaytrail.isTaxAndSocialSecuritySelfHandling\" ng-model=\"$ctrl.current.customerFundsSettings.isTaxAndSocialSecuritySelfHandling\"></salaxy-input-boolean>\r\n            <salaxy-input-boolean type=\"checkbox\" name=\"isWorkerSelfHandling\" label-type=\"plain\" label-true=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaPaytrail.isWorkerSelfHandling\" ng-model=\"$ctrl.current.customerFundsSettings.isWorkerSelfHandling\"></salaxy-input-boolean>\r\n            <div>&nbsp;</div>\r\n            <div class=\"alert alert-warning\" sxy-html=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausCfaPaytrail.alert.html\"></div>\r\n          </fieldset>\r\n        </fieldset>\r\n        <fieldset ng-switch-when=\"palkkausManual\">\r\n          <legend sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausManual.legend\"></legend>\r\n          <salaxy-input name=\"ibanNumber\" label=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausManual.ibanNumber\" sxy-iban ng-model=\"$ctrl.current.invoiceSettings.ibanNumber\"></salaxy-input>\r\n          <salaxy-input name=\"sepaBankPartyId\" label=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausManual.sepaBankPartyId\" ng-model=\"$ctrl.current.invoiceSettings.sepaBankPartyId\"></salaxy-input>\r\n        </fieldset>\r\n        <!--fieldset ng-switch-when=\"palkkausInvoices\">\r\n          <legend sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausInvoices.legend\"></legend>\r\n          <salaxy-input name=\"creditCard\" disabled=\"true\" label=\"SALAXY.NG1.PaymentChannelDialogComponent.palkkausInvoices.creditCard\" ng-model=\"dummy\"></salaxy-input     \r\n        </fieldset-->\r\n        <fieldset ng-switch-default>\r\n          <div class=\"alert alert-info\" sxy-text=\"SALAXY.NG1.PaymentChannelDialogComponent.default.info\"></div>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"button\" ng-if=\"$ctrl.current.settings.isEnabled && $ctrl.current.settings.isAvailable\" class=\"btn btn-danger pull-left\" ng-disabled=\"$ctrl.current.isReadOnly\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.unenable\"></button>\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"button\" ng-if=\"!$ctrl.current.isDefault  && $ctrl.current.settings.isAvailable\" class=\"btn btn-default\" ng-disabled=\"$ctrl.current.isReadOnly && !$ctrl.current.settings.isEnabled\" ng-click=\"$close('set-default')\" sxy-text=\"SALAXY.UI_Terms.setDefault\"></button>\r\n    <button type=\"submit\" ng-if=\"$ctrl.current.settings.isEnabled  && $ctrl.current.settings.isAvailable\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    <button type=\"button\" ng-if=\"!$ctrl.current.settings.isEnabled  && $ctrl.current.settings.isAvailable\" class=\"btn btn-primary\" ng-disabled=\"$ctrl.current.isReadOnly\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.enable\"></button>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/modals/settings/UiTranslator.html\",`\r\n<div class=\"modal-ui-translation\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-ui-translator></salaxy-ui-translator>\r\n    <div>\r\n      <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/Alert.html\",`<div class=\"modal-header\">\r\n  <h3 class=\"modal-title\" id=\"modal-title\">{{$ctrl.data.heading | sxyTranslate}}</h3>\r\n</div>\r\n<div ng-if=\"$ctrl.data.text\" class=\"modal-body salaxy-component\" id=\"modal-body\">\r\n  <p class=\"pre-wrap\">{{$ctrl.data.text | sxyTranslate}}</p>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button class=\"btn btn-primary\" type=\"button\" ng-click=\"$close('ok')\">{{$ctrl.data.okText | sxyTranslate}}</button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/Confirm.html\",`<div class=\"modal-header\">\r\n  <h3 class=\"modal-title\" id=\"modal-title\">{{$ctrl.data.heading | sxyTranslate}}</h3>\r\n</div>\r\n<div ng-if=\"$ctrl.data.text || $ctrl.data.html\" class=\"modal-body\" id=\"modal-body\">\r\n  <p ng-if=\"!$ctrl.data.html\" class=\"pre-wrap\">{{$ctrl.data.text | sxyTranslate}}</p>\r\n  <div ng-if=\"$ctrl.data.html\" sxy-html=\"{{$ctrl.data.html}}\"></div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button class=\"btn btn-default\" type=\"button\" ng-click=\"$close(false)\">{{$ctrl.data.cancelText | sxyTranslate}}</button>\r\n  <button class=\"btn btn-primary\" type=\"button\" ng-click=\"$close(true)\">{{$ctrl.data.okText | sxyTranslate}}</button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/DialogWindow.html\",`<div id=\"salaxyDialog\" class=\"salaxy-component salaxy-dialog modal-dialog {{size ? 'modal-' + size : ''}}\" aria-labelledby=\"salaxyDialogLabel\" role=\"dialog\">\r\n        <div class=\"modal-content\" role=\"document\" uib-modal-transclude></div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/DocumentPreviewWindow.html\",`<div class=\"salaxy-component container-document-print salaxy-rpt\" role=\"dialog\">\r\n    <div class=\"document-preview\" id=\"document-preview\">\r\n        <div style=\"height:auto;min-height:277mm\" class=\"modal-content document a4portrait\" role=\"document\" uib-modal-transclude></div>\r\n    </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/modals/ui/Download.html\",`<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"sxy-spinner\" ng-if=\"!$ctrl.data.isReady\">\r\n      <svg class=\"sxy-spinner-bg\" viewBox=\"0 0 64 64\"><circle cx=\"32\" cy=\"32\" r=\"26\"></circle></svg>\r\n      <svg class=\"sxy-spinner-spin\" viewBox=\"0 0 64 64\">\r\n          <circle transform=\"translate(32,32)\" r=\"26\"></circle>\r\n      </svg>\r\n  </div>\r\n  \r\n  <div style=\"text-align: center;\">\r\n      <h3 ng-if=\"!$ctrl.data.isReady\" >{{$ctrl.data.waitHeading | sxyTranslate}}</h3>\r\n      <h3 ng-if=\"$ctrl.data.isReady\" >{{$ctrl.data.readyHeading | sxyTranslate}}</h3>\r\n      <p  ng-if=\"!$ctrl.data.isReady\" style=\"white-space: pre;\">{{$ctrl.data.waitText | sxyTranslate}}</p>\r\n      <p ng-if=\"$ctrl.data.isReady\">\r\n        {{$ctrl.data.readyText | sxyTranslate}} \r\n        <a ng-if=\"$ctrl.data.target\" ng-click=\"$close('ok')\" ng-href=\"{{$ctrl.data.url}}\" target=\"{{$ctrl.data.target}}\" >{{$ctrl.data.openText | sxyTranslate}}</a>\r\n        <a ng-if=\"!$ctrl.data.target\" ng-click=\"$close('ok')\" ng-href=\"{{$ctrl.data.url}}\" >{{$ctrl.data.openText | sxyTranslate}}</a>\r\n      </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/Loading.html\",`<div class=\"modal-body\" id=\"modal-body\" style=\"text-align:center;\">\r\n  <div class=\"sxy-spinner\">\r\n    <svg class=\"sxy-spinner-bg\" viewBox=\"0 0 64 64\"><circle cx=\"32\" cy=\"32\" r=\"26\"></circle></svg>\r\n    <svg class=\"sxy-spinner-spin\" viewBox=\"0 0 64 64\">\r\n            <circle transform=\"translate(32,32)\" r=\"26\"></circle>\r\n        </svg>\r\n  </div>\r\n  <div style=\"text-align: center;\">\r\n    <h3 ng-if=\"$ctrl.data.heading\">{{$ctrl.data.heading | sxyTranslate}}</h3>\r\n    <p class=\"pre-wrap\" ng-if=\"$ctrl.data.text\">{{$ctrl.data.text | sxyTranslate}}</p>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/ui/SelectListItem.html\",`<div class=\"modal-worker-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title | sxyTranslate}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <p ng-if=\"$ctrl.logic.infoHtml\" sxy-html=\"{{$ctrl.logic.infoHtml}}\"></p>\r\n    <div class=\"table-responsive\" style=\"max-height: calc(100vh - 300px)\">\r\n      <salaxy-odata-table\r\n        template-url=\"salaxy-components/odata/lists/SelectListItem.html\"\r\n        selected-items=\"$ctrl.current\" on-list-select=\"$close('ok')\"\r\n        crud-controller=\"DatasetsCrudController as $crud\"></salaxy-odata-table>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\">{{$ctrl.logic.okButtonText ? ($ctrl.logic.okButtonText | sxyTranslate) : ('SALAXY.UI_Terms.save' |\r\n        sxyTranslate)}}</button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/worker/taxcard-income-log.html\",`<div class=\"modal-taxcard-new\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addPaidSalaries\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <div class=\"alert alert-info\" ng-if=\"$ctrl.$incomeLog.hasDiff\">\r\n      <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addSalaries\"></button>\r\n      <span sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addSalariesToTaxCard\" params=\"{validity: ($ctrl.current.card.validity | sxyDateRange)}\">\r\n      </span>\r\n     \r\n    </div>\r\n    <salaxy-taxcard-income-log parent=\"$ctrl.current\" editable=\"$ctrl.logic.editable\" ng-ref=\"$ctrl.$incomeLog\"></salaxy-taxcard-income-log>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addSalaries\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/worker/taxcard-min-percent.html\",`<div class=\"modal-taxcard-min-percent\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardMinPercent.minimumPercent\"></h2>\r\n  </div>\r\n  <div class=\"modal-body form-horizontal\">\r\n    <p class=\"lead\" sxy-html=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardMinPercent.lead.html\"></p>\r\n    <p sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardMinPercent.biggerTaxPercentThanInTaxCard\"></p>\r\n    <p sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardMinPercent.taxPercentMinimum\"></p>\r\n    <salaxy-input-number name=\"taxPercentMin\" ng-model=\"$ctrl.current.taxPercentMin\" label=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardMinPercent.minimumPercent\"></salaxy-input-number>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button class=\"btn btn-primary pull-right\" type=\"button\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    <button class=\"btn btn-default\" type=\"button\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/worker/taxcard-new.html\",`<div class=\"modal-taxcard-new\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardNew.addTaxCard\"></h2>\r\n  </div>\r\n  <div style=\"min-height: 440px;\" class=\"modal-body\">\r\n    <salaxy-taxcard-manual-edit ng-ref=\"$edit\" current=\"$ctrl.current\"></salaxy-taxcard-manual-edit>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" ng-disabled=\"!$edit.isFormValid\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/workflow/CalendarEventEdit.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyWorkflowEventEditTitle\">\r\n    <i class=\"fa fa-calendar fa-lg\" aria-hidden=\"true\" style=\"padding-right: 20px\"></i> {{ $ctrl.logic.title | sxyTranslate }}\r\n  </h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <form name=\"frmEvent\" class=\"form-horizontal\">\r\n    <salaxy-calendar-event-details ng-ref=\"$ctrl.details\" ng-if=\"$ctrl.logic.isSimplified\" model=\"$ctrl.current\" template-url=\"salaxy-components/workflow/CalendarEventDetails-simplified.html\"></salaxy-calendar-event-details>\r\n    <salaxy-calendar-event-details ng-if=\"!$ctrl.logic.isSimplified\" model=\"$ctrl.current\"></salaxy-calendar-event-details>\r\n  </form>\r\n</div>\r\n<!--\r\n<div class=\"modal-footer\">\r\n  <button class=\"btn btn-danger pull-left\" ng-disabled=\"!$ctrl.current.id\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n  <button class=\"btn btn-default\" ng-click=\"$dismiss()\" sxy-text=\"{{ $ctrl.logic.cancelText }}\"></button>\r\n  <button class=\"btn btn-primary\" ng-disabled=\"!frmEvent.$valid\" ng-click=\"$close('ok')\" sxy-text=\"{{ $ctrl.logic.okText }}\"></button>\r\n</div>\r\n-->\r\n<div class=\"modal-footer\">\r\n  <button ng-if=\"$ctrl.details.step &lt; 2\" ng-click=\"$close('cancel')\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"$ctrl.details.step >= 2\" ng-click=\"$ctrl.details.goPrevious()\" ng-disabled=\"!$ctrl.details.canGoPrevious\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n  <button ng-if=\"$ctrl.details.step &lt; $ctrl.details.steps.length\" ng-click=\"$ctrl.details.goNext()\" ng-disabled=\"!$ctrl.details.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n  <button ng-if=\"$ctrl.details.step == $ctrl.details.steps.length\" ng-click=\"$close('ok')\" class=\"btn btn-primary\" xx-disabled=\"!$ctrl.details.formDataValidity\" sxy-text=\"SALAXY.NG1.CalendarEventEditComponent.setTimingsAndCreatePayrolls\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/workflow/UsecaseInfo.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">\r\n    <i ng-if=\"$ctrl.current.icon[0] == 'f'\" class=\"fa fa-lg\" ng-class=\"$ctrl.current.icon\" aria-hidden=\"true\" style=\"padding-right: 20px\"></i>\r\n    Käyttötapaus: {{ $ctrl.current.label || $ctrl.logic.objUsecase.label || \"Ei käyttötapausta\" }}\r\n  </h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <p class=\"lead\">{{ $ctrl.current.description || $ctrl.logic.objUsecase.description }}</p>\r\n  <p><code>{{ $ctrl.logic.objUsecase.uri }}</code></p>\r\n  <div class=\"alert alert-danger\" ng-if=\"!$ctrl.current\">\r\n    <strong>Ei käyttötapausta!</strong>\r\n    Tällä tietuella ei ole määritettyä käyttötapausta.\r\n  </div>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <fieldset>\r\n          <legend>Käyttötapaus</legend>\r\n          <div ng-if=\"!$ctrl.current.defaultView\">Ei räätälöityä näkymää.</div>\r\n          <div ng-if=\"$ctrl.current.defaultView\">\r\n            <p>Näkymät (<a href=\"{{ $ctrl.current.defaultView }}\" target=\"_blank\">linkki oletusnäkymään</a>)</p>\r\n            <ul>\r\n              <li ng-repeat=\"view in $ctrl.current.views\">\r\n                <strong>{{ view.label }}</strong> {{ view.description }}\r\n              </li>\r\n            </ul>\r\n          </div>\r\n          <!-- TODO: Show actions, schemas and workflowData / flow if necessary. -->\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"col-sm-6\">\r\n        <fieldset>\r\n          <legend>Objektiin tallennettu data</legend>\r\n          <salaxy-json-formatter json=\"$ctrl.logic.objUsecase.data\" key=\"'JSON'\"></salaxy-json-formatter>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n    <salaxy-json-formatter json=\"$ctrl.current\" key=\"'JSON'\" open=\"0\"></salaxy-json-formatter>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button class=\"btn btn-danger pull-left\" ng-if=\"$ctrl.logic.canDelete\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n  <button class=\"btn btn-default\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/workflow/WorkflowBadgeDetails.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyWorkflowBadgeDetailsTitle\" sxy-text=\"{{'SALAXY.ENUM.BootstrapStyle.' + $ctrl.current.event.ui + '.label' }}\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n\r\n  <form class=\"form-horizontal\" name=\"eventAndRecord\" ng-readonly=\"true\">\r\n    <salaxy-form-group name=\"time\" label=\"SALAXY.UI_Terms.updated\">\r\n      <span>{{$ctrl.current.event.time | sxyTime }}</span>\r\n    </salaxy-form-group>\r\n    <salaxy-input-enum type=\"select\" enum=\"BootstrapStyle\" label=\"SALAXY.NG1.WorkFlowEventEditComponent.ui\" name=\"ui\" ng-model=\"$ctrl.current.event.ui\"></salaxy-input-enum>\r\n    <salaxy-input label=\"SALAXY.NG1.WorkFlowEventEditComponent.description\" name=\"message\" require=\"true\" ng-model=\"$ctrl.current.event.message\"></salaxy-input>\r\n    <div ng-if=\"$ctrl.current.record\">\r\n      <salaxy-input ng-if=\"$ctrl.current.record.recordType\" ng-model=\"$ctrl.current.record.recordType\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.recordType\" name=\"recordType\"></salaxy-input>\r\n      <salaxy-input ng-if=\"$ctrl.current.record.title\" ng-model=\"$ctrl.current.record.title\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.title\" name=\"title\"></salaxy-input>\r\n      <salaxy-textarea ng-if=\"$ctrl.current.record.text\" ng-model=\"$ctrl.current.record.text\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.text\" name=\"text\"></salaxy-textarea>\r\n      <salaxy-form-group ng-if=\"$ctrl.current.record.attachments.length > 0\" name=\"attachments\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.attachments\">\r\n        <table>\r\n          <tr ng-repeat=\"attachment in $ctrl.current.record.attachments\">\r\n            <td><i class=\"fa {{ $ctrl.logic.getAttachmentIcon(attachment) }} text-primary pull-left\"></i> <a target=\"_blank\"\r\n                ng-href=\"{{$ctrl.logic.getAttachmentDownloadUrl(attachment)}}\">{{attachment.fileName}}</a></td>\r\n          </tr>\r\n        </table>\r\n      </salaxy-form-group>\r\n      <salaxy-datepicker-popup ng-if=\"$ctrl.current.record.startDate\" ng-model=\"$ctrl.current.record.startDate\" label=\"SALAXY.NG1.WorkerDetailsComponent.records.startDate\" name=\"startDate\"></salaxy-datepicker-popup>\r\n    </div>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/modals/workflow/WorkflowEventEdit.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" id=\"salaxyWorkflowEventEditTitle\" sxy-text=\"{{$ctrl.logic.title}}\"></h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <form name=\"event\" class=\"form-horizontal\" ng-readonly=\"$ctrl.logic.readOnly\">\r\n    <salaxy-input label=\"SALAXY.NG1.WorkFlowEventEditComponent.description\" name=\"message\" require=\"true\" ng-model=\"$ctrl.current.message\"></salaxy-input>\r\n    <salaxy-input-enum ng-if=\"$ctrl.logic.showUi\" type=\"select\" enum=\"BootstrapStyle\" label=\"SALAXY.NG1.WorkFlowEventEditComponent.ui\" name=\"ui\" require=\"true\" ng-model=\"$ctrl.current.ui\"></salaxy-input-enum>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"reset\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" ng-if=\"!$ctrl.logic.readOnly\" class=\"btn btn-primary\" ng-disabled=\"!event.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/odata/lists/AbsencePeriods.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <!-- TODO: This list is currenlty not in use - may be taken to use (or remove Q1/2020) -->\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n          <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n        </th>\r\n        <th sxy-orderby=\"causeCode\">{{ \"SALAXY.NG1.AbsencePeriodsComponent.headerAbsence\" | sxyTranslate }}</th>\r\n        <th sxy-orderby=\"period/start\" class=\"right\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.wholeAbsence\"></th>\r\n        <th sxy-orderby=\"period/daysCount\" class=\"right\" sxy-html=\"SALAXY.NG1.AbsencePeriodsComponent.periodDaysCount.html\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td class=\"align-middle td-avatar\">\r\n          <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"td-name middle\">\r\n          <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong><br /> {{ row.worker.description }}\r\n        </td>\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n          <strong>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</strong><br />\r\n          <div class=\"pull-left\" style=\"padding: 0px;\">\r\n            {{ row.isPaid ? ('SALAXY.NG1.AbsencePeriodsComponent.isPaid' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notPaid' | sxyTranslate) }}\r\n            <span ng-if=\"row.isPaid != row.isHolidayAccrual\"> {{ row.isHolidayAccrual ? ('SALAXY.NG1.AbsencePeriodsComponent.isAccrual' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notAccrual' | sxyTranslate) }}</span>\r\n          </div>\r\n          <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n            &nbsp;{{ row.notes }}\r\n          </div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong><br /> {{ row.period.start | date : 'dd.MM.' }}-{{ row.period.end | date : 'dd.MM.' }}\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ (row.isPaid ? 0 : row.period.daysCount) | sxyCount : \"day\" }}</strong><br />\r\n          <strong>{{ (row.isHolidayAccrual ? 0 : row.period.daysCount) | sxyCount : \"day\" }}</strong><br />\r\n        </td>\r\n        <td class=\"hidden-xxs middle\">\r\n          <button ng-click=\"$ctrl.data.$payrollCtrl.showEditWorkerDialog(row.worker.id, 'absences')\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Absences.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n          <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"startAt\" sxy-text=\"SALAXY.NG1.AbsencesComponent.first\"></span><br />\r\n          <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.AbsencesComponent.first\">Viimeisin</span>\r\n        </th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.AbsencesComponent.salaried\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.AbsencesComponent.unpaid\">Palkattomat</th>\r\n        <th>\r\n          <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\"></salaxy-input>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td class=\"align-middle td-avatar\">\r\n          <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"td-name middle\">\r\n          <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong><br /> {{ row.data.count }} {{'SALAXY.NG1.AbsencesComponent.absence' | sxyTranslate}}, {{ row.data.days }} {{'SALAXY.NG1.AbsencesComponent.day' | sxyTranslate}}<br />\r\n          <span ng-if=\"!row.data.employmentId\" class=\"label label-danger\" sxy-text=\"SALAXY.NG1.AbsencesComponent.error\"></span>\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.startAt | sxyDate }}<br /> {{ row.endAt | sxyDate }}\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.data.paidCount }} {{'SALAXY.NG1.AbsencesComponent.pce' | sxyTranslate}}<br /> {{ row.data.paidDays }} {{'SALAXY.NG1.AbsencesComponent.d' | sxyTranslate}}\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.data.unpaidCount }} {{'SALAXY.NG1.AbsencesComponent.pce' | sxyTranslate}}<br /> {{ row.data.unpaidDays }} {{'SALAXY.NG1.AbsencesComponent.d' | sxyTranslate}}\r\n        </td>\r\n        <td class=\"hidden-xxs middle\">\r\n          <button ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/AccountingReports.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n  <salaxy-accounting-report-tools ng-ref=\"$reportTools\" reader=\"$crud.selectionDataReader\"></salaxy-accounting-report-tools>\r\n\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-datepicker-popup name=\"year\" placeholder=\"{{'SALAXY.NG1.AccountingReportsComponent.year'}}\" format=\"yyyy\" ng-change=\"$crud.logicalDateChanged()\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$crud.logicalDate\" label-type=\"plain\"\r\n        required></salaxy-datepicker-popup>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"ownerInfo/avatar/displayName\">\r\n            <span>{{ 'SALAXY.NG1_Other.Roles.employer' | sxyTranslate }}</span>\r\n          </th>\r\n          <th>\r\n            <span sxy-orderby=\"logicalDate\">{{ 'SALAXY.NG1.AccountingReportsComponent.period' | sxyTranslate }}</span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\">{{ 'SALAXY.NG1.AccountingReportsComponent.salaries' | sxyTranslate }}</span><br />\r\n            <span sxy-orderby=\"payment\">{{ 'SALAXY.NG1.AccountingReportsComponent.payments' | sxyTranslate }}</span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span>{{ 'SALAXY.NG1.AccountingReportsComponent.salariesAlt' | sxyTranslate }}</span><br />\r\n            <span>{{ 'SALAXY.NG1.AccountingReportsComponent.workers' | sxyTranslate }}</span>\r\n          </th>\r\n          <th sxy-text=\"SALAXY.NG1.AccountingReportsComponent.material\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.AccountingReportsComponent.responsiblePerson\"></th>\r\n          <th class=\"middle hidden-xxs\">\r\n            <salaxy-datepicker-popup name=\"year\" placeholder=\"SALAXY.NG1.AccountingReportsComponent.year\" format=\"yyyy\" ng-change=\"$crud.logicalDateChanged()\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$crud.logicalDate\" label-type=\"plain\"\r\n              required></salaxy-datepicker-popup>\r\n          </th>\r\n          <th class=\"middle hidden-xxs\">\r\n            <button title=\"{{'SALAXY.NG1.AccountingReportsComponent.chooseAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length == 0\" ng-disabled=\"$ctrl.selectedItems.length == $ctrl.items.length\" ng-click=\"$crud.selectAll()\">\r\n              <i class=\"fa fa-square-o\"></i>\r\n            </button>\r\n            <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length > 0\" ng-disabled=\"$ctrl.selectedItems.length == 0\" ng-click=\"$crud.unselectAll()\">\r\n              <i class=\"fa fa-check-square-o\"></i>\r\n            </button>\r\n          </th>\r\n          <th class=\"middle hidden-xxs\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <span ng-if=\"row.ownerInfo.avatar.displayName == ''\">{{ 'SALAXY.NG1.AccountingReportsComponent.notSelected' | sxyTranslate }}</span>\r\n            <strong>{{row.ownerInfo.avatar.displayName}}</strong><br /> {{row.data.officialId}}\r\n          </td>\r\n          <td class=\"middle\">\r\n            {{ row.logicalDate | date:'yyyy-MM' }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            {{ row.data.calculationCount }} {{'SALAXY.NG1.AccountingReportsComponent.pce' | sxyTranslate}}<br /> {{ row.data.workerCount }} {{'SALAXY.NG1.AccountingReportsComponent.pce' | sxyTranslate}}\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div ng-repeat=\"message in row.messages\" ng-bind-html=\"message | sxyWorkflowMessage: 'PartnerMessageIssue,PartnerMessageClosed'\"></div>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <span ng-if=\"row.data.partnerMessageAssignedTo\" ng-controller=\"WorkflowController as $workflowCtrl\" title=\"{{ $workflowCtrl.getCredential(row.data.partnerMessageAssignedTo).email || $workflowCtrl.getCredential(row.data.partnerMessageAssignedTo).avatar.displayName }}\">\r\n              <salaxy-avatar style=\"font-size:45px\" avatar=\"$workflowCtrl.getCredential(row.data.partnerMessageAssignedTo).avatar\"></salaxy-avatar>\r\n            </span>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button class=\"btn btn-sm btn-block btn-default\" ng-disabled=\"row.isReading\" type=\"button\" ng-click=\"$reportTools.export($crud.getItemDataReader(row),true)\">\r\n              <span ng-show=\"row.isReading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span ng-show=\"!row.isReading\">{{ 'SALAXY.NG1.AccountingReportsComponent.createMaterial' | sxyTranslate }}</span>\r\n            </button>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"!$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              <i class=\"fa fa-square-o\"></i>\r\n            </button>\r\n            <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              <i class=\"fa fa-check-square-o\"></i>\r\n            </button>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\">\r\n              <i class=\"fa fa-info visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/AccountingReportsPanel.html\",`<div class=\"salaxy-odata-panel list-panel report-list-panel panel panel-sm panel-secondary\">\r\n  <div class=\"panel-heading\">\r\n    {{'SALAXY.NG1.AccountingReportsComponent.accountingReports' | sxyTranslate}}\r\n    <div class=\"pull-right \" ng-show=\"$ctrl.items.length > 0\">\r\n      <button class=\"btn btn-secondary btn-xs\" ng-click=\"hideFilter = !hideFilter\" title=\"{{'SALAXY.NG1.AccountingReportsComponent.showFilters' | sxyTranslate}}\">\r\n        <i class=\"fa fa-filter\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-body filters text-right\" ng-class=\"{'showfilters' : hideFilter}\">\r\n    <div class=\"filter-buttons\">\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"logicalDate\">{{'SALAXY.NG1.AccountingReportsComponent.mm' | sxyTranslate}}</button>\r\n    </div>\r\n    <salaxy-input name=\"search1cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search hidden-xxs\" label-type=\"plain\"></salaxy-input>\r\n  </div>\r\n  <div ng-class=\"$ctrl.getCssClass()\">\r\n    <div class=\"visible-xxs\" ng-if=\"$ctrl.items.length > 0\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search2cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-body text-center panel-content lg-height align-middle\" ng-show=\"$ctrl.items.length == 0 && !$ctrl.isLoading\">\r\n      <div>\r\n        <h3 sxy-text=\"SALAXY.NG1.AccountingReportsComponent.noAccountingReports\"></h3>\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\" ng-if=\"$ctrl.items.length > 0\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"middle\">\r\n              {{ row.logicalDate | date:'yyyy-MM' }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{row.data.calculationCount}} <i class=\"fa fa-list\" title=\"{{'SALAXY.NG1.AccountingReportsComponent.calcs' | sxyTranslate}}\"></i>\r\n              <br/> {{row.data.workerCount}} <i class=\"fa fa-user\" title=\"{{'SALAXY.NG1.AccountingReportsComponent.workersAlt' | sxyTranslate}}\"></i>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              <a href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i\r\n              class=\"fa fa-info \"></i></a>\r\n            </td>\r\n\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n\r\n  </div>\r\n  <div class=\"panel-footer text-center\">\r\n    <a ng-href=\"#{{$crud.getDefaults().listUrl}}\" class=\"btn btn-primary btn-sm\" sxy-text=\"SALAXY.UI_Terms.showAll\"></a>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/AccountingTargets.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"shortText\" sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.exportDefinition\"></div>\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.targetChannel\"></div>\r\n          </th>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"ownerInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.owner\"></div>\r\n            <div sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.status\"></div>\r\n          </th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div title=\"{{ row.shortText }} ({{ row.id }})\">\r\n              <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.ownerInfo.avatar.displayName }}</div>\r\n            <div>{{ \"AccountingTargetStatus.\" + row.status | sxyEnum }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div title=\"{{ row.createdAt }}\">{{ row.createdAt | sxyDate }}</div>\r\n            <div title=\"{{ row.updatedAt }}\">{{ row.updatedAt | sxyDate }}</div>\r\n            <div></div>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n                class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n                class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/AccountingTargetSelect.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"shortText\" sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.exportDefinition\"></div>\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.targetChannel\"></div>\r\n          </th>\r\n          <th sxy-orderby=\"owner\" colspan=\"2\">\r\n            <div sxy-text=\"SALAXY.NG1.AccountingTargetsComponent.owner\"></div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"3\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div title=\"{{ row.shortText }} ({{ row.id }})\">\r\n              <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.ownerInfo.avatar.displayName }}</div>\r\n          </td>\r\n          <td></td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/ApiCrudObject.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-orderby=\"id\">\r\n          <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.id\"></div>\r\n        </th>\r\n        <th sxy-orderby=\"status\"  sxy-text=\"SALAXY.UI_Terms.status\"></th>\r\n        <th class=\"right\">\r\n          <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n          <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n        </th>\r\n        <th sxy-orderby=\"owner\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.owner\"></th>\r\n        <th sxy-orderby=\"isReadOnly\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.readOnly\"></th>\r\n        <th sxy-orderby=\"partner\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.partner\"></th>\r\n        <th colspan=\"2\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td>\r\n          <div>{{ row.shortText }}</div>\r\n          <div><code><small>{{ row.id }}</small></code></div>\r\n        </td>\r\n        <td>{{ row.status }}</td>\r\n        <td class=\"right\">\r\n          <div>{{ row.createdAt | sxyDate }}</div>\r\n          <div>{{ row.updatedAt | sxyDate }}</div>\r\n        </td>\r\n        <td class=\"td-avatar\">\r\n          <salaxy-avatar avatar=\"row.ownerInfo.avatar\" title=\"row.owner\"></salaxy-avatar>\r\n        </td>\r\n        <td>{{ row.isReadOnly }}</td>\r\n        <td>{{ row.partner }}</td>\r\n        <td>\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n              class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n        </td>\r\n        <td>\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n              class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/BrandList.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"ownerInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1.BrandListComponent.partner\"></span>\r\n          </th>\r\n          <th class=\"right\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <i class=\"salaxy-avatar\" style=\"font-size: 74px;\"><img ng-src=\"{{ row.data.logo }}\" /></i>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <strong>{{row.data.webAppName || row.ownerInfo.avatar.displayName}}</strong>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" type=\"button\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Calculations-select.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n            <span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.date\"></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ row.status ? (\"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate) : \"#ERR\" }}<br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsAll.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\" ng-show=\"!$ctrl.readOnly\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-orderby=\"status\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <a href=\"\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n              <br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n              <br /> {{row.endAt | date}}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}\r\n              <br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <br /> {{row.endAt | date}}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status == 'draft'\" class=\"btn btn-sm btn-primary btn-block\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\">\r\n              <i class=\"fa fa-pencil visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span>\r\n            </button>\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status != 'draft'\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i></a>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\" ng-if=\"!row.data.payrollId\"></span>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.CalcListComponent.calculation\" ng-if=\"row.data.payrollId\"></span>\r\n            </button>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <button ng-if=\"row.status == 'draft'\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n            <button ng-if=\"!row.data.payrollId && (row.status == 'paymentSucceeded' || row.status == 'paymentStarted')\" ng-click=\"$crud.showCopyAsNew(row)\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\">\r\n              <i class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span>\r\n            </button>\r\n            <a ng-if=\"row.data.payrollId\" class=\"btn btn-sm btn-primary btn-block\" ng-href=\"#/payroll/details/{{ row.data.payrollId }}\">\r\n              <i class=\"fa fa-list visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.CalcListComponent.payroll\"></span>\r\n            </a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsDrafts.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\" ng-show=\"!$ctrl.readOnly\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search1x{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-if-role=\"!worker\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n          </th>\r\n          <th sxy-if-role=\"worker\">\r\n            <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.CalcListComponent.date\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\" sxy-if-role=\"!worker\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.date\"></span></span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\" ></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\" sxy-if-role=\"!worker\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\" sxy-if-role=\"!worker\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n              <br />{{ row.endAt | date }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\" sxy-if-role=\"worker\" ng-click=\"$crud.showDetails(row)\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.endAt | date }}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\" ng-click=\"$crud.showDetails(row)\">\r\n\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\" sxy-if-role=\"!worker\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\" sxy-if-role=\"!worker\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}<br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\" colspan=\"{{$ctrl.readOnly ? 2 : 1}}\">\r\n\r\n            <button ng-if=\"!row.isReadOnly && !$ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\">\r\n              <i class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span>\r\n            </button>\r\n            <button ng-if=\"!row.isReadOnly && $ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\">\r\n              <i class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n            </button>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\" ng-if=\"!$ctrl.readOnly\">\r\n            <button ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n                class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsEmployer.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n\r\n          <th>\r\n            <span sxy-orderby=\"status\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.status\"></span>\r\n            </span>\r\n            <br />\r\n            <span sxy-orderby=\"endAt\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.date\"></span>\r\n            </span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n\r\n\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n\r\n          <td>\r\n            <div ng-switch=\"row.status\">\r\n              <span ng-switch-when=\"paymentWorkerCopy\" class=\"text-success\">\r\n                Maksettu\r\n              </span>\r\n              <span ng-switch-when=\"workerRequested\">\r\n                Lähetetty\r\n              </span>\r\n              <span ng-switch-when=\"workerRequestAccepted\">\r\n                Hyväksytty\r\n              </span>\r\n              <span ng-switch-when=\"workerRequestDeclined\" class=\"text-warning\">\r\n                Hylätty\r\n              </span>\r\n\r\n            </div>\r\n            <!--TODO add better status descriptons-->\r\n            <!--br> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}-->\r\n            {{ (row.salaryDate || row.endAt) | date}}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.grossSalary | currency }}\r\n            <br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button ng-click=\"$crud.showDetails(row)\" class=\"btn btn-sm btn-default\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i>\r\n              \r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n            </button>\r\n\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default\">\r\n              <i class=\"fa fa-file-pdf-o visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.printable\"></span>\r\n            </a>\r\n          </td>\r\n\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsEmployerAll.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></span>\r\n          </th>\r\n          <th>\r\n            <span sxy-orderby=\"status\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.status\"></span>\r\n            </span>\r\n            <br />\r\n            <span sxy-orderby=\"endAt\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.date\"></span>\r\n            </span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n\r\n\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar  middle\">\r\n            <div ng-if=\"row.status != 'draft'\">\r\n\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </div>\r\n            <div ng-if=\"row.status == 'draft'\">\r\n              <i class=\"fa fa-question-circle\" style=\"font-size: 45px;color: #d0d0d0;\"></i>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-name  middle\">\r\n            <div ng-if=\"row.status == 'draft'\">\r\n              <span class=\"small\" sxy-html=\"Luonnoslaskelma<br>Ei työnantajaa\"></span>\r\n            </div>\r\n            <div ng-if=\"row.status != 'draft'\">\r\n\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br>\r\n              <small>{{row.otherPartyInfo.email}}</small>\r\n            </div>\r\n          </td>\r\n          <td>\r\n            <div ng-switch=\"row.status\">\r\n              <span ng-switch-when=\"draft\">\r\n                Luonnos\r\n              </span>\r\n              <span ng-switch-when=\"paymentWorkerCopy\" class=\"text-success\">\r\n                Maksettu\r\n              </span>\r\n              <span ng-switch-when=\"workerRequested\">\r\n                Lähetetty\r\n              </span>\r\n              <span ng-switch-when=\"workerRequestAccepted\" class=\"text-warning\">\r\n                Hyväksytty\r\n              </span>\r\n              <span ng-switch-when=\"workerRequestDeclined\" class=\"text-danger\">\r\n                Hylätty\r\n              </span>\r\n\r\n            </div>\r\n            <!--TODO add better status descriptons-->\r\n            <!--br> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}-->\r\n            {{ (row.salaryDate || row.endAt) | date}}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.grossSalary | currency }}\r\n            <br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button ng-click=\"$crud.showDetails(row)\" class=\"btn btn-sm btn-default\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i>\r\n              \r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n            </button>\r\n\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default\">\r\n              <i class=\"fa fa-file-pdf-o visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.printable\"></span>\r\n            </a>\r\n          </td>\r\n\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsPaid.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\" ng-show=\"!$ctrl.readOnly\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-orderby=\"status\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"3\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n              <br /> {{ row.endAt | date }}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}<br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\" colspan=\"{{$ctrl.readOnly ? 2 : 1 }}\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n              </a>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\" ng-if=\"!$ctrl.readOnly\">\r\n            <button ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-file-pdf-o visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.printable\"></span></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsPanel.html\",`<div class=\"salaxy-odata-panel list-panel calc-list-panel panel panel-sm panel-secondary\" ng-init=\"hideFilter = false\">\r\n  <!-- TODO: add binding panel-title \r\n <div ng-if=\"$ctrl.data.panelTitle\" class=\"panel-heading\" sxy-text=\"$ctrl.panelTitle\"></div>\r\n -->\r\n\r\n  <div class=\"panel-heading\">\r\n    {{'SALAXY.NG1.CalcListComponent.panel.' + $ctrl.data.category + '.heading' | sxyTranslate}}\r\n    <div class=\"pull-right\" ng-show=\"$ctrl.data.category != 'sentAndDraft'\">\r\n      <button class=\"btn btn-secondary btn-xs\" ng-click=\"hideFilter = !hideFilter\" title=\"{{'SALAXY.NG1.CalculationsPanelComponent.showFilters' | sxyTranslate}}\">\r\n        <i class=\"fa fa-filter\"></i>\r\n      </button>\r\n\r\n    </div>\r\n\r\n    <div class=\"pull-right\" ng-if=\"$ctrl.data.category == 'sentAndDraft'\">\r\n      <salaxy-action-button action=\"'newCalc'\" button-class=\"btn-primary btn-xs\" label=\"{{'SALAXY.NG1.CalculationsPanelComponent.newCalc' | sxyTranslate}}\"></salaxy-action-button>\r\n    </div>\r\n  </div>\r\n\r\n  <div class=\"panel-body filters text-right\" ng-class=\"{showfilters: hideFilter}\" ng-if=\"$ctrl.data.category != 'sentAndDraft'\">\r\n    <div class=\"\">\r\n      <div class=\"filter-buttons\">\r\n        <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.UI_Terms.abc\"></button>\r\n        <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"endAt\">\r\n          <i class=\"fa fa-calendar\"></i>\r\n        </button>\r\n        <button ng-if=\"$ctrl.data.category == 'paid' || $ctrl.data.category == 'sent'\" class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.status\"></button>\r\n        <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"grossSalary\">\r\n          €\r\n        </button>\r\n      </div>\r\n      <salaxy-input name=\"search1cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search hidden-xs\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n\r\n  </div>\r\n\r\n  <div ng-class=\"$ctrl.getCssClass()\" ng-if=\"$ctrl.data.category != 'shared' && $ctrl.data.category != 'sentAndDraft' \">\r\n    <div class=\"visible-xxs\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search2cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"td-avatar middle hidden-xxs\">\r\n              <salaxy-avatar ng-if=\"$ctrl.data.category != 'sent'\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n              <salaxy-avatar ng-if=\"$ctrl.data.category == 'sent'\" avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <strong ng-if=\"$ctrl.data.category != 'sent'\">{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n              <strong ng-if=\"$ctrl.data.category == 'sent'\">{{row.ownerInfo.avatar.displayName}}</strong>\r\n              <br /> {{ row.endAt | date }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.grossSalary | currency }}\r\n              <br />\r\n              <span ng-if=\"row.status != 'workerRequestAccepted' && row.status != 'workerRequestDeclined' && row.status != 'workerRequested' && row.status != 'paymentWorkerCopy'\" class=\"row-status\" ng-class=\"{'text-warning' : row.status == 'paymentStarted', 'text-success' : row.status == 'paymentSucceeded'}\">{{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}</span>\r\n              <span ng-if=\"row.status == 'workerRequestAccepted' \" class=\"row-status text-success\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.accepted\"></span>\r\n              <span ng-if=\"row.status == 'workerRequestDeclined' \" class=\"row-status text-danger\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.declined\"></span>\r\n            </td>\r\n            <td class=\"right middle\">\r\n              <button ng-if=\"$ctrl.data.category == 'draft'\" ng-click=\"$crud.showDetails(row)\" title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm\" ng-class=\"$ctrl.readOnly ? 'btn-secondary' : 'btn-primary'\">\r\n                <i class=\"fa \" ng-class=\"$ctrl.readOnly ? 'fa-info' : 'fa-pencil'\"></i>\r\n              </button>\r\n              <button ng-if=\"$ctrl.data.category == 'paid' || $ctrl.data.category == 'sent' || $ctrl.data.category == 'received'\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\">\r\n                <i class=\"fa fa-info\"></i>\r\n              </button>\r\n              <button ng-if=\"$ctrl.data.category == 'paid' && !$ctrl.readOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\">\r\n                <i class=\"fa fa-copy\"></i>\r\n              </button>\r\n              <a ng-if=\"$ctrl.data.category == 'paid' || $ctrl.data.category == 'sent' || $ctrl.data.category == 'received'\" ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\">\r\n                <i class=\"fa fa-file-pdf-o\"></i>\r\n              </a>\r\n            </td>\r\n\r\n          </tr>\r\n        </tbody>\r\n\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <!-- IF category is Shared -->\r\n  <div ng-class=\"$ctrl.getCssClass()\" ng-if=\"$ctrl.data.category == 'shared' \">\r\n    <div class=\"visible-xxs\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search2cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"td-avatar middle hidden-xxs\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n              <br /> {{ row.endAt | date }}\r\n            </td>\r\n            <td class=\"middle\">\r\n              <span class=\"text-success\" ng-if=\"row.status == 'sharedApproved'\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.accepted\"></span>\r\n              <span class=\"text-warning\" ng-if=\"row.status == 'sharedWaiting'\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.waiting\" ps=\"...\"></span>\r\n\r\n\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.grossSalary | currency }}\r\n              <br /> {{ row.payment | currency }}\r\n\r\n            </td>\r\n            <td class=\"right middle\">\r\n              <button ng-if=\"!$ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\">\r\n                <i class=\"fa fa-pencil\"></i>\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <!-- IF category is Sent or Draft-->\r\n  <div ng-class=\"$ctrl.getCssClass()\" ng-if=\"$ctrl.data.category == 'sentAndDraft'\">\r\n\r\n\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"td-avatar middle hidden-xxs\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <strong>{{row.otherPartyInfo.avatar ? row.otherPartyInfo.avatar.displayName : 'SALAXY.UI_Terms.notChosen' | sxyTranslate}}</strong>\r\n              <br /> {{ row.endAt | date }}\r\n            </td>\r\n            <td class=\"middle\">\r\n              <span class=\"text-warning\" ng-if=\"row.status == 'workerRequested'\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.sent\"></span>\r\n\r\n              <span ng-if=\"row.status == 'draft'\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.draft\"></span>\r\n\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.grossSalary | currency }}\r\n              <br /> {{ row.payment | currency }}\r\n\r\n            </td>\r\n            <td class=\"right middle\">\r\n              <button ng-if=\"!$ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\">\r\n                <i class=\"fa fa-pencil\"></i>\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n\r\n\r\n  <!--TODO add binding showAllUrl -->\r\n\r\n  <div class=\"panel-footer text-center\">\r\n    <a ng-if=\"$ctrl.data.category != 'received' && $ctrl.data.category != 'sent' && $ctrl.data.category != 'sentAndDraft'\" class=\"btn btn-primary btn-sm\" href=\"#/calc/{{$ctrl.data.category}}\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.showWholeList\"></a>\r\n\r\n    <a ng-if=\"$ctrl.data.category == 'sent'\" class=\"btn btn-primary btn-sm\" href=\"#/calc/sent\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.sentAlt\"></a>\r\n    <a ng-if=\"$ctrl.data.category == 'sent'\" class=\"btn btn-primary btn-sm\" href=\"#/calc/draft\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.drafts\"></a>\r\n    <a ng-if=\"$ctrl.data.category == 'received'\" class=\"btn btn-secondary btn-sm\" href=\"#/calc/paid\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.allPaid\"></a>\r\n    <span class=\"\" ng-if=\"$ctrl.data.category == 'sentAndDraft'\">\r\n      <a class=\"btn btn-secondary btn-sm\" href=\"#/calc/sent\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.allSent\"></a>\r\n      <a class=\"btn btn-secondary btn-sm\" href=\"#/calc/draft\" sxy-text=\"SALAXY.NG1.CalculationsPanelComponent.allDrafts\"></a>\r\n    </span>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsPaymentStartedPanel.html\",`<div class=\"salaxy-odata-panel list-panel with-footer calc-list-panel panel panel-sm panel-secondary\">\r\n  <div class=\"panel-heading\">\r\n    {{'SALAXY.NG1.CalcListComponent.panel.paymentStarted.heading' | sxyTranslate}}\r\n  </div>\r\n\r\n  <div ng-class=\"$ctrl.getCssClass()\">\r\n  \r\n    <div class=\"table-responsive\">\r\n      <table class=\"table table-striped\">\r\n      \r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"td-avatar  middle\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n              {{ row.salaryDate | date }}\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              <span class=\"text-warning\">{{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}</span>              \r\n            </td>\r\n            <td class=\"middle right\">\r\n              <a href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i class=\"fa fa-info \"></i></a>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div class=\"panel-footer text-center\">\r\n      <salaxy-odata-footer></salaxy-odata-footer>\r\n    </div>\r\n    \r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsReceived.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\" ng-show=\"!$ctrl.readOnly\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive light-bg\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs right\">\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.date\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n              <br /> {{ row.endAt | date }}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.data.workerPayment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n            <a href=\"mailto:{{row.otherPartyInfo.email}}\">{{row.otherPartyInfo.email}}</a><br /> Puh: {{row.otherPartyInfo.telephone || \"-\"}}<br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle right\">\r\n            {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.data.workerPayment | currency }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></a></span>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\">\r\n              <i class=\"fa fa-file-pdf-o\"></i>\r\n              <span class=\"hidden-xs\" pre=\" \" sxy-text=\"SALAXY.UI_Terms.printable\"></span>\r\n            </a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsSent.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive light-bg\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-orderby=\"status\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\" ></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n\r\n            <a ng-click=\"$crud.showDetails(row)\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <a ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"(Ei työnantajaa)\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n              <br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n              <br /> {{row.endAt | date}}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}\r\n              <br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalculationsSentComponent.noEmployee\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <span ng-if=\"row.status == 'workerRequested'\" class=\"text-warning\" sxy-text=\"SALAXY.NG1.CalculationsSentComponent.waitingForAcception\" ps=\"...\"></span>\r\n            <span ng-if=\"row.status == 'workerRequestDeclined'\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalculationsSentComponent.declined\"></span>\r\n            <span ng-if=\"row.status == 'workerRequestAccepted'\" class=\"text-success\" sxy-text=\"SALAXY.NG1.CalculationsSentComponent.accepted\"></span>\r\n            <br /> {{row.endAt | date}}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status == 'draft'\" class=\"btn btn-sm btn-primary btn-block\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\">\r\n              <i class=\"fa fa-pencil visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span>\r\n            </button>\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status != 'draft'\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i></a>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\" ng-if=\"!row.data.payrollId\"></span>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.CalcListComponent.calculation\" ng-if=\"row.data.payrollId\"></span>\r\n            </button>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <button ng-if=\"row.status == 'draft'\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n            <button ng-if=\"!row.data.payrollId && (row.status == 'paymentSucceeded' || row.status == 'paymentStarted')\" ng-click=\"$crud.showCopyAsNew(row)\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\">\r\n              <i class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span>\r\n            </button>\r\n            <a ng-if=\"row.data.payrollId\" class=\"btn btn-sm btn-primary btn-block\" ng-href=\"#/payroll/details/{{ row.data.payrollId }}\">\r\n              <i class=\"fa fa-list visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.CalcListComponent.payroll\"></span>\r\n            </a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsShared.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search1x{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span><br />\r\n            <span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.date\"></span></span>\r\n          </th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\" ></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\" ></span></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n\r\n              <span ng-switch=\"row.status\">\r\n               \r\n              <span ng-switch-when=\"sharedApproved\" class=\"status text-success small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.accepted\"></span>\r\n              <span ng-switch-when=\"sharedWaiting\" class=\"status text-warning small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.waitingForHandling\"></span>\r\n              <span ng-switch-when=\"sharedRejected\" class=\"status text-danger small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.declined\"></span>\r\n              <br />{{ row.endAt | date }}\r\n            </a>\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            <span ng-switch=\"row.status\">\r\n              <span ng-switch-when=\"sharedWaiting\" class=\"status text-warning small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.waitingForHandling\"></span>\r\n            <span ng-switch-when=\"sharedApproved\" class=\"status text-success small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.accepted\"></span>\r\n            \r\n            <span ng-switch-when=\"sharedRejected\" class=\"status text-danger small\" sxy-text=\"SALAXY.NG1.CalculationsSharedComponent.declined\"></span>\r\n            <br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <button ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\">\r\n              <i class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n            </button>\r\n          </td>\r\n          <!-- <td class=\"hidden-xxs middle\">\r\n            <button ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n                class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          </td>-->\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsWithSalaryDate-select.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n            <span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span><br />\r\n            <span sxy-orderby=\"salaryDate\"><span sxy-text=\"SALAXY.NG1.CalculationsWithSalaryDateSelectComponent.salaryDate\"></span></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span sxy-text=\"SALAXY.NG1.CalculationsWithSalaryDateSelectComponent.start\"></span><br />\r\n            <span sxy-text=\"SALAXY.NG1.CalculationsWithSalaryDateSelectComponent.end\"></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar visible-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name visible-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <br /> {{ row.salaryDate | date }}\r\n          </td>\r\n          <td class=\"right visible-xxs bottom\">\r\n            <a href=\"\" ng-click=\"$crud.showDetails(row)\">\r\n              {{ row.grossSalary | currency }}<br />\r\n              {{ row.payment | currency }}\r\n            </a>\r\n          </td>\r\n          <td class=\"td-avatar hidden-xxs middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name hidden-xxs middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ row.status ? (\"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate) : \"#ERR\" }}<br /> {{ row.salaryDate | date }}\r\n          </td>\r\n          <td class=\"hidden-xxs middle\">\r\n            {{ row.data.workStartDate | date}}<br /> {{ row.data.workEndDate | date }}\r\n          </td>\r\n          <td class=\"right hidden-xxs middle\">\r\n            {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CalculationsWorker.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-header-container-mobile\" ng-show=\"!$ctrl.readOnly\">\r\n      <a class=\"btn btn-sm btn-block btn-primary\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.UI_Terms.createNew\"></a>\r\n    </div>\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"searchMobile{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th>\r\n            <span sxy-orderby=\"status\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.status\"></span>\r\n            </span>\r\n            <br />\r\n            <span sxy-orderby=\"endAt\">\r\n              <span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.date\"></span>\r\n            </span>\r\n          </th>\r\n          <th></th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.salary\"></span></span><br />\r\n            <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.payment\"></span></span>\r\n          </th>\r\n          <th class=\"right\" colspan=\"{{$ctrl.readOnly ? 2 : 3}}\">\r\n            <salaxy-odata-actions show-export=\"true\"></salaxy-odata-actions>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td>\r\n            {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <br /> {{ (row.salaryDate || row.endAt) | date}}\r\n          </td>\r\n          <td>\r\n            <div ng-if=\"$ctrl.logic.isNotCurrentEmployment(row)\">\r\n              Ei tämä työsuhde!<br />\r\n              <a ng-href=\"#/employments/details/{{ row.data.employmentId }}\" class=\"btn btn-xs btn-default\">Näytä työsuhde...</a>\r\n            </div>\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.grossSalary | currency }}\r\n            <br /> {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"middle\">\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status == 'draft'\" class=\"btn btn-sm btn-block\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" ng-class=\"$ctrl.readOnly ? 'btn-default' : 'btn-primary'\">\r\n              <i class=\"fa  visible-xs\" ng-class=\"$ctrl.readOnly ? 'fa-info' : 'fa-pencil'\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\" ng-if=\"!$ctrl.readOnly\"></span>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\" ng-if=\"$ctrl.readOnly\"></span>\r\n            </button>\r\n            <button ng-click=\"$crud.showDetails(row)\" ng-if=\"row.status != 'draft'\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i></a>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\" ng-if=\"!row.data.payrollId\"></span>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.calculation\" ng-if=\"row.data.payrollId\"></span>\r\n            </button>\r\n            \r\n          </td>\r\n          <td class=\"middle\" ng-if=\"!$ctrl.readOnly\">\r\n            <button ng-if=\"row.status == 'draft' || row.status == 'history'\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\">\r\n              <i class=\"fa fa-trash visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span>\r\n            </button>\r\n            <button ng-if=\"!row.data.payrollId && (row.status == 'paymentSucceeded' || row.status == 'paymentStarted') && ('employments.calcs.copyAsNew' | sxyShow: 'workers.details')\" ng-click=\"$crud.showCopyAsNew(row)\" class=\"btn btn-sm btn-default btn-block\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\">\r\n              <i class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span>\r\n            </button>\r\n            <a ng-if=\"row.data.payrollId\" class=\"btn btn-sm btn-primary btn-block\" ng-href=\"#/payroll/details/{{ row.data.payrollId }}\">\r\n              <i class=\"fa fa-list visible-xs text-white\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.calculationsWorker.payroll\"></span>\r\n            </a>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\">\r\n              <i class=\"fa fa-file-pdf-o visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.printable\"></span>\r\n            </a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/calendar/Events.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.ODataCalendarEventComponent.description\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.ODataCalendarEventComponent.categories\"></th>\r\n        <th sxy-orderby=\"logicalDate\" sxy-text=\"SALAXY.NG1.ODataCalendarEventComponent.period\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.ODataCalendarEventComponent.duration\"></th>\r\n        <th>\r\n          <button type=\"button\" ng-click=\"$crud.showDetailsDialog('new')\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.addNew\"></button>\r\n          <button type=\"button\" ng-click=\"$ctrl.reload()\" class=\"btn btn-default\">\r\n            <i class=\"fa fa-refresh\" aria-hidden=\"true\"></i>\r\n          </button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td>{{ row.shortText }}</td>\r\n        <td><small ng-repeat=\"cat in row.flags\">{{ cat + ($last ? \"\" : \", \") }}</small></td>\r\n        <td>{{ row.data | sxyDateRange }}</td>\r\n        <td>{{ row.data.duration | sxyDuration }}</td>\r\n        <td>\r\n          <button type=\"button\" ng-click=\"$crud.showDetailsDialog(row.id)\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.edit\"></button>\r\n          <a ng-href=\"{{'#/calendar/details/' + row.id}}\" class=\"btn btn-default\">Link</a>\r\n          <button ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger\">\r\n            <i class=\"fa fa-trash\"></i>\r\n          </button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/CustomerInvoices.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-orderby=\"id\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.id\"></th>\r\n        <th sxy-orderby=\"createdAt\"  sxy-text=\"SALAXY.UI_Terms.created\"></th>\r\n        <th sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></th>\r\n        <th sxy-orderby=\"owner\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.owner\"></th>\r\n        <th sxy-orderby=\"isReadOnly\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.readOnly\"></th>\r\n        <th sxy-orderby=\"partner\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.partner\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td>{{ row.id }}</td>\r\n        <td>{{ row.createdAt | sxyDate }}</td>\r\n        <td>{{ row.updatedAt | sxyDate }}</td>\r\n        <td>{{ row.owner }}</td>\r\n        <td>{{ row.isReadOnly }}</td>\r\n        <td>{{ row.partner }}</td>\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n              class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n        </td>\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n              class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Datasets.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-orderby=\"shortText\" sxy-text=\"Teksti\"></th>\r\n        <th class=\"right\">\r\n          <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n          <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n        </th>\r\n        <th sxy-orderby=\"isReadOnly\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.readOnly\"></th>\r\n        <th class=\"right hidden-xxs\" colspan=\"2\">\r\n          <div class=\"table-filter-container\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td>{{ row.shortText }}</td>\r\n        <td class=\"right\">\r\n          <div>{{ row.createdAt | sxyDate }}</div>\r\n          <div>{{ row.updatedAt | sxyDate }}</div>\r\n        </td>\r\n        <td>{{ row.isReadOnly }}</td>\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n              class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n        </td>\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n              class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/EarningsPayments.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" class=\"hidden-xxs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n          </th>\r\n          <th class=\"visible-xxs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n          </th>\r\n          <th>\r\n            <span sxy-orderby=\"status\" class=\"clickable\"><span sxy-text=\"Tila\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"payment\" class=\"clickable\"><span sxy-text=\"Maksu\"></span></span>\r\n\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"startAt\" class=\"clickable\"><span sxy-text=\"Kausi\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"searchx{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"sort-by-text\" label-type=\"plain\">\r\n              </salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle hidden-xxs\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\">{{ 'SALAXY.NG1.CalcListComponent.notSelected' | sxyTranslate }}</span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n          </td>\r\n          <td class=\"middle td-status\">\r\n            <span ng-if=\"row.status == 'new'\" class=\"text-warning small status\">\r\n                Käsitelyssä\r\n            </span>\r\n            <span ng-if=\"row.status == 'succeeded'\" class=\"text-success small status\">\r\n                Hyväksytty\r\n            </span>\r\n            <span ng-if=\"row.status == 'cancelled'\" class=\"text-danger small status\">\r\n                Hylätty\r\n            </span>\r\n          </td>\r\n          <td class=\"middle right\">\r\n            {{row.payment | currency}}<br>\r\n            <span class=\"small\">{{ row.endAt | date }}</span>\r\n          </td>\r\n          <td class=\"right\">{{row.startAt | date}} - <br>{{row.endAt | date}}</td>\r\n          <td class=\"middle right\">\r\n            <a ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i\r\n              class=\"fa fa-info visible-xxs\"></i><span class=\"hidden-xxs\">Näytä</span></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/EarningsPaymentsPanel.html\",`<div class=\"salaxy-odata-panel list-panel report-list-panel panel panel-sm panel-secondary\">\r\n  <div class=\"panel-heading\">\r\n    {{('Tulorekisteri-ilmoitukset' | sxyTranslate) }}\r\n    <div class=\"pull-right\" ng-show=\"$ctrl.items.length > 0\">\r\n      <button class=\"btn btn-secondary btn-xs\" ng-click=\"hideFilter = !hideFilter\" title=\"Näytä suodattimet\">\r\n        <i class=\"fa fa-filter\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-body filters text-right\" ng-class=\"{'showfilters' : hideFilter}\">\r\n    <div class=\"filter-buttons\">\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.UI_Terms.abc\"></button>\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"status\"> Tila</button>\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"endAt\">\r\n        <i class=\"fa fa-calendar\"></i>\r\n      </button>\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"payment\">€</button>\r\n    </div>\r\n    <salaxy-input name=\"search1cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search hidden-xxs\" label-type=\"plain\">\r\n    </salaxy-input>\r\n  </div>\r\n  <div ng-class=\"$ctrl.getCssClass()\">\r\n    <div class=\"visible-xxs\" ng-if=\"$ctrl.items.length > 0\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search2cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-body text-center panel-content lg-height align-middle\" ng-show=\"$ctrl.items.length == 0 && !$ctrl.isLoading\">\r\n      <div>\r\n        <h3>Ei Tulorekisteri-ilmoituksia</h3>\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\" ng-if=\"$ctrl.items.length > 0\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n            <td class=\"hidden\"><pre class=\"small\">{{row | json}}</pre></td>\r\n            <td class=\"td-avatar middle hidden-xxs\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\">{{ 'SALAXY.NG1.CalcListComponent.notSelected' | sxyTranslate }}</span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n            </td>\r\n            <td class=\"middle td-status\">\r\n              <span ng-if=\"row.status == 'new'\" class=\"text-warning small status\">\r\n                Käsitelyssä\r\n              </span>\r\n              <span ng-if=\"row.status == 'succeeded'\" class=\"text-success small status\">\r\n                Hyväksytty\r\n              </span>\r\n              <span ng-if=\"row.status == 'cancelled'\" class=\"text-danger small status\">\r\n                Hylätty\r\n              </span>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{row.payment | currency}}<br>\r\n              <span class=\"small\">{{ row.endAt | date }}</span>\r\n            </td>\r\n\r\n            <td class=\"middle right\">\r\n              <a ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i\r\n              class=\"fa fa-info\"></i></a>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-footer text-center\">\r\n    <a ng-href=\"#{{$crud.getDefaults().listUrl}}\" class=\"btn btn-primary btn-sm\">Näytä kaikki</a> {{$crud.listUrl}}\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Employments-select.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n       {{'SALAXY.NG1.WorkerListComponent.employments' | sxyTranslate}}:\r\n       {{ ($ctrl.url == '/v03/api/employments' ? 'SALAXY.NG1.WorkerListComponent.all' : 'SALAXY.NG1.WorkerListComponent.active') | sxyTranslate }}\r\n       <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setUrl('/v03/api/employments')\" sxy-text=\"SALAXY.NG1.WorkerListComponent.all\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setUrl('/v03/api/employments?activeDate=today')\" sxy-text=\"SALAXY.NG1.WorkerListComponent.active\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button ng-if=\"$ctrl.selectMode === 'multiselect'\" ng-click=\"$ctrl.selectAll()\" class=\"btn btn-default btn-sm\" sxy-text=\"SALAXY.NG1.WorkerListComponent.selectAll\"></button>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr class=\"\">\r\n          <th class=\"visible-xs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n            <span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span>\r\n          </th>\r\n          <th colspan=\"2\" class=\"hidden-xs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n            <span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span>\r\n          </th>\r\n          <th class=\"right hidden-xxs\">\r\n            <span sxy-text=\"SALAXY.NG1.WorkerListComponent.employment\"></span><br/>\r\n            <span sxy-orderby=\"updatedAt\" class=\"clickable\" sxy-text=\"SALAXY.UI_Terms.updated\"></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"sort-by-text\" label-type=\"plain\">\r\n              </salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle hidden-xs\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <div>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n            </div>\r\n            <div class=\"sm-description\">\r\n              {{$crud.getEmploymentDescription(row)}}\r\n            </div>\r\n          </td>\r\n          <td class=\"middle right hidden-xxs\">\r\n            <div ng-class=\"{'text-danger': !row.data.isActive }\">{{ row.data | sxyDateRange }}</div>\r\n            <div>{{ row.updatedAt | date}}</div>\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? (\"SALAXY.UI_Terms.unselect\" | sxyTranslate) : (\"SALAXY.UI_Terms.select\" | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Employments.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div ng-if=\"$ctrl.logic.showToolbar\" class=\"btn-toolbar\" role=\"toolbar\">\r\n    <salaxy-action-button label=\"SALAXY.NG1_Pages.Workers.newWorker\" action=\"'newWorker'\" button-class=\"btn-sm btn-primary\" ng-if=\"!$ctrl.readOnly && ('!assureWorkerAccount' | sxyIsInRole)\"></salaxy-action-button>\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n       {{'SALAXY.NG1.WorkerListComponent.employments' | sxyTranslate}}:\r\n       {{ ($ctrl.url == '/v03/api/employments' ? 'SALAXY.NG1.WorkerListComponent.all' : 'SALAXY.NG1.WorkerListComponent.active') | sxyTranslate }}\r\n       <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setUrl('/v03/api/employments')\" sxy-text=\"SALAXY.NG1.WorkerListComponent.all\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.setUrl('/v03/api/employments?activeDate=today')\" sxy-text=\"SALAXY.NG1.WorkerListComponent.active\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\" ng-controller=\"ExportController as $export\" ng-init=\"$export.api = $crud.getExportable()\">\r\n      <button ng-repeat=\"mapper in $export.listItemMappers\" class=\"btn btn-default \" ng-click=\"$export.quickExport('copyExcel', null, mapper)\">{{mapper.title}} {{'SALAXY.NG1.ODataActionsComponent.toExcel' | sxyTranslate}}</button>\r\n      <button class=\"btn btn-default \" ng-click=\"$export.showExport()\" sxy-text=\"SALAXY.NG1.ODataActionsComponent.export\"></button>\r\n    </div>\r\n    <button class=\"btn btn-default btn-sm\" ng-click=\"$crud.selectAutoTaxcardForEmployments($ctrl.items)\" title=\"{{'SALAXY.NG1.WorkerListComponent.activeAutoTaxcard' | sxyTranslate}}\" sxy-text=\"SALAXY.NG1.WorkerListComponent.autoTaxcard\"></button>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr class=\"\">\r\n          <th colspan=\"2\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n          </th>\r\n          <th class=\"hidden-xxs\">\r\n            <span><span sxy-text=\"SALAXY.NG1.WorkerListComponent.employment\"></span></span><br />\r\n            <span sxy-orderby=\"updatedAt\" class=\"clickable\"><span sxy-text=\"SALAXY.UI_Terms.updated\"></span></span>\r\n          </th>\r\n          <th ng-if=\"'workers.employments.records.badge' | sxyShow: 'workers.index'\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.records.badge\"></th>\r\n          <th ng-if=\"'workers.employments.taxcard' | sxyShow: 'workers.index'\" sxy-text=\"SALAXY.NG1.WorkerListComponent.taxcard\"></th>\r\n          <th class=\"right hidden-xxs\">\r\n            <div>\r\n              <div>\r\n                <div>\r\n                  <span class=\"salaxy-form-group-plain\">\r\n                    <input type=\"text\" ng-model=\"$ctrl.rawSearchStringOther\"  ng-change=\"$ctrl.searchChanged('other')\" class=\"form-control\" autocomplete=\"off\"\r\n                      id=\"searchx111\" name=\"searchx111\" placeholder=\"{{'SALAXY.UI_Terms.textSearch' | sxyTranslate}}\"\r\n                      ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" maxlength=\"1024\">\r\n                  </span>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <a href=\"#/employments/details/{{row.id}}\" class=\"cell-link\" title=\"{{'SALAXY.NG1.WorkerListComponent.editWorker' | sxyTranslate}}\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name hidden-xs middle\">\r\n            <div>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n              <img ng-if=\"row.otherPartyInfo.avatar.owner == row.otherId\" src=\"https://cdn.salaxy.com/img/elems/logo/square50x50logo.png\"\r\n                class=\"registered-user\" style=\"width: 16px; position: relative; top: -6px;\" title=\"{{'SALAXY.NG1.WorkerListComponent.registeredUser' | sxyTranslate}}\">\r\n            </div>\r\n            <div class=\"sm-description\">\r\n              {{$crud.getEmploymentDescription(row)}}\r\n            </div>\r\n          </td>\r\n          <td class=\"td-name visible-xs middle\">\r\n            <a href=\"#/employments/details/{{row.id}}\" class=\"cell-link\" title=\"{{'SALAXY.NG1.WorkerListComponent.editWorker' | sxyTranslate}}\">\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n              <span class=\"sm-description\" ng-if=\"row.otherPartyInfo.ibanNumber\">{{$crud.getEmploymentDescription(row)}}</span>\r\n              <span class=\"text-danger missing-info\" ng-if=\"!row.otherPartyInfo.ibanNumber\" sxy-text=\"SALAXY.NG1.WorkerListComponent.addIban\"></span>\r\n            </a>\r\n          </td>\r\n          <td class=\"hidden-xxs middle\" colspan=\"{{$ctrl.readOnly ? 2 : ''}}\" title=\"{{ $crud.getActiveText(row) }}\">\r\n            <div style=\"white-space: nowrap; overflow: hidden;text-overflow: ellipsis;\" ng-class=\"{'text-danger': !row.data.isActive }\">{{ row.data | sxyDateRange }}</div>\r\n            <div>{{ row.updatedAt | date}}</div>\r\n          </td>\r\n          <td ng-if=\"'workers.employments.records.badge' | sxyShow: 'workers.index'\" class=\"middle\">\r\n            <salaxy-workflow-badge model=\"row\" api-ctrl=\"$crud\"  wf-types=\"'EmployerMessageRecord'\"></salaxy-workflow-badge>\r\n          </td>\r\n          <td ng-if=\"'workers.employments.taxcard' | sxyShow: 'workers.index'\" class=\"middle\">\r\n            <span>{{ $crud.getTaxcardBadge(row.data.taxcard) }}</span>\r\n          </td>\r\n          <td class=\"right middle hidden-xxs\" style=\"white-space: nowrap;\">\r\n            <a ng-if=\"'workers.employments.buttons.newCalc' | sxyShow: 'workers.index'\" href=\"#/calc/details/{{row.id}}/new-for-employment\" class=\"btn btn-default btn-sm\" ng-if=\"!$ctrl.readOnly\" sxy-text=\"SALAXY.UI_Terms.newCalculation\"></a>\r\n            <a href=\"#/employments/details/{{row.id}}#calculations\" class=\"btn btn-sm btn-default hidden-xs\" title=\"{{'SALAXY.UI_Terms.calculations' | sxyTranslate}}\">\r\n              <i class=\"fa fa-list\" aria-hidden=\"true\"></i>\r\n            </a>\r\n            <a class=\"btn btn-sm btn-primary\" href=\"#/employments/details/{{row.id}}\" sxy-text=\"SALAXY.UI_Terms.edit\"></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Holidays.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\" sxy-orderby=\"otherPartyInfo/avatar/displayName\">\r\n          <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n        </th>\r\n        <th sxy-html=\"SALAXY.NG1.HolidaysComponent.holidayType.html\"></th>\r\n        <th sxy-orderby=\"endAt\" class=\"right\" sxy-text=\"SALAXY.NG1.HolidaysComponent.year\"></th>\r\n        <th class=\"right\" sxy-html=\"SALAXY.NG1.HolidaysComponent.holidays.html\"></th>\r\n        <th>\r\n          <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\"></salaxy-input>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td class=\"align-middle td-avatar\">\r\n          <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"td-workerSnapshot-name\">\r\n          <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong><br /> {{ \"WageBasis.\" + row.data.wageBasis | sxyEnum }}<br />\r\n          <span ng-if=\"!row.data.employmentId\" class=\"label label-danger\" sxy-text=\"SALAXY.NG1.HolidaysComponent.error\"></span>\r\n        </td>\r\n        <td>\r\n          {{ \"HolidayCode.\" + row.data.code | sxyEnum }}\r\n          <span ng-if=\"row.data.code == 'holidayCompensation'\">({{ row.data.compensation | sxyCount : 'percent' }})</span>\r\n          <div ng-if=\"row.data.bonusMethod != 'none'\">\r\n            {{ \"HolidayBonusPaymentMethod.\" + row.data.bonusMethod | sxyEnum }}\r\n            <span>({{ row.data.bonus | sxyCount : 'percent' }})</span>\r\n          </div>\r\n        </td>\r\n        <td class=\"right\">{{ row.data.year }}</td>\r\n        <td class=\"right\">\r\n          {{ row.data.plannedDays | sxyCount : 'days' }}<br /> {{ row.data.accrualDays | sxyCount : 'days' }}\r\n        </td>\r\n        <td class=\"hidden-xxs middle\">\r\n          <button ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/HouseholdYears.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-orderby=\"logicalDate\" class=\"right\" sxy-text=\"SALAXY.NG1.HouseHoldYearsComponent.year\"></th>\r\n          <th sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.HouseHoldYearsComponent.answer\"></th>\r\n          <th class=\"right\" sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.HouseHoldYearsComponent.latestSaving\"></th>\r\n          <th sxy-orderby=\"backOfficeStatus\" sxy-text=\"SALAXY.NG1.HouseHoldYearsComponent.backOfficeStatus\"></th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"right\">\r\n            {{ row.logicalDate | date:'yyyy' }}\r\n          </td>\r\n          <td>\r\n            {{ 'HouseholdYearStatus.' + row.status | sxyEnum }}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.endAt | sxyDate }}\r\n          </td>\r\n          <td>\r\n            {{ 'HouseholdYearProcessingStatus.' + row.backOfficeStatus | sxyEnum }}\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ row.createdAt | sxyDate }}</div>\r\n            <div>{{ row.updatedAt | sxyDate }}</div>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" class=\"btn btn-sm btn-primary btn-block\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n            </button>\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" class=\"btn btn-sm btn-primary btn-block\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\">\r\n              <i class=\"fa fa-pencil visible-xs\"></i>\r\n              <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Invoices.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\"><span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1.InvoicesComponent.receiverAndType\"></span></th>\r\n        <th>\r\n          <span sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.InvoicesComponent.status\"></span><br />\r\n          <small sxy-text=\"SALAXY.NG1.InvoicesComponent.channel\"></small>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"startAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.invoiceDate\"></span><br/>\r\n          <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.dueDate\"></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></span><br />\r\n          <span sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></span>\r\n        </th>\r\n        <th class=\"right\"><span sxy-orderby=\"payment\" sxy-text=\"SALAXY.NG1.InvoicesComponent.sum\"></span></th>        \r\n        <th class=\"right\" colspan=\"2\">\r\n          <div class=\"table-filter-container hidden-xxs\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\" ng-show=\"$ctrl.items.length > 0\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"middle\">\r\n          <div>{{ row.otherPartyInfo.avatar.displayName }}</div>\r\n          <small class=\"hidden-xxs\" ng-switch=\"row.entityType\">\r\n            <span ng-switch-when=\"net|gross|foreclosure|verification\" ng-switch-when-separator=\"|\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ row.logicalDate | sxyDate }}</span>\r\n            <span ng-switch-when=\"unemployment\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}}<br/>{{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n            <span ng-switch-default>{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n          </small>\r\n        </td class=\"middle\">\r\n        <td class=\"middle\">\r\n          <span ng-class=\"{ 'bg-danger': row.status == 'canceled', 'bg-success': row.status == 'paid' }\" title=\"{{ 'InvoiceStatus.' + row.status | sxyEnumDescr }}\">\r\n            {{ \"InvoiceStatus.\" + row.status | sxyEnum }}\r\n          </span><br />\r\n          <small>{{ \"PaymentChannel.\" + row.data.channel | sxyEnum }}</small>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <div>{{ row.startAt | sxyDate }}</div>\r\n          <div ng-switch=\"$crud.getDueDateType(row)\">\r\n            <span ng-switch-when=\"estimation\">{{ row.endAt | date: 'MMMM' }}</span>\r\n            <del ng-switch-when=\"canceled\" class=\"\">{{ row.endAt | sxyDate }}</del>\r\n            <span ng-switch-when=\"overdue\" class=\"bg-danger\">{{ row.endAt | sxyDate }}</span>\r\n            <em ng-switch-when=\"future\" class=\"disabled\">{{ row.endAt | sxyDate }}</em>\r\n            <span ng-switch-when=\"default\">{{ row.endAt | sxyDate }}</span>\r\n            <span ng-switch-when=\"unknown\">{{ row.endAt | sxyDate }}</span>\r\n          </div>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.createdAt | sxyDate }}<br /> {{ row.updatedAt | sxyDate }}\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.payment | currency }}\r\n        </td>       \r\n        <td class=\"middle right\">\r\n          <a href=\"\" ng-click=\"$crud.showDetails(row)\" class=\"btn btn-primary\">\r\n            {{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\r\n          </a>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n  <div class=\"salaxy-odata-footer\">\r\n    <salaxy-spinner></salaxy-spinner>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/InvoicesCompany.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <h1 sxy-text=\"SALAXY.NG1.InvoicesCompany.heading\"></h1>\r\n  <style>\r\n    .invoice-label {\r\n      display: inline-block;\r\n      width: 100px;\r\n    }\r\n  </style>\r\n  <div class=\"btn-toolbar\">\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"btnHide\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{ $crud.queryOption.text }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnHide\">\r\n        <li role=\"menuitem\" ng-repeat=\"queryOption in $crud.queryOptions\">\r\n          <a href=\"\" ng-click=\"$crud.queryOption = queryOption;$crud.doQuery()\">{{queryOption.text}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" class=\"btn btn-secondary\" ng-click=\"$crud.showloadPfd($ctrl.items)\" sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></button>\r\n    <div ng-if=\"$crud.queryOption.value != 'unpaid'\" class=\"btn-group\" uib-dropdown>\r\n      <button id=\"btnHide\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{ $crud.dateFilterQueryOption.text }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnHide\">\r\n        <li role=\"menuitem\" ng-repeat=\"queryOption in $crud.queryDateFilterOptions\">\r\n          <a href=\"\" ng-click=\"$crud.setDateFilterQueryOption(queryOption)\">{{queryOption.text}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" class=\"btn btn-primary pull-right\" ng-if=\"$crud.queryOption.value == 'unpaid' && $ctrl.items.length > 0\"\r\n      ng-click=\"$crud.markInvoicesAsPaid()\" ng-disabled=\"!$ctrl.selectedItems || $ctrl.selectedItems.length == 0\" sxy-text=\"SALAXY.NG1.InvoicesCompany.setAsPaid\">\r\n   </button>\r\n    <div ng-if=\"$crud.queryOption.value == 'unpaid' && $ctrl.items.length > 0\" class=\"btn-group pull-right\" uib-dropdown>\r\n      <button id=\"btnHide\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{'SALAXY.NG1.InvoicesCompany.selectInvoices' | sxyTranslate}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnHide\">\r\n        <li role=\"menuitem\" ng-repeat=\"option in $crud.getMarkAsPaidOptions($ctrl.items)\">\r\n          <a href=\"\" ng-click=\"$crud.selectInvoicesByType(option.value)\">{{option.text}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    \r\n    \r\n  </div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\"><span sxy-text=\"SALAXY.NG1.InvoicesCompany.receiverAndType\"></span></th>\r\n        <th ng-if=\"$crud.queryOption.value == 'unpaid'\" class=\"right\">\r\n          <span sxy-text=\"SALAXY.NG1.InvoicesCompany.sum\"></span>/ <br/>\r\n          <span sxy-text=\"SALAXY.UI_Terms.chosen\"></span>\r\n        </th>\r\n        <th ng-if=\"$crud.queryOption.value != 'unpaid'\" class=\"right\">\r\n          <span sxy-text=\"SALAXY.NG1.InvoicesCompany.sum\"></span>\r\n        </th>          \r\n        <th class=\"right\" colspan=\"2\">\r\n          <div class=\"table-filter-container hidden-xxs\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\"\r\n             placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\">\r\n            </salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"row in $ctrl.items\" ng-show=\"$ctrl.items.length > 0\" class=\"active\">\r\n        <td class=\"middle\" colspan=\"3\">\r\n          <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn btn-transparent pull-right\" type=\"button\" ng-if=\"!$ctrl.isSelected(row) && $crud.queryOption.value == 'unpaid' && $crud.showMarkAsPaidButton(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-square-o\"></i>\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-transparent pull-right\" type=\"button\" ng-if=\"$ctrl.isSelected(row) && $crud.queryOption.value == 'unpaid' && $crud.showMarkAsPaidButton(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-check-square-o\"></i>\r\n          </button>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          <span style=\"font-size: 1.4em; font-weight: bold; line-height: 2em;\">\r\n            {{ row.otherPartyInfo.avatar.displayName }}:\r\n            <span ng-switch=\"row.entityType\">\r\n              <span ng-switch-when=\"net|gross|foreclosure|verification\" ng-switch-when-separator=\"|\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ row.logicalDate | sxyDate }}</span>\r\n              <span ng-switch-default>{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n            </span>\r\n          </span>\r\n          <div ng-if=\"row.entityType == 'net'\"  ng-switch=\"row.status\">\r\n            <span ng-switch-when=\"paid\" class=\"text-success\" ng-switch-when-separator=\"|\" sxy-text=\"SALAXY.NG1.InvoicesCompany.paidNetPaymentInfo\"></span>\r\n            <span ng-switch-default  class=\"text-danger\" sxy-text=\"SALAXY.NG1.InvoicesCompany.unPaidNetPaymentInfo\"></span>\r\n          </div>\r\n          \r\n        </td>\r\n        <td class=\"right\">\r\n          <button ng-if=\"row.status != 'canceled'\" class=\"btn btn-default\" ng-click=\"$crud.showInvoiceDialog(row)\">\r\n            <i class=\"fa fa-file-o visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.InvoicesCompany.showInvoiceDetails\"></span>\r\n          </button>\r\n          <a ng-if=\"$crud.calculationHref(row)\" ng-href=\"{{$crud.calculationHref(row)}}\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1.InvoicesCompany.openCalculation\"></a>\r\n        \r\n        </td>\r\n      </tr>\r\n      <tr>\r\n        <td class=\"td-avatar hidden-xxs\" style=\"width: 160px;padding: 0px;\" ng-if=\"row.status != 'paid' && row.status != 'canceled' && $crud.getQrCode(row) !== 'loading' && $crud.getQrCode(row) !== 'error'\">\r\n          <div style=\"margin: 8px;\" height=\"160px\" ng-bind-html=\"$crud.getQrCode(row)\" ></div>\r\n        </td>\r\n        <td class=\"td-avatar hidden-xxs\" style=\"min-width: 160px;vertical-align: middle; text-align: center; height: 160px;\" ng-if=\"row.status != 'paid' && row.status != 'canceled' && $crud.getQrCode(row) === 'error'\">\r\n          <div style=\"height: 100%; display: flex;align-items: center;justify-content: center; background-color: #e9d310;\">\r\n            <div>\r\n              <small sxy-text=\"SALAXY.NG1.InvoicesCompany.qrCodeNotAvailable\"></small>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td class=\"td-avatar hidden-xxs\" style=\"vertical-align: middle; text-align: center; height: 160px; width: 160px;\" ng-if=\"row.status == 'paid'\">\r\n          <div class=\"bg-success\" style=\"height: 100%; display: flex;align-items: center;justify-content: center; font-size: 1.5em;\">\r\n            <div>\r\n              <b>\r\n                {{ \"SALAXY.ENUM.InvoiceStatus.\" + row.status + \".label\" | sxyTranslate}} <br/>\r\n                {{(row.data.statusAt || row.updatedAt) | date}}\r\n              </b>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td class=\"td-avatar hidden-xxs\" style=\"vertical-align: middle; text-align: center; height: 160px; width: 160px;\" ng-if=\"row.status == 'canceled'\">\r\n          <div class=\"bg-danger\" style=\"height: 100%; display: flex;align-items: center;justify-content: center; font-size: 1.5em;\">\r\n            <b>\r\n              {{ \"SALAXY.ENUM.InvoiceStatus.\" + row.status + \".label\" | sxyTranslate}} <br/>\r\n              {{(row.data.statusAt || row.updatedAt) | date}}\r\n            </b>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\" sxy-text=\"SALAXY.NG1.InvoicesCompany.iban\" ps=\":\"></div>\r\n            <div class=\"col-xs-9\">\r\n              {{ row.otherPartyInfo.ibanNumber  }}\r\n            </div>\r\n          </div>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\" sxy-text=\"SALAXY.NG1.InvoicesCompany.name\" ps=\":\"></div>\r\n            <div class=\"col-xs-9\">\r\n              {{ row.otherPartyInfo.avatar.displayName }}\r\n            </div>\r\n          </div>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\" sxy-text=\"SALAXY.NG1.InvoicesCompany.dueDate\" ps=\":\"></div>\r\n            <div class=\"col-xs-9\" ng-switch=\"$crud.getDueDateType(row)\">\r\n              <span ng-switch-when=\"estimation\">{{ row.endAt | sxyDate }}</span>\r\n              <del ng-switch-when=\"canceled\" class=\"\">{{ row.endAt | sxyDate }}</del>\r\n              <span ng-switch-when=\"overdue\" class=\"bg-danger\">{{ row.endAt | sxyDate }}</span>\r\n              <em ng-switch-when=\"future\" class=\"disabled\">{{ row.endAt | sxyDate }}</em>\r\n              <span ng-switch-when=\"default\">{{ row.endAt | sxyDate }}</span>\r\n              <span ng-switch-when=\"unknown\">{{ row.endAt | sxyDate }}</span>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-3\">\r\n              {{row.entityType === 'net' || row.entityType === 'gross' ? ('SALAXY.NG1.InvoicesCompany.message' | sxyTranslate) : ('SALAXY.NG1.InvoicesCompany.reference' | sxyTranslate)}}\r\n            </div>\r\n            <div class=\"col-xs-9\">\r\n              <span ng-if=\"row.entityType === 'net' || row.entityType === 'gross'\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n              <span ng-if=\"row.entityType !== 'net' && row.entityType !== 'gross'\">{{row.reference}}</span>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\" ng-if=\"row.entityType == 'tax' || row.entityType == 'union'\">\r\n            <div class=\"col-xs-3\" sxy-text=\"SALAXY.NG1.InvoicesCompany.netPaymentCount\" ps=\":\"></div>\r\n            <div class=\"col-xs-9\">\r\n              {{row.businessObjects.length}}\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td class=\"right\" ng-if=\"!row.data.totalPaid\">\r\n          <h4 style=\"font-weight: bold;\">{{ row.payment | currency }}</h4>\r\n        </td>\r\n        <td class=\"right\" ng-if=\"row.data.totalPaid && row.data.totalPaid != row.payment\">\r\n          <h4 style=\"text-decoration: line-through;\">{{'SALAXY.NG1.InvoicesCompany.sum' | sxyTranslate}} {{ row.payment | currency }}</h4>\r\n          <h4>{{'SALAXY.NG1.InvoicesCompany.alreadyPaid' | sxyTranslate}} {{ row.data.totalPaid | currency }}</h4>\r\n          <h4 class=\"total\" style=\"font-weight: bold;\">{{'SALAXY.NG1.InvoicesCompany.payable' | sxyTranslate}} {{ (row.payment - row.data.totalPaid) | currency }}</h4>\r\n        </td>\r\n        <td class=\"right\" ng-if=\"row.data.totalPaid && row.payment == row.data.totalPaid\">\r\n          <h4 style=\"font-weight: bold;\">{{ row.payment | currency }}</h4>\r\n        </td>\r\n        <td class=\"right\">\r\n          <button ng-if=\"$crud.showMarkAsPaidButton(row)\" class=\"btn btn-primary\" ng-click=\"$crud.updateInvoiceStatus(row,'paid')\">\r\n            <i class=\"fa fa-check visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.InvoicesCompany.setAsPaid\"></span>\r\n          </button> \r\n          <div style=\"height: 10px;\" ng-if=\"$crud.showMarkAsPaidButton(row) && $crud.showMarkAsCanceledButton(row)\"> <br/> </div>         \r\n          <button class=\"btn btn-danger\" ng-if=\"$crud.showMarkAsCanceledButton(row)\" ng-click=\"$crud.updateInvoiceStatus(row,'canceled')\">\r\n            <i class=\"fa fa-times visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.NG1.InvoicesCompany.cancelPayment\"></span>\r\n          </button>\r\n          <div ng-if=\"$crud.showIrCancelInfoText(row)\" class=\"text-center\" style=\"width: 140px; margin: auto; margin-top: 6px;\" sxy-text=\"SALAXY.NG1.InvoicesCompany.cancelInfoText\"></div>\r\n          <div ng-if=\"row.status == 'preview'\" class=\"text-center\" style=\"width: 140px; margin: auto; margin-top: 6px;\">\r\n            {{(row.data.paidBusinessObjectsCount || 0) }} / {{row.businessObjects.length}} {{'SALAXY.NG1.InvoicesCompany.unpaidNetSalaries' | sxyTranslate}}<br/>\r\n            {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end ng-if=\"row.status != 'paid' && row.status != 'canceled'\">\r\n        <td colspan=\"4\">\r\n          <button type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"$crud.copyBarcode(row)\">\r\n            <span><i class=\"fa fa-clipboard\"></i></span>\r\n          </button>\r\n          <span style=\"font-family: 'Courier New', Courier, monospace; font-size: 1.3em;\">{{$crud.getBarcodeValue(row)}}</span>          \r\n        </td>        \r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n  <div class=\"salaxy-odata-footer\">\r\n    <salaxy-spinner></salaxy-spinner>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/InvoicesPanel.html\",`<div class=\"salaxy-odata-panel list-panel report-list-panel panel panel-sm panel-secondary\">\r\n  <div class=\"panel-heading\">\r\n    {{('SALAXY.NG1.InvoicesComponent.invoices' | sxyTranslate) }}\r\n  </div>\r\n  <div ng-class=\"$ctrl.getCssClass()\">\r\n    <div class=\"panel-body text-center panel-content lg-height align-middle\" ng-show=\"$ctrl.items.length == 0 && !$ctrl.isLoading\">\r\n      <div>\r\n        <h3 sxy-text=\"SALAXY.NG1.InvoicesComponent.noInvoices\"></h3>\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\" ng-show=\"$ctrl.items.length > 0\">\r\n            <td class=\"td-avatar middle hidden-xxs\">\r\n              <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"middle\">\r\n              {{ row.otherPartyInfo.avatar.displayName }}<br>\r\n              <small class=\"hidden-xxs\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}}</small>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.endAt | date }}\r\n              <span ng-if=\"row.status=='paid'\" class=\"text-success status small\"><br>{{'SALAXY.NG1.InvoicesComponent.paid' | sxyTranslate}}</span>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ row.payment | currency }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              <a ng-href=\"{{$crud.getContentUrl(row.id, true)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i\r\n              class=\"fa fa-file-pdf-o\"></i></a>\r\n              <button href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i class=\"fa fa-info\"></i></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-footer text-center footer-empty\">\r\n    <a ng-href=\"#{{$crud.getDefaults().listUrl}}\" title=\"Näytä kaikki\" class=\"btn btn-primary btn-sm\" sxy-text=\"SALAXY.UI_Terms.showAll\"></a>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/InvoicesPaymentChannel.html\",`<div ng-class=\"$ctrl.getCssClass()\" ng-controller=\"InvoiceToolsController as $invoiceTools\" ng-init=\"$invoiceTools.reader = $crud.selectionDataReader\">\r\n  <div ng-show=\"'test' | sxyIsInRole\" class=\"salaxy-component salaxy-invoice-tools\" >\r\n    <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Invoice options\">\r\n      <div class=\"btn-group\">\r\n        <salaxy-input-enum type=\"uib-dropdown\" name=\"fileType\" label-type=\"plain\" ng-model=\"$invoiceTools.fileTypeId\" options=\"$invoiceTools.fileTypeOptions\" remember=\"invoice\"></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"btn-group\">\r\n        <button ng-disabled=\"$invoiceTools.reader.disabled()\" id=\"reportExport\" type=\"button\" class=\"btn btn-default\" ng-click=\"$invoiceTools.export()\">\r\n          {{ $invoiceTools.reader.exportLabel || ('SALAXY.NG1.AccountingReportToolsComponent.createExport' | sxyTranslate) }}\r\n        </button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\"><span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1.InvoicesComponent.receiverAndType\"></span></th>\r\n        <th>\r\n          <span sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.InvoicesComponent.status\"></span><br />\r\n          <small sxy-text=\"SALAXY.NG1.InvoicesComponent.channel\"></small>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"startAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.invoiceDate\"></span><br/>\r\n          <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.dueDate\"></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></span><br />\r\n          <span sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></span>\r\n        </th>\r\n        <th class=\"right\"><span sxy-orderby=\"payment\" sxy-text=\"SALAXY.NG1.InvoicesComponent.sum\"></span></th>\r\n        <th class=\"middle\" ng-if=\"'test' | sxyIsInRole\">\r\n          <button title=\"{{'SALAXY.UI_Terms.chooseAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length == 0\" ng-disabled=\"$ctrl.selectedItems.length == $ctrl.items.length\" ng-click=\"$crud.selectAll()\">\r\n            <i class=\"fa fa-square-o\"></i>\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.unselectAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length > 0\" ng-disabled=\"$ctrl.selectedItems.length == 0\" ng-click=\"$crud.unselectAll()\">\r\n            <i class=\"fa fa-check-square-o\"></i>\r\n          </button>\r\n        </th>\r\n        <th class=\"right\" colspan=\"2\">\r\n          <div class=\"table-filter-container hidden-xxs\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\" ng-show=\"$ctrl.items.length > 0\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"middle\">\r\n          <div>{{ row.otherPartyInfo.avatar.displayName }}</div>\r\n          <small class=\"hidden-xxs\" ng-switch=\"row.entityType\">\r\n            <span ng-switch-when=\"net|gross|foreclosure|verification\" ng-switch-when-separator=\"|\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ row.logicalDate | sxyDate }}</span>\r\n            <span ng-switch-when=\"unemployment\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}}<br/>{{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n            <span ng-switch-default>{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n          </small>\r\n        </td class=\"middle\">\r\n        <td class=\"middle\">\r\n          <span ng-class=\"{ 'bg-danger': row.status == 'canceled', 'bg-success': row.status == 'paid' }\" title=\"{{ 'InvoiceStatus.' + row.status | sxyEnumDescr }}\">\r\n            {{ \"InvoiceStatus.\" + row.status | sxyEnum }}\r\n          </span><br />\r\n          <small>{{ \"PaymentChannel.\" + row.data.channel | sxyEnum }}</small>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <div>{{ row.startAt | sxyDate }}</div>\r\n          <div>{{ row.endAt | sxyDate }}</div>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.createdAt | sxyDate }}<br /> {{ row.updatedAt | sxyDate }}\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.payment | currency }}\r\n        </td>\r\n        <td class=\"middle\" ng-if=\"'test' | sxyIsInRole\">\r\n          <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"!$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-square-o\"></i>\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-check-square-o\"></i>\r\n          </button>\r\n        </td>\r\n        <td class=\"middle\" ng-if=\"'test' | sxyIsInRole\">\r\n          <button class=\"btn btn-sm btn-block btn-default\" ng-disabled=\"row.isReading\" type=\"button\" ng-click=\"$invoiceTools.export($crud.getItemDataReader(row),true)\">\r\n            <span ng-show=\"row.isReading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n            <span ng-show=\"!row.isReading\">{{ 'SALAXY.NG1.AccountingReportToolsComponent.createExport' | sxyTranslate }}</span>\r\n          </button>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <a href=\"\" ng-click=\"$crud.showDetails(row)\" class=\"btn btn-primary\">\r\n            {{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\r\n          </a>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n  <div class=\"salaxy-odata-footer\">\r\n    <salaxy-spinner></salaxy-spinner>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/InvoicesPerson.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"salaxy-component salaxy-invoice-tools\" ng-controller=\"InvoiceToolsController as $invoiceTools\" ng-init=\"$invoiceTools.reader = $crud.selectionDataReaderPerson\">\r\n    <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Invoice options\">\r\n      <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n        <button id=\"invoiceOptionsFileType\" type=\"button\" class=\"btn btn-primary\" uib-dropdown-toggle>\r\n          <i class=\"fa \" ng-class=\"fa-file-pdf-o\"></i>&nbsp;{{'SALAXY.ENUM.ExportMethod.filePdf.label' | sxyTranslate}} <span class=\"caret\"></span>\r\n        </button>\r\n\r\n      </div>\r\n      <div class=\"btn-group btn-group-sm\">\r\n        <button ng-disabled=\"$crud.selectionDataReaderPerson.disabled()\" id=\"reportExport\" type=\"button\" class=\"btn btn-default\" ng-click=\"$invoiceTools.export()\">\r\n          {{'SALAXY.NG1.AccountingReportToolsComponent.createExport' | sxyTranslate}}\r\n        </button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th colspan=\"2\"><span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1.InvoicesComponent.receiverAndType\"></span></th>\r\n        <th>\r\n          <span sxy-orderby=\"status\" sxy-text=\"SALAXY.NG1.InvoicesComponent.status\"></span><br />\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"startAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.invoiceDate\"></span><br/>\r\n          <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.InvoicesComponent.dueDate\"></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></span><br />\r\n          <span sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></span>\r\n        </th>\r\n        <th class=\"right\"><span sxy-orderby=\"payment\" sxy-text=\"SALAXY.NG1.InvoicesComponent.sum\"></span></th>\r\n        <th class=\"middle\">\r\n          <button title=\"{{'SALAXY.UI_Terms.chooseAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length == 0\" ng-disabled=\"$ctrl.selectedItems.length == $ctrl.items.length\" ng-click=\"$crud.selectAll()\">\r\n            <i class=\"fa fa-square-o\"></i>\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.unselectAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length > 0\" ng-disabled=\"$ctrl.selectedItems.length == 0\" ng-click=\"$crud.unselectAll()\">\r\n            <i class=\"fa fa-check-square-o\"></i>\r\n          </button>\r\n        </th>\r\n        <th class=\"right\" colspan=\"2\">\r\n          <div class=\"table-filter-container hidden-xxs\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\" ng-show=\"$ctrl.items.length > 0\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"middle\">\r\n          <div>{{ row.otherPartyInfo.avatar.displayName }}</div>\r\n          <small class=\"hidden-xxs\" ng-switch=\"row.entityType\">\r\n            <span ng-switch-when=\"net|gross|foreclosure\" ng-switch-when-separator=\"|\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ row.logicalDate | sxyDate }}</span>\r\n            <span ng-switch-when=\"unemployment\">{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}}<br/>{{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n            <span ng-switch-default>{{(\"SALAXY.ENUM.InvoiceType.\" + row.entityType + \".label\") | sxyTranslate}} {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}</span>\r\n          </small>\r\n        </td class=\"middle\">\r\n        <td class=\"middle\" ng-if=\"row.entityType !== 'tax' && row.entityType !== 'net'\">\r\n          <span title=\"{{ 'InvoiceStatus.' + row.status | sxyEnumDescr }}\">\r\n            {{ \"InvoiceStatus.forecast\" | sxyEnum }}\r\n          </span><br />\r\n          <small>{{ row.otherPartyInfo.avatar.displayName }} {{'SALAXY.NG1.InvoicesCreateTableComponent.sendsInvoice' | sxyTranslate}}</small>\r\n        </td>\r\n        <td class=\"middle\" ng-if=\"row.entityType === 'tax' || row.entityType === 'net'\">\r\n          <span ng-class=\"{ 'bg-danger': row.status == 'canceled', 'bg-success': row.status == 'paid' }\" title=\"{{ 'InvoiceStatus.' + row.status | sxyEnumDescr }}\">\r\n            {{ \"InvoiceStatus.\" + row.status | sxyEnum }}\r\n          </span><br />\r\n          <small>{{ \"PaymentChannel.\" + row.data.channel | sxyEnum }}</small>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <div>{{ row.startAt | sxyDate }}</div>\r\n          <div ng-switch=\"$crud.getDueDateType(row)\">\r\n            <span ng-switch-when=\"estimation\">{{ row.endAt | date: 'MMMM' }}</span>\r\n            <del ng-switch-when=\"canceled\" class=\"\">{{ row.endAt | sxyDate }}</del>\r\n            <span ng-switch-when=\"overdue\" class=\"bg-danger\">{{ row.endAt | sxyDate }}</span>\r\n            <em ng-switch-when=\"future\" class=\"disabled\">{{ row.endAt | sxyDate }}</em>\r\n            <span ng-switch-when=\"default\">{{ row.endAt | sxyDate }}</span>\r\n            <span ng-switch-when=\"unknown\">{{ row.endAt | sxyDate }}</span>\r\n          </div>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.createdAt | sxyDate }}<br /> {{ row.updatedAt | sxyDate }}\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.payment | currency }}\r\n        </td>\r\n        <td class=\"middle\" ng-if=\"row.entityType === 'tax' || row.entityType === 'net'\">\r\n          <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"!$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-square-o\"></i>\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n            <i class=\"fa fa-check-square-o\"></i>\r\n          </button>\r\n        </td>\r\n        <td class=\"middle\" ng-if=\"row.entityType !== 'tax' && row.entityType !== 'net'\"></td>\r\n        <td class=\"middle\">\r\n          <button ng-click=\"$crud.showPaymentDialog(row)\" ng-if=\"row.entityType === 'net' && (row.status === 'paid' || row.status === 'unread')\" class=\"btn btn-sm btn-block btn-default\" ng-disabled=\"row.isReading\" type=\"button\">\r\n            <span ng-if=\"row.status === 'paid'\">{{ 'SALAXY.NG1.InvoicesCreateTableComponent.cancelInvoice' | sxyTranslate }}</span>\r\n            <span ng-if=\"row.status === 'unread'\">{{ 'SALAXY.NG1.InvoicesCreateTableComponent.payInvoice' | sxyTranslate }}</span>\r\n          </button>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <a ng-if=\"row.entityType === 'tax' || row.entityType === 'net'\" ng-href=\"{{$crud.getContentUrl(row.id, true)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i\r\n            class=\"fa fa-file-pdf-o\"></i></a>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n  <div class=\"salaxy-odata-footer\">\r\n    <salaxy-spinner></salaxy-spinner>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/InvoicesSepa.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div ng-controller=\"InvoiceToolsController as $invoiceTools\">\r\n    <div class=\"btn-toolbar\">\r\n      <div class=\"btn-group\">\r\n        <salaxy-input-enum type=\"uib-dropdown\" name=\"fileType\" label-type=\"plain\" ng-model=\"$invoiceTools.fileTypeId\" options=\"$invoiceTools.fileTypeOptions\" remember=\"invoice\"></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"btn-group\" uib-dropdown>\r\n        <button id=\"btnHide\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n          {{ ('SALAXY.MODEL.InvoiceListItem.status.title' | sxyTranslate) }}: {{$crud.statusFilter.text}} <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnHide\">\r\n          <li role=\"menuitem\" ng-repeat=\"statusFilter in $crud.statusFilters\">\r\n            <a href=\"\" ng-click=\"$crud.statusFilter = statusFilter\">{{statusFilter.text}}</a>\r\n          </li>\r\n        </ul>\r\n      </div>\r\n      <div class=\"btn-group\">\r\n        <salaxy-datepicker-popup style=\"display: block; width: 200px;\" name=\"year\" label-type=\"plain\" format=\"yyyy\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$crud.queryYear\"></salaxy-datepicker-popup>\r\n      </div>\r\n      <button type=\"button\" ng-click=\"$crud.loadData()\" class=\"btn btn-primary\">Hae</button>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\" style=\"min-height: 250px;\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"1\">\r\n              <span sxy-text=\"SALAXY.NG1.InvoicesComponent.payer\"></span>\r\n            </th>\r\n            <th colspan=\"2\">\r\n              <span>                \r\n                <input type=\"text\" ng-model=\"$crud.otherPartyNameFilter\" class=\"form-control\" autocomplete=\"off\" id=\"otherPartyName\" name=\"otherPartyName\" placeholder=\"{{'SALAXY.NG1.InvoicesComponent.receiver' | sxyTranslate}}\">\r\n              </span>\r\n            </th>\r\n            <th>\r\n              <span sxy-text=\"SALAXY.MODEL.InvoiceData.channel.title\"></span><br />\r\n              <span sxy-text=\"SALAXY.NG1.InvoicesComponent.iban\"></span>\r\n            </th>\r\n            <th>\r\n              <div class=\"btn-group\" uib-dropdown>\r\n                <button id=\"btnHide\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n                  {{ ('SALAXY.NG1.InvoicesComponent.invoiceType' | sxyTranslate) }}: {{$crud.invoiceEntityType.label}} <span class=\"caret\"></span>\r\n                </button>\r\n                <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"btnHide\">\r\n                  <li role=\"menuitem\" ng-repeat=\"invoiceEntityType in $crud.invoiceEntityTypes\">\r\n                    <a href=\"\" ng-click=\"$crud.invoiceEntityType = invoiceEntityType\">{{invoiceEntityType.label}}</a>\r\n                  </li>\r\n                </ul>\r\n              </div>\r\n            </th>\r\n            <th>\r\n              <span sxy-orderby=\"status\" sxy-text=\"SALAXY.MODEL.InvoiceListItem.status.title\"></span><br />\r\n              <span sxy-text=\"SALAXY.MODEL.InvoiceListItem.reference.title\"></span>/<span sxy-text=\"SALAXY.MODEL.InvoiceListItem.messages.title\"></span>\r\n            </th>\r\n            <th class=\"right\">\r\n              <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.MODEL.InvoiceData.dueDate.tableHeading\"></span><br />\r\n              <span sxy-text=\"SALAXY.MODEL.InvoiceData.date.title\"></span>\r\n            </th>\r\n            <th class=\"right\">\r\n              <span sxy-text=\"SALAXY.MODEL.InvoiceListItem.payment.tableHeading\"></span><br />\r\n              <span sxy-text=\"SALAXY.MODEL.InvoiceListItem.payment.title\"></span>\r\n            </th>\r\n            <th colspan=\"2\">\r\n              <span sxy-text=\"SALAXY.NG1.InvoicesComponent.createInvoices\"></span><br />\r\n              <span sxy-text=\"SALAXY.NG1.InvoicesComponent.markAsPaid\"></span>\r\n            </th>\r\n            <th></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat-start=\"group in $crud.getGroupedItems() | filter: $crud.invoiceFilter\" class=\"active\">\r\n            <td class=\"td-avatar middle\">\r\n              <salaxy-avatar avatar=\"group.ownerInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\" colspan=\"2\">\r\n              <strong>{{group.ownerInfo.avatar.displayName}}</strong><br />\r\n              <span>{{group.ownerInfo.officialId}}</span>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <span>{{ \"PaymentChannel.\" + group.channel | sxyEnum }}</span>\r\n            </td>\r\n            <td>\r\n              <span>{{(\"SALAXY.ENUM.InvoiceType.\" + group.invoiceType + \".label\") | sxyTranslate}}</span>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <strong ng-class=\"{ 'bg-danger': group.status == 'canceled', 'bg-success': group.status == 'paid' }\" title=\"{{ 'InvoiceStatus.' + group.status | sxyEnumDescr }}\">\r\n              {{ \"InvoiceStatus.\" + group.status | sxyEnum }}\r\n            </strong>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              <strong>{{ group.dueDate | sxyDate }}</strong>\r\n            </td>\r\n            <td class=\"middle right\">\r\n              <strong>{{ group.payment | currency }}</strong>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button class=\"btn btn-default btn-block\" ng-if=\"group.status == 'unread' || group.status == 'read' || group.status== 'waitingConfirmation'\" ng-disabled=\"group.isReadingread || group.isReadingpaid\" ng-click=\"$invoiceTools.export($crud.getGroupDataReader(group,'waitingConfirmation'),true)\">\r\n              <span ng-show=\"group.isReadingwaitingConfirmation\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span ng-show=\"!group.isReadingwaitingConformation\" sxy-text=\"SALAXY.NG1.InvoicesComponent.createInvoiceBtn\"></span>\r\n            </button>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button class=\"btn btn-default btn-block\" ng-if=\"group.status == 'unread' || group.status == 'read' || group.status== 'waitingConfirmation'\" ng-disabled=\"group.isReadingread || group.isReadingpaid\" ng-click=\"$invoiceTools.export($crud.getGroupDataReader(group,'paid'),true)\">\r\n              <span ng-show=\"group.isReadingpaid\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span ng-show=\"!group.isReadingpaid\" sxy-text=\"SALAXY.NG1.InvoicesComponent.markAsPaidBtn\"></span>\r\n            </button>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button class=\"btn btn-default btn-block\" ng-click=\"$crud.showGroupDialog(group)\" sxy-text=\"SALAXY.NG1.InvoicesComponent.detailsBtn\"></button>\r\n            </td>\r\n          </tr>\r\n          <tr ng-repeat-end ng-repeat=\"invoice in group.invoices | filter: {otherPartyInfo:{avatar:{displayName: $crud.otherPartyNameFilter}}}\" >\r\n            <td></td>\r\n            <td class=\"td-avatar-1line middle\">\r\n              <salaxy-avatar avatar=\"invoice.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\">\r\n              <div><strong>{{invoice.otherPartyInfo.avatar.displayName}}</strong></div>\r\n              <small ng-switch=\"invoice.entityType\">\r\n              <span ng-switch-when=\"net|gross|foreclosure\" ng-switch-when-separator=\"|\">{{(\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate}} {{ invoice.logicalDate | sxyDate }}</span>\r\n              <span ng-switch-when=\"unemployment\">{{(\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate}}<br/>{{ { start: invoice.data.periodStart, end: invoice.data.periodEnd } | sxyDateRange }}</span>\r\n              <span ng-switch-default>{{(\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate}} {{ { start: invoice.data.periodStart, end: invoice.data.periodEnd } | sxyDateRange }}</span>\r\n            </small>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <span ng-if=\"invoice.otherPartyInfo.ibanNumber\">{{ invoice.otherPartyInfo.ibanNumber }}</span>\r\n              <span ng-if=\"!invoice.otherPartyInfo.ibanNumber\" class=\"alert-danger\" sxy-text=\"SALAXY.NG1.InvoicesComponent.noIbanNumber\"></span>\r\n            </td>\r\n            <td class=\"middle\">\r\n              {{(\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate}}\r\n            </td>\r\n            <td class=\"middle\">\r\n              {{ invoice.reference || (\"SALAXY.ENUM.InvoiceType.\" + invoice.entityType + \".label\") | sxyTranslate }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ invoice.data.date | sxyDate }}\r\n            </td>\r\n            <td class=\"middle right\">\r\n              {{ invoice.payment | currency }}\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button class=\"btn btn-default btn-xs btn-block\" ng-if=\"invoice.status == 'unread'  || invoice.status == 'read' || invoice.status== 'waitingConfirmation'\" ng-disabled=\"invoice.isReadingwaitingConfirmation || invoice.isReadingpaid\" ng-click=\"$invoiceTools.export($crud.getGroupItemDataReader(invoice,'waitingConfirmation'),true)\">\r\n              <span ng-show=\"invoice.isReadingwaitingConfirmation\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span ng-show=\"!invoice.isReadingwaitingConfirmation\" sxy-text=\"SALAXY.NG1.InvoicesComponent.createInvoiceBtn\"></span>\r\n            </button>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button class=\"btn btn-default btn-xs btn-block\" ng-if=\"invoice.status == 'unread' || invoice.status == 'read' || invoice.status== 'waitingConfirmation'\" ng-disabled=\"invoice.isReadingwaitingConfirmation || invoice.isReadingpaid\" ng-click=\"$invoiceTools.export($crud.getGroupItemDataReader(invoice,'paid'),true)\">\r\n              <span ng-show=\"invoice.isReadingpaid\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span ng-show=\"!invoice.isReadingpaid\" sxy-text=\"SALAXY.NG1.InvoicesComponent.markAsPaidBtn\"></span>\r\n            </button>\r\n            </td>\r\n            <td class=\"middle\">\r\n              <button ng-click=\"$crud.showInvoiceDialog(invoice)\" title=\"{{ 'SALAXY.NG1.InvoicesComponent.detailsBtn' | sxyTranslate}}\" class=\"btn btn-xs btn-default btn-block\" sxy-text=\"SALAXY.NG1.InvoicesComponent.detailsBtn\">\r\n              \r\n            </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/IrEpr.html\",`<div ng-class=\"$ctrl.getCssClass()\">  \r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <input type=\"text\" ng-model=\"$ctrl.rawSearchStringOther\"  ng-change=\"$ctrl.searchChanged('both')\" class=\"form-control\" autocomplete=\"off\"\r\n            id=\"searchx111\" name=\"searchx111\" placeholder=\"{{'SALAXY.NG1_Other.Roles.worker' | sxyTranslate}}\"\r\n            ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" maxlength=\"1024\">\r\n          </th>\r\n          <th><salaxy-input-enum ng-model=\"irEprStatus\" ng-change=\"$ctrl.setFilter('status', irEprStatus, 'eq', $ctrl.originalFilter)\" placeholder=\"SALAXY.MODEL.EarningsPaymentListItem.status.title\" name=\"status\" enum=\"EarningsPaymentReportStatus\" options=\"{ '': 'SALAXY.UI_Terms.showAll','new': 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.new.label', 'succeeded': 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.succeeded.label', 'canceled' : 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.canceled.label' , 'error': 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.error.label', 'invalid': 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.invalid.label', 'scheduled': 'SALAXY.ENUM_IR.EarningsPaymentReportStatus.scheduled.label' }\" label-type=\"plain\"></salaxy-input-enum> </th>\r\n          <th class=\"right\"><span sxy-orderby=\"salaryDate\" sxy-text=\"SALAXY.NG1.IrEprComponent.salaryDate\"></span></th>\r\n          <th class=\"right\"><span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.IrEprComponent.sendTime\"></span></th>\r\n          <th class=\"right \">\r\n            <span sxy-orderby=\"payment\" sxy-text=\"SALAXY.NG1.IrEprComponent.payment\"></span><br />\r\n            <span sxy-orderby=\"grossSalary\" sxy-text=\"SALAXY.NG1.IrEprComponent.grossSalary\"></span>\r\n          </th>\r\n          <th class=\"right\" colspan=\"2\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n            <span>{{row.otherPartyInfo.email}}</span>\r\n          </td>\r\n          <td class=\"middle\">\r\n            {{ \"SALAXY.ENUM_IR.EarningsPaymentReportStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <div ng-if=\"$crud.isIrModified(row)\"><span class=\"badge bg-danger\" title=\"{{'SALAXY.NG1.IrEprComponent.irModified' | sxyTranslate}}\" sxy-text=\"SALAXY.NG1.IrEprComponent.modified\" ps=\"!\"></span></div>\r\n            <div ng-if=\"$crud.isDelayed(row)\"><span class=\"badge bg-danger\" title=\"Myöhässä\" sxy-text=\"SALAXY.NG1.IrEprComponent.delayed\" ps=\"!\"></span></div>\r\n          </td>\r\n          <td class=\"middle right\">\r\n            {{ row.salaryDate | date }}\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <div title=\"{{'SALAXY.NG1.IrEprComponent.firstDelivery' | sxyTranslate}}\" ng-if=\"row.data.firstDeliveredAt != row.data.lastDeliveredAt\"><span ng-class=\"{'badge': row.data.scheduledFor && row.data.scheduledFor == row.data.firstDeliveredAt ,'bg-warning': row.data.scheduledFor && row.data.scheduledFor == row.data.firstDeliveredAt}\">{{ row.data.firstDeliveredAt | date}}</span></div>\r\n            <div title=\"{{'SALAXY.NG1.IrEprComponent.latestDelivery' | sxyTranslate}}\"><span ng-class=\"{'badge': row.data.scheduledFor && row.data.scheduledFor == row.data.lastDeliveredAt ,'bg-warning': row.data.scheduledFor && row.data.scheduledFor == row.data.lastDeliveredAt}\">{{ row.data.lastDeliveredAt | date}}</span></div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            {{ row.payment | currency }}<br /> {{ row.grossSalary | currency }}\r\n          </td>\r\n          <td class=\"middle\">\r\n            <a ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-default\"><i\r\n              class=\"fa fa-info visible-xxs\"></i><span class=\"hidden-xxs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/IrPsr.html\",`<div ng-class=\"$ctrl.getCssClass()\">  \r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-text=\"SALAXY.NG1.IrPsrComponent.notificationType\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.IrPsrComponent.status\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.IrPsrComponent.month\" class=\"right\"><span sxy-orderby=\"logicalDate\"></span></th>\r\n          <th sxy-text=\"SALAXY.NG1.IrPsrComponent.sendTime\" class=\"right\"><span sxy-orderby=\"endAt\"></span></th>\r\n          <th sxy-text=\"SALAXY.NG1.IrPsrComponent.savaPayment\" class=\"right\"><span sxy-orderby=\"payment\"></span></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.IrPsrComponent.expense\"></th>\r\n          <th class=\"right\" colspan=\"2\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"middle\">{{ \"SALAXY.ENUM_IR.SummaryTransactionCode.\" + row.entityType + \".label\" | sxyTranslate }}</td>\r\n          <td class=\"middle\">\r\n            {{ \"SALAXY.ENUM_IR.PayerSummaryReportStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n            <div ng-if=\"$crud.isIrModified(row)\"><span class=\"badge bg-danger\" title=\"Ilmoitusta on muokattu käsin\" sxy-text=\"SALAXY.NG1.IrPsrComponent.modified\" ps=\"!\"></span></div>\r\n            <div ng-if=\"$crud.isDelayed(row)\"><span class=\"badge bg-danger\" title=\"Myöhässä\" sxy-text=\"SALAXY.NG1.IrPsrComponent.delayed\" ps=\"!\"></span></div>\r\n          </td>\r\n          <td class=\"middle right\">\r\n            {{ row.logicalDate | date : 'MM/yyyy' }}\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <div title=\"{{'SALAXY.NG1.IrPsrComponent.firstDelivery' | sxyTranslate}}\" ng-if=\"row.data.firstDeliveredAt != row.data.lastDeliveredAt\"><span ng-class=\"{'badge': row.data.scheduledFor && row.data.scheduledFor == row.data.firstDeliveredAt ,'bg-warning': row.data.scheduledFor && row.data.scheduledFor == row.data.firstDeliveredAt}\">{{ row.data.firstDeliveredAt | date}}</span></div>\r\n            <div title=\"{{'SALAXY.NG1.IrPsrComponent.latestDelivery' | sxyTranslate}}\"><span ng-class=\"{'badge': row.data.scheduledFor && row.data.scheduledFor == row.data.lastDeliveredAt ,'bg-warning': row.data.scheduledFor && row.data.scheduledFor == row.data.lastDeliveredAt}\">{{ row.data.lastDeliveredAt | date}}</span></div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            {{ row.payment | currency }}\r\n          </td>\r\n          <td class=\"right middle\">{{ row.data.socialSecurityDeduction | currency }}</td>\r\n          <td class=\"middle\">\r\n            <a ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-default\"><i class=\"fa fa-info visible-xxs\"></i><span\r\n              class=\"hidden-xxs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></a>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/MessageThreads.html\",`<div ng-class=\"$ctrl.getCssClass()\" class=\"table-responsive\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>&nbsp;</th>\r\n        <th>\r\n          <span><span sxy-text=\"SALAXY.NG1.MessageThreadsComponent.title\"></span></span><br/>\r\n          <span sxy-orderby=\"otherPartyInfo/avatar/displayName\"><span sxy-text=\"SALAXY.NG1.MessageThreadsComponent.sender\"></span></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"salaryDate\"><span sxy-text=\"SALAXY.NG1.MessageThreadComponent.salaryDate\"></span></span><br/>\r\n          <span><span sxy-text=\"SALAXY.NG1_Pages.Service.ApprovePayrollList.period\"></span></span><br/>\r\n          <span><span sxy-text=\"SALAXY.NG1.MessageThreadsComponent.answered\"></span></span>\r\n        </th>\r\n        <th class=\"right \">\r\n          <span sxy-orderby=\"grossSalary\"><span sxy-text=\"SALAXY.NG1_Pages.Service.ApproveCalculationList.salary\" ></span></span><br />\r\n          <span sxy-orderby=\"payment\"><span sxy-text=\"SALAXY.NG1_Pages.Service.ApproveCalculationList.payment\" ></span></span><br/>\r\n          <span><span sxy-text=\"SALAXY.NG1_Pages.Service.ApprovePayrollList.calculations\"></span></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"status\"><span sxy-text=\"SALAXY.NG1.MessageThreadsComponent.status\"></span></span><br />\r\n          <span sxy-orderby=\"createdAt\"><span sxy-text=\"SALAXY.UI_Terms.created\"></span></span><br />\r\n          <span sxy-orderby=\"updatedAt\"><span sxy-text=\"SALAXY.UI_Terms.updated\"></span></span>\r\n        </th>\r\n        <th></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar class=\"pull-right\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"middle\">\r\n          <span>\r\n            <b>{{row.data.title}}</b>\r\n          </span>\r\n          <span class=\"label label-primary\" ng-if=\"row.data.otherPartyUnreadCount\">\r\n            {{ row.data.otherPartyUnreadCount }}\r\n            <i class=\"fa fa-comment\" aria-hidden=\"true\"></i>\r\n          </span>\r\n          <div>{{row.otherPartyInfo.avatar.displayName}}</div>\r\n          <div class=\"truncate\" style=\"max-width: 300px; font-size: 0.9em;\"><i>{{ row.data.otherPartyLastMessage }}</i></div>\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.salaryDate | date }}<br /> {{ { start: row.data.periodStart, end: row.data.periodEnd } | sxyDateRange }}<br/> {{ row.data.otherPartyUpdatedAt | sxyTime }}\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}<br/> {{ row.data.calcCount ? (row.data.calcCount + \" \" + (\"SALAXY.NG1.MessageThreadsComponent.pce\" | sxyTranslate)) : \"-\" }}\r\n        </td>\r\n        <td class=\"middle right\">\r\n          <div ng-class=\"{ 'text-success': row.status == 'approved', 'text-danger': row.status == 'rejected' }\">\r\n            <span ng-switch=\"row.status\">\r\n              <span ng-switch-when=\"draft\" sxy-text=\"SALAXY.NG1.MessageThreadsComponent.message\"></span>\r\n            <span ng-switch-when=\"active\" sxy-text=\"SALAXY.NG1.MessageThreadsComponent.waiting\"></span>\r\n            <span ng-switch-default>{{ \"MessageThreadStatus.\" + row.status | sxyEnum }}</span>\r\n            </span>\r\n          </div>\r\n          {{ row.createdAt | sxyTime }}<br /> {{ row.updatedAt | sxyTime }}\r\n        </td>\r\n        <td class=\"middle\">\r\n          <a href=\"#{{$crud.getDefaults().detailsUrl}}{{ row.id }}\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\">\r\n            <i class=\"fa fa-comment visible-xs\"></i><span sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n          </a>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/MessageThreadsApproval.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>&nbsp;</th>\r\n        <th sxy-orderby=\"data/title\">\r\n          <span sxy-text=\"SALAXY.NG1.MessageThreadsComponent.title\"></span>\r\n          <div>Lähettäjä</div>\r\n        </th>\r\n        <th class=\"right\">Tila</th>\r\n        <th class=\"right\">\r\n          <span sxy-orderby=\"createdAt\"><span sxy-text=\"SALAXY.UI_Terms.created\"></span></span><br />\r\n          <span sxy-orderby=\"updatedAt\"><span sxy-text=\"SALAXY.UI_Terms.updated\"></span></span>\r\n        </th>\r\n        <th class=\"hidden-xxs\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td class=\"td-avatar middle\">\r\n          <salaxy-avatar class=\"pull-right\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n        </td>\r\n        <td class=\"middle\">\r\n          <span ng-switch=\"row.data.usecaseUri\">\r\n            <b ng-switch-when=\"palkkaus.fi/testing/messages-proto/timer\">Kellokortti</b>\r\n            <b ng-switch-when=\"palkkaus.fi/testing/messages-proto/timeReport\">Työaikaraportti</b>\r\n            <b ng-switch-when=\"palkkaus.fi/testing/messages-proto/hourlyReport\">Tuntiraportti</b>\r\n            <b ng-switch-when=\"palkkaus.fi/testing/messages-proto/calcRow\">Palkkarivit</b>\r\n            <b ng-switch-default>{{ row.data.title || row.data.usecaseUri }}</b>\r\n          </span>\r\n          \r\n          <span class=\"label label-primary\" ng-if=\"row.data.otherPartyUnreadCount\">\r\n            {{ row.data.otherPartyUnreadCount }}\r\n            <i class=\"fa fa-comment\" aria-hidden=\"true\"></i>\r\n          </span>\r\n\r\n          <div>{{row.otherPartyInfo.avatar.displayName}}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div ng-class=\"{ 'text-success': row.status == 'approved', 'text-danger': row.status == 'rejected' }\">{{ \"MessageThreadStatus.\" + row.status | sxyEnum }}</div>\r\n        </td>\r\n        <td class=\"middle right\">\r\n          {{ row.createdAt | sxyTime }}<br /> {{ row.updatedAt | sxyTime }}\r\n        </td>\r\n        <td class=\"middle\">\r\n          <a href=\"#{{$crud.getDefaults().approvalUrl}}{{ row.id }}\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\">\r\n            <i class=\"fa fa-comment visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n          </a>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/PaymentChannelSelect.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"shortText\"><span sxy-text=\"SALAXY.NG1.PaymentChannelSelectComponent.exportDefinition\"></span></div>\r\n            <div sxy-text=\"SALAXY.NG1.PaymentChannelSelectComponent.targetChannel\"></div>\r\n          </th>\r\n          <th sxy-orderby=\"owner\" colspan=\"2\">\r\n            <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.owner\"></div>\r\n            <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.status\"></div>\r\n          </th>\r\n\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div title=\"{{ row.shortText }} ({{ row.id }})\">\r\n              <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.ownerInfo.avatar.displayName }}</div>\r\n            <div>{{ \"AccountingTargetStatus.\" + row.status | sxyEnum }}</div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.NG1.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Payrolls-select.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <div class=\"visible-xxs\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search_xxs{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n    <table class=\"table\">\r\n      <thead>\r\n        <tr>\r\n          <th>\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.description\"></span>\r\n            <span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span>\r\n            <div>\r\n              <span sxy-text=\"SALAXY.NG1.PayrollListComponent.salaryDate\"></span>\r\n            </div>\r\n          </th>\r\n          <th sxy-orderby=\"status\">\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.status\"></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"endAt\">\r\n              <span sxy-text=\"SALAXY.NG1.PayrollListComponent.period\"></span>\r\n            </div>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.paymentDate\"></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.calculations\"></span>\r\n            <div sxy-orderby=\"grossSalary\">\r\n              <span sxy-text=\"SALAXY.NG1.PayrollListComponent.grossSalaries\"></span>\r\n            </div>\r\n          </th>\r\n          <th class=\"right\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"\">\r\n            <span class=\"payroll-title\"><strong>{{ row.data.title }}</strong></span>\r\n            <span class=\"payroll-info\"> {{ row.salaryDate | date }}<small ng-if=\"row.data.wageBasis != 'undefined'\">, {{ 'WageBasis.' + row.data.wageBasis | sxyEnum }}</small></span>\r\n          </td>\r\n          <td class=\"\">\r\n            <div>\r\n              {{ 'PayrollStatus.' + row.status | sxyEnum }}\r\n              <span ng-if=\"row.data.calendarEvent\" class=\"badge bg-primary\">\r\n                <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\r\n                <span sxy-text=\"SALAXY.NG1.PayrollListComponent.calendarEvent\"></span>\r\n              </span>\r\n              <i ng-if=\"row.data.calendarOccurence\" class=\"fa fa-calendar text-primary\" aria-hidden=\"true\" title=\"{{ 'SALAXY.NG1.PayrollListComponent.calendarOccurence' | sxyTranslate }}\"></i>\r\n              <i ng-if=\"!row.data.calendarOccurence && row.data.template\" class=\"fa fa-clone text-primary\" aria-hidden=\"true\" title=\"{{ 'SALAXY.NG1.PayrollListComponent.template' | sxyTranslate }}\"></i>\r\n            </div>\r\n            <span ng-if=\"row.status == 'draft'\" class=\"small\" ng-class=\"{'text-danger' : !row.data.isReady }\">\r\n              {{ row.data.isReady ? ('SALAXY.NG1.PayrollListComponent.readyForPayment' | sxyTranslate) : ('SALAXY.NG1.PayrollListComponent.notReadyForPayment' | sxyTranslate)  }}\r\n            </span>\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.startAt | date }}<br /> {{ row.endAt | date }}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.data.paymentDate || row.data.dueDate | date }}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ row.data.calcCount ? (row.data.calcCount + \" \" + (\"SALAXY.UI_Terms.pcs\" | sxyTranslate)) : \"-\" }}<br /> {{ row.grossSalary | currency }}\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? (\"SALAXY.UI_Terms.unselect\" | sxyTranslate) : (\"SALAXY.UI_Terms.select\" | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Payrolls.html\",`<div ng-class=\"$ctrl.getCssClass()\" class=\"table-responsive\">\r\n\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search_xxs{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th><span sxy-text=\"SALAXY.NG1.PayrollListComponent.description\"></span>\r\n          <div>\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.salaryDate\"></span>\r\n          </div>\r\n\r\n        </th>\r\n        <th sxy-orderby=\"status\"><span sxy-text=\"SALAXY.NG1.PayrollListComponent.status\"></span></th>\r\n        <th class=\"right\"><span sxy-orderby=\"endAt\"><span sxy-text=\"SALAXY.NG1.PayrollListComponent.period\"></span></span>\r\n        </th>\r\n        <th class=\"right\"><span sxy-text=\"SALAXY.NG1.PayrollListComponent.paymentDate\"></span>\r\n        </th>\r\n        <th class=\"right hidden-xxs\">\r\n\r\n          <span sxy-text=\"SALAXY.NG1.PayrollListComponent.calculations\"></span>\r\n\r\n          <div sxy-orderby=\"grossSalary\">\r\n            <span sxy-text=\"SALAXY.NG1.PayrollListComponent.grossSalaries\"></span>\r\n          </div>\r\n        </th>\r\n        <th class=\"right hidden-xxs\" colspan=\"2\">\r\n          <div class=\"table-filter-container\">\r\n            <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td ng-click=\"$crud.showDetails(row)\" class=\"visible-xs clickable\" title=\"Siirry palkkalistaan\">\r\n          <span class=\"payroll-title\"><strong>{{ row.data.title }}</strong></span>\r\n          <span class=\"payroll-info\"> {{ row.salaryDate | date }}<small ng-if=\"row.data.wageBasis != 'undefined'\">, {{ 'WageBasis.' + row.data.wageBasis | sxyEnum }}</small></span>\r\n        </td>\r\n        <td class=\"hidden-xs\">\r\n          <span class=\"payroll-title\"><strong>{{ row.data.title }}</strong></span>\r\n          <span class=\"payroll-info\"> {{ row.salaryDate | date }}<small ng-if=\"row.data.wageBasis != 'undefined'\">, {{ 'WageBasis.' + row.data.wageBasis | sxyEnum }}</small></span>\r\n        </td>\r\n        <td class=\"\">\r\n          <div>\r\n            {{ 'PayrollStatus.' + row.status | sxyEnum }}\r\n            <span ng-if=\"row.data.calendarEvent\" class=\"badge bg-primary\">\r\n              <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\r\n              <span sxy-text=\"SALAXY.NG1.PayrollListComponent.calendarEvent\"></span>\r\n            </span>\r\n            <i ng-if=\"row.data.calendarOccurence\" class=\"fa fa-calendar text-primary\" aria-hidden=\"true\" title=\"{{ 'SALAXY.NG1.PayrollListComponent.calendarOccurence' | sxyTranslate }}\"></i>\r\n            <i ng-if=\"!row.data.calendarOccurence && row.data.template\" class=\"fa fa-clone text-primary\" aria-hidden=\"true\" title=\"{{ 'SALAXY.NG1.PayrollListComponent.template' | sxyTranslate }}\"></i>\r\n          </div>\r\n          <span ng-if=\"row.status == 'draft'\" class=\"small\" ng-class=\"{'text-danger' : !row.data.isReady }\">\r\n            {{ row.data.isReady ? ('SALAXY.NG1.PayrollListComponent.readyForPayment' | sxyTranslate) : ('SALAXY.NG1.PayrollListComponent.notReadyForPayment' | sxyTranslate)  }}\r\n          </span>\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.startAt | date }}<br /> {{ row.endAt | date }}\r\n        </td>\r\n        <td class=\"right\">\r\n          {{ row.data.paymentDate || row.data.dueDate | date }}\r\n        </td>\r\n        <td class=\"right hidden-xxs\">\r\n          {{ row.data.calcCount ? (row.data.calcCount + \" \" +(\"SALAXY.UI_Terms.pcs\" | sxyTranslate)) : \"-\" }}<br /> {{ row.grossSalary | currency }}\r\n        </td>\r\n\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!(row.isReadOnly || row.status == 'paymentStarted') && !$ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n          <button ng-if=\"(row.isReadOnly || row.status == 'paymentStarted') || $ctrl.readOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n        </td>\r\n        <td class=\"middle hidden-xxs\">\r\n          <button ng-if=\"!(row.isReadOnly || row.status == 'paymentStarted') && !$ctrl.readOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          <button ng-if=\"(row.isReadOnly || row.status == 'paymentStarted') && !$ctrl.readOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/ReferenceObjects.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th sxy-orderby=\"status\">Status</th>\r\n          <th sxy-orderby=\"shortText\">Description</th>\r\n          <th sxy-orderby=\"logicalDate\">Reference date</th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"middle\">\r\n            <img ng-if=\"row.data.icon || row.ownerInfo.avatar.url\" ng-src=\"{{row.data.icon || row.ownerInfo.avatar.url}}\" style=\"width: 45px; height: 45px;\" />\r\n          </td>\r\n          <td class=\"middle\">{{ row.status  }}</td>\r\n          <td class=\"middle\">{{ row.shortText  }}</td>\r\n          <td class=\"middle\">{{ row.logicalDate | sxyDate }}</td>\r\n          <td class=\"right\">\r\n            <div title=\"{{ row.createdAt }}\">{{ row.createdAt | sxyDate }}</div>\r\n            <div title=\"{{ row.updatedAt }}\">{{ row.updatedAt | sxyDate }}</div>\r\n            <div></div>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n                class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/SalaryReports.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <div ng-controller=\"SalarySlipDownloadController as $downloadCtrl\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$downloadCtrl.export($ctrl.selectedItems)\" ng-disabled=\"$ctrl.selectedItems.length == 0\" sxy-text=\"SALAXY.UI_Terms.downloadSelected\"></button>\r\n    </div>\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\" class=\"hidden-xxs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n          </th>\r\n          <th class=\"visible-xxs\">\r\n            <span sxy-orderby=\"otherPartyInfo/avatar/displayName\" class=\"clickable\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span><i ng-if=\"$odata.getColumnOrder('avatar/displayName')\" class=\"fa fa-sort-{{ $odata.getColumnOrder('avatar/displayName') }}\"\r\n              aria-hidden=\"true\"></i></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"endAt\" class=\"clickable\"><span sxy-text=\"Pvm\"></span></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"payment\" sxy-text=\"SALAXY.NG1.SalaryReportsComponent.payment\"></span><br>\r\n            <span sxy-orderby=\"grossSalary\" sxy-text=\"SALAXY.NG1.SalaryReportsComponent.grossSalary\"></span>\r\n          </th>\r\n          <th class=\"middle hidden-xxs\">\r\n            <button title=\"{{'SALAXY.NG1.AccountingReportsComponent.chooseAll' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length == 0\" ng-disabled=\"$ctrl.selectedItems.length == $ctrl.items.length\" ng-click=\"$crud.selectAll()\">\r\n              <i class=\"fa fa-square-o\"></i>\r\n            </button>\r\n            <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.selectedItems.length > 0\" ng-disabled=\"$ctrl.selectedItems.length == 0\" ng-click=\"$crud.unselectAll()\">\r\n              <i class=\"fa fa-check-square-o\"></i>\r\n            </button>\r\n          </th>\r\n          <th class=\"right \" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"searchx{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"sort-by-text\" label-type=\"plain\">\r\n              </salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle hidden-xxs\">\r\n            <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\">{{ 'SALAXY.NG1.SalaryReportsComponent.notSelected' | sxyTranslate }}</span>\r\n            <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n          </td>\r\n          <td class=\"right middle\">{{ row.endAt | date }}</td>\r\n          <td class=\"right\">\r\n            {{ row.payment | currency }}<br> {{ row.grossSalary | currency }}\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"!$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              <i class=\"fa fa-square-o\"></i>\r\n            </button>\r\n            <button title=\"{{'SALAXY.UI_Terms.unselect' | sxyTranslate}}\" class=\"btn btn-block btn-transparent\" type=\"button\" ng-if=\"$ctrl.isSelected(row)\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              <i class=\"fa fa-check-square-o\"></i>\r\n            </button>\r\n          </td>\r\n          <td class=\"middle \">\r\n            <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-block btn-default\"><i class=\"fa fa-file-pdf-o visible-xs\"></i> <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.printable\" pre=\" \"></span></a>\r\n          </td>\r\n          <td class=\"middle \">\r\n            <button ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-block btn-default\"><i class=\"fa fa-info-circle visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\" pre=\" \"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/SalaryReportsPanel.html\",`<div class=\"salaxy-odata-panel list-panel report-list-panel panel panel-sm panel-secondary\" ng-init=\"hideFilter = false\">\r\n  <div class=\"panel-heading\">\r\n    {{('SALAXY.NG1.SalaryReportsComponent.calculations' | sxyTranslate) }}\r\n    <div class=\"pull-right\" ng-show=\"$ctrl.items.length > 0\">\r\n      <button class=\"btn btn-secondary btn-xs\" ng-click=\"hideFilter = !hideFilter\" title=\"Näytä suodattimet\">\r\n        <i class=\"fa fa-filter\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-body filters text-right\" ng-class=\"{'showfilters' : hideFilter}\">\r\n    <div class=\"filter-buttons\">\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.UI_Terms.abc\"></button>\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"endAt\">\r\n          <i class=\"fa fa-calendar\"></i>\r\n      </button>\r\n      <button class=\"btn btn-xs btn-secondary text-right\" sxy-orderby=\"grossSalary\">€</button>\r\n    </div>\r\n    <salaxy-input name=\"search1cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search hidden-xxs\" label-type=\"plain\">\r\n    </salaxy-input>\r\n  </div>\r\n  <div ng-class=\"$ctrl.getCssClass()\">\r\n\r\n    <div class=\"visible-xxs\" ng-if=\"$ctrl.items.length > 0\">\r\n      <div class=\"table-filter-container-mobile\">\r\n        <salaxy-input name=\"search2cp{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n        </salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-body text-center panel-content lg-height align-middle\" ng-show=\"$ctrl.items.length == 0 && !$ctrl.isLoading\">\r\n      <div>\r\n        <h3 sxy-text=\"SALAXY.NG1.SalaryReportsComponent.noCalculations\"></h3>\r\n      </div>\r\n    </div>\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\" ng-if=\"$ctrl.items.length > 0\">\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.items\">\r\n\r\n            <td class=\"td-avatar middle  hidden-xxs\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\">\r\n              <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\">{{ 'SALAXY.NG1.SalaryReportsComponent.notSelected' | sxyTranslate }}</span>\r\n              <strong>{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ row.grossSalary | currency }}\r\n              <br>\r\n              <small>{{ row.endAt | date }}</small>\r\n            </td>\r\n\r\n            <td class=\"middle right\">\r\n              <a ng-href=\"{{$crud.getPdfUrl(row)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i class=\"fa fa-file-pdf-o\"></i></a>\r\n              <button href=\"\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i class=\"fa fa-info\"></i></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <div class=\"salaxy-odata-footer\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel-footer text-center\">\r\n    <a ng-href=\"#{{$crud.getDefaults().listUrl}}\" title=\"Näytä kaikki\" class=\"btn btn-primary btn-sm\" sxy-text=\"SALAXY.UI_Terms.showAll\"></a>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/SelectListItem.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"{{'SALAXY.UI_Terms.textSearch' |sxyTranslate}}\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th>\r\n            <div><span class=\"label label-primary clickable\" ng-if=\"$ctrl.selectedItems.length\" ng-click=\"$ctrl.selectedItems.splice(0,$ctrl.selectedItems.length)\"> {{'SALAXY.UI_Terms.chosen' | sxyTranslate}}: {{ $ctrl.selectedItems.length }} <i class=\"fa fa-times-circle\"></i></span></div>\r\n            <div sxy-orderby=\"shortText\">Teksti</div>\r\n          </th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\"  sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\"  sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th>\r\n            <div sxy-orderby=\"status\">Tila</div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"{{'SALAXY.UI_Terms.textSearch' |sxyTranslate}}\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar ng-if=\"row.otherPartyInfo.avatar.displayName\" avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"td-name middle\">\r\n            <div><strong>{{row.shortText }}</strong></div>\r\n            <div>{{ row.otherPartyInfo.avatar.displayName }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ row.createdAt | sxyDate }}</div>\r\n            <div>{{ row.updatedAt | sxyDate }}</div>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.status }}</div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/ServiceModels.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th sxy-text=\"SALAXY.NG1.ServiceModelsComponent.serviceModel\"></th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"middle\">\r\n            <img ng-if=\"row.data.icon || row.ownerInfo.avatar.url\" ng-src=\"{{row.data.icon || row.ownerInfo.avatar.url}}\" style=\"width: 45px; height: 45px;\" />\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div ng-if=\"row.id == row.ownerInfo.avatar.id\">\r\n              <strong ng-if=\"!row.shortText\">{{'SALAXY.NG1.ServiceModelsComponent.defaultModel' | sxyTranslate}}  {{ row.ownerInfo.avatar.displayName }}</strong>\r\n              <strong ng-if=\"row.shortText\">{{ row.shortText || ('SALAXY.NG1.ServiceModelsComponent.nameless' | sxyTranslate) }}</strong>\r\n            </div>\r\n            <div ng-if=\"row.id != row.ownerInfo.avatar.id\">\r\n              <strong>{{ row.shortText || ('SALAXY.NG1.ServiceModelsComponent.nameless' | sxyTranslate) }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div title=\"{{ row.createdAt }}\">{{ row.createdAt | sxyDate }}</div>\r\n            <div title=\"{{ row.updatedAt }}\">{{ row.updatedAt | sxyDate }}</div>\r\n            <div></div>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n                class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Taxcards.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead class=\"\">\r\n        <tr>\r\n          <th colspan=\"2\"><span sxy-orderby=\"otherPartyInfo/avatar/displayName\" sxy-text=\"SALAXY.NG1.TaxcardsListComponent.worker\"></span></th>\r\n          <th class=\"right\">\r\n            <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.TaxcardsListComponent.year\"></span><br />\r\n            </td>\r\n            <th class=\"right\">\r\n              <span sxy-orderby=\"startAt\" sxy-text=\"SALAXY.NG1.TaxcardsListComponent.valid\"></span><br />\r\n              <span sxy-orderby=\"endAt\" sxy-text=\"SALAXY.NG1.TaxcardsListComponent.validTill\"></span><br />\r\n              </td>\r\n              <th class=\"right\">\r\n                <span sxy-text=\"SALAXY.NG1.TaxcardsListComponent.paid\"></span><br>\r\n                <span sxy-text=\"SALAXY.NG1.TaxcardsListComponent.incomeLimit\"></span>\r\n              </th>\r\n              <th>\r\n                <!--div class=\"table-filter-container text-right\">\r\n                  <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" label-type=\"plain\" placeholder=\"SALAXY.UI_Terms.textSearch\"></salaxy-input>\r\n                </div-->\r\n              </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"align-middle td-avatar\">\r\n            <a href=\"#/employments/details/{{row.data.employmentId}}\" class=\"cell-link\" title=\"{{'SALAXY.NG1.WorkerListComponent.editWorker' | sxyTranslate}}\">\r\n              <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </a>\r\n          </td>\r\n          <td class=\"td-name\">\r\n            <strong ng-if=\"row.otherPartyInfo.avatar.displayName\">{{row.otherPartyInfo.avatar.displayName}}</strong>\r\n            <strong ng-if=\"!row.otherPartyInfo.avatar.displayName && row.otherPartyInfo.officialId\">{{'SALAXY.NG1.TaxcardsListComponent.personalId' | sxyTranslate}} : {{row.otherPartyInfo.officialId}}</strong>\r\n            <strong ng-if=\"!row.otherPartyInfo.avatar.displayName && !row.otherPartyInfo.officialId\">{{'SALAXY.NG1.TaxcardsListComponent.unknown' | sxyTranslate}}</strong>\r\n            <br /> {{ \"SALAXY.ENUM.TaxcardKind.\" + row.data.kind + \".label\" | sxyTranslate}}\r\n            <span ng-if=\"row.data.kind !== 'noTaxCard' && row.data.kind !== 'noWithholdingHousehold' && row.data.kind !== 'undefined'\">{{row.data.taxPercent}} %</span>\r\n            <span ng-if=\"row.data.taxPercent2\">\r\n              <br />{{'SALAXY.NG1.TaxcardsListComponent.taxPercent2' | sxyTranslate}} {{row.data.taxPercent2}} %\r\n            </span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <span>{{row.data.forYear}}</span><br />\r\n          </td>\r\n          <td class=\"right\">\r\n            <span>{{row.data.start | sxyDate}}</span><br />\r\n            <span>{{row.data.end | sxyDate}}</span><br />\r\n          </td>\r\n          <td class=\"right\">\r\n            <span class=\"small paidsalaries\">{{ row.data.totalIncome | currency: ' €' : 0 }}</span>\r\n            <span class=\"small incomelimit\">{{(row.data.incomeLimit | currency: ' €' : 0) || '-'}}</span>\r\n            <span class=\"visible-xs visible-sm\"></span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div class=\"btn-group-sm\">\r\n              <button class=\"btn btn-primary\" ng-disabled=\"$ctrl.loaders['showTaxCardAddDialogForTaxCardsList']\" ng-click=\"$crud.showTaxCardAddDialogForTaxCardsList(row);\" ng-if=\"row.otherId && ('!household' | sxyIsInRole)\" sxy-text=\"SALAXY.UI_Terms.addNew\"></button>\r\n              <button title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" ng-click=\"$crud.showDetails(row)\" class=\"btn btn-default\" ng-if=\"'!household' | sxyIsInRole\"><i\r\n                class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n            </div>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/Usecases.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th></th>\r\n          <th sxy-orderby=\"shortText\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.description\"></th>\r\n          <th sxy-orderby=\"entityType\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.entityType\"></th>\r\n          <th class=\"hidden-xxs\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.owner\"></th>\r\n          <th class=\"right\">\r\n            <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n            <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"2\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td>\r\n            <div class=\"thumbnail\" style=\"margin-bottom: 0;\">\r\n              <div class=\"text-center thumbnail-pic-fixed\" style=\"width: 60px;height: 60px\">\r\n                <img ng-if=\"row.data.icon[0] == 'h'\" ng-src=\"{{row.data.icon}}\">\r\n                <div ng-if=\"row.data.icon[0] != 'h'\" class=\"bg-primary thumbnail-pic-icon\" style=\"font-size: 32px\">\r\n                  <i class=\"fa\" ng-class=\"row.data.icon || 'fa-euro'\" aria-hidden=\"true\"></i>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </td>\r\n          <td>\r\n            <div><strong>{{ row.shortText }}</strong></div>\r\n            <div>{{ row.data.description }}</div>\r\n          </td>\r\n          <td>\r\n            <div>{{ \"ApiItemType.\" + row.entityType | sxyEnum }}</div>\r\n            <div ng-switch=\"row.status\">\r\n              <span class=\"badge\" ng-class=\"$crud.getStatusBgColor(row.status)\">{{ \"UsecaseStatus.\" + row.status | sxyEnum }}</span>\r\n            </div>\r\n          </td>\r\n          <td class=\"align-middle td-avatar hidden-xxs\" title=\"{{ row.ownerInfo.avatar.displayName }}\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ row.createdAt | sxyDate }}</div>\r\n            <div>{{ row.updatedAt | sxyDate }}</div>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n                class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n          </td>\r\n          <td class=\"middle hidden-xxs\">\r\n            <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n                class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n            <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n                class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/UsecasesAdHocReport.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-6 col-md-4\" ng-repeat=\"row in $ctrl.items | orderBy: $crud.getOrder\" ng-if=\"$crud.getActive(row) != 'inactive'\">\r\n      <div class=\"thumbnail\">\r\n        <div class=\"text-center thumbnail-pic-fixed\" style=\"height: 150px;\">\r\n          <img ng-if=\"row.data.icon[0] == 'h'\" ng-src=\"{{row.data.icon}}\">\r\n          <div ng-if=\"row.data.icon[0] != 'h'\" class=\"bg-primary thumbnail-pic-icon\">\r\n            <i class=\"fa\" ng-class=\"row.data.icon || 'fa-euro'\" aria-hidden=\"true\"></i>\r\n          </div>\r\n       </div>\r\n        <div class=\"caption\">\r\n          <h3 class=\"truncate\">{{ row.shortText }}</h3>\r\n          <p style=\"height: 80px;overflow: hidden\">{{ row.data.description }}</p>\r\n          <p ng-switch=\"row.entityType\">\r\n             <a ng-switch-when=\"dataset\" ng-href=\"#/reports/ad-hoc/new?usecase=%2FUsecaseDefinition%2F{{ row.owner }}%2F{{ row.id }}\" class=\"btn btn-primary\" role=\"button\" style=\"color: white\" sxy-text=\"SALAXY.UI_Terms.select\" ps=\"...\"></a>\r\n            <a ng-switch-default class=\"btn btn-primary\" role=\"button\" style=\"color: white\" sxy-text=\"TODO\" ps=\"...\"></a>\r\n          </p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/UsecasesCalc.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-6 col-md-4\" ng-repeat=\"row in $ctrl.items\" ng-if=\"$crud.getActive(row) != 'inactive'\">\r\n      <div class=\"thumbnail\">\r\n        <div class=\"text-center thumbnail-pic-fixed\" style=\"height: 150px;\">\r\n          <img ng-if=\"row.data.icon[0] == 'h'\" ng-src=\"{{row.data.icon}}\">\r\n          <div ng-if=\"row.data.icon[0] != 'h'\" class=\"bg-primary thumbnail-pic-icon\">\r\n            <i class=\"fa\" ng-class=\"row.data.icon || 'fa-euro'\" aria-hidden=\"true\"></i>\r\n          </div>\r\n          <span class=\"badge pull-right\" ng-class=\"$crud.getStatusBgColor($crud.getActive(row))\">{{ \"UsecaseStatus.\" + $crud.getActive(row) | sxyEnum }}</span>\r\n        </div>\r\n        <div class=\"caption\">\r\n          <h3 class=\"truncate\">{{ row.shortText }}</h3>\r\n          <p style=\"height: 80px;overflow: hidden\">{{ row.data.description }}</p>\r\n          <p ng-switch=\"row.entityType\">\r\n            <a ng-switch-when=\"calculation\" ng-href=\"#/calc/usecase/new?usecase=%2FUsecaseDefinition%2F{{ row.owner }}%2F{{ row.id }}\" class=\"btn btn-primary\" role=\"button\" style=\"color: white\" sxy-text=\"SALAXY.UI_Terms.createNew\" ps=\"...\"></a>\r\n            <a ng-switch-default class=\"btn btn-primary\" role=\"button\" style=\"color: white\" sxy-text=\"TODO\" ps=\"...\"></a>\r\n          </p>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/UsecaseSelect.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <div class=\"visible-xxs\">\r\n    <div class=\"table-filter-container-mobile\">\r\n      <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" placeholder=\"SALAXY.UI_Terms.textSearch\" class=\"salaxy-odata-table-search\" label-type=\"plain\">\r\n      </salaxy-input>\r\n    </div>\r\n  </div>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            <div sxy-orderby=\"shortText\" sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.name\"></div>\r\n          </th>\r\n          <th sxy-orderby=\"owner\" colspan=\"2\">\r\n            <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.owner\"></div>\r\n          </th>\r\n          <th class=\"right hidden-xxs\" colspan=\"3\">\r\n            <div class=\"table-filter-container\">\r\n              <salaxy-input name=\"search{{::$id}}\" ng-model=\"$ctrl.options.$search\" ng-change=\"$ctrl.searchChanged()\" class=\"salaxy-odata-table-search\" placeholder=\"SALAXY.UI_Terms.textSearch\" label-type=\"plain\"></salaxy-input>\r\n            </div>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.items\">\r\n          <td class=\"td-avatar middle\">\r\n            <div>\r\n              <strong>{{ row.shortText }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div title=\"{{ row.shortText }} ({{ row.id }})\">\r\n              <strong>{{ row.otherPartyInfo.avatar.displayName }}</strong>\r\n            </div>\r\n          </td>\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <div>{{ row.ownerInfo.avatar.displayName }}</div>\r\n          </td>\r\n          <td></td>\r\n          <td class=\"right middle\">\r\n            <button class=\"btn btn-sm\" type=\"button\" ng-class=\"$ctrl.isSelected(row) ? 'btn-danger' : 'btn-info'\" ng-click=\"$ctrl.setSelected(row, 'toggle')\">\r\n              {{ $ctrl.isSelected(row) ? ('SALAXY.UI_Terms.unselect' | sxyTranslate) : ('SALAXY.UI_Terms.select' | sxyTranslate) }}\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/WorktimeImport.html\",`<div ng-class=\"$ctrl.getCssClass()\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-orderby=\"id\">\r\n          <div>Title</div>\r\n          <div sxy-text=\"SALAXY.NG1.ApiCrudObjectComponent.id\"></div>\r\n        </th>\r\n        <th sxy-orderby=\"status\"  sxy-text=\"SALAXY.UI_Terms.status\"></th>\r\n        <th class=\"right\">\r\n          <div sxy-orderby=\"createdAt\" sxy-text=\"SALAXY.UI_Terms.created\"></div>\r\n          <div sxy-orderby=\"updatedAt\" sxy-text=\"SALAXY.UI_Terms.updated\"></div>\r\n        </th>\r\n        <th class=\"right\">Files</th>\r\n        <th class=\"right\">\r\n          <div>Empl.</div>\r\n          <div>Rows</div>\r\n        </th>\r\n        <th class=\"right\">\r\n          Errors\r\n        </th>\r\n        <th class=\"right\">\r\n          <div>Period</div>\r\n          <div>Salary date</div>\r\n        </th>\r\n        <th colspan=\"2\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.items\">\r\n        <td>\r\n          <div>{{ row.shortText || \"-\" }}</div>\r\n          <div><code><small>{{ row.id }}</small></code></div>\r\n        </td>\r\n        <td>{{ row.status }}</td>\r\n        <td class=\"right\">\r\n          <div>{{ row.createdAt | sxyTime }}</div>\r\n          <div>{{ row.updatedAt | sxyTime }}</div>\r\n        </td>\r\n        <td class=\"right\">{{ row.data.filesCount || \"-\" }}</td>\r\n        <td class=\"right\">\r\n          <div>{{ row.data.employmentsCount || \"-\" }}</div>\r\n          <div>{{ row.data.rowsCount || \"-\" }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div ng-class=\"row.data.employmentsErrors ? 'text-danger' : 'text-success'\">{{ row.data.employmentsErrors || \"OK\" }}</div>\r\n          <div ng-class=\"row.data.employmentsErrors ? 'text-danger' : 'text-success'\">{{ row.data.rowsErrors || \"OK\" }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div>{{ row | sxyDateRange }}</div>\r\n          <div>{{ row.salaryDate | sxyDate }}</div>\r\n        </td>\r\n        <td>\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary btn-block\"><i\r\n              class=\"fa fa-pencil visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.edit\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showDetails(row)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-info visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.show\"></span></button>\r\n        </td>\r\n        <td>\r\n          <button ng-if=\"!row.isReadOnly\" ng-click=\"$crud.delete(row)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-sm btn-danger btn-block\"><i\r\n              class=\"fa fa-trash visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span></button>\r\n          <button ng-if=\"row.isReadOnly\" ng-click=\"$crud.showCopyAsNew(row)\" title=\"{{ 'SALAXY.UI_Terms.copyAsNew' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><i\r\n              class=\"fa fa-copy visible-xs\"></i><span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></span></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <salaxy-odata-footer></salaxy-odata-footer>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/lists/_default.html\",`<ng-include src=\"$ctrl.$crudController.getDefaults().oDataTemplateUrl || 'salaxy-components/odata/lists/ApiCrudObject.html'\"></ng-include>`);\n\n $templateCache.put(\"salaxy-components/odata/OdataActions.html\",`<div class=\"salaxy-component salaxy-odata-actions\" ng-init=\"$ctrl.$crud = $ctrl.$odata.$crudController\">\r\n  <div>\r\n    <div ng-if=\"$ctrl.showExport\" class=\"btn-group pull-right\" uib-dropdown>\r\n      <button id=\"single-button\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        <i class=\"fa fa-ellipsis-h\" aria-hidden=\"true\"></i>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-controller=\"ExportController as $export\" ng-click=\"$export.showExport($ctrl.getExportable())\" sxy-text=\"SALAXY.NG1.ODataActionsComponent.export\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n\r\n    <div>\r\n      <span class=\"salaxy-form-group-plain\">\r\n        <input type=\"text\" ng-model=\"$ctrl.$odata.options.$search\"  ng-change=\"$ctrl.$odata.searchChanged()\" class=\"form-control\" autocomplete=\"off\"\r\n          id=\"searchx111\" name=\"searchx111\" placeholder=\"{{'SALAXY.UI_Terms.textSearch' | sxyTranslate}}\"\r\n          ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" maxlength=\"1024\">\r\n      </span>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/odata/OdataFooter.html\",`<div class=\"salaxy-component salaxy-odata-footer\">\r\n  <salaxy-spinner></salaxy-spinner>\r\n  <div ng-if=\"$ctrl.getNoItemsMessage()\" class=\"salaxy-odata-no-data\">\r\n    <div ng-class=\"$ctrl.getNoItemsCssClass()\">{{ $ctrl.getNoItemsMessage() | sxyTranslate }}</div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.getPagingView() == 'nextPageLink'\">\r\n    {{'SALAXY.NG1.ODataFooterComponent.showing' | sxyTranslate}} {{ $ctrl.$odata.count ? ($ctrl.$odata.items.length + \"/\" + $ctrl.$odata.count) : $ctrl.$odata.items.length }} {{'SALAXY.NG1.ODataFooterComponent.rows' | sxyTranslate}}.\r\n    <a href=\"\" ng-click=\"$ctrl.$odata.loadNextPage(true)\" sxy-text=\"SALAXY.NG1.ODataFooterComponent.downloadMore\" ps=\"...\"></a>\r\n  </div>\r\n  <div ng-if=\"$ctrl.getPagingView() == 'clientLimit'\">\r\n    {{'SALAXY.NG1.ODataFooterComponent.showing' | sxyTranslate}} {{ $ctrl.$odata.count ? ($ctrl.$odata.items.length + \"/\" + $ctrl.$odata.count) : $ctrl.$odata.items.length }} {{'SALAXY.NG1.ODataFooterComponent.rows' | sxyTranslate}}.\r\n    <a href=\"\" ng-click=\"$ctrl.$odata.options.$top = null; $ctrl.$odata.reload()\" sxy-text=\"SALAXY.NG1.ODataFooterComponent.downloadMore\" ps=\"...\"></a>\r\n  </div>\r\n  <div ng-if=\"$ctrl.getPagingView() == 'url'\">\r\n    {{'SALAXY.NG1.ODataFooterComponent.showing' | sxyTranslate}} {{ $ctrl.$odata.count ? ($ctrl.$odata.items.length + \"/\" + $ctrl.$odata.count) : $ctrl.$odata.items.length }} {{'SALAXY.NG1.ODataFooterComponent.rows' | sxyTranslate}}.\r\n    <a ng-href=\"{{$ctrl.nextPageUrl}}\" sxy-text=\"SALAXY.NG1.ODataFooterComponent.showAll\" ps=\"...\"></a>\r\n  </div>\r\n  <div ng-if=\"$ctrl.getPagingView() == 'server'\">\r\n    {{'SALAXY.NG1.ODataFooterComponent.showingRows' | sxyTranslate}} rivit {{ ($ctrl.$odata.options.$skip || 0) + 1 }} - {{ ($ctrl.$odata.options.$skip || 0) + $ctrl.$odata.items.length }}\r\n    <span ng-if=\"$ctrl.count\"> {{'SALAXY.NG1.ODataFooterComponent.total' | sxyTranslate}} {{ $ctrl.$odata.count }} {{'SALAXY.NG1.ODataFooterComponent.rows' | sxyTranslate}}</span>\r\n    <a href=\"\" ng-click=\"$ctrl.loadNextPage(false)\" sxy-text=\"SALAXY.NG1.ODataFooterComponent.nextPage\" ps=\"...\"></a>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting/details.html\",`<main class=\"salaxy-content sxytpl-accounting-report-viewer\">\r\n  <section>\r\n    <salaxy-accounting-report-viewer model=\"'url'\"></salaxy-accounting-report-viewer>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting/holiday-pay-debt-query.html\",`<main class=\"salaxy-content sxytpl-accounting-holiday-pay-debt-report-query\">\r\n  <section>\r\n    <salaxy-accounting-holiday-pay-debt-report-query></salaxy-accounting-holiday-pay-debt-report-query>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting/index.html\",`<main class=\"salaxy-content sxytpl-accounting-report-list\">\r\n  <section class=\"text-right\">\r\n    <div class=\"spacer-bottom\">\r\n      <span>\r\n        <a class=\"btn btn-default\" href=\"#/accounting/query\" >{{ \"SALAXY.NG1_Sitemap.reports.accountingQuery\" | sxyTranslate}}...</a>\r\n      </span>\r\n    </div>\r\n    <div>\r\n      <span>\r\n        <a class=\"btn btn-default\" href=\"#/accounting/holiday-pay-debt-query\" >{{ \"SALAXY.NG1_Sitemap.reports.accountingHolidayPayDebtQuery\" | sxyTranslate}}...</a>\r\n      </span>\r\n    </div>\r\n  </section>\r\n  <section>\r\n    <salaxy-accounting-report-list></salaxy-accounting-report-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting/query.html\",`<main class=\"salaxy-content sxytpl-accounting-report-query\">\r\n  <section>\r\n    <salaxy-accounting-report-query></salaxy-accounting-report-query>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting-targets/details.html\",`<main class=\"salaxy-content sxytpl-accounting-target-details\">\r\n  <section>\r\n    <salaxy-accounting-target-details model=\"'url'\"></salaxy-accounting-target-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/accounting-targets/index.html\",`<main class=\"salaxy-content sxytpl-accounting-target-list\">\r\n  <section>\r\n    <div class=\"salaxy-component salaxy-accounting-target-list\">\r\n      <salaxy-odata-table crud-controller=\"AccountingTargetCrudController as $crud\">\r\n      </salaxy-odata-table>\r\n    </div>\r\n  </section>\r\n</main>\r\n \r\n `);\n\n $templateCache.put(\"salaxy-components/pages/calc/all.html\",`<main class=\"salaxy-content sxytpl-calculations-all-list\">\r\n  <section>\r\n    <salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\"></salaxy-action-button>\r\n    <salaxy-calc-list category=\"all\"></salaxy-calc-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/details.html\",`<main class=\"salaxy-content sxytpl-calc-details\">\r\n  <section>\r\n    <salaxy-calc-usecase ng-if=\"'test' | sxyIsInRole\" model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-calc-usecase>\r\n    <salaxy-calc ng-if=\"!('test' | sxyIsInRole)\" model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-calc>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/draft.html\",`<main class=\"salaxy-content sxytpl-calculations-draft-list\">\r\n  <section>\r\n    <salaxy-action-button ng-if=\"!$ctrl.route.readOnly\" action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\"></salaxy-action-button>\r\n    <salaxy-calc-list category=\"draft\" read-only=\"$ctrl.route.readOnly\"></salaxy-calc-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/editor.html\",`<salaxy-calc-editor model=\"'url'\">\r\n</salaxy-calc-editor>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/error.html\",`<main class=\"salaxy-content sxytpl-calculations-error-list\">\r\n  <section>\r\n    <salaxy-calc-list category=\"error\"></salaxy-calc-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/history.html\",`<div ng-controller=\"Calculator2022Controller as $ctrl\" ng-init=\"$ctrl.updateRows = false;$ctrl.model = 'url';\">\r\n  <!-- TODO: Move texts to the model as much as possible. -->\r\n  <h2 sxy-text=\"SALAXY.NG1_Pages.Calc.History.heading\"></h2>\r\n  <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.Calc.History.lead\"></p>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"Calculation\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n      <div>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.workerJobLabel\"></legend>\r\n          <salaxy-calc-employment model=\"$ctrl\" update-rows=\"false\"></salaxy-calc-employment>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.payrollInfo\"></legend>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.salaryDateLabel\" model=\"form.workflow.salaryDate\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.workStartDateLabel\" model=\"form.info.workStartDate\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.workEndDateLabel\" model=\"form.info.workEndDate\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.statusLabel\" model=\"form.workflow.status\" read-only=\"true\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.fixedTaxAmountLabel\" model=\"form.worker.tax.fixedTaxAmount\" format=\"euro\"></sxy-input>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.rows\"></legend>\r\n          <salaxy-calc-rows-2019-editor parent=\"$ctrl.current\" title=\"{{'SALAXY.NG1_Pages.Calc.History.payrollRows' | sxyTranslate}}\" on-commit=\"$ctrl.historyUsecase.recalculate()\" show-edit-buttons=\"false\" show-gross-totals=\"false\"\r\n            is-in-edit=\"!$ctrl.current.isReadOnly\"></salaxy-calc-rows-2019-editor>\r\n        </fieldset>\r\n        <div class=\"text-right\">\r\n          <button ng-if=\"$ctrl.showAction('recalculate')\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.historyUsecase.recalculate()\" sxy-text=\"SALAXY.NG1_Pages.Calc.History.reCalculate\"></button>\r\n        </div>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.cumulativePayrollRows\"></legend>\r\n          <p sxy-html=\"SALAXY.NG1_Pages.Calc.History.cumulativePayrollInfo.html\"></p>\r\n          <table class=\"table\">\r\n            <colgroup>\r\n              <col width=\"35%\">\r\n              <col width=\"15%\">\r\n              <col width=\"35%\">\r\n              <col width=\"15%\">\r\n            </colgroup>\r\n            <tbody>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.totalGrossSalary\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.totals.totalGrossSalary | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.benefits\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.benefits | currency }}</td>\r\n              </tr>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.holidayCompensation\" ps=\"*\"></th>\r\n                <td class=\"right\">{{ $ctrl.getRowTotal(\"holidayCompensation\") | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.holidayBonus\" ps=\"*\"></th>\r\n                <td class=\"right\">{{ $ctrl.getRowTotal(\"holidayBonus\") | currency }}</td>\r\n              </tr>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.holidaySalary\" ps=\"*\"></th>\r\n                <td class=\"right\">{{ $ctrl.getRowTotal(\"holidaySalary\") | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.totalTaxable\" ps=\"*\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.totals.totalTaxable | currency }}</td>\r\n              </tr>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.tax\" ps=\"*\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.tax | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.pension\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.pension | currency }}</td>\r\n              </tr>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.unemploymentInsurance\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.unemploymentInsurance | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.deductions\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.deductions | currency }}</td>\r\n              </tr>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.totalExpenses\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.totals.totalExpenses | currency }}</td>\r\n                <th sxy-text=\"SALAXY.NG1_Pages.Calc.History.salaryPayment\"></th>\r\n                <td class=\"right\">{{ $ctrl.current.result.workerCalc.salaryPayment | currency }}</td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </fieldset>\r\n        <div class=\"text-right\" ng-if=\"$ctrl.showAction('save')\">\r\n          <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.historyUsecase.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n        </div>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/import-calcs.html\",`<main class=\"salaxy-content\">\r\n  <section>\r\n    <!-- Forcing isFullWidth  -->\r\n    <div style=\"display: none;\" ng-init=\"$ctrl.current.isFullWidth = true\"></div>\r\n    <uib-tabset>\r\n      <uib-tab index=\"'default'\" heading=\"Palkkalaskelmien tuonti\">\r\n        <salaxy-calc-import></salaxy-calc-import>\r\n      </uib-tab>\r\n      <uib-tab index=\"'list'\" heading=\"Palkkalistat\">\r\n        <salaxy-payroll-list details-url=\"/payroll/details/\" hide-button=\"$ctrl.route.readOnly\" is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-payroll-list>\r\n      </uib-tab> \r\n    </uib-tabset>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/index.html\",`<main class=\"salaxy-content sxytpl-calculations-dashboard\">\r\n  <section>\r\n    <salaxy-calc-dashboard hide-button=\"$ctrl.route.readOnly\" read-only=\"$ctrl.route.readOnly\"></salaxy-calc-dashboard>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/ircalc.html\",`<salaxy-ir-calc model=\"'url'\"></salaxy-ir-calc>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/paid.html\",`<main class=\"salaxy-content sxytpl-calculations-paid-list\">\r\n  <section>\r\n    <salaxy-action-button ng-if=\"!$ctrl.route.readOnly\" action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\"></salaxy-action-button>\r\n    <salaxy-calc-list category=\"paid\" read-only=\"$ctrl.route.readOnly\"></salaxy-calc-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/payment.html\",`<main class=\"salaxy-content sxytpl-calc-payment\">\r\n  <section>\r\n    <div class=\"container\" ng-controller=\"CalculationCrudController as $calc\" ng-init=\"$calc.model='url'\">\r\n      <salaxy-invoices-create ng-if=\"$calc.current\" model=\"$calc.current\"></salaxy-invoices-create>\r\n    </div>\r\n  </section>\r\n</main>\r\n`);\n\n $templateCache.put(\"salaxy-components/pages/calc/shared.html\",`<main class=\"salaxy-content sxytpl-calculations-shared-list\">\r\n  <section>\r\n    <salaxy-calc-list category=\"shared\" read-only=\"$ctrl.route.readOnly\"></salaxy-calc-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calc/travel.html\",`<div ng-controller=\"Calculator2022Controller as $ctrl\" ng-init=\"$ctrl.updateRows = false;$ctrl.model = 'url';\">\r\n  <!-- TODO: Move texts to the model as much as possible. -->\r\n  <h2>Matkalasku</h2>\r\n  <p class=\"lead\"></p>\r\n  <salaxy-spinner ng-if=\"!$ctrl.current\"></salaxy-spinner>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"Calculation\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n      <div>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.workerJobLabel\"></legend>\r\n          <salaxy-calc-employment model=\"$ctrl\" update-rows=\"false\"></salaxy-calc-employment>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1_Pages.Calc.History.payrollInfo\"></legend>\r\n          <sxy-input label=\"Matkan alku\" model=\"form.info.workStartDate\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.workEndDateLabel\" model=\"form.info.workEndDate\"></sxy-input>\r\n          <sxy-input label=\"SALAXY.NG1_Pages.Calc.History.statusLabel\" model=\"form.workflow.status\" read-only=\"true\"></sxy-input>\r\n        </fieldset>\r\n        <salaxy-calc-rows-editor parent=\"$ctrl.current\" title=\"Matkalaskun rivit\" on-commit=\"$ctrl.recalculate()\"\r\n          show-edit-buttons=\"false\" show-gross-totals=\"true\" ng-ref=\"$rows\"\r\n          is-in-edit=\"!$ctrl.current.isReadOnly\">\r\n          <footer>\r\n            <p>Lisää matkalaskun rivi:</p>\r\n            <button class=\"btn btn-default\" ng-click=\"$rows.showEdit({ rowType: 'expenses' })\">Kulu</button>\r\n            <button class=\"btn btn-default\" ng-click=\"$rows.showEdit({ rowType: 'milageOwnCar' })\">Kilometrikorvaus</button>\r\n            <button class=\"btn btn-default\" ng-click=\"$rows.showEdit({ rowType: 'dailyAllowance' })\">Päiväraha</button>\r\n          </footer>\r\n        </salaxy-calc-rows-editor>\r\n        <div class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculate()\" sxy-text=\"SALAXY.NG1_Pages.Calc.History.reCalculate\"></button>\r\n          <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n        </div>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/calendar/details.html\",`<main class=\"salaxy-content sxytpl-calendar-details\">\r\n  <section>\r\n    <form name=\"frmEvent\">\r\n      <h2 sxy-text=\"SALAXY.NG1_Pages.Calendar.heading\"></h2>\r\n      <salaxy-calendar-event-details ng-ref=\"$ctrl.$calendar\" model=\"'url'\"></salaxy-calendar-event-details>\r\n      <hr />\r\n      <div>\r\n        <a href=\"#/calendar-events\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.back\"></a>\r\n        <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.$calendar.save()\" ng-disabled=\"!frmEvent.$valid\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n    </form>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calendar/index.html\",`<main class=\"salaxy-content sxytpl-calendar-index\">\r\n  <section>\r\n    <h1>TODO: Calendar front page</h1>\r\n    <p>\r\n      Todennäköisesti ei events-listaa, vaan occurences-kalenteri. Events-lista erillisenä sivuna.\r\n    </p>\r\n    <salaxy-odata-table crud-controller=\"CalendarEventsCrudController as $crud\"></salaxy-odata-table>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/calendar/occurences.html\",`<div class=\"salaxy-component salaxy-calendar-event-list\" ng-controller=\"CalendarOccurencesController as $ctrl\">\r\n  <h1 sxy-text=\"SALAXY.NG1_Pages.Calendar.Occurences.accountantCalendar\"></h1>\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Calendar buttons\" style=\"margin-top: -10px; margin-bottom: 15px;\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Kategoriat 2\">\r\n      <div class=\"form-inline\">\r\n        <salaxy-input-enum ng-model=\"$ctrl.categories\" options=\"$ctrl.categorySelections\" name=\"categories\" label-type=\"no-label\" label-cols=\"none\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Periodi\">\r\n      <div class=\"form-inline\">\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.range.start\" name=\"start\" label=\"SALAXY.NG1_Pages.Calendar.Occurences.periodLabel\" label-type=\"inline\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.range.end\" name=\"end\" label=\"\" label-type=\"no-label\" label-cols=\"none\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Actions\">\r\n      <div class=\"form-inline\">\r\n        <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.reload()\" sxy-text=\"SALAXY.UI_Terms.download\"></button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div ng-init=\"$ctrl.currentTab = 'week'\">\r\n    <uib-tabset active=\"$ctrl.currentTab\" ng-if=\"!$ctrl.isLoading\">\r\n      <uib-tab index=\"'list'\" heading=\"{{'SALAXY.NG1_Pages.Calendar.Occurences.listHeading' | sxyTranslate}}\">\r\n        <ng-include ng-if=\"$ctrl.currentTab == 'list'\" src=\"'salaxy-components/workflow/calendar/Occurences-list.html'\"></ng-include>\r\n      </uib-tab>\r\n      <uib-tab index=\"'daily'\" heading=\"{{'SALAXY.NG1_Pages.Calendar.Occurences.dailyHeading' | sxyTranslate}}\">\r\n        <ng-include ng-if=\"$ctrl.currentTab == 'daily'\" src=\"'salaxy-components/workflow/calendar/Occurences-daily.html'\"></ng-include>\r\n      </uib-tab>\r\n      <uib-tab index=\"'week'\" heading=\"{{'SALAXY.NG1_Pages.Calendar.Occurences.weekHeading' | sxyTranslate}}\">\r\n        <ng-include ng-if=\"$ctrl.currentTab == 'week'\" src=\"'salaxy-components/workflow/calendar/Occurences-week.html'\"></ng-include>\r\n      </uib-tab>\r\n      <uib-tab index=\"'debug'\" heading=\"Debugger\">\r\n        <salaxy-json-formatter json=\"$ctrl.list\"></salaxy-json-formatter>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/customer-invoices/details.html\",`<main class=\"salaxy-content sxytpl-datasets-details\">\r\n  <section>\r\n    <h1>TODO: Laskunäkymä</h1>\r\n    <div ng-controller=\"CustomerInvoiceCrudController as $ctrl\" ng-init=\"$ctrl.model = 'url'\">\r\n      <salaxy-spinner ng-if=\"!$ctrl.current\"></salaxy-spinner>\r\n      <div ng-if=\"$ctrl.current\">\r\n        <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\">Tallenna</button>\r\n        <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"CustomerInvoice\" auto-gen=\"true\" debugger=\"true\" model=\"$ctrl.current\">\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/customer-invoices/index.html\",`<main class=\"salaxy-content sxytpl-datasets-list\">\r\n  <section>\r\n    <a href=\"#/customer-invoices/details/new\" class=\"btn btn-primary\" sxy-text=\"Luo uusi\"></a>\r\n    <salaxy-odata-table crud-controller=\"CustomerInvoiceCrudController as $crud\"></salaxy-odata-table>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/datasets/details.html\",`<main class=\"salaxy-content sxytpl-datasets-details\">\r\n  <section>\r\n    <salaxy-dataset-details mode=\"full-edit\" model=\"'url'\"></salaxy-dataset-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/datasets/index.html\",`<main class=\"salaxy-content sxytpl-datasets-list\">\r\n  <section>\r\n    <a href=\"#/datasets/details/new\" class=\"btn btn-primary pull-right\" sxy-text=\"Luo uusi\"></a>\r\n    <h1>{{'Datasets' | sxyTranslate}}<span class=\"badge bg-primary\">BETA</span></h1>\r\n    <salaxy-odata-table crud-controller=\"DatasetsCrudController as $crud\"></salaxy-odata-table>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/employments/details.html\",`<main class=\"salaxy-content sxytpl-workers-details\">\r\n  <section>\r\n    <salaxy-employment-details model=\"'url'\" list-url=\"/employments/index\" is-read-only-forced=\"$ctrl.route.readOnly\" hide-buttons=\"$ctrl.route.readOnly\"></salaxy-employment-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/employments/index.html\",`<main class=\"salaxy-content sxytpl-workers-list\">\r\n  <section>\r\n    <salaxy-employment-list show-toolbar=\"true\" read-only=\"$ctrl.route.readOnly\"></salaxy-employment-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/employments/taxcards.html\",`<main class=\"salaxy-content sxytpl-workers-taxcardslist\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.Workers.Taxcards.lead\"></p>\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-tax-cards-list></salaxy-tax-cards-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/home/error404.html\",`<main class=\"salaxy-content sxytpl-home-error404\">\r\n  <section>\r\n    <h1 class=\"page-header\" sxy-text=\"SALAXY.NG1_Pages.Home.Error.pageNotFound\"></h1>\r\n    <p class=\"lead\" sxy-html=\"SALAXY.NG1_Pages.Home.Error.lead.html\"></p>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/home/index.html\",`<main class=\"salaxy-content sxytpl-home-index\" salaxy-if-role=\"auth\">\r\n  <salaxy-signing ng-ref=\"$ctrl.$signing\" show-in-popup=\"true\"></salaxy-signing>\r\n  \r\n  <div ng-if=\"$ctrl.$signing.isSigningOk\">\r\n    <section ng-if=\"$ctrl.showKyc\">\r\n      <salaxy-alert ng-if=\"$ctrl.applicationId !== 'HAUSVISE'\" type=\"warning\" class=\"alert-insurance-and-pension\" force-more-info=\"true\">\r\n        <main>\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-11\">\r\n              <p class=\"lead lead-with-text\">Päivitä asiakkaan tuntemistiedot (KYC)</p>            \r\n            </div>\r\n          </div>\r\n        </main>\r\n        <aside>\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-11\">\r\n              <p>\r\n                <span>\r\n                  Asiakasvaratilin kautta maksaminen (esim. Paytrail, viitemaksu) edellyttää asiakkaan tuntemistietojen (KYC) päivittämisen. Päivityksen voi tehdä nimenkirjoitusoikeudellinen henkilö “Päivitä asiakkaan tuntemistiedot nyt” -linkin kautta. Sivulta “Lue ohjeet” löytyy tarkat ohjeet ja linkki päivityksen tekijälle toimitettavaksi, jos et itse voi tehdä päivitystä.\r\n                </span>\r\n              </p>\r\n            </div>\r\n            <div class=\"col-sm-11\">\r\n              <a href=\"https://help.palkkaus.fi/hc/fi/articles/19590957330589-Asiakkaan-tuntemistietojen-päivitys-KYC\" target=\"_blank\" class=\"btn btn-primary\" role=\"button\">Lue ohjeet </a>\r\n              <a ng-href=\"{{('test' | sxyIsInRole) ? 'https://rc-iam.palkkaus.fi/wizard/index.html' : 'https://iam.palkkaus.fi/wizard/index.html'}}\" target=\"_blank\" class=\"btn btn-primary\" role=\"button\">Päivitä asiakkaan tuntemistiedot nyt</a>\r\n            </div>\r\n          </div>\r\n        </aside>\r\n      </salaxy-alert>\r\n      <!-- Hack: Show special alert for FI86POYF0022398945 (Hausvise, Festum Software Oy) -->\r\n      <salaxy-alert ng-if=\"$ctrl.applicationId == 'HAUSVISE'\" type=\"warning\" class=\"alert-insurance-and-pension\" force-more-info=\"true\">\r\n        <main>\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-11\">\r\n              <p class=\"lead lead-with-text\">Päivitä asiakkaan tuntemistiedot (KYC)</p>            \r\n            </div>\r\n          </div>\r\n        </main>\r\n        <aside>\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-11\">\r\n              <p>\r\n                <span>\r\n                  Asiakasvaratilin kautta maksaminen edellyttää asiakkaan tuntemistietojen (KYC) päivittämisen. Päivityksen voi tehdä nimenkirjoitusoikeudellinen henkilö “Päivitä asiakkaan tuntemistiedot nyt” -linkin kautta. Sivulta “Lue ohjeet” löytyy tarkat ohjeet ja linkki päivityksen tekijälle toimitettavaksi. Voit päivittää usean yhtiön tiedot kerralla.\r\n                </span>\r\n              </p>\r\n            </div>\r\n            <div class=\"col-sm-11\">\r\n              <a href=\"https://help.palkkaus.fi/hc/fi/articles/19590957330589-Asiakkaan-tuntemistietojen-päivitys-KYC\" target=\"_blank\" class=\"btn btn-primary\" role=\"button\">Lue ohjeet </a>\r\n              <a ng-href=\"{{('test' | sxyIsInRole) ? 'https://rc-iam.palkkaus.fi' : 'https://iam.palkkaus.fi'}}\" target=\"_blank\" class=\"btn btn-primary\" role=\"button\">Päivitä asiakkaan tuntemistiedot nyt</a>\r\n            </div>\r\n          </div>\r\n        </aside>\r\n      </salaxy-alert>\r\n    </section>\r\n    <section ng-if=\"$ctrl.getRoute('#/').getFlag('features','welcome')\" class=\"sxytpl-welcome\">\r\n      <salaxy-welcome settings-by-proxy=\"false\"></salaxy-welcome>\r\n    </section>\r\n    <section ng-if=\"$ctrl.getRoute('#/').getFlag('features', 'messages')\" class=\"sxytpl-list\">\r\n      <div>\r\n        <h3 class=\"section-title list-title\">Toimenpiteitä odottavat...</h3>\r\n        <salaxy-message-thread-list limit-to=\"10\" read-only=\"$ctrl.route.node.newMessageThreadDisabled\"></salaxy-message-thread-list>\r\n      </div>\r\n    </section>\r\n    <section ng-if=\"$ctrl.getRoute('#/').getFlag('features', 'workerList')\" class=\"sxytpl-list\">\r\n      <salaxy-employment-list limit-to=\"10\" read-only=\"$ctrl.route.node.newCalcDisabled\"></salaxy-employment-list>\r\n    </section>\r\n  </div>\r\n  <section ng-if=\"$ctrl.getRoute('#/').getFlag('features', 'contact')\" class=\"sxytpl-contact-info\">\r\n    <p>&nbsp;</p>\r\n    <salaxy-contact-info hide-contact-info=\"'contactInfoComponent.hideContactInfo' | sxyIsInRole\"></salaxy-contact-info>\r\n  </section>\r\n  <p>&nbsp;</p>\r\n  <p>&nbsp;</p>\r\n\r\n  <p class=\"copyright-text\"><small sxy-text=\"SALAXY.NG1_Pages.Home.copyRight\"></small> <small class=\"copyright-year\">{{$ctrl.getCurrentYear()}}</small></p>\r\n\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/household-years/active.html\",`\r\n<div ng-controller=\"HouseholdYearCrudController as $ctrl\" ng-init=\"$ctrl.setActiveYear()\">\r\n  <salaxy-household-year-details  model=\"$ctrl\" ></salaxy-household-year-details>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/household-years/details.html\",`<salaxy-household-year-details model=\"'url'\" ></salaxy-household-year-details>`);\n\n $templateCache.put(\"salaxy-components/pages/household-years/index.html\",`<salaxy-household-year-list></salaxy-household-year-list>`);\n\n $templateCache.put(\"salaxy-components/pages/info/abc.html\",`<div class=\"row\">\r\n  <div class=\"col-xs-12\">\r\n    <h3>Käyttöohjeet</h3>\r\n    <p class=\"\">\r\n      Ohjelman käyttöohjeet löytyvät tukisivustolta osoitteesta <a href=\"https://help.palkkaus.fi/hc/fi\" target=\"_blank\">help.palkkaus.fi</a>.\r\n    </p>\r\n    <p>Pääset ohjeisiin myös oikean alakulman Apua-napin kautta. Kirjoita hakusana hakukenttään niin saat listauksen siihen liittyvistä ohjeista. Voit siirtyä tukisivustolle ohjeen yläkulmassa olevan nuoli-ikonin kautta. Jos et löydä sopivaa ohjetta, voit\r\n      olla yhteydessä asiakaspalveluumme Apua-napin kautta, sähköpostitse tai puhelimitse, niin autamme sinua!\r\n    </p>\r\n  </div>\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/info/index.html\",`<div class=\"row\">\r\n  <div class=\"col-xs-12\">\r\n    <h3 sxy-text=\"SALAXY.NG1_Pages.Info.instructions\"></h3>\r\n    <p class=\"\" sxy-html=\"SALAXY.NG1_Pages.Info.infoText.html\"></p>\r\n    <p sxy-text=\"SALAXY.NG1_Pages.Info.infoText.info\"></p>\r\n  </div>\r\n\r\n  <div class=\"col-xs-12\" ng-if=\"!$ctrl.route.node.hideButtons\">\r\n    <span sxy-html=\"SALAXY.NG1_Pages.Info.buttons.web.html\"></span>\r\n    <span sxy-html=\"SALAXY.NG1_Pages.Info.buttons.dataProtection.html\"></span>\r\n    <span sxy-html=\"SALAXY.NG1_Pages.Info.buttons.termsOfService.html\"></span>\r\n  </div>\r\n</div>\r\n<div class=\"row\" ng-if=\"!$ctrl.route.node.hideContactInfo\">\r\n  <div class=\"col-xs-12\">\r\n    <h3 sxy-text=\"SALAXY.NG1_Pages.Info.customerService.title\"></h3>\r\n  </div>\r\n  <div class=\"col-xs-12\">\r\n\r\n    <salaxy-contact-info hide-contact-info=\"'contactInfoComponent.hideContactInfo' | sxyIsInRole\"></salaxy-contact-info>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/invoices/company.html\",`<main class=\"salaxy-content sxytpl-company-invoices\">\r\n  <section>  \r\n    <salaxy-company-invoices></salaxy-company-invoices>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/invoices/details.html\",`<main class=\"salaxy-content sxytpl-invoice-details\">\r\n\r\n  <style>\r\n    @media print {\r\n      /*Move to less*/\r\n      .nav-tabs,\r\n      #launcher {\r\n        display: none;\r\n      }\r\n    }\r\n  </style>\r\n  <section ng-controller=\"InvoiceCrudController as $invoice\" ng-init=\"$invoice.model = 'url'\">\r\n    <uib-tabset>\r\n      <uib-tab index=\"'default'\" ng-if=\"$ctrl.route.getFlag('features', 'preview')\" heading=\"{{'SALAXY.NG1_Pages.Invoices.preview' | sxyTranslate}}\">\r\n        <salaxy-invoice-preview model=\"$invoice\"></salaxy-invoice-preview>\r\n      </uib-tab>\r\n      <uib-tab index=\"'calc'\" ng-if=\"$invoice.current && $ctrl.route.getFlag('features', 'calc') && ($invoice.current.header.type == 'foreclosure' || $invoice.current.header.type == 'net' || $invoice.current.header.type == 'gross') && $invoice.getReportCalcs().length\" heading=\"{{'SALAXY.NG1_Pages.Invoices.calcs' | sxyTranslate}}\">\r\n        <salaxy-calc-reports calcs=\"$invoice.getReportCalcs()\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n      </uib-tab>\r\n      <uib-tab index=\"'printAndBarCode'\" ng-if=\"$ctrl.route.getFlag('features', 'printAndBarCode')\" heading=\"{{'SALAXY.NG1_Pages.Invoices.printAndBarCode' | sxyTranslate}}\">\r\n        <div>\r\n          <p class=\"lead\">\r\n            <button type=\"button\" class=\"btn btn-primary pull-right\" onclick=\"window.print()\" sxy-text=\"SALAXY.NG1.PalkkausPersonalPaymentOverviewComponent.printInvoices\"></button>\r\n          </p>\r\n          <div class=\"credit-transfer-container\" ng-if=\"$invoice.current\">\r\n            <salaxy-credit-transfer invoice=\"$invoice.current\"></salaxy-credit-transfer>\r\n          </div>\r\n        </div>\r\n      </uib-tab>\r\n      <uib-tab index=\"'actions'\" ng-if=\"(('test' | sxyIsInRole ) && $invoice.current.header.channel == 'palkkausWS') || $ctrl.route.getFlag('features', 'actions')\" heading=\"{{'SALAXY.NG1_Pages.Invoices.actions' | sxyTranslate}}\">\r\n        <salaxy-invoice-edit model=\"$invoice\"></salaxy-invoice-edit>\r\n      </uib-tab>\r\n      <uib-tab index=\"'debug'\" ng-if=\"'test' | sxyIsInRole\" heading=\"Debug\">\r\n        <p>\r\n          <span class=\"badge bg-primary\">test</span> Debug-toiminnot vain testissä.\r\n        </p>\r\n        <salaxy-json-formatter json=\"$invoice.current\" open=\"1\"></salaxy-json-formatter>\r\n      </uib-tab>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/invoices/index.html\",`<main class=\"salaxy-content sxytpl-invoices-list\">\r\n  <section>  \r\n    <salaxy-invoice-list ng-if=\"'!person' | sxyIsInRole\"></salaxy-invoice-list>\r\n    <salaxy-invoice-list ng-if=\"'person' | sxyIsInRole\" mode=\"person\"></salaxy-invoice-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/invoices/sepa.html\",`<main class=\"salaxy-content sxytpl-invoices-list\">\r\n  <section>  \r\n    <salaxy-invoice-list mode=\"sepa\"></salaxy-invoice-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/irepr/details.html\",`<main class=\"salaxy-content sxytpl-ir-earnings-payment\">\r\n  <section>\r\n    <salaxy-ir-earnings-payment model=\"'url'\"></salaxy-ir-earnings-payment>\r\n  </section>\r\n</main>\r\n`);\n\n $templateCache.put(\"salaxy-components/pages/irepr/index.html\",`<main class=\"salaxy-content sxytpl-ir-earnings-payment-list\">\r\n  <section>\r\n    <salaxy-ir-earnings-payment-list></salaxy-ir-earnings-payment-list>\r\n  </section>\r\n</main>\r\n \r\n `);\n\n $templateCache.put(\"salaxy-components/pages/irpsr/details.html\",`<main class=\"salaxy-content sxytpl-ir-payer-summary\">\r\n  <section>\r\n    <salaxy-ir-payer-summary model=\"'url'\"></salaxy-ir-payer-summary>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/irpsr/index.html\",`<main class=\"salaxy-content sxytpl-ir-payer-summary-list\">\r\n  <section>\r\n    <salaxy-ir-payer-summary-list></salaxy-ir-payer-summary-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/messages/approval-list.html\",`<div>\r\n  <div class=\"btn-toolbar\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-default\"\r\n        ng-click=\"$ctrl.$odata.options.$filter = 'status eq \\\\'active\\\\'';$ctrl.$odata.searchChanged()\"\r\n        ng-class=\"{ active: $ctrl.$odata.options.$filter != null }\">Aktiiviset</button>\r\n      <button type=\"button\" class=\"btn btn-default\"\r\n        ng-click=\"$ctrl.$odata.options.$filter = null;$ctrl.$odata.searchChanged()\"\r\n        ng-class=\"{ active: $ctrl.$odata.options.$filter == null }\">Kaikki</button>\r\n    </div>\r\n  </div>\r\n  <salaxy-odata-table crud-controller=\"MessageThreadCrudController as $crud\" ng-ref=\"$ctrl.$odata\"\r\n    options=\"{ $filter: 'status eq \\\\'active\\\\'' }\"\r\n    template-url=\"salaxy-components/odata/lists/MessageThreadsApproval.html\"></salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/messages/approval.html\",`<main class=\"salaxy-content sxytpl-messages-details\">\r\n  <section>\r\n    <h3>Hyväksy / hylkää aineisto</h3>\r\n    <main>\r\n      <div ng-controller=\"MessageThreadCrudController as $ctrl\" ng-init=\"$ctrl.createCalc=true;$ctrl.model = 'url'\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-4\">\r\n            <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Incoming message toolbar\">\r\n              <div class=\"btn-group\" role=\"group\" aria-label=\"Approval toolbar\">\r\n                <button type=\"button\" class=\"btn btn-success\" ng-click=\"$ctrl.current.status = 'approved';$ctrl.save()\"\r\n                  ng-disabled=\"$ctrl.current.status == 'approved'\">Hyväksy</button>\r\n                <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.current.status = 'rejected';$ctrl.save()\"\r\n                  ng-disabled=\"$ctrl.current.status == 'rejected'\">Hylkää</button>\r\n              </div>\r\n              <div class=\"btn-group\" role=\"group\" aria-label=\"Update toolbar\">\r\n                <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\">Tallenna</button>\r\n              </div>\r\n            </div>\r\n            <div ng-switch=\"$ctrl.current.usecase.data.protoId\">\r\n              <div ng-switch-when=\"timer\">\r\n                <salaxy-timer ng-if=\"$ctrl.current\" timer-mode=\"edit\" parent=\"$ctrl.current\" crud-controller=\"$ctrl\"></salaxy-timer>\r\n              </div>\r\n              <div ng-switch-when=\"hourlyReport\">\r\n                <salaxy-hourly-report ng-if=\"$ctrl.current\" parent=\"$ctrl.current\" report-type=\"$ctrl.current.usecase.data.protoId\" crud-controller=\"$ctrl\"></salaxy-hourly-report>\r\n              </div>\r\n              <div ng-switch-when=\"timeReport\">\r\n                <salaxy-hourly-report ng-if=\"$ctrl.current\" parent=\"$ctrl.current\" report-type=\"$ctrl.current.usecase.data.protoId\" crud-controller=\"$ctrl\"></salaxy-hourly-report>\r\n              </div>\r\n              <div ng-switch-when=\"absence\">\r\n                <salaxy-absence-periods ng-if=\"$ctrl.current\" parent=\"$ctrl.getMessage().contentData\" condensed=\"true\"></salaxy-absence-periods>\r\n              </div>\r\n              <div ng-switch-when=\"annualLeave\">\r\n                <salaxy-holiday-year-holidays ng-if=\"$ctrl.current\" parent=\"$ctrl.getMessage().contentData\" condensed=\"true\"></salaxy-holiday-year-holidays>\r\n              </div>\r\n              <div ng-switch-when=\"calcRow\">\r\n                <salaxy-calc-rows-editor ng-if=\"$ctrl.current\" parent=\"$ctrl.getMessage().contentData\">\r\n                </salaxy-calc-rows-editor>\r\n              </div>\r\n              <div ng-switch-when=\"expense\">\r\n                <salaxy-expense-report ng-if=\"$ctrl.current\" parent=\"$ctrl.current\" report-type=\"$ctrl.current.usecase.data.protoId\" crud-controller=\"$ctrl\">\r\n                </salaxy-expense-report>\r\n              </div>\r\n              <div ng-switch-when=\"travel\">\r\n                <salaxy-expense-report ng-if=\"$ctrl.current\" parent=\"$ctrl.current\" report-type=\"$ctrl.current.usecase.data.protoId\" crud-controller=\"$ctrl\">\r\n                </salaxy-expense-report>\r\n              </div>\r\n              <div ng-switch-when=\"default\">\r\n                <div ng-if=\"$ctrl.isNew()\">\r\n                  <h2>Temp UI: This will be replaced!</h2>\r\n                  <salaxy-input name=\"title\" label=\"SALAXY.NG1.MessageThreadComponent.title\" require=\"true\" ng-model=\"$ctrl.current.title\"></salaxy-input>\r\n                  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\">\r\n                    <span sxy-text=\"SALAXY.UI_Terms.save\"></span>\r\n                  </button>\r\n                  <hr />\r\n                </div>\r\n                <div class=\"messages-container\" ng-if=\"$ctrl.current.messages && !$ctrl.isNew()\">\r\n                  <h2>{{ $ctrl.current.title }}</h2>\r\n                  <div ng-repeat=\"item in $ctrl.current.messages\" ng-switch=\"item.fromParty\">\r\n                    <div ng-switch-when=\"owner,undefined\" ng-switch-when-separator=\",\">\r\n                      <salaxy-avatar avatar=\"$ctrl.current.ownerInfo\" class=\"pull-left\"></salaxy-avatar>\r\n                      <div class=\"message-bubble left\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item)  }\">\r\n                        <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n                        <span class=\"updated-at\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read' |sxyTranslate) + ' ' +\r\n                          ($ctrl.getReadTime(item) | sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate) }}</span>\r\n                      </div>\r\n                    </div>\r\n                    <div ng-switch-when=\"otherParty\" class=\"text-right\">\r\n                      <salaxy-avatar avatar=\"$ctrl.current.otherPartyInfo\" class=\"pull-right\"></salaxy-avatar>\r\n                      <div class=\"message-bubble right {{item.type}}\" ng-class=\"{ 'in-edit': $ctrl.isInEdit, 'unread': !$ctrl.getReadTime(item) }\">\r\n                        <ng-include src=\"'salaxy-components/communications/messages/MessageContent.html'\"></ng-include>\r\n                        <span class=\"updated-at\" ng-if=\"item.type != 'email'\">{{ item.time | sxyTime }}, {{ $ctrl.getReadTime(item) ? (('SALAXY.NG1.MessageThreadComponent.read'\r\n                          |sxyTranslate) + ' ' + ($ctrl.getReadTime(item) | sxyTime)) : ('SALAXY.NG1.MessageThreadComponent.unread' |sxyTranslate)}}</span>\r\n                        <span class=\"updated-at\" ng-if=\"item.type == 'email'\">{{ item.time | sxyTime }}</span>\r\n                      </div>\r\n                    </div>\r\n                    <div ng-switch-default class=\"alert alert-danger\">\r\n                      <ng-include src=\"'salaxy-components/communications/MessageThread_MessageContent.html'\"></ng-include>\r\n                    </div>\r\n                  </div>\r\n                  <div>\r\n                    <div ng-if=\"$ctrl.isReadOnly\" class=\"alert alert-info\">\r\n                      <p><strong>Työnantaja on merkinnyt viestiketjun käsitellyksi.</strong></p>\r\n                    </div>\r\n                    <div class=\"row\">\r\n                      <div class=\"col-xs-8 col-sm-9\">\r\n                        <textarea placeholder=\"{{'SALAXY.NG1.MessageThreadComponent.writeOrPaste' |sxyTranslate}}\" ng-model=\"$ctrl.newMessage.content\"></textarea>\r\n                      </div>\r\n                      <div class=\"col-xs-4 col-sm-3\">\r\n                        <button type=\"button\" class=\"btn btn-primary btn-labeled-left\" style=\"width: 100%; text-align: left; margin-bottom: 4px\" ng-click=\"$ctrl.sendMessage()\"\r\n                          ng-disabled=\"!$ctrl.newMessage.content\"><i class=\"fa fa-paper-plane\"></i>\r\n                          <span sxy-text=\"SALAXY.UI_Terms.send\"></span>\r\n                        </button>\r\n                      </div>\r\n                    </div>\r\n                  </div>\r\n                  <div id=\"messageContainerBottom\">&nbsp;</div>\r\n                </div>\r\n              </div>\r\n              <div ng-switch-default>\r\n                TODO: Handle {{ $ctrl.current.usecase.uri }} / {{ $ctrl.current.usecase.data.protoId }}.\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div class=\"col-sm-8\">\r\n            <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Calculator toolbar\">\r\n              <div class=\"btn-group\" role=\"group\" aria-label=\"Update\">\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.updateCalc()\">Päivitä rivit</button>\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.recalculate()\">Laske uudelleen</button>\r\n              </div>\r\n              <div class=\"btn-group\" role=\"group\" aria-label=\"Select calc / payroll\">\r\n                <button type=\"button\" class=\"btn btn-default\">Valitse palkkalista...</button>\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.selectCalc()\">...laskelma</button>\r\n              </div>\r\n              <div class=\"btn-group\" role=\"group\" aria-label=\"Process calculation\">\r\n                <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.saveCalc()\">Tallenna</button>\r\n                <a ng-href=\"#/calc/details/{{ $ctrl.calc.id }}\" ng-disabled=\"!$ctrl.calc.id\" class=\"btn btn-default\">Siirry laskelmaan</a>\r\n              </div>\r\n            </div>\r\n            <salaxy-calc-rows-2019-editor parent=\"$ctrl.calc\" mode=\"edit\" title=\"Laskelman rivit\"></salaxy-calc-rows-2019-editor>\r\n            <div ng-if=\"$ctrl.calc.result.totals\">\r\n              <salaxy-calc-reports calcs=\"[$ctrl.calc]\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </main>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/messages/details.html\",`<main class=\"salaxy-content sxytpl-messages-details\">\r\n  <section>\r\n    <salaxy-assure-partner>\r\n      <main>\r\n        <salaxy-message-thread model=\"'url'\" role=\"owner\" other-party=\"'partner'\" mark-as-read=\"5\">\r\n          <header-new>\r\n            <h2 sxy-text=\"SALAXY.NG1_Pages.Messages.newMessageDetails.title\"></h2>\r\n            <p class=\"lead\" sxy-html=\"SALAXY.NG1_Pages.Messages.newMessageDetails.description.html\"></p>\r\n          </header-new>\r\n        </salaxy-message-thread>\r\n      </main>\r\n    </salaxy-assure-partner>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/messages/index.html\",`<main class=\"salaxy-content sxytpl-message-thread-list\">\r\n  <section>\r\n    <salaxy-message-thread-list read-only=\"$ctrl.route.readOnly\"></salaxy-message-thread-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/messages/omapalkka.html\",`<div ng-controller=\"OmapalkkaController as $ctrl\">\r\n  <iframe ng-if=\"$ctrl.url\" ng-src=\"{{$ctrl.url}}\" style=\"width: 100%; height: calc(100vh - 180px); margin-bottom: -100px; border: 0;\"></iframe>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/partners/assure-worker-account.html\",`<main class=\"salaxy-content sxytpl-partners-worker-assure\">\r\n    <section>\r\n        <salaxy-worker-assure></salaxy-worker-assure>\r\n    </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/payment-channel/details.html\",`<main class=\"salaxy-content sxytpl-invoices-list\">\r\n  <section ng-controller=\"PaymentChannelController as $ctrl\" ng-init=\"$ctrl.model = 'url'\">\r\n    <div ng-if=\"$ctrl.channel\">\r\n      <salaxy-avatar class=\"salaxy-calc-row-type-avatar salaxy-input-enum-avatar pull-left\" avatar=\"$ctrl.getChannelAvatar()\"></salaxy-avatar>\r\n      <div class=\"salaxy-input-enum-text\"><strong>{{\"PaymentChannel.\" + $ctrl.channel | sxyEnum}}</strong></div>\r\n      <div class=\"salaxy-input-enum-title\">{{ \"PaymentChannel.\" + $ctrl.channel | sxyEnumDescr }}</div>\r\n      <uib-tabset>\r\n        <uib-tab index=\"'default'\" heading=\"Esikatselu\">\r\n          <salaxy-spinner ng-if=\"!$ctrl.current && $ctrl.isLoading\"></salaxy-spinner>\r\n          <salaxy-payment-channel-invoice-preview ng-if=\"$ctrl.current\" model=\"$ctrl\"></salaxy-payment-channel-invoice-preview>\r\n        </uib-tab>\r\n        <uib-tab ng-if=\"'test' | sxyIsInRole\" index=\"'status'\" heading=\"Tilan päivitys\">      \r\n          <div class=\"alert alert-danger\" ng-if=\"!$ctrl.isLoading && !$ctrl.current\">Laskua ei löydy</div>\r\n          <form ng-if=\"$ctrl.current\" ng-submit=\"$ctrl.updateStatus()\">\r\n            <div class=\"form-horizontal\" ng-init=\"$ctrl.resetStatusData()\">\r\n              <h2>Päivitä tila</h2>\r\n              <p>Testilomake tilan päivitykseen. Alta voit myös poistaa laskun.</p>\r\n              <salaxy-input name=\"statusId\" ng-model=\"$ctrl.statusData.id\" label=\"Id\" disabled=\"true\"></salaxy-input>\r\n              <salaxy-input name=\"statusExternalId\" ng-model=\"$ctrl.statusData.externalId\" label=\"ID maksukanavassa\"></salaxy-input>\r\n              <salaxy-input-enum label=\"Maksun tila\" name=\"statusStatus\" ng-model=\"$ctrl.statusData.status\" enum=\"InvoiceStatus\" required></salaxy-input-enum>\r\n              <salaxy-datepicker-popup name=\"statusDate\" ng-model=\"$ctrl.statusData.date\" label=\"Maksupäivä\"></salaxy-datepicker-popup>\r\n              <salaxy-input-number name=\"statusAmount\" ng-model=\"$ctrl.statusData.amount\" label=\"Maksettu summa\"></salaxy-input-number>\r\n              <salaxy-input name=\"statusReceiverFullName\" ng-model=\"$ctrl.statusData.receiverFullName\" label=\"Vastaanottajan nimi\"></salaxy-input>\r\n              <salaxy-input name=\"statusReceiverIban\" ng-model=\"$ctrl.statusData.receiverIban\" label=\"Vastaanottajan tilinumero\"></salaxy-input>\r\n              <salaxy-input name=\"statusReferenceNumber\" ng-model=\"$ctrl.statusData.referenceNumber\" label=\"Viitenumero\"></salaxy-input>\r\n            </div>\r\n            <div>\r\n              <button type=\"submit\" class=\"btn btn-primary pull-right\">Päivitä tila</button>\r\n              <button type=\"button\" ng-click=\"$ctrl.delete()\" class=\"btn btn-danger\">Poista lasku</button>\r\n            </div>\r\n          </form>\r\n        </uib-tab>\r\n        <uib-tab ng-if=\"'test' | sxyIsInRole\" index=\"'edit'\" heading=\"Laskun muokkaus\">      \r\n          <div class=\"alert alert-danger\" ng-if=\"!$ctrl.isLoading && !$ctrl.current\">Laskua ei löydy</div>\r\n          <form ng-if=\"$ctrl.current\" ng-submit=\"$ctrl.save()\">\r\n            <div class=\"form-horizontal\">\r\n              <h2>Muokkaa laskua</h2>\r\n              <p>Testilomake laskun muokkaukseen. Alta voit myös poistaa laskun.</p>\r\n              <salaxy-datepicker-popup name=\"date\" ng-model=\"$ctrl.current.header.date\" label=\"Laskun päivä\"></salaxy-datepicker-popup>\r\n              <salaxy-datepicker-popup name=\"dueDate\" ng-model=\"$ctrl.current.header.dueDate\" label=\"Eräpäivä\"></salaxy-datepicker-popup>\r\n              <salaxy-datepicker-popup name=\"logicalDate\" ng-model=\"$ctrl.current.header.logicalDate\" label=\"Looginen päivä\"></salaxy-datepicker-popup>\r\n              <salaxy-input name=\"message\" ng-model=\"$ctrl.current.header.message\" label=\"Viesti\"></salaxy-input>\r\n            </div>\r\n            <div>\r\n              <button type=\"submit\" class=\"btn btn-primary pull-right\">Tallenna</button>\r\n              <button type=\"button\" ng-click=\"$ctrl.delete()\" class=\"btn btn-danger\">Poista lasku</button>\r\n            </div>\r\n          </form>\r\n        </uib-tab>\r\n        <uib-tab ng-if=\"'test' | sxyIsInRole\" index=\"'debug'\" heading=\"Debug\">\r\n          <salaxy-json-formatter  ng-if=\"$ctrl.current\" json=\"$ctrl.current\" open=\"1\"></salaxy-json-formatter>\r\n        </uib-tab>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.channel && !$ctrl.isLoading\">\r\n      <div class=\"alert alert-danger\">Käyttäjätilillä ei ole omaa maksukanavaa</div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/payment-channel/index.html\",`<main class=\"salaxy-content sxytpl-payment-channel\">\r\n  <section ng-controller=\"PaymentChannelController as $ctrl\">\r\n    <div ng-if=\"$ctrl.channel\">\r\n      <salaxy-avatar class=\"salaxy-calc-row-type-avatar salaxy-input-enum-avatar pull-left\" avatar=\"$ctrl.getChannelAvatar()\"></salaxy-avatar>\r\n      <div class=\"salaxy-input-enum-text\"><strong>{{\"PaymentChannel.\" + $ctrl.channel | sxyEnum}}</strong></div>\r\n      <div class=\"salaxy-input-enum-title\">{{ \"PaymentChannel.\" + $ctrl.channel | sxyEnumDescr }}</div>\r\n      <uib-tabset>\r\n        <uib-tab index=\"'odata'\" heading=\"All items\">\r\n          <salaxy-odata-table crud-controller=\"PaymentChannelController as $crud\" options=\"{ $orderby: 'endAt desc'}\" template-url=\"salaxy-components/odata/lists/InvoicesPaymentChannel.html\">\r\n          </salaxy-odata-table>\r\n        </uib-tab>\r\n        <uib-tab index=\"'fullData'\" heading=\"Unread items\">\r\n          <div>\r\n            <table class=\"table\">\r\n              <thead>\r\n                <tr>\r\n                  <th colspan=\"2\">Payer</th>\r\n                  <th colspan=\"2\">\r\n                    Receiver<br /> Payment type\r\n                  </th>\r\n                  <th class=\"right\">\r\n                    Date<br /> Due date\r\n                  </th>\r\n                  <th class=\"right\">\r\n                    Created<br /> Updated\r\n                  </th>\r\n                  <th class=\"right\">Payment</th>\r\n                  <th></th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"item in $ctrl.unreadInvoices\">\r\n                  <td class=\"td-avatar middle\">\r\n                    <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"item.payer.avatar\"></salaxy-avatar>\r\n                  </td>\r\n                  <td class=\"middle\">\r\n                    {{ item.payer.avatar.displayName }}<br>\r\n                    <small class=\"hidden-xxs\">{{ item.payer.officialId }}, {{ item.payer.partnerKey }}</small>\r\n                  </td class=\"middle\">\r\n                  <td class=\"td-avatar middle\">\r\n                    <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"item.recipient.beneficiary.avatar\"></salaxy-avatar>\r\n                  </td>\r\n                  <td class=\"middle\">\r\n                    {{ item.recipient.beneficiary.avatar.displayName }}<br>\r\n                    <small class=\"hidden-xxs\">{{ item.header.message }}</small>\r\n                  </td class=\"middle\">\r\n                  <td class=\"middle right\">\r\n                    {{ item.header.date | sxyDate }}<br /> {{ item.header.dueDate | sxyDate }}\r\n                  </td>\r\n                  <td class=\"right\">\r\n                    {{ item.createdAt | sxyDate }}<br /> {{ item.updatedAt | sxyDate }}\r\n                  </td>\r\n                  <td class=\"middle right\">\r\n                    {{ item.header.total | currency }}\r\n                  </td>\r\n                  <td class=\"middle right\">\r\n                    <a ng-href=\"#{{$ctrl.getDefaults().detailsUrl}}{{ item.id }}\" class=\"btn btn-primary\">\r\n                      {{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\r\n                    </a>\r\n                  </td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </div>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.channel\">\r\n      <div class=\"alert alert-danger\">Käyttäjätilillä ei ole omaa maksukanavaa</div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/payroll/details.html\",`<main class=\"salaxy-content sxytpl-calculations-payroll-edit\">\r\n  <div ng-if=\"$ctrl.newPayrollVersion.show\" class=\"hidden-xs hidden-sm salaxy-payroll-v4 form-horizontal pull-right\" style=\"z-index:1000; position:relative\">\r\n      <salaxy-input-boolean name=\"newPayrollSwitch\" type=\"switch-xl\" ng-model=\"$ctrl.userSettings.ng1Binder('payroll.newVersion').val\" label=\"SALAXY.NG1.PayrollComponent.newVersion\" label-true=\"on\" label-false=\"off\"></salaxy-input-boolean>\r\n  </div>\r\n  <section ng-if=\"$ctrl.newPayrollVersion.use\">\r\n    <!-- Switching isFullWidth as long as the two UI are in same URL. -->\r\n    <div style=\"display: none;\" ng-init=\"$ctrl.current.isFullWidth = true\"></div>\r\n    <salaxy-payroll-details model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\" actions=\"$ctrl.route.getParam('actions')\"></salaxy-payroll-details>\r\n  </section>\r\n  <section ng-if=\"!$ctrl.newPayrollVersion.use\">\r\n    <div style=\"display: none;\" ng-init=\"$ctrl.current.isFullWidth = false\"></div>\r\n    <salaxy-payroll-edit model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\"\r\n      actions=\"$ctrl.route.getParam('actions')\"></salaxy-payroll-edit>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/payroll/import.html\",`<main class=\"salaxy-content sxytpl-calculations-payroll-import\">\r\n  <section>\r\n    <div ng-controller=\"SalaryBasesController as $ctrl\">\r\n      <div ng-if=\"!$ctrl.datasets\" class=\"container\">\r\n        <salaxy-spinner title=\"Ladataan määrittelyjä...\"></salaxy-spinner>\r\n      </div>\r\n      <div ng-if=\"$ctrl.datasets && !$ctrl.datasets.length\" class=\"alert alert-danger container\">  \r\n        <strong>BETA:</strong>\r\n        Tietojen tuonti (import) on rajoitetussa testauksessa PRO-palvelussa ja tuodaan tuotantoon syksyllä.\r\n        Kysy asiakaspalvelusta lisätietoja ennen kuin käytät tätä toimintoa.\r\n      </div>\r\n      <div ng-if=\"$ctrl.datasets.length && !$ctrl.dataset\" class=\"container\">\r\n        <h3>Valitse Import-tyyppi</h3>\r\n        <div style=\"max-width: 600px;\">\r\n          <label ng-repeat=\"ds in $ctrl.datasets\" class=\"btn btn-block btn-default\" ng-click=\"$ctrl.loadDataset(ds)\">{{ ds.shortText }}</label>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.dataset\">\r\n        <div class=\"btn-toolbar\">\r\n          <div class=\"btn-group\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.getEmployments()\">1. Hae työsuhteet</button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-controller=\"ImportController as $import\" ng-click=\"$import.showImport($ctrl.getImportable())\">2. Lataa data</button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.processImport()\">3. Käsittele data (mapper)</button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.saveToPayroll()\">4. Tallenna palkkalistaan</button>\r\n          </div>\r\n        </div>\r\n        <uib-tabset active=\"$ctrl.currentTab\" ng-if=\"$ctrl.current\">\r\n          <uib-tab index=\"'payroll'\" heading=\"Palkkalista\">\r\n            <salaxy-payroll-edit model=\"'url'\" ng-ref=\"$ctrl.payrollController\"></salaxy-payroll-edit>\r\n          </uib-tab>\r\n          <uib-tab index=\"'employments'\" heading=\"Työsuhteet\">\r\n            <table class=\"table table-condensed\">\r\n              <thead>\r\n                <tr>\r\n                  <th></th>\r\n                  <th>\r\n                    <div>Työntekijän nimi (Palkkaus.fi)</div>\r\n                    <div><small>Työsuhteen tyyppi</small></div>\r\n                  </th>\r\n                  <th class=\"right\">\r\n                    <div>ID lähteessä</div>\r\n                    <div>Tuntia / kk</div>\r\n                  </th>\r\n                  <th>Rivit</th>\r\n                  <th></th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"emp in $ctrl.employments\">\r\n                  <td>\r\n                    <salaxy-avatar style=\"font-size: 50px;\" avatar=\"emp.personalInfo.avatar\"></salaxy-avatar>\r\n                  </td>\r\n                  <td>\r\n                    <div><strong>{{ emp.personalInfo.avatar.displayName }}</strong> ({{ emp.personalInfo.officialId }})</div>\r\n                    <div><small>{{ emp.work.wageBasis }}</small></div>\r\n                    <div><small>{{ emp.updatedAt }}</small></div>\r\n                  </td>\r\n                  <td class=\"right\">\r\n                    <div>{{ emp.info.sourceId || \"-\" }}</div>\r\n                    <div ng-if=\"emp.work.monthlyHours\"><strong>{{ emp.work.monthlyHours }}</strong></div>\r\n                    <div ng-if=\"!emp.work.monthlyHours\" class=\"text-muted\">160</div>\r\n                  </td>\r\n                  <td>\r\n                    <table class=\"table table-condensed\">\r\n                      <tr ng-repeat=\"row in emp.work.salaryDefaults\">\r\n                        <td>{{ \"CalculationRowType.\" + row.rowType | sxyEnum }}</td>\r\n                        <td class=\"right\">{{ row.count | number }} * {{ row.price ? (row.price | currency) : \"-\" }}</td>\r\n                      </tr>\r\n                    </table>                  \r\n                  </td>\r\n                  <td>\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.editEmployment(emp)\">Muokkaa</button>\r\n                  </td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </uib-tab>\r\n          <uib-tab index=\"'rowTypeMapNew'\" heading=\"Säännöt (rivityypit)\">\r\n            <div class=\"toolbar\">\r\n              <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.save()\">Tallenna</button>\r\n            </div>\r\n            <table class=\"table\" ng-controller=\"CalcRows2019Controller as $rows\" ng-init=\"$rows.rows=$ctrl.getRowTypeMapper()\">\r\n              <thead>\r\n                <tr>\r\n                  <th colspan=\"2\">Lähdedata</th>\r\n                  <th></th>\r\n                  <th colspan=\"2\">Kohde</th>\r\n                </tr>\r\n                <tr>\r\n                  <th>Haku</th>\r\n                  <th>RegEx</th>\r\n                  <th>Toiminto</th>\r\n                  <th>\r\n                    <div>Rivityyppi</div>\r\n                    <div>Alatyyppi (kind)</div>\r\n                  </th>\r\n                  <th class=\"right\">\r\n                    <div>Hinta/kerroin</div>\r\n                    <div>Määrä</div>\r\n                  </th>\r\n                  <th>Viesti palkkalaskelmaan</th>\r\n                  <th>Kommentti</th>\r\n                  <th>\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$rows.showRowTypeSelectionDialog()\">Luo uusi</button>\r\n                  </th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"match in $rows.list\">\r\n                  <td ng-if=\"!match.$edit\">{{ match.search }}</td>\r\n                  <td ng-if=\"!match.$edit\">{{ match.searchType }}</td>\r\n                  <td ng-if=\"!match.$edit\">{{ match.type }}</td>\r\n  \r\n                  <td ng-if=\"match.$edit\"><salaxy-input name=\"searh{{ $index }}\" label-type=\"plain\" ng-model=\"match.search\"></salaxy-input></td>\r\n                  <td ng-if=\"match.$edit\"><input type=\"checkbox\" ng-checked=\"match.searchType == 'regExp'\" ng-click=\"match.searchType = (match.searchType != 'regExp' ? 'regExp' : 'string')\"></td>\r\n                  <td ng-if=\"match.$edit\">\r\n                    <salaxy-input-enum options=\"$ctrl.matchTypes\" name=\"type{{ $index }}\" label-type=\"plain\" ng-model=\"match.type\"></salaxy-input-enum>\r\n                  </td>\r\n                  \r\n                  <td>\r\n                    <div>{{ match.rowType }}</div>\r\n                    <div>{{ match.data.kind }}</div>\r\n                  </td>\r\n                  <td class=\"right\">\r\n                    <div>{{ match.price || \"-\" }}</div>\r\n                    <div>{{ match.count || \"-\" }}</div>\r\n                  </td>\r\n                  <td>{{ match.message }}</td>\r\n  \r\n                  <td ng-if=\"!match.$edit\">{{ match.comment }}</td>\r\n                  <td ng-if=\"match.$edit\"><salaxy-input name=\"comment{{ $index }}\" label-type=\"plain\" ng-model=\"match.comment\"></salaxy-input></td>\r\n  \r\n                  <td>\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-disabled=\"!match.rowType\" ng-click=\"match.rowIndex = $index;$rows.showEdit(match)\"><i class=\"fa fa-list\" aria-hidden=\"true\"></i></button>\r\n                    <button type=\"button\" class=\"btn btn-primary\" ng-click=\"match.$edit = !match.$edit\"><i class=\"fa fa-pencil\" aria-hidden=\"true\"></i></button>\r\n                    <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$rows.delete(match)\"><i class=\"fa fa-trash\" aria-hidden=\"true\"></i></button>\r\n                  </td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </uib-tab>\r\n          <uib-tab index=\"'rows'\" heading=\"Rivit\">\r\n            <table class=\"table table-condensed\">\r\n              <thead>\r\n                <tr>\r\n                  <th></th>\r\n                  <th colspan=\"2\">Lähde</th>\r\n                  <th colspan=\"2\">Palkkaus.fi</th>\r\n                  <th colspan=\"3\"></th>\r\n                </tr>\r\n                <tr>\r\n                  <th>Päivä</th>\r\n                  <th>Henk. nro</th>\r\n                  <th>Rivikoodi</th>\r\n                  <th>Työntekijä</th>\r\n                  <th>Rivityyppi</th>\r\n                  <th>Alatyyppi</th>\r\n                  <th class=\"right\">Määrä</th>\r\n                  <th class=\"right\">Hinta</th>\r\n                  <th class=\"right\">Kustannusp.</th>\r\n                </tr>\r\n              </thead>\r\n              <tbody>\r\n                <tr ng-repeat=\"row in $ctrl.current.rows\">\r\n                  <td>{{ row.date | sxyDate }}</td>\r\n                  <td>{{ row.srcEmploymentId }}</td>\r\n                  <td>{{ row.srcRowTypeId }}</td>\r\n                  <td>\r\n                    <div ng-if=\"row.employment\">\r\n                      <salaxy-avatar style=\"font-size: 18px;\" avatar=\"row.employment.personalInfo.avatar\"></salaxy-avatar>\r\n                      {{ row.employment.personalInfo.avatar.displayName }}\r\n                    </div>\r\n                    <div ng-if=\"!row.employment\" class=\"text-danger\">{{ row.employmentId || \"Puuttuu!\" }}</div>\r\n                  </td>\r\n                  <td>{{ (\"CalculationRowType.\" + (row.rowType || \"\") | sxyEnum) || \"-\" }}</td>\r\n                  <td>{{ row.data.kind || row.message }}</td>\r\n                  <td class=\"right\">{{ row.count | sxyCount }}</td>\r\n                  <td class=\"right\">{{ row.price ? (row.price | currency) : \"-\" }}</td>\r\n                  <td class=\"right\">{{ row.costCenter }}</td>\r\n                </tr>\r\n              </tbody>\r\n            </table>\r\n          </uib-tab>\r\n          <uib-tab index=\"'src'\" heading=\"Debug\">\r\n            <salaxy-json-formatter json=\"$ctrl.getRowTypeMapper()\" key=\"'Source'\"></salaxy-json-formatter>\r\n          </uib-tab>\r\n        </uib-tabset>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/payroll/index.html\",`<main class=\"salaxy-content sxytpl-calculations-payroll\">\r\n  <div ng-if=\"$ctrl.newPayrollVersion.show\" class=\"hidden-xs hidden-sm salaxy-payroll-v4 form-horizontal pull-right\">\r\n    <salaxy-input-boolean name=\"newPayrollSwitch\" type=\"switch-xl\" ng-model=\"$ctrl.userSettings.ng1Binder('payroll.newVersion').val\" label=\"SALAXY.NG1.PayrollComponent.newVersion\" label-true=\"on\" label-false=\"off\"></salaxy-input-boolean>\r\n  </div>\r\n  <section class=\"sxytpl-intro hidden-xs hidden-sm\" ng-if=\"$ctrl.newPayrollVersion.show && !$ctrl.newPayrollVersion.use\">\r\n    <h3 sxy-text=\"SALAXY.NG1.PayrollComponent.newVersionInfo\"></h3>\r\n    <p sxy-html=\"SALAXY.NG1.PayrollComponent.newPayrollInfo.html\"></p>\r\n  </section>\r\n  <section class=\"sxytpl-list\" ng-if=\"$ctrl.newPayrollVersion.use\">\r\n    <salaxy-payroll-details-list  details-url=\"/payroll/details/\" hide-button=\"$ctrl.route.readOnly\" is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-payroll-details-list>\r\n  </section>\r\n  <section class=\"sxytpl-list\" ng-if=\"!$ctrl.newPayrollVersion.use\">\r\n    <salaxy-payroll-list  details-url=\"/payroll/details/\" hide-button=\"$ctrl.route.readOnly\" is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-payroll-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reference-objects/details.html\",`<main class=\"salaxy-content sxytpl-reference-object-details\">\r\n  <section>\r\n    <!-- This should be a component -->\r\n    <!--salaxy-reference-object model=\"'url'\"></salaxy-reference-object -->\r\n\r\n    <div class=\"salaxy-component salaxy-reference-object\" ng-controller=\"ReferenceObjectCrudController as $ctrl\" ng-init=\"$ctrl.model='url'\">\r\n      <div ng-if=\"$ctrl.current\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"ReferenceObject\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n          <div class=\"col-xs-12\">\r\n            <fieldset>\r\n              <legend>Header</legend>\r\n              <sxy-input  model=\"form.header.status\"></sxy-input>\r\n              <sxy-input model=\"form.header.referenceDate\"></sxy-input>\r\n              <sxy-input model=\"form.header.description\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend>Events</legend>\r\n              <sxy-input model=\"form.events\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend>Event</legend>\r\n                    <sxy-input model=\"form.name\" ></sxy-input>\r\n                    <sxy-input model=\"form.date\" ></sxy-input>\r\n                    <sxy-input model=\"form.result\" ></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12 text-right\">\r\n            <button class=\"btn btn-danger\" ng-click=\"$ctrl.delete($ctrl.current)\">Poista</button>\r\n            <button class=\"btn btn-primary\" ng-click=\"$ctrl.save()\">Tallenna</button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reference-objects/index.html\",`<main class=\"salaxy-content sxytpl-reference-object-list\">\r\n  <div class=\"text-right\">\r\n    <a class=\"btn btn-primary\" ng-href=\"#{{$odata.$crudController.getDefaults().detailsUrl}}new\" sxy-text=\"Uusi\"></a>\r\n  </div>\r\n  \r\n  <section>\r\n    <div ng-show=\"$odata.items.length\" class=\"salaxy-component salaxy-service-model-list\">\r\n      <salaxy-odata-table ng-ref=\"$odata\" crud-controller=\"ReferenceObjectCrudController as $crud\">\r\n      </salaxy-odata-table>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/absences.html\",`<div ng-controller=\"WorkerAbsencesCrudController as $ctrl\" ng-init=\"$ctrl.testYear=2021;$ctrl.getAbsences()\">\r\n  <h1 class=\"hidden-print\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.heading\"></h1>\r\n  <h2 class=\"visible-print-block\">{{'SALAXY.NG1_Pages.Reports.Absences.heading' | sxyTranslate}} ({{ $ctrl.reportParams | sxyDateRange }})</h2>\r\n  <div class=\"btn-toolbar hidden-print\" role=\"toolbar\" aria-label=\"Calendar buttons\" style=\"margin-top: -10px; margin-bottom: 15px;\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Views\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: !$ctrl.view || $ctrl.reportView == 'calendar' }\" ng-click=\"$ctrl.view = 'calendar'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.calendar\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.view == 'list' }\" ng-click=\"$ctrl.view = 'list'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.list\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Periods\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: !$ctrl.reportView || $ctrl.reportView == 'thisYear' }\" ng-click=\"$ctrl.reportView = 'thisYear'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.thisYear\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'lastYear' }\" ng-click=\"$ctrl.reportView = 'lastYear'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.lastYear\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'thisMonth' }\" ng-click=\"$ctrl.reportView = 'thisMonth'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.thisMonth\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'lastMonth' }\" ng-click=\"$ctrl.reportView = 'lastMonth'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.lastMonth\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1_Pages.Reports.Absences.dates' | sxyTranslate}}\">\r\n      <div class=\"form-inline\">\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.reportParams.start\" name=\"start\" label=\"SALAXY.NG1_Pages.Reports.Absences.dates\" label-type=\"inline\">\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.reportParams.end\" name=\"end\" label=\"\" label-type=\"no-label\" label-cols=\"none\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Actions\">\r\n      <button ng-click=\"$ctrl.showAddWorker()\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.addWorker\"></button>\r\n    </div>\r\n  </div>\r\n  <salaxy-spinner ng-if=\"!$ctrl.allAbsences\"></salaxy-spinner>\r\n  <div ng-if=\"$ctrl.allAbsences.length === 0\" sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.employeeNoAnsences\"></div>\r\n  <div ng-if=\"$ctrl.allAbsences.length &gt; 0\">\r\n    <salaxy-absence-periods style=\"display: none;\" ng-ref=\"$ctrl.$periodList\" on-commit=\"$ctrl.saveAbsences(parent)\"></salaxy-absence-periods>\r\n    <div ng-if=\"$ctrl.view != 'list'\">\r\n      <salaxy-calendar on-list-select=\"type == 'series' ? $ctrl.showEditDialog(series.data) : null\" data=\"$ctrl.allAbsences\" mode=\"horizontal\" mapper=\"$ctrl.mapToCalendar\" list-controller=\"$ctrl.$periodList\" start=\"$ctrl.reportParams.start\" end=\"$ctrl.reportParams.end\"></salaxy-calendar>\r\n    </div>\r\n    <div ng-if=\"$ctrl.view == 'list'\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\">\r\n              <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n            </th>\r\n            <th class=\"right\">\r\n              <span sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.first\"></span><br />\r\n              <span sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.latest\"></span>\r\n            </th>\r\n            <th class=\"right\">\r\n              <div sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.absencesPaid\"></div>\r\n              <div sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.absencesUnpaid\"></div>\r\n            </th>\r\n            <th class=\"right\">\r\n              <div sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.absencesHolidayAccrual\"></div>\r\n              <div sxy-text=\"SALAXY.NG1_Pages.Reports.Absences.absencesNoHolidayAccrual\"></div>\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.allAbsences\">\r\n            <td class=\"align-middle td-avatar clickable\"  ng-click=\"$ctrl.showEditDialog(row)\">\r\n              <salaxy-avatar avatar=\"row.workerSnapshot\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle clickable\"  ng-click=\"$ctrl.showEditDialog(row)\">\r\n              <div><strong>{{ row.workerSnapshot.displayName }}</strong></div>\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"length\") }} {{'SALAXY.NG1_Pages.Reports.Absences.absence' | sxyTranslate}}, {{ $ctrl.getPeriodCalculation(row, \"all\") | sxyCount : \"day\" }}</div>\r\n            </td>\r\n            <td class=\"right\">\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"firstPeriod\") | sxyDateRange }}</div>\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"lastPeriod\") | sxyDateRange }}</div>\r\n            </td>\r\n            <td class=\"right\">\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"absencesPaid\") | sxyCount : \"day\" }}</div>\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"absencesUnpaid\") | sxyCount : \"day\" }}</div>\r\n            </td>\r\n            <td class=\"right\">\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"absencesHolidayAccrual\") | sxyCount : \"day\" }}</div>\r\n              <div>{{ $ctrl.getPeriodCalculation(row, \"absencesNoHolidayAccrual\") | sxyCount : \"day\" }}</div>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/accounting-legacy.html\",`<main class=\"salaxy-content sxytpl-reports-accounting\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\"> {{ 'SALAXY.NG1_Pages.Reports.accountingIntro' | sxyTranslate }}\r\n    </p>\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <h2>{{ 'SALAXY.NG1_Pages.Reports.accountingMonthly' | sxyTranslate }}</h2>\r\n    <salaxy-report-list report-type=\"'monthlyDetails'\"></salaxy-report-list>\r\n    <salaxy-report-list report-type=\"'monthlyLiikekirjuri'\"></salaxy-report-list>\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <h2>{{ 'SALAXY.NG1_Pages.Reports.accountingYearly' | sxyTranslate }}</h2>\r\n    <salaxy-report-list report-type=\"'yearlyDetails'\"></salaxy-report-list>\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <h2>{{ 'SALAXY.NG1_Sitemap.reports.archive' | sxyTranslate }}</h2>\r\n    <a href=\"#/reports/archive-2018\">{{ 'SALAXY.UI_Terms.show' | sxyTranslate }}...</a>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/accounting-row-report.html\",`<main class=\"salaxy-content sxytpl-accounting-row-report\">\r\n  <section style=\"height: calc(100vh - 150px)\">\r\n    <salaxy-accounting-row-report template-id=\"'holidays'\"></salaxy-accounting-row-report>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/ad-hoc-list.html\",`<salaxy-odata-table crud-controller=\"UsecasesCrudController as $crud\" options=\"{ $filter: 'entityType eq \\\\'dataset\\\\'' }\" template-url=\"salaxy-components/odata/lists/UsecasesAdHocReport.html\"></salaxy-odata-table>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/ad-hoc.html\",`<main class=\"salaxy-content sxytpl-reports-ad-hoc\">\r\n  <section>\r\n    <div ng-controller=\"DatasetsCrudController as $ctrl\" ng-init=\"$ctrl.model='url'\">\r\n      <salaxy-spinner ng-if=\"!$ctrl.usecase\"></salaxy-spinner>\r\n      <div ng-if=\"$ctrl.usecase && !$ctrl.usecase.defaultView\" class=\"alert alert-danger\">\r\n        ERROR: This usecase {{ $ctrl.usecase.uri }} does not have user interface (view) defined.\r\n      </div>\r\n      <div ng-if=\"$ctrl.usecase && $ctrl.usecase.defaultView\">\r\n        <ng-include src=\"$ctrl.usecase.defaultView\"></ng-include>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/archive-2018.html\",`<main class=\"salaxy-content sxytpl-reports-archive-2018\">\r\n  <section class=\"sxytpl-intro\">\r\n    <h2 sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.heading\"></h2>\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.lead\"></p>\r\n  </section>\r\n  <h3 sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.unemploymentInsuranceFund\"></h3>\r\n  <section class=\"sxytpl-list\">\r\n    <div ng-controller=\"ReportsController as $ctrl\" ng-init=\"rptType = 'unemployment'\">\r\n      <salaxy-report-list report-type=\"'unemployment'\"></salaxy-report-list>\r\n    </div>\r\n  </section>\r\n  <h3 sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.taxYearlyNotification\"></h3>\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-report-list report-type=\"'taxYearly7801'\"></salaxy-report-list>\r\n  </section>\r\n  <h3 sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.taxMonthlyNotification\"></h3>\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-report-list report-type=\"'taxMonthly4001'\"></salaxy-report-list>\r\n  </section>\r\n  <h3 sxy-text=\"SALAXY.NG1_Pages.Reports.Archive.pension\"></h3>\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-report-list report-type=\"'insurance'\"></salaxy-report-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/calculation-report.html\",`<main class=\"salaxy-content sxytpl-calculation-report\">\r\n  <section style=\"height: calc(100vh - 150px)\">\r\n    <salaxy-calculation-report template-id=\"'incomeTypes'\"></salaxy-calculation-report>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/holiday-pay-report-query.html\",`<main class=\"salaxy-content sxytpl-holiday-pay-report-query\">\r\n  <section>\r\n    <salaxy-holiday-pay-report-query></salaxy-holiday-pay-report-query>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/holiday-report.html\",`<main class=\"salaxy-content sxytpl-holiday-report\">\r\n  <section>\r\n    <salaxy-holiday-report></salaxy-holiday-report>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/holidays.html\",`<div ng-controller=\"HolidayYearCrudController as $ctrl\" ng-init=\"$ctrl.getHolidayYears()\">\r\n  <h1 class=\"hidden-print\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.holidayList\"></h1>\r\n  <h2 class=\"visible-print-block\">{{'SALAXY.NG1_Pages.Reports.Holidays.holidayYear' | sxyTranslate}} {{ $ctrl.reportYear }} ({{ $ctrl.reportParams | sxyDateRange }})</h2>\r\n  <div class=\"btn-toolbar hidden-print\" role=\"toolbar\" aria-label=\"Calendar buttons\" style=\"margin-top: -10px; margin-bottom: 15px;\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1_Pages.Reports.Holidays.holidayYear' | sxyTranslate}}\">\r\n      <div class=\"form-inline\">\r\n        <salaxy-form-group name=\"year\" label=\"SALAXY.NG1_Pages.Reports.Holidays.holidayYear\" label-type=\"inline\">\r\n          <select id=\"year\" name=\"year\" ng-model=\"$ctrl.reportYear\" class=\"form-control\" ng-change=\"$ctrl.getHolidayYears()\" ng-options=\"item as item for item in $ctrl.reportParams.years\">\r\n          </select>\r\n        </salaxy-form-group>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1_Pages.Reports.Holidays.show' | sxyTranslate}}\">\r\n      <div class=\"form-inline\">\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.reportParams.start\" name=\"start\" label=\"SALAXY.NG1_Pages.Reports.Holidays.show\" label-type=\"inline\" min-date=\"$ctrl.reportParams.yearStart\" max-date=\"$ctrl.reportParams.yearEnd\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup ng-model=\"$ctrl.reportParams.end\" name=\"end\" label=\"\" label-type=\"no-label\" label-cols=\"none\" min-date=\"$ctrl.reportParams.yearStart\" max-date=\"$ctrl.reportParams.yearEnd\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Views\">\r\n      \r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'summerPeriod' }\" ng-click=\"$ctrl.reportView = 'summerPeriod'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.summerPeriod\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'winterPeriod' }\" ng-click=\"$ctrl.reportView = 'winterPeriod'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.winterPeriod\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'otherPeriod' }\" ng-click=\"$ctrl.reportView = 'otherPeriod'\" sxy-text=\"Muu\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-class=\"{ active: $ctrl.reportView == 'list' }\" ng-click=\"$ctrl.reportView = 'list'\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.list\"></button>\r\n      \r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Actions\">\r\n      <button ng-click=\"$ctrl.showAddWorker()\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.addWorker\"></button>\r\n    </div>\r\n  </div>\r\n  <salaxy-spinner ng-if=\"!$ctrl.allYears\"></salaxy-spinner>\r\n  <div ng-if=\"$ctrl.allYears.length === 0\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.employeeNoHolidays\"></div>\r\n  <div ng-if=\"$ctrl.allYears.length &gt; 0\">\r\n    <salaxy-holiday-year-holidays style=\"display: none;\" ng-ref=\"$ctrl.$holidayList\" on-commit=\"$ctrl.saveYear(parent)\"></salaxy-holiday-year-holidays>\r\n    <div ng-if=\"$ctrl.reportView != 'list'\">\r\n      <salaxy-calendar show-export=\"true\" on-list-select=\"type == 'series' ? $ctrl.showEditDialog(series.data) : null\" data=\"$ctrl.allYears\" mode=\"horizontal\" mapper=\"$ctrl.mapToCalendar\" list-controller=\"$ctrl.$holidayList\" start=\"$ctrl.reportParams.start\" end=\"$ctrl.reportParams.end\"></salaxy-calendar>\r\n    </div>\r\n    <div ng-if=\"$ctrl.reportView == 'list'\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span></th>\r\n            <th sxy-html=\"SALAXY.NG1_Pages.Reports.Holidays.holidayCompensation.html\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.year\"></th>\r\n            <th class=\"right\" sxy-html=\"SALAXY.NG1_Pages.Reports.Holidays.planned.html\"></th>\r\n            <th class=\"right\" sxy-html=\"SALAXY.NG1_Pages.Reports.Holidays.summerWinter.html\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1_Pages.Reports.Holidays.endSaldo\"></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"year in $ctrl.allYears\">\r\n            <td class=\"align-middle td-avatar clickable\" ng-click=\"$ctrl.showEditDialog(year)\">\r\n              <salaxy-avatar avatar=\"year.workerSnapshot\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-workerSnapshot-name clickable\" ng-click=\"$ctrl.showEditDialog(year)\">\r\n              <strong>{{ year.workerSnapshot.displayName }}</strong><br /> {{ \"WageBasis.\" + year.spec.wageBasis | sxyEnum }}<br />\r\n            </td>\r\n            <td>\r\n              {{ \"HolidayCode.\" + year.spec.code | sxyEnum }}\r\n              <span ng-if=\"year.spec.code == 'holidayCompensation'\">({{ year.spec.compensation | sxyCount : 'percent' }})</span>\r\n              <div ng-if=\"year.spec.bonusMethod != 'none'\">\r\n                {{ \"HolidayBonusPaymentMethod.\" + year.spec.bonusMethod | sxyEnum }}\r\n                <span>({{ year.spec.bonus | sxyCount : 'percent' }})</span>\r\n              </div>\r\n            </td>\r\n            <td class=\"right\">{{ year.year }}</td>\r\n            <td class=\"right\">\r\n              {{ $ctrl.getTotalDays(\"all\", year) | sxyCount : 'days' }}<br /> {{ year.leaves.planned.length | sxyCount : 'count' }}\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ $ctrl.getTotalDays(\"summer\", year) | sxyCount : 'days' }}<br /> {{ $ctrl.getTotalDays(\"winter\", year) | sxyCount : 'days' }}\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ year.accrual.endSaldo | sxyCount : 'days' }}\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <p>&nbsp;</p>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/index.html\",`<main class=\"salaxy-content sxytpl-reports-dashboard\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\">\r\n      {{ 'SALAXY.NG1_Pages.Reports.latestReports' | sxyTranslate }}\r\n    </p>\r\n  </section>\r\n  <section class=\"sxytpl-report-panels\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 col-sm-6\" ng-if=\"$ctrl.route.getFlag('features', 'salaryReportList')\">\r\n        <salaxy-salary-report-list mode=\"panel\"></salaxy-salary-report-list>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-6\" ng-if=\"$ctrl.route.getFlag('features', 'accountingReportList')\">\r\n        <salaxy-accounting-report-list mode=\"panel\"></salaxy-accounting-report-list>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-6\" ng-if=\"$ctrl.route.getFlag('features', 'invoiceList') || ('pro' | sxyIsInRole)\">\r\n        <salaxy-invoice-list mode=\"panel\"></salaxy-invoice-list>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/pay-certificate.html\",`<main class=\"salaxy-content sxytpl-pay-certificate\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p sxy-text=\"SALAXY.NG1_Pages.Reports.PayCertificate.intro.text\"></p>\r\n    <p sxy-html=\"SALAXY.NG1_Pages.Reports.PayCertificate.intro.html\"></p>\r\n  </section>\r\n  <section>\r\n    <salaxy-pay-certificate></salaxy-pay-certificate>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/salary-reports.html\",`<main class=\"salaxy-content sxytpl-salary-reports\">\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-salary-report-list>\r\n    </salaxy-salary-report-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/summary-report-query.html\",`<main class=\"salaxy-content sxytpl-summary-report-query\">\r\n  <section>\r\n    <salaxy-summary-report-query></salaxy-summary-report-query>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/reports/yearly-summary.html\",`<main class=\"salaxy-content sxytpl-reports-yearly-summary\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\">\r\n      {{ 'SALAXY.NG1_Pages.Reports.yearlySummary' | sxyTranslate }}\r\n    </p>\r\n\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <h2>{{ 'SALAXY.NG1_Pages.Reports.yearlyTitle' | sxyTranslate }}</h2>\r\n    <salaxy-report-list report-type=\"'yearlyWorkerSummary'\"></salaxy-report-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/service-models/current.html\",`<main class=\"salaxy-content sxytpl-service-model-current\">\r\n  <section>\r\n    <h1>TODO: Current service model</h1>\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.ServiceModels.Current.lead\"></p>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/service-models/details.html\",`<main class=\"salaxy-content sxytpl-service-model-details\">\r\n  <section>\r\n    <salaxy-service-model-details model=\"'url'\"></salaxy-service-model-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/service-models/index.html\",`<main class=\"salaxy-content sxytpl-service-model-list\">\r\n  <a class=\"btn btn-primary pull-right\" ng-href=\"#{{$odata.$crudController.getDefaults().detailsUrl}}new\" sxy-text=\"SALAXY.NG1_Pages.ServiceModels.addServiceModel\"></a>\r\n  <p class=\"lead\">\r\n    {{'SALAXY.NG1_Pages.ServiceModels.lead' | sxyTranslate}} <a href=\"\">Ota yhteys myyntiimme</a>.\r\n  </p>\r\n  <section>\r\n    <div ng-show=\"$odata.items.length\" class=\"salaxy-component salaxy-service-model-list\">\r\n      <salaxy-odata-table ng-ref=\"$odata\" crud-controller=\"ServiceModelCrudController as $crud\">\r\n      </salaxy-odata-table>\r\n    </div>\r\n    <div ng-if=\"$odata.status == 'loaded' && !$odata.items.length\" class=\"salaxy-placeholder-empty placeholder-md placeholder-default text-center\">\r\n      <a class=\"btn btn-primary\" ng-href=\"#{{$odata.$crudController.getDefaults().detailsUrl}}new\" sxy-text=\"SALAXY.NG1_Pages.ServiceModels.addServiceModel\"></a>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/service-models/read-only.html\",`<main class=\"salaxy-content sxytpl-service-model-details\">\r\n  <section>\r\n    <salaxy-service-model-details is-read-only-forced=\"true\" model=\"'url'\"></salaxy-service-model-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/account-reset.html\",`<main class=\"salaxy-content sxytpl-settings-account-reset\">\r\n  <section class=\"sxytpl-account-reset\">\r\n    <salaxy-account-reset></salaxy-account-reset>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/accountants.html\",`<main class=\"salaxy-content sxytpl-partners-accountants\">\r\n  <section>\r\n    <div class=\"content settings\">\r\n\r\n      <salaxy-accountant removal-disabled=\"$ctrl.route.node.accountantRemovalDisabled || 'accountantComponent.removalDisabled' | sxyIsInRole\"></salaxy-accountant>\r\n\r\n    </div>\r\n  </section>\r\n  <section sxy-if-role=\"test\">\r\n    <div class=\"row\" ng-controller=\"PartnerController as $partnerCtrl\">\r\n      <div class=\"col-md-6\">\r\n        <div class=\"alert alert-danger\">\r\n          <b>Testiympäristö</b>\r\n          <p>Vaihda tyyli tätä sessiota varten!</p>\r\n          <button id=\"style\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$partnerCtrl.showSwitchCss()\">\r\n            Vaihda tyyli (CDN)\r\n          </button>\r\n          <button id=\"style\" type=\"button\" class=\"btn btn-secondary\" ng-click=\"$partnerCtrl.showSwitchCssDev()\">\r\n            Vaihda tyyli <span class=\"small\">(DEV)</span>\r\n          </button>\r\n          <hr />\r\n          <div>Brand ID: {{ $partnerCtrl.brandId || \"-\" }}</div>\r\n          <div>Skin: {{ $partnerCtrl.skin || \"-\" }}</div>\r\n          <a ng-href=\"{{ $partnerCtrl.getLoginUrl() }}\" target=\"_blank\" class=\"btn btn-default\">Näytä login</a>\r\n          <a ng-href=\"{{ $partnerCtrl.getOnboardingUrl() }}\" target=\"_blank\" class=\"btn btn-default\">Näytä onboarding</a>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/accounting-target-settings.html\",`<main class=\"salaxy-content sxytpl-accounting-targets\">\r\n  <section>\r\n    <salaxy-accounting-settings></salaxy-accounting-settings>\r\n  </section>\r\n  <section>\r\n    <div>\r\n      <salaxy-accountant template-url=\"salaxy-components/settings/AccountantInfo.html\"></salaxy-accountant>\r\n    </div>\r\n  </section>\r\n  <section>\r\n    <salaxy-cost-accounting-settings></salaxy-cost-accounting-settings>\r\n  </section>\r\n  <section>\r\n    <salaxy-holiday-settings></salaxy-holiday-settings>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/authorizations.html\",`<main class=\"salaxy-content sxytpl-settings-certificates settings content\">\r\n  <section class=\"sxytpl-credentials\">\r\n    <salaxy-credentials></salaxy-credentials>\r\n  </section>\r\n  <section class=\"sxytpl-certificates\">\r\n    <salaxy-certificates></salaxy-certificates>\r\n  </section>\r\n  <section class=\"sxytpl-authorized-accounts\">\r\n    <!-- <p class=\"lead\">{{ 'SALAXY.NG1_Pages.Settings.Authorizations.lead' | sxyTranslate}}</p> -->\r\n    <salaxy-authorized-accounts></salaxy-authorized-accounts>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/index.html\",`<main class=\"salaxy-content sxytpl-settings-dashboard\" ng-controller=\"SessionController as $session\">\r\n  <section class=\"sxytpl-settings-panels\">\r\n    <div class=\"row\">\r\n\r\n      <div class=\"col-xs-12\" ng-if=\"$ctrl.route.getFlag('features', 'account')\">\r\n        <div class=\"salaxy-odata-panel list-panel settings-list-panel panel panel-sm panel-secondary\">\r\n          <div class=\"panel-heading\" sxy-text=\"SALAXY.NG1_Pages.Settings.accountTitle\">\r\n\r\n          </div>\r\n          <div class=\"panel-body panel-content\">\r\n            <div class=\"row table-row\">\r\n\r\n              <div class=\"col-xs-4\">\r\n                <span sxy-text=\"SALAXY.NG1_Pages.Settings.languageLabel\" ps=\":\"></span>\r\n              </div>\r\n\r\n              <div class=\"col-xs-8 text-right\">\r\n                {{(\"Language.\" + $session.session.currentAccount.language | sxyEnum) || \"-\" }}\r\n              </div>\r\n            </div>\r\n\r\n            <div class=\"row\">\r\n              <div class=\"col-md-6\">\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-12\">\r\n                    <strong sxy-text=\"SALAXY.NG1_Pages.Settings.contactLabel\"></strong>\r\n                  </div>\r\n                </div>\r\n\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-4\">\r\n                    <span sxy-text=\"SALAXY.NG1.AccountInfoComponent.email\" ps=\":\"></span>\r\n\r\n                  </div>\r\n                  <div class=\"col-xs-8 text-right\">\r\n                    {{ $session.company.contact.email }}\r\n                  </div>\r\n                </div>\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-4\">\r\n                    <span sxy-text=\"SALAXY.NG1.AccountInfoComponent.phone\" ps=\":\"></span>\r\n\r\n                  </div>\r\n                  <div class=\"col-xs-8 text-right\">\r\n                    {{ $session.company.contact.telephone }}\r\n                  </div>\r\n                </div>\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-4\">\r\n                    <span sxy-text=\"SALAXY.NG1.AccountInfoComponent.address\" ps=\":\"></span>\r\n\r\n                  </div>\r\n                  <div class=\"col-xs-8 text-right\">\r\n                    {{ $session.company.contact.street }}<br /> {{ $session.company.contact.postalCode }} {{ $session.company.contact.city }}\r\n                  </div>\r\n                </div>\r\n              </div>\r\n              <div class=\"col-md-6\">\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-12\">\r\n                    <strong sxy-text=\"SALAXY.NG1_Pages.Settings.userLabel\"></strong>\r\n                  </div>\r\n                </div>\r\n\r\n                <div class=\"row table-row\" ng-if=\"$session.session.currentCredential.authenticationMethod != 'salaxy' && $session.session.currentCredential.authenticationMethod != 'x509'\">\r\n                  <div class=\"col-xs-4\">\r\n                    <span sxy-text=\"SALAXY.NG1.UserInfoComponent.email\" ps=\":\"></span>\r\n\r\n                  </div>\r\n                  <div class=\"col-xs-8 text-right\">\r\n\r\n                    {{ $session.session.currentCredential.email }}\r\n                  </div>\r\n                </div>\r\n                <div class=\"row table-row\">\r\n                  <div class=\"col-xs-4\">\r\n                    <span sxy-text=\"SALAXY.NG1.UserInfoComponent.name\" ps=\":\"></span>\r\n                  </div>\r\n                  <div class=\"col-xs-8 text-right\">\r\n                    {{ $session.session.currentCredential.avatar.displayName }}\r\n                  </div>\r\n                </div>\r\n              </div>\r\n            </div>\r\n\r\n          </div>\r\n          <div class=\"panel-footer text-center\">\r\n            <a href=\"#/settings/service-settings\" title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\" sxy-text=\"SALAXY.UI_Terms.edit\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n      <div class=\"col-sm-6 col-xs-12\" ng-if=\"$ctrl.route.getFlag('features', 'insurances')\" ng-controller=\"CompanySettingsController as $settings\">\r\n        <div class=\"salaxy-odata-panel list-panel settings-list-panel panel panel-sm panel-secondary\">\r\n          <div class=\"panel-heading\" sxy-text=\"SALAXY.NG1_Pages.Settings.insurancesTitle\">\r\n\r\n          </div>\r\n          <div class=\"panel-body panel-content lg-height\">\r\n\r\n            <div class=\"row table-row\">\r\n              <div class=\"col-xs-6\" ng-class=\"$session.session.settings.pensionContracts == '' ? 'col-xs-6' : 'col-xs-12'\">\r\n                <strong sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.titleLong\"></strong>\r\n              </div>\r\n\r\n              <div class=\"col-xs-6 text-right\" ng-if=\"$session.session.settings.pensionContracts == ''\">\r\n                <a href=\"#/settings/payment-settings\" class=\"btn btn-danger btn-xs\" sxy-text=\"SALAXY.NG1_Pages.Settings.insuranceMissing\"></a>\r\n              </div>\r\n            </div>\r\n            <div class=\"row-wrapper\" ng-repeat=\"item in $settings.pensionContracts\" ng-if=\"$settings.isVisibleContract(item, $settings.pensionContracts)\">\r\n              <div class=\"row table-row\">\r\n                <div class=\"col-xs-4\" ps=\":\" sxy-text=\"SALAXY.MODEL.PensionContract.company.title\">\r\n  \r\n                </div>\r\n                <div class=\"col-xs-8 text-right\">\r\n                  {{(\"PensionCompany.\" + item.company | sxyEnum) || '-'}}\r\n                </div>\r\n              </div>\r\n              \r\n              <div class=\"row table-row\">\r\n                <div class=\"col-xs-4\" sxy-text=\"SALAXY.MODEL.PensionContract.contractNumber.title\" ps=\":\">\r\n  \r\n                </div>\r\n                <div class=\"col-xs-8 text-right\">\r\n                  {{item.contractNumber || '-'}}\r\n                </div>\r\n              </div>\r\n            </div>\r\n          \r\n            <div class=\"row-wrapper\" ng-repeat=\"item in $settings.insuranceContracts\" ng-if=\"$settings.isVisibleContract(item, $settings.insuranceContracts)\">\r\n              <div class=\"row table-row\">\r\n                <div class=\"col-xs-6\" ng-class=\"$session.session.settings.insuranceContracts == '' ? 'col-xs-6' : 'col-xs-12'\">\r\n                  <strong sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.title\"></strong>\r\n                </div>\r\n\r\n                <div class=\"col-xs-6 text-right\" ng-if=\"$session.session.settings.insuranceContracts == ''\">\r\n                  <a href=\"#/settings/payment-settings\" class=\"btn btn-danger btn-xs\" sxy-text=\"SALAXY.NG1_Pages.Settings.insuranceMissing\"></a>\r\n                </div>\r\n              </div>\r\n              <div class=\"row table-row\">\r\n                <div class=\"col-xs-4\" sxy-text=\"SALAXY.MODEL.InsuranceContract.company.title\" ps=\":\">\r\n\r\n                </div>\r\n                <div class=\" col-xs-8 text-right\">\r\n                  {{(\"InsuranceCompany.\" + item.company | sxyEnum) || '-'}}\r\n                </div>\r\n              </div>\r\n              <div class=\"row table-row\">\r\n                <div class=\"col-xs-4\" sxy-text=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\" ps=\":\">\r\n\r\n                </div>\r\n                <div class=\"col-xs-8 text-right\">\r\n                  {{item.contractNumber || '-'}}\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div class=\"panel-footer text-center\">\r\n            <a href=\"#/settings/insurances\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\" sxy-text=\"SALAXY.UI_Terms.edit\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-sm-6 col-xs-12\" ng-if=\"$ctrl.route.getFlag('features', 'accountant')\">\r\n        <div class=\"salaxy-odata-panel list-panel settings-list-panel panel panel-sm panel-secondary\">\r\n          <div class=\"panel-heading\">\r\n            {{'SALAXY.NG1_Pages.Settings.accountantTitle' | sxyTranslate }}\r\n          </div>\r\n          <div class=\"panel-body panel-content lg-height text-center align-middle\" ng-if=\"!$session.session.settings.partner\">\r\n            <div>\r\n              <h3 sxy-text=\"SALAXY.NG1_Pages.Settings.noAccountant\"></h3>\r\n            </div>\r\n          </div>\r\n          <div class=\"panel-body panel-content lg-height\" ng-if=\"$session.session.settings.partner\">\r\n            <div class=\"row table-row\">\r\n              <div class=\"col-xs-4\" sxy-text=\"SALAXY.NG1.AccountantComponent.name\" ps=\":\">\r\n              </div>\r\n              <div class=\"col-xs-8 text-right\">\r\n                <salaxy-avatar style=\"font-size: 20px; margin-right: 12px;\" avatar=\"$session.session.settings.partner.info.avatar\"></salaxy-avatar>\r\n                {{ $session.session.settings.partner.info.avatar.displayName}}\r\n              </div>\r\n            </div>\r\n\r\n            <div class=\"row table-row\" ng-if=\"$session.session.settings.partner.info.officialId\">\r\n              <div class=\"col-xs-4\" sxy-text=\"SALAXY.NG1.AccountantComponent.officialId\" ps=\":\"></div>\r\n              <div class=\"col-xs-8 text-right\">{{ $session.session.settings.partner.info.officialId}}</div>\r\n            </div>\r\n            <div class=\"row table-row\" ng-if=\"$session.session.settings.partner.info.email\">\r\n              <div class=\"col-xs-4\" sxy-text=\"SALAXY.NG1.AccountantComponent.email\" ps=\":\"></div>\r\n              <div class=\"col-xs-8 text-right\">{{ $session.session.settings.partner.info.email }}</div>\r\n            </div>\r\n            <div class=\"row table-row\" ng-if=\"$session.session.settings.partner.info.telephone\">\r\n              <div class=\"col-xs-4\" sxy-text=\"SALAXY.NG1.AccountantComponent.phone\" ps=\":\"></div>\r\n              <div class=\"col-xs-8 text-right\">{{ $session.session.settings.partner.info.telephone }}</div>\r\n            </div>\r\n            <div class=\"row table-row\" ng-if=\"$session.session.settings.partner.type=='primaryPartner' || $session.session.settings.partner.type=='pendingPrimaryPartner' || $session.session.settings.partner.type=='unlinkedPrimaryPartner' || $session.session.settings.partner.type=='unlinkedAccountingOnly'\">\r\n              <div class=\"col-xs-4\" sxy-text=\"SALAXY.NG1.AccountantComponent.accountantType\" ps=\":\">\r\n              </div>\r\n              <div class=\"col-xs-8 text-right\">\r\n                <span ng-if=\"$session.session.settings.partner.type=='primaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.primaryPartner\"></span>\r\n                <span ng-if=\"$session.session.settings.partner.type=='pendingPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.pendingPrimaryPartner\"></span>\r\n                <span ng-if=\"$session.session.settings.partner.type=='unlinkedPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedPrimaryPartner\"></span>\r\n                <span ng-if=\"$session.session.settings.partner.type=='unlinkedAccountingOnly'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedAccountingOnly\"></span>\r\n              </div>\r\n            </div>\r\n          </div>\r\n\r\n          <div class=\"panel-footer text-center\">\r\n            <a href=\"#/settings/accountants\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\" sxy-text=\"SALAXY.UI_Terms.edit\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-sm-6 col-xs-12\" ng-if=\"$session.session.settings.paymentChannels && $ctrl.route.getFlag('features', 'paymentChannels')\">\r\n        <div class=\"salaxy-odata-panel list-panel settings-list-panel panel panel-sm panel-secondary\">\r\n          <div class=\"panel-heading\" sxy-text=\"SALAXY.NG1_Pages.Settings.paymentChannelsTitle\">\r\n\r\n          </div>\r\n          <div class=\"panel-body panel-content lg-height\">\r\n            <div class=\"row table-row\">\r\n              <div class=\"col-xs-6\">\r\n                <strong sxy-text=\"SALAXY.NG1_Pages.Settings.defaultChannelLabel\" ps=\":\"></strong>\r\n              </div>\r\n              <div class=\"col-xs-6 text-right\">\r\n                {{\"PaymentChannel.\" + $session.session.settings.defaultPaymentChannel | sxyEnum}}\r\n              </div>\r\n            </div>\r\n            <div class=\"row table-row\">\r\n              <div class=\"col-xs-12\">\r\n                <strong sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.title\" ps=\":\"></strong>\r\n              </div>\r\n            </div>\r\n            <div class=\"row table-row\" ng-repeat=\"channel in $session.session.settings.paymentChannels\">\r\n\r\n              <div class=\"col-xs-12\">\r\n\r\n                {{\"PaymentChannel.\" + channel | sxyEnum}}<br>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div class=\"panel-footer text-center\">\r\n            <a href=\"#/settings/payment-channel-settings\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-primary\" sxy-text=\"SALAXY.UI_Terms.edit\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/insurances.html\",`<main class=\"salaxy-content sxytpl-insurance-settings\">\r\n  <section>\r\n    <salaxy-insurance-settings is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-insurance-settings>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/integrations.html\",`<main class=\"salaxy-content sxytpl-partners-integrations\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\">\r\n      {{ 'SALAXY.NG1_Pages.Settings.Integrations.lead' | sxyTranslate }}\r\n    </p>\r\n  </section>\r\n  <section class=\"sxytpl-cards\">\r\n    <div ng-controller=\"AccountAuthorizationController as authCtrl\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-sm-6 col-md-4 col-lg-3\" ng-repeat=\"site in authCtrl.partnerIntegrationSites\">\r\n          <salaxy-auth-card auth-id=\"site.id\"></salaxy-auth-card>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/owner-settings.html\",`<salaxy-owner-settings is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-owner-settings>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/payment-channel-settings.html\",`<main class=\"salaxy-content sxytpl-payment-channel-settings\">\r\n  <section>\r\n    <salaxy-payment-channel-settings></salaxy-payment-channel-settings>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/payment-settings.html\",`<main class=\"salaxy-content sxytpl-payment-settings\">\r\n\r\n  <section>\r\n    <salaxy-payment-settings is-read-only-forced=\"$ctrl.route.readOnly\"></salaxy-payment-settings>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/pro-settings.html\",`<main class=\"salaxy-content sxytpl-pro-settings\">\r\n  <section>\r\n    <salaxy-pro-settings></salaxy-pro-settings>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/row-types-settings.html\",`<main class=\"salaxy-content sxytpl-row-types-settings\">\r\n  <section>\r\n    <div>\r\n      <uib-tabset active=\"$ctrl.currentTab\">\r\n        <uib-tab index=\"'built-in'\" heading=\"Tuotteen palkkalajit\">\r\n          <div>\r\n            <p>\r\n              Tuotteen palkkalajit listaa kaikki palkkalajit, jotka on määritetty suoraan tuotteeseen.\r\n              Niitä ei voi muokata. <strong>Klikkaa räätälöi luodaksesi uusi yrityskohtainen palkkalaji.</strong>\r\n            </p>\r\n            <salaxy-row-types-settings mode=\"builtIn\"></salaxy-row-types-settings>\r\n          </div>\r\n        </uib-tab>\r\n        <uib-tab index=\"'custom'\" heading=\"Yrityskohtaiset palkkalajit\">\r\n          <p>\r\n            Voit luoda uuden yrityskohtaisen palkkalajin valitsemalla tuotteen palkkalajin ensimmäiseltä välilehdeltä ja klikkaamalla \"räätälöi\".\r\n            <br />\r\n            <strong>HUOM: Tässä versiossa yrityskohtaiset palkkalajit toimivat vain tuntitiedon tuonnissa (esim. Nepton, EASoft).</strong>\r\n            Myöhemmissä versioissa ne tulevat mukaan myös laskuriin.\r\n          </p>\r\n          <div>\r\n            <salaxy-row-types-settings mode=\"custom\" ng-if=\"$ctrl.currentTab == 'custom'\"></salaxy-row-types-settings>\r\n          </div>\r\n        </uib-tab>\r\n        <uib-tab index=\"'prices'\" heading=\"Oletushinnat\">\r\n          <div class=\"pull-right\">\r\n            <button class=\"btn btn-primary\" ng-click=\"$ctrl.$prices.save()\"></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n          <p style=\"min-height: 24px;\">Hintoja käytetään tällä hetkellä tuntien sisään tuonnissa. Myöhemmissä versioissa oletushintoja käytetään myös laskurissa.</p>\r\n          <salaxy-row-types-settings ng-ref=\"$ctrl.$prices\" mode=\"prices\" ng-if=\"$ctrl.currentTab == 'prices'\"></salaxy-row-types-settings>\r\n        </uib-tab>\r\n        <uib-tab index=\"'json'\" heading=\"Debug\">\r\n          <salaxy-row-types-settings mode=\"debugger\" ng-if=\"$ctrl.currentTab == 'json'\"></salaxy-row-types-settings>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/service-settings.html\",`<main class=\"salaxy-content sxytpl-settings-service-settings settings content\">\r\n  <section class=\"sxytpl-language-selection\">\r\n    <salaxy-language-selector></salaxy-language-selector>\r\n  </section>\r\n  <section class=\"sxytpl-account-info\">\r\n    <div class=\"panel account-info panel-default\">\r\n      <div class=\"panel-heading\">\r\n        <h2>{{'SALAXY.NG1_Pages.Settings.ServiceSettings.heading' | sxyTranslate}}</h2>\r\n\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <salaxy-account-info></salaxy-account-info>\r\n      </div>\r\n    </div>\r\n  </section>\r\n  <section class=\"sxytpl-user-info\" salaxy-if-role=\"test\">\r\n    <div class=\"panel user-info panel-default\">\r\n      <div class=\"panel-heading\">\r\n        <h2>{{'SALAXY.NG1.UserInfoComponent.panelTitle' | sxyTranslate}} (TEST ONLY)</h2>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <salaxy-user-info></salaxy-user-info>\r\n      </div>\r\n    </div>\r\n  </section>\r\n  <section class=\"sxytpl-account-records\">\r\n    <div class=\"panel account-records panel-default\">\r\n      <div class=\"panel-heading\">\r\n        <h2>{{'SALAXY.NG1.WorkerDetailsComponent.records.label' | sxyTranslate}}</h2>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div ng-if=\"'person' | sxyIsInRole\" ng-controller=\"PersonAccountController as $person\">\r\n          <salaxy-records ng-if=\"$person.current\" read-only=\"$ctrl.route.readOnly\" api-ctrl=\"$person\" entity-type=\"'account'\"></salaxy-records>\r\n        </div>\r\n        <div ng-if=\"'company' | sxyIsInRole\" ng-controller=\"CompanyAccountController as $company\">\r\n          <salaxy-records ng-if=\"$company.current\" read-only=\"$ctrl.route.readOnly\" api-ctrl=\"$company\" entity-type=\"'account'\"></salaxy-records>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/signing-cancel.html\",`<div class=\"text-center\" style=\"height: 100vh; padding-top: 30vh;\">\r\n  <div>\r\n    <h1>Allekirjoitus peruttu / Digital signature canceled / \r\n      Digital signatur avbröts</h1>\r\n    <button type=\"button\" class=\"btn btn-primary\" onclick=\"closePopup()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/pages/settings/signing-new.html\",`<main class=\"salaxy-content sxytpl-settings-signing\">\r\n  <h1>Signing tester</h1>\r\n  <salaxy-signing ng-ref=\"$ctrl.$signing\" show-in-popup=\"true\" show-always=\"true\"></salaxy-signing>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/settings/signing-success.html\",`<div class=\"text-center\" style=\"height: 100vh; padding-top: 30vh;\">\r\n  <div>\r\n    <h1 sxy-text=\"SALAXY.NG1_Pages.Settings.SigningSuccess.success\"></h1>\r\n    <button type=\"button\" class=\"btn btn-primary\" onclick=\"closePopup()\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/pages/settings/signing.html\",`<div ng-cloak ng-controller=\"NaviController as $ctrl\">\r\n  <salaxy-spinner ng-if=\"$ctrl.showFullPageLoader\" full-screen=\"true\" heading=\"SALAXY.UI_Terms.loading\">\r\n  </salaxy-spinner>\r\n  <div class=\"salaxy-component\" ng-if=\"!$ctrl.showFullPageLoader\">\r\n    <div ng-controller=\"CompanyOnboardingController as $onBoarding\">\r\n      <div ng-if=\"'auth' | sxyIsInRole\" ng-init=\"$onBoarding.launchSigningWizard()\"></div>\r\n      <div class=\"text-center\" style=\"margin-top:100px;\">\r\n        <a onClick=\"window.opener.postMessage({ action: 'refresh' },'*');window.close()\" href=\"#\" sxy-text=\"SALAXY.UI_Terms.close\"></a>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n\r\n   `);\n\n $templateCache.put(\"salaxy-components/pages/settings/translate.html\",`<salaxy-ui-translator></salaxy-ui-translator>`);\n\n $templateCache.put(\"salaxy-components/pages/taxcards/details.html\",`<div class=\"container\">\r\n  <h2>{{'SALAXY.NG1_Pages.Taxcards.Details.heading' | sxyTranslate}}: {{ $ctrl.$taxcardCtrl.current.worker.displayName }}</h2>\r\n  <p class=\"lead\" ng-if=\"$ctrl.$taxcardCtrl.current\">\r\n    <strong>{{ \"TaxcardKind.\" + $ctrl.$taxcardCtrl.current.card.kind | sxyEnum }}, {{ $ctrl.$taxcardCtrl.current.card.validity | sxyDateRange }}</strong>. {{'SALAXY.NG1_Pages.Taxcards.Details.heading' | sxyTranslate}}\r\n  </p>\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab heading=\"{{'SALAXY.NG1_Pages.Taxcards.Details.overview' | sxyTranslate}}\" index=\"'overview'\">\r\n      <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\" ng-if=\"$ctrl.$taxcardCtrl.isLoading\"></salaxy-spinner>\r\n      <div ng-if=\"$ctrl.$taxcardCtrl.current && $ctrl.$taxcardCtrl.currentId\">\r\n        <salaxy-taxcard-details model=\"$ctrl.$taxcardCtrl.current\" hide-buttons=\"true\"></salaxy-taxcard-details>\r\n        <div class=\"text-center\" ng-if=\"!$ctrl.$taxcardCtrl.getTaxcardDownloadUrl()\" sxy-text=\"SALAXY.NG1_Pages.Taxcards.Details.noAttachment\"></div>\r\n        <a ng-if=\"$ctrl.$taxcardCtrl.getTaxcardDownloadUrl()\" ng-href=\"{{$ctrl.$taxcardCtrl.getTaxcardDownloadUrl()}}\" target=\"_blank\" class=\"btn btn-xs btn-primary pull-right\" sxy-text=\"SALAXY.NG1_Pages.Taxcards.Details.download\">Download</a>\r\n        <div ng-if=\"$ctrl.$taxcardCtrl.getTaxcardPreviewUrl()\" class=\"document-preview text-center\">\r\n          <img ng-src=\"{{ $ctrl.$taxcardCtrl.getTaxcardPreviewUrl() }}\" class=\"img-responsive\" style=\"display: inline;\" />\r\n        </div>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1_Pages.Taxcards.Details.editing' | sxyTranslate}}\" index=\"'pro'\">\r\n      <salaxy-taxcard-details model=\"'url'\" list-url=\"/taxcards\" ng-ref=\"$ctrl.$taxcardCtrl\" mode=\"pro\"></salaxy-taxcard-details>\r\n    </uib-tab>\r\n    <uib-tab heading=\"{{'SALAXY.NG1_Pages.Taxcards.Details.allTaxcards' | sxyTranslate}}\" index=\"'allTaxcards'\">\r\n      <div ng-if=\"$ctrl.currentTab == 'allTaxcards'\">\r\n        <salaxy-employment-taxcards employment-id=\"$ctrl.$taxcardCtrl.current.employmentId\" ng-ref=\"$ctrl.$allTaxcardsCtrl\" mode=\"list\"></salaxy-employment-taxcards>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab heading=\"Json / debug\" index=\"'debug'\">\r\n      <p class=\"clearfix\" sxy-if-role=\"test\">\r\n        <button type=\"button\" class=\"btn btn-danger pull-right\" ng-click=\"$ctrl.$taxcardCtrl.delete()\" sxy-text=\"SALAXY.NG1_Pages.Taxcards.Details.deleteButton\">Poista (test)</button> {{'SALAXY.NG1_Pages.Taxcards.Details.deleteButtonInfo' | sxyTranslate}}\r\n      </p>\r\n      <salaxy-json-formatter open=\"1\" json=\"$ctrl.$taxcardCtrl.current\"></salaxy-json-formatter>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/taxcards/index.html\",`<div class=\"container\">\r\n  <h2 sxy-text=\"SALAXY.NG1_Pages.Taxcards.heading\"></h2>\r\n  <p class=\"lead\" sxy-if-role=\"!worker\" sxy-html=\"SALAXY.NG1_Pages.Taxcards.lead.noWorkerHtml\"></p>\r\n  <p class=\"lead\" sxy-if-role=\"worker\" sxy-html=\"SALAXY.NG1_Pages.Taxcards.lead.workerHtml\"></p>\r\n  <salaxy-odata-table crud-controller=\"TaxcardCrudController as $crud\" crud-bindings=\"{ detailsUrl: '/taxcards/details/'}\"></salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages/test/account-reset.html\",`<main class=\"salaxy-content sxytpl-settings-account-reset\">\r\n  <section class=\"sxytpl-account-reset\">\r\n    <salaxy-account-reset></salaxy-account-reset>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/test/smoke.html\",`<main class=\"salaxy-content sxytpl-test-smoke\">\r\n  <section class=\"sxytpl-test-smoke\">\r\n    <h1>Salaxy tester page</h1>\r\n      <p class=\"lead\">\r\n        This page tests whether <code>@salaxy</code> functionality is working.\r\n        <br />\r\n        <a href=\"/ng1/\">Go to AngularJS Components</a>\r\n      </p>\r\n      <fieldset>\r\n        <legend>AngularJS</legend>\r\n        <p>Expressions: 1 + 2 = {{ 1 + 2 }} <i>(result should be \"3\")</i></p>\r\n        <p>\r\n          Ng-if: <span style=\"background-color: red; color: white;\" ng-if=\"false\">FAILURE</span>\r\n          <i>(should NOT show text \"failure\" in red background).</i>\r\n        </p>\r\n        <p>\r\n          Directive (ng-style): <span style=\"background-color: red; color: white;\" ng-style=\"{ 'background-color': 'green' }\">This text should be in GREEN backgroung</span>\r\n        </p>\r\n      </fieldset>\r\n      <fieldset>\r\n        <legend>Salaxy styles (LESS)</legend>\r\n        <p>The following buttons should be in Bootstrap colors:</p>\r\n        <div class=\"btn-toolbar\">\r\n          <button type=\"button\" class=\"btn btn-default\">Default</button>\r\n          <button type=\"button\" class=\"btn btn-primary\">Primary</button>\r\n          <a href=\"\" class=\"btn btn-success\">Success a-href</a>\r\n          <button type=\"button\" class=\"btn btn-info\">Info</button>\r\n          <a href=\"\" class=\"btn btn-warning\">Warning a-href</a>\r\n          <button type=\"button\" class=\"btn btn-danger\">Danger</button>\r\n          <button type=\"button\" class=\"btn btn-link\">Link</button>\r\n        </div>\r\n        <p style=\"margin-top: 10px;\">...if this is not the case, rest of the tests may be difficult to read (no red / green etc.)</p>\r\n      </fieldset>\r\n      <p style=\"background-color: red; color: white; margin-top: 10px;\" ng-if=\"false\">\r\n        FAILURE: Angular not available: Rest of tests will not show!\r\n      </p>\r\n      <salaxy-smoke-test mode=\"core\"></salaxy-smoke-test>\r\n      <salaxy-smoke-test mode=\"reports\"></salaxy-smoke-test>\r\n      <salaxy-smoke-test mode=\"ng1\"></salaxy-smoke-test>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/usecases/details.html\",`<main class=\"salaxy-content sxytpl-usecase-details\">\r\n  <section>\r\n    <salaxy-usecase-details model=\"'url'\"></salaxy-usecase-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/usecases/index.html\",`<main class=\"salaxy-content sxytpl-usecase-list\">\r\n  <section>\r\n    <a ng-href=\"#{{$ctrl.$odata.$crudController.getDefaults().detailsUrl}}new\" class=\"btn btn-primary pull-right\" sxy-text=\"SALAXY.NG1_Pages.Usecases.createNewUsecase\"></a>\r\n    <h1>{{'SALAXY.NG1_Pages.Usecases.usecase' | sxyTranslate}}<span class=\"badge bg-primary\">BETA</span></h1>\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.Usecases.lead\"></p>\r\n    <div class=\"toolbar\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$odata.setFilter(null)\">Näytä kaikki</button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$odata.setFilter('entityType', 'calculation')\">Laskelmat</button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.$odata.setFilter('entityType', 'dataset')\">Dataset</button>\r\n    </div>\r\n    <salaxy-odata-table crud-controller=\"UsecasesCrudController as $crud\" ng-ref=\"$ctrl.$odata\"></salaxy-odata-table>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/workers/details.html\",`<main class=\"salaxy-content sxytpl-workers-details\">\r\n  <section>\r\n    <salaxy-worker-details model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\" hide-buttons=\"$ctrl.route.readOnly\"></salaxy-worker-details>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/workers/import-workers.html\",`<main class=\"salaxy-content\">\r\n  <section>\r\n    <!-- Forcing isFullWidth  -->\r\n    <div style=\"display: none;\" ng-init=\"$ctrl.current.isFullWidth = true\"></div>\r\n    <uib-tabset>\r\n      <uib-tab index=\"'default'\" heading=\"Työntekijöiden tuonti\">\r\n        <salaxy-worker-import></salaxy-worker-import>\r\n      </uib-tab>\r\n      <uib-tab index=\"'list'\" heading=\"Työntekijät\">\r\n        <salaxy-employment-list show-toolbar=\"true\" read-only=\"$ctrl.route.readOnly\"></salaxy-employment-list>\r\n      </uib-tab> \r\n    </uib-tabset>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/workers/index.html\",`<main class=\"salaxy-content sxytpl-workers-list\">\r\n  <section>\r\n    <salaxy-employment-list show-toolbar=\"true\" read-only=\"$ctrl.route.readOnly\" ng-ref=\"$odata\"></salaxy-employment-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/workers/taxcards.html\",`<main class=\"salaxy-content sxytpl-workers-taxcardslist\">\r\n  <section class=\"sxytpl-intro\">\r\n    <p class=\"lead\" sxy-text=\"SALAXY.NG1_Pages.Workers.Taxcards.lead\"></p>\r\n  </section>\r\n  <section class=\"sxytpl-list\">\r\n    <salaxy-tax-cards-list></salaxy-tax-cards-list>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages/worktime-imports/index.html\",`<main class=\"salaxy-content sxytpl-usecase-list\">\r\n  <section ng-controller=\"ImportStagingController as $ctrl\">\r\n    <div ng-if=\"$ctrl.isSupported\">\r\n      <salaxy-import-staging></salaxy-import-staging>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.isSupported\" class=\"container\">\r\n      <h1>Työajan tuonti ei käytössä</h1>\r\n      <p class=\"lead\">\r\n        Työajan tuonti ei ole käytössä tälle asiakastilille.\r\n        Ominaisuus on käytössä ensimmäisillä kumppaneilla.\r\n        Kysy asiakaspalvelusta miten voit ottaa tuonnin käyttöön.\r\n      </p>\r\n      <p>\r\n        <strong>HUOM:</strong>\r\n        Jos tiedosasi on jo organisaatiosi Staging-palvelimen osoite\r\n        ,<a href=\"#/settings/pro-settings\">voit määrittää sen asetuksissa</a> => Välilehti   \"Muut\".\r\n      </p>\r\n    </div>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/account/authorizations.html\",`<main class=\"salaxy-content sxytpl-settings-certificates settings content\">\r\n  <section class=\"sxytpl-credentials\">\r\n    <salaxy-credentials></salaxy-credentials>\r\n  </section>\r\n  <section class=\"sxytpl-certificates\">\r\n    <salaxy-certificates></salaxy-certificates>\r\n  </section>\r\n  <section class=\"sxytpl-authorized-accounts\">\r\n    <salaxy-authorized-accounts></salaxy-authorized-accounts>\r\n  </section>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/account/index.html\",`<salaxy-account-details-person></salaxy-account-details-person>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/employer-archive.html\",`<div>\r\n  <p class=\"lead\" sxy-html=\"SALAXY.NG1_PagesPersonal.employerArchive.intro.html\"></p>\r\n  <ul>\r\n    <li><a href=\"#/archive/employer-paid\" sxy-text=\"SALAXY.NG1_Sitemap.personalWeb.employerArchive.employerPaid\"></a></li>\r\n    <li><a href=\"#/archive/employer-report\" sxy-text=\"SALAXY.NG1_Sitemap.personalWeb.employerArchive.employerReport\"></a></li>\r\n    <li><a href=\"#/household-years/active\" sxy-text=\"SALAXY.NG1_Sitemap.personalWeb.employerArchive.householdYears.main\"></a></li>\r\n  </ul>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/employer-paid.html\",`<salaxy-calc-list category=\"paid\" read-only=\"true\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/employer-report.html\",`<salaxy-employer-report></salaxy-employer-report>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/household-deduction-report.html\",`<div>\r\n  <salaxy-household-deduction-report></salaxy-household-deduction-report>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/index.html\",`<div class=\"embed loader\" salaxy-if-role=\"auth\">\r\n  <salaxy-spinner full-screen=\"true\" id=\"iFrameLoader\" heading=\"Ladataan tietoja arkistosta...\"></salaxy-spinner>\r\n  <iframe src=\"/Yearly\" onload=\"document.getElementById('iFrameLoader').style.display = 'none'\"></iframe>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/archive/worker-report.html\",`<salaxy-worker-report></salaxy-worker-report>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/details.html\",`<div class=\"container-fixed\">\r\n  <salaxy-calc ng-ref=\"$calc\" model=\"'url'\" ng-hide=\"$calc.currentCalc.workflow.status == 'paymentStarted' || $calc.currentCalc.workflow.status == 'paymentSucceeded'\"></salaxy-calc>\r\n  <div class=\"light-bg\" ng-if=\"$calc.currentCalc.workflow.status == 'paymentStarted' || $calc.currentCalc.workflow.status == 'paymentSucceeded'\">\r\n    <salaxy-calc-reports calcs=\"[$calc.currentCalc]\" report-type=\"'salarySlip'\"></salaxy-calc-reports>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/draft.html\",`<salaxy-action-button sxy-if-role=\"!household\" action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\" button-class=\"btn-primary spacer-bottom hidden-xxs\"></salaxy-action-button>\r\n<salaxy-calc-list category=\"draft\" class=\"worker-drafts\" read-only=\"'household' | sxyIsInRole\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/error.html\",`<salaxy-calc-list category=\"error\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/index.html\",`<div class=\"row visible-xs\">\r\n  <div class=\"col-xs-12\" ng-if=\"!$ctrl.hideButton\">\r\n    <div style=\"margin-bottom:15px;\">\r\n      <salaxy-action-button action=\"'newCalc'\" label=\"Luo uusi palkkalaskelma\"></salaxy-action-button>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"row\">\r\n  <div class=\"col-sm-6 col-xs-12\">\r\n    <salaxy-calc-list category=\"received\" mode=\"panel\" limit-to=\"5\" read-only=\"'household' | sxyIsInRole\"></salaxy-calc-list>\r\n  </div>\r\n  <div class=\"col-sm-6 col-xs-12\">\r\n    <salaxy-odata-table url=\"/v03/api/calculations/category/all\" crud-controller=\"CalculationCrudController as $crud\" options=\"{$top: 5, $filter: 'status eq \\\\'workerRequested\\\\' or status eq \\\\'workerRequestAccepted\\\\' or status eq \\\\'workerRequestDeclined\\\\' or status eq \\\\'draft\\\\'', $orderby:  'createdAt desc'}\"\r\n      template-url=\"salaxy-components/odata/lists/CalculationsPanel.html\" data=\"{ category: 'sentAndDraft' }\">\r\n    </salaxy-odata-table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/paid-household.html\",`<salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\" button-class=\"btn-primary spacer-bottom hidden-xxs\" sxy-if-role=\"!household\"></salaxy-action-button>\r\n<div>\r\n  <salaxy-calc-list category=\"paid\" read-only=\"true\"></salaxy-calc-list>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/paid-worker.html\",`<salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\" button-class=\"btn-primary spacer-bottom hidden-xxs\" sxy-if-role=\"!household\"></salaxy-action-button>\r\n<div>\r\n  <salaxy-calc-list category=\"received\"></salaxy-calc-list>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/paid.html\",`<salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\" button-class=\"btn-primary spacer-bottom hidden-xxs\"></salaxy-action-button>\r\n<salaxy-calc-list category=\"received\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/sent.html\",`<p class=\"lead\">\r\n  Olet lähettänyt nämä palkkalaskelmat työnantajalle maksettavaksi.\r\n</p>\r\n<salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculation\" button-class=\"btn-primary spacer-bottom hidden-xxs\" sxy-if-role=\"!household\"></salaxy-action-button>\r\n<salaxy-calc-list category=\"sent\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/shared.html\",`<salaxy-calc-list category=\"shared\" read-only=\"true\"></salaxy-calc-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/calc/sharing.html\",`<salaxy-calc-sharing model=\"'url'\"></salaxy-calc-sharing>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/employers/index.html\",`<!--\r\n  This is currently in test only and Palkkamylly\r\n  TODO: Move component to Palkkamylly and remove from NG1 (may be recreated in Omapalkka)\r\n-->\r\n<salaxy-employer-list></salaxy-employer-list>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/home/error404.html\",`<div class=\"alert alert-danger\">\r\n  <span sxy-text=\"SALAXY.NG1_PagesPersonal.error404\"></span><br />\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/home/index.html\",`<div ng-controller=\"WelcomeController as $welcomeCtrl\">\r\n\r\n  <div sxy-if-role=\"anon\" class=\"alert alert-danger\" sxy-html=\"SALAXY.NG1_PagesPersonal.index.alert.anon.html\"></div>\r\n  <div sxy-if-role=\"company\" class=\"alert alert-danger\" sxy-html=\"SALAXY.NG1_PagesPersonal.index.alert.company.html\"></div>\r\n  <div sxy-if-role=\"person\">\r\n    <div class=\"salaxy-component salaxy-component-welcome row\" style=\"position:relative;\">\r\n      <div class=\"\" ng-if=\"!$welcomeCtrl.workerDataNew.timeline\">\r\n        <salaxy-spinner></salaxy-spinner>\r\n      </div>\r\n\r\n      <div class=\"timeline\">\r\n        <div ng-if=\"$welcomeCtrl.hasSystemAlert\">\r\n          <div>\r\n            <div class=\"salaxy-welcome-system-alert alert-has-system-alert\" ng-bind-html=\"$welcomeCtrl.systemAlertHtml\"></div>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"$welcomeCtrl.workerDataNew.timeline\" class=\"visible-xs timeline-topbar\">\r\n          <div class=\"row\" style=\"margin-bottom:10px;\">\r\n            <div class=\"col-xs-6\">\r\n              <salaxy-action-button action=\"'newTaxcard'\" label=\"SALAXY.NG1.WelcomeComponent.taxcard\" button-class=\"btn-labeled-right btn-primary btn-block\"></salaxy-action-button>\r\n            </div>\r\n            <div class=\"col-xs-6\">\r\n              <salaxy-action-button action=\"'newCalc'\" label=\"SALAXY.NG1.ActionButtonComponent.newCalculationAlt\" button-class=\"btn-labeled-right btn-secondary btn-block\"></salaxy-action-button>\r\n            </div>\r\n          </div>\r\n          <div class=\"list-panel panel panel-sm panel-secondary panel-own-taxcard panel-secondary\">\r\n            <div ng-show=\"$welcomeCtrl.workerUI.taxCardAdded\" class=\"salaxy-component table-responsive panel-content md-height\">\r\n              <div class=\"panel-content md-height\">\r\n                <div class=\"panel-body no-vertical-padding salaxy-tax-card-chart chart-container\" style=\"max-height:216px; padding-top:0; padding-bottom:0; padding-left:5px;padding-right:5px;\">               \r\n                  <salaxy-chart ng-if=\"$welcomeCtrl.taxcardChartData.limits.hasLimit == true\" custom-height=\"210px\" config=\"$welcomeCtrl.taxcardMobileChartData\"></salaxy-chart>\r\n                  <salaxy-chart ng-if=\"$welcomeCtrl.taxcardChartData.limits.hasLimit == false || !$welcomeCtrl.taxcardChartData.limits.hasLimit\" custom-height=\"200px\" config=\"$welcomeCtrl.taxcardChartData.config\"></salaxy-chart>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n\r\n        <div ng-repeat=\"item in $welcomeCtrl.workerDataNew.timeline\">\r\n          <div class=\"panel card-panel\" ng-class=\"{'panel-solid card-paid' : item.type == 'calculationPaid'}\">\r\n            <div class=\"panel-heading\">\r\n              <div class=\"pull-left icon-container\" ng-class=\"{\r\n                'accepted': (item.status == 'workerRequestAccepted' || item.status == 'sharedApproved'), \r\n                'requested': (item.status == 'workerRequested'|| item.status == 'shared'), \r\n                'paid' : item.type == 'calculationPaid', \r\n                'rejected' : (item.status == 'workerRequestDeclined' || item.status == 'sharedRejected' || item.status == 'sharedRejectedWithoutOpen')\r\n              }\">\r\n                <i class=\"fa\" ng-class=\"{\r\n                  'fa-vcard-o': item.type == 'employment', \r\n                  'fa-user-o': item.type == 'personAccount', \r\n                  'fa-calculator': (item.type == 'calculation' && item.status != 'workerRequestAccepted' && item.status != 'workerRequestDeclined' && item.status != 'workerRequested' ),\r\n                  'fa-reply' : (item.status == 'workerRequestAccepted' || item.status == 'sharedApproved'), \r\n                  'fa-file-text-o': (item.type == 'taxcard' && item.status != 'shared' && item.status != 'sharedApproved' && item.status != 'sharedRejected' && item.status != 'sharedRejectedWithoutOpen'), \r\n                  'fa-share' : (item.status == 'shared' || item.status == 'workerRequested'), \r\n                  'fa-check' : item.type == 'calculationPaid',\r\n                  'fa-times' : (item.status == 'workerRequestDeclined' || item.status == 'sharedRejected' || item.status == 'sharedRejectedWithoutOpen'),\r\n                }\">\r\n                </i>\r\n              </div>\r\n              <!--<div class=\"pull-right actions-container clickable text-center\">\r\n              <i class=\"fa fa-ellipsis-h\" style=\"font-size:1.3em;\"></i></div>-->\r\n              <h3 class=\"panel-title\">{{ item.shortText }}</h3>\r\n              <div class=\"date\">{{ item.logicalDate | sxyDate }}</div>\r\n\r\n            </div>\r\n            <div class=\"panel-content\" ng-class=\"{'panel-body' : !$welcomeCtrl.getPreviewUrl(item)}\">\r\n              <div ng-if=\"$welcomeCtrl.getPreviewUrl(item)\" style=\"max-height: 200px; overflow: hidden;\">\r\n                <img ng-src=\"{{$welcomeCtrl.getPreviewUrl(item)}}\" style=\"width: 100%;\" />\r\n              </div>\r\n              <div ng-if=\"!$welcomeCtrl.getPreviewUrl(item)\" ng-switch=\"item.type\">\r\n                <div ng-switch-when=\"calculation\">\r\n                  <div ng-if=\"item.status != 'draft'\" class=\"otherparty-container\">\r\n                    <salaxy-avatar avatar=\"item.otherPartyInfo.avatar\"></salaxy-avatar>\r\n                    <span>{{item.otherPartyInfo.avatar.displayName}}</span>\r\n                  </div>\r\n\r\n                  <div class=\"card-main text-center\" ng-class=\"{'accepted': item.status == 'workerRequestAccepted', 'requested' : item.status == 'workerRequested', 'rejected' : item.status == 'workerRequestDeclined' }\">\r\n                    <span class=\"\">{{item.grossSalary | currency}}</span>\r\n                  </div>\r\n                  <div class=\"card-details-title\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.grossSalary\"></div>\r\n                  <div class=\"card-details text-center\">\r\n                    <span><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.netSalary\"></span>: {{ item.data.workerPayment | currency }}</span><br>\r\n                    <span><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.taxes\"></span>: {{ item.data.taxPayment | currency }}</span>\r\n                  </div>\r\n                </div>\r\n                <div ng-switch-when=\"calculationPaid\">\r\n                  <div class=\"otherparty-container\">\r\n                    <salaxy-avatar avatar=\"item.otherPartyInfo.avatar\"></salaxy-avatar>\r\n                    <span>{{item.otherPartyInfo.avatar.displayName}}</span>\r\n                  </div>\r\n\r\n                  <div class=\"card-main text-center paid-calc\">\r\n                    <span class=\"\">{{item.grossSalary | currency}}</span>\r\n                  </div>\r\n                  <div class=\"card-details-title\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.grossSalary\"></div>\r\n                  <div class=\"card-details text-center\">\r\n                    <span><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.netSalary\"></span>: {{ item.data.workerPayment | currency }}</span><br>\r\n                    <span><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.taxes\"></span>: {{ item.data.taxPayment | currency }}</span>\r\n                  </div>\r\n                </div>\r\n                <div ng-switch-when=\"taxcard\">\r\n                  <div ng-if=\"item.status == 'sharedApproved' || item.status == 'sharedRejected' || item.status == 'sharedRejectedWithoutOpen'\" class=\"otherparty-container\">\r\n                    <salaxy-avatar avatar=\"item.ownerInfo.avatar\"></salaxy-avatar>\r\n                    <span>{{item.ownerInfo.avatar.displayName}}</span>\r\n                  </div>\r\n                  <div ng-if=\"item.data.taxPercent\" class=\"card-main text-center\" ng-class=\"{'accepted' : item.status == 'sharedApproved', 'requested' : item.status == 'shared', 'rejected' : (item.status == 'sharedRejected' || item.status == 'sharedRejectedWithoutOpen') }\">\r\n                    <span class=\"\">{{item.data.taxPercent || \"-\"}} %</span>\r\n                  </div>\r\n                  <div class=\"card-details-title\" ng-if=\"item.data.taxPercent\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.taxcard.taxPercent\"></div>\r\n                  <div ng-if=\"item.data.taxPercent\" class=\"card-details text-center\">\r\n                    <strong> {{ \"TaxcardKind.\" + item.data.kind | sxyEnum }}</strong><br>\r\n                    <span ng-if=\"item.data.incomeLimit\"><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.taxcard.incomeLimit\"></span>: {{ item.data.incomeLimit | currency }}</span><br>\r\n                    <span ng-if=\"item.data.taxPercent2\"><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.taxcard.taxPercent2\"></span>: {{ item.data.taxPercent2 }} %</span>\r\n                  </div>\r\n                </div>\r\n                <div ng-switch-when=\"personAccount\">\r\n                  <div class=\"text-primary\">{{ item.ownerInfo.displayName }}</div>\r\n                  <div><a href=\"mailto:{{ item.ownerInfo.email }}\">{{ item.ownerInfo.email }}</a></div>\r\n                  <div><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.account.iban\"></span>: {{ item.ownerInfo.ibanNumber | sxyIban }}</div>\r\n                  <div><span sxy-text=\"SALAXY.NG1_PagesPersonal.index.account.phone\"></span>: {{ item.ownerInfo.telephone }}</div>\r\n                </div>\r\n                <div ng-switch-when=\"employment\">\r\n\r\n                  <div class=\"row\">\r\n                    <div class=\"col-xs-6 text-center\">\r\n                      <div class=\"otherparty-container\">\r\n                        <salaxy-avatar avatar=\"item.ownerInfo.avatar\"></salaxy-avatar>\r\n                      </div>\r\n                      <span> {{ item.ownerInfo.avatar.displayName}}</span>\r\n                    </div>\r\n                    <div class=\"col-xs-6 text-center\">\r\n                      <div class=\"otherparty-container\">\r\n                        <salaxy-avatar avatar=\"item.otherPartyInfo.avatar\"></salaxy-avatar>\r\n                      </div>\r\n                      <span> {{ item.otherPartyInfo.avatar.displayName}}</span>\r\n                    </div>\r\n                  </div>\r\n                </div>\r\n                <div ng-switch-default>\r\n                  <!--TODO: Handle {{ item.type }}-->\r\n                </div>\r\n              </div>\r\n              <div class=\"collapse small\" ng-class=\"{show: item.showInfo}\">\r\n                <pre>{{ item | json }}</pre>\r\n              </div>\r\n            </div>\r\n            <div class=\"panel-footer\">\r\n              <span ng-switch=\"item.type\">\r\n                <span ng-switch-when=\"calculationPaid\">\r\n                  <a class=\"btn btn-sm btn-white\" target=\"_blank\" ng-href=\"{{$welcomeCtrl.getPdfUrl(item, true)}}\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.buttons.openCalculationBtn\"></a>\r\n                  <a ng-href=\"{{$welcomeCtrl.getPdfUrl(item)}}\" class=\"btn btn-sm btn-white\" title=\"tuloste\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.buttons.downloadPdfBtn\"></a>\r\n                </span>\r\n              <a ng-switch-when=\"calculation\" href=\"#/calc/details/{{item.id}}\" class=\"btn btn-secondary btn-sm\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.calculation.buttons.showCalculationBtn\"></a>\r\n              <a ng-switch-when=\"taxcard\" href=\"#/taxcards\" class=\"btn btn-secondary btn-sm\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.taxcard.buttons.showTaxcardsBtn\"></a>\r\n              <a ng-switch-when=\"personAccount\" href=\"#/account\" class=\"btn btn-secondary btn-sm\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.account.showAccountInfoBtn\"></a>\r\n              </span>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/taxcards/household.html\",`<div>\r\n  <salaxy-tax-cards-list></salaxy-tax-cards-list>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/taxcards/index.html\",`<div class=\"salaxy-my-taxcards\">\r\n  <div ng-controller=\"MyTaxcardsController as $ctrl\">\r\n    <salaxy-spinner ng-if=\"!$ctrl.current\"></salaxy-spinner>\r\n    <div ng-if=\"$ctrl.current\" class=\"light-bg spacer-bottom\">\r\n      <div ng-if=\"!$ctrl.current.active\">\r\n        <p class=\"lead\">\r\n          <span sxy-html=\"SALAXY.NG1_PagesPersonal.taxcards.introGetAutoTaxcard.html\"></span>\r\n        </p>\r\n        <div class=\"salaxy-placeholder-empty placeholder-md text-center\">\r\n          <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.setSharedAutoForSelf()\"\r\n            sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.buttons.getTaxPercentsBtn\"></button>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.active\">\r\n        <div ng-if=\"$ctrl.current.active.card.kind != 'auto'\">\r\n          <p class=\"lead\">\r\n            <span sxy-html=\"SALAXY.NG1_PagesPersonal.taxcards.introGetAutoTaxcard.html\"></span>\r\n            <a href=\"\" ng-click=\"$ctrl.showMoreText = true\" ng-if=\"!$ctrl.showMoreText\" sxy-text=\"SALAXY.UI_Terms.readMore\"></a>\r\n          </p>\r\n        </div>\r\n        <div ng-if=\"$ctrl.current.active.card.kind == 'auto'\" sxy-html=\"SALAXY.NG1_PagesPersonal.taxcards.intro.html\"></div>\r\n        <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.setSharedAutoForSelf()\"\r\n          sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.buttons.checkTaxPercentsBtn\"></button>\r\n        <h3 sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.currentTaxCard\"></h3>\r\n        <ng-include src=\"'salaxy-components/pages-personal/taxcards/TaxcardDetails_Personal.html'\"></ng-include>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current\" class=\"light-bg\">\r\n      <uib-tabset active=\"$ctrl.currentTab\">\r\n        <uib-tab heading=\"{{'SALAXY.NG1_PagesPersonal.taxcards.calcsPaidForCardTabHeading' |sxyTranslate}}\" index=\"'calcs'\" ng-if=\"$ctrl.current.active\">\r\n          <salaxy-taxcard-income-log parent=\"$ctrl.current.active\" ng-ref=\"$ctrl.$incomeLog\"></salaxy-taxcard-income-log>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1_PagesPersonal.taxcards.employersTabHeading' | sxyTranslate}}\" index=\"'employers'\" ng-if=\"$ctrl.current.employers\">\r\n          <table class=\"table table-striped\">\r\n            <thead>\r\n              <tr>\r\n                <th class=\"th-xxs\" colspan=\"2\">\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.employerTableHeading\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.typeTableHeading\"></div>\r\n                </th>\r\n                <th class=\"hidden-xs hidden-sm\" sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.yearTableHeading\"></th>\r\n                <th class=\"hidden-xs hidden-sm right\">\r\n                  <div sxy-text=\"SALAXY.MODEL.TaxcardData.taxPercent.title\"></div>\r\n                  <div sxy-text=\"SALAXY.MODEL.TaxcardData.taxPercent2.title\"></div>\r\n                </th>\r\n                <th class=\"right\">\r\n                  <div sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.incomeLimitTableHeading\"></div>\r\n                </th>\r\n                <th class=\"right\">\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.validDateTableHeading\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.startDateTableHeading\"></div>\r\n                </th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"taxCard in $ctrl.current.employers\">\r\n                <td class=\"align-middle td-avatar\">\r\n                  <salaxy-avatar avatar=\"taxCard.ownerInfo.avatar\"></salaxy-avatar>\r\n                </td>\r\n                <td>\r\n                  <div class=\"visible-xs visible-sm\"><strong>{{taxCard.ownerInfo.avatar.displayName}}</strong></div>\r\n                  <div class=\"visible-xs visible-sm\">\r\n                    <strong>{{ \"TaxcardKind.\" + taxCard.data.kind | sxyEnum }} {{ taxCard.data.forYear }}</strong>\r\n                    {{taxCard.data.taxPercent}} %\r\n                    <span ng-if=\"taxCard.data.taxPercent2 != null\">({{ taxCard.data.taxPercent2 }} %)</span>\r\n                  </div>\r\n                  <div class=\"hidden-xs hidden-sm\"><strong>{{taxCard.ownerInfo.avatar.displayName}}</strong></div>\r\n                  <div class=\"hidden-xs hidden-sm\">{{ \"TaxcardKind.\" + taxCard.data.kind | sxyEnum }}</div>\r\n                </td>\r\n                <td class=\"hidden-xs hidden-sm\">{{ taxCard.data.forYear }}</td>\r\n                <td class=\"hidden-xs hidden-sm right\">\r\n                  <div>{{taxCard.data.taxPercent}} %</div>\r\n                  <div>{{taxCard.data.taxPercent2 != null ? (taxCard.data.taxPercent2 + ' %') : '-'}}</div>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <div>{{ taxCard.data.totalIncome | currency: ' €' : 0 }}</div>\r\n                  <div>{{(taxCard.data.incomeLimit | currency: ' €' : 0) || '-'}}</div>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <div>{{ taxCard.data | sxyDateRange }}</div>\r\n                  <div>{{ taxCard.createdAt | sxyTime }}</div>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1_PagesPersonal.taxcards.earlierTaxCardsTabHeading' | sxyTranslate}}\" index=\"'history'\" ng-if=\"$ctrl.current.list.length > 0\">\r\n          <table class=\"table table-striped\">\r\n            <thead>\r\n              <tr>\r\n                <th>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.validDateTableHeading\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.startDateTableHeading\"></div>\r\n                </th>\r\n                <th sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.yearTableHeading\"></th>\r\n                <th class=\"hidden-sm hidden-xs right\">\r\n                  <div sxy-text=\"SALAXY.MODEL.TaxcardData.taxPercent.title\"></div>\r\n                  <div sxy-text=\"SALAXY.MODEL.TaxcardData.taxPercent2.title\"></div>\r\n                </th>\r\n                <th class=\"visible-sm visible-xs right\">%</th>\r\n                <th class=\"visible-sm visible-xs right\" colspan=\"2\">\r\n                  <div sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.incomeLimitTableHeading\"></div>\r\n                </th>\r\n                <th class=\"hidden-sm hidden-xs right\">\r\n                  <div sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></div>\r\n                  <div sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.incomeLimitTableHeading\"></div>\r\n                </th>\r\n                <th class=\"hidden-sm hidden-xs right\"></th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"taxCard in $ctrl.current.list\">\r\n                <td>\r\n                  <div>{{ taxCard.data | sxyDateRange }}</div>\r\n                  <div>{{ taxCard.createdAt | sxyTime }}</div>\r\n                </td>\r\n                <td>{{ taxCard.data.forYear }}</td>\r\n                <td class=\"right\">\r\n                  <div>{{taxCard.data.taxPercent}}&nbsp;%</div>\r\n                  <div>{{taxCard.data.taxPercent2 != null ? (taxCard.data.taxPercent2 + '&nbsp;%') : '-'}}</div>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <div>{{ taxCard.data.totalIncome | currency: ' €' : 0 }}</div>\r\n                  <div>{{(taxCard.data.incomeLimit | currency: ' €' : 0) || '-'}}</div>\r\n                </td>\r\n                <td class=\"middle-align right\" ng-if=\"!taxCard.isReadOnly\">\r\n                  <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.deleteTaxCard(taxCard.id)\">\r\n                    <span title=\"{{'SALAXY.UI_Terms.delete' | sxyTranslate}}\">&times;</span>\r\n                  </button>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/taxcards/TaxcardDetails_Personal.html\",`<div>\r\n  <div class=\"row\">\r\n    <div class=\"col-md-7 col-lg-7\" ng-switch=\"$ctrl.chartType\">\r\n      <div ng-switch-when=\"full\" class=\"salaxy-tax-card-chart chart-container\">    \r\n          <salaxy-chart custom-height=\"400px\" config=\"$ctrl.getMainChartConfig($ctrl.current.active)\"></salaxy-chart>\r\n      </div>\r\n      <div ng-switch-when=\"pie\" class=\"salaxy-tax-card-chart chart-container text-center\">      \r\n          <salaxy-chart style=\"height: 400px; position: relative;\" config=\"$ctrl.getPieChartConfig($ctrl.current.active)\"></salaxy-chart>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-md-5 col-lg-5\">\r\n      <div class=\"row current-taxcard-row table-row\">\r\n        <div class=\"col-xs-12\">\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardKind\"></strong><br /> {{ 'TaxcardKind.' + $ctrl.current.active.card.kind | sxyEnum }}\r\n          ({{$ctrl.current.active.card.forYear}})\r\n        </div>\r\n      </div>\r\n      <div class=\"row current-taxcard-row table-row\">\r\n        <div class=\"col-xs-8\">\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.validDate\"></strong><br /> {{$ctrl.current.active.card.validity.start | date}} - {{$ctrl.current.active.card.validity.end | date}}\r\n        </div>\r\n        <div class=\"col-xs-4 text-right\">\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardAdded\"></strong><br />\r\n          <span title=\"{{ $ctrl.current.active.createdAt | date : 'short' }}\">{{ $ctrl.current.active.createdAt | sxyDate }}</span>\r\n        </div>\r\n      </div>\r\n      <table class=\"table table-condensed\" style=\"margin-bottom: 0; margin-top: 6px\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\" style=\"padding-left: 0;\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.mainTaxPercent2\"></span></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.basicPercent\"></td>\r\n            <td class=\"right\">{{ $ctrl.current.active.card.taxPercent }} %</td>\r\n          </tr>\r\n          <tr ng-if=\"!$ctrl.current.active.card.incomeLimit\">\r\n            <td colspan=\"2\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noIncomeLimit\"></span></td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.active.card.incomeLimit\">\r\n            <td><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercent2.name\"></span> <small>(tulorajan {{ $ctrl.current.active.card.incomeLimit | currency : '€' : 0 }}\r\n                {{'SALAXY.NG1.CurrentTaxCardComponent.after' | sxyTranslate}})</small></td>\r\n            <td class=\"right\">{{ $ctrl.current.active.card.taxPercent2 || \"-\" }} %</td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.active.card.taxPercentMin\">\r\n            <!-- Only needed if the view is used for showing Employer taxcards: Worker taxcards no longer can have a minimum. -->\r\n            <td>\r\n              <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercentMin.title\"></span>\r\n            </td>\r\n            <td class=\"right\">\r\n              <span>{{ $ctrl.current.active.card.taxPercentMin || \"-\" }} %</span>\r\n            </td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.active.card.kind == 'auto'\">\r\n            <td colspan=\"2\">\r\n              <span class=\"text-info\" ng-if=\"$ctrl.current.active.card.lastChecked != '2000-01-01T00:00:00Z'\"><small>{{'SALAXY.NG1.CurrentTaxCardComponent.taxCardChecked' | sxyTranslate}}\r\n                  {{$ctrl.current.active.card.lastChecked | date: \"dd.MM.yyyy HH:mm\"}}</small></span>\r\n              <br />\r\n              <button type=\"button\" ng-click=\"$ctrl.setSharedAutoForSelf()\"\r\n                class=\"btn btn-info\">{{'SALAXY.NG1.CurrentTaxCardComponent.checkAutomaticTaxCard' | sxyTranslate}}</button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <table class=\"table table-condensed\" style=\"margin-top: 6px\" ng-if=\"$ctrl.current.active.card.incomeLimit\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\" style=\"padding-left: 0;\"><strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.incomeLimit\"></strong></th>\r\n            <th class=\"right\">{{ $ctrl.current.active.card.incomeLimit | currency : '€' : 0 }}</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td style=\"width: 20px;\" class=\"text-center\">-</td>\r\n            <td><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.active.result.totalIncome | currency }}</td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.active.result.totalIncomeJanuary\">\r\n            <td></td>\r\n            <td>...<span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.inJanuary\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.active.result.totalIncomeJanuary | currency }}</td>\r\n          </tr>\r\n          <tr class=\"total\">\r\n            <td colspan=\"2\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.beforeIncomeLimit\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.active.card.incomeLimit - $ctrl.current.active.result.totalIncome | currency }}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/templates/WorkerLayout.html\",`<div ng-cloak class=\"salaxy-component salaxy-navi-page-container container-personal\" ng-class=\"($ctrl.isNaviOpen ? 'salaxy-navi-sm-opened ' : '') + $ctrl.current.cssClass\" ng-if=\"!$ctrl.showFullPageLoader\">\r\n\r\n  <div class=\"salaxy-navi-sidebar hidden-print\" ng-if=\"!$ctrl.showFullPageLoader\">\r\n    <div class=\"salaxy-logo-container\">\r\n      <a href=\"/#/\"><!--<img src=\"/img/navi-logo.png\" />--></a>\r\n    </div>\r\n    <div ng-controller=\"SessionController as $session\">\r\n      <div class=\"salaxy-login-button text-center\" style=\"padding:7px;\" ng-hide=\"$session.isAuthenticated\">\r\n        <button ng-click=\"$session.signIn()\" class=\"btn btn-default salaxy-login-button-login\">\r\n        <span class=\"glyphicon glyphicon-lock\"></span>\r\n        <span class=\"salaxy-login-button-text\">{{ $session.isSessionChecking ?  ('SALAXY.NG1.LoginButtonComponent.searching' | sxyTranslate) : ('SALAXY.UI_Terms.login' | sxyTranslate) }}</span>\r\n      </button>\r\n      </div>\r\n      <div class=\"salaxy-login-button-personal\" ng-controller=\"PersonalWebLegacyController as $legacy\">\r\n\r\n        <div ng-show=\"$session.isAuthenticated\" class=\"salaxy-login-button-logout\" ng-init=\"isNavCollapsed = true\">\r\n          <salaxy-avatar avatar=\"$session.avatar\"></salaxy-avatar>\r\n          <div class=\"login-text\">\r\n            <span class=\"salaxy-login-button-text\">\r\n            {{ $session.isAuthenticated ? $session.avatar.displayName : ('SALAXY.NG1.LoginButtonComponent.authenticating' | sxyTranslate) }}\r\n          </span>\r\n            <button ng-if=\"$session.isAuthenticated\" ng-click=\"$legacy.signOut()\" class=\"btn btn-transparent btn-xs\"><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> <span class=\"\" sxy-text=\"SALAXY.UI_Terms.logout\"></span></button>\r\n            <div class=\"btn-group language-selection btn-group-xs\" uib-dropdown ng-show=\"'test' | sxyIsInRole\" ng-controller=\"PersonAccountController as $accountCtrl\">\r\n              <button type=\"button\" class=\"btn btn-transparent\" uib-dropdown-toggle>\r\n                <i class=\"fa fa-globe\" style=\"font-size:1.1em;\"></i>\r\n                <span> {{\"SALAXY.ENUM.Language.\" + $accountCtrl.getAccountLanguage() + \".label\" | sxyTranslate}}</span> \r\n          \r\n                <i class=\"fa fa-chevron-down\"></i>\r\n            </button>\r\n              <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n                <li role=\"menuitem\" ng-if=\"$accountCtrl.getAccountLanguage() != 'fi'\"><a ng-click=\"$accountCtrl.current.language = 'fi'; $accountCtrl.saveCurrent()\">Suomi</a></li>\r\n                <li role=\"menuitem\" ng-if=\"$accountCtrl.getAccountLanguage() != 'en'\"><a ng-click=\"$accountCtrl.current.language = 'en'; $accountCtrl.saveCurrent()\">English</a></li>\r\n                <li role=\"menuitem\" ng-if=\"$accountCtrl.getAccountLanguage() != 'sv'\"><a ng-click=\"$accountCtrl.current.language = 'sv';$accountCtrl.saveCurrent()\">Svenska</a></li>\r\n              </ul>\r\n            </div>\r\n\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <salaxy-navi-sitemap template-url=\"salaxy-components/pages-personal/templates/WorkerSitemap.html\" mode=\"accordion\"></salaxy-navi-sitemap>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.id == 'home'\">\r\n    <div ng-controller=\"WelcomeController as $welcomeCtrl\" sxy-if-role=\"worker\">\r\n      <div ng-if=\"$welcomeCtrl.workerDataNew.timeline\" class=\"timeline-sidebar  hidden-xs\">\r\n        <div class=\"list-panel  panel panel-sm panel-secondary panel-own-taxcard panel-secondary\">\r\n          <div class=\"panel-heading\" sxy-text=\"SALAXY.NG1.WelcomeComponent.taxcard\"></div>\r\n          <div ng-show=\"$welcomeCtrl.workerUI.taxCardAdded\" class=\"salaxy-component table-responsive panel-content md-height\">\r\n            <div class=\"panel-content md-height\">\r\n              <div class=\"panel-body no-vertical-padding salaxy-tax-card-chart chart-container\" style=\"max-height:230px; padding-top:0; padding-bottom:0; padding-left:5px;padding-right:5px;\">              \r\n                <salaxy-chart ng-if=\"$welcomeCtrl.taxcardChartData.limits.hasLimit == true\" custom-height=\"210px\" config=\"$welcomeCtrl.taxcardChartData.config\"></salaxy-chart>             \r\n                <salaxy-chart ng-if=\"$welcomeCtrl.taxcardChartData.limits.hasLimit == false || !$welcomeCtrl.taxcardChartData.limits.hasLimit\" config=\"$welcomeCtrl.taxcardChartData.config\"></salaxy-chart>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-show=\"!$welcomeCtrl.workerUI.taxCardAdded\" class=\"panel-body panel-content md-height align-middle\">\r\n            <div class=\"text-center\">\r\n              <p sxy-text=\"SALAXY.NG1_PagesPersonal.taxcards.buttons.getTaxPercentsBtn\"></p>\r\n            </div>\r\n          </div>\r\n          <div class=\"panel-footer text-center\">\r\n            <a class=\"btn btn-primary btn-sm\" href=\"#/taxcards\" sxy-text=\"SALAXY.NG1.WelcomeComponent.taxcard\"></a>\r\n\r\n          </div>\r\n        </div>\r\n        <div class=\"list-panel panel panel-sm panel-secondary panel-new-calculation\">\r\n          <div class=\"panel-heading\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.sendCalculation.panelHeading\"></div>\r\n          <div class=\"panel-body panel-content\">\r\n            <div class=\"text-center\">\r\n              <h3 class=\"text-warning\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.sendCalculation.panelTitle\"></h3>\r\n              <p sxy-text=\"SALAXY.NG1_PagesPersonal.index.sendCalculation.panelText\"></p>\r\n            </div>\r\n          </div>\r\n          <div class=\"panel-footer text-center\">\r\n            <a class=\"btn btn-primary btn-sm\" href=\"#/calc/details/new\" sxy-text=\"SALAXY.NG1_PagesPersonal.index.sendCalculation.button\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <header class=\"salaxy-navi-header-mobile\">\r\n    <button type=\"button\" class=\"salaxy-navi-hamburger btn btn-default pull-right\" ng-click=\"$ctrl.toggleNavi()\">\r\n      <span class=\"sr-only\" sxy-text=\"SALAXY.UI_Terms.navigation\"></span>\r\n      <i class=\"fa  fa-bars\" aria-hidden=\"true\"></i>\r\n    </button>\r\n    <div class=\"btn-group pull-right btn-group-login-button\" ng-controller=\"SessionController as $session\" uib-dropdown>\r\n      <button ng-hide=\"$session.isAuthenticated\" ng-click=\"$session.signIn()\" class=\"btn btn-default salaxy-login-button-login\">\r\n        <span class=\"glyphicon glyphicon-lock\"></span>\r\n        <span class=\"salaxy-login-button-text\">{{ $ctrl.isSessionChecking ?  ('SALAXY.NG1.LoginButtonComponent.searching' | sxyTranslate) : ('SALAXY.UI_Terms.login' | sxyTranslate) }}</span>\r\n    </button>\r\n      <div class=\"login-button\" uib-dropdown-toggle type=\"button\" ng-show=\"$session.isAuthenticated\">\r\n        <salaxy-avatar avatar=\"$session.avatar\"></salaxy-avatar>\r\n      </div>\r\n      <ul ng-controller=\"PersonalWebLegacyController as $legacy\" class=\"dropdown-menu\" role=\"menu\" aria-labelledby=\"account-menu\" uib-dropdown-menu>\r\n        <li>\r\n          <a href=\"#\" ng-click=\"$legacy.signOut()\" sxy-text=\"SALAXY.UI_Terms.logout\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <h1>{{ $ctrl.title | sxyTranslate }}</h1>\r\n  </header>\r\n  <div class=\"salaxy-navi-main-container\">\r\n    <content>\r\n      <ng-transclude ng-transclude-slot=\"header\">\r\n\r\n      </ng-transclude>\r\n      <div id=\"salaxy-alert-container\"></div>\r\n      <ng-transclude ng-transclude-slot=\"main\">\r\n        <main>\r\n          <div class=\"hidden-sm hidden-xs\">\r\n            <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' : 'container'\">\r\n\r\n              <div class=\"row\" ng-if=\"$ctrl.current.id != 'home'\">\r\n                <div class=\"col-xs-12\">\r\n                  <h1 class=\"page-title\">\r\n                    {{ $ctrl.title | sxyTranslate }}\r\n                  </h1>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-class=\"$ctrl.current.isFullWidth ? 'container-fluid' :  'container'\" ng-view autoscroll=\"true\"></div>\r\n        </main>\r\n      </ng-transclude>\r\n    </content>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/templates/WorkerSitemap.html\",`<div class=\"salaxy-component salaxy-navi-sitemap\">\r\n  <ul class=\"list-group\">\r\n    <li ng-repeat=\"section in $ctrl.sitemap | filter:{ hidden: '!true' }\" class=\"list-group-item\">\r\n      <a ng-href=\"{{section.id != 'abc' ? section.url : 'https://help.palkkaus.fi/hc/fi'}}\" ng-attr-target=\"{{section.id == 'abc' ? '_blank' : undefined}}\" ng-click=\"!section.children || !section.children.length ? $ctrl.toggleNavi() : return\" ng-class=\"{ 'active' : $ctrl.isCurrent(section)}\">\r\n        <span ng-if=\"$ctrl.mode=='accordion' && section.children && section.children.length\">\r\n          <i class=\"fa fa-chevron-down pull-right\" ng-class=\"{'upside' : $ctrl.getSectionId() == section.id}\" aria-hidden=\"true\"></i>\r\n        </span> {{section.title | sxyTranslate}}\r\n      </a>\r\n      <ul ng-hide=\"!section.children.length || ($ctrl.mode=='accordion' && $ctrl.getSectionId() != section.id)\">\r\n        <li class=\"visible-xs\">\r\n          <strong ng-show=\"$ctrl.isCurrent(section)\">\r\n            <a ng-href=\"{{section.url}}\" ng-click=\"$ctrl.toggleNavi()\">{{section.title | sxyTranslate}}</a>\r\n          </strong>\r\n          <span ng-hide=\"$ctrl.isCurrent(section)\">\r\n            <a ng-href=\"{{section.url}}\" ng-click=\"$ctrl.toggleNavi()\">{{section.title | sxyTranslate}}</a>\r\n          </span>\r\n        </li>\r\n        <li ng-repeat=\"subNavi in section.children | filter:{ hidden: '!true' }\">\r\n          <strong ng-show=\"$ctrl.isCurrent(subNavi)\">\r\n            <a ng-href=\"{{subNavi.url}}\" ng-click=\"$ctrl.toggleNavi()\">{{subNavi.title | sxyTranslate}}</a>\r\n          </strong>\r\n          <span ng-hide=\"$ctrl.isCurrent(subNavi)\">\r\n            <a ng-href=\"{{subNavi.url}}\" ng-click=\"$ctrl.toggleNavi()\">{{subNavi.title | sxyTranslate}}</a>\r\n          </span>\r\n        </li>\r\n      </ul>\r\n    </li>\r\n  </ul>\r\n\r\n  <div class=\"poweredby\">\r\n    <span class=\"poweredby-image\"></span>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/workers/details.html\",`<salaxy-worker-details model=\"'url'\" is-read-only-forced=\"$ctrl.route.readOnly\" hide-button=\"$ctrl.route.readOnly\"></salaxy-worker-details>`);\n\n $templateCache.put(\"salaxy-components/pages-personal/workers/index.html\",`<salaxy-employment-list read-only=\"'household' | sxyIsInRole\"></salaxy-employment-list>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountAuthorizationPerson.html\",`﻿<div class=\"salaxy-component salaxy-account-authorization-person\">\r\n  <form name=\"accountAuthorization\" sxy-if-role=\"auth\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 col-sm-6 col-md-12\">\r\n        <legend sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.identificationTitle\"></legend>\r\n        <div class=\"row table-row\" ng-if=\"!$ctrl.session.currentAccount.identity.contract.isSigned\">\r\n          <div class=\"col-xs-12 \" ng-controller=\"WorkerOnboardingController as $wizard\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.notIdentified\"></strong><br>\r\n            <button class=\"btn btn-primary\" ng-click=\"$wizard.launch()\" sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.identifyBtn\"></button>\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\" ng-if=\"$ctrl.session.currentAccount.identity.contract.isSigned\">\r\n          <div class=\"col-xs-12\">\r\n            <strong><span sxy-text-=\"SALAXY.NG1.AccountAuthorizationPersonComponent.haveIdentified\"></span> {{$ctrl.session.currentAccount.identity.contract.signedAt | date}}.</strong>\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.credentialLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            {{$ctrl.session.currentCredential.avatar.id}}\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.authorizationTypeLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            {{'SALAXY.ENUM.AuthorizationType.' + $ctrl.session.currentAccount.identity.contract.authorizationType + '.label' |sxyTranslate}}\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-4  text-right\" ng-if=\"$ctrl.session.currentAccount.identity.contract.authorizationType == 'employerAuthorization'\">\r\n            <a class=\"\" ng-href=\"{{$ctrl.authorizationPdfUrl}}\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.seePreview\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-6 col-md-12 margin-top-md margin-top-xs\">\r\n        <legend sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.userInfoTitle\"></legend>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.userNameLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            {{$ctrl.session.currentCredential.email}}\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-4\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.authMethodLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            {{'SALAXY.ENUM.AuthenticationMethod.' + $ctrl.session.currentCredential.authenticationMethod + '.label' |sxyTranslate}}\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-6 col-md-12 margin-top-md margin-top-sm\">\r\n        <legend sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.termsAndPrivacyTitle\"></legend>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.termsLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-4 text-right\">\r\n            <span sxy-html=\"SALAXY.NG1.AccountAuthorizationPersonComponent.termsBtn.html\"></span>\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.privacyLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-4 text-right\">\r\n            <span sxy-html=\"SALAXY.NG1.AccountAuthorizationPersonComponent.privacyBtn.html\"></span>\r\n\r\n          </div>\r\n        </div>\r\n        <div class=\"row table-row\">\r\n          <div class=\"col-xs-12 col-sm-8\">\r\n            <strong sxy-text=\"SALAXY.NG1.AccountAuthorizationPersonComponent.privacyStatementLabel\"></strong>\r\n          </div>\r\n          <div class=\"col-xs-12 col-sm-4 text-right\">\r\n\r\n            <span sxy-html=\"SALAXY.NG1.AccountAuthorizationPersonComponent.privacyStatementBtn.html\"></span>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountAvatarEditPerson.html\",`<div class=\"salaxy-component salaxy-account-avatar-edit-person\">\r\n  <form name=\"workerForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current\">\r\n    <div class=\"form-group\">\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <label for=\"avatarPreview\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarLabel\"></label>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-8\">\r\n        <div class=\"worker-avatar-col\">\r\n          <salaxy-avatar style=\"font-size: 200px\" avatar=\"$ctrl.current.avatar\"></salaxy-avatar>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"form-group\">\r\n      <div class=\"col-xs-12 col-sm-4\">\r\n        <label for=\"avatarPictureType\" class=\"control-label\" style=\"text-align:left\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarTypeLabel\"></label>\r\n      </div>\r\n      <div class=\"col-xs-12 col-sm-8\">\r\n        <select class=\"form-control\" id=\"avatarPictureType\" ng-model=\"$ctrl.current.avatar.pictureType\" ng-change=\"$ctrl.typeForAvatarChanged()\">\r\n          <option value=\"\" disabled sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionChoose\"></option>\r\n          <option value=\"icon\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionIcon\"></option>\r\n          <option value=\"uploaded\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionUploaded\"></option>\r\n          <option value=\"gravatar\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.optionGravatar\"></option>\r\n        </select>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.avatar.pictureType == 'gravatar'\" class=\"row\">\r\n      <div class=\"input-info col-sm-8 col-sm-offset-4\">\r\n        <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n        <p class=\"small input-info-text with-icon \" sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.gravatarInfo.html\"></p>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.avatar.pictureType == 'icon'\">\r\n      <salaxy-input name=\"avatarInitials\" label=\"SALAXY.NG1.AccountAvatarEditPersonComponent.initialsLabel\" ng-model=\"$ctrl.current.avatar.initials\" max-length=\"2\"></salaxy-input>\r\n      <salaxy-input-enum ng-model=\"$ctrl.current.avatar.color\" name=\"avatarColor\" label=\"SALAXY.NG1.AccountAvatarEditPersonComponent.colorLabel\" options=\"{ '#7F2C2A': ('SALAXY.NG1.AccountAvatarEditPersonComponent.colorBrown' | sxyTranslate), '#91D214': ('SALAXY.NG1.AccountAvatarEditPersonComponent.colorLime' | sxyTranslate), '#61703B': ('SALAXY.NG1.AccountAvatarEditPersonComponent.colorDarkGreen' | sxyTranslate), '#D10074': ('SALAXY.NG1.AccountAvatarEditPersonComponent.colorPink' | sxyTranslate)}\">\r\n      </salaxy-input-enum>\r\n    </div>\r\n    <div class=\"form-group\">\r\n      <div ng-if=\"$ctrl.current.avatar.pictureType == 'uploaded'\">\r\n        <div class=\"col-xs-12 col-sm-4\">\r\n          <label for=\"avatarImageUpload\" sxy-text=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImageLabel\"></label>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-8\">\r\n          <div name=\"avatarImageUpload\" ng-model=\"avatarImage\" ngf-drop=\"$ctrl.uploadAvatarImage($file)\" ngf-select=\"$ctrl.uploadAvatarImage($file)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" ngf-multiple=\"false\" ngf-min-size=\"5KB\" ngf-max-size=\"10MB\"\r\n            ngf-pattern=\"'image/*'\" ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\">\r\n            <span sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImage.html\"></span>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-8 col-sm-offset-4 input-info\">\r\n        <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n        <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.avatarDescription.html\" style=\"padding-top:0.4em;\"></p>\r\n      </div>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button ng-click=\"$ctrl.saveCurrent()\" ng-disabled=\"workerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountContactEditPerson.html\",`<div class=\"salaxy-component salaxy-account-contact-edit-person\">\r\n  <form name=\"workerForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <salaxy-input name=\"email\" label=\"SALAXY.MODEL.PersonAccount.contact.email.title\" sxy-email ng-model=\"$ctrl.current.contact.email\" ng-change=\"$ctrl.emailForAvatarChanged()\">\r\n        </salaxy-input>\r\n        <salaxy-input name=\"telephone\" label=\"SALAXY.MODEL.PersonAccount.contact.telephone.title\" sxy-mobile-phone ng-model=\"$ctrl.current.contact.telephone\"></salaxy-input>\r\n        <salaxy-input name=\"street\" label=\"SALAXY.MODEL.PersonAccount.contact.street.title\" ng-model=\"$ctrl.current.contact.street\" ng-required=\"'household' | sxyIsInRole\"></salaxy-input>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-sm-offset-4 input-info\">\r\n            <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n            <p class=\"small input-info-text with-icon\" style=\"padding-top:0.4em;\" sxy-text=\"SALAXY.NG1.AccountContactEditPersonComponent.addressInfo\"></p>\r\n          </div>\r\n        </div>\r\n        <salaxy-input name=\"postalCode\" label=\"SALAXY.MODEL.PersonAccount.contact.postalCode.title\" sxy-postal-code-fi ng-model=\"$ctrl.current.contact.postalCode\" ng-required=\"'household' | sxyIsInRole\"></salaxy-input>\r\n        <salaxy-input name=\"city\" label=\"SALAXY.MODEL.PersonAccount.contact.city.title\" ng-model=\"$ctrl.current.contact.city\" ng-required=\"'household' | sxyIsInRole\"></salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button ng-click=\"$ctrl.saveCurrent()\" ng-disabled=\"workerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountDetailsEditPerson.html\",`<div class=\"salaxy-component salaxy-account-details-edit-person\">\r\n  <form name=\"workerForm\" class=\"form-horizontal\" ng-if=\"$ctrl.current\">\r\n    <div class=\"row language-selection spacer-bottom\" ng-controller=\"SessionController as $session\">\r\n      <div class=\"col-xs-4 control-label\"><strong class=\"\" sxy-text=\"SALAXY.NG1.LanguageSelectionComponent.languageSelectionLabel\"></strong></div>\r\n      <div class=\"col-xs-8\">\r\n\r\n        <div class=\"btn-group btn-group-sm pull-right\" role=\"group\">\r\n\r\n          <button class=\"btn\" ng-class=\"$ctrl.getAccountLanguage() == 'fi' ? 'active btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.current.language='fi'\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></button>\r\n          <button class=\"btn\" ng-class=\"$ctrl.getAccountLanguage() == 'en' ? 'active btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.current.language='en'\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></button>\r\n          <button class=\"btn\" ng-class=\"$ctrl.getAccountLanguage() == 'sv' ? 'active btn-primary disabled' : 'btn-default'\" ng-click=\"$ctrl.current.language='sv'\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n\r\n        <salaxy-input name=\"firstName\" label=\"SALAXY.MODEL.PersonAccount.identity.firstName.title\" readonly=\"true\" ng-model=\"$ctrl.current.identity.firstName\"></salaxy-input>\r\n        <salaxy-input name=\"lastName\" label=\"SALAXY.MODEL.PersonAccount.identity.lastName.title\" readonly=\"true\" ng-model=\"$ctrl.current.identity.lastName\"></salaxy-input>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-sm-offset-4 input-info\">\r\n            <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n            <p class=\"small input-info-text with-icon \" sxy-html=\"SALAXY.NG1.AccountDetailsEditPersonComponent.nameDecription.html\"></p>\r\n          </div>\r\n          <div class=\"col-sm-2\">\r\n            <button class=\"btn btn-default pull-right btn-sm\" ng-controller=\"WorkerOnboardingController as $wizard\" ng-click=\"$wizard.launch()\" sxy-text=\"SALAXY.NG1.AccountDetailsEditPersonComponent.launchWizardBtn\"></button>\r\n          </div>\r\n        </div>\r\n        <salaxy-input name=\"officialPersonId\" label=\"SALAXY.MODEL.PersonAccount.identity.officialId.title\" sxy-personal-id-fi readonly=\"true\" ng-model=\"$ctrl.current.identity.officialId\">\r\n        </salaxy-input>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-8 col-sm-offset-4 input-info\">\r\n            <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n            <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.AccountDetailsEditPersonComponent.personalIdDescription.html\"></p>\r\n          </div>\r\n        </div>\r\n        <salaxy-input name=\"ibanNumber\" label=\"SALAXY.MODEL.PersonAccount.identity.ibanNumber.title\" sxy-iban ng-model=\"$ctrl.current.identity.ibanNumber\"></salaxy-input>\r\n      </div>\r\n      <div class=\"col-xs-12 text-right\">\r\n        <button ng-click=\"$ctrl.saveCurrent()\" ng-disabled=\"workerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountDetailsPerson.html\",`<div class=\"salaxy-component salaxy-account-details-person\">\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12  col-md-4 account-info-container\">\r\n      <div class=\"light-bg\">\r\n        <div class=\"worker-avatar-wrapper\">\r\n          <salaxy-account-info-person></salaxy-account-info-person>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-xs-12 col-md-8\" ng-if=\"$ctrl.current\">\r\n      <div>\r\n        <uib-tabset active=\"$ctrl.currentTab\">\r\n          <uib-tab index=\"'default'\" heading=\"{{'SALAXY.NG1.AccountDetailsPersonComponent.personalInfoTabHeading' | sxyTranslate}}\">\r\n            <salaxy-account-details-edit-person current=\"$ctrl.current\"></salaxy-account-details-edit-person>\r\n          </uib-tab>\r\n          <uib-tab index=\"'contact'\" heading=\"{{'SALAXY.NG1.AccountDetailsPersonComponent.contactInfoTabHeading' | sxyTranslate}}\">\r\n            <salaxy-account-contact-edit-person current=\"$ctrl.current\"></salaxy-account-contact-edit-person>\r\n          </uib-tab>\r\n          <uib-tab index=\"'avatar'\" heading=\"{{'SALAXY.NG1.AccountDetailsPersonComponent.avatarTabHeading' | sxyTranslate}}\">\r\n            <salaxy-account-avatar-edit-person current=\"$ctrl.current\"></salaxy-account-avatar-edit-person>\r\n          </uib-tab>\r\n          <uib-tab index=\"'identity'\" heading=\"{{'SALAXY.NG1.AccountDetailsPersonComponent.authorizationTabHeading' | sxyTranslate}}\">\r\n            <salaxy-account-authorization-person></salaxy-account-authorization-person>\r\n          </uib-tab>\r\n          <uib-tab index=\"'insurance'\" heading=\"{{'SALAXY.NG1.AccountDetailsPersonComponent.insurancesTabHeading' | sxyTranslate}}\" ng-if=\"'household' | sxyIsInRole\">\r\n            <salaxy-account-insurance-edit-person></salaxy-account-insurance-edit-person>\r\n          </uib-tab>\r\n        </uib-tabset>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-xs-12\" sxy-if-role=\"test\">\r\n      <hr />\r\n      <p>Test only:</p>\r\n      <ul ng-controller=\"SessionController as $session\">\r\n        <li>\r\n          Last login as (session):\r\n          <strong>{{ $session.person.lastLoginAs }}</strong> (isEmployer: {{$session.person.isEmployer}}, isWorker: {{$session.person.isWorker}})\r\n        </li>\r\n        <li>\r\n          Server-side:\r\n          <strong>{{ $ctrl.current.lastLoginAs }}</strong> (isEmployer: {{$ctrl.current.isEmployer}}, isWorker: {{$ctrl.current.isWorker}})\r\n        </li>\r\n        <li>\r\n          Vaihda roolia:\r\n          <a ng-click=\"$session.switchRole('household')\">Kotitalous</a>\r\n          <a ng-click=\"$session.switchRole('worker')\">Työntekijä</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountInfoPerson.html\",`<div class=\"salaxy-component salaxy-account-info-person\">\r\n  <div class=\"worker-avatar-wrapper text-center\">\r\n    <salaxy-avatar avatar=\"$ctrl.avatar\"></salaxy-avatar>\r\n  </div>\r\n  <div class=\"info-wrapper text-center\" style=\"margin-top:15px;\">\r\n    <h2>{{ $ctrl.person.avatar.displayName || (\"SALAXY.NG1.AccountInfoPersonComponent.noSelection\" | sxyTranslate) }}</h2>\r\n    <div class=\"account-info-contact-details\">\r\n      <span ng-if=\"$ctrl.person.contact.telephone\">{{$ctrl.person.contact.telephone}}</span>\r\n      <br /> {{ $ctrl.person.contact.email }}\r\n      <br />\r\n      <span ng-if=\"$ctrl.person.identity.ibanNumber\">\r\n        {{ $ctrl.person.identity.ibanNumber | sxyIban }}\r\n      </span>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/AccountInsuranceEditPerson.html\",`<div class=\"salaxy-component salaxy-account-insurance-edit-person\">\r\n  <form name=\"insuranceForm\" class=\"form-horizontal\">\r\n    <legend>Tapaturmavakuutus</legend>\r\n    <div class=\"input-info\">\r\n      <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n      <p class=\"small input-info-text with-icon\">\r\n        Lakisääteinen tapaturmavakuutus on työnantajalle pakollinen, jos maksat palkkaa kaikille työntekijöillesi yhteensä\r\n        <strong>väh. 1400€</strong> kalenterivuoden aikana. Vakuutus on työnantajan vakuutus, joka kattaa kaikki hänen työntekijänsä.\r\n      </p>\r\n      <p class=\"small input-info-text with-icon\" ng-if=\"($ctrl.personal.insurance.company || 'none') == 'none'\">\r\n        Saat hankittua työnantajan lakisääteisen työtapaturmavakuutuksen omasta vakuutusyhtiöstäsi.\r\n        <strong>HUOM:</strong> Vakuutus pitää olla voimassa ennen töiden aloittamista.\r\n      </p>\r\n    </div>\r\n    <div>\r\n      <p>\r\n        <b>Anna voimassa olevan vakuutuksen tiedot.</b> Valitse \"Ei yhtiötä\", jos sinulla ei ole vakuutusta.\r\n      </p>\r\n      <salaxy-input-enum ng-model=\"$ctrl.personal.insurance.company\" type=\"select\" enum=\"InsuranceCompany\" filter=\"none,fennia,if,lähiTapiola,pohjantähti,pohjola,turva,aVakuutus,folksam,alandia,ålands\" label=\"SALAXY.MODEL.InsuranceContract.company.editLabel\"\r\n        name=\"insurance-company\" require=\"true\"></salaxy-input-enum>\r\n      <div ng-if=\"($ctrl.personal.insurance.company || 'none') != 'none'\">\r\n        <salaxy-input ng-model=\"$ctrl.personal.insurance.contractNumber\" require=\"true\" name=\"insuranceContractNumber\" label=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\">\r\n        </salaxy-input>\r\n        <salaxy-form-group name=\"insuranceWarning\" label-type=\"empty-label\">\r\n          <small>Tähän syötetyt vakuutustiedot näkyvät myös työntekijän palkkalaskelmassa.</small>\r\n        </salaxy-form-group>\r\n      </div>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button ng-disabled=\"!$ctrl.personal.insurance.company || $ctrl.isSaving('insuranceContracts')\" class=\"btn btn-primary\" ng-click=\"$ctrl.save('insuranceContracts')\"><i\r\n          ng-if=\"$ctrl.isSaving('insuranceContracts')\" class=\"fa fa-refresh fa-spin fa-fw\"></i>\r\n        <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n    </div>\r\n  </form>\r\n  <form name=\"pensionForm\" class=\"form-horizontal\">\r\n    <legend>TYEL-sopimus</legend>\r\n    <div class=\"input-info\">\r\n      <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n      <p class=\"small input-info-text with-icon\">\r\n        Palkkaus.fi-palvelu ilmoittaa TyEL-ilmoitukset tulorekisteriin oletuksena suoraan työeläkeyhtiö Varman kautta ja Varma lähettää näistä laskun jälkikäteen.\r\n        <strong>Tilapäinen työnantaja ei tarvitse siihen sopimusta.</strong>\r\n        <br> Jos sinulla on jatkuva työsopimus tai maksat palkkaa yli {{ $ctrl.sideCosts.tyelContractEmployerLimit | currency}} puolessa vuodessa, suosittelemme tekemään sopimuksen työeläkeyhtiön kanssa.\r\n      </p>\r\n    </div>\r\n    <div>\r\n      <p>\r\n        <b>Anna voimassa olevan sopimuksen tiedot.</b> Valitse \"Ei yhtiötä\", jos olet tilapäinen työnantaja.\r\n      </p>\r\n      <salaxy-input-enum ng-model=\"$ctrl.personal.pension.company\" type=\"select\" label=\"SALAXY.MODEL.PensionContract.company.editLabel\" name=\"pensionCompany\" enum=\"PensionCompany\" filter=\"none,varma,elo,ilmarinen,veritas,apteekkien,verso,valio,kevaMunicipal,kevaAland,kevaChurch,kevaKela,kevaState\" require=\"true\"></salaxy-input-enum>\r\n      <div salaxy-if-role=\"test\" class=\"test-number\">\r\n        <div class=\"form-group\" ng-if=\"$ctrl.personal.pension.company && $ctrl.personal.pension.company != 'none'\">\r\n          <div class=\"col-sm-8 col-sm-offset-4 text-right-sm\">\r\n            <span>Test only: <button class=\"btn btn-secondary btn-xs\" ng-click=\"$ctrl.setPensionNumberForTest($ctrl.personal.pension)\"> Generoi numero </button></span>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <salaxy-input ng-if=\"$ctrl.personal.pension.company && $ctrl.personal.pension.company != 'none'\" require=\"true\" name=\"pensionContractNumber\" label=\"SALAXY.MODEL.PensionContract.contractNumber.title\" ng-model=\"$ctrl.personal.pension.contractNumber\" tooltip-html=\"{{'SALAXY.NG1.InsuranceSettingsComponent.pension.errors.sxyPensionContractNumber.html' | sxyTranslate}}\"\r\n        tooltip-placement=\"top-right\" sxy-pension-contract-number></salaxy-input>\r\n    </div>\r\n    <div ng-show=\"pensionForm.pensionContractNumber.$error.sxyTemporaryPensionContractNumber\">\r\n      <div class=\"input-info text-danger\">\r\n        <div class=\"input-info-icon\"><i class=\"fa fa-exclamation-triangle \"></i></div>\r\n        <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.InsuranceSettingsComponent.pension.errors.sxyTemporaryPensionContractNumber.html\"></p>\r\n      </div>\r\n    </div>\r\n    <div class=\"text-right\">\r\n      <button ng-disabled=\"!$ctrl.personal.pension.company || pensionForm.$invalid || $ctrl.isSaving('pensionContracts')\" class=\"btn btn-primary\" ng-click=\"$ctrl.save('pensionContracts')\"><i ng-if=\"$ctrl.isSaving('pensionContracts')\" class=\"fa fa-refresh fa-spin fa-fw\"></i>\r\n        <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n    </div>\r\n  </form>\r\n  <div>\r\n    <legend>Työttömyysvakuutus</legend>\r\n    <div class=\"input-info\">\r\n      <div class=\"input-info-icon\"><i class=\"fa fa-info-circle text-default\"></i></div>\r\n      <p class=\"small input-info-text with-icon\">\r\n        Työttömyysvakuutusmaksuja ei voi maksaa Palkkaus.fi-palvelun kautta, koska <a href=\"https://www.tyollisyysrahasto.fi/\" target=\"_blank\">Työllisyysrahasto</a> laskuttaa työnantajia suoraan neljännesvuosittain, jos työnantaja maksaa palkkaa vähintään\r\n        1400€ kalenterivuoden aikana.\r\n      </p>\r\n      <p class=\"small input-info-text with-icon\">\r\n        Maksut näkyvät laskelmilla, ne ilmoitetaan tulorekisteriin eikä niiden takia tarvitse tehdä mitään muuta, kuin maksaa Työllisyysrahastolta aikanaan tulevat laskut.\r\n      </p>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/CalcHouseholdUsecase.html\",`<div class=\"salaxy-component salaxy-calc-household-usecase\">\r\n  <form ng-submit=\"$ctrl.submitHouseholdUsecase()\" ng-readonly=\"$ctrl.isReadOnly\" name=\"detailsUsecase\" class=\"form-horizontal\">\r\n    <div class=\"salaxy-calc-dialog-body\">\r\n      <div class=\"salaxy-calc-dialog-container\">\r\n        <div class=\"row\">\r\n          <div class=\"col-md-5 col-xs-12\" ng-if=\"$ctrl.isReadOnly\">\r\n            <button type=\"button\" class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.startEdit()\" sxy-text=\"SALAXY.UI_Terms.edit\"></button>\r\n          </div>\r\n          <div class=\"col-md-5 col-xs-12\" ng-if=\"!$ctrl.isReadOnly\">\r\n            <h1 ng-if=\"!$ctrl.isUsecaseSelected\" sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.ui.selectionTitle\" class=\"choose-usecase\"></h1>\r\n            <div ng-if=\"$ctrl.isUsecaseSelected\" class=\"spacer-bottom \">\r\n              <div ng-if=\"$ctrl.showSave\" class=\"spacer-bottom\">\r\n                <button type=\"button\" class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.saveEmployment()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n                <button type=\"button\" class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.resetEmployment()\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n                <button ng-if=\"$ctrl.isUsecaseSelected\" class=\"btn btn-secondary btn-sm\" type=\"button\" ng-click=\"$ctrl.resetUsecase()\"><span\r\n                  HouseholdUsecaseComponent></span></button>\r\n              </div>\r\n              <button ng-if=\"$ctrl.isUsecaseSelected && !$ctrl.showSave\" class=\"btn btn-secondary btn-sm btn-labeled-left\" type=\"button\" ng-click=\"$ctrl.resetUsecase()\"><i\r\n                  class=\"fa fa-chevron-left\"></i><span sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.ui.changeSelection\"></span></button>\r\n            </div>\r\n            <div ng-if=\"$ctrl.isUsecaseSelected && !$ctrl.isEmployment\" style=\"padding-top:15px;\">\r\n              <h1 sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.ui.salaryDate\"></h1>\r\n              <p sxy-text=\"SALAXY.NG1.HouseholdUsecaseComponent.ui.salaxyDateInfo.html\"></p>\r\n              <div class=\"form-horizontal\">\r\n                <salaxy-datepicker-popup name=\"requestedSalaryDate\" ng-model=\"$ctrl.requestedSalaryDate\" label=\"SALAXY.NG1.CalcWorktimeComponent.salaryDateLabel\" label-cols=\"col-sm-6\" date-disabled=\"salary\" placeholder=\"SALAXY.NG1.HouseholdUsecaseComponent.datePickerPlaceHolder\"\r\n                zero-payment=\"$ctrl.isCurrentZeroPayment\" payment-channel=\"$ctrl.calc.info.paymentChannel\"></salaxy-datepicker-popup>\r\n              </div>\r\n              <h1 sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.worktime.title\"></h1>\r\n              <p ng-if=\"!$ctrl.dateRange.start || !$ctrl.dateRange.start\" sxy-text=\"SALAXY.NG1.CalcWorktimeComponent.worktime.description\"></p>\r\n              <div class=\"form-horizontal\">\r\n                <salaxy-input-enum ng-model=\"$ctrl.periodShortcut\" name=\"periodShortcut\" ng-if=\"!$ctrl.periodShortcut\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.label\" label-cols=\"col-sm-6\" type=\"radio\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n                <salaxy-input-enum ng-model=\"$ctrl.periodShortcut\" name=\"periodShortcut\" ng-if=\"$ctrl.periodShortcut\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.label\" label-cols=\"col-sm-6\" type=\"select\" options=\"$ctrl.periodShortcuts\"></salaxy-input-enum>\r\n                <salaxy-date-range ng-model=\"$ctrl.dateRange\" class=\"condensed\" name=\"dateRange\" ng-if=\"$ctrl.periodShortcut == 'other'\" on-change=\"$ctrl.dateRangeChange()\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.label\" label-days-count=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.labelDaysCount\"\r\n                  label-cols=\"col-sm-6\" read-only=\"$ctrl.isReadOnly\"></salaxy-date-range>\r\n                <div ng-if=\"$ctrl.periodShortcut && $ctrl.periodShortcut != 'other'\">\r\n                  <salaxy-form-group name=\"periodStartDate\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.labelStartDate\" label-cols=\"col-sm-6\">\r\n                    <input type=\"text\" class=\"form-control\" autocomplete=\"off\" id=\"periodStartDate\" name=\"periodStartDate\" placeholder=\"{{'SALAXY.UI_Terms.dateFormats.dm' | sxyTranslate}}\" ng-model=\"$ctrl.periodStartDate\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\"\r\n                    />\r\n                    <div ng-if=\"$ctrl.periodStartDateError\" class=\"salaxy-read-only-value text-danger\">{{ $ctrl.periodStartDateError | sxyTranslate }}</div>\r\n                  </salaxy-form-group>\r\n                  <salaxy-form-group name=\"formattedRange\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.labelStartAndEndDate\" label-cols=\"col-sm-6\" class=\"salaxy-read-only\">\r\n                    <div class=\"salaxy-read-only-value\">{{ $ctrl.dateRange | sxyDateRange }}</div>\r\n                  </salaxy-form-group>\r\n                  <salaxy-input-number name=\"labelDaysCount\" ng-model=\"$ctrl.dateRange.daysCount\" ng-change=\"$ctrl.dateRangeChange()\" label=\"SALAXY.NG1.CalcWorktimeComponent.worktime.periodShortcut.labelWorkDaysCount\" label-cols=\"col-sm-6\">\r\n                  </salaxy-input-number>\r\n                </div>\r\n              </div>\r\n            </div>\r\n            <uib-accordion close-others=\"true\" class=\"salaxy-accordion\" ng-if=\"!$ctrl.isUsecaseSelected\">\r\n              <div uib-accordion-group class=\"\" is-open=\"status.open\" ng-repeat=\"group in $ctrl.tree\">\r\n                <uib-accordion-heading>\r\n                  {{group.label}} <i class=\"pull-right fa\" ng-class=\"{'fa-chevron-up': status.open, 'fa-chevron-down': !status.open}\"></i>\r\n                  <br><small> {{group.descr}}</small>\r\n                </uib-accordion-heading>\r\n                <div id=\"child-list\">\r\n                  <div ng-repeat=\"child in group.children\" ng-click=\"$ctrl.selectUsecase(child)\" class=\"clickable usecase-selection\" class>\r\n                    <div class=\"icon-wrapper salaxy-household-usecase-avatar\">\r\n                      <div class=\"main-icon-wrapper\">\r\n                        <img ng-src=\"{{child.icon}}\">\r\n                      </div>\r\n                      <div ng-if=\"child.badge\" class=\"badge-image-wrapper\">\r\n                        <img ng-src=\"{{child.badge}}\">\r\n                      </div>\r\n                    </div>\r\n                    <strong class=\"usecase-title\">{{child.label}}</strong>\r\n                    <small>{{child.descr |sxyTranslate}}</small>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n            </uib-accordion>\r\n          </div>\r\n          <div class=\"col-md-7 col-xs-12 panel-detail usecase-details\" ng-if=\"$ctrl.isUsecaseSelected\">\r\n            <ng-include src=\"$ctrl.getTemplate()\"></ng-include>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <button ng-if=\"!$ctrl.isReadOnly && !$ctrl.isEmployment\" class=\"btn btn-warning btn-lg salaxy-calc-btn-recalculate\" type=\"submit\" sxy-text=\"SALAXY.UI_Terms.updateCalculation\"></button>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/CalcSharing.html\",`<div class=\"salaxy-component salaxy-calc-sharing\">\r\n  <button class=\"btn btn-secondary btn-labeled-left btn-sm spacer-bottom\" ng-click=\"$ctrl.showDetails($ctrl.current)\"><i class=\"fa fa-chevron-left\"></i> <span sxy-text=\"SALAXY.NG1.CalcSharingComponent.backBtn\"></span></button>\r\n  <p ng-if=\"$ctrl.showLinkSharing\" class=\"calc-sharing-instructions\" sxy-html=\"SALAXY.NG1.CalcSharingComponent.intro.html\"></p>\r\n  <div class=\"spacer-bottom\" ng-if=\"$ctrl.showLinkSharing\">\r\n\r\n    <h3 sxy-text=\"SALAXY.NG1.CalcSharingComponent.sharing.title\"></h3>\r\n    <p class=\"spacer-bottom\" sxy-text=\"SALAXY.NG1.CalcSharingComponent.sharing.description\"></p>\r\n    <button ng-click=\"$ctrl.share('url')\" class=\"btn btn-primary btn-sm\">\r\n      <span ng-show=\"$ctrl.isSharing('url')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.NG1.CalcSharingComponent.sharing.createLinkBtn\"></span>\r\n     </button>\r\n\r\n  </div>\r\n\r\n  <h3 sxy-text=\"SALAXY.NG1.CalcSharingComponent.select.title\"></h3>\r\n  <p sxy-text=\"SALAXY.NG1.CalcSharingComponent.select.description\"></p>\r\n\r\n  <div class=\"table-responsive salaxy-odata-table\">\r\n    <table class=\"table table-striped\">\r\n      <thead>\r\n        <tr class=\"\">\r\n          <th colspan=\"2\">\r\n            <span sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></span>\r\n          </th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.employingRelations\">\r\n          <td class=\"td-avatar middle\">\r\n            <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td class=\"middle\">\r\n            <strong>{{row.ownerInfo.avatar.displayName}}</strong><br />\r\n\r\n          </td>\r\n          <td class=\"middle right\">\r\n            <button class=\"btn btn-sm btn-primary\" type=\"button\" ng-click=\"$ctrl.share('employer', row)\">\r\n               <span sxy-text=\"SALAXY.UI_Terms.select\"></span>  <span ng-show=\"$ctrl.isSharing('employer'+row.ownerId)\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/CalcSharingInfo.html\",`<div class=\"salaxy-component salaxy-calc-sharing-info\">\r\n  <div ng-if=\"$ctrl.current.workflow.status == 'paymentWorkerCopy'\">\r\n    <p class=\"text-center\">\r\n      <span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.paidDate\"></span> {{ $ctrl.current.workflow.paidAt | date }}\r\n    </p>\r\n    <p>\r\n      <button type=\"button\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" class=\"btn btn-primary btn-block\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n    </p>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.sharing.type == 'url'\">\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequested'\">\r\n      <p class=\"text-center\">\r\n        <strong sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.sharedViaLink\"></strong><br>\r\n        <strong class=\"small\" ng-if=\"$ctrl.current.sharing.lastSharedTo\"><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.sharedViaEmail\"></span> {{$ctrl.current.sharing.lastSharedTo}}</strong> <br>\r\n        <span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.shareToEmployer\"></span>\r\n      </p>\r\n      <form class=\"form-inline spacer-bottom\">\r\n        <div class=\"form-group copy-share-url\">\r\n          <div class=\"input-group \" ng-class=\"{'has-success': $ctrl.uriCopied}\">\r\n            <div class=\"input-group-addon clickable\" title=\"{{'SALAXY.NG1.CalcSharingInfoComponent.copyToClipBoard' | sxyTranslate}}\" type=\"button\" ng-click=\"$ctrl.copyUri()\">\r\n              <i class=\"fa fa-clipboard\"></i>\r\n\r\n              <span class=\"text-success text-center text-indicate\" ng-if=\"$ctrl.uriCopied\"><br><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.linkCopied\"></span></span>\r\n            </div>\r\n            <textarea class=\"form-control\" rows=\"1\" wrap=\"off\">{{$ctrl.current.sharing.uri}}</textarea>\r\n          </div>\r\n        </div>\r\n      </form>\r\n\r\n      <div ng-if=\"!$ctrl.isMobileSharingEnabled\" class=\"spacer-bottom text-center\">\r\n        <div ng-repeat=\"target in $ctrl.webSharingTargets\" style=\"display:inline\">\r\n          <a ng-if=\"target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-click=\"target.action()\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          </a>\r\n          <a ng-if=\"!target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-href=\"{{target.getUrl()}}\" target=\"_blank\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n         </a>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.isMobileSharingEnabled\" class=\"spacer-bottom text-center\">\r\n        <div ng-repeat=\"target in $ctrl.mobileSharingTargets\" style=\"display:inline\">\r\n          <a ng-if=\"target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-click=\"target.action()\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          {{target.title}}\r\n          </a>\r\n          <a ng-if=\"!target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-href=\"{{target.getUrl()}}\" target=\"_blank\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          {{target.title}}\r\n         </a>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-center spacer-bottom\">\r\n        <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.share('undefined')\"><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.deleteLinkBtn\"></span><span ng-show=\"$ctrl.isSharing('undefined')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></button>\r\n        <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequestAccepted'\">\r\n      <p class=\"text-center\">\r\n        <strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestAccepted\"></strong>\r\n      </p>\r\n      <div ng-if=\"$ctrl.employer\" class=\"spacer-bottom\">\r\n        <salaxy-avatar style=\"font-size:45px;\" avatar=\"$ctrl.employer.ownerInfo.avatar\"></salaxy-avatar>\r\n        <div>\r\n          <strong>&nbsp;{{$ctrl.employer.ownerInfo.avatar.displayName}}</strong>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-center spacer-bottom\">\r\n\r\n        <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequestDeclined'\">\r\n      <p class=\"text-center\">\r\n        <strong class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestDeclined\"></strong>\r\n      </p>\r\n      <form ng-if=\"!$ctrl.isMobileSharingEnabled\" class=\"form-inline spacer-bottom\">\r\n        <div class=\"form-group copy-share-url\">\r\n          <div class=\"input-group \" ng-class=\"{'has-success': $ctrl.uriCopied}\">\r\n            <div class=\"input-group-addon clickable\" title=\"{{'SALAXY.NG1.CalcSharingInfoComponent.copyToClipBoard' | sxyTranslate}}\" type=\"button\" ng-click=\"$ctrl.copyUri()\">\r\n              <i class=\"fa fa-clipboard\"></i>\r\n\r\n              <span class=\"text-success text-center text-indicate\" ng-if=\"$ctrl.uriCopied\"><br><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.linkCopied\"></span></span>\r\n            </div>\r\n            <textarea class=\"form-control\" rows=\"1\" wrap=\"off\">{{$ctrl.current.sharing.uri}}</textarea>\r\n          </div>\r\n        </div>\r\n      </form>\r\n\r\n      <div ng-if=\"!$ctrl.isMobileSharingEnabled\" class=\"spacer-bottom text-center\">\r\n        <div ng-repeat=\"target in $ctrl.webSharingTargets\" style=\"display:inline\">\r\n          <a ng-if=\"target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-click=\"target.action()\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          </a>\r\n          <a ng-if=\"!target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-href=\"{{target.getUrl()}}\" target=\"_blank\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n         </a>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.isMobileSharingEnabled\" class=\"spacer-bottom text-center\">\r\n        <div ng-repeat=\"target in $ctrl.mobileSharingTargets\" style=\"display:inline\">\r\n          <a ng-if=\"target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-click=\"target.action()\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          {{target.title}}\r\n          </a>\r\n          <a ng-if=\"!target.action\" class=\"btn btn-transparent btn-share-calc\" title=\"{{target.title}}\" ng-href=\"{{target.getUrl()}}\" target=\"_blank\"><i style=\"font-size: xx-large\" class=\"fa\" ng-class=\"target.icon\"></i>\r\n          {{target.title}} \r\n         </a>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-center spacer-bottom\">\r\n        <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.share('undefined')\"><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.deleteLinkBtn\"></span><span ng-show=\"$ctrl.isSharing('undefined')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></button>\r\n        <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n  <div ng-if=\"$ctrl.current.sharing.type == 'employer'\" class=\"text-center\">\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequested'\">\r\n      <p class=\"text-center\"><strong class=\"text-warning\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequested\"></strong></p>\r\n      <div ng-if=\"$ctrl.employer\" class=\"spacer-bottom\">\r\n        <salaxy-avatar style=\"font-size:45px;\" avatar=\"$ctrl.employer.ownerInfo.avatar\"></salaxy-avatar>\r\n        <div>\r\n          <strong>&nbsp;{{$ctrl.employer.ownerInfo.avatar.displayName}}</strong>\r\n        </div>\r\n      </div>\r\n      <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.share('undefined')\"><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.cancelDeliveryBtn\"></span> <span ng-show=\"$ctrl.isSharing('undefined')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></button>\r\n      <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequestAccepted'\">\r\n      <p class=\"text-center\"><strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestAccepted\"></strong></p>\r\n      <div ng-if=\"$ctrl.employer\" class=\"spacer-bottom\">\r\n        <salaxy-avatar style=\"font-size:45px;\" avatar=\"$ctrl.employer.ownerInfo.avatar\"></salaxy-avatar>\r\n        <div>\r\n          <strong>&nbsp;{{$ctrl.employer.ownerInfo.avatar.displayName}}</strong>\r\n        </div>\r\n      </div>\r\n\r\n      <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.workflow.status == 'workerRequestDeclined'\">\r\n      <p class=\"text-center\"><strong class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestDeclined\"></strong></p>\r\n      <div ng-if=\"$ctrl.employer\" class=\"spacer-bottom\">\r\n        <salaxy-avatar style=\"font-size:45px;\" avatar=\"$ctrl.employer.ownerInfo.avatar\"></salaxy-avatar>\r\n        <div>\r\n          <strong>&nbsp;{{$ctrl.employer.ownerInfo.avatar.displayName}}</strong>\r\n        </div>\r\n      </div>\r\n      <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.share('undefined')\"><span sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.cancelDeliveryBtn\"></span> <span ng-show=\"$ctrl.isSharing('undefined')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></button>\r\n      <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current.sharing.type == 'undefined'\">\r\n    <p ng-if=\"$ctrl.current.workflow.status == 'workerRequested'\" class=\"text-center\"><strong sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestedAlt\"></strong></p>\r\n    <p ng-if=\"$ctrl.current.workflow.status == 'workerRequestAccepted'\" class=\"text-center\"><strong class=\"text-success\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestAccepted\"></strong></p>\r\n    <p ng-if=\"$ctrl.current.workflow.status == 'workerRequestDeclined'\" class=\"text-center\"><strong class=\"text-danger\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.statusText.workerRequestDeclined\"></strong></p>\r\n    <button ng-if=\"$ctrl.validation.isValid && ( !$ctrl.current.isReadOnly || $ctrl.current.workflow.status == 'workerRequestDeclined')\" class=\"btn btn-primary btn-block\" ng-click=\"$ctrl.showSharing()\" sxy-text=\"SALAXY.NG1.CalcSharingInfoComponent.sendToEmployerBtn\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/EmployerList.html\",`<div class=\"salaxy-component salaxy-employer-list\">\r\n  <div class=\"list-group avatar-list-group\">\r\n    <div ng-repeat=\"row in $ctrl.selectedItems\" class=\"list-group-item\">\r\n      <div class=\"list-group-item-content-wrapper\">\r\n        <salaxy-avatar avatar=\"row.ownerInfo.avatar\" class=\"pull-left icon-wrapper\"></salaxy-avatar>\r\n        <div class=\"list-group-item-text-wrapper\">\r\n          <h4 class=\"list-group-item-heading\">{{row.ownerInfo.avatar.displayName}}</h4>\r\n          <p class=\"list-group-item-text\">{{row.ownerInfo.email}}</p>\r\n        </div>\r\n      </div>\r\n\r\n      <button ng-click=\"$ctrl.setEmployerSelected(row, false);\" class=\"btn btn-sm btn-default\" sxy-text=\"SALAXY.UI_Terms.change\"></button>\r\n\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.selectedItems.length\">\r\n\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr class=\"\">\r\n            <th colspan=\"2\">\r\n              <span class=\"clickable\" sxy-text=\"SALAXY.NG1_Other.Roles.employer\"></span>\r\n            </th>\r\n            <th>\r\n              <span sxy-text=\"SALAXY.NG1.WorkerListComponent.employment\"></span><br />\r\n              <span class=\"small\"><span sxy-text=\"SALAXY.UI_Terms.updated\"></span></span>\r\n            </th>\r\n            <!--th sxy-text=\"Palkkoja maksettu\"></th-->\r\n            <th class=\"right\"> </th>\r\n          </tr>\r\n        </thead>\r\n\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.employingRelations\">\r\n            <td class=\"td-avatar middle\">\r\n              <salaxy-avatar avatar=\"row.ownerInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td class=\"td-name middle\">\r\n              <strong>{{row.ownerInfo.avatar.displayName}}</strong><br />\r\n              <span class=\"sm-description\">\r\n              {{row.ownerInfo.email}}\r\n            </span>\r\n            </td>\r\n            <td class=\"middle\">\r\n              {{ row.data | sxyDateRange }}<br /> <small>{{ row.updatedAt | date}}</small>\r\n            \r\n            </td>\r\n            <!--td class=\"middle\">\r\n            <span class=\"\">TODO: viimeisin palkka (pvm)</span><br>\r\n            <span class=\"\">TODO: tänä vuonna yht €</span>\r\n          </td-->\r\n            <td class=\"right middle\">\r\n              <button class=\"btn btn-sm btn-default\" sxy-text=\"SALAXY.UI_Terms.calculations\" ng-click=\"$ctrl.setEmployerSelected(row, true)\"></button>\r\n              <!-- TODO button class=\"btn btn-sm btn-default\" sxy-text=\"SALAXY.UI_Terms.newCalculation\"></button-->\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n\r\n  </div>\r\n\r\n\r\n\r\n  <salaxy-odata-table ng-if=\"$ctrl.selectedItems.length\" url=\"/v03/api/calculations/category/all\" crud-controller=\"CalculationCrudController as $crud\" options=\"{ $filter: 'otherId eq \\\\'' + $ctrl.employerId + '\\\\' and (status eq \\\\'paymentWorkerCopy\\\\' or status eq \\\\'workerRequested\\\\' or status eq \\\\'workerRequestAccepted\\\\' or status eq \\\\'workerRequestDeclined\\\\') ' }\"\r\n    template-url=\"salaxy-components/odata/lists/CalculationsEmployer.html\">\r\n  </salaxy-odata-table>\r\n\r\n</div>\r\n\r\n<div class=\"salaxy-component salaxy-employer-list hidden\">\r\n  <div ng-if=\"!$ctrl.employingRelations.length\" class=\"\">\r\n    <h2>Ei työnantajia</h2>\r\n  </div>\r\n  <div ng-if=\"$ctrl.employingRelations.length\" class=\"\">\r\n    <div class=\"list-group avatar-list-group\">\r\n      <div class=\"list-group-item list-group-header\">\r\n\r\n\r\n        <div class=\"list-group-item-content-wrapper one-third\">\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <p class=\"list-group-item-heading\">Työnantaja</p>\r\n          </div>\r\n        </div>\r\n        <div class=\"list-group-item-content-wrapper one-fifth\">\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <p class=\"list-group-item-heading\">Työsuhde alkanut<br>...päivitetty</p>\r\n\r\n          </div>\r\n        </div>\r\n        <div class=\"list-group-item-content-wrapper one-fifth\">\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <p class=\"list-group-item-heading\">Työsuhde alkanut<br> ...päivitetty\r\n            </p>\r\n\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n\r\n\r\n      <div ng-repeat=\"row in $ctrl.employingRelations\" class=\"list-group-item\">\r\n\r\n        <div class=\"list-group-item-content-wrapper one-third\">\r\n          <salaxy-avatar avatar=\"row.ownerInfo.avatar\" class=\"pull-left icon-wrapper\"></salaxy-avatar>\r\n          <div class=\"list-group-item-text-wrapper\">\r\n\r\n            <h4 class=\"list-group-item-heading\">{{row.ownerInfo.avatar.displayName}}</h4>\r\n            <p class=\"list-group-item-text\">{{row.ownerInfo.email}}</p>\r\n          </div>\r\n        </div>\r\n        <div class=\"list-group-item-content-wrapper one-fifth\">\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <h4 class=\"list-group-item-heading\">{{row.createdAt | date}}</h4>\r\n            <p class=\"list-group-item-text\">{{row.updatedAt | date}}</p>\r\n          </div>\r\n        </div>\r\n        <div class=\"list-group-item-content-wrapper one-fifth\">\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <h4 class=\"list-group-item-heading\">{{row.createdAt | date}}</h4>\r\n            <p class=\"list-group-item-text\">{{row.updatedAt | date}}</p>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <button ng-click=\"$ctrl.setEmployerSelected(row, true)\" class=\"btn btn-xs btn-default\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n    </div>\r\n  </div>\r\n</div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/EmployerReport.html\",`<div class=\"salaxy-component salaxy-employer-report\">\r\n  <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\" ng-if=\"!$ctrl.currentReport\"></salaxy-spinner>\r\n  <div class=\"pull-right col-xs-3\" style=\"width: 200px\">\r\n    <label>Valitse vuosi: </label>\r\n    <select ng-options=\"option.name for option in $ctrl.yearOptions track by option.value\" ng-model=\"$ctrl.selectedYear\" name=\"years\" id=\"years\"></select>\r\n  </div>\r\n  <div ng-if=\"$ctrl.currentReport.employerReports.length <= 0\">\r\n    <p>\r\n      Sinulla ei ole Palkkaus.fi-palvelussa vuonna {{ $ctrl.selectedYear.value }} maksettuja palkkoja.\r\n      Vetovalikosta voit vaihtaa raportointivuotta.\r\n    </p>\r\n    <hr />\r\n    <h2>Ei palkanmaksuja vuonna {{ $ctrl.selectedYear.value }}</h2>\r\n    <p>\r\n      Kun maksat palkkoja kauttamme, edellisten vuosien palkat ja niistä tehdyt raportit jäävät arkistoon tälle sivulle.\r\n      Muut raportit kohdassa voit esikatsella muutaman yleisen raportin\r\n      ja sivun alalaidasta löydät lisätietoja työntekijäkohtaisista raporteista.\r\n    </p>\r\n  </div>\r\n  <div ng-if=\"$ctrl.currentReport.employerReports.length > 0\">\r\n    <p>\r\n      Alla näet kaikki palkanmaksut, jotka olet tehnyt Palkkaus.fi-palvelun kautta vuonna {{ $ctrl.selectedYear.value }}.\r\n    </p>\r\n    <hr />\r\n    <h3>Raportit työntekijöittäin</h3>\r\n    <p>\r\n      Alla on listattu työntekijöittäin ja palkkalaskelmittain tärkeimmät tiedot ja raportit:\r\n      Työntekijän yhteenveto ja Verottajan vuosi-ilmoitus (7801)<span ng-if=\"$ctrl.selectedYear.value < 2021\"> sekä Kotitalousvähennyksen vuosi-ilmoitus (14B)</span>.\r\n      Lisätietoja raporteista löydät sivun alalaidasta.\r\n    </p>\r\n    <table class=\"table\" ng-controller=\"WorkerSummaryReportDisplayController as $displayCtrl\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">Työntekijä</th>\r\n          <th class=\"right\">\r\n            Bruttopalkka<br />\r\n            Verotettava\r\n          </th>\r\n          <th>Yhteenveto</th>\r\n          <th>Vero (7801)</th>\r\n          <th ng-if=\"$ctrl.selectedYear.value < 2021\">KT-väh. (14B)</th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat-start=\"report in $ctrl.currentReport.employerReports\">\r\n          <td>\r\n            <div style=\"font-size: 64px; line-height: 1\" ng-init=\"avatar = $ctrl.avatarFrom(report.worker.avatar.url)\">\r\n              <i ng-if=\"!avatar.url\" class=\"salaxy-avatar fa\" ng-class=\"avatar.baseIcon\" ng-style=\"{color: avatar.color }\"><strong>{{ avatar.initials }}</strong></i>\r\n              <i ng-if=\"avatar.url\" class=\"salaxy-avatar fa\"><img ng-src=\"{{avatar.url}}\"></img></i>\r\n            </div>\r\n          </td>\r\n          <td>\r\n            {{ report.worker.fullName}}<br />\r\n            <a ng-href=\"mailto:{{ $ctrl.workerEmailFrom(report) }}\">{{ $ctrl.workerEmailFrom(report) }}</a><br />\r\n            {{ report.worker.identity.socialSecurityNumberValid }}\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ report.grossSalary | currency : \"€\" : 2}}<br />\r\n            {{ report.totalTaxable | currency : \"€\" : 2}}\r\n          </td>\r\n          <td>\r\n            <a ng-click=\"$displayCtrl.display($ctrl.selectedYear.value + '-01-01', report.worker.identity.socialSecurityNumberValid , $ctrl.employerId )\"\r\n              >Yhteenveto&nbsp;&raquo;\r\n            </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"$ctrl.isSelectedYearBeforeIncomesRegistry\"\r\n              href=\"{{ $ctrl.apiServerAddress }}/ReportPdf/TaxYearly7801/{{ report.worker.identity.socialSecurityNumberValid }}?year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\"\r\n              target=\"_blank\">Tuloste&nbsp;&raquo;\r\n            </a>\r\n          </td>\r\n          <td ng-if=\"$ctrl.selectedYear.value < 2021\">\r\n            <a ng-if=\"report.totalTaxableDeductible > 0\"\r\n              ng-href=\"{{ $ctrl.apiServerAddress }}/ReportPdf/TaxHouseholdDeduction14B/{{ report.worker.identity.socialSecurityNumberValid }}?year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\"\r\n              target=\"_blank\" class=\"\">Tuloste&nbsp;&raquo;\r\n            </a>\r\n            <p ng-if=\"report.totalTaxableDeductible <= 0\">Ei merkitty koti&shy;talous&shy;vähen&shy;nykseen.</p>\r\n          </td>\r\n        </tr>\r\n        <tr ng-repeat-end=\"\" ng-repeat=\"calculation in report.underlyingCalculations\">\r\n          <td></td>\r\n          <td>\r\n            <b ng-if=\"!$ctrl.isSelectedYearBeforeIncomesRegistry\">\r\n              {{ calculation.salaryDate | date : \"dd.MM\" }}\r\n            </b>\r\n            <b ng-if=\"$ctrl.isSelectedYearBeforeIncomesRegistry\">\r\n              {{ calculation.paidAt | date : \"dd.MM\" }}\r\n            </b>\r\n          </td>\r\n          <td class=\"right\">\r\n            {{ calculation.totals.totalGrossSalary | currency : \"€\" : 2 }}<br />\r\n            {{ calculation.totals.totalTaxable | currency : \"€\" : 2 }}\r\n          </td>\r\n          <td ng-controller=\"CalcReportsDisplayController as $displayCtrl\">\r\n            <button  ng-click=\"$displayCtrl.displayForId('salarySlip', calculation.id)\"\r\n                    class=\"btn btn-primary btn-xs\">Tuloste&nbsp;&raquo;</button><br />\r\n          <td>\r\n            {{ calculation.workerCalc.tax > 0 ? \"Ennakonpidätys: \" + (calculation.workerCalc.tax | currency : \"€\" : 2) : \"Ei ennakonpidätystä\" }}\r\n          </td>\r\n          <td ng-if=\"$ctrl.selectedYear.value < 2021\">\r\n            {{ calculation.salary.isDeductible ? \"Kotitalousvähennys: \" + (calculation.employerCalc.householdDeduction | currency : \"€\" : 2) : \"Ei lasketa kotitalousväh.\" }}\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <hr />\r\n  <br />\r\n  <h3>Muut raportit</h3>\r\n  <p>Raportit, jotka eivät ole työntekijäkohtaisia.</p>\r\n  <div class=\"row\">\r\n    <div ng-if=\"$ctrl.isSelectedYearBeforeIncomesRegistry\" class=\"col-sm-4\">\r\n      <h4>TVR Palkka&shy;summa&shy;ilmoitus</h4>\r\n      <p>\r\n        Työttömyys&shy;vakuutus&shy;rahastolle (TVR) ilmoitetaan\r\n        yhteystiedot, palkkasumma sekä tilinumero mahdollisia takaisinmaksuja varten.\r\n      </p>\r\n      <p>\r\n        <strong>\r\n          Ilmoitettava palkkasumma on: {{ $ctrl.tvrSalaryAmount | currency : \"\" : 2 }} euroa.\r\n        </strong>\r\n      </p>\r\n      <p>\r\n        Avaa <a ng-href=\"{{ $ctrl.apiServerAddress }}/ReportPdf/Unemployment?year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\" target=\"_blank\">PDF-dokumentti\r\n          tästä linkistä</a>.\r\n      </p>\r\n    </div>\r\n    <div class=\"col-sm-4\">\r\n      <h4>Vakuutusyhtiön vuosi-ilmoitus</h4>\r\n      <p>\r\n        Vakuutus- tai työeläkeyhtiö saattaa vaatia sinulta selvitystä maksetuista palkoista vuoden ajalta.\r\n        Tämä raportti on tarkoitettu sitä varten.\r\n      </p>\r\n      <p>\r\n        <strong>\r\n          Jos olet ostanut tapaturmavakuutuksen Palkkaus.fi-palvelusta ja\r\n          olet antanut Palkkaus.fi-palvelun hoitaa TyEL-vakuutuksen,\r\n          ei tämä raportti ole tarpeellinen.\r\n        </strong>\r\n      </p>\r\n      <p>\r\n        Avaa <a ng-href=\"{{ $ctrl.apiServerAddress }}/ReportHtml/Insurance?year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\" target=\"_blank\">Raportti tästä</a>.\r\n      </p>\r\n    </div>\r\n    <div class=\"col-sm-4\">\r\n      <h4>Raportti kotitalous&shy;vähennyksistä</h4>\r\n      <p>\r\n        Yksityiskohtainen raportti näyttää yhdessä näkymässä kaikki\r\n        kotitalousvähennysta varten Palkkauksen verottajalle ilmoittamat tiedot.\r\n      </p>\r\n      <p>\r\n        Lisäksi tietoa miten ilmoitat Palkkaus.fi-palvelun ulkopuolella maksetut kotitalousvähennyksen alaiset kustannukset.\r\n      </p>\r\n      <p>\r\n        Avaa <a  ng-href=\"{{$ctrl.selectedYear.value < 2021 ? '#/archive/household-deduction-report' : '#/household-years/active'}}\">Raportti tästä</a>.\r\n      </p>\r\n    </div>\r\n  </div>\r\n  <hr />\r\n  <br />\r\n  <h3 id=\"more-info\">Lisätietoja raporteista</h3>\r\n  <p>\r\n    Lisätietoja yllä listatutuista työntekijäkohtaisista raporteista.\r\n  </p>\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-4\">\r\n      <h4>Työntekijän yhteenveto</h4>\r\n      <p>\r\n        Lain mukaan työnantajan pitää toimittaa työntekijälle yhteenveto kaikista palkoista, joita on maksanut vuoden aikana.\r\n      </p>\r\n      <p>\r\n        <strong>Jos Palkkaus.fi-palvelussa on työntekijän sähköpostiosoite, lähetämme tähän linkin suoraan työntekijälle.</strong>\r\n        Jos sähköpostiosoite ei ole oikein, voit tulostaa tämän yhteenvedon ja lähettää työntekijälle.\r\n      </p>\r\n      <ul ng-controller=\"WorkerSummaryReportDisplayController as $displayCtrl\">\r\n        <li ng-repeat=\"employerReport in $ctrl.currentReport.employerReports\">\r\n          <a ng-click=\"$displayCtrl.display($ctrl.selectedYear.value + '-01-01', employerReport.worker.identity.socialSecurityNumberValid , $ctrl.employerId )\">{{\r\n            employerReport.worker.fullName }}</a>\r\n          {{ $ctrl.workerEmailFrom(employerReport) || 'Ei sähköpostia' }}\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div ng-if=\"$ctrl.isSelectedYearBeforeIncomesRegistry\" class=\"col-sm-4\">\r\n      <h4>Vuosi-ilmoitus verottajalle (7801)</h4>\r\n      <p>\r\n        <i>Verottajan lomake 7801: Työnantajan tai suorituksen maksajan vuosi-ilmoitus</i>\r\n        Näitä lomakkeita tuotamme jokaista työntekijääsi kohden yhden.\r\n      </p>\r\n      <p>\r\n        Jokaisen vuoden tammikuussa luomme edellisen vuoden ilmoitukset ja voit vielä tarkistaa lomakkeen tiedot.\r\n        Tämän jälkeen <strong>lähetämme ilmoituksen verottajalle</strong> ja alkuperäinen ilmoitus jää Palkkaus.fi-arkistoon.\r\n      </p>\r\n      <ul>\r\n        <li ng-repeat=\"employerReport in $ctrl.currentReport.employerReports\">\r\n          <a href=\"{{ $ctrl.apiServerAddress }}/ReportPdf/TaxYearly7801/{{ employerReport.worker.identity.socialSecurityNumberValid }}?year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\"\r\n            target=\"_blank\">{{\r\n            employerReport.worker.fullName }}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"col-sm-4\" >\r\n      <h4>Kotitalous&shy;vähennyksen vuosi-ilmoitus (14B)</h4>\r\n      <p>\r\n        <i>Verottajan lomake 14B / 3026: Kotitalousvähennys työntekijälle maksetusta palkasta</i>\r\n        Yhteen lomakesivuun mahtuu tiedot kahdesta työntekijästä\r\n      </p>\r\n      <p>\r\n        <strong>\r\n          Lähetämme tiedot verottajalle tammikuun loppuun mennessä,\r\n        </strong> kun olet käynyt tarkistamassa tietosi\r\n      </p>\r\n      <p>\r\n        Huomaathan, että verottaja käsittelee kaikki lomakkeet 14B yhdellä kertaa veroilmoitusten kanssa kesäkuussa,\r\n        joten nämä tiedot eivät näy vielä esitäytetyssä veroilmoituksessa.\r\n      </p>\r\n\r\n      <ul ng-if=\"$ctrl.selectedYear.value < 2021\">\r\n        <li ng-repeat=\"employerGroup in $ctrl.employers14BGroups\">\r\n          <a href=\"{{ $ctrl.apiServerAddress }}/ReportPdf/TaxHouseholdDeduction14B/{{ employerGroup.id1 }}?id2={{ employerGroup.id2 }}&year={{ $ctrl.selectedYear.value }}&access_token={{ $ctrl.token }}\"\r\n            target=\"_blank\">\r\n            {{ employerGroup.names }}\r\n          </a>\r\n        </li>\r\n      </ul>\r\n      <span ng-if=\"$ctrl.selectedYear.value >= 2021\">Avaa <a href=\"#/household-years/active\">Raportti tästä</a>.</span>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/EmployerSelect.html\",`<div class=\"salaxy-component salaxy-employer-select\">\r\n  <div ng-if=\"!$ctrl.employingRelations.length\" class=\"\">\r\n    <h2>Ei työnantajia</h2>\r\n  </div>\r\n\r\n\r\n  <div class=\"list-group avatar-list-group\">\r\n    <div ng-repeat=\"row in $ctrl.selectedItems\" class=\"list-group-item\">\r\n      <div class=\"list-group-item-content-wrapper\">\r\n        <salaxy-avatar avatar=\"row.ownerInfo.avatar\" class=\"pull-left icon-wrapper\"></salaxy-avatar>\r\n        <div class=\"list-group-item-text-wrapper\">\r\n          <h4 class=\"list-group-item-heading\">{{row.ownerInfo.avatar.displayName}}</h4>\r\n          <p class=\"list-group-item-text\">{{row.owner | sxyIban}}</p>\r\n        </div>\r\n      </div>\r\n\r\n      <button ng-if=\"$ctrl.employingRelations.length > 1\" ng-click=\"$ctrl.setEmployerSelected(row, false);\" class=\"btn btn-xs btn-default\" sxy-text=\"SALAXY.UI_Terms.change\"></button>\r\n\r\n    </div>\r\n  </div>\r\n\r\n  <div ng-if=\"$ctrl.employingRelations.length > 1 && !$ctrl.selectedItems.length\">\r\n    <div class=\"list-group avatar-list-group\">\r\n      <div ng-repeat=\"row in $ctrl.employingRelations\" class=\"list-group-item\">\r\n        <div class=\"list-group-item-content-wrapper\">\r\n          <salaxy-avatar avatar=\"row.ownerInfo.avatar\" class=\"pull-left icon-wrapper\"></salaxy-avatar>\r\n          <div class=\"list-group-item-text-wrapper\">\r\n            <h4 class=\"list-group-item-heading\">{{row.ownerInfo.avatar.displayName}}</h4>\r\n            <p class=\"list-group-item-text\">{{row.owner | sxyIban}}</p>\r\n          </div>\r\n        </div>\r\n        <button ng-click=\"$ctrl.setEmployerSelected(row, true)\" class=\"btn btn-xs btn-default\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/HouseholdDeductionReport.html\",`<div style=\"max-width: calc(100% - 45px); margin-left: 15px\">\r\n  <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\" ng-if=\"!$ctrl.currentReport\"></salaxy-spinner>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12 spacer-bottom\">\r\n      <label>Valitse vuosi: </label>\r\n      <select ng-options=\"option.name for option in $ctrl.yearOptions track by option.value\" ng-model=\"$ctrl.selectedYear\" name=\"years\" id=\"years\"></select>\r\n    </div>\r\n  </div>\r\n  <h2>Palkkaus.fi-palvelussa maksetut palkat</h2>\r\n  <h3 ng-repeat-start=\"yearlyReport in $ctrl.currentReport\" ng-if=\"$index == 0\">Nämä työt voit vähentää omassa verotuksessasi.</h3>\r\n  <p ng-if=\"$index == 0\">Kotitalousvähennys on enintään {{ $ctrl.deductionMaxAmount | currency : \"\" : 0 }} euroa vuodessa. Vähennyksen omavastuu on 100 euroa.</p>\r\n  <h3 ng-if=\"$index == 1\">Nämä työt voit vähentää mahdollisen puolisosi verotuksessa.</h3>\r\n  <p ng-if=\"$index == 1\">Kotitalousvähennys on henkilökohtainen, joten puolisot voivat saada yhteensä {{ (2 * $ctrl.deductionMaxAmount) | currency : \"\" : 0 }} euron vähennyksen. Jos {{ $ctrl.deductionMaxAmount | currency : \"\" : 0 }} euron raja ei ylity, vähennys kannattaa hakea\r\n    vain toiselle puolisolle. Silloin omavastuu vähennetään vain yhden kerran.</p>\r\n  <h3 ng-if=\"$index == 2\">Näitä töitä et voi vähentää verotuksessa</h3>\r\n  <p ng-if=\"$index == 2\">Kotitalousvähennyksen maksimimäärä on {{ $ctrl.deductionMaxAmount | currency : \"\" : 0 }} yhdessä puolison kanssa.</p>\r\n  <b>Työnantaja {{ yearlyReport.employer.fullName }}</b>\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th>Työntekijä</th>\r\n        <th>Työ: maksupäivä ja kuvaus</th>\r\n        <th class=\"right\" colspan=\"2\">Luvut 14B-lomakkeessa</th>\r\n        <th class=\"right\">KT-vähennys</th>\r\n      </tr>\r\n    </thead>\r\n    <tbody ng-repeat=\"employerReport in yearlyReport.employerReports\">\r\n      <tr ng-if-start=\"employerReport.isHouseholdDeductionWork\">\r\n        <td rowspan=\"4\">\r\n          {{ employerReport.worker.displayName }}<br /> {{ employerReport.worker.identity.socialSecurityNumberValid }}<br />\r\n        </td>\r\n        <td rowspan=\"4\">\r\n          {{ $ctrl.formatDateRange(employerReport.firstDeductiblePaymentDate, employerReport.lastDeductiblePaymentDate) }} {{ employerReport.deductionWorkDescription }}\r\n          <div class=\"form-group form-group-display\">\r\n            <label class=\"col-sm-10 control-label\">Kotitaloustyö</label>\r\n            <div class=\"col-sm-2\">\r\n              <input ng-checked=\"employerReport.hasHouseholdWork\" class=\"check-box\" disabled=\"disabled\" type=\"checkbox\">\r\n            </div>\r\n          </div>\r\n          <div class=\"form-group form-group-display\">\r\n            <label class=\"col-sm-10 control-label\">Hoiva- ja hoitotyö</label>\r\n            <div class=\"col-sm-2\">\r\n              <input ng-checked=\"employerReport.hasCareAndNurtureWork\" class=\"check-box\" disabled=\"disabled\" type=\"checkbox\">\r\n            </div>\r\n          </div>\r\n          <div class=\"form-group form-group-display\">\r\n            <label class=\"col-sm-10 control-label\">Asunnon kunnossapito- tai perusparannustyö</label>\r\n            <div class=\"col-sm-2\">\r\n              <input ng-checked=\"employerReport.hasConstructionWork\" class=\"check-box\" disabled=\"disabled\" type=\"checkbox\">\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>Palkka</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.totalTaxableDeductible) }}</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.totalTaxableDeduction) }}</td>\r\n      </tr>\r\n\r\n      <tr>\r\n        <td>Sivukulut (TyEL+Sava+TVR)</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.totalMandatorySideCosts) }}</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.totalMandatorySideCosts) }}</td>\r\n      </tr>\r\n      <tr>\r\n        <td>Vakuutus</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.deductionInsuranceEtc) }}</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.deductionInsuranceEtc) }}</td>\r\n      </tr>\r\n      <tr ng-if-end class=\"total\">\r\n        <td>Yhteensä</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.deduction14BFormTotal) }}</td>\r\n        <td class=\"right\">{{ $ctrl.employerDeductionsTotalAmount(employerReport) }}</td>\r\n      </tr>\r\n      <tr ng-if=\"!employerReport.isHouseholdDeductionWork\">\r\n        <td>\r\n          {{ employerReport.worker.displayName }}<br /> {{ employerReport.worker.identity.socialSecurityNumberValid }}<br />\r\n        </td>\r\n        <td>\r\n          {{ $ctrl.formatDateRange(employerReport.firstPaymentDate, employerReport.lastPaymentDate) }} Ei töitä merkittynä kotitalousvähennykseen.\r\n        </td>\r\n        <td>Palkka</td>\r\n        <td class=\"right\">{{ $ctrl.formatNumber(employerReport.totalTaxableDeductible) }}</td>\r\n        <td class=\"right\">-</td>\r\n      </tr>\r\n    </tbody>\r\n    <tfoot>\r\n      <tr>\r\n        <td colspan=\"2\">&nbsp;</td>\r\n      </tr>\r\n      <tr class=\"total\">\r\n        <th colspan=\"2\">Yhteensä</th>\r\n        <th colspan=\"2\" class=\"right\">{{ $ctrl.yearlyForm14BTotalAmount(yearlyReport) }}</th>\r\n        <th class=\"right\">{{ $ctrl.yearlyDeductionsTotalAmount(yearlyReport) }}</th>\r\n      </tr>\r\n      <tr>\r\n        <td>Omavastuu</td>\r\n        <td>Max. {{ $ctrl.deductionMaxAmount | currency : \"\" : 0 }} euroa / henkilö (pariskunta {{ (2 * $ctrl.deductionMaxAmount) | currency : \"\" : 0 }})</td>\r\n        <td colspan=\"3\" class=\"right\">-100,00</td>\r\n      </tr>\r\n      <tr class=\"total\">\r\n        <th colspan=\"2\">Kotitalousvähennys yhteensä</th>\r\n        <th colspan=\"3\" class=\"right\">{{ $ctrl.yearlyDeductionTotal(yearlyReport) }}</th>\r\n      </tr>\r\n    </tfoot>\r\n  </table>\r\n  <p ng-repeat-end=\"\">&nbsp;</p>\r\n\r\n  <p>\r\n    Verottaja käsittelee kaikki lomakkeet 14B yhdellä kertaa veroilmoitusten kanssa kesäkuussa, joten nämä tiedot\r\n    <strong>eivät näy vielä esitäytetyssä veroilmoituksessa</strong>. Käymme aktiivista keskustelua verottajan kanssa, jotta ensi vuodeksi saisimme tiedot jo tähän esitäytettyyn veroilmoitukseen. Jos tämä on sinusta tärkeä juttu, lähetä meille palautetta\r\n    osoitteeseen aspa@palkkaus.fi. Viemme mielellämme tätä tietoa eteenpäin verottajalle.\r\n  </p>\r\n  <p>\r\n    Tulet saamaan <strong>elo-syyskuussa Verottajalta korjatun verotuspäätöksen</strong>, jossa kotitalousvähennys on huomioitu kokonaisuudessaan. Jos vielä silloin huomaat joitain puutteita, voit tehdä muutoksen lokakuun aikana. Lopullisesti verotus\r\n    vahvistetaan lokakuun viimeinen päivä.\r\n  </p>\r\n  <hr />\r\n  <h2 id=\"info14B\">Palkkaus.fi-palvelun ulkopuolella maksetut palkat</h2>\r\n  <p>\r\n    Jos olet teettänyt työtä, jonka palkan olet maksanut Palkkaus.fi-palvelun ulkopuolella, muistathan ilmoittaa siitä erikseen verottajalle.\r\n  </p>\r\n  <p>\r\n    Kotitalousvähennyksen alaisen työn voi ilmoittaa kahdella tavalla:\r\n  </p>\r\n  <ol>\r\n    <li>\r\n      Tulosta lomake\r\n      <a href=\"https://www.vero.fi/fi-FI/Syventavat_veroohjeet/Lomakkeet/Henkiloasiakkaiden_lomakkeet/14B_Kotitalousvahennys_tyontekijalle_mak(12921)\" target=\"_blank\">\r\n        14B tästä linkistä\r\n      </a> ja lähetä se verottajalle.\r\n    </li>\r\n    <li>Sähköisellä veroilmoituksella <a href=\"https://www.vero.fi/veroilmoitus\" target=\"_blank\">https://www.vero.fi/veroilmoitus</a></li>\r\n  </ol>\r\n  <hr />\r\n  <h2 id=\"info14A\">Yrityksen laskuttama työ kotitalousvähennykseen</h2>\r\n  <p>\r\n    Jos olet teettänyt yrityksellä työtä, joka kelpaa kotitalousvähennykseen, muistathan ilmoittaa myös sen verottajalle.\r\n  </p>\r\n  <p>\r\n    Laskulla teetetyn työn voi ilmoittaa kahdella tavalla:\r\n  </p>\r\n  <ol>\r\n    <li>\r\n      Tulosta lomake\r\n      <a href=\"http://www.vero.fi/fi-FI/Syventavat_veroohjeet/Lomakkeet/Henkiloasiakkaiden_lomakkeet/14A_Kotitalousvahennys_yritykselle_makse(12918)\" target=\"_blank\">\r\n        14A tästä linkistä\r\n      </a> ja lähetä se verottajalle.\r\n    </li>\r\n    <li>Sähköisellä veroilmoituksella <a href=\"https://www.vero.fi/veroilmoitus\" target=\"_blank\">https://www.vero.fi/veroilmoitus</a></li>\r\n  </ol>\r\n  <p>\r\n    Olemme suunnitelleet tähän myös työkalua Palkkaus.fi-sivustolle. Työkalulla voisi kirjata laskut jo etukäteen ja tallentaa kuitit arkistoon. Palkkaus.fi ilmoittaisi tiedot verottajalle vuoden lopussa. Jos tämä on sinusta tärkeä juttu, lähetä meille palautetta\r\n    osoitteeseen aspa@palkkaus.fi.\r\n  </p>\r\n  <hr />\r\n  <h2 id=\"info-kuuluuko\">Mistä tiedän kuuluuko työ kotitalousvähennykseen?</h2>\r\n  <p>Perusidea on, että työn pitää olla jotain seuraavista:</p>\r\n  <ul>\r\n    <li>kotitaloustyö</li>\r\n    <li>hoiva- tai hoitotyö</li>\r\n    <li>asunnon kunnossapito- tai perusparannustyö</li>\r\n  </ul>\r\n  <p>\r\n    Lisäksi työ pitää tehdä omassa käytössä olevassa asunnossa tai vapaa-ajan asunnnossa. (Erikoistapauksena myös joidenkin lähisukulaisten käytössä olevat asunnot)\r\n  </p>\r\n  <p>\r\n    Jos olet epävarma, niin <a href=\"http://www.vero.fi/fi-FI/Henkiloasiakkaat/Kotitalousvahennys\" target=\"_blank\">tällä verottajan sivulla on kuvattu</a> tarkemmin kotitalousvähennystä. Huomaa alalaidan linkit eri työtyyppeihin.\r\n    <a href=\"http://www.vero.fi/fi-FI/Henkiloasiakkaat/Kotitalousvahennys/Taulukko_kysytyimmista_kotitalousvahenny(9231)\" target=\"_blank\">Tällä toisella sivulla on pitkä lista</a> eri töistä.\r\n  </p>\r\n\r\n  <p>Jos et vieläkään ole varma, voit kysyä mielipidettä Suomen Palkanlaskenta Oy:n asiantuntijoilta (yhteystiedot sivun alalaidassa).</p>\r\n\r\n  <p>Me autamme mielellämme!</p>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/HouseholdYearDetails.html\",`<div class=\"salaxy-component salaxy-household-year-details\">\r\n\r\n  <div class=\"btn-toolbar pull-right\" role=\"toolbar\" salaxy-if-role=\"pro\">\r\n    <salaxy-workflow-buttons api-ctrl=\"$ctrl\" disabled=\"!$ctrl.current || $ctrl.isNew() || $ctrl.current.isReadOnly\"></salaxy-workflow-buttons>\r\n  </div>\r\n\r\n  <div class=\"table-responsive\">\r\n    <p class=\"lead\">\r\n      Palvelu tekee puolestasi kotitalousvähennysilmoitukset maksetuista palkoista, kun laskelmalla on kotitalousvähennysmerkintä. Tarkista valinnat ja täydennä tarvittavat tiedot.\r\n    </p>\r\n    <div ng-if=\"$ctrl.current && $ctrl.isOpen\">\r\n      <p>\r\n        Alla on listattu vuoden {{ $ctrl.current.year || \"\" }} aikana palvelun kautta maksamasi palkat.\r\n      </p>\r\n      <ol>\r\n        <li>Tarkista palkat</li>\r\n        <li>Lisää tai poista kotitalousvähennys</li>\r\n        <li>Hyväksy tarkistamasi tiedot</li>\r\n      </ol>\r\n      <p>\r\n        <big>Kotitalousvähennys:</big> laita rasti ruutuun niiden palkkalaskelmien kohdalle, joista haluat kotitalousvähennyksen.\r\n      </p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current && !$ctrl.isOpen\">\r\n      <h3>Tiedot on jo lähetetty</h3>\r\n      <p>\r\n        Olet lähettänyt alla olevat tiedot {{$ctrl.current.userFeedbackTime | date : 'dd.MM.yyyy HH:mm'}}\r\n      </p>\r\n      <p>\r\n        Jos haluat avata tarkistuksen, ole yhteydessä asiakaspalveluun.\r\n      </p>\r\n    </div>\r\n    <hr />\r\n  </div>\r\n  <form name=\"theForm\" ng-if=\"$ctrl.current\">\r\n    <div class=\"table-responsive\" ng-controller=\"WorkerSummaryReportDisplayController as $displayCtrl\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"7\">\r\n              <h3>Työntekijöiden palkkalaskelmat</h3>\r\n            </th>\r\n          </tr>\r\n          <tr>\r\n            <th colspan=\"2\">Työntekijä</th>\r\n            <th class=\"right\">Bruttopalkka</th>\r\n            <th class=\"right\">Työnantaja&shy;kulut</th>\r\n            <th colspan=\"3\">Kotitalousvähennys <br>(laita rasti ruutuun)</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat-start=\"workerSummary in $ctrl.yearlyCalculations.workers\">\r\n            <td style=\"font-size: 64px; line-height: 1\">\r\n              <salaxy-avatar avatar=\"workerSummary.worker.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td>\r\n              {{ workerSummary.worker.avatar.displayName }}<br />\r\n              <a ng-href=\"mailto:{{ workerSummary.worker.paymentData.email }}\"> {{ workerSummary.worker.paymentData.email }}</a><br /> {{ workerSummary.worker.paymentData.socialSecurityNumberValid }}<br />\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ workerSummary.totalTaxable | number : 2 }}€\r\n            </td>\r\n            <td class=\"right\">\r\n              {{ workerSummary.mandatorySideCosts | number : 2 }}€\r\n            </td>\r\n            <td></td>\r\n            <td></td>\r\n            <td>\r\n              Työntekijän raportit (esikatselu):\r\n              <div>\r\n                <a ng-click=\"$displayCtrl.display($ctrl.current.year + '-01-01', workerSummary.worker.paymentData.socialSecurityNumberValid , null)\">Yhteenveto</a>\r\n              </div>\r\n            </td>\r\n          </tr>\r\n          <tr ng-repeat=\"calc in workerSummary.calculations\">\r\n            <td></td>\r\n            <td class=\"valign-middle\" ng-controller=\"CalcReportsDisplayController as $displayCtrl\">\r\n              <a ng-click=\"$displayCtrl.displayForId('salarySlip', calc.id)\">Laskelma {{ calc.workflow.salaryDate | date : 'dd.MM.' }} &raquo;</a>\r\n            </td>\r\n            <td class=\"right valign-middle\">\r\n              {{ calc.result.totals.totalTaxable | number : 2 }}€\r\n            </td>\r\n            <td class=\"right valign-middle\">\r\n              {{ calc.result.employerCalc.mandatorySideCosts | number : 2 }}€\r\n            </td>\r\n            <td class=\"valign-middle\" style=\"min-width: 40px;\">\r\n              <input type=\"checkbox\" class=\"form-control\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"calc.usecase.data.isHouseholdDeductible\" ng-change=\"$ctrl.calculationUpdated(calc)\" />\r\n            </td>\r\n            <td class=\"right valign-middle tax-deduction-item\" ng-class=\"{ 'text-disabled': !calc.usecase.data.isHouseholdDeductible }\">\r\n              {{ (calc.result.employerCalc.mandatorySideCosts + calc.result.totals.totalTaxable * $ctrl.getHouseholdDeduction(calc)) | number : 2 }}€\r\n            </td>\r\n            <td>\r\n              <span ng-if=\"!calc.usecase.data.isHouseholdDeductible\" class=\"text-danger\">Ei kotitalousvähennystä</span>\r\n              <div ng-if=\"calc.usecase.data.isHouseholdDeductible\">\r\n                <select class=\"form-control\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"calc.usecase.data.taxDeductionCategories\" ng-change=\"$ctrl.calculationUpdated(calc)\">\r\n                  <option hidden value=\"\">Valitse työn tyyppi...</option>\r\n                  <option value=\"none\">Ei valintaa</option>\r\n                  <option value=\"householdwork\">Kotitaloustyö</option>\r\n                  <option value=\"carework\">Hoiva- ja hoitotyö</option>\r\n                  <option value=\"homeImprovement\">Asunnon/loma-asunnon kunnossapito- tai korjaustyö</option>\r\n                  <option value=\"oilHeatingReplacementWork\">Öljylämmityksestä luopuminen</option>\r\n                </select>\r\n              </div>\r\n              <div ng-if=\"calc.usecase.data.isHouseholdDeductible\">\r\n                <select class=\"form-control\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"calc.usecase.data.taxDeductionProperty\" ng-change=\"$ctrl.calculationUpdated(calc)\">\r\n                  <option hidden value=\"\">Valitse työn sijainti</option>\r\n                  <option value=\"none\">Ei valintaa</option>\r\n                  <option value=\"ownProperty\">Omassa käytössä oleva asunto tai vapaa-ajan asunto</option>\r\n                  <option value=\"relativesProperty\">Vanhempien, isovanhempien yms. käytössä oleva asunto tai vapaa-ajan asunto.</option>\r\n                </select>\r\n              </div>\r\n            </td>\r\n          </tr>\r\n          <tr ng-repeat-end>\r\n            <td colspan=\"7\" style=\"border-top-color: rgb(145,210,20); line-height: 0; padding: 0;\"></td>\r\n          </tr>\r\n          <tr>\r\n            <th colspan=\"7\">\r\n              <h4>Tapaturmavakuutus kotitalousvähennykseen</h4>\r\n            </th>\r\n          </tr>\r\n          <tr>\r\n            <td></td>\r\n            <td colspan=\"5\">\r\n              <div>\r\n                Tapaturmavakuutus kelpaa kotitalousvähennykseen. Lisää maksamasi vakuutuksen summa tähän.\r\n              </div>\r\n            </td>\r\n            <td>\r\n              <salaxy-input-number name=\"insuranceAmount\" disabled=\"!$ctrl.isOpen\" label-type=\"plain\" unit=\"euro\" ng-model=\"$ctrl.current.insuranceAmount\" />\r\n            </td>\r\n          </tr>\r\n          <tr class=\"total\">\r\n            <th colspan=\"4\">\r\n              <h4>Kotitalousvähennys yhteensä</h4>\r\n            </th>\r\n            <th></th>\r\n            <th class=\"right valign-middle\">{{ $ctrl.getTaxDeductionTotal() + $ctrl.getTaxDeductionTotalExtended() + $ctrl.current.insuranceAmount  | number : 2 }}€</th>\r\n            <th class=\"valign-middle\">\r\n              <small style=\"font-weight: normal\">...josta vähennetään omavastuu.</small>\r\n            </th>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <p>\r\n        Huomioi: kotitalousvähennyksesi ei näy kevään esitäytetyssä veroilmoituksessasi, koska verottaja käsittelee ilmoitukset niin hitaasti. Lopulliseen verotukseesi ne tulevat kuitenkin oikein.\r\n      </p>\r\n    </div>\r\n    <div ng-show=\"$ctrl.canSplitWithSpouse()\">\r\n      <h3>Jaa kotitalousvähennys puolisosi kanssa</h3>\r\n      <p>\r\n        Kotitalousvähennystä voi saada {{ $ctrl.getGetSplittableMaxAmount() }}€ per henkilö ({{$ctrl.getHouseholdDeductionDeductible()}}€ omavastuun jälkeen).\r\n      </p>\r\n      <p>\r\n        Jos sinulla on puoliso, niin lisää tähän hänen tietonsa. Näin voimme lähettää {{ $ctrl.getGetSplittableMaxAmount() + $ctrl.getHouseholdDeductionDeductible()}}€ ylittävän osan kotitalousvähennyksestä hänen veroilmoitukseensa.\r\n      </p>\r\n      <div class=\"form-group\">\r\n        <label for=\"spouseName\" class=\"control-label\">Puolison nimi:</label>\r\n        <salaxy-input name=\"spouseName\" disabled=\"!$ctrl.isOpen\" placeholder=\"Koko nimi verottajalle\" label-type=\"plain\" ng-model=\"$ctrl.current.spouseName\"></salaxy-input>\r\n      </div>\r\n      <div class=\"form-group\">\r\n        <label for=\"spousePersonalId\" class=\"control-label\">Puolison henkilötunnus:</label>\r\n        <salaxy-input name=\"spousePersonalId\" disabled=\"!$ctrl.isOpen\" placeholder=\"ddmmyy-123X\" label-type=\"plain\" sxy-personal-id-fi ng-model=\"$ctrl.current.spousePersonalId\"></salaxy-input>\r\n      </div>\r\n    </div>\r\n    <div>\r\n      <h3>Tietojen lähettäminen</h3>\r\n      <p>Kun ole tarkistanut tiedot, valitse joku alla olevista vaihtoehdoista.</p>\r\n      <table>\r\n        <tr>\r\n          <td>\r\n            <label for=\"statusOk\">\r\n            <input id=\"statusOk\" type=\"radio\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"$ctrl.current.status\" value=\"ok\">\r\n            <span class=\"text-success\">Kyllä, tiedot tarkistettu / korjattu</span>\r\n            </label>\r\n          </td>\r\n          <td>\r\n            <p>Palvelu lähettää kotitalousvähennysilmoituksen 14B-lomakkeen verottajalle</p>\r\n          </td>\r\n        </tr>\r\n        <tr>\r\n          <td>\r\n            <label for=\"statusOkWithModifications\">\r\n            <input id=\"statusOkWithModifications\" type=\"radio\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"$ctrl.current.status\" value=\"okWithModifications\">\r\n            <span class=\"text-danger\">Tiedoissa on puutteita / virheitä<span>\r\n            </label>\r\n          </td>\r\n          <td>\r\n            <p>Jos tiedoissa on puutteita, joita et voinut korjata tällä sivulla itse, listaa puutteet tähän. Palvelu on sinuun tarvittaessa yhteydessä.</p>\r\n            <div ng-if=\"$ctrl.current.status == 'okWithModifications'\">\r\n              <textarea class=\"form-control\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"$ctrl.current.userFeedbackText\" rows=\"2\"></textarea>\r\n            </div>\r\n          </td>\r\n        </tr>\r\n        <tr>\r\n          <td>\r\n            <label for=\"statusWillHandleMyself\">\r\n            <input id=\"statusWillHandleMyself\" type=\"radio\" ng-disabled=\"!$ctrl.isOpen\" ng-model=\"$ctrl.current.status\" value=\"willHandleMyself\">\r\n            <span class=\"text-default\">Teen kotitalous&shy;vähennysilmoituksen itse</span>\r\n            </label>\r\n          </td>\r\n          <td>\r\n            <p>\r\n              Palvelu ei lähetä kotitalousvähennysilmoitusta (14B-lomake) verottajalle. Valitse tämä vaihtoehto, jos olet jo itse tehnyt kotitalousvähennysilmoitukset OmaVerossa tai et halua hakea kotitalousvähennystä.\r\n            </p>\r\n          </td>\r\n        </tr>\r\n      </table>\r\n    </div>\r\n\r\n    <div class=\"text-right\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-disabled=\"!$ctrl.current || !$ctrl.current.id\" ng-click=\"$ctrl.export()\">Lataa pdf(t)</button>\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current || !theForm.$valid || $ctrl.current.isReadOnly || !$ctrl.isOpen\" ng-click=\"$ctrl.save()\">Tallenna</button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/HouseholdYearList.html\",`<div class=\"salaxy-component household-year-list\">\r\n  <salaxy-odata-table ng-ref=\"$odata\" crud-controller=\"HouseholdYearCrudController as $crud\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/personal/WorkerReport.html\",`<div class=\"salaxy-component salaxy-worker-report\">\r\n  <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\" ng-if=\"!$ctrl.currentReport\"></salaxy-spinner>\r\n  <main>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 spacer-bottom\">\r\n        <label sxy-text=\"SALAXY.NG1.WorkerReportComponent.selectYearLabel\"></label>\r\n        <select ng-options=\"option.name for option in $ctrl.yearOptions track by option.value\" ng-model=\"$ctrl.selectedYear\" name=\"years\" id=\"years\"></select>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <h2 ng-if-start=\"$ctrl.currentReport.length <= 0\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.noPaidSalaries.title\" params=\"{year: $ctrl.selectedYear.value}\"></h2>\r\n        <p sxy-text=\"SALAXY.NG1.WorkerReportComponent.noPaidSalaries.description\" params=\"{year: $ctrl.selectedYear.value}\"></p>\r\n        <p ng-if-end sxy-text=\"SALAXY.NG1.WorkerReportComponent.contactCustomerService\" params=\"{year: $ctrl.selectedYear.value}\"></p>\r\n        <p ng-if-start=\"$ctrl.currentReport.length > 0\" class=\"\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.paidSalariesText\" params=\"{year: $ctrl.selectedYear.value}\">\r\n\r\n        </p>\r\n        <div ng-if-end class=\"table-responsive light-bg\">\r\n          <table class=\"table table-striped table-condensed\">\r\n            <thead>\r\n              <tr>\r\n                <th colspan=\"2\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.employer\"></th>\r\n                <th class=\"right\">\r\n                  <span sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.grossSalary\"></span><br /><span sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.totalTaxable\"></span>\r\n                </th>\r\n                <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.compensation\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.summary\"></th>\r\n                <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.taxPercent\"></th>\r\n                <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.householdDeduction\"></th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat-start=\"report in $ctrl.currentReport\" ng-controller=\"WorkerSummaryReportDisplayController as $displayCtrl\">\r\n                <td>\r\n                  <div style=\"font-size: 64px; line-height: 1\" ng-init=\"avatar = $ctrl.avatarFrom(report.employer.avatar.url)\">\r\n                    <i ng-if=\"!avatar.url\" class=\"salaxy-avatar fa\" ng-class=\"avatar.baseIcon\" ng-style=\"{color: avatar.color}\"><strong>{{ avatar.initials }}</strong></i>\r\n                    <i ng-if=\"avatar.url\" class=\"salaxy-avatar fa\"><img ng-src=\"{{ avatar.url }}\"></img></i>\r\n                  </div>\r\n                </td>\r\n                <td>\r\n                  {{ report.employer.fullName}}<br />\r\n                  <a ng-href=\"mailto:{{ $ctrl.workerEmailFrom(report) }}\">{{ $ctrl.employerEmailFrom(report) }}</a><br /> {{ report.employer.identity.socialSecurityNumberValid }}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ report.grossSalary | currency : \"€\" : 2}}<br /> {{ report.totalTaxable | currency : \"€\" : 2}}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ report.totalExpenses | currency : \"€\" : 2}}\r\n                </td>\r\n                <td>\r\n                  <a ng-click=\"$displayCtrl.display($ctrl.selectedYear.value, 'self', report.employer.id)\"\r\n                    class=\"btn btn-primary btn-xs\"\r\n                    sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.yearlyReport\" post=\"&nbsp;&raquo;\"\r\n                    ></a>\r\n                </td>\r\n                <td colspan=\"2\">\r\n                  <p class=\"small\">\r\n                    <strong sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.workerYearlySummaryTitle\"></strong><br />\r\n                    <a ng-click=\"$displayCtrl.display($ctrl.selectedYear.value, 'self', report.employer.id)\">\r\n                      <span sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.workerYearlySummaryLink\"></span></a> <span\r\n                      sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.workerYearlySummaryText\"></span>\r\n                  </p>\r\n                </td>\r\n              </tr>\r\n              <tr ng-repeat-end=\"\" ng-repeat=\"calculation in report.underlyingCalculations\">\r\n                <td></td>\r\n                <td>\r\n                  <b ng-if=\"!$ctrl.isSelectedYearBeforeIncomesRegistry\">\r\n                    {{ calculation.salaryDate | date : \"dd.MM\" }}\r\n                  </b>\r\n                  <b ng-if=\"$ctrl.isSelectedYearBeforeIncomesRegistry\">\r\n                    {{ calculation.paidAt | date : \"dd.MM\" }}\r\n                  </b>\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ calculation.totals.totalGrossSalary | currency : \"€\" : 2 }}<br /> {{ calculation.totals.totalTaxable | currency : \"€\" : 2 }}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ calculation.totals.totalExpenses | currency : \"€\" : 2 }}\r\n                </td>\r\n                <td ng-controller=\"CalcReportsDisplayController as $displayCtrl\">\r\n                  <a ng-href=\"#/calc/details/{{ calculation.id }}\" class=\"btn btn-secondary btn-xs\"><span\r\n                      sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.calculationBtn\"></span>&nbsp;&raquo;</a><br />\r\n                  <button ng-click=\"$displayCtrl.displayForId('salarySlip', calculation.id)\" class=\"btn btn-primary btn-xs\"><span\r\n                      sxy-text=\"SALAXY.NG1.WorkerReportComponent.table.printBtn\"></span>&nbsp;&raquo;</button><br />\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ calculation.workerCalc.tax > 0 ? (calculation.workerCalc.tax | currency : \"€\" : 2) : \"-\" }}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{ calculation.salary.isDeductible ? (calculation.employerCalc.householdDeduction | currency : \"€\" : 2) : \"-\" }}\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n          <br />\r\n        </div>\r\n\r\n\r\n      </div>\r\n    </div>\r\n  </main>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/records/Records.html\",`<div class=\"salaxy-component salaxy-records\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>{{\"SALAXY.NG1.WorkerDetailsComponent.records.recordType\" | sxyTranslate}}</th>\r\n        <th>{{\"SALAXY.NG1.WorkerDetailsComponent.records.title\" | sxyTranslate}}</th>\r\n        <th>{{\"SALAXY.NG1.WorkerDetailsComponent.records.text\" | sxyTranslate}}</th>\r\n        <th>{{\"SALAXY.NG1.WorkerDetailsComponent.records.startDate\" | sxyTranslate}}</th>\r\n        <th>{{\"SALAXY.NG1.WorkerDetailsComponent.records.badge\" | sxyTranslate}}</th> \r\n        <th class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.readOnly\" ng-click=\"$ctrl.showEditRecord({attachments: []})\" sxy-text=\"SALAXY.UI_Terms.add\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"item in $ctrl.records\">\r\n        <td>{{item.recordType}}</td>\r\n        <td>{{item.title}}</td>\r\n        <td>{{item.text}} <div ng-repeat=\"attachment in item.attachments\">\r\n          <i class=\"fa {{ $ctrl.getAttachmentIcon(attachment) }} text-primary pull-left\"></i><a target=\"_blank\" ng-href=\"{{$ctrl.getAttachmentDownloadUrl(attachment)}}\">{{attachment.fileName}}</a>\r\n        </div>\r\n        </td>\r\n        <td>{{ item.startDate | date }}</td>\r\n        <td>\r\n          <div ng-repeat=\"wfEvent in $ctrl.getEvents(item)\">\r\n            <span  ng-class=\"'badge bg-' + wfEvent.ui\">\r\n              {{wfEvent.message}}\r\n            </span>\r\n          </div>\r\n        </td>\r\n        <td class=\"text-right\" ng-if=\"!$ctrl.readOnly\">\r\n          <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.showEditRecord(item, $index)\">\r\n            <i class=\"fa fa-pencil\" title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\"></i>\r\n          </button>\r\n          <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.deleteRecord(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\"></i>\r\n          </button>\r\n        </td>\r\n        <td class=\"text-right\" ng-if=\"$ctrl.readOnly\">\r\n          <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.showEditRecord(item, $index)\">\r\n            <i class=\"fa fa-info\" title=\"{{'SALAXY.UI_Terms.show' | sxyTranslate}}\"></i>\r\n          </button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingHolidayPayDebtReportQuery.html\",`<div class=\"salaxy-component salaxy-accounting-report-query\">\r\n  <form name=\"queryForm\" class=\"form-horizontal\">\r\n    <div ng-show=\"false\" ng-init=\"$ctrl.queryForm = queryForm\"></div>\r\n    <fieldset>\r\n      <div class=\"col col-md-6\">\r\n        <salaxy-datepicker-popup name=\"refDate\" ng-model=\"$ctrl.refDate\" label=\"Velan päivämäärä\" required ng-change=\"$ctrl.query()\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </fieldset>\r\n  </form>\r\n  <div class=\"col col-md-12 text-right\">\r\n    <button class=\"btn btn-primary\" ng-disabled=\"!$ctrl.queryForm.$valid\" ng-click=\"$ctrl.queryData($reportTools.targetId)\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.queryRows\"></button>\r\n  </div>\r\n\r\n  <salaxy-accounting-report-tools ng-ref=\"$reportTools\" any-expanded=\"$reportRows.anyExpanded\" on-expand-change=\"$reportRows.expand(close)\" on-target-change=\"$ctrl.queryData(targetId)\" reader=\"$ctrl.dataReader\" view=\"$ctrl.view\"></salaxy-accounting-report-tools>\r\n  <salaxy-accounting-report-rows lang=\"$ctrl.lang\" ng-ref=\"$reportRows\" data=\"$ctrl.data\" view=\"$ctrl.view\"></salaxy-accounting-report-rows>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingReportList.html\",`<div class=\"salaxy-component salaxy-accounting-report-list\">\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode != 'panel'\" crud-controller=\"AccountingReportCrudController as $crud\" template-url=\"salaxy-components/odata/lists/AccountingReports.html\" options=\"{ $filter: $ctrl.getODataFilter(), $orderby: 'logicalDate desc' }\">\r\n  </salaxy-odata-table>\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode == 'panel'\" crud-controller=\"AccountingReportCrudController as $crud\" template-url=\"salaxy-components/odata/lists/AccountingReportsPanel.html\" options=\"$ctrl.panelQueryOptions\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingReportQuery.html\",`<div class=\"salaxy-component salaxy-accounting-report-query\">\r\n  <form name=\"queryForm\" ng-if=\"!$ctrl.calcs\" class=\"form-horizontal\">\r\n    <div ng-show=\"false\" ng-init=\"$ctrl.queryForm = queryForm\"></div>\r\n    <fieldset>\r\n      <div class=\"col col-md-6\">\r\n        <salaxy-input-enum name=\"queryType\" label=\"SALAXY.NG1.AccountingReportQueryComponent.reportCalcsLabel\" options=\"{periodQuery: ('SALAXY.NG1.AccountingReportQueryComponent.periodQueryEnum' | sxyTranslate), selectionQuery: ('SALAXY.NG1.AccountingReportQueryComponent.selectionQueryEnum' | sxyTranslate) }\"\r\n          ng-model=\"$ctrl.queryType\" type=\"radio\" required></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"col col-md-6\" ng-if=\"$ctrl.queryType == 'selectionQuery'\">\r\n        <p>\r\n          <span class=\"label label-primary\" ng-if=\"$ctrl.calculations.length\"> <span sxy-text=\"SALAXY.UI_Terms.chosen\" ps=\":\"></span>{{ $ctrl.calculations.length }}</span>\r\n        </p>\r\n        <div class=\"btn-toolbar\" role=\"toolbar\">\r\n          <button class=\"btn btn-default\" ng-click=\"$ctrl.addCalcs('paid')\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.addPaidCalcs\"></button>\r\n          <button class=\"btn btn-default\" ng-click=\"$ctrl.addCalcs('draft')\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.addDraftCalcs\"></button>\r\n        </div>\r\n      </div>\r\n      <div class=\"col col-md-6\" ng-if=\"$ctrl.queryType == 'periodQuery'\">\r\n        <salaxy-input-enum name=\"periodDateKind\" label=\"SALAXY.NG1.AccountingReportQueryComponent.periodDateKindLabel\" enum=\"PeriodDateKind\"\r\n          ng-model=\"$ctrl.periodDateKind\" type=\"radio\" required></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"col col-md-6\" ng-if=\"$ctrl.queryType == 'periodQuery'\">\r\n        <salaxy-input-enum name=\"period\" label=\"SALAXY.NG1.AccountingReportQueryComponent.period\" options=\"{month: ('SALAXY.NG1.AccountingReportQueryComponent.monthEnum' | sxyTranslate), custom: ('SALAXY.NG1.AccountingReportQueryComponent.customEnum' | sxyTranslate) }\"\r\n          ng-model=\"$ctrl.periodType\" type=\"radio\" required></salaxy-input-enum>\r\n      </div>\r\n      <div class=\"col col-md-6\" ng-if=\"$ctrl.queryType == 'periodQuery'\">\r\n        <salaxy-datepicker-popup name=\"refDateMonth\" placeholder=\"SALAXY.NG1.AccountingReportQueryComponent.monthPlaceHolder\" ng-if=\"$ctrl.periodType == 'month'\" format=\"MMMM\" datepicker-options=\"{ datepickerMode : 'month', minMode: 'month' }\" ng-model=\"$ctrl.refDate\"\r\n          label=\"SALAXY.NG1.AccountingReportQueryComponent.refDateMonthLabel\" required></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"refDateQuarter\" placeholder=\"SALAXY.NG1.AccountingReportQueryComponent.monthPlaceHolder\" ng-if=\"$ctrl.periodType == 'quarter'\" format=\"MMMM\" datepicker-options=\"{ datepickerMode : 'month', minMode: 'month' }\" ng-model=\"$ctrl.refDate\"\r\n          label=\"SALAXY.NG1.AccountingReportQueryComponent.refDateQuarterLabel\" required>\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"refDateYear\" placeholder=\"SALAXY.NG1.AccountingReportQueryComponent.yearPlaceholder\" ng-if=\"$ctrl.periodType == 'year'\" format=\"yyyy\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$ctrl.refDate\"\r\n          label=\"SALAXY.NG1.AccountingReportQueryComponent.refDateYearLabel\" required></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"refDateCustom\" ng-if=\"$ctrl.periodType == 'custom'\" ng-model=\"$ctrl.refDate\" label=\"SALAXY.NG1.AccountingReportQueryComponent.refDateCustomLabel\" required>\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"endDateCustom\" ng-if=\"$ctrl.periodType == 'custom'\" ng-model=\"$ctrl.endDate\" label=\"SALAXY.NG1.AccountingReportQueryComponent.endDateCustomLabel\"></salaxy-datepicker-popup>\r\n      </div>\r\n    </fieldset>\r\n    <div ng-if=\"$ctrl.queryType == 'selectionQuery'\" class=\"col col-md-12\">\r\n      <div ng-if=\"$ctrl.calculations.length\" class=\"table-responsive salaxy-odata-table\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th colspan=\"2\">\r\n                <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n              </th>\r\n              <th class=\"hidden-xxs\">\r\n                <span sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.status\"></span><br />\r\n                <span><span sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.date\"></span></span>\r\n              </th>\r\n              <th class=\"right hidden-xxs\">\r\n                <span sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.salary\"></span><br />\r\n                <span><span sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.payment\"></span></span>\r\n              </th>\r\n              <th class=\"hidden-xxs\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"row in $ctrl.calculations\">\r\n              <td class=\"td-avatar visible-xxs middle\">\r\n                <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td class=\"td-name visible-xxs middle\">\r\n                <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.notSelected\"></span>\r\n                <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n                <br /> {{ row.endAt | date }}\r\n              </td>\r\n              <td class=\"right visible-xxs bottom\">\r\n                <div>\r\n                  {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n                </div>\r\n              </td>\r\n              <td class=\"td-avatar hidden-xxs middle\">\r\n                <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td class=\"td-name hidden-xxs middle\">\r\n                <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.notSelected\"></span>\r\n                <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n              </td>\r\n              <td class=\"hidden-xxs middle\">\r\n                {{ row.status ? (\"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate) : \"#ERR\" }}<br /> {{ row.endAt | date }}\r\n              </td>\r\n              <td class=\"right hidden-xxs middle\">\r\n                {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n              </td>\r\n              <td class=\"right middle\">\r\n                <button class=\"btn btn-sm  btn-danger\" type=\"button\" ng-click=\"$ctrl.removeCalc(row)\">\r\n                      {{ 'SALAXY.UI_Terms.unselect' | sxyTranslate }}\r\n                    </button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </form>\r\n  <div ng-if=\"!$ctrl.calcs\" class=\"col col-md-12 text-right\">\r\n    <button class=\"btn btn-primary\" ng-disabled=\"!$ctrl.queryForm.$valid\" ng-click=\"$ctrl.queryData($reportTools.targetId)\" sxy-text=\"SALAXY.NG1.AccountingReportQueryComponent.queryRows\"></button>\r\n  </div>\r\n\r\n  <salaxy-accounting-report-tools ng-ref=\"$reportTools\" any-expanded=\"$reportRows.anyExpanded\" on-expand-change=\"$reportRows.expand(close)\" on-target-change=\"$ctrl.queryData(targetId)\" reader=\"$ctrl.dataReader\" view=\"$ctrl.view\"></salaxy-accounting-report-tools>\r\n  <salaxy-accounting-report-rows lang=\"$ctrl.lang\" ng-ref=\"$reportRows\" data=\"$ctrl.data\" view=\"$ctrl.view\"></salaxy-accounting-report-rows>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingReportRows.html\",`<div class=\"salaxy-component salaxy-accounting-report-rows\">\r\n  <table ng-if=\"$ctrl.view != 'full'\" class=\"table table-condensed\">\r\n    <thead style=\"background:#f5f5f5; display: table-header-group;\">\r\n      <tr>\r\n        <th class=\"col-md-3\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.accountNumber\"></th>\r\n        <th class=\"col-md-6\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.accountName\"></th>\r\n        <th class=\"col-md-3 right\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.saldo\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr style=\"background:#f5f5f5\" ng-repeat-start=\"ledgerAccount in ($ctrl.data || {}).ledgerAccounts\">\r\n        <td>{{ledgerAccount.accountNumber }}</td>\r\n        <td>{{ledgerAccount.accountName}}</td>\r\n        <td class=\"right\"><a ng-click=\"ledgerAccount.rowToggle = !ledgerAccount.rowToggle\">{{ledgerAccount.saldo | currency}}</a></td>\r\n      </tr>\r\n      <tr ng-if=\"ledgerAccount.rowToggle\" ng-repeat-end>\r\n        <td colspan=\"3\">\r\n          <table class=\"table table-condensed\">\r\n            <thead>\r\n              <tr>\r\n                <th class=\"col-md-3\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.calculation\"></th>\r\n                <th class=\"col-md-6\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.description\"></th>\r\n                <th class=\"col-md-1 right\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.vatPercent\"></th>\r\n                <th class=\"col-md-2 right\" sxy-text=\"SALAXY.NG1.AccountingReportRowsComponent.sum\"></th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"entry in ledgerAccount.entries\">\r\n                <td>\r\n                  <a ng-if=\"entry.dimension.calculationId\" ng-href=\"#/calc/details/{{entry.dimension.calculationId}}\">{{entry.dimension.calculationTitle}}</a>\r\n                  <a ng-if=\"!entry.dimension.calculationId && entry.dimension.employmentId\" ng-href=\"#/employments/details/{{entry.dimension.employmentId}}\">{{entry.dimension.workerName}}</a>\r\n                </td>\r\n                <td>{{entry.description}}\r\n                  <div ng-if=\"entry.dimension.projectNumber\">{{'SALAXY.NG1.AccountingReportRowsComponent.projectNumber' | sxyTranslate}}: {{entry.dimension.projectNumber}}</div>\r\n                  <div ng-if=\"entry.dimension.costCenter\">{{'SALAXY.NG1.AccountingReportRowsComponent.costCenter' | sxyTranslate}}: {{entry.dimension.costCenter}}</div>\r\n                  <div ng-if=\"entry.dimension.dimensions\" ng-repeat=\"(k,v) in entry.dimension.dimensions\">\r\n                    {{k}}: {{v}}\r\n                  </div>\r\n                </td>\r\n                <td class=\"right\"><span ng-if=\"entry.vatPercent >= 0\">{{ entry.vatPercent | sxyCount : 'percent'}}</span></td>\r\n                <td class=\"right\">{{!entry.isDebit ? -1 * entry.amount : entry.amount | currency}}</td>\r\n\r\n              </tr>\r\n            </tbody>\r\n          </table>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <div ng-if=\"$ctrl.view == 'full'\">\r\n    <div ng-bind-html=\"$ctrl.html\" class=\"report-binder table-responsive\"></div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingReportTools.html\",`<div class=\"salaxy-component salaxy-accounting-report-tools\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Report options\">\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"reportOptionsTarget\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{'SALAXY.NG1.AccountingReportToolsComponent.target' | sxyTranslate}}: <img style=\"height: 15px;\" ng-if=\"$ctrl.getTarget($ctrl.targetId).avatar.url\" ng-src=\"{{$ctrl.getTarget($ctrl.targetId).avatar.url}}\">&nbsp;{{$ctrl.getTarget($ctrl.targetId).avatar.displayName}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"reportOptionsTarget\">\r\n        <li ng-repeat=\"target in $ctrl.targets\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.changeTarget(target.id)\"><img style=\"height: 20px;\" ng-if=\"$ctrl.getTarget(target.id).avatar.url\" ng-src=\"{{$ctrl.getTarget(target.id).avatar.url}}\">&nbsp;{{$ctrl.getTarget(target.id).avatar.displayName}}</a>\r\n        </li>\r\n        <li role=\"menuitem\"><button class=\"btn btn-link\" ng-click=\"$ctrl.navigate('/settings/accounting-target-settings')\" sxy-text=\"SALAXY.NG1.AccountingReportToolsComponent.settingsAddMoreTargets\" ps=\"...\"></button></li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown  ng-if=\"$ctrl.getTarget($ctrl.targetId).schemes.length\">\r\n      <button id=\"reportOptionsScheme\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{$ctrl.getScheme($ctrl.schemeId).label}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"reportOptionsScheme\">\r\n        <li ng-repeat=\"scheme in $ctrl.getTarget($ctrl.targetId).schemes\" role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.schemeId = scheme.id\">{{$ctrl.getScheme(scheme.id).label}}</a></li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"reportOptionsExportMethod\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        {{$ctrl.getExportMethod($ctrl.exportMethod).label}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"reportOptionsExportMethod\">\r\n        <li role=\"menuitem\" ng-repeat=\"exportMethod in $ctrl.exportMethods\"><a href=\"\" ng-click=\"$ctrl.exportMethod = exportMethod.id\">{{$ctrl.getExportMethod(exportMethod.id).label}}</a></li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"reportOptionsCulture\" type=\"button\" class=\"btn btn-default\" ng-disabled=\"!$ctrl.getExportMethod($ctrl.exportMethod).hasLocales\" uib-dropdown-toggle>\r\n        {{$ctrl.getLocale($ctrl.localeId).label}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"reportOptionsCulture\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.localeId = 'fi'\">{{$ctrl.getLocale('fi').description}}</a></li>\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.localeId = 'en'\">{{$ctrl.getLocale('en').description}}</a></li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm\">\r\n      <button ng-disabled=\"$ctrl.reader.disabled()\" id=\"reportExport\" type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.export()\">\r\n        {{ $ctrl.reader.exportLabel || ('SALAXY.NG1.AccountingReportToolsComponent.createExport' | sxyTranslate) }}  \r\n      </button>\r\n    </div>\r\n    <div class=\"pull-right\" ng-if=\"$ctrl.reader.showExpand && $ctrl.view == 'partial'\">\r\n\r\n      <button ng-if=\"!$ctrl.anyExpanded\" ng-disabled=\"$ctrl.reader.hasRows()\" class=\"btn btn-block btn-transparent\" title=\"{{'SALAXY.NG1.AccountingReportToolsComponent.showRowsAndExports' | sxyTranslate}}\" ng-click=\"$ctrl.expand()\">\r\n        <i class=\"fa fa-expand\"></i>\r\n      </button>\r\n      <button ng-if=\"$ctrl.anyExpanded\" ng-disabled=\"$ctrl.reader.hasRows()\" class=\"btn btn-block btn-transparent\" title=\"{{'SALAXY.NG1.AccountingReportToolsComponent.showOnlyRows' | sxyTranslate}}\" ng-click=\"$ctrl.expand(true)\">\r\n        <i class=\"fa fa-compress\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingReportViewer.html\",`<div class=\"btn-toolbar pull-right\" role=\"toolbar\" salaxy-if-role=\"test,pro\">\r\n  <salaxy-workflow-buttons disabled=\"!($ctrl.currentData && $ctrl.currentData.ledgerAccounts.length > 0)\" api-ctrl=\"$ctrl\"></salaxy-workflow-buttons>\r\n</div>\r\n<salaxy-accounting-report-tools  any-expanded=\"$reportRows.anyExpanded\" on-expand-change=\"$reportRows.expand(close)\" on-target-change=\"$ctrl.loadCurrentData(targetId)\"  reader=\"$ctrl.currentDataReader\"></salaxy-accounting-report-tools>\r\n<salaxy-accounting-report-rows  ng-ref=\"$reportRows\" data=\"$ctrl.currentData\"></salaxy-accounting-report-rows>`);\n\n $templateCache.put(\"salaxy-components/report/AccountingRowReport.html\",`<div class=\"salaxy-component salaxy-accounting-row-report\" style=\"width:100%;height:100%;display:flex;flex-flow:column\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1.CumulativeReportComponent.chooseData' | sxyTranslate}}\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showPeriodSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectPeriod\" ps=\"...\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showCalcsSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectCalcs\" ps=\"...\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showPayrollSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectPayrolls\" ps=\"...\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1.CumulativeReportComponent.reportTemplates' | sxyTranslate}}\">\r\n      <div class=\"btn-group btn-group\" uib-dropdown>\r\n        <button id=\"templateId\" type=\"button\" class=\"btn btn-default\" ng-disabled=\"!$ctrl.data\" uib-dropdown-toggle >\r\n          <span ng-if=\"$ctrl.data\">\r\n            <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"$ctrl.getTemplate($ctrl.templateId).avatar\"></salaxy-avatar> {{$ctrl.getTemplate($ctrl.templateId).label}}\r\n          </span>\r\n          <span ng-if=\"!$ctrl.data\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.reportTemplates\"></span>\r\n          <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"templateId\">\r\n          <li role=\"menuitem\" ng-repeat=\"template in $ctrl.templates\"><a href=\"\" ng-click=\"$ctrl.selectTemplate(template.id)\">\r\n               <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"$ctrl.getTemplate(template.id).avatar\"></salaxy-avatar> {{$ctrl.getTemplate(template.id).label}}\r\n            </a>\r\n           </li>\r\n        </ul>\r\n      </div>\r\n      <button type=\"button\" class=\"btn btn-default\"  ng-disabled=\"!$ctrl.data\" ng-click=\"$ctrl.showSaveTemplate()\">{{'SALAXY.UI_Terms.edit' | sxyTranslate}}...</button>\r\n    </div>\r\n  </div>\r\n  <div style=\"height:100%;flex-grow:1\">\r\n    <div id=\"dataGrid\" class=\"ag-theme-balham\" style=\"height:100%;overflow: hidden;\"></div>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/report/CalculationReport.html\",`<div class=\"salaxy-component salaxy-calculation-report\" style=\"width:100%;height:100%;display:flex;flex-flow:column\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1.CumulativeReportComponent.chooseData' | sxyTranslate}}\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showPeriodSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectPeriod\" ps=\"...\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showCalcsSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectCalcs\" ps=\"...\"></button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showPayrollSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectPayrolls\" ps=\"...\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1.CumulativeReportComponent.reportTemplates' | sxyTranslate}}\">\r\n      <div class=\"btn-group btn-group\" uib-dropdown>\r\n        <button id=\"templateId\" type=\"button\" class=\"btn btn-default\" ng-disabled=\"!$ctrl.data\" uib-dropdown-toggle >\r\n          <span ng-if=\"$ctrl.data\">\r\n            <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"$ctrl.getTemplate($ctrl.templateId).avatar\"></salaxy-avatar> {{$ctrl.getTemplate($ctrl.templateId).label}}\r\n          </span>\r\n          <span ng-if=\"!$ctrl.data\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.reportTemplates\"></span>\r\n          <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"templateId\">\r\n          <li role=\"menuitem\" ng-repeat=\"template in $ctrl.templates\"><a href=\"\" ng-click=\"$ctrl.selectTemplate(template.id)\">\r\n               <salaxy-avatar style=\"font-size: 1.8em; margin: -2px 4px -2px -2px;\" avatar=\"$ctrl.getTemplate(template.id).avatar\"></salaxy-avatar> {{$ctrl.getTemplate(template.id).label}}\r\n            </a>\r\n           </li>\r\n        </ul>\r\n      </div>\r\n      <button type=\"button\" class=\"btn btn-default\"  ng-disabled=\"!$ctrl.data\" ng-click=\"$ctrl.showSaveTemplate()\">{{'SALAXY.UI_Terms.edit' | sxyTranslate}}...</button>\r\n    </div>\r\n  </div>\r\n  <div style=\"height:100%;flex-grow:1\">\r\n    <div id=\"dataGrid\" class=\"ag-theme-balham\" style=\"height:100%;overflow: hidden;\"></div>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/report/HolidayPayReportQuery.html\",`<div class=\"salaxy-component salaxy-holiday-pay-report-query\">\r\n  <div ng-if=\"$ctrl.data.holidayYear.employmentId\" class=\"salaxy-calc-worker-info\" ng-controller=\"EmploymentCrudController as $employmentCtrl\" ng-init=\"$employmentCtrl.model=$ctrl.data.holidayYear.employmentId\">\r\n    <div class=\"row spacer-bottom\" ng-if=\"$employmentCtrl.current\">\r\n      <div class=\"col-xs-3 col-sm-2 col-xxs-3\">\r\n        <salaxy-avatar avatar=\"$employmentCtrl.current.personalInfo.avatar\"></salaxy-avatar>\r\n      </div>\r\n      <div class=\"col-xs-9 col-sm-10 col-xxs-9 worker-info-col\">\r\n        <h2>{{ $employmentCtrl.current.personalInfo.avatar.displayName || (\"SALAXY.NG1.WorkerInfo.noSelection\" | sxyTranslate) }}</h2>\r\n        <div class=\"row\" ng-if=\"$employmentCtrl.current\">\r\n          <div class=\"col-xs-12 col-sm-6 \">\r\n            <div ng-class=\"$employmentCtrl.current.personalInfo.officialId ? '' : 'text-danger'\">\r\n              {{ $employmentCtrl.current.personalInfo.officialId || ( \"SALAXY.NG1.PaymentDialogComponent.noSSNumber\" | sxyTranslate ) }}\r\n              &nbsp;\r\n              <div class=\"btn-group\" uib-dropdown ng-if=\"$employmentCtrl.otherEmployments.length > 0\">\r\n                <button id=\"single-button\" type=\"button\" class=\"btn btn-default btn-xs\" uib-dropdown-toggle>\r\n                  {{ $employmentCtrl.otherEmployments.length }} muuta työsuhdetta <span class=\"caret\"></span>\r\n                </button>\r\n                <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n                  <li role=\"menuitem\" ng-repeat=\"item in $employmentCtrl.otherEmployments\">\r\n                    <a ng-href=\"{{$employmentCtrl.isModal ? '' : ('#/employments/details/' + item.id)}}\">\r\n                      {{ $employmentCtrl.getEmploymentDescription(item) }}\r\n                      ({{ $employmentCtrl.getActiveText(item) }})\r\n                    </a>\r\n                  </li>\r\n                </ul>\r\n              </div>\r\n              <span ng-if=\"!$employmentCtrl.otherEmployments\">Tarkistetaan muita työsuhteita...</span>\r\n            </div>\r\n            <div>{{ $employmentCtrl.getEmploymentDescription($employmentCtrl.current) }}</div>\r\n            <div>{{ $employmentCtrl.getActiveText($employmentCtrl.current) }}</div>\r\n            <div><small>{{ $employmentCtrl.current.id }}</small></div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-sm-6\">\r\n        <form class=\"form-horizontal\">\r\n            <salaxy-input-enum  name=\"year\"  ng-model=\"$ctrl.year\"   label=\"SALAXY.NG1.HolidayReportComponent.holidayYear\" options=\"$ctrl.years\" ng-change=\"$ctrl.query()\"></salaxy-input-enum>\r\n            <salaxy-input-enum ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' || $ctrl.data.holidayYear.spec.code == 'permanent35Hours' || $ctrl.data.holidayYear.spec.code == 'temporaryTimeOff'\" name=\"holidayPayCalculation\" ng-model=\"$ctrl.data.holidayYear.spec.holidayPayCalculation\" disabled=\"true\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayCalculation.title\" enum=\"HolidayPayCalculation\"></salaxy-input-enum>\r\n            <salaxy-input-enum name=\"holidayCode\" ng-model=\"$ctrl.data.holidayYear.spec.code\" disabled=\"true\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.code.title\" enum=\"HolidayCode\"></salaxy-input-enum>\r\n            <salaxy-input-enum name=\"wageBasis\" ng-model=\"$ctrl.data.holidayYear.spec.wageBasis\" disabled=\"true\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.wageBasis\" enum=\"WageBasis\"></salaxy-input-enum>   \r\n        </form>\r\n      </div>\r\n      <div class=\"col-sm-6\">\r\n        <form class=\"form-horizontal\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' || $ctrl.data.holidayYear.spec.code == 'permanent35Hours' || $ctrl.data.holidayYear.spec.code == 'temporaryTimeOff'\">\r\n\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.accrual.total\" name=\"accrualTotal\"   disabled=\"true\" label=\"Lomavuoden kertymä\" ></salaxy-input-number>\r\n\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.otherPay\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'otherPay'\" name=\"otherPay\"   disabled=\"true\"  label=\"SALAXY.MODEL.HolidayPay.otherPay.title\" ></salaxy-input-number>\r\n\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.normalMonthlyPayDailySalary\" name=\"normalMonthlyPayDailySalary\" ng-if=\"($ctrl.data.holidayYear.spec.code == 'permanent14Days' || $ctrl.data.holidayYear.spec.code == 'permanent35Hours') && $ctrl.data.holidayYear.spec.wageBasis =='monthly' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'normalMonthlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPayDailySalary.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.normalMonthlyPayManual\" name=\"normalMonthlyPayManual\" ng-if=\"($ctrl.data.holidayYear.spec.code == 'permanent14Days' || $ctrl.data.holidayYear.spec.code == 'permanent35Hours') && $ctrl.data.holidayYear.spec.wageBasis =='monthly' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'normalMonthlyPay'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPayManual.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.normalMonthlyPay\" name=\"normalMonthlyPay\" ng-if=\"($ctrl.data.holidayYear.spec.code == 'permanent14Days' || $ctrl.data.holidayYear.spec.code == 'permanent35Hours') && $ctrl.data.holidayYear.spec.wageBasis =='monthly' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'normalMonthlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPay.title\" ></salaxy-input-number>\r\n\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPayDailySalary\" name=\"averageDailyPayDailySalary\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayDailySalary.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPayManual\" name=\"averageDailyPayManual\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayManual.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPay\" name=\"averageDailyPay\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPay.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPayBase\" name=\"averageDailyPayBase\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\"  label=\"SALAXY.MODEL.HolidayPay.averageDailyPayBase.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPayDays\" name=\"averageDailyPayDays\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayDays.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageDailyPayMultiplier\" name=\"averageDailyPayMultiplier\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayMultiplier.title\" ></salaxy-input-number>\r\n  \r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPayDailySalary\" name=\"averageHourlyPayDailySalary\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayDailySalary.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPayManual\" name=\"averageHourlyPayManual\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayManual.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPay\" name=\"averageHourlyPay\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPay.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPayBase\" name=\"averageHourlyPayBase\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\"  label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayBase.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPayHours\" name=\"averageHourlyPayHours\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayHours.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.averageHourlyPayMultiplier\" name=\"averageHourlyPayMultiplier\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent14Days' && ($ctrl.data.holidayYear.spec.wageBasis =='hourly' || $ctrl.data.holidayYear.spec.wageBasis =='performanceBased' || $ctrl.data.holidayYear.spec.wageBasis =='other') && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayMultiplier.title\" ></salaxy-input-number>\r\n      \r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.percentageBasedPayDailySalary\" name=\"percentageBasedPayDailySalary\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayDailySalary.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.percentageBasedPayManual\" name=\"percentageBasedPayManual\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayManual.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.percentageBasedPay\" name=\"percentageBasedPay\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPay.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.percentageBasedPayBase\" name=\"percentageBasedPayBase\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay'\"  disabled=\"true\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayBase.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.spec.holidayPayPercent\" name=\"holidayPayPercent\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay'\" required unit=\"percent\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayPercent.title\" ></salaxy-input-number>\r\n\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.compensationPayDailySalary\" name=\"compensationPayDailySalary\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'temporaryTimeOff' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPayDailySalary.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.compensationPayManual\" name=\"compensationPayManual\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'temporaryTimeOff' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPayManual.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.compensationPay\" name=\"compensationPay\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'temporaryTimeOff' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPay.title\" ></salaxy-input-number>\r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.holidayPay.compensationPayBase\" name=\"compensationPayBase\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'temporaryTimeOff' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPayBase.title\" ></salaxy-input-number>        \r\n            <salaxy-input-number ng-model=\"$ctrl.data.holidayYear.spec.compensation\" name=\"compensation\" ng-if=\"$ctrl.data.holidayYear.spec.code == 'temporaryTimeOff' && $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation'\" unit=\"percent\" required  disabled=\"true\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.compensation.title\" ></salaxy-input-number>\r\n \r\n        </form>\r\n      </div>\r\n    </div>\r\n    <uib-tabset active=\"$ctrl.currentTab\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay' || $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay' || $ctrl.data.holidayYear.spec.holidayPayCalculation == 'percentageBasedPay' || $ctrl.data.holidayYear.spec.holidayPayCalculation == 'holidayCompensation' || $ctrl.data.holidayYear.spec.holidayPayCalculation == 'normalMonthlyPay'\">\r\n      <uib-tab heading=\"{{ 'SALAXY.NG1.HolidayPayReportQueryComponent.calculationsTab' | sxyTranslate}}\" index=\"'calcs'\">     \r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.calculation\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.description\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.count\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.price\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.toHolidayPay\"></th>\r\n              <th class=\"right\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.toWorkingHours\"></th>\r\n              <th class=\"right\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.toOvertimeHours\"></th>\r\n              <th class=\"right\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.workingDays\"></th>\r\n              <th class=\"right\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.absenceDays\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.holidayPaySelection\"></th>\r\n              <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.workingHoursSelection\"></th>\r\n              <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.overtimeHoursSelection\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat-start=\"calc in $ctrl.data.calculations\">\r\n              <td><a ng-href=\"#/calc/details/{{calc.calculationId}}\">{{calc.calculationTitle}} {{calc.salaryDate | date}}</a></td>\r\n              <td>{{calc.workStartDate | date }} - {{calc.workEndDate | date}}</td>\r\n              <td class=\"right\"></td>\r\n              <td class=\"right\"></td>\r\n              <td class=\"right\"></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" class=\"right\"></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\"></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{calc.workingDays}}</td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{calc.absenceDays}}</td>\r\n              <td></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\"></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\"></td>\r\n            </tr>\r\n            <tr ng-repeat-end ng-repeat=\"row in calc.rows\">\r\n              <td></td>\r\n              <td>{{$ctrl.getLabel(row.irRow)}}</td>\r\n              <td class=\"right\">{{row.irRow.count}}</td>\r\n              <td class=\"right\">{{row.irRow.price | currency}}</td>\r\n              <td class=\"right\">{{row.total | currency}}</td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" class=\"right\">{{row.hours}}</td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{row.overtimeHours}}</td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\"></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\"></td>\r\n              <td><salaxy-input-holiday-row-type name=\"salaryType\" label-type=\"no-label\" ng-model=\"row.salaryType\" read-only=\"true\"></salaxy-input-holiday-row-type></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\"><salaxy-input-holiday-row-type name=\"workingTimeType\" label-type=\"no-label\" ng-model=\"row.workingTimeType\" read-only=\"true\"></salaxy-input-holiday-row-type></td>\r\n              <td ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\"><salaxy-input-holiday-row-type name=\"overtimeType\" label-type=\"no-label\" ng-model=\"row.overtimeType\" read-only=\"true\"></salaxy-input-holiday-row-type></td>\r\n            </tr>\r\n          </tbody>\r\n          <tfoot>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayPayReportQueryComponent.total\"></th>\r\n            <th></th>\r\n            <th class=\"right\"></th>\r\n            <th class=\"right\"></th>\r\n            <th class=\"right\">{{$ctrl.totals.total | currency}}</th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" class=\"right\">{{$ctrl.totals.hours}}</th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{$ctrl.totals.overtimeHours}}</th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{$ctrl.totals.workingDays}}</th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" class=\"right\">{{$ctrl.totals.absenceDays}}</th>\r\n            <th></th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\"></th>\r\n            <th ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\"></th>\r\n          </tfoot>\r\n        </table>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{ 'SALAXY.NG1.HolidayPayReportQueryComponent.parametersTab' | sxyTranslate}}\" index=\"'parameters'\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6\">\r\n            <form class=\"form-horizontal\">\r\n              <salaxy-form-group  name=\"salaryTypes\" label=\"SALAXY.NG1.HolidayPayReportQueryComponent.holidayPayRowTypes\">\r\n                <salaxy-input-holiday-row-type ng-repeat=\"rowType in $ctrl.data.holidayPaySettings.salaryTypes\" name=\"salaryType\" label-type=\"no-label\" ng-model=\"rowType\" read-only=\"true\"></salaxy-input-holiday-row-type>\r\n              </salaxy-form-group>\r\n            </form>\r\n          </div>\r\n          <div class=\"col-sm-6\">\r\n            <form class=\"form-horizontal\">\r\n              <salaxy-form-group  ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay'\" name=\"workingTimeTypes\" label=\"SALAXY.NG1.HolidayPayReportQueryComponent.workingHoursRowTypes\">\r\n                <salaxy-input-holiday-row-type ng-repeat=\"rowType in $ctrl.data.holidayPaySettings.workingTimeTypes\" name=\"workingTimeType\" label-type=\"no-label\" ng-model=\"rowType\" read-only=\"true\"></salaxy-input-holiday-row-type>\r\n              </salaxy-form-group>\r\n              <salaxy-form-group  ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" name=\"overtimeTypes\" label=\"SALAXY.NG1.HolidayPayReportQueryComponent.overtimeHoursRowTypes\">\r\n                <salaxy-input-holiday-row-type ng-repeat=\"rowType in $ctrl.data.holidayPaySettings.overtimeTypes\" name=\"overtimeType\" label-type=\"no-label\" ng-model=\"rowType\" read-only=\"true\"></salaxy-input-holiday-row-type>\r\n              </salaxy-form-group>\r\n              <salaxy-form-group  ng-if=\"$ctrl.data.holidayYear.spec.code == 'permanent35Hours'\"  name=\"accrualWorkingTimeTypes\" label=\"SALAXY.NG1.HolidayPayReportQueryComponent.accrualWorkingTimeRowTypes\">\r\n                <salaxy-input-holiday-row-type ng-repeat=\"rowType in $ctrl.data.holidayAccrualSettings.workingTimeTypes\" name=\"accrualWorkingTimeType\" label-type=\"no-label\" ng-model=\"rowType\" read-only=\"true\"></salaxy-input-holiday-row-type>\r\n              </salaxy-form-group>\r\n            </form>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6\">\r\n            <form class=\"form-horizontal\">\r\n              <salaxy-input-holiday-multipliers ng-if=\"$ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageHourlyPay' || $ctrl.data.holidayYear.spec.holidayPayCalculation == 'averageDailyPay'\" name=\"multipliers\" label=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\" ng-model=\"$ctrl.data.holidayPaySettings.multipliers\" read-only=\"true\"></salaxy-input-holiday-multipliers>\r\n            </form>\r\n          <div>\r\n        </div>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/report/HolidayReport.html\",`<div class=\"salaxy-component salaxy-holiday-report\">\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab index=\"'years'\" heading=\"{{ 'SALAXY.NG1.HolidayReportComponent.holidayYears' | sxyTranslate }}\">\r\n      <div class=\"row\">\r\n        <div class=\"form-horizontal col-sm-3\">\r\n          <salaxy-input-enum  name=\"year\"  ng-model=\"$ctrl.year\"   label=\"SALAXY.NG1.HolidayReportComponent.holidayYear\" options=\"$ctrl.years\"></salaxy-input-enum>\r\n        </div>\r\n        <div class=\"col-sm-3\">\r\n          <button type=\"button\" class=\"btn btn-secondary\" ng-click=\"$ctrl.exportToExcel()\">\r\n            <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.exportToExcel\"></span>\r\n            <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n          </button>\r\n        </div>\r\n      </div>\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span></th>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.startDate\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.endDate\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.employment\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.salary\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.holidayCode\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.periodDefaultAccrual\"></th>\r\n            <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.holidayPayCalculation\"></th>        \r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.startSaldo\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.total\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paid\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.available\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidaySalary\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayCompensation\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paidBonus\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.availableBonus\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayBonus\"></th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayPayDailySalary\"></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.resultRows | filter: { data : { holidayYear : { year: $ctrl.year } } } track by $index\">\r\n            <td class=\"align-middle td-avatar\">\r\n              <salaxy-avatar class=\"clickable\" ng-click=\"$ctrl.showEditEmploymentDialog(row)\" avatar=\"row.holidayYearReportRow.workerAvatar\"></salaxy-avatar>\r\n            </td>\r\n            <td>{{row.holidayYearReportRow.workerAvatar.displayName}}</td>\r\n            <td>{{row.holidayYearReportRow.startDate | sxyDate}}</td>\r\n            <td>{{row.holidayYearReportRow.endDate | sxyDate}}</td>\r\n            <td>{{row.holidayYearReportRow.employmentType}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.grossSalary| currency) || \"&nbsp;\"}}</td>\r\n            <td>{{row.holidayYearReportRow.holidayCode}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.periodDefaultAccrual | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td>{{row.holidayYearReportRow.holidayPayCalculation}}</td>      \r\n            <td class=\"right\">{{(row.holidayYearReportRow.startSaldo | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.total| sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.paid | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.available | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.holidaySalary | currency) || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.holidayCompensation| currency) || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.paidBonus | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.availableBonus | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n            <td class=\"right\">{{(row.holidayYearReportRow.holidayBonus| currency) || \"&nbsp;\"}}</td>\r\n            <td class=\"right\"><a ng-href=\"#/reports/holiday-pay-report-query/{{row.data.holidayYear.year}}/{{row.employment.id}}\">{{(row.holidayYearReportRow.holidayPayDailySalary | currency) || \"&nbsp;\"}}</a></td>      \r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </uib-tab>\r\n    <uib-tab index=\"'debt'\" heading=\"{{ 'SALAXY.NG1.HolidayReportComponent.holidayPayDebt' | sxyTranslate }}\">\r\n      <div class=\"row\">\r\n        <div class=\"form-horizontal col-sm-3\">\r\n          <salaxy-input-enum  name=\"year\"  ng-model=\"$ctrl.year\"   label=\"SALAXY.NG1.HolidayReportComponent.holidayYear\" options=\"$ctrl.years\"></salaxy-input-enum>\r\n        </div>\r\n        <div class=\"col-sm-3\">\r\n          <button type=\"button\" class=\"btn btn-secondary\" ng-click=\"$ctrl.exportToExcel()\">\r\n            <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.exportToExcel\"></span>\r\n            <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n          </button>\r\n        </div>\r\n        <div class=\"form-horizontal  col-sm-3\">\r\n          <salaxy-datepicker-popup name=\"refDate\" placeholder=\"\"  ng-model=\"$ctrl.refDate\"\r\n          label=\"SALAXY.NG1.HolidayReportComponent.holidayPayDebtDate\" required ng-change=\"$ctrl.query(true)\"></salaxy-datepicker-popup>\r\n        </div>\r\n        <div class=\"col-sm-3\">\r\n          <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.query(true)\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.calculateHolidayPayDebt\"></button>\r\n        </div>\r\n      </div>\r\n        <table class=\"table table-striped\" ng-if=\"$ctrl.hasQueryedDebt\">\r\n          <thead>\r\n            <tr>\r\n              <th colspan=\"2\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.startDate\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.endDate\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.employment\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.salary\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.holidayCode\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.periodDefaultAccrual\"></th>\r\n              <th sxy-text=\"SALAXY.NG1.HolidayReportComponent.table.holidayPayCalculation\"></th>         \r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.startSaldo\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.total\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paid\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.available\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidaySalary\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayCompensation\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.paidBonus\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.availableBonus\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayBonus\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.holidayPayDailySalary\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayPay\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayBonus\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidaySocialSecurity\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayPension\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayUnemployment\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayAccidentInsurance\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayGroupLifeInsurance\"></th>\r\n              <th class=\"right\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.holidayYearReportRow.totalAccruedHolidayTotal\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"row in $ctrl.resultRows | filter: { data : { holidayYear : { year: $ctrl.year } } } track by $index\">\r\n              <td class=\"align-middle td-avatar\">\r\n                <salaxy-avatar class=\"clickable\" ng-click=\"$ctrl.showEditEmploymentDialog(row)\" avatar=\"row.holidayYearReportRow.workerAvatar\"></salaxy-avatar>\r\n              </td>\r\n              <td>{{row.holidayYearReportRow.workerAvatar.displayName}}</td>\r\n              <td>{{row.holidayYearReportRow.startDate | sxyDate}}</td>\r\n              <td>{{row.holidayYearReportRow.endDate | sxyDate}}</td>\r\n              <td>{{row.holidayYearReportRow.employmentType}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.grossSalary| currency) || \"&nbsp;\"}}</td>\r\n              <td>{{row.holidayYearReportRow.holidayCode}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.periodDefaultAccrual | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td>{{row.holidayYearReportRow.holidayPayCalculation}}</td>       \r\n              <td class=\"right\">{{(row.holidayYearReportRow.startSaldo | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.total| sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.paid | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.available | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.holidaySalary | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.holidayCompensation| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.paidBonus | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.availableBonus | sxyCount : 'day') || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.holidayBonus| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\"><a ng-href=\"#/reports/holiday-pay-report-query/{{row.data.holidayYear.year}}/{{row.employment.id}}\">{{(row.holidayYearReportRow.holidayPayDailySalary | currency) || \"&nbsp;\"}}</a></td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayPay| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayBonus| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidaySocialSecurity | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayPension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayUnemployment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayAccidentInsurance| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayGroupLifeInsurance| currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.holidayYearReportRow.totalAccruedHolidayTotal| currency) || \"&nbsp;\"}}</td>       \r\n            </tr>\r\n          </tbody>\r\n          <tfoot>\r\n            <tr>&nbsp;</tr>\r\n            <tr>\r\n              <th colspan=\"19\">{{ \"SALAXY.NG1.HolidayReportComponent.yearAccruedDebt\" | sxyTranslate }} {{$ctrl.year}} </th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayPay| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayBonus| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidaySocialSecurity | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayPension | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayUnemployment | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayAccidentInsurance| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc[$ctrl.year].totalAccruedHolidayGroupLifeInsurance| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalcTotal[$ctrl.year] | currency) || \"&nbsp;\"}}</td>       \r\n            </tr>\r\n            <tr>\r\n              <th colspan=\"19\">{{ \"SALAXY.NG1.HolidayReportComponent.allAccruedDebt\" | sxyTranslate }}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayPay| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayBonus| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidaySocialSecurity | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayPension | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayUnemployment | currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayAccidentInsurance| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalc['total'].totalAccruedHolidayGroupLifeInsurance| currency) || \"&nbsp;\"}}</th>\r\n              <th class=\"right\">{{($ctrl.holidayCalcTotal['total'] | currency) || \"&nbsp;\"}}</td>       \r\n            </tr>\r\n          </tfoot>\r\n        </table>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/IrEarningsPayment.html\",`<div class=\"salaxy-component salaxy salaxy-ir-earnings-payment\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\" full-screen=\"true\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.UI_Terms.pleaseWait\"></salaxy-spinner>\r\n  <div ng-if=\"'test' | sxyIsInRole\">\r\n    <div ng-if=\"$ctrl.current.isReadOnly\" class=\"alert alert-info\" pre=\"VAIN TEST: \" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.readOnlyInfo\"></div>\r\n    <div class=\"btn-toolbar\" role=\"toolbar\" ng-if=\"$ctrl.current && $ctrl.isReadOnly && !$ctrl.current.isReadOnly\">\r\n      <div class=\"btn-group\" role=\"group\" aria-label=\"Muokkaa\">\r\n        <button ng-click=\"$ctrl.tempShowEditInNonAdminMode = true\" type=\"button\" role=\"group\" class=\"btn btn-primary\">VAIN TEST: Muokkaa</button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" ng-if=\"!$ctrl.isReadOnly\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Tallenna\">\r\n      <button ng-click=\"$ctrl.saveChanges()\" type=\"button\" role=\"group\" class=\"btn btn-primary\" ng-disabled=\"!($ctrl.hasChanges || ( $ctrl.calcController && $ctrl.calcController.hasChanges)) || $ctrl.isReadOnly\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Lähetä/mitätöi\">\r\n      <button ng-click=\"$ctrl.sendToIncomesRegister()\" type=\"button\" role=\"group\" class=\"btn btn-default\" ng-disabled=\"$ctrl.isReadOnly\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n      <button ng-click=\"$ctrl.openSetScheduleDialog()\" type=\"button\" role=\"group\" class=\"btn btn-default\" ng-disabled=\"$ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.addScheduling\"></button>\r\n      <button ng-click=\"$ctrl.removeIrQueueItem()\" type=\"button\" role=\"group\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.current.scheduledFor || $ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.removeScheduling\"></button>\r\n      <button ng-click=\"$ctrl.cancelToIncomesRegister()\" type=\"button\" role=\"group\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.isCancellable || $ctrl.isReadOnly\" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.cancel\"></button>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"!$ctrl.isLoading && !$ctrl.current\">\r\n    <h3>Ei Palkkatietoilmoitusta</h3>\r\n    <p>Palkkatietoilmoitus luodaan vasta, kun laskelma on merkitty maksetuksi.</p>\r\n  </div>\r\n  <div class=\"form-horizontal form-condensed\">\r\n    <uib-tabset active=\"currentTab\" ng-if=\"$ctrl.current\">\r\n      <uib-tab index=\"'default'\" heading=\"{{'SALAXY.NG1.EarningsPaymentComponent.common.basicInfo' | sxyTranslate}}\">\r\n        <div>\r\n          <div class=\"label label-success pull-right\" style=\"font-size: 1.5em\" ng-if=\"$ctrl.current.validation.isValid\">{{'SALAXY.NG1.EarningsPaymentComponent.common.noErrors' | sxyTranslate}}</div>\r\n          <!-- TODO: Check texts and add to language versioning. Consider could this be done with SXY-IPT infra. -->\r\n          <h3 ng-switch=\"$ctrl.current.status\">\r\n            <span ng-switch-when=\"new\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.new.text' | sxyTranslate}} <small sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.statuses.new.smallText\"></small></span>\r\n            <span ng-switch-when=\"succeeded\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.succeeded.text' | sxyTranslate}} <small>{{ $ctrl.current.lastDeliveredAt | sxyDate }} {{'SALAXY.NG1.EarningsPaymentComponent.common.time' | sxyTranslate}} {{ $ctrl.current.lastDeliveredAt | date : \"hh:mm\" }}</small></span>\r\n            <span ng-switch-when=\"canceled\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.canceled.text' | sxyTranslate}} <small sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.statuses.canceled.smallText\"></small> </span>\r\n            <span ng-switch-when=\"error\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.error.text' | sxyTranslate}} <small>{{'SALAXY.NG1.EarningsPaymentComponent.statuses.error.sending' | sxyTranslate}} {{ $ctrl.current.lastDeliveredAt | sxyDate }} {{'SALAXY.NG1.EarningsPaymentComponent.common.time' | sxyTranslate}} {{ $ctrl.current.lastDeliveredAt | date : \"hh:mm\" }} {{'SALAXY.NG1.EarningsPaymentComponent.statuses.error.gaveError' | sxyTranslate}}</small></span>\r\n            <span ng-switch-when=\"invalid\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.invalid.text' | sxyTranslate}} <small sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.statuses.invalid.smallText\"></small></span>\r\n            <span ng-switch-when=\"scheduled\">{{'SALAXY.NG1.EarningsPaymentComponent.statuses.scheduled.text' | sxyTranslate}} <small>{{ $ctrl.current.scheduledFor | sxyDate }} {{'SALAXY.NG1.EarningsPaymentComponent.common.time' | sxyTranslate}} {{ $ctrl.current.scheduledFor | date : \"hh:mm\" }}</small></span>\r\n            <span ng-switch-default>{{'SALAXY.MODEL.EarningsPayment.status.title' | sxyTranslate}}: {{ \"EarningsPaymentReportStatus.\" + $ctrl.current.status | sxyEnum }}</span>\r\n          </h3>\r\n          <salaxy-validation-summary api-validation=\"$ctrl.current.validation\" ng-if=\"!$ctrl.current.validation.isValid\">\r\n          </salaxy-validation-summary>\r\n          <salaxy-validation-summary api-validation=\"$ctrl.current.irErrors\" ng-if=\"!$ctrl.current.irErrors.isValid\">\r\n          </salaxy-validation-summary>\r\n        </div>\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current\" type=\"EarningsPayment\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <div class=\"row\">\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.MODEL.PaymentPeriod.title\"></legend>\r\n                  <sxy-input model=\"form.deliveryData.paymentPeriod.startDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.paymentPeriod.endDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.paymentPeriod.paymentDate\" format=\"date\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.worker\"></legend>\r\n                  <salaxy-avatar class=\"pull-left\" style=\"margin-right: 20px;font-size: 102px;\" avatar=\"$ctrl.current.info.worker\"></salaxy-avatar>\r\n                  <div>{{ $ctrl.current.info.worker.sortableName }}</div>\r\n                  <div>{{ $ctrl.current.deliveryData.reports[0].incomeEarner.incomeEarnerIds[0].code || \"Ei henkilötunnusta\" }}</div>\r\n                </fieldset>\r\n              </div>\r\n            </div>\r\n            <div class=\"row\">\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.basicInfo\"></legend>\r\n                  <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" model=\"$ctrl.current.deliveryData.reports[0].reportData\" type=\"ReportData\" debugger=\"false\" auto-gen=\"false\">\r\n                    <div>\r\n                      <sxy-input model=\"form.reportId\" read-only=\"true\"></sxy-input>\r\n                      <!--sxy-input model=\"form.irReportId\" read-only=\"true\"></sxy-input-->\r\n                    </div>\r\n                  </sxy-form>\r\n                  <sxy-input model=\"form.createdAt\"></sxy-input>\r\n                  <sxy-input model=\"form.updatedAt\"></sxy-input>\r\n                  <sxy-input model=\"form.irStatus\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.isModified\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.scheduledFor\" read-only=\"true\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.deliveryData.title\"></legend>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataType\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.timestamp\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataCreator.code\" label=\"SALAXY.NG1.EarningsPaymentComponent.deliveryData.deliveryDataCreator\" read-only=\"true\">\r\n                  </sxy-input>\r\n                  </sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataSender.code\" label=\"SALAXY.NG1.EarningsPaymentComponent.deliveryData.deliveryDataSender\" read-only=\"true\">\r\n                  </sxy-input>\r\n                </fieldset>\r\n              </div>\r\n            </div>\r\n            <sxy-input model=\"form.deliveryData.contactPersons\" include=\"name,responsibilityCode\"></sxy-input>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.deliveryData.deliveryDataOwner\"></legend>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.code\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.type\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.countryName\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'payer'\" heading=\"{{'SALAXY.MODEL.Payer.title' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current.deliveryData.payer\" type=\"Payer\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.payer.title\"></legend>\r\n              <sxy-input model=\"form.payerBasic.companyName\"></sxy-input>\r\n              <sxy-input model=\"form.payerBasic.missingId\" format=\"checkbox\"></sxy-input>\r\n              <sxy-input model=\"form.payerIds\"></sxy-input>\r\n              <sxy-input model=\"form.payerOther.payerTypes\"></sxy-input>\r\n              <sxy-input model=\"form.subOrgs\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.address.title\"></legend>\r\n              <sxy-input model=\"form.address.co\"></sxy-input>\r\n              <sxy-input model=\"form.address.street\"></sxy-input>\r\n              <sxy-input model=\"form.address.poBox\"></sxy-input>\r\n              <sxy-input model=\"form.address.postalCode\"></sxy-input>\r\n              <sxy-input model=\"form.address.postOffice\"></sxy-input>\r\n              <sxy-input model=\"form.address.countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.address.countryName\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.SubstitutePayer.title\"></legend>\r\n              <sxy-input model=\"form.substitutePayer.acts\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.employerName\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.employerId.type\" label=\"SALAXY.NG1.EarningsPaymentComponent.substitutePayer.employerIdType.title\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.employerId.code\" label=\"SALAXY.NG1.EarningsPaymentComponent.substitutePayer.employerIdCode.title\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.employerId.countryCode\" label=\"SALAXY.NG1.EarningsPaymentComponent.substitutePayer.employerIdCountryCode.title\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.employerId.countryName\" label=\"SALAXY.NG1.EarningsPaymentComponent.substitutePayer.employerIdCountryName.title\"></sxy-input>\r\n              <sxy-input model=\"form.substitutePayer.wageSec\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'incomeEarner'\" heading=\"{{'SALAXY.MODEL.IncomeEarner.title' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current.deliveryData.reports[0].incomeEarner\" type=\"IncomeEarner\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <fieldset>\r\n              <sxy-input model=\"form.incomeEarnerIds\" include=\"code,type,countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.missingId\" format=\"checkbox\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.companyName\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.firstName\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.lastName\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.birthDate\" format=\"date\"></sxy-input>\r\n              <sxy-input model=\"form.incomeEarnerBasic.gender\"></sxy-input>\r\n              <sxy-input model=\"form.addresses\" include=\"street,postalCode,postOffice,countryCode\"></sxy-input>\r\n              <salaxy-custom-code>\r\n                <sxy-input model=\"form.professions\" template-url=\"epr-professions.html\"></sxy-input>\r\n              </salaxy-custom-code>\r\n              <sxy-input model=\"form.employmentRegs\"></sxy-input>\r\n              <sxy-input ng-if=\"$ctrl.current.deliveryData.reports[0].incomeEarner.incomeEarnerOther != null && $ctrl.current.deliveryData.reports[0].incomeEarner.incomeEarnerOther.incomeEarnerTypes != null\" model=\"form.incomeEarnerOther.incomeEarnerTypes\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.Employment.title\"></legend>\r\n              <sxy-input model=\"form.employment.employed\"></sxy-input>\r\n              <sxy-input model=\"form.employment.employmentCode\"></sxy-input>\r\n              <sxy-input model=\"form.employment.termCode\"></sxy-input>\r\n              <sxy-input model=\"form.employment.partTime\"></sxy-input>\r\n              <sxy-input model=\"form.employment.hoursPerWeek\"></sxy-input>\r\n              <sxy-input model=\"form.employment.paymentTypes\"></sxy-input>\r\n              <sxy-input model=\"form.employment.employmentPeriods\" include=\"startDate,endDate\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL_IR.Period.title\"></legend>\r\n                    \r\n                    <sxy-input model=\"form.startDate\" format=\"date\"></sxy-input>\r\n                    <sxy-input model=\"form.endDate\" format=\"date\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n              <sxy-input model=\"form.employment.employmentEndings\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'insurances'\" heading=\"{{'SALAXY.NG1.EarningsPaymentComponent.common.insurances' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current.deliveryData.reports[0].incomeEarner\" type=\"IncomeEarner\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.PensionInsurance.title\"></legend>\r\n              <sxy-input model=\"form.pensionInsurance.pensionActCode\"></sxy-input>\r\n              <sxy-input model=\"form.pensionInsurance.pensionProvIdCode\"></sxy-input>\r\n              <sxy-input model=\"form.pensionInsurance.pensionPolicyNo\"></sxy-input>\r\n              <sxy-input ng-if=\"$ctrl.current.deliveryData.reports[0].incomeEarner.incomeEarnerOther != null && $ctrl.current.deliveryData.reports[0].incomeEarner.incomeEarnerOther.payments != null\" model=\"form.incomeEarnerOther.payments\" include=\"paymentRef,paymentSpecifier\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.AccidentInsurance.title\"></legend>\r\n              <sxy-input model=\"form.accidentInsurance.accInsPolicyNo\"></sxy-input>\r\n              <sxy-input model=\"form.accidentInsurance.accInsProvId.type\"></sxy-input>\r\n              <sxy-input model=\"form.accidentInsurance.accInsProvId.code\"></sxy-input>\r\n              <sxy-input model=\"form.accidentInsurance.accInsProvId.countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.accidentInsurance.accInsProvId.countryName\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'absenses'\" heading=\"{{'SALAXY.NG1.EarningsPaymentComponent.common.absences' | sxyTranslate}}\">\r\n        <salaxy-custom-code>\r\n          <div class=\"text-right\">\r\n            <button type=\"button\" class=\"btn btn-xs btn-primary\" ng-if=\"!$ctrl.isReadOnly\" ng-click=\"$ctrl.importAbsences()\" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.selectAbsences\"></button>\r\n          </div>\r\n        </salaxy-custom-code>\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current.deliveryData.reports[0].absence\" type=\"Absence\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <sxy-input model=\"form.absenceRepStartDate\" format=\"date\"></sxy-input>\r\n            <sxy-input model=\"form.absenceRepEndDate\" format=\"date\"></sxy-input>\r\n            <sxy-input model=\"form.unpaidAbsence.unpaidAbsencePeriods\" include=\"startDate,endDate,causeCode\">\r\n              <form>\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.MODEL.UnpaidAbsencePeriod.title\"></legend>\r\n                  <sxy-input model=\"form.startDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.endDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.causeCode\"></sxy-input>\r\n                  <sxy-input model=\"form.absenceDays\"></sxy-input>\r\n                </fieldset>\r\n              </form>\r\n            </sxy-input>\r\n            <sxy-input model=\"form.paidAbsence.paidAbsencePeriods\" include=\"startDate,endDate,causeCode\">\r\n              <form>\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.MODEL.PaidAbsencePeriod.title\"></legend>\r\n                  <sxy-input model=\"form.startDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.endDate\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.causeCode\"></sxy-input>\r\n                  <sxy-input model=\"form.absenceDays\"></sxy-input>\r\n                  <sxy-input model=\"form.absenceUntil\" format=\"date\"></sxy-input>\r\n                  <sxy-input model=\"form.amount\"></sxy-input>\r\n                  <sxy-input model=\"form.paidAbsencePeriodInfo\"></sxy-input>\r\n                  <sxy-input model=\"form.reimbApp\"></sxy-input>\r\n                </fieldset>\r\n              </form>\r\n            </sxy-input>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'calcRows'\" heading=\"{{'SALAXY.NG1.EarningsPaymentComponent.common.rows' | sxyTranslate}}\">\r\n        <div ng-if=\"$ctrl.current.deliveryData.reports.length == 1\">\r\n\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.calcRows\"></legend>\r\n            <salaxy-calc-ir-rows model=\"$ctrl.calculation\" is-read-only-forced=\"true\" ng-ref=\"$ctrl.calcController\"></salaxy-calc-ir-rows>\r\n          </fieldset>\r\n          <hr/>\r\n\r\n          <fieldset>\r\n            <legend sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.common.allRows\"></legend>\r\n            <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current.deliveryData.reports[0]\" type=\"Report\" debugger=\"false\" auto-gen=\"false\">\r\n              <div>\r\n                <fieldset>\r\n                  <sxy-input model=\"form.transactions\" read-only=\"true\" template-url=\"epr-transactions.html\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n            </sxy-form>\r\n          </fieldset>\r\n\r\n        </div>\r\n      </uib-tab>\r\n\r\n      <uib-tab index=\"'history'\" heading=\"{{'SALAXY.NG1.EarningsPaymentComponent.common.history' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irepr.json\" read-only=\"{{ $ctrl.isReadOnly }}\" model=\"$ctrl.current\" type=\"EarningsPayment\" debugger=\"false\" auto-gen=\"false\">\r\n          <div>\r\n            <fieldset>\r\n              <sxy-input model=\"form.reportLog\" read-only=\"true\" include=\"irTimestamp,eventType,reportId,irReportId,irVersion\">\r\n              </sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>\r\n<script type=\"text/ng-template\" id=\"epr-professions.html\">\r\n  <table class=\"table\">\r\n    <caption sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.professions.caption\"></caption>\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.professions.type\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.professions.code\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.professions.title\"></th>\r\n        <th class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-xs btn-primary\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.value.push({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody class=\"form-horizontal\">\r\n      <tr ng-repeat=\"item in $ctrl.value\">\r\n        <td>\r\n          <salaxy-input-enum name=\"professionType\" label-type=\"plain\" type=\"select\" read-only=\"$ctrl.getReadOnly()\" enum=\"SALAXY.ENUM_IR.ProfessionType\" require=\"true\" ng-model=\"item.type\"></salaxy-input-enum>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"$ctrl.getReadOnly() && item.type == 'statisticsFinland'\">\r\n            <salaxy-input-occupation-type style=\"display: inline-block\" require=\"true\" name=\"statCode\" ng-model=\"item.code\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-occupation-type>\r\n            <span style=\"display: inline-block\" ng-if=\"$ctrl.getReadOnly()\">{{item.code}}</span>\r\n          </div>\r\n          <salaxy-input-occupation-type ng-if=\"!$ctrl.getReadOnly() && item.type == 'statisticsFinland'\" require=\"true\" name=\"statCode\" ng-model=\"item.code\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-occupation-type>\r\n          <salaxy-input ng-if=\"item.type != 'statisticsFinland'\" require=\"true\" name=\"code\" ng-model=\"item.code\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input>\r\n        </td>\r\n        <td>\r\n          <salaxy-input name=\"title\" ng-model=\"item.title\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input>\r\n        </td>\r\n        <td class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-xs btn-danger\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</script>\r\n<script type=\"text/ng-template\" id=\"epr-transactions.html\">\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.transactions.code\"></th>\r\n        <th class=\"text-right\" sxy-text=\"SALAXY.NG1.EarningsPaymentComponent.transactions.count\"></th>\r\n        <!--th class=\"text-right\">Ansaintakauden<br> alku ja loppu</th -->\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"item in $ctrl.value\">\r\n        <td>\r\n          <salaxy-input-income-type name=\"code\" label-type=\"plain\" ng-model=\"item.transactionBasic.transactionCode\" read-only=\"true\"></salaxy-input-income-type>\r\n        </td>\r\n        <td class=\"text-right\">\r\n          <salaxy-input-number name=\"amount\" label-type=\"plain\" ng-model=\"item.transactionBasic.amount\" read-only=\"true\">\r\n        </td>\r\n        <!--td class=\"text-right\">\r\n          <span ng-repeat=\"earningPeriod in item.earningPeriods\">\r\n            {{earningPeriod.startDate | sxyDate}} - {{earningPeriod.endDate | sxyDate}}\r\n          </span>\r\n\r\n\r\n        </td-->\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</script>`);\n\n $templateCache.put(\"salaxy-components/report/IrEarningsPaymentList.html\",`<div class=\"salaxy-component salaxy-ir-earnings-payment-list\">\r\n  <salaxy-odata-table crud-controller=\"IrEarningsPaymentCrudController as $crud\" template-url=\"salaxy-components/odata/lists/IrEpr.html\" options=\"$ctrl.queryOptions\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/IrPayerSummary.html\",`<div class=\"salaxy-component salaxy salaxy-ir-payer-summary\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\" full-screen=\"true\" heading=\"SALAXY.UI_Terms.loading\" text=\"SALAXY.UI_Terms.pleaseWait\"></salaxy-spinner>\r\n  <div ng-if=\"'test' | sxyIsInRole\">\r\n    <div class=\"btn-toolbar\" role=\"toolbar\" ng-if=\"$ctrl.isReadOnly\">\r\n      <div class=\"btn-group\" role=\"group\" aria-label=\"Muokkaa\">\r\n        <button ng-click=\"$ctrl.tempShowEditInNonAdminMode = true\" type=\"button\" role=\"group\" class=\"btn btn-primary\">VAIN TEST: Muokkaa</button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" ng-if=\"!$ctrl.isReadOnly\">\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Tallenna\">\r\n      <button ng-click=\"$ctrl.save()\" type=\"button\" role=\"group\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.hasChanges\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n    <div class=\"btn-group\" role=\"group\" aria-label=\"Lähetä/mitätöi\">\r\n      <button ng-click=\"$ctrl.sendToIncomesRegister()\" type=\"button\" role=\"group\" class=\"btn btn-default\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n      <button ng-click=\"$ctrl.openSetScheduleDialog()\" type=\"button\" role=\"group\" class=\"btn btn-default\" sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.addScheduling\"></button>\r\n      <button ng-click=\"$ctrl.removeIrQueueItem()\" type=\"button\" role=\"group\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.current.scheduledFor\" sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.removeScheduling\"></button>\r\n      <button ng-click=\"$ctrl.cancelToIncomesRegister()\" type=\"button\" role=\"group\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.isCancellable\" sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.cancel\"></button>\r\n    </div>\r\n  </div>\r\n  <div class=\"form-horizontal\">\r\n    <uib-tabset active=\"currentTab\" ng-if=\"$ctrl.current\">\r\n      <uib-tab index=\"'default'\" heading=\"{{'SALAXY.NG1.PayerSummaryComponent.common.basicInfo' | sxyTranslate}}\">\r\n        <div>\r\n          <h3>\r\n            {{'SALAXY.MODEL.PayerSummary.status.title' | sxyTranslate}}: {{ \"SALAXY.ENUM_IR.PayerSummaryReportStatus.\" + $ctrl.current.status + \".label\" | sxyTranslate }}\r\n            <div class=\"label label-success pull-right\" ng-if=\"$ctrl.current.validation.isValid\">{{SALAXY.NG1.PayerSummaryComponent.common.noErrors | sxyTranslate}}</div>\r\n          </h3>\r\n          <salaxy-validation-summary api-validation=\"$ctrl.current.validation\" ng-if=\"!$ctrl.current.validation.isValid\">\r\n          </salaxy-validation-summary>\r\n          <salaxy-validation-summary api-validation=\"$ctrl.current.irErrors\" ng-if=\"!$ctrl.current.irErrors.isValid\">\r\n          </salaxy-validation-summary>\r\n        </div>\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current\" type=\"PayerSummary\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n          <div>\r\n            <div class=\"row\">\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.basicInfo\"></legend>\r\n                  <sxy-form open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current.deliveryData.reports[0].reportData\" type=\"ReportData\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n                    <div>\r\n                      <sxy-input model=\"form.reportId\" read-only=\"true\"></sxy-input>\r\n                      <!--sxy-input model=\"form.irReportId\" read-only=\"true\"></sxy-input-->\r\n                    </div>\r\n                  </sxy-form>\r\n                  <sxy-input model=\"form.createdAt\"></sxy-input>\r\n                  <sxy-input model=\"form.updatedAt\"></sxy-input>\r\n                  <sxy-input model=\"form.irStatus\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.isModified\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.scheduledFor\" read-only=\"true\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-md-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.deliveryDataTitle\"></legend>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataType\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.timestamp\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.reportDate\" format=\"date\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataCreator.code\" label=\"SALAXY.NG1.PayerSummaryComponent.common.deliveryDataCreator\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input model=\"form.deliveryData.deliveryDataSender.code\" label=\"SALAXY.NG1.PayerSummaryComponent.common.deliveryDataSender\" read-only=\"true\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n            </div>\r\n            <sxy-input model=\"form.deliveryData.contactPersons\" include=\"name,responsibilityCode\"></sxy-input>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.deliveryDataOwner\"></legend>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.code\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.type\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.deliveryData.deliveryDataOwner.countryName\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'payer'\" heading=\"{{'SALAXY.NG1.PayerSummaryComponent.common.payer' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current.deliveryData.payer\" type=\"Payer\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n          <div>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.payerTitle\"></legend>\r\n              <sxy-input model=\"form.payerBasic.companyName\"></sxy-input>\r\n              <sxy-input model=\"form.payerBasic.missingId\"></sxy-input>\r\n              <sxy-input model=\"form.payerIds\"></sxy-input>\r\n              <sxy-input model=\"form.payerOther.payerTypes\"></sxy-input>\r\n              <sxy-input model=\"form.subOrgs\"></sxy-input>\r\n              <sxy-input model=\"form.pensionInsurances\"></sxy-input>\r\n              <sxy-input model=\"form.accidentInsurances\" include=\"accInsPolicyNo\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.AccidentInsurance.title\"></legend>\r\n                    <sxy-input model=\"form.accInsPolicyNo\"></sxy-input>\r\n                    <sxy-input model=\"form.accInsProvId.code\"></sxy-input>\r\n                    <sxy-input model=\"form.accInsProvId.type\"></sxy-input>\r\n                    <sxy-input model=\"form.accInsProvId.countryCode\"></sxy-input>\r\n                    <sxy-input model=\"form.accInsProvId.countryName\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.PayerSummaryComponent.common.payerAddressTitle\"></legend>\r\n              <sxy-input model=\"form.address.co\"></sxy-input>\r\n              <sxy-input model=\"form.address.street\"></sxy-input>\r\n              <sxy-input model=\"form.address.poBox\"></sxy-input>\r\n              <sxy-input model=\"form.address.postalCode\"></sxy-input>\r\n              <sxy-input model=\"form.address.postOffice\"></sxy-input>\r\n              <sxy-input model=\"form.address.countryCode\"></sxy-input>\r\n              <sxy-input model=\"form.address.countryName\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'paymentMonth'\" heading=\"{{'SALAXY.NG1.PayerSummaryComponent.common.payerInfo' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current.deliveryData.reports[0]\" type=\"Report\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n          <div>\r\n            <fieldset>\r\n              <sxy-input model=\"form.paymentMonth.year\" read-only=\"true\"></sxy-input>\r\n              <sxy-input model=\"form.paymentMonth.month\" read-only=\"true\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <salaxy-custom-code>\r\n                <sxy-input model=\"form.transactions\" template-url=\"psr-transactions.html\"></sxy-input>\r\n              </salaxy-custom-code>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab index=\"'history'\" heading=\"{{'SALAXY.NG1.PayerSummaryComponent.common.historyTitle' | sxyTranslate}}\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current\" type=\"PayerSummary\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n          <div>\r\n            <fieldset>\r\n              <sxy-input model=\"form.reportLog\" read-only=\"true\" include=\"irTimestamp,eventType,reportId,irReportId,irVersion\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n      <uib-tab ng-if=\"$ctrl.current.info.calculationIds.length\" index=\"'calculations'\" heading=\"{{'SALAXY.NG1.PayerSummaryComponent.common.calculationsTitle' | sxyTranslate}}\">\r\n        <sxy-form ng-if=\"$ctrl.calculationsOpened || currentTab == 'calculations'\" ng-init=\"$ctrl.calculationsOpened=true\" open-api=\"salaxy-secure/schemas/irpsr.json\" model=\"$ctrl.current\" type=\"PayerSummary\" debugger=\"false\" auto-gen=\"false\" read-only=\"{{ $ctrl.isReadOnly }}\">\r\n          <div>\r\n            <fieldset>\r\n              <salaxy-custom-code>\r\n                <sxy-input model=\"form.info.calculationIds\" template-url=\"psr-calculations.html\"></sxy-input>\r\n              </salaxy-custom-code>\r\n            </fieldset>\r\n          </div>\r\n        </sxy-form>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>\r\n<script type=\"text/ng-template\" id=\"psr-transactions.html\">\r\n  <table class=\"table\">\r\n    <caption sxy-text=\"SALAXY.NG1.PayerSummaryComponent.transactions.incomeTypes\"></caption>\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.PayerSummaryComponent.transactions.incomeType\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.PayerSummaryComponent.transactions.count\"></th>\r\n        <th class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-xs btn-primary\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.value.push({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody class=\"form-horizontal\">\r\n      <tr ng-repeat=\"item in $ctrl.value\">\r\n        <td>\r\n          <salaxy-input-enum name=\"transactionCode\" label-type=\"plain\" type=\"select\" read-only=\"$ctrl.getReadOnly()\" enum=\"SALAXY.ENUM_IR.SummaryTransactionCode\" require=\"true\" ng-model=\"item.transactionBasic.summaryTransactionCode\"></salaxy-input-enum>\r\n        </td>\r\n        <td>\r\n          <salaxy-input-number ng-if=\"item.transactionBasic.summaryTransactionCode != 'noWagesPayable'\" require=\"true\" name=\"transactionAmount\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" ng-model=\"item.transactionBasic.amount\"></salaxy-input-number>\r\n          <div ng-if=\"item.transactionBasic.summaryTransactionCode == 'noWagesPayable'\" class=\"salaxy-read-only-value\" ng-init=\"item.transactionBasic.amount = null\">-</div>\r\n        </td>\r\n        <td class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-xs btn-danger\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</script>\r\n<script type=\"text/ng-template\" id=\"psr-calculations.html\">\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table table-striped\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\">\r\n              <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n            </th>\r\n            <th>\r\n              <span><span sxy-text=\"SALAXY.NG1.CalcListComponent.status.title\"></span></span><br />\r\n              <span><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\"></span></span>\r\n            </th>\r\n            <th class=\"right\">\r\n              <span><span sxy-text=\"SALAXY.NG1.CalcListComponent.salary\"></span></span><br />\r\n              <span><span sxy-text=\"SALAXY.NG1.CalcListComponent.payment\"></span></span>\r\n            </th>\r\n            <th class=\"right\" colspan=\"2\">\r\n            </th>\r\n          </tr>\r\n        </thead>\r\n        <tbody ng-controller=\"CalculationCrudController as $crud\">\r\n          <tr ng-repeat=\"id in $ctrl.value\" ng-controller=\"ODataQueryController as $odata\" ng-init=\"$odata.url='/v03/api/calculations/category/all?$filter=id eq \\\\'' + id + '\\\\'';$odata.reload()\">\r\n            <td ng-if=\"!$odata.items[0]\" colspan=\"6\"><span><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span></td>\r\n            <td ng-if=\"$odata.items[0]\" class=\"td-avatar middle\">\r\n              <salaxy-avatar avatar=\"$odata.items[0].otherPartyInfo.avatar\"></salaxy-avatar>\r\n            </td>\r\n            <td ng-if=\"$odata.items[0]\"class=\"td-name middle\">\r\n              <span ng-if=\"$odata.items[0].otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.CalcListComponent.notSelected\"></span>\r\n              <strong>{{$odata.items[0].otherPartyInfo.avatar.displayName}}</strong><br />\r\n            </td>\r\n            <td ng-if=\"$odata.items[0]\" class=\"middle\">\r\n              {{ \"SALAXY.ENUM.CalculationStatus.\" + $odata.items[0].status + \".label\" | sxyTranslate }}<br /> {{ $odata.items[0].endAt | date }}\r\n            </td>\r\n            <td ng-if=\"$odata.items[0]\" class=\"right middle\">\r\n              {{ $odata.items[0].grossSalary | currency }}<br /> {{ $odata.items[0].payment | currency }}\r\n            </td>\r\n            <td ng-if=\"$odata.items[0]\" class=\"middle\">\r\n              <a href=\"\" ng-click=\"$crud.showDetails($odata.items[0])\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><span sxy-text=\"SALAXY.UI_Terms.show\"></span>\r\n                </a>\r\n            </td>    \r\n            <td ng-if=\"$odata.items[0]\" class=\"middle\">\r\n              <a ng-href=\"{{$crud.getPdfUrl($odata.items[0])}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-default btn-block\"><span sxy-text=\"SALAXY.UI_Terms.printable\"></span></a>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n</script>`);\n\n $templateCache.put(\"salaxy-components/report/IrPayerSummaryList.html\",`<div class=\"salaxy-component salaxy-ir-payer-summary-list\">\r\n  <salaxy-odata-table crud-controller=\"IrPayerSummaryCrudController as $crud\" template-url=\"salaxy-components/odata/lists/IrPsr.html\" options=\"$ctrl.queryOptions\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/AccountNumbers.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close(null)\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.AccountNumbersComponent.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"table-responsive\" style=\"max-height: 40vh;\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-text=\"SALAXY.NG1.AccountNumbersComponent.accountNumber\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.AccountNumbersComponent.description\"></th>\r\n          <th>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"account in $ctrl.data.accounts\">\r\n          <td>\r\n            {{account.account}}\r\n          </td>\r\n          <td>\r\n            {{account.text}}\r\n          </td>\r\n          <td class=\"right\">\r\n            <button ng-disabled=\"account.isSelected\" title=\"Valitse\" class=\"btn btn-success\" type=\"button\" ng-click=\"$close(account)\" sxy-text=\"SALAXY.NG1.AccountNumbersComponent.choose\"></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n      <tfoot>\r\n      </tfoot>\r\n    </table>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$close(null)\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/CalculationReportPeriodSelection.html\",`<form name=\"periodForm\" class=\"form-horizontal\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CumulativeReportPeriodSelection.title\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-input-enum name=\"period\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.periodLabel\" options=\"{year: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionYear' | sxyTranslate), month: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionMonth' | sxyTranslate), all: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionAll' | sxyTranslate), custom: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionCustom' | sxyTranslate)}\"\r\n      ng-model=\"$ctrl.current.periodType\" type=\"radio\" required>\r\n    </salaxy-input-enum>\r\n    <salaxy-input-enum name=\"periodDateKind\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.periodDateKindLabel\" enum=\"PeriodDateKind\"\r\n      ng-model=\"$ctrl.current.periodDateKind\" type=\"radio\" required>\r\n    </salaxy-input-enum>\r\n    <salaxy-datepicker-popup name=\"refDateMonth\" placeholder=\"SALAXY.NG1.CumulativeReportPeriodSelection.month\" ng-if=\"$ctrl.current.periodType == 'month'\" format=\"MMMM\" datepicker-options=\"{ datepickerMode : 'month', minMode: 'month' }\" ng-model=\"$ctrl.current.refDate\"\r\n      label=\"SALAXY.NG1.CumulativeReportPeriodSelection.chooseMonthLabel\" required></salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"refDateYear\" placeholder=\"SALAXY.NG1.CumulativeReportPeriodSelection.year\" ng-if=\"$ctrl.current.periodType == 'year'\" format=\"yyyy\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$ctrl.current.refDate\"\r\n      label=\"SALAXY.NG1.CumulativeReportPeriodSelection.chooseYearLabel\" required></salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"refDateCustom\" ng-if=\"$ctrl.current.periodType == 'custom'\" ng-model=\"$ctrl.current.refDate\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.refDateCustomLabel\" required>\r\n    </salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"endDateCustom\" ng-if=\"$ctrl.current.periodType == 'custom'\" ng-model=\"$ctrl.current.endDate\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.endDateCustomLabel\">\r\n    </salaxy-datepicker-popup>\r\n    <salaxy-form-group name=\"Workers\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.workersLabel\">\r\n      <span ng-if=\"$ctrl.current.selectedWorkers.length\"> {{'SALAXY.NG1.CumulativeReportPeriodSelection.chosen' | sxyTranslate}}: {{ $ctrl.current.selectedWorkers.length }} </span>\r\n      <span ng-if=\"!$ctrl.current.selectedWorkers.length\"> {{'SALAXY.NG1.CumulativeReportPeriodSelection.all' | sxyTranslate}} </span>\r\n      <button type=\"button\" class=\"btn btn-xs btn-default\" ng-click=\"$ctrl.logic.showWorkerSelection($ctrl.current)\" sxy-text=\"SALAXY.NG1.CumulativeReportPeriodSelection.more\" ps=\"...\"></button>\r\n    </salaxy-form-group>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!periodForm.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/report/modals/CalculationReportSaveTemplate.html\",`<form name=\"templateForm\" class=\"form-horizontal\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CumulativeReportSaveTemplate.title\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-input-boolean disabled=\"!$ctrl.current.isEditable\" name=\"isNew\" label=\"SALAXY.NG1.CumulativeReportSaveTemplate.isNewLabel\" ng-model=\"$ctrl.current.isNew\" type=\"radio\" label-true=\"SALAXY.NG1.CumulativeReportSaveTemplate.isNewLabelTrue\" label-false=\"SALAXY.NG1.CumulativeReportSaveTemplate.isNewLabelFalse\" required>\r\n    </salaxy-input-boolean>\r\n    <salaxy-input name=\"label\" label=\"SALAXY.NG1.CumulativeReportSaveTemplate.currentLabel\" ng-model=\"$ctrl.current.label\" required></salaxy-input>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"button\" ng-if=\"!$ctrl.current.isNew\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!templateForm.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/report/modals/EntryCodes.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close(null)\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.EntryCodesComponent.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <form name=\"entryCodesForm\" class=\"form-horizontal\">\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <salaxy-input-enum label=\"SALAXY.NG1.EntryCodesComponent.entryCodeGroupLabel\" name=\"EntryCodeGroup\" ng-model=\"$ctrl.data.row.entryCodeGroup\" options=\"$ctrl.data.entryCodeGroups\" type=\"typeahead\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12\">\r\n        <salaxy-input-enum label=\"SALAXY.NG1.EntryCodesComponent.incomeTypeLabel\" ng-if=\"$ctrl.data.row.entryCodeGroup == 'incomeType'\" name=\"IncomeType\" ng-model=\"$ctrl.data.row.entryCode\" options=\"$ctrl.data.incomeTypes\" type=\"typeahead\"></salaxy-input-enum>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.EntryCodesComponent.totalTypeLabel\" ng-if=\"$ctrl.data.row.entryCodeGroup == 'totalType'\" name=\"TotalType\" ng-model=\"$ctrl.data.row.entryCode\" options=\"$ctrl.data.totalTypes\" type=\"typeahead\"></salaxy-input-enum>\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$close(null)\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$close($ctrl.data.row)\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/FivaldiPreview.html\",`<div class=\"table-responsive\">\r\n  <table class=\"table table-condensed table-striped text-small\">\r\n    <tbody>\r\n      <tr>\r\n        <th>voucherTypeId</th>\r\n        <td>{{item.preview.voucherTypeId}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>originalVoucherNumber</th>\r\n        <td>{{item.preview.originalVoucherNumber}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>voucherDate</th>\r\n        <td>{{item.preview.voucherDate}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>bookkeepingMonth</th>\r\n        <td>{{item.preview.bookkeepingMonth}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>validateEntrySum</th>\r\n        <td>{{item.preview.validateEntrySum}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>vatType</th>\r\n        <td>{{item.preview.vatType}}</td>\r\n        <td colspan=\"7\"></td>\r\n      </tr>\r\n      <tr>\r\n        <th>amount</th>\r\n        <th>accountNumber</th>\r\n        <th>balanceCode</th>\r\n        <th>dimensionValue1</th>\r\n        <th>description</th>\r\n        <th>vat.vatCode</th>\r\n        <th>vat.vatAmount</th>\r\n        <th>vat.account</th>\r\n        <th>vat.account2</th>\r\n      </tr>\r\n      <tr ng-repeat=\"entry in item.preview.voucherEntries\">\r\n        <td class=\"right\">{{ entry.amount }}</td>\r\n        <td class=\"right\">{{ entry.accountNumber}}</td>\r\n        <td class=\"right\">{{ entry.balanceCode }}</td>\r\n        <td>{{ entry.dimensionValue1 }}</td>\r\n        <td>{{ entry.description }}</td>      \r\n        <td>{{entry.vat.vatCode}}</td>\r\n        <td class=\"right\">{{entry.vat.vatAmount}}</td>\r\n        <td>{{entry.vat.account}}</td>\r\n        <td>{{entry.vat.account2}}</td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/Flags.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close(null)\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.FlagsComponent.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"table-responsive\" style=\"max-height: 40vh;\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-text=\"SALAXY.NG1.FlagsComponent.flag\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.FlagsComponent.description\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"flag in $ctrl.data.flags\">\r\n          <td>\r\n            {{flag.text}}\r\n          </td>\r\n          <td>\r\n            {{flag.description}}\r\n          </td>\r\n          <td class=\"right\">\r\n            <button title=\"{{'SALAXY.UI_Terms.select' | sxyTranslate}}\" class=\"btn\" ng-class=\"flag.isSelected ? 'btn-danger' : 'btn-success'\" type=\"button\" ng-click=\"flag.isSelected = !flag.isSelected\">\r\n              <span ng-if=\"!flag.isSelected\" sxy-text=\"SALAXY.UI_Terms.select\"></span>\r\n              <span ng-if=\"flag.isSelected\" sxy-text=\"SALAXY.UI_Terms.unselect\"></span>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n      <tfoot>\r\n      </tfoot>\r\n    </table>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$close(null)\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$close($ctrl.data.flags)\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/IncomeTypeCodeEditor.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.title\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\">\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-6 form-horizontal\">\r\n      <salaxy-input-income-type name=\"Tulolaji\"  ng-model=\"$ctrl.data.row.transactionBasic.transactionCode\" ></salaxy-input-income-type>\r\n      <salaxy-input-number name=\"Summa\" ng-model=\"$ctrl.data.row.transactionBasic.amount\"></salaxy-input-number>\r\n\r\n      <salaxy-form-group name=\"carBenefit\" label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitTypeLabel\" label-type=\"horizontal\">\r\n        <select class=\"form-control\" ng-model=\"$ctrl.data.carBenefit\" ng-model-options=\"{ getterSetter: true }\">\r\n          <option value=\"\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.noSelection\"></option>\r\n          <option value=\"limitedCarBenefit\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitLimited\"></option>\r\n          <option value=\"fullCarBenefit\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitFull\"></option>\r\n        </select>\r\n      </salaxy-form-group>\r\n\r\n      <salaxy-input-enum ng-if=\"$ctrl.data.row.carBenefit\" label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitAgeGroupCodeLabel\" name=\"ageGroupCode\" ng-model=\"$ctrl.data.row.carBenefit.ageGroupCode\" options=\"{ '': ('SALAXY.NG1.IncomeTypeCodeEditorComponent.noSelection' | sxyTranslate), 'a': 'A', 'b': 'B', 'c': 'C', 'u': 'U' }\" type=\"select\"></salaxy-input-enum>\r\n\r\n      <salaxy-input-number ng-if=\"$ctrl.data.row.carBenefit\" label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitEmissionsValueLabel\" name=\"emissionsValue\" ng-model=\"$ctrl.data.row.carBenefit.emissionsValue\" minimum=\"0\" maximum=\"100\" ></salaxy-input-number>\r\n\r\n      <salaxy-form-group name=\"kilometers\" label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.carBenefitKilometersLabel\" label-type=\"horizontal\">\r\n        <label>\r\n          {{ $ctrl.data.row.carBenefit.kilometers == null ? \"-\" : $ctrl.data.row.carBenefit.kilometers }}\r\n        </label>\r\n      </salaxy-form-group>\r\n\r\n      <salaxy-form-group name=\"mealBenefit\" label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.mealBenefitLabel\" label-type=\"horizontal\">\r\n        <select class=\"form-control\" ng-model=\"$ctrl.data.mealBenefit\" ng-model-options=\"{ getterSetter: true }\">\r\n          <option value=\"\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.noSelection\">Ei valintaa</option>\r\n          <option ng-value=\"true\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.mealBenefitTrue\">Kyllä</option>\r\n          <option ng-value=\"false\" sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.mealBenefitFalse\">Ei</option>\r\n        </select>\r\n      </salaxy-form-group>\r\n\r\n      <div class=\"form-group\" ng-if=\"!$ctrl.data.row.dailyAllowance || $ctrl.data.row.dailyAllowance.length != 1\">\r\n        <label for=\"addDailyAllowance\" class=\"col-sm-4 control-label\">\r\n              <span sxy-text=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.dailyAllowanceTypeLabel\"></span>\r\n          </label>\r\n        <div class=\"col-sm-8\">\r\n          <button type=\"button\" class=\"btn btn-block btn-success\" ng-click=\"$ctrl.data.row.dailyAllowance = ['fullDailyAllowance']\"><i class=\"fa fa-plus\"></i> {{'SALAXY.NG1.IncomeTypeCodeEditorComponent.add' | sxyTranslate}}</button>\r\n        </div>\r\n      </div>\r\n\r\n      <div ng-if=\"$ctrl.data.row.dailyAllowance && $ctrl.data.row.dailyAllowance.length == 1\">\r\n        <salaxy-input-enum label=\"SALAXY.NG1.IncomeTypeCodeEditorComponent.dailyAllowanceTypeLabel\" name=\"dailyAllowance\" ng-model=\"$ctrl.data.row.dailyAllowance[0]\" options=\"{ '': ('SALAXY.NG1.IncomeTypeCodeEditorComponent.noSelection' | sxyTranslate), 'partialDailyAllowance': ('SALAXY.NG1.IncomeTypeCodeEditorComponent.partialDailyAllowanceEnum' | sxyTranslate), 'fullDailyAllowance': ('SALAXY.NG1.IncomeTypeCodeEditorComponent.fullDailyAllowanceEnum' | sxyTranslate), 'internationalDailyAllowance': ('SALAXY.NG1.IncomeTypeCodeEditorComponent.internationalDailyAllowanceEnum' | sxyTranslate) }\"\r\n          type=\"select\"></salaxy-input-enum>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-4\"></div>\r\n          <div class=\"col-sm-8\">\r\n            <button type=\"button\" class=\"btn btn-block btn-danger\" ng-click=\"$ctrl.data.row.dailyAllowance = null\"><i class=\"fa fa-trash\"></i> {{'SALAXY.UI_Terms.delete' | sxyTranslate}}</button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n    </div>\r\n    <div class=\"col-xs-6\">\r\n      <div style=\"width: 100%; overflow: auto\">\r\n        <pre>{{ $ctrl.data.row | json }}</pre>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/IrImportAbsencesDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.IrImportAbsencesDialogComponent.heading\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <div class=\"table-responsive\">\r\n      <table class=\"table\">\r\n        <thead>\r\n          <tr>\r\n            <th>{{ \"SALAXY.NG1.IrImportAbsencesDialogComponent.absences\" | sxyTranslate }}</th>\r\n            <th class=\"right\" sxy-text=\"SALAXY.NG1.IrImportAbsencesDialogComponent.wholeAbsence\"></th>\r\n            <th class=\"right\" sxy-html=\"SALAXY.NG1.IrImportAbsencesDialogComponent.isHolidayAccrual.html\"></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr ng-repeat=\"row in $ctrl.current.periods\">\r\n            <td>\r\n              <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\">\r\n              </salaxy-avatar>\r\n              <strong>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</strong><br />\r\n              <div class=\"pull-left\" style=\"padding: 0px;\">\r\n                {{ row.isPaid ? ('SALAXY.NG1.IrImportAbsencesDialogComponent.isPaid' | sxyTranslate) : ('SALAXY.NG1.IrImportAbsencesDialogComponent.notPaid' | sxyTranslate) }}\r\n                <span ng-if=\"row.isPaid != row.isHolidayAccrual\"> {{ row.isHolidayAccrual ? ('SALAXY.NG1.IrImportAbsencesDialogComponent.isAccrual' | sxyTranslate) :\r\n                  ('SALAXY.NG1.IrImportAbsencesDialogComponent.notAccrual' | sxyTranslate) }}</span>\r\n              </div>\r\n              <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n                &nbsp;{{ row.notes }}\r\n              </div>\r\n            </td>\r\n            <td class=\"right\">\r\n              <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong><br /> {{ row.period.start | date : 'dd.MM.' }}-{{ row.period.end | date : 'dd.MM.' }}\r\n            </td>\r\n            <td class=\"right\">\r\n              <strong>{{ (row.isPaid ? 0 : row.period.daysCount) | sxyCount : \"day\" }}</strong><br />\r\n              <strong>{{ (row.isHolidayAccrual ? 0 : row.period.daysCount) | sxyCount : \"day\" }}</strong><br />\r\n            </td>\r\n            <td class=\"middle right\">\r\n              <button class=\"btn btn-xs\" type=\"button\" ng-class=\"row.selected ? 'btn-danger' : 'btn-info'\" ng-click=\"row.selected = !row.selected\">\r\n                {{ row.selected ? (\"SALAXY.UI_Terms.unselect\" | sxyTranslate) : (\"SALAXY.UI_Terms.select\" | sxyTranslate) }}\r\n              </button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div>\r\n      <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/IrRowsEditorDialog.html\",`<div class=\"modal-calc-list\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <salaxy-calc-ir-rows model=\"$ctrl.current\"></salaxy-calc-ir-rows>\r\n    <div>\r\n      <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/IrScheduleSendDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.IrScheduleSendDialogComponent.heading\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <form class=\"form-horizontal\" name=\"schedulingDialog\">\r\n      <div class=\"col-xs-12\">\r\n        <div class=\"salaxy-component salaxy-datepicker\">\r\n          <salaxy-form-group label=\"SALAXY.NG1.IrScheduleSendDialogComponent.dateLabel\" name=\"date\">\r\n            <div uib-datepicker ng-model=\"$ctrl.current.startAt\"></div>\r\n          </salaxy-form-group>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-xs-12\">\r\n        <div class=\"salaxy-component salaxy-datepicker\">\r\n          <salaxy-form-group label=\"SALAXY.NG1.IrScheduleSendDialogComponent.timeLabel\" name=\"time\">\r\n            <style>\r\n              .uib-timepicker table {\r\n                width: auto\r\n              }\r\n            </style>\r\n            <div uib-timepicker class=\"uib-timepicker\" ng-model=\"$ctrl.current.startAt\" show-meridian=\"false\"></div>\r\n          </salaxy-form-group>\r\n        </div>\r\n      </div>\r\n      <div class=\"col-xs-12\">\r\n        <salaxy-form-group label=\"SALAXY.NG1.IrScheduleSendDialogComponent.dateTimeLabel\" name=\"dateTime\">\r\n          <pre class=\"alert alert-danger\">{{$ctrl.current.startAt | sxyTime }}</pre>\r\n        </salaxy-form-group>\r\n      </div>\r\n      <div>\r\n        <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"schedulingDialog.$invalid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.send\"></button>\r\n        <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/PostAccountingData.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.UI_Terms.send\"></h2>\r\n</div>\r\n<div class=\"modal-body\" id=\"modal-body\"  style=\"max-height: calc(100vh - 300px); overflow-y: auto;\">\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th><span sxy-text=\"SALAXY.NG1.AccountingReportToolsComponent.accountingData\"></span></th>\r\n          <th><span sxy-text=\"SALAXY.NG1.AccountingReportToolsComponent.status\"></span></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat-start=\"item in $ctrl.current\">\r\n          <td><a ng-click=\"item.rowToggle = !item.rowToggle\">{{item.accountingData.employer.displayName}}/{{item.accountingData.period.start}}</a></td>\r\n          <td>\r\n            <span ng-if=\"item.error\" class=\"text-danger\">{{item.error}}</span>\r\n            <span ng-if=\"item.result\" class=\"text-success\">{{item.result}}</span>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button  class=\"btn btn-default\" ng-click=\"$ctrl.logic.postData(item)\" ng-disabled=\"item.isPosting\" type=\"button\">\r\n              <span ng-show=\"!item.isPosting\"><i class=\"fa fa-upload\"></i></span>\r\n              <span ng-show=\"item.isPosting\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.send\"></span>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n        <tr ng-if=\"item.rowToggle\" ng-repeat-end>\r\n          <td colspan=\"3\">\r\n            <ng-include src=\"$ctrl.logic.previewTemplateUrl\" ></ng-include>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/modals/SummaryReportPeriodSelection.html\",`<form name=\"periodForm\" class=\"form-horizontal\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.CumulativeReportPeriodSelection.title\"></h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-input-enum name=\"period\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.periodLabel\" options=\"{year: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionYear' | sxyTranslate), month: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionMonth' | sxyTranslate), all: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionAll' | sxyTranslate), custom: ('SALAXY.NG1.CumulativeReportPeriodSelection.enumOptionCustom' | sxyTranslate)}\"\r\n      ng-model=\"$ctrl.current.periodType\" type=\"radio\" required>\r\n    </salaxy-input-enum>\r\n    <salaxy-input-enum name=\"periodDateKind\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.periodDateKindLabel\" enum=\"PeriodDateKind\"\r\n      ng-model=\"$ctrl.current.periodDateKind\" type=\"radio\" required>\r\n    </salaxy-input-enum>\r\n    <salaxy-datepicker-popup name=\"refDateMonth\" placeholder=\"SALAXY.NG1.CumulativeReportPeriodSelection.month\" ng-if=\"$ctrl.current.periodType == 'month'\" format=\"MMMM\" datepicker-options=\"{ datepickerMode : 'month', minMode: 'month' }\" ng-model=\"$ctrl.current.refDate\"\r\n      label=\"SALAXY.NG1.CumulativeReportPeriodSelection.chooseMonthLabel\" required></salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"refDateYear\" placeholder=\"SALAXY.NG1.CumulativeReportPeriodSelection.year\" ng-if=\"$ctrl.current.periodType == 'year'\" format=\"yyyy\" datepicker-options=\"{ datepickerMode : 'year', minMode: 'year' }\" ng-model=\"$ctrl.current.refDate\"\r\n      label=\"SALAXY.NG1.CumulativeReportPeriodSelection.chooseYearLabel\" required></salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"refDateCustom\" ng-if=\"$ctrl.current.periodType == 'custom'\" ng-model=\"$ctrl.current.refDate\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.refDateCustomLabel\" required>\r\n    </salaxy-datepicker-popup>\r\n    <salaxy-datepicker-popup name=\"endDateCustom\" ng-if=\"$ctrl.current.periodType == 'custom'\" ng-model=\"$ctrl.current.endDate\" label=\"SALAXY.NG1.CumulativeReportPeriodSelection.endDateCustomLabel\">\r\n    </salaxy-datepicker-popup>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"!periodForm.$valid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.select\"></button>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/report/PayCertificate.html\",`<div class=\"salaxy-component salaxy-pay-certificate\">\r\n  <div class=\"salaxy-wizard\">\r\n    <div class=\"visible-xs visible-sm\">\r\n      <h4><span sxy-text=\"SALAXY.NG1.PayCertificateComponent.step\"></span> {{$ctrl.currentStep.number}}/{{$ctrl.steps.length}}</h4>\r\n    </div>\r\n    <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n      <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n        <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n          <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n        </span>\r\n        <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n          <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n        </a>\r\n      </div>\r\n    </div>\r\n    <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n      <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n        <span>{{ step.title | sxyTranslate}}</span>\r\n      </div>\r\n    </div>\r\n    <div class=\"wizard-content\" style=\"height: 600px; overflow-y: auto;\">\r\n      <ng-include src=\"$ctrl.currentStep.view\"></ng-include>\r\n    </div>\r\n    <div class=\"modal-footer\">\r\n      <button ng-if=\"$ctrl.step >= 2\" ng-click=\"$ctrl.goPrevious()\" ng-disabled=\"!$ctrl.canGoPrevious\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n      <button ng-if=\"($ctrl.step < $ctrl.steps.length)\" ng-click=\"$ctrl.goNext()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/PayCertificateStep1.html\",`<div>\r\n  <salaxy-employment-list mode=\"select\" selected-items=\"$ctrl.selectedWorkers\" on-list-select=\"$ctrl.selectWorker(item, value)\"></salaxy-employment-list>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/PayCertificateStep2.html\",`<div>\r\n  <div class=\"btn-toolbar spacer-bottom\" role=\"toolbar\">\r\n    <div class=\"btn-group\" role=\"group\">\r\n      <button type=\"button\" class=\"btn btn-sm btn-primary\" ng-click=\"$ctrl.selectCalculations($odata.items, 26)\" sxy-text=\"SALAXY.NG1.PayCertificateComponent.choose26Weeks\"></button>\r\n      <button type=\"button\" class=\"btn btn-sm btn-primary\" ng-click=\"$ctrl.selectCalculations($odata.items, 34)\" sxy-text=\"SALAXY.NG1.PayCertificateComponent.choose34Weeks\"></button>\r\n      <button type=\"button\" class=\"btn btn-sm btn-default\" ng-click=\"$ctrl.unselectCalculations()\" sxy-text=\"SALAXY.NG1.PayCertificateComponent.clear\"></button>\r\n    </div>\r\n  </div>\r\n  <salaxy-odata-table ng-ref=\"$odata\" selected-items=\"$ctrl.periodCalculations\" url=\"/v03/api/calculations/category/readonly\"\r\n    template-url=\"salaxy-components/odata/lists/CalculationsWithSalaryDate-select.html\" crud-controller=\"CalculationCrudController as $crud\"\r\n    options=\"{$orderby: 'salaryDate desc', $filter: 'otherId eq \\\\'' + $ctrl.worker.otherId + '\\\\' and ( status eq \\\\'paymentSucceeded\\\\' )' }\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/PayCertificateStep3.html\",`\r\n<salaxy-spinner ng-show=\"!$ctrl.validation\" heading=\"SALAXY.NG1.PayCertificateComponent.creatingPayCertificate\"></salaxy-spinner>\r\n<salaxy-validation-summary api-validation=\"$ctrl.validation\" template-url=\"pay-certificate-validation.html\">\r\n  <p class=\"text-center\">\r\n    <b sxy-text=\"SALAXY.NG1.PayCertificateComponent.payCertificateReadyForDownload\"></b>\r\n  </p>\r\n</salaxy-validation-summary>\r\n\r\n<p>&nbsp;</p>\r\n<p class=\"text-center\" ng-show=\"$ctrl.validation && $ctrl.worker && $ctrl.periodCalculations.length > 0\">{{'SALAXY.NG1.PayCertificateComponent.open' | sxyTranslate}} <a ng-href=\"{{$ctrl.getDownloadPdfUrl(true)}}\" target=\"_blank>\">{{'SALAXY.NG1.PayCertificateComponent.payCertificate' | sxyTranslate}}</a>. </p>\r\n\r\n\r\n<button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.startNew()\" sxy-text=\"SALAXY.NG1.PayCertificateComponent.createNewPayCertificate\"></button>\r\n\r\n\r\n\r\n<script type=\"text/ng-template\" id=\"pay-certificate-validation.html\">\r\n<div ng-if=\"!$ctrl.hasValidation\" ng-bind-html=\"$ctrl.loadingHtml\"></div>\r\n<div ng-if=\"$ctrl.hasValidation\">\r\n  <ng-transclude ng-if=\"$ctrl.isValid\"></ng-transclude>\r\n  <div ng-if=\"!$ctrl.isValid\" class=\"alert alert-danger\">\r\n      <h4 sxy-text=\"SALAXY.NG1.PayCertificateComponent.alertHeading\" ps=\":\"></h4>\r\n      <p style=\"display: block; font-family: monospace; white-space: pre;\" ng-repeat=\"error in $ctrl.getErrors()\">{{ error.msg }}</p>\r\n  </div>\r\n</div>\r\n</script>`);\n\n $templateCache.put(\"salaxy-components/report/ReportList.html\",`<div class=\"salaxy-component salaxy-report-list\">\r\n  <div ng-hide=\"$ctrl.getReports($ctrl.reportType).length > 0\">\r\n    <p sxy-text=\"SALAXY.NG1.ReportListComponent.noReportsToShow\" ps=\".\"></p>\r\n  </div>\r\n  <div class=\"table-responsive\" ng-show=\"$ctrl.getReports($ctrl.reportType).length > 0\">\r\n    <table class=\"table\">\r\n      <thead>\r\n        <tr>\r\n          <th style=\"width: 100px\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.ReportListComponent.report\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.ReportListComponent.links\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.ReportListComponent.reportDate\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.ReportListComponent.updated\"></th>\r\n          <th sxy-text=\"SALAXY.NG1.ReportListComponent.note\" ps=\".\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody ng-if=\"$ctrl.reportType !== 'monthlyDetails' && $ctrl.reportType !== 'yearlyDetails' && $ctrl.reportType !== 'monthlyLiikekirjuri'\" ng-controller=\"WorkerSummaryReportDisplayController as $displayCtrl\">\r\n        <tr ng-repeat=\"report in $ctrl.getReports($ctrl.reportType)\">\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate, $displayCtrl.parseWorkerID(report.htmlUrl), null)\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">{{ report.title }}</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate, $displayCtrl.parseWorkerID(report.htmlUrl), null)\">{{ report.title }} </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview && report.pdfUrl\" href=\"{{ report.pdfUrl }}\" target=\"_blank\">PDF</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate, $displayCtrl.parseWorkerID(report.htmlUrl), null)\">HTML</a>\r\n            <a ng-if=\"!report.isPreview && report.jsonUrl\" href=\"{{ report.jsonUrl }}\" target=\"_blank\">JSON</a>\r\n          </td>\r\n          <td>{{ report.reportDate | date }}</td>\r\n          <td>{{ report.updatedAt | date }}</td>\r\n          <td>\r\n            <span class=\"label label-info\" ng-if=\"report.isPreview\" sxy-text=\"SALAXY.NG1.ReportListComponent.preview\"></span>\r\n            <span class=\"label label-danger\" ng-if=\"report.isDemoData\">DEMO: demodataa</span>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n      <tbody ng-if=\"$ctrl.reportType === 'monthlyDetails' || $ctrl.reportType === 'yearlyDetails'\" ng-controller=\"SummaryReportDisplayController as $displayCtrl\">\r\n        <tr ng-repeat=\"report in $ctrl.getReports($ctrl.reportType)\">\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate,report.type)\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">{{ report.title }}</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate,report.type)\">{{ report.title }} </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview && report.pdfUrl\" href=\"{{ report.pdfUrl }}\" target=\"_blank\">PDF</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate,report.type)\">HTML</a>\r\n            <a ng-if=\"!report.isPreview && report.jsonUrl\" href=\"{{ report.jsonUrl }}\" target=\"_blank\">JSON</a>\r\n          </td>\r\n          <td>{{ report.reportDate | date }}</td>\r\n          <td>{{ report.updatedAt | date }}</td>\r\n          <td>\r\n            <span class=\"label label-info\" ng-if=\"report.isPreview\" sxy-text=\"SALAXY.NG1.ReportListComponent.preview\"></span>\r\n            <span class=\"label label-danger\" ng-if=\"report.isDemoData\">DEMO: demodataa</span>\r\n          </td>\r\n        </tr>\r\n      \r\n      </tbody>\r\n      <tbody ng-if=\"$ctrl.reportType === 'monthlyLiikekirjuri'\" ng-controller=\"AccountingReportDisplayController as $displayCtrl\">\r\n        <tr ng-repeat=\"report in $ctrl.getReports($ctrl.reportType)\">\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate,report.type, report)\">\r\n              <img ng-src=\"{{ report.thumbnail }}\" class=\"img-responsive img-thumbnail\" />\r\n            </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview\" href=\"{{ report.pdfUrl || report.htmlUrl || report.jsonUrl }}\" target=\"_blank\">{{ report.title }}</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate,report.type)\">{{ report.title }} </a>\r\n          </td>\r\n          <td>\r\n            <a ng-if=\"!report.isPreview && report.pdfUrl\" href=\"{{ report.pdfUrl }}\" target=\"_blank\">PDF</a>\r\n            <a ng-if=\"report.isPreview\" ng-click=\"$displayCtrl.display(report.reportDate)\">HTML</a>\r\n            <a ng-if=\"!report.isPreview && report.jsonUrl\" href=\"{{ report.jsonUrl }}\" target=\"_blank\">JSON</a>\r\n          </td>\r\n          <td>{{ report.reportDate | date }}</td>\r\n          <td>{{ report.updatedAt | date }}</td>\r\n          <td>\r\n            <span class=\"label label-info\" ng-if=\"report.isPreview\" sxy-text=\"SALAXY.NG1.ReportListComponent.preview\"></span>\r\n            <span class=\"label label-danger\" ng-if=\"report.isDemoData\">DEMO: demodataa</span>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/SalaryReportList.html\",`<div class=\"salaxy-component salaxy-salary-report-list\">\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode != 'panel'\" crud-controller=\"SalaryReportCrudController as $crud\" template-url=\"salaxy-components/odata/lists/SalaryReports.html\" options=\"$ctrl.queryOptions\">\r\n  </salaxy-odata-table>\r\n  <salaxy-odata-table ng-if=\"$ctrl.mode == 'panel'\" crud-controller=\"SalaryReportCrudController as $crud\" template-url=\"salaxy-components/odata/lists/SalaryReportsPanel.html\" options=\"$ctrl.panelQueryOptions\">\r\n  </salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/SummaryReport.html\",`<div class=\"salaxy-component salaxy-summary-report\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Report options\">\r\n\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n        <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguage\" ps=\":\"></span> {{$ctrl.languageText | sxyTranslate}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n        <li ng-if=\"$ctrl.reportType === 'salarySlip'\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'default'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageWorker\"></a>\r\n        </li>\r\n        <li ng-if=\"$ctrl.reportType !== 'salarySlip'\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'default'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'fi'\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'en'\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'sv'\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm pull-right-xs\" role=\"group\" aria-label=\"Pdf\">\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(true)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.print\"></span>\r\n        <i class=\"fa fa-print\" aria-hidden=\"true\"></i>\r\n      </button>\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(false)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></span>\r\n        <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <div class=\"\" ng-class=\"{'report-table-html': $ctrl.applySiteStyles}\">\r\n    <div ng-bind-html=\"$ctrl.html\" class=\"report-binder table-responsive\"></div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/SummaryReportQuery.html\",`<div class=\"salaxy-component salaxy-summary-report-query\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showPeriodSelection()\" sxy-text=\"SALAXY.NG1.CumulativeReportComponent.selectPeriod\" ps=\"...\"></button>\r\n      <button type=\"button\" class=\"btn btn-secondary\" ng-click=\"$ctrl.exportToExcel()\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.NG1.HolidayReportComponent.exportToExcel\"></span>\r\n        <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n      </button>\r\n  </div>\r\n  <p> {{ $ctrl.getQueryInfoText()}}</p>\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab index=\"'incomeReport'\" heading=\"{{'SALAXY.NG1.HolidayReportComponent.irIncomeTypeReport' | sxyTranslate}}\">\r\n      <div ng-if=\"$ctrl.getIrReportRows().length > 0 && $ctrl.getIrReportRows()[0].rows.length > 0\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th colspan=\"2\"><span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span></th>\r\n              <th ng-repeat=\"row in $ctrl.getIrReportRows()[0].rows\" class=\"right\">{{row.label}}</th>             \r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"row in $ctrl.getIrReportRows()\">\r\n              <td class=\"align-middle td-avatar\">\r\n                <salaxy-avatar class=\"clickable\" ng-click=\"$ctrl.showEditEmploymentDialog(row)\" avatar=\"row.workerAvatar\"></salaxy-avatar>\r\n              </td>\r\n              <td>{{row.workerAvatar.displayName}}</td>\r\n              <td ng-repeat=\"r in row.rows\" class=\"right\">{{ r.isCount ?  r.total  : (r.total| currency) || \"&nbsp;\"}}</td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'salaryPaymentReport'\" heading=\"{{'SALAXY.NG1.HolidayReportComponent.salaryPaymentReport' | sxyTranslate}}\">\r\n      <div ng-if=\"$ctrl.resultRows.length > 0 &&  ($ctrl.getEntrepreneurSummaryReportResults().length > 0 || $ctrl.getWorkerSummaryReportResults().length > 0)\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th></th>             \r\n              <th></th>             \r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalGrossSalary\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalRowCategory\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.benefits\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.irCode\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalTaxable\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.tax\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.pension\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.unemploymentInsurance\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.unionPayment\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.foreclosure\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.otherDeductions\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalExpenses\" | sxyTranslate}}</th>\r\n              <th class=\"right\" style=\"border-right: 1px solid #000\">{{ \"SALAXY.REPORTS.summary.table.totalWorkerPayment\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalPayment\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.palkkaus\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.service\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.socialSecurity\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.totalPensions\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.employerPension\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.unemployment\" | sxyTranslate}}</th>\r\n              <th class=\"right\">{{ \"SALAXY.REPORTS.summary.table.employerUnemployment\" | sxyTranslate}}</th>\r\n            </tr>\r\n          </thead>\r\n          <tbody ng-if=\"$ctrl.getEntrepreneurSummaryReportResults().length > 0\">\r\n            <tr >\r\n              <td colspan=\"15\" style=\"border-right: 1px solid #000\"><strong>{{\"SALAXY.REPORTS.summary.table.entrepreneurSalary\" | sxyTranslate}}</strong></td>\r\n              <td colspan=\"8\"></td>\r\n            </tr>\r\n            <tr ng-repeat=\"row in $ctrl.getEntrepreneurSummaryReportResults()\">\r\n              <td class=\"align-middle td-avatar\">\r\n                <salaxy-avatar class=\"clickable\" ng-click=\"$ctrl.showEditEmploymentDialog(row)\" avatar=\"row.avatar\"></salaxy-avatar>\r\n              </td>     \r\n              <td>{{row.avatar.displayName}}</td>\r\n              <td class=\"right\">{{(row.totalGrossSalary | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalRowCategory | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.benefits | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.irCode | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalTaxable | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.tax | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.pension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemploymentInsurance | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unionPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.foreclosure | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.otherDeductions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalExpenses | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\" style=\"border-right: 1px solid #000\">{{(row.totalWorkerPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.palkkaus | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.service | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.socialSecurity | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPensions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerPension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemployment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerUnemployment | currency) || \"&nbsp;\"}}</td>\r\n            </tr>\r\n          </tbody>\r\n          <tbody ng-if=\"$ctrl.getWorkerSummaryReportResults().length > 0\">\r\n            <tr>\r\n              <td colspan=\"15\" style=\"border-right: 1px solid #000\"><strong>{{\"SALAXY.REPORTS.summary.table.workerSalary\" | sxyTranslate}}</strong></td>\r\n              <td colspan=\"8\"></td>\r\n            </tr>\r\n            <tr ng-repeat=\"row in $ctrl.getWorkerSummaryReportResults()\">\r\n              <td class=\"align-middle td-avatar\">\r\n                <salaxy-avatar class=\"clickable\" ng-click=\"$ctrl.showEditEmploymentDialog(row)\" avatar=\"row.avatar\"></salaxy-avatar>\r\n              </td>     \r\n              <td>{{row.avatar.displayName}}</td>\r\n              <td class=\"right\">{{(row.totalGrossSalary | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalRowCategory | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.benefits | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.irCode | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalTaxable | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.tax | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.pension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemploymentInsurance | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unionPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.foreclosure | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.otherDeductions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalExpenses | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\" style=\"border-right: 1px solid #000\">{{(row.totalWorkerPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.palkkaus | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.service | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.socialSecurity | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPensions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerPension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemployment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerUnemployment | currency) || \"&nbsp;\"}}</td>\r\n            </tr>\r\n          </tbody>\r\n          <tbody ng-if=\"$ctrl.getTotalSummaryReportResults().length > 0\">           \r\n            <tr ng-repeat=\"row in $ctrl.getTotalSummaryReportResults()\">\r\n              <td class=\"right\"><strong>{{\"SALAXY.REPORTS.summary.table.total\" | sxyTranslate }}:</strong></td>\r\n              <td></td>\r\n              <td class=\"right\">{{(row.totalGrossSalary | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalRowCategory | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.benefits | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.irCode | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalTaxable | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.tax | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.pension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemploymentInsurance | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unionPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.foreclosure | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.otherDeductions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalExpenses | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\" style=\"border-right: 1px solid #000\">{{(row.totalWorkerPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPayment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.palkkaus | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.service | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.socialSecurity | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.totalPensions | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerPension | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.unemployment | currency) || \"&nbsp;\"}}</td>\r\n              <td class=\"right\">{{(row.employerUnemployment | currency) || \"&nbsp;\"}}</td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n        <small>\r\n          <small>\r\n            <div>\r\n              <span>{{\"SALAXY.REPORTS.summary.infoText.tt\" | sxyTranslate}}</span><br />\r\n              <span>{{\"SALAXY.REPORTS.summary.infoText.ta\" | sxyTranslate}}</span><br />\r\n              <span>{{\"SALAXY.REPORTS.summary.infoText.lo\" | sxyTranslate}}</span><br />\r\n            </div>\r\n          </small>\r\n        </small>\r\n      </div>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/report/WorkerSummaryReport.html\",`<div class=\"salaxy-component salaxy-summary-report\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Report options\">\r\n\r\n    <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n      <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n        <span sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguage\" ps=\":\"></span> {{$ctrl.languageText | sxyTranslate}} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n        <li ng-if=\"$ctrl.reportType === 'salarySlip'\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'default'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageWorker\"></a>\r\n        </li>\r\n        <li ng-if=\"$ctrl.reportType !== 'salarySlip'\" role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'default'\" sxy-text=\"SALAXY.NG1.CalcReportsComponent.reportLanguageCompany\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'fi'\" sxy-text=\"SALAXY.ENUM.Language.fi.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'en'\" sxy-text=\"SALAXY.ENUM.Language.en.label\"></a>\r\n        </li>\r\n        <li role=\"menuitem\">\r\n          <a href=\"\" ng-click=\"$ctrl.reportLang = 'sv'\" sxy-text=\"SALAXY.ENUM.Language.sv.label\"></a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <div class=\"btn-group btn-group-sm pull-right-xs\" role=\"group\" aria-label=\"Pdf\">\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(true)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.print\"></span>\r\n        <i class=\"fa fa-print\" aria-hidden=\"true\"></i>\r\n      </button>\r\n      <button sxy-if-role=\"!anon\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showDownloadDialog(false)\">\r\n        <span class=\"hidden-sm hidden-xs\" sxy-text=\"SALAXY.UI_Terms.downloadPdf\"></span>\r\n        <i class=\"fa fa-file-pdf-o\" aria-hidden=\"true\"></i>\r\n      </button>\r\n    </div>\r\n  </div>\r\n  <div class=\"\" ng-class=\"{'report-table-html': $ctrl.applySiteStyles}\">\r\n    <div ng-bind-html=\"$ctrl.html\" class=\"report-binder table-responsive\"></div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/Accountant.html\",`<div class=\"content settings\">\r\n  <div class=\"panel panel-default accountant\" ng-if=\"$ctrl.accountant\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.AccountantComponent.title\"></span> <i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n      <p>\r\n        <small sxy-text=\"SALAXY.NG1.AccountantComponent.intro2\"></small>\r\n      </p>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <fieldset>\r\n            <div class=\"container-fixed salaxy-component salaxy-accountant-info\">\r\n              <div>\r\n                <table>\r\n                  <tr ng-if=\"$ctrl.accountant.info.avatar.displayName\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.name\" ps=\":\"></td>\r\n                    <td>\r\n                      <salaxy-avatar style=\"font-size: 20px; margin-right: 12px;\" avatar=\"$ctrl.accountant.info.avatar\"></salaxy-avatar><strong>{{ $ctrl.accountant.info.avatar.displayName}}<strong></td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.officialId\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.officialId\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.officialId}}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.email\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.email\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.email }}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.telephone\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.phone\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.telephone }}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner' || $ctrl.accountant.type == 'unlinkedPrimaryPartner' || $ctrl.accountant.type == 'unlinkedAccountingOnly'\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.accountantType\" ps=\":\"></td>\r\n                    <td>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'primaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.primaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'pendingPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.pendingPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedAccountingOnly'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedAccountingOnly\"></span>\r\n                    </td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountantMainType == 'none' && !($ctrl.accountant.info.avatar.firstName || $ctrl.accountant.info.avatar.lastName || $ctrl.accountant.info.email || $ctrl.accountant.info.telephone)\">\r\n                    <td colspan=\"2\">\r\n                      <span sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.noAccountantEnum\"></span>\r\n                    </td>\r\n                  </tr>\r\n                </table>\r\n              </div>\r\n            </div>\r\n\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <button class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.showEdit($ctrl.removalDisabled)\" sxy-text=\"SALAXY.UI_Terms.edit\"></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountantEmails.html\",`<div class=\"content settings\">\r\n  <div class=\"panel panel-default accountant\" ng-if=\"$ctrl.accountant\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.AccountantComponent.title\"></span>\r\n      </h2>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <form name=\"companyAccountantForm\" class=\"form-horizontal\">\r\n          <div class=\"col-xs-12\">\r\n            <fieldset ng-if=\"$ctrl.accountantMainType != 'none'\">\r\n              <div  class=\"container-fixed salaxy-component salaxy-accountant-info\">\r\n                <div class=\"table-responsive\">\r\n                  <table class=\"table\">\r\n                    <tr>\r\n                      <th sxy-text=\"SALAXY.NG1.AccountantComponent.name\" ps=\":\"></th>\r\n                      <td>\r\n                        <salaxy-avatar style=\"font-size: 20px; margin-right: 12px;\" avatar=\"$ctrl.accountant.info.avatar\"></salaxy-avatar><strong>{{ $ctrl.accountant.info.avatar.displayName}}<strong></td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.officialId\">\r\n                    <th sxy-text=\"SALAXY.NG1.AccountantComponent.officialId\" ps=\":\"></th>\r\n                    <td>{{ $ctrl.accountant.info.officialId}}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner'\">\r\n                    <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.companyAccountantForm.accountingDataEmail\" ps=\":\"></th>\r\n                    <td>\r\n                      <salaxy-input-boolean ng-model=\"$ctrl.accountant.info.accountantEmailsOrdered\" type=\"checkbox\" name=\"order\" label=\"\" label-type=\"plain\">\r\n                        </salaxy-input-boolean>\r\n                    </td>\r\n                  </tr>\r\n      \r\n                  <tr ng-if=\"$ctrl.accountant.type == 'unlinkedAccountingOnly' || !$ctrl.accountant.info.avatar.id || $ctrl.accountant.type == 'pendingPrimaryPartner' || $ctrl.accountant.type == 'primaryPartner'\">\r\n                    <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.email\" ps=\":\"></th>\r\n                    <td>\r\n                      <salaxy-input name=\"email\" label=\"\" read-only=\"($ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner') && !$ctrl.accountant.info.accountantEmailsOrdered\" require=\"!(($ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner') && !$ctrl.accountant.info.accountantEmailsOrdered)\"\r\n                        label-type=\"plain\" sxy-email ng-model=\"$ctrl.accountant.info.email\"></salaxy-input>\r\n                    </td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.type == 'unlinkedAccountingOnly' || !$ctrl.accountant.info.avatar.id || $ctrl.accountant.type == 'pendingPrimaryPartner' || $ctrl.accountant.type == 'primaryPartner'\">\r\n                    <th sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.telephone\" ps=\":\"></th>\r\n                    <td>\r\n                      <salaxy-input name=\"telephone\" label=\"\" read-only=\"($ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner') && !$ctrl.accountant.info.accountantEmailsOrdered\" require=\"!(($ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner') && !$ctrl.accountant.info.accountantEmailsOrdered)\"\r\n                        label-type=\"plain\" sxy-mobile-phone ng-model=\"$ctrl.accountant.info.telephone\"></salaxy-input>\r\n                    </td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner' || $ctrl.accountant.type == 'unlinkedPrimaryPartner' || $ctrl.accountant.type == 'unlinkedAccountingOnly'\">\r\n                    <th sxy-text=\"SALAXY.NG1.AccountantComponent.accountantType\" ps=\":\"></th>\r\n                    <td>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'primaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.primaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'pendingPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.pendingPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedAccountingOnly'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedAccountingOnly\"></span>\r\n                    </td>\r\n                  </tr>\r\n                </table>\r\n              </div>\r\n            </div>\r\n          </fieldset>\r\n          <fieldset ng-if=\"$ctrl.accountantMainType == 'none'\">\r\n            <salaxy-input name=\"firstName\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.firstName\" ng-model=\"$ctrl.accountant.info.avatar.firstName\"></salaxy-input>\r\n            <salaxy-input name=\"lastName\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.lastName\"  ng-model=\"$ctrl.accountant.info.avatar.lastName\"></salaxy-input>\r\n            <salaxy-input name=\"email\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.email\"  sxy-email ng-model=\"$ctrl.accountant.info.email\"></salaxy-input>\r\n            <salaxy-input name=\"telephone\" label=\"SALAXY.NG1.AccountantSelectionComponent.personAccountantForm.telephone\"  sxy-mobile-phone ng-model=\"$ctrl.accountant.info.telephone\"></salaxy-input>\r\n          </fieldset>\r\n        </div>\r\n      </form>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <div class=\"text-right\">\r\n            <a ng-if=\"$ctrl.accountantMainType == 'none'\" class=\"btn btn-default\" href=\"#/settings/accountants\" sxy-text=\"SALAXY.NG1.AccountantComponent.addPrimaryPartner\"></a>\r\n            <button ng-disabled=\"!companyAccountantForm.$valid\" class=\"btn btn-primary\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountantInfo.html\",`<div class=\"content settings\">\r\n  <div class=\"panel panel-default accountant\" ng-if=\"$ctrl.accountant\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.AccountantComponent.title\"></span>\r\n      </h2>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <fieldset>\r\n            <div class=\"container-fixed salaxy-component salaxy-accountant-info\">\r\n              <div >\r\n                <table>\r\n                  <tr ng-if=\"$ctrl.accountant.info.avatar.displayName\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.name\" ps=\":\"></td>\r\n                    <td>\r\n                      <salaxy-avatar style=\"font-size: 20px; margin-right: 12px;\" avatar=\"$ctrl.accountant.info.avatar\"></salaxy-avatar><strong>{{ $ctrl.accountant.info.avatar.displayName}}<strong>\r\n                    </td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.officialId\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.officialId\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.officialId}}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.email\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.email\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.email }}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.info.telephone\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.phone\" ps=\":\"></td>\r\n                    <td>{{ $ctrl.accountant.info.telephone }}</td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountant.type == 'primaryPartner' || $ctrl.accountant.type == 'pendingPrimaryPartner' || $ctrl.accountant.type == 'unlinkedPrimaryPartner' || $ctrl.accountant.type == 'unlinkedAccountingOnly'\">\r\n                    <td sxy-text=\"SALAXY.NG1.AccountantComponent.accountantType\" ps=\":\"></td>\r\n                    <td>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'primaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.primaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'pendingPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.pendingPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedPrimaryPartner'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedPrimaryPartner\"></span>\r\n                      <span ng-if=\"$ctrl.accountant.type == 'unlinkedAccountingOnly'\" sxy-text=\"SALAXY.NG1.AccountantComponent.unlinkedAccountingOnly\"></span>\r\n                    </td>\r\n                  </tr>\r\n                  <tr ng-if=\"$ctrl.accountantMainType == 'none' && !($ctrl.accountant.info.avatar.firstName || $ctrl.accountant.info.avatar.lastName || $ctrl.accountant.info.email || $ctrl.accountant.info.telephone)\">\r\n                    <td colspan=\"2\">\r\n                      <span sxy-text=\"SALAXY.NG1.AccountantSelectionComponent.noAccountantEnum\"></span>\r\n                    </td>\r\n                  </tr>\r\n                </table>\r\n              </div>\r\n            </div>\r\n\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\" ng-if=\"$ctrl.accountantMainType == 'none'\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <div class=\"text-right\">\r\n            <a class=\"btn btn-default\" href=\"#/settings/accountants\" sxy-text=\"SALAXY.NG1.AccountantComponent.addPrimaryPartner\"></a>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingSettings.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\">\r\n  <div class=\"panel accounting panel-default\">\r\n    <div>\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2 sxy-text=\"SALAXY.MODEL.AccountingSettings.title\"></h2>\r\n        <p><small sxy-text=\"SALAXY.MODEL.AccountingSettings.descr\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n\r\n          <sxy-form ng-ref=\"$frm\" open-api=\"salaxy-secure/schemas/v02.json\" type=\"CompanyAccountSettings\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\" read-only=\"{{!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting}}\">\r\n            <div class=\"col-xs-12 form-horizontal\">\r\n              <fieldset>\r\n                <salaxy-input-enum  read-only=\"$frm.readOnly == 'true'\" type=\"typeahead\" name=\"options_type\" ng-model=\"$ctrl.current.accounting.defaultTargetId\" options=\"$ctrl.getSelectableAccountingTargets()\" disable-cache=\"true\"\r\n                  label=\"SALAXY.MODEL.AccountingSettings.defaultTargetId.title\"></salaxy-input-enum>\r\n                \r\n                <salaxy-form-group name=\"targets\" label=\"SALAXY.MODEL.AccountingSettings.targets.title\">\r\n                  <div>\r\n                    <span>\r\n                        <i ng-click=\"$ctrl.showTargets = !$ctrl.showTargets\" class=\"clickable fa\" ng-class=\"$frm.readOnly == 'true' ? 'fa-info' : 'fa-pencil'\"></i>\r\n                    </span>\r\n                  </div>\r\n                </salaxy-form-group>\r\n                  \r\n                 \r\n                  <sxy-input ng-if=\"$ctrl.showTargets\" template-url=\"salaxy-components/sxy-form/custom-templates/array-accounting-targets.html\" model=\"form.accounting.targets\">\r\n                    <form>\r\n                      <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"CompanySettingsController as $companySettingsCtrl\" ng-init=\"$ctrl.logic.isReadOnly = true\">\r\n                        <salaxy-odata-table crud-controller=\"AccountingTargetCrudController as $crud\" template-url=\"salaxy-components/odata/lists/AccountingTargetSelect.html\" selected-items=\"$ctrl.selectedItems\" on-list-select=\"$companySettingsCtrl.onAccountingTargetSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                        </salaxy-odata-table>\r\n                      </fieldset>\r\n                      <fieldset ng-show=\"$ctrl.logic.showDelete\" ng-init=\"$ctrl.logic.isReadOnly = false\">\r\n                        <salaxy-input-enum disabled=\"false\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsvFormat\" ng-model=\"$ctrl.current.format\"\r\n                        options=\"{\r\n                          '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                          '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                          '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                          'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                          '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                          '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                          '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                          'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                          'ba271dac-dd63-4036-9d70-053a09ca4d9e' :'Visma Netvisor',\r\n                          '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                          'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                          'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                          '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                          '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                        }\">\r\n                      </salaxy-input-enum>\r\n                        <sxy-input model=\"form.method\" read-only=\"false\"></sxy-input>\r\n                        <salaxy-input-enum disabled=\"false\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.availableMethods.title\" name=\"availableMethods\" type=\"multi-select\" ng-model=\"$ctrl.current.availableMethods\"></salaxy-input-enum>\r\n                      </fieldset>\r\n                    </form>\r\n                  </sxy-input>\r\n\r\n                <sxy-input model=\"form.accounting.defaultPeriodDateKind\"></sxy-input>\r\n                <salaxy-input-enum ng-if=\"$ctrl.defaultAccountingTarget\"\r\n                  read-only=\"$frm.readOnly == 'true'\" type=\"select\" name=\"method\"\r\n                  ng-model=\"$ctrl.defaultAccountingTarget.method\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.method.title\"></salaxy-input-enum>\r\n              </fieldset>\r\n              <fieldset>\r\n                <legend sxy-text=\"SALAXY.MODEL.AccountingSettings.reportDelivery.title\"></legend>\r\n                <sxy-input read-only=\"false\" format=\"checkbox\" model=\"form.accounting.reportDelivery.isEnabled\"></sxy-input>\r\n                <sxy-input read-only=\"false\"  format=\"email\" model=\"form.accounting.reportDelivery.address\" ng-if=\"$ctrl.current.accounting.reportDelivery.isEnabled\"></sxy-input>\r\n              </fieldset>\r\n              <fieldset>\r\n                <legend sxy-text=\"SALAXY.MODEL.AccountingSettings.accountantReportDelivery.title\"></legend>\r\n                <sxy-input read-only=\"false\" format=\"checkbox\" model=\"form.accounting.accountantReportDelivery.isEnabled\"></sxy-input>\r\n                <sxy-input read-only=\"false\"  format=\"email\" model=\"form.accounting.accountantReportDelivery.address\" ng-if=\"$ctrl.current.accounting.accountantReportDelivery.isEnabled\"></sxy-input>\r\n           \r\n              </fieldset>\r\n            </div>\r\n          </sxy-form>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button type=\"submit\" ng-disabled=\"!$frm.ngForm.$valid || $ctrl.isSaving('all')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('all')\">\r\n              <span ng-if=\"$ctrl.isSaving('all')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span sxy-text=\"SALAXY.UI_Terms.save\"></span>\r\n            </button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetDetails.html\",`<div class=\"salaxy-component salaxy-accounting-target-editor\">\r\n  <div ng-if=\"!$ctrl.current\">\r\n    <salaxy-spinner heading=\"SALAXY.UI_Terms.loading\"></salaxy-spinner>\r\n  </div>\r\n  <div class=\"row\" ng-if=\"$ctrl.current\">\r\n    <div class=\"col-xs-12 accounting-target-info-col\">\r\n      <div class=\"row spacer-bottom\">\r\n        <div class=\"col-xs-12\">\r\n          <div class=\"btn-toolbar pull-right\" role=\"toolbar\" aria-label=\"Tilit\">\r\n            <div class=\"btn-group\" role=\"group\" aria-label=\"Save and load\">\r\n              <button class=\"btn btn-danger\" ng-disabled=\"$ctrl.isReadOnly\" ng-click=\"$ctrl.delete()\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n              <button class=\"btn btn-default\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n              <button class=\"btn btn-primary\" ng-disabled=\"!$ctrl.hasChanges && !$ctrl.isNew()\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n            </div>\r\n          </div>\r\n          <salaxy-avatar class=\"pull-left\" style=\"font-size: 58px; margin-right: 15px; margin-top: -15px;\" avatar=\"$ctrl.current.info.target.avatar\"></salaxy-avatar>\r\n          <h2>{{ $ctrl.current.info.target.avatar.displayName}}</h2>\r\n\r\n          <fieldset class=\"form-horizontal\">\r\n            <legend sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.accountingTargetLegend\"></legend>\r\n            <div ng-if=\"$ctrl.template\">\r\n              <div class=\"row\">\r\n                <div class=\"col-sm-4\">\r\n                  <salaxy-input read-only=\"true\" name=\"template_name\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.name\"\r\n                    ng-model=\"$ctrl.template.info.target.avatar.displayName\"></salaxy-input>\r\n                  <salaxy-input read-only=\"true\" name=\"template_id\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.id\" ng-model=\"$ctrl.template.id\"></salaxy-input>\r\n                </div>\r\n                <div class=\"col-sm-4\">\r\n                  <salaxy-input-enum read-only=\"true\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsv\" ng-model=\"$ctrl.template.info.format\" options=\"{\r\n                    '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                    '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                    '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                    'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                    '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                    '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                    '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                    'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                    'ba271dac-dd63-4036-9d70-053a09ca4d9e': 'Visma Netvisor',\r\n                    '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                    'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                    'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                    '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                    '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                  }\"></salaxy-input-enum>\r\n                </div>\r\n                <div class=\"col-sm-4\">\r\n                  <salaxy-datepicker read-only=\"true\" name=\"createdAt\" ng-model=\"$ctrl.template.createdAt\" label=\"SALAXY.UI_Terms.created\"></salaxy-datepicker>\r\n                  <salaxy-datepicker read-only=\"true\" name=\"updatedAt\" ng-model=\"$ctrl.template.updatedAt\" label=\"SALAXY.UI_Terms.updated\"></salaxy-datepicker>\r\n                </div>\r\n              </div>\r\n            </div>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <uib-tabset active=\"$ctrl.currentTab\">\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.overview' | sxyTranslate}}\" index=\"'overview'\">\r\n        <form name=\"ruleSetForm\" class=\"form-horizontal\">\r\n          <div class=\"row\">\r\n            <div class=\"col-xs-6\">\r\n              <fieldset>\r\n                <div ng-if=\"$ctrl.isReadOnly\" class=\"alert alert-danger\">\r\n                  <span class=\"text-danger\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.readOnly\"></span>\r\n                </div>\r\n                <salaxy-input disabled=\"$ctrl.isReadOnly\" name=\"ruleSetName\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.name\"\r\n                  ng-model=\"$ctrl.current.info.target.avatar.displayName\"></salaxy-input>\r\n                  <salaxy-input disabled=\"$ctrl.isReadOnly\" name=\"logoUrl\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.logoUrl\"\r\n                  ng-model=\"$ctrl.current.info.target.avatar.url\"></salaxy-input>\r\n                <salaxy-input-enum disabled=\"$ctrl.isReadOnly\" name=\"channel\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.channel\" ng-model=\"$ctrl.current.info.channel\" enum=\"AccountingChannel\">\r\n                </salaxy-input-enum>\r\n                <salaxy-input-enum disabled=\"$ctrl.isReadOnly\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsvFormat\" ng-model=\"$ctrl.current.info.format\"\r\n                  options=\"{\r\n                    '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                    '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                    '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                    'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                    '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                    '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                    '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                    'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                    'ba271dac-dd63-4036-9d70-053a09ca4d9e' :'Visma Netvisor',\r\n                    '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                    'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                    'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                    '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                    '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                  }\">\r\n                </salaxy-input-enum>\r\n                <salaxy-form-group name=\"method\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.exportMethod\" label-type=\"horizontal\">\r\n                  <select class=\"form-control\" ng-model=\"$ctrl.current.info.method\">\r\n                    <option ng-repeat=\"method in $ctrl.current.info.availableMethods\"ng-value=\"method\">{{'SALAXY.ENUM.ExportMethod.' + method + \".label\" | sxyTranslate}}</option>\r\n                  </select>\r\n                </salaxy-form-group>\r\n                <salaxy-input-enum label=\"SALAXY.NG1.AccountingTargetDetailsComponent.exportMethods\" disabled=\"false\" enum=\"ExportMethod\"\r\n                  name=\"availableMethods\" type=\"multi-select\" ng-model=\"$ctrl.current.info.availableMethods\"></salaxy-input-enum>\r\n              </fieldset>\r\n            </div>\r\n          </div>\r\n        </form>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.chartOfAccounts' | sxyTranslate}}\" index=\"'coa'\">\r\n        <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Data options\">\r\n          <div class=\"btn-group\" role=\"group\">\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.pasteFromClipboard()\">\r\n              <span><span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.pasteFromClipboard\"></span> <i class=\"fa fa-clipboard\"></i></span></button>\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" type=\"button\" class=\"btn btn-default\" ngf-select=\"$ctrl.readFile($file)\" ngf-multiple=\"false\" ngf-max-size=\"10MB\">\r\n              <span><span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.readFile\" ps=\"...\"></span><i class=\"fa fa-file-text-o\"></i></span>\r\n            </button>\r\n          </div>\r\n        </div>\r\n        <div class=\"table-responsive\" ng-if=\"$ctrl.hasTargetCoA\">\r\n          <table class=\"table table-condensed\">\r\n            <thead>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.accountNumber\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.name\"></th>\r\n                <th class=\"right\">\r\n                  <button title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addTargetCoaAccount(false)\"\r\n                    sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n                </th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"account in $ctrl.current.ruleSet.targetCoA\">\r\n                <td>\r\n                  <salaxy-input read-only=\"$ctrl.isReadOnly\" name=\"{{'accountAccount'+$index}}\" ng-change=\"$ctrl.updateRuleSetAccount(account)\" ng-model=\"account.account\" label-type=\"plain\"></salaxy-input>\r\n                </td>\r\n                <td>\r\n                  <salaxy-input read-only=\"$ctrl.isReadOnly\" name=\"{{'accountText'+$index}}\" ng-change=\"$ctrl.updateRuleSetAccount(account)\" ng-model=\"account.text\"\r\n                    label-type=\"plain\"></salaxy-input>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <button title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\" class=\"btn btn-transparent\" type=\"button\" ng-if=\"!account.isReadOnly\"\r\n                    ng-click=\"$ctrl.removeAccount(account, true)\">\r\n                    <i class=\"fa fa-trash\"></i>\r\n                  </button>\r\n                </td>\r\n              </tr>\r\n              <tr ng-if=\"$ctrl.hasTargetCoA\">\r\n                <td></td>\r\n                <td></td>\r\n                <td class=\"right\">\r\n                  <button title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addTargetCoaAccount(true)\"\r\n                    sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n            <tfoot>\r\n            </tfoot>\r\n          </table>\r\n        </div>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.usedAccounts' | sxyTranslate}}\" index=\"'accounts'\" ng-click=\"$ctrl.sortRulesetAccounts()\">\r\n        <div class=\"btn-group btn-group-sm\" uib-dropdown>\r\n          <button id=\"single-button2\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle uib-dropdown-toggle ng-disabled=\"disabled\">\r\n            <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.filters.rowsToShow\" ps=\":\"></span> {{$ctrl.accountFilterText | sxyTranslate}} <span class=\"caret\"></span>\r\n          </button>\r\n          <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button2\">\r\n            <li role=\"menuitem\">\r\n              <a href=\"\" ng-click=\"$ctrl.accountFilter = 'all'\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.filters.all\"></a>\r\n            </li>\r\n            <li role=\"menuitem\">\r\n              <a href=\"\" ng-click=\"$ctrl.accountFilter = 'includedAndEnabled'\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.filters.includedAndEnabled\"></a>\r\n            </li>\r\n            <li role=\"menuitem\">\r\n              <a href=\"\" ng-click=\"$ctrl.accountFilter = 'error'\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.filters.error\"></a>\r\n            </li>\r\n          </ul>\r\n        </div>\r\n        <button class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.showDistinct = !$ctrl.showDistinct\">{{$ctrl.showDistinct ?\r\n          ('SALAXY.NG1.AccountingTargetDetailsComponent.filters.showNormal' | sxyTranslate) : \"SALAXY.NG1.AccountingTargetDetailsComponent.filters.showDistinct\" |\r\n          sxyTranslate}}</button>\r\n          <div ng-if=\"$ctrl.showDistinct && !$ctrl.distinctAccounts.length || !$ctrl.showDistinct && !$ctrl.filteredAccounts.length\">\r\n            <p sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.filters.noRows\"></p>\r\n          </div>\r\n        <div class=\"table-responsive\" ng-if=\"!$ctrl.showDistinct && $ctrl.filteredAccounts.length\">\r\n          <table class=\"table table-condensed\">\r\n            <thead>\r\n              <tr>\r\n                <th></th>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.accountNumber\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.name\"></th>\r\n                <th class=\"right\">\r\n                  <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\"\r\n                    ng-click=\"$ctrl.addAccount(false)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n                </th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"account in $ctrl.filteredAccounts\">\r\n                <td class=\"middle\">\r\n                  <div class=\"text-center\" ng-if=\"!$ctrl.isValidAccount(account)\" data-toggle=\"tooltip\" data-placement=\"top\"\r\n                    title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.noAccountNumberFound' | sxyTranslate}}\">\r\n                    <i class=\"fa fa-exclamation-circle text-danger\"></i>\r\n                  </div>\r\n                </td>\r\n                <td>\r\n                  <salaxy-input read-only=\"$ctrl.isReadOnly\" name=\"{{'accountAccount'+$index}}\" ng-change=\"$ctrl.updateAccountToMatchTargetCoa(account)\" ng-model=\"account.account\" label-type=\"plain\"></salaxy-input>\r\n                </td>\r\n                <td>\r\n                  <salaxy-input read-only=\"true\" name=\"{{'accountText'+$index}}\" ng-model=\"account.text\" label-type=\"plain\"></salaxy-input>\r\n                </td>\r\n                <td class=\"right\">\r\n                  <button title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\" class=\"btn btn-transparent\" type=\"button\" ng-if=\"!account.isReadOnly\"\r\n                    ng-click=\"$ctrl.removeAccount(account)\">\r\n                    <i class=\"fa fa-trash\"></i>\r\n                  </button>\r\n                  <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.changeAccount' | sxyTranslate}}\" class=\"btn btn-transparent\"\r\n                    type=\"button\" ng-click=\"$ctrl.selectTargetAccount(account)\" ng-if=\"$ctrl.hasTargetCoA\">\r\n                    <i class=\"fa fa-pencil\"></i>\r\n                  </button>\r\n                </td>\r\n              </tr>\r\n              <tr ng-if=\"$ctrl.current.ruleSet.accounts.length\">\r\n                <td></td>\r\n                <td></td>\r\n                <td></td>\r\n                <td class=\"right\">\r\n                  <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\"\r\n                    ng-click=\"$ctrl.addAccount(true)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n                </td>\r\n              </tr>\r\n            </tbody>\r\n            <tfoot>\r\n            </tfoot>\r\n          </table>\r\n        </div>\r\n        <div class=\"table-responsive\" ng-if=\"$ctrl.showDistinct && $ctrl.distinctAccounts.length\">\r\n          <table class=\"table table-condensed\">\r\n            <thead>\r\n              <tr>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.accountNumber\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.name\"></th>\r\n                <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.ruleCount\"></th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"account in $ctrl.distinctAccounts\">\r\n                <td>\r\n                  <salaxy-input read-only=\"true\" name=\"{{'accountAccount'+$index}}\" ng-model=\"account.account\" label-type=\"plain\"></salaxy-input>\r\n                </td>\r\n                <td>\r\n                  <salaxy-input read-only=\"true\" name=\"{{'accountText'+$index}}\" ng-model=\"account.text\" label-type=\"plain\">\r\n                  </salaxy-input>\r\n                </td>\r\n                <td>{{$ctrl.getRulesCount(account.account)}}</td>\r\n              </tr>\r\n            </tbody>\r\n            <tfoot>\r\n            </tfoot>\r\n          </table>\r\n        </div>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.guidelines' | sxyTranslate}}\" index=\"'guidelines'\">\r\n        <div sxy-html=\"SALAXY.NG1.AccountingTargetDetailsComponent.guidelinesInfo.html\"></div>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.rules' | sxyTranslate}}\" index=\"'rules'\">\r\n        <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.accounts' | sxyTranslate}}\">\r\n          <div class=\"btn-group\" role=\"group\" aria-label=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.sorting' | sxyTranslate}}\" ng-init=\"$ctrl.ruleViewSorting = 'default'\">\r\n            <label class=\"btn btn-default\" ng-model=\"$ctrl.ruleViewSorting\" uib-btn-radio=\"'default'\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.sortDefault\"></label>\r\n            <label class=\"btn btn-default\" ng-model=\"$ctrl.ruleViewSorting\" uib-btn-radio=\"'byAccountPairs'\"\r\n              sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.sortByAccountPairs\"></label>\r\n            <label class=\"btn btn-default\" ng-model=\"$ctrl.ruleViewSorting\" uib-btn-radio=\"'byAccount'\"\r\n              sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.sortByAccount\"></label>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"$ctrl.currentTab == 'rules'\">\r\n          <ng-include\r\n            src=\"'salaxy-components/settings/AccountingTargetEditorRulesTable' + ($ctrl.ruleViewSorting == 'byAccountPairs' ? 2 : $ctrl.ruleViewSorting == 'byAccount' ? 3 : 1) + '.html'\">\r\n          </ng-include>\r\n        </div>\r\n      </uib-tab>\r\n      <uib-tab heading=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.tabs.accountingQuery' | sxyTranslate}}\" index=\"'accountingQuery'\">\r\n        <ng-include src=\"'salaxy-components/settings/AccountingTargetEditorQuery.html'\"></ng-include>\r\n      </uib-tab>\r\n      <uib-tab heading=\"Debugger\" index=\"'debugger'\" ng-if=\"'test' | sxyIsInRole\">\r\n        <salaxy-json-formatter json=\"$ctrl.current\"></salaxy-json-formatter>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetEditorQuery.html\",`<div class=\"salaxy-component salaxy-accounting-report-query\" ng-controller=\"AccountingReportQueryController as $ctrlQuery\" ng-init=\"$ctrlQuery.queryType = 'selectionQuery'\">\r\n  <form name=\"queryForm\" class=\"form-horizontal\">\r\n    <fieldset>\r\n      <div class=\"col col-md-6\">\r\n        <p>\r\n          <span class=\"label label-primary\" ng-if=\"$ctrlQuery.calculations.length\">\r\n            <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.selectedAmount\" ps=\":\"></span>{{ $ctrlQuery.calculations.length }}\r\n          </span>\r\n        </p>\r\n        <div class=\"btn-toolbar\" role=\"toolbar\">\r\n          <button class=\"btn btn-default\" ng-click=\"$ctrlQuery.addCalcs('draft')\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.addDraftBtn\"></button>\r\n        </div>\r\n      </div>\r\n    </fieldset>\r\n    <div class=\"col col-md-12\">\r\n      <div ng-if=\"$ctrlQuery.calculations.length\" class=\"table-responsive salaxy-odata-table\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th colspan=\"2\">\r\n                <span sxy-text=\"SALAXY.NG1_Other.Roles.worker\"></span>\r\n              </th>\r\n              <th class=\"hidden-xxs\">\r\n                <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.status\"></span><br />\r\n                <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.date\"></span>\r\n              </th>\r\n              <th class=\"right hidden-xxs\">\r\n                <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.salary\"></span><br />\r\n                <span sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.payment\"></span>\r\n              </th>\r\n              <th class=\"hidden-xxs\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"row in $ctrlQuery.calculations\">\r\n              <td class=\"td-avatar visible-xxs middle\">\r\n                <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td class=\"td-name visible-xxs middle\">\r\n                <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.notSelected\"></span>\r\n                <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br /> {{ \"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate }}\r\n                <br /> {{ row.endAt | date }}\r\n              </td>\r\n              <td class=\"right visible-xxs bottom\">\r\n                <div>\r\n                  {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n                </div>\r\n              </td>\r\n              <td class=\"td-avatar hidden-xxs middle\">\r\n                <salaxy-avatar avatar=\"row.otherPartyInfo.avatar\"></salaxy-avatar>\r\n              </td>\r\n              <td class=\"td-name hidden-xxs middle\">\r\n                <span ng-if=\"row.otherPartyInfo.avatar.displayName == ''\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.notSelected\"></span>\r\n                <strong>{{row.otherPartyInfo.avatar.displayName}}</strong><br />\r\n              </td>\r\n              <td class=\"hidden-xxs middle\">\r\n                {{ row.status ? (\"SALAXY.ENUM.CalculationStatus.\" + row.status + \".label\" | sxyTranslate) : \"#ERR\" }}<br /> {{ row.endAt | date }}\r\n              </td>\r\n              <td class=\"right hidden-xxs middle\">\r\n                {{ row.grossSalary | currency }}<br /> {{ row.payment | currency }}\r\n              </td>\r\n              <td class=\"right middle\">\r\n                <button class=\"btn btn-sm  btn-danger\" type=\"button\" ng-click=\"$ctrlQuery.removeCalc(row)\">\r\n                        {{ 'SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.unselect' | sxyTranslate }}\r\n                      </button>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </form>\r\n  <div class=\"col col-md-12 text-right\">\r\n    <button class=\"btn btn-primary\" ng-disabled=\"!queryForm.$valid || !$ctrlQuery.calculations.length\" ng-click=\"$ctrlQuery.queryData($ctrl.current.id)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.editorQuery.fetchRowsBtn\"></button>\r\n  </div>\r\n  <salaxy-accounting-report-rows data=\"$ctrlQuery.data\"></salaxy-accounting-report-rows>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetEditorRulesTable1.html\",`<div class=\"table-responsive\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.incomeTypeHead\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.additionalSelectionsHead\"></th>\r\n        <th>\r\n          <div sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.includeHead\"></div>\r\n          <div sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabledHead\"></div>\r\n        </th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.debetHead\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.creditHead\"></th>\r\n        <th class=\"right\">\r\n          <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.UI_Terms.addRow'| sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null, true)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"ruleSetRow in $ctrl.current.ruleSet.rows\">\r\n        <td>{{$ctrl.getEntryDescription(ruleSetRow)}}</td>\r\n        <td>\r\n          <div ng-repeat=\"flag in ruleSetRow.flags\">\r\n            <span title=\"{{$ctrl.getFlag(flag).description}}\" class=\"badge bg-success\">{{$ctrl.getFlag(flag).text}}</span>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-class=\"{ 'text-danger': !ruleSetRow.isIncluded }\">{{ ruleSetRow.isIncluded ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.included'| sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.excluded'| sxyTranslate) }}</div>\r\n          <div ng-class=\"{ 'text-danger': !ruleSetRow.enabled }\">{{ ruleSetRow.enabled ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabled'| sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.disabled'| sxyTranslate) }}</div>\r\n        </td>\r\n        <td ng-if=\"ruleSetRow.isIncluded\">\r\n          <div>\r\n            {{ $ctrl.getAccount(ruleSetRow.debitId).account || ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.debitUndefined'| sxyTranslate) }}\r\n            <span ng-if=\"ruleSetRow.debitGrouping\">\r\n              <span>{{ ruleSetRow.debitGrouping }}</span>\r\n            <small style=\"text-decoration: line-through\">{{ $ctrl.getAccount(ruleSetRow.debitId).text }}</small>\r\n            </span>\r\n            <span ng-if=\"!ruleSetRow.debitGrouping\">\r\n              <span>{{ $ctrl.getAccount(ruleSetRow.debitId).text }}</span>\r\n            </span>\r\n          </div>\r\n        </td>\r\n        <td ng-if=\"ruleSetRow.isIncluded\">\r\n          <div>\r\n            {{ $ctrl.getAccount(ruleSetRow.creditId).account || ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.creditUndefined'| sxyTranslate) }}\r\n            <span ng-if=\"ruleSetRow.creditGrouping\">\r\n              <span>{{ ruleSetRow.creditGrouping }}</span>\r\n            <small style=\"text-decoration: line-through\">{{ $ctrl.getAccount(ruleSetRow.creditId).text }}</small>\r\n            </span>\r\n            <span ng-if=\"!ruleSetRow.creditGrouping\">\r\n              <span>{{ $ctrl.getAccount(ruleSetRow.creditId).text }}</span>\r\n            </span>\r\n          </div>\r\n        </td>\r\n        <td colspan=\"2\" ng-if=\"!ruleSetRow.isIncluded\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></td>\r\n        <td class=\"right\">\r\n          <div class=\"btn-group\">\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editRule' | sxyTranslate}}\" class=\"btn btn-sm\" ng-class=\"{ 'btn-primary': !ruleSetRow.isInEdit, 'btn-default': ruleSetRow.isInEdit }\" type=\"button\"\r\n              ng-click=\"ruleSetRow.isInEdit=!ruleSetRow.isInEdit\">\r\n              <i class=\"fa fa-edit\"></i>\r\n            </button>\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.copyAsNewRule' | sxyTranslate}}\" class=\"btn btn-default btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(ruleSetRow)\">\r\n              <i class=\"fa fa-copy\"></i>\r\n            </button>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end ng-if=\"ruleSetRow.isInEdit\">\r\n        <td>\r\n          <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" class=\"btn btn-sm btn-default\" type=\"button\" ng-click=\"$ctrl.selectEntry(ruleSetRow)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeIncomeTypeBtn\"></button>\r\n        </td>\r\n        <td>\r\n          <button title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-sm btn-default\" type=\"button\" ng-click=\"$ctrl.selectFlags(ruleSetRow)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editAdditionalsBtn\"></button>\r\n        </td>\r\n        <td>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetIsIncluded'+$index}}\" ng-model=\"ruleSetRow.isIncluded\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.includeHead\">\r\n          </salaxy-input-boolean>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetEnabled'+$index}}\" ng-model=\"ruleSetRow.enabled\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabledHead\"></salaxy-input-boolean>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" ng-disabled=\"!ruleSetRow.isIncluded\" class=\"btn btn-default btn-sm btn-block\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, false)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n            <salaxy-input name=\"{{'debitGrouping'+$index}}\" placeholder=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.grouping\" label-type=\"plain\" ng-model=\"ruleSetRow.debitGrouping\"></salaxy-input>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" ng-disabled=\"!ruleSetRow.isIncluded\" class=\"btn btn-default btn-sm btn-block\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, true)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n            <salaxy-input name=\"{{'creditGrouping'+$index}}\" placeholder=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.grouping\" label-type=\"plain\" ng-model=\"ruleSetRow.creditGrouping\"></salaxy-input>\r\n          </div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <button title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\" class=\"btn btn-danger btn-sm\" type=\"button\" ng-disabled=\"ruleSetRow.isReadOnly\" ng-click=\"$ctrl.removeRow(ruleSetRow)\" sxy-text=\"SALAXY.UI_Terms.deleteRow\"></button>\r\n        </td>\r\n      </tr>\r\n      <tr>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td class=\"right\">\r\n          <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetEditorRulesTable2.html\",`<div class=\"table-responsive\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.debetHead\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.creditHead\"></th>\r\n        <th></th>\r\n        <th></th>\r\n        <th class=\"right\">\r\n          <button ng-disabled=\"true\" title=\"{{'SALAXY.UI_Terms.addRow'| sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null, true)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"(key, ruleSetGroup) in $ctrl.groupedRows\" class=\"primary\">\r\n        <td ng-if=\"ruleSetGroup[0].isIncluded\">\r\n          <div>\r\n            {{ $ctrl.getAccount(ruleSetGroup[0].debitId).account || ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.debitUndefined'| sxyTranslate) }}\r\n            <span ng-if=\"ruleSetGroup[0].debitGrouping\">\r\n              <span>{{ ruleSetGroup[0].debitGrouping }}</span>\r\n            <small style=\"text-decoration: line-through\">{{ $ctrl.getAccount(ruleSetGroup[0].debitId).text }}</small>\r\n            </span>\r\n            <span ng-if=\"!ruleSetGroup[0].debitGrouping\">\r\n              <span>{{ $ctrl.getAccount(ruleSetGroup[0].debitId).text }}</span>\r\n            </span>\r\n          </div>\r\n        </td>\r\n        <td ng-if=\"ruleSetGroup[0].isIncluded\">\r\n          <div>\r\n            {{ $ctrl.getAccount(ruleSetGroup[0].creditId).account || ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.creditUndefined'| sxyTranslate) }}\r\n            <span ng-if=\"ruleSetGroup[0].creditGrouping\">\r\n              <span>{{ ruleSetGroup[0].creditGrouping }}</span>\r\n            <small style=\"text-decoration: line-through\">{{ $ctrl.getAccount(ruleSetGroup[0].creditId).text }}</small>\r\n            </span>\r\n            <span ng-if=\"!ruleSetGroup[0].creditGrouping\">\r\n              <span>{{ $ctrl.getAccount(ruleSetGroup[0].creditId).text }}</span>\r\n            </span>\r\n          </div>\r\n        </td>\r\n        <td colspan=\"2\" ng-if=\"!ruleSetGroup[0].isIncluded\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></td>\r\n        <td colspan=\"4\"></td>\r\n      </tr>\r\n      <tr ng-repeat-start=\"ruleSetRow in ruleSetGroup\">\r\n        <td colspan=\"2\">{{$ctrl.getEntryDescription(ruleSetRow)}}</td>\r\n        <td>\r\n          <div ng-repeat=\"flag in ruleSetRow.flags\">\r\n            <span title=\"{{$ctrl.getFlag(flag).description}}\" class=\"badge bg-success\">{{$ctrl.getFlag(flag).text}}</span>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-class=\"{ 'text-danger': !ruleSetRow.enabled }\">{{ ruleSetRow.enabled ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabled'| sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.disabled'| sxyTranslate) }}</div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <div class=\"btn-group\">\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editRule' | sxyTranslate}}\" class=\"btn btn-sm\" ng-class=\"{ 'btn-primary': !ruleSetRow.isInEdit, 'btn-default': ruleSetRow.isInEdit }\" type=\"button\"\r\n              ng-click=\"ruleSetRow.isInEdit=!ruleSetRow.isInEdit\">\r\n              <i class=\"fa fa-edit\"></i>\r\n            </button>\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.copyAsNewRule' | sxyTranslate}}\" class=\"btn btn-default btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(ruleSetRow)\">\r\n              <i class=\"fa fa-copy\"></i>\r\n            </button>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end ng-if=\"ruleSetRow.isInEdit\" class=\"no-border\">\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.debitId).account + ' ' + $ctrl.getAccount(ruleSetRow.debitId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, false)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n              </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.debitGroupingTemp = ruleSetRow.debitGrouping\" ng-model=\"ruleSetRow.debitGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.debitGrouping = ruleSetRow.debitGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n              </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.creditId).account + ' ' + $ctrl.getAccount(ruleSetRow.creditId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, true)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n              </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.creditGroupingTemp = ruleSetRow.creditGrouping\" ng-model=\"ruleSetRow.creditGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.creditGrouping = ruleSetRow.creditGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n              </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectEntry(ruleSetRow)\">\r\n            <span sxy-text=\"SALAXY.UI_Terms.change\"></span> {{ ruleSetRow.entryCodeGroup == 'incomeType' ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.incomeTypeBtnPS' | sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.calcRowBtnPS' | sxyTranslate) }}\r\n          </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectFlags(ruleSetRow)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editAdditionalsBtn\"></button>\r\n        </td>\r\n        <td>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetIsIncluded'+$index}}\" ng-model=\"ruleSetRow.isIncluded\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.includeHead\">\r\n          </salaxy-input-boolean>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetEnabled'+$index}}\" ng-model=\"ruleSetRow.enabled\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabledHead\"></salaxy-input-boolean>\r\n        </td>\r\n        <td class=\"right\">\r\n          <button title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\" class=\"btn btn-danger btn-sm\" ng-disabled=\"ruleSetRow.isReadOnly\" type=\"button\" ng-disabled=\"ruleSetRow.isReadOnly\" ng-click=\"$ctrl.removeRow(ruleSetRow)\" sxy-text=\"SALAXY.UI_Terms.deleteRow\"></button>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end></tr>\r\n      <tr>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td class=\"right\">\r\n          <button ng-disabled=\"true\" title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetEditorRulesTable3.html\",`<div class=\"table-responsive\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.accountsHead\"></th>\r\n        <th></th>\r\n        <th></th>\r\n      </tr>\r\n      <tr>\r\n        <th></th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.debetHead\"></th>\r\n        <th sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.creditHead\"></th>\r\n        <th></th>\r\n        <th class=\"right\">\r\n          <button ng-disabled=\"true\" title=\"{{'SALAXY.UI_Terms.addRow'| sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null, true)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"account in $ctrl.current.ruleSet.accounts\" class=\"primary\">\r\n        <td>\r\n          {{account.account}} {{account.text}}\r\n        </td>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n      </tr>\r\n      <tr ng-repeat-start=\"ruleSetRow in $ctrl.getRulesetByAccount(account, true)\">\r\n        <td></td>\r\n        <td>\r\n          {{$ctrl.getEntryDescription(ruleSetRow)}}\r\n        </td>\r\n        <td></td>\r\n        <td></td>\r\n        <td class=\"right\">\r\n          <div class=\"btn-group\">\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editRule' | sxyTranslate}}\" class=\"btn btn-sm\" ng-class=\"{ 'btn-primary': !ruleSetRow.isInEdit, 'btn-default': ruleSetRow.isInEdit }\" type=\"button\"\r\n              ng-click=\"ruleSetRow.isInEdit=!ruleSetRow.isInEdit\">\r\n                <i class=\"fa fa-edit\"></i>\r\n              </button>\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.copyAsNewRule' | sxyTranslate}}\" class=\"btn btn-default btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(ruleSetRow)\">\r\n                <i class=\"fa fa-copy\"></i>\r\n              </button>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"ruleSetRow.isInEdit\">\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.debitId).account + ' ' + $ctrl.getAccount(ruleSetRow.debitId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, false)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n                </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.debitGroupingTemp = ruleSetRow.debitGrouping\" ng-model=\"ruleSetRow.debitGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.debitGrouping = ruleSetRow.debitGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n                </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.creditId).account + ' ' + $ctrl.getAccount(ruleSetRow.creditId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, true)\"  sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n                </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.creditGroupingTemp = ruleSetRow.creditGrouping\" ng-model=\"ruleSetRow.creditGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.creditGrouping = ruleSetRow.creditGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n                </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td></td>\r\n        <td>\r\n          <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectEntry(ruleSetRow)\">\r\n            <span sxy-text=\"SALAXY.UI_Terms.change\"></span> {{ ruleSetRow.entryCodeGroup == 'incomeType' ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.incomeTypeBtnPS' | sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.calcRowBtnPS' | sxyTranslate) }}\r\n            </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectFlags(ruleSetRow)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editAdditionalsBtn\"></button>\r\n        </td>\r\n        <td>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetIsIncluded'+$index}}\" ng-model=\"ruleSetRow.isIncluded\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.includeHead\">\r\n          </salaxy-input-boolean>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetEnabled'+$index}}\" ng-model=\"ruleSetRow.enabled\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabledHead\"></salaxy-input-boolean>\r\n          <button title=\"Poista rivi\" ng-disabled=\"ruleSetRow.isReadOnly\" class=\"btn btn-danger btn-sm\" type=\"button\" ng-click=\"$ctrl.removeRow(ruleSetRow)\" sxy-text=\"SALAXY.UI_Terms.deleteRow\"></button>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end></tr>\r\n      <tr ng-repeat-start=\"ruleSetRow in $ctrl.getRulesetByAccount(account, false)\">\r\n        <td></td>\r\n        <td></td>\r\n        <td>\r\n          {{$ctrl.getEntryDescription(ruleSetRow)}}\r\n        </td>\r\n        <td></td>\r\n        <td class=\"right\">\r\n          <div class=\"btn-group\">\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" ttitle=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editRule' | sxyTranslate}}\" class=\"btn btn-sm\" ng-class=\"{ 'btn-primary': !ruleSetRow.isInEdit, 'btn-default': ruleSetRow.isInEdit }\" type=\"button\"\r\n              ng-click=\"ruleSetRow.isInEdit=!ruleSetRow.isInEdit\">\r\n              <i class=\"fa fa-edit\"></i>\r\n            </button>\r\n            <button ng-disabled=\"$ctrl.isReadOnly\" title=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.copyAsNewRule' | sxyTranslate}}\" class=\"btn btn-default btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(ruleSetRow)\">\r\n              <i class=\"fa fa-copy\"></i>\r\n            </button>\r\n          </div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"ruleSetRow.isInEdit\">\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.debitId).account + ' ' + $ctrl.getAccount(ruleSetRow.debitId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, false)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n                </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.debitGroupingTemp = ruleSetRow.debitGrouping\" ng-model=\"ruleSetRow.debitGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.debitGrouping = ruleSetRow.debitGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n                </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <div ng-if=\"!ruleSetRow.isIncluded\">\r\n            <small sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.notIncluded\"></small>\r\n          </div>\r\n          <div ng-if=\"ruleSetRow.isIncluded\">\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-value=\"$ctrl.getAccount(ruleSetRow.creditId).account + ' ' + $ctrl.getAccount(ruleSetRow.creditId).text\" disabled=\"true\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"$ctrl.selectAccount(ruleSetRow, true)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeAccountBtn\"></button>\r\n                </span>\r\n            </div>\r\n            <div class=\"input-group\">\r\n              <input type=\"text\" class=\"form-control\" ng-init=\"ruleSetRow.creditGroupingTemp = ruleSetRow.creditGrouping\" ng-model=\"ruleSetRow.creditGroupingTemp\" placeholder=\"{{'SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.addGrouping' | sxyTranslate}}\">\r\n              <span class=\"input-group-btn\">\r\n                  <button class=\"btn btn-default fixed-width-addon\" type=\"button\" ng-click=\"ruleSetRow.creditGrouping = ruleSetRow.creditGroupingTemp\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.changeGroupingBtn\"></button>\r\n                </span>\r\n            </div>\r\n          </div>\r\n        </td>\r\n        <td>\r\n          <button title=\"{{'SALAXY.UI_Terms.change' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectEntry(ruleSetRow)\">\r\n            <span sxy-text=\"SALAXY.UI_Terms.change\"></span> {{ ruleSetRow.entryCodeGroup == 'incomeType' ? ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.incomeTypeBtnPS' | sxyTranslate) : ('SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.calcRowBtnPS' | sxyTranslate) }}\r\n            </button>\r\n          <button title=\"{{'SALAXY.UI_Terms.edit' | sxyTranslate}}\" class=\"btn btn-default fixed-width-button\" type=\"button\" ng-click=\"$ctrl.selectFlags(ruleSetRow)\" sxy-text=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.editAdditionalsBtn\"></button>\r\n        </td>\r\n        <td>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetIsIncluded'+$index}}\" ng-model=\"ruleSetRow.isIncluded\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.includeHead\">\r\n          </salaxy-input-boolean>\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"{{'ruleSetEnabled'+$index}}\" ng-model=\"ruleSetRow.enabled\" label-type=\"plain\" label-true=\"SALAXY.NG1.AccountingTargetDetailsComponent.rulesTables.enabledHead\"></salaxy-input-boolean>\r\n          <button title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\" ng-disabled=\"ruleSetRow.isReadOnly\" class=\"btn btn-danger btn-sm\" type=\"button\" ng-click=\"$ctrl.removeRow(ruleSetRow)\">\r\n              Poista rivi\r\n            </button>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end>\r\n\r\n      </tr>\r\n      <tr ng-repeat-end></tr>\r\n      <tr>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td></td>\r\n        <td class=\"right\">\r\n          <button ng-disabled=\"true\" title=\"{{'SALAXY.UI_Terms.addRow' | sxyTranslate}}\" class=\"btn btn-primary btn-sm\" type=\"button\" ng-click=\"$ctrl.addRow(null)\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/AccountingTargetSettings.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\">\r\n  <div class=\"panel accounting-target-settings panel-default\">\r\n    <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"CompanyAccountSettings\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2 sxy-text=\"SALAXY.NG1.AccountingTargetSettings.title\"></h2>\r\n        <p ng-if=\"!(!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting)\"><small sxy-text=\"SALAXY.NG1.AccountingTargetSettings.intro\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <fieldset>\r\n          <legend><span sxy-text=\"SALAXY.NG1.AccountingTargetSettings.accountingLegend\"></span></legend>\r\n          <salaxy-input-enum disabled=\"!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting\" type=\"typeahead\" name=\"options_type\" ng-model=\"$ctrl.current.accounting.defaultTargetId\" options=\"$ctrl.getSelectableAccountingTargets()\"\r\n            disable-cache=\"true\" label=\"SALAXY.NG1.AccountingTargetSettings.defaultTarget\"></salaxy-input-enum>\r\n          <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-accounting-targets.html\" model=\"form.accounting.targets\" read-only=\"{{!$ctrl.current.accounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.accounting}}\">\r\n            <form>\r\n              <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"CompanySettingsController as $companySettingsCtrl\" ng-init=\"$ctrl.logic.isReadOnly = true\">\r\n                <salaxy-odata-table  crud-controller=\"AccountingTargetCrudController as $crud\" template-url=\"salaxy-components/odata/lists/AccountingTargetSelect.html\" selected-items=\"$ctrl.selectedItems\" on-list-select=\"$companySettingsCtrl.onAccountingTargetSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                </salaxy-odata-table>\r\n              </fieldset>\r\n              <fieldset ng-show=\"$ctrl.logic.showDelete\" ng-init=\"$ctrl.logic.isReadOnly = false\">\r\n                <salaxy-input-enum disabled=\"false\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsvFormat\" ng-model=\"$ctrl.current.format\"\r\n                options=\"{\r\n                  '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                  '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                  '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                  'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                  '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                  '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                  '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                  'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                  'ba271dac-dd63-4036-9d70-053a09ca4d9e' :'Visma Netvisor',\r\n                  '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                  'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                  'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                  '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                  '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                }\">\r\n                </salaxy-input-enum>\r\n                <sxy-input model=\"form.method\" read-only=\"false\"></sxy-input>\r\n                <salaxy-input-enum disabled=\"false\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.availableMethods.title\" name=\"availableMethods\" type=\"multi-select\" ng-model=\"$ctrl.current.availableMethods\"></salaxy-input-enum>\r\n              </fieldset>\r\n            </form>\r\n          </sxy-input>\r\n          <sxy-input model=\"form.accounting.defaultPeriodDateKind\" read-only=\"{{!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting}}\"></sxy-input>\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12 text-right\">\r\n            <button class=\"btn btn-primary\" ng-click=\"$ctrl.save('all')\" ng-disabled=\"(!$ctrl.current.accounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.accounting) || $ctrl.isSaving('all')\"><span ng-if=\"$ctrl.isSaving('all')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/CostAccountingSettings.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\">\r\n  <div class=\"panel costAccounting panel-default\">\r\n    <div>\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2 sxy-text=\"SALAXY.MODEL.CostAccountingSettings.title\"></h2>\r\n        <p><small sxy-text=\"SALAXY.MODEL.CostAccountingSettings.descr\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n\r\n          <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"CompanyAccountSettings\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\"\r\n            read-only=\"{{(!$ctrl.current.costAccounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.costAccounting) || $ctrl.isReadOnlyForced}}\">\r\n            \r\n            <div class=\"col-xs-12 form-horizontal\">\r\n              \r\n              <sxy-input model=\"form.costAccounting.dimensions\" include=\"id,label,scope\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.CostAccountingDimensionDefinition.title\"></legend>\r\n                    <sxy-input model=\"form.id\" read-only=\"{{$ctrl.logic.showDelete}}\"></sxy-input>\r\n                    <sxy-input model=\"form.label\"></sxy-input>\r\n                    <sxy-input model=\"form.allowCostSharing\"></sxy-input>\r\n                    <sxy-input model=\"form.scope\"></sxy-input>\r\n                    <sxy-input model=\"form.options\" template-url=\"salaxy-components/sxy-form/custom-templates/cost-accounting-options.html\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input> \r\n              \r\n            </div>\r\n          </sxy-form>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button type=\"submit\" ng-disabled=\"(!$ctrl.current.costAccounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.costAccounting) ||$ctrl.isSaving('all')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('all')\"><span ng-if=\"$ctrl.isSaving('all')\"><i\r\n                  class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/HolidaySettings.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\">\r\n  <div class=\"panel accounting panel-default\">\r\n    <div>\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2 sxy-text=\"SALAXY.MODEL.HolidaySettings.title\"></h2>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n\r\n          <sxy-form ng-ref=\"$frm\" open-api=\"salaxy-secure/schemas/v02.json\" type=\"CompanyAccountSettings\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\" read-only=\"{{!$ctrl.current.holidays.denyServiceModel  && $ctrl.current.partner.serviceModel.features.holidays}}\">\r\n            <div>\r\n              <sxy-input model=\"form.partner.serviceModel.features.holiday\" label=\"SALAXY.NG1.ProSettingsComponent.customHoliday\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc6\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.holiday\" ng-model=\"$ctrl.current.holiday.denyServiceModel\"></salaxy-input-boolean>\r\n              <sxy-input model=\"form.holiday.holidayPaySettings\"\r\n                read-only=\"{{!$ctrl.current.holiday.denyServiceModel  && $ctrl.current.partner.serviceModel.features.holiday }}\" include=\"holidayPayCalculation\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.title\"></legend>\r\n                    <salaxy-input-enum enum=\"HolidayPayCalculation\" label=\"SALAXY.MODEL.HolidayPaySettings.holidayPayCalculation.title\" name=\"holidayPayCalculation\" filter=\"averageDailyPay,averageHourlyPay,percentageBasedPay,holidayCompensation\" require=\"true\" ng-model=\"$ctrl.current.holidayPayCalculation\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.salaryTypes.title\"></legend>\r\n                    <sxy-input model=\"form.salaryTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.workingTimeTypes.title\"></legend>\r\n                    <sxy-input ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.overtimeTypes.title\"></legend>\r\n                    <sxy-input  ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" model=\"form.overtimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\"></legend>\r\n                    <salaxy-input-holiday-multipliers ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" name=\"multipliers\" label=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\" ng-model=\"$ctrl.current.multipliers\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-holiday-multipliers>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n              <sxy-input model=\"form.holiday.holidayAccrualSettings\"\r\n                read-only=\"{{!$ctrl.current.holiday.denyServiceModel  && $ctrl.current.partner.serviceModel.features.holiday }}\" include=\"code\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.title\"></legend>\r\n                    <salaxy-input-enum enum=\"HolidayCode\" label=\"SALAXY.MODEL.HolidayAccrualSettings.code.title\" name=\"code\" filter=\"permanent35Hours\" require=\"true\" ng-model=\"$ctrl.current.code\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.workingTimeTypes.title\"></legend>\r\n                    <sxy-input model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </div>\r\n           \r\n          </sxy-form>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button type=\"submit\" ng-disabled=\"(!$ctrl.current.holidays.denyServiceModel && $ctrl.current.partner.serviceModel.features.holidays) || !$frm.ngForm.$valid || $ctrl.isSaving('all')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('all')\">\r\n              <span ng-if=\"$ctrl.isSaving('all')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\r\n              <span sxy-text=\"SALAXY.UI_Terms.save\"></span>\r\n            </button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/Insurances.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\" ng-controller=\"VarmaBannerController as $varma\">\r\n  <div class=\"panel pension panel-default\" ng-repeat=\"item in $ctrl.pensionContracts\" ng-if=\"$ctrl.sections.indexOf('pensionContracts') >= 0 && $ctrl.isVisibleContract(item, $ctrl.pensionContracts)\">\r\n\r\n    <form name=\"pensionForm\" class=\"pension-form\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2><span sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.title\"></span><i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n        </h2>\r\n        <p><small sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.description\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <div class=\"form-horizontal\">\r\n              <fieldset>\r\n                <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.currentContractLegend\"></legend>\r\n                <salaxy-input-enum ng-model=\"item.company\" type=\"select\" label=\"SALAXY.MODEL.PensionContract.company.editLabel\" name=\"pensionCompany\" enum=\"PensionCompany\" filter=\"none,varma,elo,ilmarinen,veritas,apteekkien,verso,valio,kevaMunicipal,kevaAland,kevaChurch,kevaKela,kevaState\" require=\"true\" ng-change=\"item.contractNumber = null\"></salaxy-input-enum>\r\n\r\n                <main salaxy-if-role=\"test\" class=\"test-number\">\r\n                  <div class=\"form-group\" ng-if=\"item.company && item.company != 'none'\">\r\n                    <div class=\"col-sm-8 col-sm-offset-4 text-right-sm\">\r\n                      <span>Test only: <button class=\"btn btn-secondary btn-xs\" ng-click=\"$ctrl.setPensionNumberForTest(item)\"> Generoi numero </button></span>\r\n                    </div>\r\n                  </div>\r\n                </main>\r\n\r\n                <salaxy-input ng-if=\"item.company && item.company != 'none'\" require=\"true\" name=\"pensionContractNumber\" label=\"SALAXY.MODEL.PensionContract.contractNumber.title\" ng-model=\"item.contractNumber\" tooltip-html=\"{{'SALAXY.NG1.InsuranceSettingsComponent.pension.errors.sxyPensionContractNumber.html' | sxyTranslate}}\"\r\n                  tooltip-placement=\"top-right\" sxy-pension-contract-number=\"item.company\"></salaxy-input>\r\n\r\n                <div class=\"row\" ng-show=\"pensionForm.pensionContractNumber.$error.sxyTemporaryPensionContractNumber\">\r\n                  <div class=\"col-xs-12 col-sm-offset-4 input-info text-danger\">\r\n                    <div class=\"input-info-icon\"><i class=\"fa fa-exclamation-triangle\"></i></div>\r\n                    <p class=\"small input-info-text with-icon\" sxy-html=\"SALAXY.NG1.InsuranceSettingsComponent.pension.errors.sxyTemporaryPensionContractNumber.html\"></p>\r\n                  </div>\r\n                </div>\r\n                <salaxy-input-number disabled=\"true\" ng-if=\"(item.company && item.company != 'none')\" unit=\"percent\" ng-model=\"item.pensionDefaultPercent\" name=\"pensionDefaultPercent\" label=\"SALAXY.MODEL.PensionContract.pensionDefaultPercent.title\"></salaxy-input-number>\r\n                <salaxy-input-number disabled=\"!('admin,pro' | sxyIsInRole)\" ng-if=\"(item.company && item.company != 'none') && (('admin,pro' | sxyIsInRole) || item.pensionPercent)\" unit=\"percent\" ng-model=\"item.pensionPercent\" name=\"pensionPercent\" label=\"SALAXY.MODEL.PensionContract.pensionPercent.title\"></salaxy-input-number>\r\n              </fieldset>\r\n\r\n            </div>\r\n\r\n\r\n\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\" ng-show=\"item.company && item.company != 'none' && item.company != 'varma'\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.moveContractLegend\"></legend>\r\n              <p sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.moveContractDescription\"></p>\r\n              <div>\r\n\r\n                <a ng-href=\"{{$varma.getVarmaShopLink()}}\" target=\"_blank\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.moveContractCta\"></a>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\" ng-show=\"!item.company || item.company == 'none'\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.varmaLegend\"></legend>\r\n              <p sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.varmaDescription\"></p>\r\n              <div>\r\n                <a ng-href=\"{{$varma.getVarmaShopLink()}}\" target=\"_blank\" class=\"btn btn-primary\" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.varmaCta\"></a>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\" ng-show=\"!item.company || item.company == 'none'\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.pension.temporaryLegend\"></legend>\r\n              <p sxy-html=\"SALAXY.NG1.InsuranceSettingsComponent.pension.temporaryDescription.html\"></p>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"!item.company || pensionForm.$invalid || $ctrl.isSaving('pensionContracts')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('pensionContracts')\"><span ng-if=\"$ctrl.isSaving('pensionContracts')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n\r\n    </form>\r\n  </div>\r\n  <div class=\"panel pension yel-pension panel-default\" ng-if=\"$ctrl.sections.indexOf('yelPensionContracts') >= 0\">\r\n\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.yelPension.title\"></span>\r\n      </h2>\r\n\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <p sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.yelPension.description\"></p>\r\n    </div>\r\n    <div class=\"panel-footer text-right\">\r\n      <a class=\"btn btn-primary\" ng-href=\"{{$varma.getVarmaShopLink()}}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.yelPension.takeInsuranceBtn\"></a>\r\n    </div>\r\n  </div>\r\n\r\n\r\n  <div class=\"panel insurance panel-default\" ng-repeat=\"item in $ctrl.insuranceContracts\" ng-if=\"$ctrl.sections.indexOf('insuranceContracts') >= 0 && $ctrl.isVisibleContract(item, $ctrl.insuranceContracts)\">\r\n\r\n    <form ng-if=\"item.status != 'pending'\" name=\"insuranceForm\" class=\"insurance-form\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n      <div class=\"panel-heading icon-panel \">\r\n        <h2><span sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.title\"></span><i class=\"fa text-success fa-check-circle status-icon\"></i>\r\n        </h2>\r\n        <p><small sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.description\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.currentContractLegend\"></legend>\r\n              <div class=\"form-horizontal\">\r\n                <salaxy-input-enum ng-model=\"item.company\" type=\"select\" enum=\"InsuranceCompany\" filter=\"none,fennia,if,lähiTapiola,pohjantähti,pohjola,turva,aVakuutus,folksam,alandia,ålands\" label=\"SALAXY.MODEL.InsuranceContract.company.editLabel\" name=\"insurance-company\"\r\n                  require=\"true\"></salaxy-input-enum>\r\n              </div>\r\n              <div class=\"form-horizontal\" ng-if=\"item.company && item.company != 'none'\">\r\n                <salaxy-input ng-model=\"item.contractNumber\" require=\"true\" name=\"insuranceContractNumber\" label=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\"></salaxy-input>\r\n              </div>\r\n              <div class=\"form-horizontal\" ng-if=\"item.company\">\r\n                <salaxy-input-number unit=\"percent\" tooltip-html=\"{{'SALAXY.MODEL.InsuranceContract.insurancePercent.descr' | sxyTranslate}}\" ng-model=\"item.insurancePercent\" name=\"insurancePercent\" label=\"SALAXY.MODEL.InsuranceContract.insurancePercent.title\"></salaxy-input-number>\r\n              </div>\r\n              <div class=\"form-horizontal\" ng-if=\"item.company\">\r\n                <salaxy-input-number unit=\"percent\" tooltip-html=\"{{'SALAXY.MODEL.InsuranceContract.groupLifeInsurancePercent.descr' | sxyTranslate}}\" ng-model=\"item.groupLifeInsurancePercent\" name=\"groupLifeInsurancePercent\" label=\"SALAXY.MODEL.InsuranceContract.groupLifeInsurancePercent.title\"></salaxy-input-number>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\" ng-if=\"!$ctrl.isReadOnlyForced\">\r\n            <fieldset ng-show=\"item.company && item.company != 'lähiTapiola' && item.company != 'none' \">\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.moveToLocalTapiolaLegend\"></legend>\r\n              <div ng-controller=\"InsuranceWizardController as insuranceCtrl\">\r\n                <button class=\"btn btn-primary\" ng-click=\"insuranceCtrl.openModal();\" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.moveToLocalTapiolaBtn\"></button>\r\n              </div>\r\n            </fieldset>\r\n            <fieldset ng-if=\"item.company == 'none' || !item.company\">\r\n              <legend sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.takeFromLocalTapiolaLegend\"></legend>\r\n\r\n              <div ng-controller=\"InsuranceWizardController as insuranceCtrl\">\r\n                <button class=\"btn btn-primary\" ng-click=\"insuranceCtrl.openModal();\" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.takeFromLocalTapiolaBtn\"></button>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\" style=\"margin-top:10px;\">\r\n          <div class=\"col-xs-12\">\r\n            <div ng-if=\"item.company && item.company != 'none'\">\r\n              <div class=\"pull-left\"><i class=\"fa fa-info-circle alert-icon text-info icon-info\"></i></div>\r\n              <div class=\"alert-text\">\r\n                <p class=\"text-info \" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.insuranceComment\"></p>\r\n              </div>\r\n            </div>\r\n            <div ng-if=\"item.company == 'none'\">\r\n              <div class=\"pull-left\"><i class=\"fa fa-exclamation alert-icon text-danger icon-danger\"></i></div>\r\n              <div class=\"alert-text\">\r\n                <p class=\"text-danger \" sxy-text=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.warning\"></p>\r\n              </div>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"!item.company || $ctrl.isSaving('insuranceContracts')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('insuranceContracts')\"><span ng-if=\"$ctrl.isSaving('insuranceContracts')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </form>\r\n  </div>\r\n\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/OwnerSettings.html\",`<div class=\"salaxy-component salaxy-owner-settings\">\r\n\r\n  <style>\r\n    @media print {\r\n      .uib-tab {\r\n        display: none !important;\r\n      }\r\n    }\r\n  </style>\r\n  <uib-tabset active=\"$ctrl.currentTab\">\r\n    <uib-tab index=\"'default'\" heading=\"{{'SALAXY.NG1.OwnerSettingsComponent.tabs.editing' | sxyTranslate}}\">\r\n      <form class=\"form-horizontal\" ng-if=\"$ctrl.current\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.shareAmountTitle\"></legend>\r\n              <div class=\"row\">\r\n                <div class=\"col-md-6\">\r\n                  <salaxy-input-enum type=\"radio\" options=\"{ byPercent: ('SALAXY.NG1.OwnerSettingsComponent.byPercent' | sxyTranslate), byAmount: ('SALAXY.NG1.OwnerSettingsComponent.byAmount' | sxyTranslate)}\" ng-model=\"$ctrl.mode\" name=\"editMode\" label=\"SALAXY.NG1.OwnerSettingsComponent.sharesBy\"\r\n                    label-cols=\"col-md-6\"></salaxy-input-enum>\r\n                </div>\r\n                <div class=\"col-md-6\">\r\n                  <salaxy-input-number ng-model=\"$ctrl.current.ownedCompanyDetails.totalNumberOfShares\" name=\"numberOfShares\" label=\"SALAXY.NG1.OwnerSettingsComponent.shareAmount\" label-cols=\"col-md-6\" ng-change=\"$ctrl.recalculateShares()\"></salaxy-input-number>\r\n                </div>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.ownerInfoTitle\"></legend>\r\n          <div ng-if=\"!$ctrl.current.owners.length\" class=\"salaxy-placeholder-empty placeholder-md placeholder-default text-center\">\r\n            <h4 sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.noOwnersTitle\"></h4>\r\n            <p></p>\r\n            <button class=\"btn btn-primary\" ng-click=\"$ctrl.current.owners.push({numberOfShares:0,percentOfShares:0, avatar:{}});\" ng-disabled=\"!$ctrl.mode\" sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.addOwnerBtn\"></button>\r\n          </div>\r\n          <div class=\"row\" ng-repeat=\"owner in $ctrl.current.owners\">\r\n            <div class=\"col-md-6\">\r\n              <salaxy-input ng-model=\"owner.avatar.displayName\" name=\"ownerName{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerName\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-3\">\r\n              <salaxy-input ng-model=\"owner.officialId\" name=\"officialId{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerOfficialId\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-3\">\r\n              <salaxy-input ng-model=\"owner.email\" name=\"email{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerEmail\" label-type=\"basic\" sxy-email></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-6\">\r\n              <salaxy-input ng-model=\"owner.address\" name=\"address{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerAddress\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-3 col-xs-5 \">\r\n              <salaxy-input-number ng-model=\"owner.numberOfShares\" name=\"ownerShare{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerShareAmount\" label-type=\"basic\" read-only=\"$ctrl.mode == 'byPercent' || $ctrl.isReadOnlyForced\" ng-change=\"$ctrl.recalculateShares()\"></salaxy-input-number>\r\n            </div>\r\n            <div class=\"col-md-2 col-xs-5 \">\r\n              <salaxy-input-number ng-model=\"owner.percentOfShares\" name=\"ownerpercentOfShares{{$index}}\" label=\"SALAXY.NG1.OwnerSettingsComponent.ownerSharePercent\" label-type=\"basic\" read-only=\"$ctrl.mode == 'byAmount' || $ctrl.isReadOnlyForced\" ng-change=\"$ctrl.recalculateShares()\"></salaxy-input-number>\r\n            </div>\r\n            <div class=\"col-md-1 col-xs-2 text-right\" style=\"padding-top:28px\">\r\n              <button ng-if=\"!$ctrl.isReadOnlyForced\" class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.owners.splice($index,1)\" title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\"><i class=\"fa fa-trash\"></i></button>\r\n            </div>\r\n            <div class=\"col-xs-12\">\r\n              <hr>\r\n            </div>\r\n          </div>\r\n          <div class=\"row total-row\" ng-if=\"$ctrl.current.owners.length\">\r\n            <div class=\"col-xs-6\">\r\n              <strong sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.totalShares\"></strong>\r\n            </div>\r\n            <div class=\"col-xs-6 text-right\" ng-if=\"$ctrl.mode == 'byAmount'\" ng-class=\"{'text-danger' : $ctrl.getTotalAmount() > $ctrl.current.ownedCompanyDetails.totalNumberOfShares, 'text-warning' : $ctrl.getTotalAmount() < $ctrl.current.ownedCompanyDetails.totalNumberOfShares && $ctrl.getTotalAmount() > 0, 'text-success' : $ctrl.getTotalAmount() == $ctrl.current.ownedCompanyDetails.totalNumberOfShares}\">\r\n              <strong>{{$ctrl.getTotalAmount()}} / {{$ctrl.current.ownedCompanyDetails.totalNumberOfShares}} <span sxy-text=\"SALAXY.UI_Terms.units.pce\"></span></strong>\r\n            </div>\r\n            <div class=\" col-xs-6 text-right\" ng-if=\"$ctrl.mode != 'byAmount'\" ng-class=\"{'text-danger' : $ctrl.getTotalPercent() > 100, 'text-warning' : $ctrl.getTotalPercent() < 100 && $ctrl.getTotalPercent() > 0, 'text-success' : $ctrl.getTotalPercent() == 100}\">\r\n              <strong>{{$ctrl.getTotalPercent()}} / 100 %</strong>\r\n            </div>\r\n            <div class=\"col-xs-12\">\r\n              <hr>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\" ng-if=\"$ctrl.current.owners.length && !$ctrl.isReadOnlyForced\">\r\n            <div class=\"col-xs-6 \">\r\n              <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.owners.push({numberOfShares:0,percentOfShares:0, avatar: {}})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i><span sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.addOwnerBtn\"></span></button>\r\n            </div>\r\n            <div class=\"col-xs-6 text-right\">\r\n              <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.save('owners')\" ng-disabled=\"$ctrl.isSaving('owners')\"><span ng-if=\"$ctrl.isSaving('owners')\"><i\r\n                class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n            </div>\r\n          </div>\r\n        </fieldset>\r\n      </form>\r\n    </uib-tab>\r\n    <uib-tab index=\"'beneficiaries'\" heading=\"{{'SALAXY.NG1.OwnerSettingsComponent.tabs.beneficiaries' | sxyTranslate}}\">\r\n      <form class=\"form-horizontal\" ng-if=\"$ctrl.current\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.beneficiariesInfoTitle\"></legend>\r\n          <div ng-if=\"!$ctrl.current.beneficiaries.length\" class=\"salaxy-placeholder-empty placeholder-md placeholder-default text-center\">\r\n            <h4 sxy-title=\"SALAXY.NG1.OwnerSettingsComponent.noBeneficiariesTitle\">Edunsaajat</h4>\r\n            <p></p>\r\n            <button class=\"btn btn-primary\" ng-click=\"$ctrl.current.beneficiaries.push({ avatar:{}});\" sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.addBeneficiaryBtn\"></button>\r\n          </div>\r\n          <div class=\"row\" ng-repeat=\"beneficiary in $ctrl.current.beneficiaries\">\r\n            <div class=\"col-md-5\">\r\n              <salaxy-input ng-model=\"beneficiary.avatar.displayName\" name=\"beneficiaryName\" label=\"SALAXY.NG1.OwnerSettingsComponent.beneficiaryName\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-3\">\r\n              <salaxy-input ng-model=\"beneficiary.officialId\" name=\"beneficiaryOfficialId\" label=\"SALAXY.NG1.OwnerSettingsComponent.beneficiaryOfficialId\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-3 col-xs-10\">\r\n              <salaxy-input ng-model=\"beneficiary.nationality\" name=\"beneficiaryNationality\" label=\"SALAXY.NG1.OwnerSettingsComponent.beneficiaryNationality\" label-type=\"basic\"></salaxy-input>\r\n            </div>\r\n            <div class=\"col-md-1 col-xs-2 text-right\" style=\"padding-top:28px\">\r\n              <button ng-if=\"!$ctrl.isReadOnlyForced\" class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.current.beneficiaries.splice($index,1)\" title=\"{{'SALAXY.UI_Terms.deleteRow' | sxyTranslate}}\"><i class=\"fa fa-trash\"></i></button>\r\n            </div>\r\n            <div class=\"col-xs-12\">\r\n              <hr>\r\n            </div>\r\n          </div>\r\n          <div class=\"row\" ng-if=\"$ctrl.current.beneficiaries.length && !$ctrl.isReadOnlyForced\">\r\n            <div class=\"col-xs-6\">\r\n              <button class=\"btn btn-secondary btn-sm\" ng-click=\"$ctrl.current.beneficiaries.push({avatar:{}})\"><i class=\"fa fa-plus\" style=\"margin-right:5px\"></i> <span sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.addBeneficiaryBtn\"></span></button>\r\n            </div>\r\n            <div class=\"col-xs-6 text-right\">\r\n              <button class=\"btn btn-primary btn-sm\" ng-click=\"$ctrl.save('beneficiaries')\" ng-disabled=\"$ctrl.isSaving('beneficiaries')\"><span ng-if=\"$ctrl.isSaving('beneficiaries')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n            </div>\r\n          </div>\r\n        </fieldset>\r\n      </form>\r\n    </uib-tab>\r\n    <uib-tab index=\"'printable'\" heading=\"{{'SALAXY.NG1.OwnerSettingsComponent.tabs.printable' | sxyTranslate}}\">\r\n      <div class=\"report-table-html\" ng-if=\"$ctrl.current\">\r\n        <div class=\"table-responsive\">\r\n\r\n          <h1 sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.shareHoldersTitle\"></h1>\r\n          <table class=\"report-table columns-tree\">\r\n            <thead>\r\n              <tr style=\"border-bottom:1px solid black;\">\r\n                <th sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.shareHolder\"></th>\r\n                <th class=\"right\" sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.shares\"></th>\r\n                <th class=\"right\" sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.sharesPercent\"></th>\r\n              </tr>\r\n            </thead>\r\n            <tbody>\r\n              <tr ng-repeat=\"owner in $ctrl.current.owners\">\r\n                <td>\r\n                  {{owner.avatar.displayName}}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{owner.numberOfShares}}\r\n                </td>\r\n                <td class=\"right\">\r\n                  {{owner.percentOfShares}}\r\n                </td>\r\n              </tr>\r\n              <tfoot class=\"\">\r\n                <tr class=\"total\">\r\n                  <td><strong sxy-text=\"SALAXY.NG1.OwnerSettingsComponent.totalShares\"></strong></td>\r\n                  <td class=\"right\">{{$ctrl.getTotalAmount()}}</td>\r\n                  <td class=\"right\">{{$ctrl.getTotalPercent()}}</td>\r\n                </tr>\r\n              </tfoot>\r\n            </tbody>\r\n          </table>\r\n        </div>\r\n      </div>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n\r\n\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/PaymentChannelSettings.html\",`<div class=\"salaxy-component salaxy-payment-channel-settings\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-6 max-h-600\">\r\n      <h4 sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.title\"></h4>\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"channel in $ctrl.getPaymentChannels('enabled')\">\r\n            <td>\r\n              <salaxy-avatar avatar=\"$ctrl.getAvatar(channel.channel)\" class=\"\" style=\"font-size: 64px; border-bottom: 32px;\"></salaxy-avatar>\r\n            </td>\r\n            <td>\r\n              <div>\r\n                <button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.openChannelSetupDialog(channel.channel)\" sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.settingsBtn\" ps=\"...\"></button>\r\n                <strong>{{$ctrl.getAvatar(channel.channel).displayName}}</strong>\r\n                <strong ng-if=\"channel.channel == $ctrl.defaultChannel\" class=\"text-primary\" sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.defaultChannel\"></strong>\r\n              </div>\r\n              <div>{{$ctrl.getAvatar(channel.channel).description}}</div>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n    <div class=\"col-sm-6 max-h-600\">\r\n      <h4 sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.addNewTitle\" ps=\":\"></h4>\r\n      <table class=\"table\">\r\n        <tbody>\r\n          <tr ng-repeat=\"channel in $ctrl.getPaymentChannels('available')\">\r\n            <td>\r\n              <salaxy-avatar avatar=\"$ctrl.getAvatar(channel.channel)\" class=\"\" style=\"font-size: 64px; border-bottom: 32px;\"></salaxy-avatar>\r\n            </td>\r\n            <td>\r\n              <button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.openChannelSetupDialog(channel.channel)\" sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.addBtn\" ps=\"...\"></button>\r\n              <div><strong>{{$ctrl.getAvatar(channel.channel).displayName}}</strong></div>\r\n              <div>{{$ctrl.getAvatar(channel.channel).description}}</div>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\" ng-if=\"'test' | sxyIsInRole\">\r\n    <div class=\"col-sm-12\">\r\n      <h4><span sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.notAvailableTitle\"></span> <span class=\"badge bg-primary\"><span class=\"small text-white\" sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.test\"></span></span>\r\n      </h4>\r\n      <p sxy-text=\"SALAXY.NG1.PaymentChannelSettingsComponent.notAvailableText\"></p>\r\n      <div class=\"max-h-200\">\r\n        <table class=\"table table-condensed\">\r\n          <tbody>\r\n            <tr ng-repeat=\"channel in $ctrl.getPaymentChannels('unavailable') | filter: { id: '!undefined' }\">\r\n              <td>\r\n                <salaxy-avatar avatar=\"$ctrl.getAvatar(channel.channel)\" class=\"\" style=\"font-size: 32px; border-bottom: 32px;\"></salaxy-avatar>\r\n              </td>\r\n              <td>\r\n                <div>\r\n                  <strong>{{$ctrl.getAvatar(channel.channel).displayName}}</strong>:\r\n                  <small>{{$ctrl.getAvatar(channel.channel).description}}</small>\r\n                </div>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/PaymentSettings.html\",`<div class=\"content settings\" ng-if=\"$ctrl.current\">\r\n  <div class=\"panel tax panel-default\" ng-if=\"$ctrl.sections.indexOf('incomesRegister') >= 0\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.tax.title\"></span><i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.tax.intro\"></small></p>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <fieldset>\r\n            <salaxy-input-enum read-only=\"$ctrl.isReadOnlyForced\" type=\"radio\" ng-model=\"$ctrl.current.calc.incomesRegister.irReporting\" name=\"irReporting\" label=\"SALAXY.MODEL.IncomesRegisterSettings.irReporting.editLabel\" options=\"{ \r\n                                default: ('SALAXY.ENUM.TaxReportHandling.default.label' | sxyTranslate),\r\n                                noMonthlyReport: ('SALAXY.ENUM.TaxReportHandling.noMonthlyReport.label' | sxyTranslate),\r\n                                always: ('SALAXY.ENUM.TaxReportHandling.always.label' | sxyTranslate)\r\n                              }\">\r\n            </salaxy-input-enum>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"$ctrl.isSaving('incomesRegister')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('incomesRegister')\"><span ng-if=\"$ctrl.isSaving('incomesRegister')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel einvoice panel-default\" ng-if=\"$ctrl.sections.indexOf('eInvoice') >= 0\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2>\r\n        <span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.einvoice.title\"></span>\r\n        <i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.einvoice.description\"></small></p>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <form name=\"eInvoiceForm\" class=\"einvoice-form\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n            <fieldset>\r\n              <salaxy-form-group name=\"eInvoiceReceiver\" label=\"SALAXY.NG1.PaymentSettingsComponent.einvoice.invoiceAddress\">\r\n                <div class=\"input-group\">\r\n                  <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"eInvoiceReceiver\" name=\"eInvoiceReceiver\" ng-disabled=\"true\" ng-model=\"$ctrl.current.payments.invoice.eInvoiceReceiver\">\r\n                  <span class=\"input-group-btn\">\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-if=\"!$ctrl.isReadOnlyForced\" ng-click=\"$ctrl.selectEInvoiceAddress()\" sxy-text=\"SALAXY.UI_Terms.choose\"></button>\r\n                  </span>\r\n                </div>\r\n              </salaxy-form-group>\r\n              <salaxy-input disabled=\"true\" name=\"intermediator\" ng-model=\"$ctrl.current.payments.invoice.eInvoiceIntermediator\" label=\"SALAXY.NG1.NewPaymentComponent.einvoice.intermediatorLabel\"></salaxy-input>\r\n\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"$ctrl.isSaving('eInvoice')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('eInvoice')\"><span ng-if=\"$ctrl.isSaving('eInvoice')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel sepa panel-default\" ng-if=\"$ctrl.sections.indexOf('sepa') >= 0\">\r\n    <form name=\"sepaForm\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n      <div class=\"panel-heading icon-panel\">\r\n        <h2>\r\n          <span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.sepa.title\"></span>\r\n          <i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n        </h2>\r\n        <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.sepa.title\"></small></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12 form-horizontal\">\r\n            <fieldset>\r\n              <salaxy-input name=\"ibanNumber\" label=\"SALAXY.NG1.PaymentSettingsComponent.sepa.iban\" ng-model=\"$ctrl.current.payments.invoice.ibanNumber\" sxy-iban></salaxy-input>\r\n              <salaxy-input name=\"sepaBankPartyId\" label=\"SALAXY.NG1.PaymentSettingsComponent.sepa.sepaId\" ng-model=\"$ctrl.current.payments.invoice.sepaBankPartyId\"></salaxy-input>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-12\">\r\n            <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"sepaForm.$invalid || $ctrl.isSaving('sepa')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('sepa')\"><span ng-if=\"$ctrl.isSaving('sepa')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </form>\r\n  </div>\r\n\r\n  <div class=\"panel taxAndSocialSecuritySelfHandling panel-default\" ng-if=\"$ctrl.sections.indexOf('taxAndSocialSecuritySelfHandling') >= 0\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.taxSelfHandling.title\"></span><i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.taxSelfHandling.intro\"></small></p>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.taxSelfHandling.intro2\"></small></p>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <fieldset>\r\n            <salaxy-input-boolean read-only=\"$ctrl.isReadOnlyForced\" type=\"checkbox\" name=\"isTaxAndSocialSecuritySelfHandling\" label-type=\"plain\" label-true=\"SALAXY.NG1.PaymentSettingsComponent.taxSelfHandling.taxSelfHandlingTrue\" ng-model=\"$ctrl.current.payments.customerFunds.isTaxAndSocialSecuritySelfHandling\"></salaxy-input-boolean>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"$ctrl.isSaving('taxAndSocialSecuritySelfHandling')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('taxAndSocialSecuritySelfHandling')\"><span ng-if=\"$ctrl.isSaving('taxAndSocialSecuritySelfHandling')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n  <div class=\"panel workerSelfHandling panel-default\" ng-if=\"$ctrl.sections.indexOf('workerSelfHandling') >= 0\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.workerSelfHandling.title\"></span> <i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.workerSelfHandling.intro\"></small></p>\r\n      <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.workerSelfHandling.intro2\"></small></p>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <fieldset>\r\n            <salaxy-input-boolean read-only=\"$ctrl.isReadOnlyForced\" type=\"checkbox\" name=\"isWorkerSelfHandling\" label-type=\"plain\" label-true=\"SALAXY.NG1.PaymentSettingsComponent.workerSelfHandling.workerSelfHandlingTrue\" ng-model=\"$ctrl.current.payments.customerFunds.isWorkerSelfHandling\"></salaxy-input-boolean>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"panel-footer\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <button ng-if=\"!$ctrl.isReadOnlyForced\" ng-disabled=\"$ctrl.isSaving('workerSelfHandling')\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save('workerSelfHandling')\"><span ng-if=\"$ctrl.isSaving('workerSelfHandling')\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n\r\n  <div class=\"panel unemployment panel-default\" ng-if=\"$ctrl.sections.indexOf('unemploymentSelfHandling') >= 0\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2><span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.unemployment.title\"></span><i class=\"fa fa-check-circle text-success status-icon\"></i>\r\n      </h2>\r\n\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <fieldset>\r\n            <p sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.unemployment.intro\"></p>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel salarySlipDeliveryMethods panel-default\" ng-if=\"$ctrl.sections.indexOf('payslip') >= 0  && ('test,payslip' | sxyIsInRole)\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2>\r\n        <span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.salarySlipDeliveryMethods.payslip.title\"></span>\r\n      </h2>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <form name=\"salarySlipDeliveryMethodsForm\" class=\"salarySlipDeliveryMethods-form\">\r\n            <fieldset>\r\n              <p><small sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.salarySlipDeliveryMethods.payslip.description\"></small></p>\r\n              <salaxy-input-boolean label=\"SALAXY.ENUM.WorkerSalarySlipDeliveryMethod.payslip.label\" name=\"payslip\" type=\"checkbox\" ng-model=\"$ctrl.payslip\" disabled=\"$ctrl.disableSwitchInput()\"></salaxy-input-boolean>\r\n            </fieldset>\r\n          </form>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"panel omapalkka panel-default\" ng-if=\"$ctrl.sections.indexOf('omapalkka') >= 0 && ('test,admin' | sxyIsInRole)\">\r\n    <div class=\"panel-heading icon-panel\">\r\n      <h2>\r\n        <span sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.salarySlipDeliveryMethods.omapalkka.title\"></span>\r\n      </h2>\r\n    </div>\r\n    <div class=\"panel-body\">\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 form-horizontal\">\r\n          <form name=\"omapalkkaForm\" class=\"omapalkka-form\">\r\n            <fieldset>\r\n              <salaxy-input-boolean label=\"SALAXY.ENUM.WorkerSalarySlipDeliveryMethod.omapalkka.label\" name=\"omapalkka\" type=\"checkbox\" ng-model=\"$ctrl.omapalkka\" disabled=\"$ctrl.disableSwitchInput()\"></salaxy-input-boolean>\r\n            </fieldset>\r\n          </form>\r\n          <salaxy-form-group name=\"paidCalculationsToOmapalkka\" label=\"SALAXY.NG1.PaymentSettingsComponent.salarySlipDeliveryMethods.omapalkka.label\">\r\n            <div class=\"input-group\">\r\n              <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.sendPaidCalculationsToOmapalkka()\" sxy-text=\"SALAXY.NG1.PaymentSettingsComponent.salarySlipDeliveryMethods.omapalkka.sendToOmapalkkaButtonText\"></button>\r\n            </div>\r\n          </salaxy-form-group>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/ProSettings.html\",`<div class=\"salaxy-component salaxy-pro-settings\">\r\n  <div class=\"btn-toolbar\">\r\n    <button class=\"btn btn-primary\" ng-click=\"$ctrl.save('all')\" ng-disabled=\"$ctrl.isSaving('all')\"><span ng-if=\"$ctrl.isSaving('all')\"><i\r\n          class=\"fa fa-refresh fa-spin fa-fw\"></i></span> <span sxy-text=\"SALAXY.UI_Terms.save\"></span></button>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"CompanyAccountSettings\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n      <div>\r\n        <uib-tabset active=\"$ctrl.currentTab\">\r\n          <uib-tab index=\"'insurances'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.insurances' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.insurances\"></span> </legend>\r\n              <sxy-input model=\"form.calc.pensionContracts\" template-url=\"salaxy-components/sxy-form/custom-templates/array-pension.html\">\r\n                <form>\r\n                  <fieldset>\r\n                    <sxy-input model=\"form.company\"></sxy-input>\r\n                    <sxy-input model=\"form.contractNumber\" format=\"pension-contract-number\"></sxy-input>\r\n                    <sxy-input model=\"form.startDate\" format=\"date\"></sxy-input>\r\n                    <sxy-input model=\"form.endDate\" format=\"date\"></sxy-input>\r\n                    <sxy-input model=\"form.pensionDefaultPercent\"></sxy-input>\r\n                    <sxy-input model=\"form.pensionPercent\"></sxy-input>\r\n                    <sxy-input ng-show=\"['kevaMunicipal','kevaAland','kevaChurch','kevaKela','kevaState'].indexOf($ctrl.current.company) >= 0\" model=\"form.subOrgCode\"></sxy-input>\r\n                    <sxy-input ng-show=\"'admin' | sxyIsInRole\" model=\"form.pensionDiscountPercent\"></sxy-input>\r\n                    <sxy-input ng-show=\"'admin' | sxyIsInRole\" model=\"form.status\" read-only=\"false\"></sxy-input>\r\n                    <sxy-input ng-show=\"'!admin' | sxyIsInRole\" model=\"form.status\" read-only=\"true\"></sxy-input>\r\n                    <!--sxy-input model=\"form.id\" read-only=\"true\"></sxy-input-->\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n              <sxy-input model=\"form.calc.insuranceContracts\" template-url=\"salaxy-components/sxy-form/custom-templates/array-insurance.html\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.insurance\"></span> </legend>\r\n                    <sxy-input model=\"form.company\"></sxy-input>\r\n                    <sxy-input model=\"form.contractNumber\"></sxy-input>\r\n                    <sxy-input model=\"form.startDate\" format=\"date\"></sxy-input>\r\n                    <sxy-input model=\"form.endDate\" format=\"date\"></sxy-input>\r\n                    <sxy-input model=\"form.insurancePercent\"></sxy-input>\r\n                    <sxy-input model=\"form.groupLifeInsurancePercent\"></sxy-input>\r\n                    <sxy-input model=\"form.isPartnerInsurance\"></sxy-input>\r\n                    <sxy-input ng-show=\"'admin' | sxyIsInRole\" model=\"form.status\" read-only=\"false\"></sxy-input>\r\n                    <sxy-input ng-show=\"'!admin' | sxyIsInRole\" model=\"form.status\" read-only=\"true\"></sxy-input>\r\n                    <!--sxy-input model=\"form.id\" read-only=\"true\"></sxy-input-->\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.unemploymentInsurance\"></span> </legend>\r\n              <sxy-input model=\"form.calc.unemploymentInsurance.payrollLimitStatus\"></sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'rows'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.defaultRows' | sxyTranslate}}\">\r\n            <salaxy-calc-rows-editor ng-if=\"!$ctrl.isLoading\" rows=\"$ctrl.current.calc.salaryDefaults\"\r\n              title=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.defaultCalcRows' | sxyTranslate }}\" type=\"salary-defaults\"></salaxy-calc-rows-editor>\r\n          </uib-tab>\r\n          <uib-tab index=\"'coms'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.messagingAndLayout' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.messaging\"></span> <span\r\n                  ng-if=\"!$ctrl.current.messaging.denyServiceModel && $ctrl.current.partner.serviceModel.features.messaging\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.messaging\" label=\"SALAXY.NG1.ProSettingsComponent.customMessages\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"messagingDeny\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.messaging\" ng-model=\"$ctrl.current.messaging.denyServiceModel\"></salaxy-input-boolean>\r\n              <salaxy-input-boolean ng-if=\"$ctrl.current.partner.serviceModel.features.messaging\" read-only=\"!$ctrl.current.messaging.denyServiceModel\"\r\n                ng-model=\"$ctrl.current.messaging.partnerMessages\" name=\"partnerMessages\" label=\"SALAXY.NG1.ProSettingsComponent.messagesAccountant\"></salaxy-input-boolean>\r\n              <salaxy-input-enum read-only=\"!$ctrl.current.messaging.denyServiceModel && $ctrl.current.partner.serviceModel.features.messaging\" type=\"multi-select\"\r\n                enum=\"WorkerSalaryNotification\" ng-model=\"$ctrl.current.messaging.workerSalaryNotifications\" name=\"workerSalaryNotifications\"\r\n                label=\"SALAXY.NG1.ProSettingsComponent.messagesPayment\"></salaxy-input-enum>\r\n              <salaxy-input-enum read-only=\"!$ctrl.current.messaging.denyServiceModel && $ctrl.current.partner.serviceModel.features.messaging\" type=\"multi-select\"\r\n                enum=\"WorkerSalarySlipDeliveryMethod\" ng-model=\"$ctrl.current.messaging.workerSalarySlipDeliveryMethods\" name=\"workerSalarySlipDeliveryMethods\"\r\n                label=\"SALAXY.NG1.ProSettingsComponent.workerSalarySlipDeliveryMethods\"></salaxy-input-enum>\r\n            </fieldset>\r\n            <fieldset ng-init=\"$ctrl.isReportLogoManuallyUploaded = false\">\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.reporting\"></span> <span\r\n                  ng-if=\"!$ctrl.current.reporting.denyServiceModel && $ctrl.current.partner.serviceModel.features.reporting\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.reporting\" label=\"SALAXY.NG1.ProSettingsComponent.customReporting\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc4\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.reporting\" ng-model=\"$ctrl.current.reporting.denyServiceModel\"></salaxy-input-boolean>\r\n              <salaxy-input-enum read-only=\"!$ctrl.current.reporting.denyServiceModel && $ctrl.current.partner.serviceModel.features.reporting\"\r\n                ng-model=\"$ctrl.current.reporting.layoutTemplateId\" name=\"layputTemplateId\" label=\"SALAXY.NG1.ProSettingsComponent.layoutTemplateId\" options=\"{'palkkaus-report-options@FI53POYS0025543933': ('SALAXY.NG1.ProSettingsComponent.templateIdPalkkaus' | sxyTranslate),\r\n                'no-logo-report-options@FI53POYS0025543933': ('SALAXY.NG1.ProSettingsComponent.templateIdNoLogo' | sxyTranslate),\r\n                'logo-report-options@FI53POYS0025543933': ('SALAXY.NG1.ProSettingsComponent.templateIdLogo' | sxyTranslate)\r\n               }\"></salaxy-input-enum>\r\n               <salaxy-input-boolean ng-if=\"$ctrl.current.reporting.layoutTemplateId == 'logo-report-options@FI53POYS0025543933'\" type=\"radio\" name=\"reportLogoUploadType\" label=\"SALAXY.NG1.ProSettingsComponent.fileUpload.uploadMethod\" ng-model=\"$ctrl.isReportLogoManuallyUploaded\" label-true=\"SALAXY.NG1.ProSettingsComponent.fileUpload.manualUpload\" label-false=\"SALAXY.NG1.ProSettingsComponent.fileUpload.uploadFromDevice\"></salaxy-input-boolean>\r\n               <div class=\"form-group\" ng-if=\"!$ctrl.isReportLogoManuallyUploaded && $ctrl.current.reporting.layoutTemplateId == 'logo-report-options@FI53POYS0025543933'\">\r\n                  <div class=\"col-xs-12 col-sm-4\">\r\n                    <label for=\"avatarImageUpload\" sxy-text=\"SALAXY.NG1.ProSettingsComponent.fileUpload.previewLabel\"></label>\r\n                  </div>\r\n                  <div class=\"col-xs-12 col-sm-8\">\r\n                    <div name=\"avatarImageUpload\" ng-model=\"avatarImage\" ngf-drop=\"$ctrl.createReportLogoDatauri($file)\" ngf-select=\"$ctrl.createReportLogoDatauri($file)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" ngf-multiple=\"false\" ngf-min-size=\"1KB\" ngf-max-size=\"10MB\"\r\n                       ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\">\r\n                      <span sxy-html=\"SALAXY.NG1.AccountAvatarEditPersonComponent.uploadImage.html\"></span>\r\n                    </div>\r\n                  </div>\r\n              </div>\r\n              <salaxy-textarea maxlength=\"\" read-only=\"!$ctrl.current.reporting.denyServiceModel && $ctrl.current.partner.serviceModel.features.reporting\"\r\n                label=\"SALAXY.NG1.ProSettingsComponent.customReportLogo\" name=\"logo\" ng-model=\"$ctrl.current.reporting.logo\" rows=\"3\"\r\n                ng-if=\"$ctrl.current.reporting.layoutTemplateId == 'logo-report-options@FI53POYS0025543933' && $ctrl.isReportLogoManuallyUploaded\">\r\n              </salaxy-textarea>\r\n              <div class=\"form-group\" ng-if=\"$ctrl.current.reporting.logo && $ctrl.current.reporting.layoutTemplateId == 'logo-report-options@FI53POYS0025543933'\">\r\n                <div class=\"col-xs-12 col-sm-4\">\r\n                  <label for=\"avatarImageUpload\" sxy-text=\"Logo\"></label>\r\n                </div>\r\n                <div class=\"col-xs-12 col-sm-8\">\r\n                  <div class=\"salaxy-report-logo-preview\">\r\n                    <div ng-bind-html=\"$ctrl.getReportLogo()\" ></div>\r\n                  </div>\r\n                </div>\r\n              </div>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'payment-channels'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.paymentChannels' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.selfHandling\"></span> </legend>\r\n              <sxy-input model=\"form.payments.customerFunds.isWorkerSelfHandling\"></sxy-input>\r\n              <sxy-input model=\"form.payments.customerFunds.isPensionSelfHandling\"></sxy-input>\r\n              <sxy-input model=\"form.payments.customerFunds.isTaxAndSocialSecuritySelfHandling\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.invoices\"></span> </legend>\r\n              <sxy-input model=\"form.payments.invoice.eInvoiceReceiver\"></sxy-input>\r\n              <sxy-input model=\"form.payments.invoice.eInvoiceIntermediator\"></sxy-input>\r\n              <sxy-input model=\"form.payments.invoice.sepaBankPartyId\"></sxy-input>\r\n              <sxy-input model=\"form.payments.invoice.ibanNumber\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.paymentChannels\"></span> <span\r\n                  ng-if=\"!$ctrl.current.payments.denyServiceModel && $ctrl.current.partner.serviceModel.features.payments\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.payments\" label=\"SALAXY.NG1.ProSettingsComponent.customPaymentChannels\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc1\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.payments\" ng-model=\"$ctrl.current.payments.denyServiceModel\"></salaxy-input-boolean>\r\n\r\n              <salaxy-input-enum class=\"default-channel-input-enum\" disabled=\"!$ctrl.current.payments.denyServiceModel && $ctrl.current.partner.serviceModel.features.payments\"\r\n                type=\"typeahead\" name=\"options_type\" ng-model=\"$ctrl.current.payments.defaultChannel\" options=\"$ctrl.getSelectablePaymenMethods()\" disable-cache=\"true\"\r\n                label=\"SALAXY.NG1.ProSettingsComponent.defaultChannel\"></salaxy-input-enum>\r\n\r\n              <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-payment-channels.html\" model=\"form.payments.channels\"\r\n                read-only=\"{{!$ctrl.current.payments.denyServiceModel && $ctrl.current.partner.serviceModel.features.payments}}\">\r\n                <form>\r\n                  <fieldset ng-init=\"$ctrl.logic.showDelete = false\">\r\n                    <sxy-input model=\"form.channel\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.isAvailable\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.isEnabled\" read-only=\"{{!$ctrl.current.isAvailable}}\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'dimansions'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.dimensions' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.MODEL.CostAccountingSettings.title\"></span> <span\r\n                  ng-if=\"!$ctrl.current.costAccounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.costAccounting\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.costAccounting\" label=\"SALAXY.NG1.ProSettingsComponent.customCostAccounting\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc5\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.costAccounting\" ng-model=\"$ctrl.current.costAccounting.denyServiceModel\"></salaxy-input-boolean>\r\n              <sxy-input model=\"form.costAccounting.dimensions\"\r\n                read-only=\"{{!$ctrl.current.costAccounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.costAccounting }}\" include=\"id,label,scope\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.CostAccountingDimensionDefinition.title\"></legend>\r\n                    <sxy-input model=\"form.id\" read-only=\"{{$ctrl.logic.showDelete}}\"></sxy-input>\r\n                    <sxy-input model=\"form.label\"></sxy-input>\r\n                    <sxy-input model=\"form.allowCostSharing\"></sxy-input>\r\n                    <sxy-input model=\"form.scope\"></sxy-input>\r\n                    <sxy-input model=\"form.options\" template-url=\"salaxy-components/sxy-form/custom-templates/cost-accounting-options.html\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'accounting'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.accounting' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.accounting\"></span> <span\r\n                  ng-if=\"!$ctrl.current.accounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.accounting\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.accounting\" label=\"SALAXY.NG1.ProSettingsComponent.customAccounting\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc2\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.accounting\" ng-model=\"$ctrl.current.accounting.denyServiceModel\"></salaxy-input-boolean>\r\n              <salaxy-input-enum read-only=\"!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting\" type=\"typeahead\"\r\n                name=\"options_type\" ng-model=\"$ctrl.current.accounting.defaultTargetId\" options=\"$ctrl.getSelectableAccountingTargets()\" disable-cache=\"true\"\r\n                label=\"SALAXY.NG1.ProSettingsComponent.defaultTarget\"></salaxy-input-enum>\r\n              <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-accounting-targets.html\" model=\"form.accounting.targets\"\r\n                read-only=\"{{!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting}}\">\r\n                <form>\r\n                  <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"CompanySettingsController as $companySettingsCtrl\" ng-init=\"$ctrl.logic.isReadOnly = true\">\r\n                    <salaxy-odata-table url=\"/v03/api/accounting-target\" template-url=\"salaxy-components/odata/lists/AccountingTargetSelect.html\"\r\n                      selected-items=\"$ctrl.selectedItems\" on-list-select=\"$companySettingsCtrl.onAccountingTargetSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                    </salaxy-odata-table>\r\n                  </fieldset>\r\n                  <fieldset ng-show=\"$ctrl.logic.showDelete\" ng-controller=\"AccountingChannelSettingsController as $settings\" ng-init=\"$ctrl.logic.isReadOnly = false\">\r\n                    <salaxy-input-enum disabled=\"false\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsvFormat\" ng-model=\"$ctrl.current.format\"\r\n                    options=\"{\r\n                      '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                      '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                      '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                      'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                      '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                      '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                      '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                      'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                      'ba271dac-dd63-4036-9d70-053a09ca4d9e' :'Visma Netvisor',\r\n                      '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                      'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                      'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                      '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                      '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                    }\">\r\n                   </salaxy-input-enum>\r\n                    <sxy-input model=\"form.method\" read-only=\"false\"></sxy-input>           \r\n                    <salaxy-input-enum disabled=\"false\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.availableMethods.title\" name=\"availableMethods\"\r\n                      type=\"multi-select\" ng-model=\"$ctrl.current.availableMethods\"></salaxy-input-enum>\r\n                    <button ng-show=\"$settings.isApiIntegration($ctrl.current)\" type=\"button\" class=\"btn btn-sm btn-default\"\r\n                      ng-click=\"$settings.openChannelSetupDialog($ctrl.current, $close)\">\r\n                      Siirry APIn konfigurointiin <i class=\"fa fa-external-link\"></i>\r\n                    </button>\r\n                    <button ng-show=\"$settings.isApiIntegration($ctrl.current)\" type=\"button\" class=\"btn btn-sm btn-default\"\r\n                      ng-click=\"$settings.configureCoa($ctrl.current, $close)\">\r\n                      Siirry tilikartan konfigurointiin <i class=\"fa fa-chevron-right\"></i>\r\n                    </button>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n              <sxy-input model=\"form.accounting.defaultPeriodDateKind\"\r\n                read-only=\"{{!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting}}\"></sxy-input>\r\n              <salaxy-input-enum ng-if=\"$ctrl.defaultAccountingTarget\"\r\n                read-only=\"!$ctrl.current.accounting.denyServiceModel  && $ctrl.current.partner.serviceModel.features.accounting\" type=\"select\" name=\"method\"\r\n                ng-model=\"$ctrl.defaultAccountingTarget.method\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.method.title\"></salaxy-input-enum>\r\n              <legend sxy-text=\"SALAXY.MODEL.AccountingSettings.reportDelivery.title\"></legend>\r\n              <sxy-input model=\"form.accounting.reportDelivery.isEnabled\"></sxy-input>\r\n              <sxy-input model=\"form.accounting.reportDelivery.address\"></sxy-input>\r\n              <legend sxy-text=\"SALAXY.MODEL.AccountingSettings.accountantReportDelivery.title\"></legend>\r\n              <sxy-input model=\"form.accounting.accountantReportDelivery.isEnabled\"></sxy-input>\r\n              <sxy-input model=\"form.accounting.accountantReportDelivery.address\"></sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'holidays'\" heading=\"Lomalaskenta\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.MODEL.HolidaySettings.title\"></span> <span\r\n                  ng-if=\"!$ctrl.current.costAccounting.denyServiceModel && $ctrl.current.partner.serviceModel.features.holiday\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.holiday\" label=\"SALAXY.NG1.ProSettingsComponent.customHoliday\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc6\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.holiday\" ng-model=\"$ctrl.current.holiday.denyServiceModel\"></salaxy-input-boolean>\r\n              <sxy-input model=\"form.holiday.holidayPaySettings\"\r\n                read-only=\"{{!$ctrl.current.holiday.denyServiceModel  && $ctrl.current.partner.serviceModel.features.holiday }}\" include=\"holidayPayCalculation\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.title\"></legend>\r\n                    <salaxy-input-enum enum=\"HolidayPayCalculation\" label=\"SALAXY.MODEL.HolidayPaySettings.holidayPayCalculation.title\" name=\"holidayPayCalculation\" filter=\"averageDailyPay,averageHourlyPay,percentageBasedPay,holidayCompensation\" require=\"true\" ng-model=\"$ctrl.current.holidayPayCalculation\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.salaryTypes.title\"></legend>\r\n                    <sxy-input model=\"form.salaryTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.workingTimeTypes.title\"></legend>\r\n                    <sxy-input ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.overtimeTypes.title\"></legend>\r\n                    <sxy-input  ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" model=\"form.overtimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\"></legend>\r\n                    <salaxy-input-holiday-multipliers ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" name=\"multipliers\" label=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\" ng-model=\"$ctrl.current.multipliers\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-holiday-multipliers>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n              <sxy-input model=\"form.holiday.holidayAccrualSettings\"\r\n                read-only=\"{{!$ctrl.current.holiday.denyServiceModel  && $ctrl.current.partner.serviceModel.features.holiday }}\" include=\"code\">\r\n                <form>\r\n                  <fieldset>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.title\"></legend>\r\n                    <salaxy-input-enum enum=\"HolidayCode\" label=\"SALAXY.MODEL.HolidayAccrualSettings.code.title\" name=\"code\" filter=\"permanent35Hours\" require=\"true\" ng-model=\"$ctrl.current.code\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                    <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.workingTimeTypes.title\"></legend>\r\n                    <sxy-input model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'other'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.other' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.incomesRegister\"></span> </legend>\r\n              <sxy-input model=\"form.calc.incomesRegister.irReporting\"></sxy-input>\r\n              <sxy-input model=\"form.calc.incomesRegister.taxReferenceNumber\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.usecases\"></span> <span\r\n                  ng-if=\"!$ctrl.current.usecase.denyServiceModel && $ctrl.current.partner.serviceModel.features.usecase\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.usecase.serverUrl\" label=\"Integration server (staging)\"></sxy-input>\r\n              <sxy-input model=\"form.partner.serviceModel.features.usecase\" label=\"SALAXY.NG1.ProSettingsComponent.customUsecases\" read-only=\"true\"></sxy-input>\r\n              <salaxy-input-boolean label=\"SALAXY.NG1.ProSettingsComponent.overwriteServiceModel\" name=\"uc3\" ng-change=\"$ctrl.confirmServiceModelChange()\"\r\n                ng-if=\"$ctrl.current.partner.serviceModel.features.usecase\" ng-model=\"$ctrl.current.usecase.denyServiceModel\"></salaxy-input-boolean>\r\n              <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-usecase.html\" model=\"form.usecase.usecases\"\r\n                read-only=\"{{!$ctrl.current.usecase.denyServiceModel  && $ctrl.current.partner.serviceModel.features.usecase}}\">\r\n                <form>\r\n                  <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"CompanySettingsController as $companySettingsCtrl\">\r\n                    <salaxy-odata-table url=\"/v03/api/usecases\" template-url=\"salaxy-components/odata/lists/UsecaseSelect.html\" selected-items=\"$ctrl.selectedItems\"\r\n                      on-list-select=\"$companySettingsCtrl.onUsecaseSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                    </salaxy-odata-table>\r\n                  </fieldset>\r\n                  <fieldset ng-show=\"$ctrl.logic.showDelete\">\r\n                    <sxy-input model=\"form.uri\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.label\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.itemType\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.status\"></sxy-input>\r\n                    <sxy-input model=\"form.order\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'read-only'\" heading=\"{{'SALAXY.NG1.ProSettingsComponent.tabs.read-only' | sxyTranslate}}\">\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.pricing\"></span> <span ng-if=\"$ctrl.current.partner.accountId\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.pricing.pricingModel\" read-only=\"true\"></sxy-input>\r\n              <sxy-input model=\"form.partner.serviceModel.pricing.fixedFee\" read-only=\"true\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.webApp\"></span> <span class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.site.webApp\" read-only=\"true\"></sxy-input>\r\n              <sxy-input model=\"form.partner.serviceModel.site.webAppUrl\" read-only=\"true\"></sxy-input>\r\n              <sxy-input model=\"form.partner.serviceModel.site.webAppName\" read-only=\"true\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.NG1.ProSettingsComponent.branding\"></span> <span class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.branding.logo\" read-only=\"true\"></sxy-input>\r\n              <sxy-input model=\"form.partner.serviceModel.branding.skin\" read-only=\"true\"></sxy-input>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend><span sxy-text=\"SALAXY.MODEL.FormsSettings.title\"></span> <span\r\n                  ng-if=\"!$ctrl.current.forms.denyServiceModel && $ctrl.current.partner.serviceModel.features.forms\" class=\"badge bg-danger pull-right\"\r\n                  sxy-text=\"SALAXY.NG1.ProSettingsComponent.serviceModelBadge\"></span></legend>\r\n              <sxy-input model=\"form.partner.serviceModel.features.forms\" label=\"SALAXY.NG1.ProSettingsComponent.customForms\" read-only=\"true\"></sxy-input>\r\n            </fieldset>\r\n          </uib-tab>\r\n        </uib-tabset>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/RowTypesSettings.html\",`<div class=\"salaxy-component salaxy-pro-settings\" ng-class=\"'salaxy-pro-settings-' + $ctrl.mode\"\r\n  ng-if=\"$ctrl.current\" ng-switch=\"$ctrl.mode\">\r\n  <div ng-switch-when=\"custom\">\r\n    <div style=\"display: flex;\">\r\n      <div class=\"btn-group pull-left\" uib-dropdown>\r\n        <button id=\"categories\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n          Kategoriat <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = null\">All categories (no filter)</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['salary', 'salaryCalc', 'holidays', 'salaryAdditions']\">Salaries and additions</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['benefits']\">Benefits</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['expenses']\">Expenses</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['deductions']\">Deductions</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['other']\">Other</a></li>\r\n        </ul>\r\n      </div>\r\n      <div class=\"form-horizontal\" style=\"margin-left: 10px; flex-grow: 10;\">\r\n        <salaxy-input name=\"calcRowTypeSearch\" ng-model=\"$ctrl.searchText\" label=\"Search name and description\"></salaxy-input>\r\n      </div>\r\n    </div>\r\n    <ng-include src=\"'salaxy-components/settings/RowTypesSettings_table.html'\"></ng-include>\r\n  </div>\r\n  <div ng-switch-when=\"prices\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">Rivityyppien hinnat</th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.DateRange.labelStartAndEndDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.price\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.pricesList\">\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td style=\"width: 40%;\">\r\n            <div>{{row.message || $ctrl.getConfig(row).label || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div><small><code>{{ row.type }}{{ row.data.kind ? \"/\" + row.data.kind : \"\" }}</code></small>  &nbsp;</div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <div>{{ row.period | sxyDateRange }}&nbsp;&nbsp;</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <salaxy-input-number name=\"{{ 'iptPrice' + row.rowIndex }}\" ng-model=\"row.price\" label-type=\"plain\"  disabled=\"$ctrl.isDisabled(row, 'price')\" require=\"true\"></salaxy-input-number>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\"><i class=\"fa fa-pencil-square\"></i></button>\r\n            <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.delete(row)\"><i class=\"fa fa-trash\"></i>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n      <tfoot>\r\n        <tr>\r\n          <td></td>\r\n          <td class=\"middle\">\r\n            Lisää hinta:\r\n          </td>\r\n          <td>\r\n            <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\"\r\n              on-row-changed=\"$ctrl.commitNewRow('price', false)\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tfoot>\r\n    </table>\r\n  </div>\r\n  <div ng-switch-when=\"defaults\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">Oletusrivit</th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.DateRange.labelStartAndEndDate\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.totals.total\"></th>\r\n          <th></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.defaultsList\">\r\n          <td style=\"width: 32px;\">\r\n            <salaxy-avatar ng-if=\"row.rowType\" class=\"salaxy-calc-row-type-avatar\"\r\n              avatar=\"{ color: $ctrl.getConfig(row).color, initials: $ctrl.getConfig(row).iconText, entityType: 'company' }\"></salaxy-avatar>\r\n          </td>\r\n          <td style=\"width: 40%;\">\r\n            <div>{{row.message || ( \"CalculationRowType.\" + row.rowType | sxyEnum) }}</div>\r\n            <div>{{row.data.kind }}&nbsp;</div>\r\n          </td>\r\n          <td class=\"right middle\">\r\n            <div>{{ row.period | sxyDateRange }}&nbsp;&nbsp;</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <salaxy-input-number name=\"{{ 'iptPrice' + row.rowIndex }}\" ng-model=\"row.price\" label-type=\"plain\"  disabled=\"$ctrl.isDisabled(row, 'price')\" require=\"true\"></salaxy-input-number>\r\n          </td>\r\n          <td class=\"right\">\r\n            <button type=\"button\" class=\"edit btn btn-info\" ng-click=\"$ctrl.showEdit(row, 'auto')\"\r\n              title=\"{{'SALAXY.NG1.CalcRowsComponent.editor.buttons.infoIcon' | sxyTranslate}}\">\r\n              <i class=\"fa fa-info-circle\" ng-class=\"$ctrl.current == row ? 'fa-arrow-circle-right' : 'fa-info-circle'\"></i></button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n      <tfoot>\r\n        <tr>\r\n          <td></td>\r\n          <td class=\"middle\">\r\n            Lisää oletusrivi:\r\n          </td>\r\n          <td>\r\n            <salaxy-calc-row-type name=\"newRowType\" model=\"$ctrl.newRow\" placeholder=\"SALAXY.NG1.CalcRowsComponent.editor.calcRowTypePlaceholder\"\r\n              on-row-changed=\"$ctrl.commitNewRow('manualRow', true)\" categories=\"$ctrl.categories\"></salaxy-calc-row-type>\r\n          </td>\r\n          <td>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showRowTypeSelectionDialog()\"><i class=\"fa fa-info fa-lg fa-fw text-primary\"></i> <span\r\n                sxy-text=\"SALAXY.NG1.CalcRowsComponent.editor.buttons.readMore\" ps=\"...\"></span></button>\r\n          </td>\r\n        </tr>\r\n      </tfoot>\r\n    </table>\r\n  </div>\r\n  <div ng-switch-when=\"debugger\">\r\n    <salaxy-json-formatter key=\"'Rivit'\" json=\"$ctrl.list\" open=\"1\"></salaxy-json-formatter>\r\n    <hr />\r\n    <salaxy-calc-rows-editor ng-if=\"!$ctrl.isLoading\" rows=\"$ctrl.list\"\r\n      title=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.defaultCalcRows' | sxyTranslate }}\" type=\"salary-defaults\"></salaxy-calc-rows-editor>\r\n  </div>\r\n  <div ng-switch-default>\r\n    <div style=\"display: flex;\">\r\n      <div class=\"btn-group pull-left\" uib-dropdown>\r\n        <button id=\"categories\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"disabled\">\r\n          Kategoriat <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = null\">All categories (no filter)</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['salary', 'salaryCalc', 'holidays', 'salaryAdditions']\">Salaries and additions</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['benefits']\">Benefits</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['expenses']\">Expenses</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['deductions']\">Deductions</a></li>\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.categories = ['other']\">Other</a></li>\r\n        </ul>\r\n      </div>\r\n      <div class=\"form-horizontal\" style=\"margin-left: 10px; flex-grow: 10;\">\r\n        <salaxy-input name=\"calcRowTypeSearch\" ng-model=\"$ctrl.searchText\" label=\"Search name and description\"></salaxy-input>\r\n      </div>\r\n    </div>\r\n    <ng-include src=\"'salaxy-components/settings/RowTypesSettings_table.html'\"></ng-include>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/RowTypesSettings_table.html\",`<div class=\"salaxy-calc-row-type-table\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr class=\"active\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: 'rgb(79, 205, 196)', initials: 'type', entityType: 'company' }\"></salaxy-avatar>\r\n        </td>\r\n        <td>\r\n          <div><b sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowType\" ps=\" (type)\"></b></div>\r\n          <div sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowDescription\"></div>\r\n        </td>\r\n        <td><b sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowTypeEn\"></b></td>\r\n        <td></td>\r\n      </tr>\r\n      <tr class=\"active\">\r\n        <td></td>\r\n        <td sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowKind\" ps=\" (kind)\"></td>\r\n        <td sxy-text=\"SALAXY.NG1.CalcRowTypeComponent.rowKindEn\"></td>\r\n        <td></td>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat-start=\"item in $ctrl.getCachedSearch($ctrl.searchText, true)\" ng-if=\"item.ui.iconText\">\r\n        <th rowspan=\"2\">\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"{ color: item.ui.color, initials: item.ui.iconText, entityType: 'company' }\"></salaxy-avatar>\r\n        </th>\r\n        <th>\r\n          <div>\r\n            <b class=\"salaxy-highlight\" ng-bind-html=\"item.text | uibTypeaheadHighlight:$ctrl.searchText\"></b>\r\n          </div>\r\n        </th>\r\n        <th>\r\n          <div class=\"salaxy-highlight\" ng-bind-html=\"item.value | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n        </th>\r\n        <th ng-if=\"item.ui.group == 'builtIn'\" style=\"width: 140px;\" rowspan=\"2\">\r\n          <div class=\"btn-group\">\r\n            <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showRowTypeDetails(item)\" title=\"{{ 'SALAXY.UI_Terms.show' | sxyTranslate }}\">\r\n              <i class=\"fa fa-info-circle fa-lg\" aria-hidden=\"true\"></i></button>\r\n            <button type=\"button\" class=\"btn btn-info\" ng-click=\"$ctrl.createCustomRowType(item)\" title=\"Räätälöi\">\r\n              <i class=\"fa fa-plus-square fa-lg\" aria-hidden=\"true\"></i></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.copyToClipboard(item.ui.type)\" title=\"Kopioi ID leikepöydälle\">\r\n              <i class=\"fa fa-clipboard fa-lg\" aria-hidden=\"true\"></i></button>\r\n          </div>\r\n        </th>\r\n        <th ng-if=\"item.ui.group != 'builtIn'\" style=\"width: 140px;\" rowspan=\"2\">\r\n          <div class=\"btn-group\">\r\n            <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showRowTypeDetails(item)\" title=\"{{ 'SALAXY.UI_Terms.edit' | sxyTranslate }}\">\r\n              <i class=\"fa fa-pencil-square fa-lg\" aria-hidden=\"true\"></i></button>\r\n            <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.deleteCustomRowType(item)\" title=\"Poista\">\r\n              <i class=\"fa fa-trash fa-lg\" aria-hidden=\"true\"></i></button>\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.copyToClipboard(item.ui.type)\" title=\"Kopioi ID leikepöydälle\">\r\n              <i class=\"fa fa-clipboard fa-lg\" aria-hidden=\"true\"></i></button>\r\n          </div>\r\n        </th>\r\n      </tr>\r\n      <tr ng-if=\"item.ui.iconText\" class=\"no-border\">\r\n        <td colspan=\"2\" style=\"padding-top: 0;\">\r\n          <div style=\"padding-top: 0;\" class=\"salaxy-highlight\" ng-bind-html=\"item.title | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"!item.ui.iconText\">\r\n        <td></td>\r\n        <td>\r\n          <div class=\"salaxy-highlight\" ng-bind-html=\"item.text | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n        </td>\r\n        <td colspan=\"2\">\r\n          <div class=\"salaxy-highlight\" ng-bind-html=\"item.value.split('.')[1] | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat-end ng-if=\"!item.ui.iconText\" class=\"no-border\">\r\n        <td></td>\r\n        <td colspan=\"3\" style=\"padding-top: 0;\">\r\n          <div class=\"salaxy-highlight\" ng-bind-html=\"item.title | uibTypeaheadHighlight:$ctrl.searchText\"></div>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/settings/ServiceModelDetails.html\",`<style>\r\n  /* TODO: Move to less */\r\n  \r\n  .salaxy-workspace {\r\n    display: flex;\r\n  }\r\n  \r\n  .salaxy-workspace-navi {\r\n    flex: 0 0 200px;\r\n  }\r\n  \r\n  .salaxy-workspace-content {\r\n    flex: 1 1 100%;\r\n    margin-left: -1px;\r\n    height: calc(100vh - 200px);\r\n    overflow-y: auto;\r\n    border: solid 1px #009fd8;\r\n    padding: 10px;\r\n  }\r\n  \r\n  .salaxy-workspace-content .container {\r\n    margin-left: 0px;\r\n  }\r\n</style>\r\n<!--\r\n\r\nTODO-lista:\r\n\r\nTyönkulut:\r\n\r\n- Itsepalvelu (Asiakas yksin)\r\n- Tilitoimisto tekee laskelman => Hyväksyntä => Tilitoimisto maksaa\r\n- Tilitoimisto tekee laskelman => Hyväksyntä => Asiakas maksaa\r\n- Asiakas tekee laskelman => PRO Tarkistaa => Asiakas maksaa\r\n- Asiakas tekee laskelman => PRO Tarkistaa => Tilitoimisto maksaa\r\n\r\nFlagit:\r\n\r\n- Aineiston lähetys: Näkyvissä / ei\r\n- Yritys: Maksaako vai hyväksyykö?\r\n\r\nMietittävä:\r\n\r\n- Entäs useita?\r\n- Saako muokata (osana hyväksyntää)?\r\n- Palkkalaskelman (Salary Slip) lähetys\r\n  - Notifikaatiot\r\n\r\n-->\r\n<div class=\"salaxy-component salaxy-service-model-details\">\r\n\r\n  <div class=\"btn-toolbar\" style=\"margin-left: 195px; margin-bottom: 2px;\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly || $ctrl.isReadOnly\" ng-click=\"$ctrl.saveServiceModel()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-disabled=\"$ctrl.isReadOnlyForced\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"> </button>\r\n      <button class=\"btn btn-default\" ng-click=\"$ctrl.reload()\" title=\"{{ 'SALAXY.UI_Terms.refresh' | sxyTranslate}}\"><i class=\"fa fa-refresh\" aria-hidden=\"true\"></i></button>\r\n    </div>\r\n    <div class=\"btn-group pull-right\">\r\n      <button type=\"button\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly || $ctrl.isReadOnly\" ng-click=\"$ctrl.delete($ctrl.current)\" sxy-text=\"Poista (test)\" ng-if=\"'test' | sxyIsInRole\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></button>\r\n\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <div class=\"form-inline\">\r\n        <div class=\"form-group\" style=\"line-height: 34px;\">\r\n          <strong> &nbsp; <span sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.name\"></span></strong> {{$ctrl.current.name}}\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"ServiceModel\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\" read-only=\"{{$ctrl.isReadOnly}}\">\r\n      <div ng-init=\"$ctrl.currentSection = 'basicInfo'\" class=\"salaxy-workspace\">\r\n        <div class=\"salaxy-workspace-navi\">\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'basicInfo'\" ng-class=\"$ctrl.currentSection == 'basicInfo' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.basicInfo\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'exports'\" ng-class=\"$ctrl.currentSection == 'exports' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.exports\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'branding'\" ng-class=\"$ctrl.currentSection == 'branding' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.branding\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'sitemap'\" ng-class=\"$ctrl.currentSection == 'sitemap' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.sitemap\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'messaging'\" ng-class=\"$ctrl.currentSection == 'messaging' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.messaging\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'i18n'\" ng-class=\"$ctrl.currentSection == 'i18n' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.i18n\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'workflow'\" ng-class=\"$ctrl.currentSection == 'workflow' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.workflow\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'usecases'\" ng-class=\"$ctrl.currentSection == 'usecases' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\" sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.usecases\"></label>\r\n          <label class=\"btn btn-block\" uib-btn-radio=\"'advanced'\" ng-class=\"$ctrl.currentSection == 'advanced' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Tech</label>\r\n        </div>\r\n        <div class=\"salaxy-workspace-content\">\r\n          <div ng-if=\"$ctrl.currentSection == 'basicInfo'\" class=\"form-horizontal container\">\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-8\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.serviceModelTitle\"></legend>\r\n                  <p><strong sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.serviceModelId\" ps=\":\"></strong> {{ $ctrl.current.id + \"@\" + $ctrl.current.owner }}</p>\r\n                  <sxy-input model=\"form.name\"></sxy-input>\r\n                  <sxy-input model=\"form.icon\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.serviceModelIcon\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-sm-4 text-center\">\r\n                <img ng-if=\"$ctrl.current.icon\" ng-src=\"{{ $ctrl.current.icon }}\" style=\"width: 100px; margin-top: 60px;\" />\r\n              </div>\r\n            </div>\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-8\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.endUserPricing\"></legend>\r\n                  <sxy-input model=\"form.pricing.pricingModel\"></sxy-input>\r\n                  <sxy-input model=\"form.pricing.fixedFee\" ng-if=\"$ctrl.current.pricing.pricingModel == 'fixedFee'\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-sm-4\"></div>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'exports'\" class=\"form-horizontal container\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.paymentChannelsTitle\"></legend>\r\n              <sxy-input model=\"form.features.payments\" format=\"switch\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customPaymentChannels\"></sxy-input>\r\n              <div ng-if=\"$ctrl.current.features.payments\">\r\n                <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-service-model-payment-channels.html\" model=\"form.payments.channels\">\r\n                  <form>\r\n                    <fieldset>\r\n                      <sxy-input model=\"form.channel\"></sxy-input>\r\n                      <sxy-input model=\"form.isAvailable\"></sxy-input>\r\n                      <sxy-input model=\"form.isEnabled\"></sxy-input>\r\n                    </fieldset>\r\n                  </form>\r\n                </sxy-input>\r\n\r\n                <salaxy-input-enum read-only=\"$ctrl.isReadOnly\" class=\"default-channel-input-enum\" type=\"typeahead\" name=\"options_type\" ng-model=\"$ctrl.current.payments.defaultChannel\" options=\"$ctrl.getSelectablePaymentChannels()\" ng-if=\"$ctrl.getSelectablePaymentChannels().length &gt; 1\"\r\n                  disable-cache=\"true\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.defaultChannel\"></salaxy-input-enum>\r\n              </div>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.accountingTitle\"></legend>\r\n              <sxy-input model=\"form.features.accounting\" format=\"switch\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customAccounting\"></sxy-input>\r\n              <div ng-if=\"$ctrl.current.features.accounting\">\r\n                <sxy-input model=\"form.accounting.defaultPeriodDateKind\"></sxy-input>\r\n                <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-accounting-targets.html\" model=\"form.accounting.targets\">\r\n                  <form>\r\n                    <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"ServiceModelCrudController as $serviceModelController\" ng-init=\"$ctrl.logic.isReadOnly = true\">\r\n                      <salaxy-odata-table crud-controller=\"AccountingTargetCrudController as $crud\" template-url=\"salaxy-components/odata/lists/AccountingTargetSelect.html\" selected-items=\"$ctrl.selectedItems\" on-list-select=\"$serviceModelController.onAccountingTargetSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                      </salaxy-odata-table>\r\n                    </fieldset>\r\n                    <fieldset ng-show=\"$ctrl.logic.showDelete\" ng-init=\"$ctrl.logic.isReadOnly = false\">\r\n                      <salaxy-input-enum disabled=\"false\" name=\"format\" label=\"SALAXY.NG1.AccountingTargetDetailsComponent.excelCsvFormat\" ng-model=\"$ctrl.current.format\"\r\n                    options=\"{\r\n                      '36dff2e2-e181-4f0d-9004-0e4aa92f5e17': 'Palkkaus.fi',\r\n                      '0db4e85f-93a8-46f1-b6d2-f7523d289d88': 'Fennoa',\r\n                      '8613f133-3fce-4611-b372-51f6a2e007dd': 'Procountor',\r\n                      'e62c10b0-222a-4170-b8b4-b1e02d9a7644': 'Passeli Merit',\r\n                      '53fd3863-b8f9-4909-86c9-cb4597595181': 'Heeros',\r\n                      '2fc7899c-7a3d-4d56-ad2f-05d52782bbbc': 'Asteri',\r\n                      '0a2bd312-06da-4862-aef5-75166e0bf461': 'Maestro',\r\n                      'c04e0757-63f3-420d-a183-3427710fc954': 'Visma Fivaldi',\r\n                      'ba271dac-dd63-4036-9d70-053a09ca4d9e' :'Visma Netvisor',\r\n                      '27e271d5-41f5-4319-ab29-4d5d9eb945c6': 'Lemonsoft',\r\n                      'd311f9d3-8c3a-4fd8-a665-8e3698e41e87': 'Tampuuri',\r\n                      'd58e95b7-d0b5-40ac-992b-6d3b29efc45e': 'Domus',\r\n                      '54e93c5f-bd74-4157-8a74-3515be7f585d': 'Oscar Software',\r\n                      '0e4f0a71-dcb9-43ba-9028-0239e674711f': 'Digia Enterprise'\r\n                    }\">\r\n                     </salaxy-input-enum>\r\n                      <sxy-input model=\"form.method\" read-only=\"false\"></sxy-input>\r\n                      <salaxy-input-enum disabled=\"false\" enum=\"ExportMethod\" label=\"SALAXY.MODEL.AccountingTargetSettings.availableMethods.title\" name=\"availableMethods\" type=\"multi-select\" ng-model=\"$ctrl.current.availableMethods\"></salaxy-input-enum>\r\n                    </fieldset>\r\n                  </form>\r\n                </sxy-input>\r\n                <salaxy-input-enum type=\"typeahead\" name=\"options_type\" ng-model=\"$ctrl.current.accounting.defaultTargetId\" options=\"$ctrl.getSelectableAccountingTargets()\" disable-cache=\"true\" ng-if=\"$ctrl.getSelectableAccountingTargets().length &gt; 1\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.defaultTarget\"></salaxy-input-enum>\r\n              </div>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.ServiceModelCostAccounting.title\"></legend>\r\n              <sxy-input model=\"form.features.costAccounting\" format=\"switch\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customCostAccounting\"></sxy-input>\r\n              <div ng-if=\"$ctrl.current.features.costAccounting\">\r\n                <sxy-input model=\"form.costAccounting.dimensions\" include=\"id,label,scope\">\r\n                  <form>\r\n                    <fieldset>\r\n                      <legend sxy-text=\"SALAXY.MODEL.CostAccountingDimensionDefinition.title\"></legend>\r\n                      <sxy-input model=\"form.id\" read-only=\"{{$ctrl.logic.showDelete}}\"></sxy-input>\r\n                      <sxy-input model=\"form.label\"></sxy-input>\r\n                      <sxy-input model=\"form.allowCostSharing\"></sxy-input>\r\n                      <sxy-input model=\"form.scope\"></sxy-input>\r\n                      <sxy-input model=\"form.options\" template-url=\"salaxy-components/sxy-form/custom-templates/cost-accounting-options.html\"></sxy-input>\r\n                    </fieldset>\r\n                  </form>\r\n                </sxy-input>\r\n              </div>\r\n            </fieldset>\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.MODEL.ServiceModelHoliday.title\"></legend>\r\n              <sxy-input model=\"form.features.holiday\" format=\"switch\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customHoliday\"></sxy-input>\r\n              <div ng-if=\"$ctrl.current.features.holiday\">\r\n                <sxy-input model=\"form.holiday.holidayPaySettings\" include=\"holidayPayCalculation\">\r\n                  <form>\r\n                    <fieldset>\r\n                      <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.title\"></legend>\r\n                      <salaxy-input-enum enum=\"HolidayPayCalculation\" label=\"SALAXY.MODEL.HolidayPaySettings.holidayPayCalculation.title\" name=\"holidayPayCalculation\" filter=\"averageDailyPay,averageHourlyPay,percentageBasedPay,holidayCompensation\" require=\"true\" ng-model=\"$ctrl.current.holidayPayCalculation\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                      <legend sxy-text=\"SALAXY.MODEL.HolidayPaySettings.salaryTypes.title\"></legend>\r\n                      <sxy-input model=\"form.salaryTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                      <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.workingTimeTypes.title\"></legend>\r\n                      <sxy-input ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay'\" model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                      <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.overtimeTypes.title\"></legend>\r\n                      <sxy-input  ng-show=\"$ctrl.current.holidayPayCalculation == 'averageDailyPay'\" model=\"form.overtimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                      <legend ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" sxy-text=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\"></legend>\r\n                      <salaxy-input-holiday-multipliers ng-show=\"$ctrl.current.holidayPayCalculation == 'averageHourlyPay' || $ctrl.current.holidayPayCalculation == 'averageDailyPay'\" name=\"multipliers\" label=\"SALAXY.MODEL.HolidayPaySettings.multipliers.title\" ng-model=\"$ctrl.current.multipliers\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-holiday-multipliers>\r\n                    </fieldset>\r\n                  </form>\r\n                </sxy-input>\r\n               <sxy-input model=\"form.holiday.holidayAccrualSettings\" include=\"code\">\r\n                  <form>\r\n                    <fieldset>\r\n                      <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.title\"></legend>\r\n                      <salaxy-input-enum enum=\"HolidayCode\" label=\"SALAXY.MODEL.HolidayAccrualSettings.code.title\" name=\"code\" filter=\"permanent35Hours\" require=\"true\" ng-model=\"$ctrl.current.code\" read-only=\"$ctrl.getReadOnly()\"></salaxy-input-enum>\r\n                      <legend sxy-text=\"SALAXY.MODEL.HolidayAccrualSettings.workingTimeTypes.title\"></legend>\r\n                      <sxy-input model=\"form.workingTimeTypes\" template-url=\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\"></sxy-input>\r\n                    </fieldset>\r\n                  </form>\r\n                </sxy-input>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'branding'\" class=\"form-horizontal container\">\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.webAppTitle\"></legend>\r\n                  <sxy-input model=\"form.site.webApp\"></sxy-input>\r\n                  <sxy-input model=\"form.site.webAppUrl\"></sxy-input>\r\n                  <sxy-input model=\"form.site.webAppName\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-sm-6\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.reportingTitle\"></legend>\r\n                  <sxy-input model=\"form.features.reporting\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customReporting\"></sxy-input>\r\n                  <salaxy-input-enum ng-model=\"$ctrl.current.reporting.layoutTemplateId\" name=\"layputTemplateId\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.layoutTemplateId\" options=\"{'palkkaus-report-options@FI53POYS0025543933': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdPalkkaus' | sxyTranslate),\r\n                      'no-logo-report-options@FI53POYS0025543933': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdNoLogo' | sxyTranslate),\r\n                      'logo-report-options@FI53POYS0025543933': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdLogo' | sxyTranslate),\r\n                      'kevytyrittaja-report-options@FI06POYT0009439335': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdTalenom' | sxyTranslate),\r\n                      'tilijaska-report-options@FI39POYT0025590211': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdTilijaska' | sxyTranslate),\r\n                      'treamer-report-options@FI86POYI0028244891': ('SALAXY.NG1.ServiceModelDetailsComponent.templateIdTreamer' | sxyTranslate)}\" read-only=\"$ctrl.isReadOnly\"></salaxy-input-enum>\r\n                  <salaxy-textarea maxlength=\"\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customReportLogo\" name=\"logo\" ng-model=\"$ctrl.current.reporting.logo\" rows=\"3\" ng-if=\"$ctrl.current.reporting.layoutTemplateId == 'logo-report-options@FI53POYS0025543933'\">\r\n                  </salaxy-textarea>\r\n                </fieldset>\r\n              </div>\r\n            </div>\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-8\">\r\n                <fieldset>\r\n                  <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.brandingTitle\"></legend>\r\n                  <sxy-input model=\"form.branding.logo\"></sxy-input>\r\n                  <sxy-input model=\"form.branding.skin\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-sm-4 text-center\">\r\n                <img ng-if=\"$ctrl.current.branding.logo\" ng-src=\"{{ $ctrl.current.branding.logo }}\" style=\"width: 100px; margin-top: 35px;\" />\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'sitemap'\" class=\"form-horizontal height100\">\r\n            <div class=\"row height100\" style=\"width: 95%;\">\r\n              <div class=\"col-xs-6 height100\" style=\"width: 45%; overflow-y: auto\">\r\n                <div class=\"toolbar\">\r\n                  <div class=\"btn-group\">\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showHideAll(true)\">Avaa kaikki</button>\r\n                    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showHideAll(false)\">Sulje kaikki</button>\r\n                  </div>\r\n                  <button type=\"button\" ng-disabled=\"$ctrl.isReadOnly\" class=\"btn btn-danger\" ng-click=\"$ctrl.resetSitemapChanges()\">Palauta kaikki</button>\r\n                </div>\r\n                <table class=\"table table-condensed\">\r\n                  <thead>\r\n                    <tr>\r\n                      <th colspan=\"3\">Title</th>\r\n                      <th class=\"right\">Flags</th>\r\n                      <th class=\"right\">Roles</th>\r\n                      <th class=\"right\">Changes</th>\r\n                      <th colspan=\"2\"></th>\r\n                    </tr>\r\n                  </thead>\r\n                  <tbody>\r\n                    <tr ng-repeat-start=\"level1 in $ctrl.sitemap\" class=\"clickable\" ng-class=\"{ 'active': $ctrl.currentSitemapNode == level1 }\">\r\n                      <td colspan=\"3\" ng-click=\"$ctrl.currentSitemapNode = level1\">{{ $ctrl.translate(level1.title) }}</td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level1\">\r\n                        <i ng-class=\"'fa ' + icon\" ng-repeat=\"icon in level1.$edit.$faIcons\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level1\">\r\n                        <span ng-if=\"$ctrl.getIsTest(level1)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span>\r\n                        <span>{{ $ctrl.getRoles(level1) }}</span>\r\n                      </td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level1\">\r\n                        <i class=\"fa fa-language text-primary\" ng-if=\"level1.$edit.$hasTextChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square text-primary\" ng-if=\"level1.$edit.$hasChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square-o\" ng-if=\"level1.$edit.$hasChildrenChanges\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td colspan=\"2\" class=\"right\" ng-if=\"level1.children.length\" ng-click=\"level1.$edit.$isOpen = !level1.$edit.$isOpen\">\r\n                        <i class=\"fa\" ng-class=\"level1.$edit.$isOpen ? 'fa-chevron-up' : 'fa-chevron-down'\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td colspan=\"2\" ng-if=\"!level1.children.length\"></td>\r\n                    </tr>\r\n                    <tr ng-if=\"level1.$edit.$isOpen\" ng-repeat-start=\"level2 in level1.children\" class=\"clickable\" ng-class=\"{ 'active': $ctrl.currentSitemapNode == level2 }\">\r\n                      <td style=\"width: 10px;\">-</td>\r\n                      <td colspan=\"2\" ng-click=\"$ctrl.currentSitemapNode = level2\">{{ $ctrl.translate(level2.title) }}</td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level2\">\r\n                        <i ng-class=\"'fa ' + icon\" ng-repeat=\"icon in level2.$edit.$faIcons\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level2\">\r\n                        <span ng-if=\"$ctrl.getIsTest(level2)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span>\r\n                        <span>{{ $ctrl.getRoles(level2) }}</span>\r\n                      </td>\r\n                      <td class=\"right\" ng-click=\"$ctrl.currentSitemapNode = level2\">\r\n                        <i class=\"fa fa-language text-primary\" ng-if=\"level2.$edit.$hasTextChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square text-primary\" ng-if=\"level2.$edit.$hasChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square-o\" ng-if=\"level2.$edit.$hasChildrenChanges\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td ng-if=\"level2.children.length\" ng-click=\"level2.$edit.$isOpen = !level2.$edit.$isOpen\">\r\n                        <i class=\"fa\" ng-class=\"level2.$edit.$isOpen ? 'fa-chevron-up' : 'fa-chevron-down'\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td ng-if=\"!level2.children.length\"></td>\r\n                      <td></td>\r\n                    </tr>\r\n                    <tr ng-if=\"level1.$edit.$isOpen && level2.$edit.$isOpen\" ng-repeat-end ng-repeat=\"level3 in level2.children\" class=\"clickable\" ng-click=\"$ctrl.currentSitemapNode = level3\" ng-class=\"{ 'active': $ctrl.currentSitemapNode == level3 }\">\r\n                      <td style=\"width: 10px;\">&nbsp;</td>\r\n                      <td style=\"width: 10px;\">-</td>\r\n                      <td>{{ $ctrl.translate(level3.title) }}</td>\r\n                      <td class=\"right\">\r\n                        <i ng-class=\"'fa ' + icon\" ng-repeat=\"icon in level3.$edit.$faIcons\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td class=\"right\">\r\n                        <span ng-if=\"$ctrl.getIsTest(level3)\" class=\"badge bg-primary\"><span class=\"small\">test</span></span>\r\n                        <span>{{ $ctrl.getRoles(level3) }}</span>\r\n                      </td>\r\n                      <td class=\"right\">\r\n                        <i class=\"fa fa-language text-primary\" ng-if=\"level3.$edit.$hasTextChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square text-primary\" ng-if=\"level3.$edit.$hasChanges\" aria-hidden=\"true\"></i>\r\n                        <i class=\"fa fa-pencil-square-o\" ng-if=\"level3.$edit.$hasChildrenChanges\" aria-hidden=\"true\"></i>\r\n                      </td>\r\n                      <td colspan=\"2\"></td>\r\n                    </tr>\r\n                    <tr ng-repeat-end ng-if=0></tr>\r\n                  </tbody>\r\n                </table>\r\n              </div>\r\n              <div class=\"col-xs-6\">\r\n                <div class=\"toolbar\">\r\n                  <button type=\"button\" ng-disabled=\"$ctrl.isReadOnly\" class=\"btn btn-danger\" ng-click=\"$ctrl.resetSitemapNode(true)\">Palauta muutokset</button>\r\n                  <div class=\"btn-group pull-right\">\r\n                    <button type=\"button\" ng-disabled=\"$ctrl.isReadOnly\" class=\"btn btn-default\" ng-click=\"$ctrl.resetSitemapNode()\">Peruuta</button>\r\n                    <button type=\"button\" ng-disabled=\"$ctrl.isReadOnly\" class=\"btn btn-primary\" ng-click=\"$ctrl.commitSitemapNode()\">OK</button>\r\n                  </div>\r\n                </div>\r\n\r\n                <h3>{{ $ctrl.translate($ctrl.currentSitemapNode.title) }} <small>({{ $ctrl.currentSitemapNode.$edit.$id }})</small></h3>\r\n                <uib-tabset active=\"$ctrl.SitemapActive\">\r\n                  <uib-tab index=\"'general'\" heading=\"Perustiedot\">\r\n                    <div class=\"form-horizontal\">\r\n                      <salaxy-input name=\"id\" read-only=\"true\" ng-model=\"$ctrl.currentSitemapNode.$edit.$id\" label=\"Id\"></salaxy-input>\r\n                      <salaxy-input name=\"url\" read-only=\"true\" ng-model=\"$ctrl.currentSitemapNode.url\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.url\"></salaxy-input>\r\n                      <salaxy-input-enum name=\"visibility\" enum=\"SitemapVisibility\" label=\"Näkyvyys ({{ 'SitemapVisibility.' + ($ctrl.currentSitemapNode.visibility || 'visible') | sxyEnum }})\" ng-model=\"$ctrl.currentSitemapNode.$edit.visibility\" read-only=\"$ctrl.isReadOnly\"></salaxy-input-enum>\r\n                      <salaxy-input name=\"roles\" ng-model=\"$ctrl.currentSitemapNode.$edit.roles\" label=\"Roolit ({{ $ctrl.currentSitemapNode.roles || '-' }})\" read-only=\"$ctrl.isReadOnly\"></salaxy-input>\r\n                      <salaxy-input-boolean name=\"isFullWidth\" type=\"select\" label=\"Leveä näyttö ({{ $ctrl.currentSitemapNode.isFullWidth ? 'Kyllä' : 'Ei' }})\" ng-model=\"$ctrl.currentSitemapNode.$edit.isFullWidth\" read-only=\"$ctrl.isReadOnly\"></salaxy-input-boolean>\r\n                      <div class=\"row\">\r\n                        <div ng-if=\"$ctrl.currentSitemapNode.$edit.isFullWidth != null\" class=\"col-sm-6 col-sm-offset-4\">\r\n                          <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$ctrl.currentSitemapNode.$edit.isFullWidth = null\">Palauta oletus</button>\r\n                        </div>\r\n                      </div>\r\n                      <fieldset>\r\n                        <legend>Sivun otsikko</legend>\r\n                        <small><p>Klikkaa muokataksesi kieliversioita. HUOM: Muutokset menevät suoraan kieliversiointiin, \"Peruuta\"/\"OK\"-nappuloila yllä ei ole vaikutusta. Käytä delete-nappia alla erikseen poistaaksesi muutokset.</p></small>\r\n                        <div style=\"padding-left: 10px;\">\r\n                          <salaxy-ui-translator mode=\"fieldset\" texts=\"$ctrl.current.site.texts\" filter=\"$ctrl.currentSitemapNode.$edit.$i18nKey\"></salaxy-ui-translator>\r\n                        </div>\r\n                      </fieldset>\r\n                    </div>\r\n                  </uib-tab>\r\n                  <uib-tab index=\"'params'\" heading=\"Parametrit\">\r\n                    <sxy-form open-api=\"SitemapParams\" open-api-doc=\"$ctrl.getSitemapParamsSchema()\" type=\"{{$ctrl.currentSitemapNode.$edit.$id}}\" auto-gen=\"true\" model=\"$ctrl.currentSitemapNode.$edit\" read-only=\"{{$ctrl.isReadOnly}}\"></sxy-form>\r\n                  </uib-tab>\r\n                  <uib-tab index=\"'i18n'\" heading=\"Tekstit\">\r\n                    <div class=\"alert alert-info\"><strong>HUOM!</strong> Suurin osa teksteistä on komponenttien tekstejä. Niiden muokkaaminen vaikuttaa kaikkiin sivuihin, joissa komponentti on käytössä: Ei pelkästään tähän sivuun.</div>\r\n                    <div ng-if=\"!$ctrl.currentSitemapNode.i18n.length\">Käännöstekstejä ei ole määritetty tälle sivulle.</div>\r\n                    <salaxy-ui-translator ng-if=\"$ctrl.currentSitemapNode.i18n.length\" texts=\"$ctrl.current.site.texts\" filter=\"$ctrl.currentSitemapNode.i18n\"></salaxy-ui-translator>\r\n                  </uib-tab>\r\n                  <uib-tab index=\"'debug'\" heading=\"Debug\">\r\n                    <salaxy-json-formatter json=\"$ctrl.currentSitemapNode\" key=\"'Node'\"></salaxy-json-formatter>\r\n                    <salaxy-json-formatter json=\"$ctrl.currentSitemapNode.$edit\" key=\"'$edit'\"></salaxy-json-formatter>\r\n                  </uib-tab>\r\n                </uib-tabset>\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'messaging'\" class=\"form-horizontal container\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.ServiceModelDetailsComponent.messagingTitle\"></legend>\r\n              <sxy-input model=\"form.features.messaging\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.messagingActive\"></sxy-input>\r\n              <sxy-input model=\"form.messaging.partnerMessages\"></sxy-input>\r\n              <sxy-input model=\"form.messaging.workerSalaryNotifications\"></sxy-input>\r\n              <sxy-input model=\"form.messaging.workerSalarySlipDeliveryMethods\"></sxy-input>\r\n            </fieldset>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'i18n'\" class=\"form-horizontal\" ng-init=\"$ctrl.current.site.texts = $ctrl.current.site.texts ? $ctrl.current.site.texts : {}\">\r\n            <salaxy-ui-translator texts=\"$ctrl.current.site.texts\"></salaxy-ui-translator>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'workflow'\" class=\"form-horizontal\">\r\n            <div class=\"container\">\r\n              <sxy-input model=\"form.features.forms\" legend=\"Aineiston lähetys käytössä\"></sxy-input>\r\n            </div>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'usecases'\" class=\"form-horizontal container\">\r\n            <fieldset>\r\n              <sxy-input model=\"form.features.usecase\" label=\"SALAXY.NG1.ServiceModelDetailsComponent.customUsecases\"></sxy-input>\r\n              <sxy-input template-url=\"salaxy-components/sxy-form/custom-templates/array-usecase.html\" model=\"form.usecase.usecases\">\r\n                <form>\r\n                  <fieldset ng-show=\"!$ctrl.logic.showDelete\" ng-controller=\"ServiceModelCrudController as $serviceModelController\">\r\n                    <salaxy-odata-table url=\"/v03/api/usecases\" template-url=\"salaxy-components/odata/lists/UsecaseSelect.html\" selected-items=\"$ctrl.selectedItems\" on-list-select=\"$serviceModelController.onUsecaseSelect($ctrl.current, $ctrl.logic, value, item, allItems)\">\r\n                    </salaxy-odata-table>\r\n                  </fieldset>\r\n                  <fieldset ng-show=\"$ctrl.logic.showDelete\">\r\n                    <sxy-input model=\"form.uri\" read-only=\"true\"></sxy-input>\r\n                    <sxy-input model=\"form.label\"></sxy-input>\r\n                    <sxy-input model=\"form.itemType\"></sxy-input>\r\n                    <sxy-input model=\"form.status\"></sxy-input>\r\n                    <sxy-input model=\"form.order\"></sxy-input>\r\n                  </fieldset>\r\n                </form>\r\n              </sxy-input>\r\n            </fieldset>\r\n          </div>\r\n          <div ng-if=\"$ctrl.currentSection == 'advanced'\">\r\n            <div class=\"container\" ng-init=\"$ctrl.exportJson()\">\r\n              <h3>Tuonti ja vienti</h3>\r\n              <div class=\"btn-toolbar\">\r\n                <div class=\"btn-group\">\r\n                  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.importJson()\">Import JSON to this service model</button>\r\n                </div>\r\n              </div>\r\n              <sxy-code-editor read-only=\"$ctrl.current.isReadOnly\" lang=\"json\" ng-model=\"$ctrl.json\"></sxy-code-editor>\r\n            </div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </sxy-form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/array/default.html\",`<div ng-switch=\"$ctrl.schemaModel.items.type\">\r\n  <div ng-switch-when=\"object\">\r\n    <table class=\"table\">\r\n      <caption>{{ $ctrl.getLabel() }}</caption>\r\n      <thead>\r\n        <tr>\r\n          <th ng-repeat=\"itemInput in $ctrl.getChildInputs(3)\">{{ $ctrl.getLabel(itemInput.name) }}</th>\r\n          <th class=\"text-right\">\r\n            <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"item in $ctrl.value\">\r\n          <td ng-repeat=\"itemInput in $ctrl.getChildInputs(3)\">{{ $ctrl.formatValue(itemInput.name, $parent.$index) }}</td>\r\n          <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n            <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n              <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n            </button>\r\n            <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(item, $index)\">\r\n              <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n            </button>\r\n          </td>\r\n          <td class=\"text-right\" ng-if=\"$ctrl.getReadOnly()\">\r\n            <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n              <i class=\"fa fa-info\" title=\"Show row\"></i>\r\n            </button>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n  </div>\r\n  <div ng-switch-when=\"string\">\r\n    <salaxy-input-enum ng-if=\"$ctrl.schemaModel.items.enum.length\" ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\"\r\n      type=\"multi-select\" options=\"$ctrl.getEnumOptions()\"></salaxy-input-enum>\r\n    <salaxy-form-group ng-if=\"!$ctrl.schemaModel.items.enum.length\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\">\r\n      <div class=\"input-group\" ng-repeat=\"item in $ctrl.value track by $index\">\r\n        <input type=\"text\" class=\"form-control\" ng-model=\"$ctrl.value[$index]\" name=\"{{ $ctrl.id + '_' + $index }}\" id=\"{{ $ctrl.id + '_' + $index }}\" ng-readonly=\"$ctrl.getReadOnly()\" ng-disabled=\"$ctrl.getDisable()\">\r\n        <div class=\"input-group-btn\">\r\n          <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n        </div>\r\n      </div>\r\n      <div class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.value.push('')\">Add new</button>\r\n      </div>\r\n    </salaxy-form-group>\r\n  </div>\r\n  <div ng-switch-default>\r\n    <salaxy-form-group name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\">\r\n      <p>Unhandled array type: {{ $ctrl.schemaModel.items.type }}</p>\r\n    </salaxy-form-group>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/array/PercentDimension.html\",`<table class=\"table\">\r\n  <caption>{{ $ctrl.getLabel() }}</caption>\r\n  <thead>\r\n    <tr>\r\n      <th>{{\"SALAXY.MODEL.PercentDimension.id.title\" | sxyTranslate}}</th>\r\n      <th class=\"right\">{{\"SALAXY.MODEL.PercentDimension.percent.title\" | sxyTranslate}}</th>\r\n      <th class=\"right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>\r\n        <salaxy-input ng-model=\"item.id\" name=\"{{ 'id' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\"></salaxy-input>\r\n      </td>\r\n      <td>\r\n        <salaxy-input-number ng-model=\"item.percent\" name=\"{{ 'percent' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" unit=\"percent\"></salaxy-input-number>\r\n      </td>\r\n      <td class=\"text-right\">\r\n        <button  ng-if=\"!$ctrl.getReadOnly()\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.delete(item, $index)\">\r\n          <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n        </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n  <tfoot>\r\n    <tr class=\"total\">\r\n      <td>{{\"SALAXY.UI_Terms.total\" | sxyTranslate}}</td>\r\n      <td class=\"right\">{{ ($ctrl.getTotal('percent') || ($ctrl.value.length == 1 ? 1 : \"-\")) | sxyCount : 'percent' }}</td>\r\n      <td></td>\r\n    </tr>\r\n  </tfoot>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/boolean/checkbox.html\",`<salaxy-input-boolean ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" ng-require=\"$ctrl.getRequire()\" type=\"checkbox\">\r\n\r\n</salaxy-input-boolean>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/boolean/default.html\",`<salaxy-input-boolean ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"select\"></salaxy-input-boolean>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/boolean/radio.html\",`<salaxy-input-boolean ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"radio\"></salaxy-input-boolean>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/boolean/switch.html\",`<salaxy-input-boolean ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"switch\"></salaxy-input-boolean>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-accounting-targets.html\",`\r\n<table class=\"table\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.AccountingSettings.targets.title\" colspan=\"2\"></th>\r\n      <th></th>\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>\r\n        <salaxy-avatar avatar=\"item.avatar\"></salaxy-avatar>\r\n      </td>\r\n      <td>{{item.avatar.displayName}}</td>\r\n      <td></td>\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n          <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n        </button>\r\n        <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n      </td>\r\n\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-insurance.html\",`<p sxy-text=\"SALAXY.MODEL.CalculationSettings.insuranceContracts.title\" class=\"table-title\"></p>\r\n<table class=\"table\">\r\n\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.InsuranceContract.company.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.InsuranceContract.status.title\"></th>\r\n      <th class=\"right\" sxy-text=\"SALAXY.MODEL.InsuranceContract.startDate.title\"></th>\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>{{'SALAXY.ENUM.InsuranceCompany.' + item.company + '.label' | sxyTranslate}}</td>\r\n      <td>{{item.contractNumber}}</td>\r\n      <td>{{'SALAXY.ENUM.SettingsStatus.' + item.status + '.label' | sxyTranslate}}</td>\r\n      <td class=\"right\">{{item.startDate | date}}\r\n        <span class=\"\" ng-if=\"item.endDate\">\r\n          <br><small>(päättyy {{item.endDate | date}})</small>\r\n        </span>\r\n      </td>\r\n\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n          </button>\r\n        <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-info\" title=\"Show row\"></i>\r\n          </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-payment-channels.html\",`<table class=\"table\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.PaymentSettings.channels.title\" colspan=\"2\"></th>\r\n      <th>Käytössä</th>\r\n      <th>Valittavissa</th>\r\n      <th class=\"text-right\"></th>\r\n\r\n    </tr>\r\n  </thead>\r\n  <tbody ng-controller=\"CompanySettingsController as $settingsCtrl\">\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td style=\"padding: 2px;\">\r\n        <salaxy-avatar style=\"font-size: 2.4em;\" avatar=\"$settingsCtrl.getPaymentChannelAvatar(item)\"></salaxy-avatar>\r\n      </td>\r\n      <td>\r\n        {{$settingsCtrl.getPaymentChannelAvatar(item).displayName}}\r\n      </td>\r\n      <td>\r\n        <span ng-if=\"item.isAvailable\">{{'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n        <span ng-if=\"!item.isAvailable\">{{'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n      </td>\r\n      <td>\r\n        <span ng-if=\"item.isEnabled\">{{'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n        <span ng-if=\"!item.isEnabled\">{{'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n          </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-pension.html\",`<p sxy-text=\"SALAXY.MODEL.CalculationSettings.pensionContracts.title\" class=\"table-title\"></p>\r\n<table class=\"table\">\r\n\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.PensionContract.company.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.PensionContract.contractNumber.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.PensionContract.status.title\"></th>\r\n      <th class=\"right\" sxy-text=\"SALAXY.MODEL.PensionContract.startDate.title\"></th>\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>{{'SALAXY.ENUM.PensionCompany.' + item.company + '.label' | sxyTranslate}}</td>\r\n      <td>{{ item.contractNumber}}</td>\r\n      <td>{{'SALAXY.ENUM.SettingsStatus.' + item.status + '.label' | sxyTranslate}}</td>\r\n      <td class=\"right\">{{item.startDate | date}}\r\n        <span class=\"\" ng-if=\"item.endDate\">\r\n          <br><small>(päättyy {{item.endDate | date}})</small>\r\n        </span>\r\n      </td>\r\n\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n          </button>\r\n        <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(item, $index)\">\r\n            <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n          </button>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-info\" title=\"Show row\"></i>\r\n          </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-service-model-payment-channels.html\",`<table class=\"table\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.PaymentSettings.channels.title\" colspan=\"2\"></th>\r\n      <th>Käytössä</th>\r\n      <th>Valittavissa</th>\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n\r\n    </tr>\r\n  </thead>\r\n  <tbody ng-controller=\"CompanySettingsController as $settingsCtrl\">\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>\r\n        <salaxy-avatar avatar=\"$settingsCtrl.getPaymentChannelAvatar(item)\"></salaxy-avatar>\r\n      </td>\r\n      <td>\r\n        {{$settingsCtrl.getPaymentChannelAvatar(item).displayName}}\r\n      </td>\r\n      <td>\r\n        <span ng-if=\"item.isAvailable\">{{'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n        <span ng-if=\"!item.isAvailable\">{{'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n      </td>\r\n      <td>\r\n        <span ng-if=\"item.isEnabled\">{{'SALAXY.UI_Terms.yes' | sxyTranslate}} </span>\r\n        <span ng-if=\"!item.isEnabled\">{{'SALAXY.UI_Terms.no' | sxyTranslate}} </span>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n            <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n          </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/array-usecase.html\",`<table class=\"table\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.NG1.ArrayUsecase.table.usecaseLabel\" colspan=\"2\"></th>\r\n      <th></th>\r\n\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew()\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>\r\n        {{item.label}}\r\n      </td>\r\n      <td>{{'SALAXY.NG1.CalcListComponent.' + item.itemType | sxyTranslate}}</td>\r\n      <td></td>\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$ctrl.edit(item, $index)\">\r\n          <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n        </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/cost-accounting-options.html\",`<table class=\"table\" ng-if=\"$ctrl.form\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.MODEL.CostAccountingDimensionOption.value.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.CostAccountingDimensionOption.text.title\"></th>\r\n      <th sxy-text=\"SALAXY.MODEL.CostAccountingDimensionOption.scope.title\"></th>\r\n      <th class=\"text-right\">\r\n          <button type=\"button\" class=\"btn btn-default btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.createNew({})\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n      <th>\r\n        <div class=\"btn-group btn-group-xs\" uib-dropdown>\r\n          <button id=\"single-button\" type=\"button\" class=\"btn btn-default btn-xs\" uib-dropdown-toggle>\r\n            <i class=\"fa fa-ellipsis-h\" aria-hidden=\"true\"></i>\r\n          </button>\r\n          <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n            <li role=\"menuitem\">\r\n              <a href=\"\" ng-controller=\"ExportController as $export\" ng-click=\"$export.showExport($ctrl.getExportable())\" sxy-text=\"SALAXY.NG1.ODataActionsComponent.export\"></a>\r\n            </li>\r\n            <!--\r\n            <li role=\"menuitem\">\r\n              <a href=\"\" ng-controller=\"ImportController as $import\" ng-click=\"$import.showImport($ctrl.getImportable())\" sxy-text=\"SALAXY.NG1.ODataActionsComponent.import\"></a>\r\n            </li> --> \r\n          </ul>\r\n        </div>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value\">\r\n      <td>\r\n        <salaxy-input ng-model=\"item.value\" name=\"{{ 'value' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" ></salaxy-input>\r\n      </td>\r\n      <td>\r\n        <salaxy-input ng-model=\"item.text\" name=\"{{ 'text' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" ></salaxy-input>\r\n      </td>\r\n      <td>\r\n        <salaxy-input-enum enum=\"CostAccountingDimensionScope\" ng-model=\"item.scope\" name=\"{{ 'scope' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" ></salaxy-input-enum>\r\n      </td>\r\n      <td colspan=\"2\" class=\"text-right\">\r\n        <button ng-if=\"!$ctrl.getReadOnly()\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.delete(item, $index)\">\r\n          <i class=\"fa fa-trash-o\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></i>\r\n        </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/holiday-row-types.html\",`<table class=\"table\" ng-if=\"$ctrl.form\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.inputs.type\"></th>\r\n      <th class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-if=\"!$ctrl.getReadOnly()\" ng-click=\"$ctrl.value=($ctrl.value || []);$ctrl.value.push('')\" sxy-text=\"SALAXY.UI_Terms.addRow\"></button>\r\n      </th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr ng-repeat=\"item in $ctrl.value track by $index\">\r\n      <td>\r\n        <salaxy-input-holiday-row-type ng-ref=\"$row\" ng-model=\"$ctrl.value[$index]\" name=\"{{ 'rowType' + $index }}\" label-type=\"plain\" read-only=\"$ctrl.getReadOnly()\" ></salaxy-input-holiday-row-type>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"!$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$row.edit()\">\r\n          <i class=\"fa fa-pencil\" title=\"Edit row\"></i>\r\n        </button>\r\n        <button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"$ctrl.delete(item, $index)\">\r\n          <i class=\"fa fa-trash-o\" title=\"Delete row\"></i>\r\n        </button>\r\n      </td>\r\n      <td class=\"text-right\" ng-if=\"$ctrl.getReadOnly()\">\r\n        <button type=\"button\" class=\"btn btn-primary btn-xs\" ng-click=\"$row.edit()\">\r\n          <i class=\"fa fa-info\" title=\"Show row\"></i>\r\n        </button>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/custom-templates/select-accounting-target-item.html\",`<a class=\"clickable salaxy-component salaxy-avatar-item\">\r\n  <salaxy-avatar style=\"font-size: 30px; vertical-align: middle;\"\r\n  avatar=\"match.model.otherPartyInfo.avatar\"></salaxy-avatar>\r\n  <b class=\"salaxy-highlight\" ng-bind-html=\"match.label | uibTypeaheadHighlight:query\"></b>\r\n</a>\r\n`);\n\n $templateCache.put(\"salaxy-components/sxy-form/error/default.html\",`<salaxy-form-group name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\"\r\n  require=\"$ctrl.getRequire()\">\r\n  <sxy-alert type=\"error\">\r\n    <div ng-if=\"$ctrl.input.content\">{{ $ctrl.input.content }}</div>\r\n    <div ng-if=\"!$ctrl.input.content\">No UI for model \"{{ $ctrl.model }}\",  type \"{{ $ctrl.type }}\", format \"{{ $ctrl.format }}\".</div>\r\n    <div>\r\n      <salaxy-json-formatter key=\"'See input json'\" json=\"$ctrl.input\" type=\"dialog\"></salaxy-json-formatter>\r\n      <salaxy-json-formatter key=\"'See schema'\" json=\"$ctrl.schemaModel\" type=\"dialog\"></salaxy-json-formatter>\r\n    </div>\r\n  </sxy-alert>\r\n</salaxy-form-group>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/integer/default.html\",`<salaxy-input-number ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" sxy-integer>\r\n</salaxy-input-number>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/number/default.html\",`<salaxy-input-number ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" unit=\"{{ $ctrl.input.format }}\"\r\n  minimum=\"{{$ctrl.getMinimum()}}\" maximum=\"{{$ctrl.getMaximum()}}\" multiple-of=\"{{$ctrl.getMultipleOf()}}\">\r\n</salaxy-input-number>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/object/Avatar.html\",`<salaxy-form-group name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\">\r\n  <table>\r\n    <tr>\r\n      <td class=\"td-avatar middle\">\r\n        <salaxy-avatar avatar=\"$ctrl.value\"></salaxy-avatar>\r\n      </td>\r\n      <td class=\"td-name middle\">\r\n        <strong>{{$ctrl.value.displayName}}</strong><br />\r\n        <span class=\"\">{{ $ctrl.value.id | sxyIban }}</span>\r\n      </td>\r\n    </tr>\r\n  </table>\r\n</salaxy-form-group>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/object/DateRange.html\",`<salaxy-date-range ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\">\r\n</salaxy-date-range>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/object/default.html\",`<salaxy-form-group name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\"\r\n  require=\"$ctrl.getRequire()\">\r\n  <div>\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.isInEdit[$ctrl.id] = !$ctrl.isInEdit[$ctrl.id]\">{{ $ctrl.isInEdit[$ctrl.id] ? \"Hide\" : \"Edit\" }}</button>\r\n  </div>\r\n</salaxy-form-group>\r\n<div ng-if=\"$ctrl.isInEdit[$ctrl.id]\" class=\"row\">\r\n  <div class=\"col-md-offset-1 col-xs-11\">\r\n    <sxy-fieldset model=\"{{ $ctrl.model }}\"></sxy-fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/date-time.html\",`<salaxy-form-group name=\"{{$ctrl.id}}\" class=\"salaxy-component salaxy-read-only\" label=\"{{$ctrl.getLabel()}}\">\r\n  <div class=\"salaxy-read-only-value\">{{ $ctrl.value | date : \"dd.MM.yyyy HH:mm\" }}</div>\r\n</salaxy-form-group>\r\n`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/date.html\",`<salaxy-datepicker-popup ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\"></salaxy-datepicker-popup>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/default.html\",`<salaxy-input ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" minlength=\"{{$ctrl.getMinLength()}}\"\r\n  maxlength=\"{{$ctrl.getMaxLength()}}\" pattern=\"{{$ctrl.getPattern()}}\">\r\n</salaxy-input>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/email.html\",`<salaxy-input ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" sxy-email>\r\n</salaxy-input>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/enum.html\",`<salaxy-input-enum ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"{{ $ctrl.getFormat() }}\" options=\"$ctrl.getEnumOptions()\"></salaxy-input-enum>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/multiline.html\",`<salaxy-textarea ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" maxlength=\"10000\">\r\n</salaxy-textarea>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/password.html\",`<salaxy-input ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"password\"></salaxy-input>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/pension-contract-number.html\",`<salaxy-input  ng-if=\"'!admin' | sxyIsInRole\" ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"pension-contract-number\" sxy-pension-contract-number>\r\n</salaxy-input>\r\n<salaxy-input  ng-if=\"'admin' | sxyIsInRole\" ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\" disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" type=\"pension-contract-number\">\r\n</salaxy-input>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/string/telephone.html\",`<salaxy-input ng-model=\"$ctrl.value\" name=\"{{ $ctrl.id }}\" label=\"{{ $ctrl.getLabel() }}\" tooltip-html=\"{{ $ctrl.getDescr() }}\" read-only=\"$ctrl.getReadOnly()\"\r\n  disabled=\"$ctrl.getDisable()\" require=\"$ctrl.getRequire()\" sxy-mobile-phone></salaxy-input>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyAlert.html\",`<div class=\"salaxy-component salaxy-alert\">\r\n  <!-- TODO: Switch styling to \"sxy-component sxy-alert\" -->\r\n  <div ng-class=\"$ctrl.getAlertClasses()\">\r\n    <div>\r\n      <table style=\"width: 100%; border-collapse:separate;\">\r\n        <!-- TODO: Switch this to position:absolute & margins or flex-grid -->\r\n        <tr>\r\n          <td class=\"icon-container hidden-xxs\" ng-if=\"$ctrl.getAlertIcon()\">\r\n            <span class=\"icon\"><i class=\"fa {{ $ctrl.getAlertIcon() }}\"></i></span>\r\n          </td>\r\n          <td>\r\n            <div class=\"main\">\r\n              <ng-transclude>\r\n                <div sxy-html=\"{{$ctrl.msg}}\"></div>\r\n              </ng-transclude>\r\n            </div>\r\n          </td>\r\n          <td ng-if=\"$ctrl.aside\" class=\"text-right\">\r\n            <button class=\"btn btn-info btn-main\" ng-click=\"$ctrl.showMoreInfo = !$ctrl.showMoreInfo\" sxy-text=\"SALAXY.UI_Terms.learnMore\"></button>\r\n          </td>\r\n        </tr>\r\n      </table>\r\n      <div class=\"collapse\" ng-if=\"$ctrl.aside\" ng-class=\"{ show: $ctrl.showMoreInfo }\">\r\n        <div sxy-html=\"$ctrl.aside\"></div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyCodeEditor.html\",`<div class=\"salaxy-component sxy-code-editor\">\r\n  <div ng-if=\"$ctrl.mode == 'basic'\">\r\n    <pre ng-if=\"$ctrl.readOnly\" style=\"padding: 10px; background-color: #1e1e1e; color: #d4d4d4\">{{ $ctrl.code }}</pre>\r\n    <textarea ng-if=\"!$ctrl.readOnly\"\r\n      style=\"font-family: 'Courier New', Courier, monospace; background-color: #1e1e1e; color: #d4d4d4; padding: 10px; width: 100%;\"\r\n      ng-model=\"$ctrl.value\" ng-model-options=\"{allowInvalid: true, debounce: 250, updateOn: 'default' }\" ng-change=\"$ctrl.onChange()\"\r\n      name=\"actionContent\" rows=\"10\"></textarea>\r\n  </div>\r\n  <div ng-if=\"$ctrl.mode != 'basic'\">\r\n    <iframe ng-src=\"{{ $ctrl.monacoUrl }}\" style=\"width: 100%;\" ng-style=\"{ height: $ctrl.height || '400px' }\"></iframe>\r\n  </div>\r\n</div>\r\n\r\n\r\n`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyFieldset.html\",`<div ng-switch=\"$ctrl.format\" ng-if=\"$ctrl.form\">\r\n  <fieldset ng-switch-when=\"source\">\r\n    <legend>Form inputs source code (auto-gen)</legend>\r\n    <pre>&lt;fieldset&gt;\r\n  &lt;legend&gt;{{ $ctrl.label }}&lt;/legend&gt;\r\n<span ng-repeat=\"input in $ctrl.getChildInputs()\">  &lt;sxy-input model=\"{{ input.path }}\"&gt;&lt;/sxy-input&gt;<br /></span>&lt;/fieldset&gt;\r\n</pre>\r\n  </fieldset>\r\n  <fieldset ng-switch-default>\r\n    <legend>{{ $ctrl.getLabel() }}</legend>\r\n    <p>{{ $ctrl.getDescr() }}</p>\r\n    <sxy-input model=\"{{ input.path }}\" ng-repeat=\"input in $ctrl.getChildInputs()\"></sxy-input>\r\n  </fieldset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyForm.html\",`<div class=\"salaxy-component sxy-form form-horizontal\">\r\n  <h2 ng-if=\"$ctrl.legend\">{{ $ctrl.legend }}</h2>\r\n  <ng-form name=\"$ctrl.ngForm\">\r\n    <div ng-if=\"!$ctrl.isReady\">\r\n      <p>Ladataan...</p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.isReady\">\r\n      <div ng-if=\"!$ctrl.autoGen\" ng-transclude=\"div\">\r\n        <div class=\"alert alert-info\">\r\n          Either set <code>auto-gen</code> attribute to true or add a\r\n          <code>DIV</code> element with your form sxy-input definitions.\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.autoGen\">\r\n        <sxy-fieldset model=\"form\" label=\"{{ $ctrl.label }}\"></sxy-fieldset>\r\n      </div>\r\n      <div ng-if=\"$ctrl.debugger\">\r\n        <uib-tabset active=\"$ctrl.currentTab\">\r\n          <uib-tab index=\"'data'\" heading=\"Data\">\r\n            <salaxy-json-formatter key=\"'data'\" json=\"$ctrl.model\" open=\"2\"></salaxy-json-formatter>\r\n          </uib-tab>\r\n          <uib-tab index=\"'schema'\" heading=\"Auto-gen\">\r\n            <salaxy-json-formatter key=\"$ctrl.type\" json=\"$ctrl.schemaModel\" open=\"2\"></salaxy-json-formatter>\r\n          </uib-tab>\r\n          <uib-tab index=\"'codeGen'\" heading=\"Code-gen\">\r\n            <sxy-fieldset model=\"form\" format=\"source\" label=\"{{ $ctrl.label }}\"></sxy-fieldset>\r\n          </uib-tab>\r\n          <uib-tab index=\"'registrations'\" heading=\"Components\">\r\n            <p>\r\n              This is a list of component registrations. Note that debugger \"Code-gen\" tab currently makes one registration for the form (with name \"[Parent][n1]_form[n2]\"). This might be removed later.\r\n            </p>\r\n            <ul>\r\n              <li ng-repeat=\"(key, value) in $ctrl.registeredInputs\">{{ key }}</li>\r\n            </ul>\r\n          </uib-tab>\r\n          <uib-tab index=\"'validation'\" heading=\"Validation\">\r\n            <salaxy-validation-summary api-validation=\"$ctrl.getValidation()\"></salaxy-validation-summary>\r\n          </uib-tab>\r\n        </uib-tabset>\r\n      </div>\r\n    </div>\r\n  </ng-form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyGrid.html\",`<div class=\"salaxy-component sxy-grid height100\">\r\n  <div class=\"btn-toolbar\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.addRow()\">Add row</button>\r\n      <button type=\"button\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.selection.length\" ng-click=\"$ctrl.deleteSelectedRows()\">Delete rows ({{ $ctrl.selection.length }})</button>\r\n    </div>\r\n    <div class=\"btn-group\" ng-if=\"$ctrl\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-controller=\"ExportController as $export\" ng-click=\"$export.showExport($ctrl.getExportable())\">Export</button>\r\n    </div>\r\n  </div>\r\n  <div id=\"dataGrid\" class=\"ag-theme-balham height100\" style=\"height: calc(100% - 34px);overflow: hidden;\"></div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyInput-dialog-edit.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h4 class=\"modal-title\">{{ $ctrl.logic.title }}</h4>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <sxy-form open-api=\"{{ $ctrl.logic.openApi }}\" type=\"{{ $ctrl.logic.type }}\" auto-gen=\"true\" debugger=\"$ctrl.logic.debugger\" model=\"$ctrl.current\" read-only=\"{{$ctrl.logic.isReadOnly ? 'true' : ''}}\"></sxy-form>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button type=\"button\" ng-if=\"$ctrl.logic.showDelete\" class=\"btn btn-danger pull-left\" ng-click=\"$close('delete-no-save')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n  <button type=\"reset\" ng-if=\"!$ctrl.logic.isReadOnly\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n  <button type=\"button\" ng-if=\"!$ctrl.logic.isReadOnly\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n  <button type=\"button\" ng-if=\"$ctrl.logic.isReadOnly\" class=\"btn btn-primary\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxyInput.html\",`<ng-include src=\"$ctrl.templateUrl\" ng-if=\"$ctrl.form\"></ng-include>`);\n\n $templateCache.put(\"salaxy-components/sxy-form/SxySchemaEditor.html\",`<div class=\"row\">\r\n  <div class=\"col-md-6\" ng-repeat=\"(key, value) in $ctrl.model\">\r\n    <fieldset>\r\n      <legend>\r\n        <button type=\"button\" class=\"btn btn-danger btn-xs pull-right\" ng-click=\"$ctrl.deleteProperty(key)\">Poista</button>\r\n        {{ $index + 1 }}. {{ key }}\r\n      </legend>\r\n      <salaxy-input label=\"Teksti\" name=\"title\" ng-model=\"value.title\"></salaxy-input>\r\n      <salaxy-input label=\"Kuvaus\" name=\"description\" ng-model=\"value.description\"></salaxy-input>\r\n      <salaxy-input-enum label=\"Tietotyyppi\" name=\"type\" ng-model=\"value.type\"\r\n        options=\"$ctrl.types\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"value.type\" label=\"Käyttöliittymä\" name=\"type\" ng-model=\"value.format\"\r\n        disable-cache=\"true\" options=\"$ctrl.getFormats(value.type)\"></salaxy-input-enum>\r\n<!--\r\n- Lisää esikatselu\r\n- Lisää Array: Prosenttipohjainen jako, ehkä myös string ja number\r\n-->\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-md-6\">\r\n    <button type=\"button\" class=\"btn btn-primary btn-block\" ng-click=\"$ctrl.addProperty()\">Lisää uusi</button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/sxy-table/SxyTable.html\",`<div style=\"margin-top: 10px; margin-bottom: 10px;\"></div>`);\n\n $templateCache.put(\"salaxy-components/test/AccountReset.html\",`<div class=\"salaxy-component salaxy-account-reset\">\r\n  <hr />\r\n  <h2>Vain testiympäristö</h2>\r\n  <p class=\"lead\">\r\n    Nämä toiminnallisuudet ovat näkyvissä vain testiympäristössä. Voit käyttää näitä toimintoja testataksesi työnantajan tiliä eri tiloissa.\r\n  </p>\r\n  <div class=\"table-responsive\">\r\n    <table class=\"table\">\r\n      <tr>\r\n        <td>Poista kaikki laskelmat.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteCalculations()\">Poista laskelmat</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista kaikki työntekijät. Tämä poistaa myös laskelmat, jos niitä on.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteWorkers()\">Poista työntekijät</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista loma- ja poissaolokirjanpito kaikilta työntekijöiltä.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteHolidays()\">Poista lomat ja poissaolot</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista kaikki data: Laskelmien ja työntekijöiden lisäksi myös mahd. työsopimukset, raportit jne. Asetukset ja allekirjoitus pysyvät ennallaan.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteData()\">Poista kaikki data</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista TyEL ja Tapavak: Käyttäjällä on puutteita palkanmaksun asetuksissa.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deletePensionAndInsurance()\">Poista TyEL ja Tapavak</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista Allekirjoitus: Käyttäjä keskeyttänyt Onboarding-wizardin ennen digitaalista allekirjoitusta.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteSignature()\">Poista Allekirjoitus</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Poista luodut tilit. Tämän tilin luomat uudet tilit, joilla ei ole maksettuja laskelmia tai allekirjoituksia, poistetaan.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteAuthorizingAccounts()\">Poista luodut tilit</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>Tuhoa tili: Tuhoa koko tili. Voit aloittaa Onboarding-prosessin alusta.</td>\r\n        <td><button class=\"btn btn-danger btn-block\" ng-click=\"$ctrl.deleteCurrent()\">Tuhoa tili</button></td>\r\n      </tr>\r\n      <tr>\r\n        <td>{{$ctrl.isKycMissing() ? 'Aktivoi tilin KYC' : 'Poista tilin KYC'}}</td>\r\n        <td>\r\n          <button ng-class=\"$ctrl.isKycMissing() ? 'btn-info' : 'btn-danger'\" class=\"btn btn-block\" ng-click=\"$ctrl.handleKyc()\">{{$ctrl.isKycMissing() ? 'Aktivoi KYC' : 'Poista KYC'}}</button>\r\n        </td>\r\n      </tr>\r\n    </table>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/test/SmokeTest.html\",`<div ng-switch=\"$ctrl.mode\">\r\n  <fieldset ng-switch-when=\"reports\">\r\n    <legend><code>@salaxy/reports</code> functionality</legend>\r\n    <p>\r\n      Library loaded:\r\n      <span class=\"label\" ng-class=\"$ctrl.reportsTests.loaded ? 'label-success' : 'label-danger'\">{{ $ctrl.reportsTests.loaded ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Basic functionality:\r\n      <span class=\"label\" ng-class=\"$ctrl.reportsTests.mapper ? 'label-success' : 'label-danger'\">{{ $ctrl.reportsTests.mapper ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Report templates <small>(Handlebars)</small>:\r\n      <span class=\"label\" ng-class=\"$ctrl.reportsTests.handlebars ? 'label-success' : 'label-danger'\">{{ $ctrl.reportsTests.handlebars ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n  </fieldset>\r\n  <fieldset ng-switch-default>\r\n    <legend><code>@salaxy/core</code> functionality</legend>\r\n    <p>\r\n      Basic functionality:\r\n      <span class=\"label\" ng-class=\"$ctrl.getNumber() ? 'label-success' : 'label-danger'\">{{ $ctrl.getNumber() ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Dates <small>(MomentJS loaded)</small>:\r\n      <span class=\"label\" ng-class=\"$ctrl.getADate() == '20.02.2020' ? 'label-success' : 'label-danger'\">\r\n        {{ $ctrl.getADate() == '20.02.2020' ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Token <small>(Base64)</small>:\r\n      <span class=\"label\" ng-class=\"$ctrl.readToken() ? 'label-success' : 'label-danger'\">{{ $ctrl.readToken() ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Text from json: {{ $ctrl.getJson() }}\r\n      <span class=\"label\" ng-class=\"$ctrl.getJson() == 'This text is in json' ? 'label-success' : 'label-danger'\">{{ $ctrl.getJson() == 'This text is in json' ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n  </fieldset>\r\n  <fieldset ng-switch-when=\"ng1\">\r\n    <legend><code>@salaxy/ng1</code> functionality</legend>\r\n    <p>\r\n      Library loaded:\r\n      <span class=\"label\" ng-class=\"$ctrl.sessionSrv ? 'label-success' : 'label-danger'\">{{ $ctrl.sessionSrv ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <p>\r\n      Basic functionality:\r\n      <span class=\"label\" ng-class=\"$ctrl.sessionSrv.isInSomeRole('auth,anon,init') ? 'label-success' : 'label-danger'\">{{ $ctrl.sessionSrv.isInSomeRole('auth,anon,init') ? \"OK\" : \"ERROR\" }}</span>\r\n    </p>\r\n    <div>\r\n      <p>Component with template: You should see a drop-down menu with insurance companies below.</p>\r\n      <salaxy-input-enum enum=\"InsuranceCompany\" name=\"InsuranceCompany\" label=\"SALAXY.NG1.ProductDialogsComponent.company\" ng-model=\"$ctrl.temp.insuranceCompany\"></salaxy-input-enum>\r\n    </div>\r\n  </fieldset>\r\n  <fieldset ng-switch-when=\"ng1\">\r\n    <legend><code>@salaxy/ng1</code> AngularJS Modules</legend>\r\n    <div>\r\n      <b>angular-i18n (angular-locale_fi):</b><br /> The following sums should have the same euro currency format: {{ 1234 | currency }} == 1 234,00€<br /> Date should be in Finnish format: 20.12.2021 == {{ \"2021-12-20\" | date }}\r\n    </div>\r\n    <div>\r\n      <b>angular-route:</b>\r\n      <span class=\"label label-warning\">TODO</span>\r\n    </div>\r\n    <div>\r\n      <b>angular-sanitize:</b>\r\n      <div sxy-html=\"&lt;span class='label label-success'&gt;This text should be in GREEN background&lt;/span&gt;\"></div>\r\n    </div>\r\n    <div>\r\n      <b>angular-translate:</b><br />\r\n      <p>This text should be \"Kyllä\" / \"Yes\": <strong sxy-text=\"SALAXY.UI_Terms.yes\">ERROR</strong> <small>(ng1)</small></p>\r\n      <p>This text should be \"OK\": <strong sxy-text=\"SALAXY.UI_Terms.ok\">ERROR</strong> <small>(core)</small></p>\r\n    </div>\r\n    <div>\r\n      <b>angular-ui-bootstrap:</b> You should see a progress bar below:<br />\r\n      <uib-progressbar class=\"progress-striped active\" max=\"200\" value=\"166\" type=\"danger\"></uib-progressbar>\r\n    </div>\r\n    <!-- <div>\r\n      <b>Chart <small>Chart.js, angular-chart.js and chartjs-plugin-annotation</small>:</b> You should see a chart below with annotation.\r\n      <div class=\"salaxy-tax-card-chart chart-container\">\r\n        <canvas id=\"line\" class=\"chart chart-line\" chart-data=\"$ctrl.chartData.data\" chart-dataset-override=\"$ctrl.chartData.datasets\" chart-labels=\"$ctrl.chartData.labels\" chart-fill=\"$ctrl.chartData.fill\" chart-colors=\"$ctrl.chartData.colors\" chart-options=\"$ctrl.chartData.options\"></canvas>\r\n      </div>\r\n    </div> -->\r\n    <div>\r\n      <b>ng-file-upload:</b><br />\r\n      <button type=\"button\" class=\"btn btn-default\" ngf-select=\"upload($file)\">Click me to show Upload dialog</button> (Open/Cancel does nothing)\r\n    </div>\r\n    <hr />\r\n    <legend><code>@salaxy/ng1</code> Imported Modules</legend>\r\n    <div>\r\n      <b>file-saver:</b>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.saveAs()\">Click me to download a text file.</button>\r\n    </div>\r\n    <div>\r\n      <b>jszip:</b>\r\n      <span class=\"label label-warning\">TODO</span>\r\n    </div>\r\n    <div>\r\n      <b>marked: The following text should be formatted:</b>\r\n      <div ng-bind-html=\"'_italic_, **bold**, 'monospace', ~~strikethrough~~, [link](http://example.com)' | sxyMarkdown\"></div>\r\n    </div>\r\n    <div>\r\n      <b>rrule:</b>\r\n      <span class=\"label label-warning\">TODO</span>\r\n    </div>\r\n    <hr />\r\n    <legend>Removed</legend>\r\n    <p>The following dependencies have been dropped from this version:</p>\r\n    <ul>\r\n      <li>Babel (was in core): Babel was obsolete and we can target 2015. If necesssary, consider https://github.com/ryanelian/ts-polyfill or https://polyfill.io/v3/url-builder/ instead of js-core 3 (it has advertising issues).</li>\r\n      <li>js-base64: Moved from NG1 to Core (so not really removed)</li>\r\n      <li>angular-i18n: Not currently in use. Contains angular locales, e.g. </li>\r\n      <li>angular-animate: Removed as not used. Search for \"ngAnimate\" in projects.</li>\r\n      <li>angular-touch: Removed. Project marked as obsolete ages ago.</li>\r\n    </ul>\r\n  </fieldset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/AbsencePeriods.html\",`<div class=\"salaxy-component salaxy-holiday-year-absences\">\r\n  <div ng-if=\"!$ctrl.list\" class=\"alert alert-info\">\r\n    <p sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.selectWorker\"></p>\r\n  </div>\r\n  <div ng-if=\"$ctrl.list && $ctrl.mode == 'calendar'\">\r\n    <salaxy-calendar data=\"$ctrl.parent\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\"\r\n      start=\"$ctrl.filterStart\" end=\"$ctrl.filterEnd\" mapper=\"$ctrl.mapToCalendar\"></salaxy-calendar>\r\n    <div class=\"text-right\">\r\n      &nbsp;<br/>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showEditDialog('new')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.addAbsenceButtonText\"></button>\r\n    </div>\r\n  </div>\r\n  <div ng-if=\"$ctrl.list && $ctrl.mode != 'calendar'\">\r\n    <table class=\"table table-striped {{ $ctrl.condensed ? 'table-condensed' : '' }}\">\r\n      <thead>\r\n        <tr>\r\n          <th sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerAbsence\"></th>\r\n          <th class=\"right\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.headerDays\"></th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n        <tr ng-repeat=\"row in $ctrl.list | filter: $ctrl.filter\" ng-click=\"$ctrl.showEditDialog(row)\" class=\"clickable\">\r\n          <td>\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n            <strong>{{ \"AbsenceCauseCode.\" + row.causeCode | sxyEnum }}</strong><br />\r\n            <div class=\"pull-left\" style=\"padding: 0px;\">\r\n              {{ row.isPaid ? ('SALAXY.NG1.AbsencePeriodsComponent.isPaid' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notPaid' |sxyTranslate) }}\r\n              <span ng-if=\"row.isPaid != row.isHolidayAccrual\"> {{ row.isHolidayAccrual ? ('SALAXY.NG1.AbsencePeriodsComponent.isAccrual' | sxyTranslate) : ('SALAXY.NG1.AbsencePeriodsComponent.notAccrual' | sxyTranslate) }}</span>\r\n            </div>\r\n            <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n              &nbsp;{{ row.notes }}\r\n            </div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <strong>{{ row.period.daysCount | sxyCount : \"day\" }}</strong><br /> {{ row.period | sxyDateRange }}\r\n          </td>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.filteredList.length == 0\">\r\n          <td colspan=\"2\">\r\n            <h3 sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.noAbsences\"></h3>\r\n            <p sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.noAbsencesDescription\"></p>\r\n            <p sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.noAbsencesDescription2\"></p>\r\n          </td>\r\n        </tr>\r\n        <tr class=\"total\">\r\n          <td>\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" style=\"margin-bottom: 20px\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n            <strong>\r\n             <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalUnpaid\"></span><br />\r\n                         <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalNoHolidayAccrual\"></span><br />\r\n                           <span sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.totalAll\"></span><br />\r\n            </strong>\r\n          </td>\r\n          <td class=\"right\">\r\n            <strong>\r\n              {{ $ctrl.getTotalDays(\"absencesUnpaid\") | sxyCount : \"day\" }}<br />\r\n              {{ $ctrl.getTotalDays(\"absencesNoHolidayAccrual\") | sxyCount : \"day\" }}<br />\r\n              {{ $ctrl.getTotalDays(\"all\") | sxyCount : \"day\" }}<br />\r\n            </strong>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <div class=\"text-right\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showEditDialog('new')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsComponent.addAbsenceButtonText\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/AbsencePeriodsEditDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.panelHeading\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <form class=\"form-horizontal\" name=\"absencePeriodsForm\">\r\n      <salaxy-input-enum name=\"causeCode\" ng-model=\"$ctrl.current.causeCode\" enum=\"AbsenceCauseCode\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.absencesId.title\" type=\"typeahead\" ng-change=\"$ctrl.logic.updateIsPaid($ctrl.current)\" require=\"true\"></salaxy-input-enum>\r\n      <salaxy-datepicker-popup name=\"start\" ng-model=\"$ctrl.current.period.start\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.MODEL.DateRange.start.title\"></salaxy-datepicker-popup>\r\n      <salaxy-datepicker-popup name=\"end\" ng-model=\"$ctrl.current.period.end\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.MODEL.DateRange.end.title\"></salaxy-datepicker-popup>\r\n      <salaxy-form-group name=\"daysCount\" label=\"SALAXY.MODEL.DateRange.daysCount.title\" ng-if=\"$ctrl.current.period.days == null\">\r\n        <div class=\"input-group\">\r\n          <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"daysCount\" name=\"daysCount\" ng-model=\"$ctrl.current.period.daysCount\" disabled>\r\n          <span class=\"input-group-btn\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.logic.setDaysSelection($ctrl.current)\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.editDatesButtonText\"></button>\r\n          </span>\r\n        </div>\r\n      </salaxy-form-group>\r\n      <salaxy-date-range ng-model=\"$ctrl.current.period\" name=\"days\" mode=\"multiple\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.period.title\" min-date=\"$ctrl.current.period.start\" max-date=\"$ctrl.current.period.end\" ng-if=\"$ctrl.current.period.days != null\"></salaxy-date-range>\r\n      <salaxy-input-boolean type=\"checkbox\" name=\"isPaid\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.isPaid.title\" label-true=\"SALAXY.NG1.AbsencePeriodsEditDialog.label.isPaidLabelTrue\" disabled=\"!$ctrl.logic.canSelectIsPaid($ctrl.current)\" ng-model=\"$ctrl.current.isPaid\"\r\n        ng-change=\"$ctrl.logic.updateIsHolidayAccrual($ctrl.current)\"></salaxy-input-boolean>\r\n      <salaxy-input-boolean type=\"checkbox\" name=\"isHolidayAccrual\" label=\"SALAXY.MODEL.WorkerAbsencePeriod.isHolidayAccrual.title\" label-true=\"SALAXY.NG1.AbsencePeriodsEditDialog.label.isAccrualLabelTrue\" ng-model=\"$ctrl.current.isHolidayAccrual\"></salaxy-input-boolean>\r\n      <div>\r\n        <button type=\"submit\" ng-disabled=\"absencePeriodsForm.$invalid\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n        <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n        <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.deleteButtonText\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details.html\",`<ng-include src=\"'salaxy-components/worker/employment/Details_Header.html'\"></ng-include>\r\n\r\n<div ng-if=\"$ctrl.status == 'initialLoading'\">\r\n  <p sxy-text=\"SALAXY.UI_Terms.loading\"></p>\r\n</div>\r\n<div>\r\n  <uib-tabset active=\"$ctrl.currentTab\" ng-if=\"$ctrl.current\">\r\n    <uib-tab index=\"'default'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.workerInfo' | sxyTranslate }}\">\r\n      <ng-include src=\"'salaxy-components/worker/employment/Details_Basic.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab index=\"'employment'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.employment' | sxyTranslate }}\">\r\n      <ng-include src=\"'salaxy-components/worker/employment/Details_EmploymentRelation.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab index=\"'calcRows'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.defaultCalcRows' | sxyTranslate }}\">\r\n      <ng-include src=\"'salaxy-components/worker/employment/Details_Calc.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab index=\"'calculations'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.calculations' | sxyTranslate }}\">\r\n      <salaxy-odata-table ng-if=\"$ctrl.current.personalInfo\" read-only=\"$ctrl.isReadOnlyForced\" crud-controller=\"CalculationCrudController as $crud\"\r\n        options=\"{ $filter: 'otherPartyInfo/officialId eq \\\\'' + $ctrl.current.personalInfo.officialId + '\\\\' and ( status ne \\\\'proDraft\\\\' and status ne \\\\'payrollDraft\\\\')' }\"\r\n        template-url=\"salaxy-components/odata/lists/CalculationsWorker.html\" logic=\"$ctrl.calcListLogic\">\r\n      </salaxy-odata-table>\r\n    </uib-tab>\r\n    <uib-tab index=\"'taxcards'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.taxcards' | sxyTranslate }}\">\r\n      <ng-include src=\"'salaxy-components/worker/employment/Details_Tax.html'\"></ng-include>\r\n    </uib-tab>\r\n    <uib-tab ng-if=\"!('disableHolidays' | sxyIsInRole)\" index=\"'holidays'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.holidays' | sxyTranslate }}\">\r\n      <salaxy-worker-holidays employment-id=\"$ctrl.current.id\"></salaxy-worker-holidays>\r\n    </uib-tab>\r\n    <uib-tab ng-if=\"!('disableHolidays' | sxyIsInRole)\" index=\"'absences'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.absences' | sxyTranslate }}\">\r\n      <salaxy-worker-absences employment-id=\"$ctrl.current.id\"></salaxy-worker-absences>\r\n    </uib-tab>\r\n    <uib-tab ng-if=\"!$ctrl.isModal || !isHousehold\" index=\"'records'\" heading=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.records.label' | sxyTranslate }}\">\r\n      <!-- Removed from modal / household combination because tabs were too wide in Palkkamylly. -->\r\n      <salaxy-records ng-if=\"$ctrl.current\" read-only=\"$ctrl.isReadOnlyForced\" api-ctrl=\"$ctrl\" entity-type=\"'employment'\"></salaxy-records>\r\n    </uib-tab>\r\n    <uib-tab ng-if=\"'disabled-test' | sxyIsInRole\" index=\"'debugger'\" heading=\"DEBUG\">\r\n      <p><a ng-href=\"{{'#/workers/details/' + $ctrl.current.info.workerAccountId}}\">Old version (Worker ID {{ $ctrl.current.info.workerAccountId }})</a></p>\r\n      <salaxy-json-formatter json=\"$ctrl.current\" open=\"1\" key=\"'Employment'\"></salaxy-json-formatter>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details_Basic.html\",`<div class=\"salaxy-component salaxy-worker-employment\">\r\n  <form name=\"basicForm\" class=\"form-horizontal\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n    <div class=\"row\">\r\n      <div class=\"col-md-6\">\r\n        <fieldset ng-if=\"$ctrl.isNew()\">\r\n          <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.details\"></legend>\r\n          <salaxy-input name=\"firstName\" label=\"SALAXY.NG1.WorkerDetailsComponent.firstName\" ng-required=\"true\" ng-model=\"$ctrl.current.identity.firstName\"></salaxy-input>\r\n          <salaxy-input name=\"lastName\" label=\"SALAXY.NG1.WorkerDetailsComponent.lastName\" ng-required=\"true\" ng-model=\"$ctrl.current.identity.lastName\"></salaxy-input>\r\n          <salaxy-input name=\"officialPersonId\" label=\"SALAXY.NG1.WorkerDetailsComponent.ssNumber\" sxy-personal-id-fi ng-required=\"true\" ng-model=\"$ctrl.current.identity.personalId\"></salaxy-input>\r\n          <salaxy-input-enum enum=\"Language\" ng-model=\"$ctrl.current.identity.language\" name=\"workerLanguage\" label=\"SALAXY.NG1.WorkerDetailsComponent.language\"></salaxy-input-enum>\r\n        </fieldset>\r\n        <fieldset ng-if=\"!$ctrl.isNew()\">\r\n          <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.details\"></legend>\r\n          <salaxy-form-group label=\"SALAXY.UI_Terms.name\" name=\"name\" class=\"salaxy-read-only\">\r\n            <div class=\"salaxy-read-only-value\">{{ $ctrl.current.identity.lastName}}, {{ $ctrl.current.identity.firstName}}</div>\r\n          </salaxy-form-group>\r\n          <salaxy-input name=\"officialPersonId\" label=\"SALAXY.NG1.WorkerDetailsComponent.ssNumber\" sxy-personal-id-fi read-only=\"true\" ng-required=\"true\" ng-model=\"$ctrl.current.identity.personalId\"></salaxy-input>\r\n          <salaxy-form-group ng-if=\"'workers.employments.employmentId' | sxyShow: 'workers.index'\" label=\"SALAXY.NG1.WorkerDetailsComponent.workerId\" name=\"workerId\">\r\n            <div class=\"salaxy-read-only-value\">\r\n              <small ng-if=\"!$ctrl.current.isRegistered\">{{ $ctrl.current.info.workerAccountId | sxyIban }}</small>\r\n              <code ng-if=\"$ctrl.current.isRegistered\">{{ $ctrl.current.info.workerAccountId | sxyIban }}</code><br/>\r\n              <small>({{ $ctrl.current.isRegistered ? \"Rekisteröitynyt, pysyvä ID\" : \"Ei rekisteröitynyt, tilapäinen ID\" }})</small>\r\n            </div>\r\n          </salaxy-form-group>\r\n          <salaxy-input-enum enum=\"Language\" ng-model=\"$ctrl.current.identity.language\" read-only=\"$ctrl.current.isRegistered\" name=\"workerLanguage\" label=\"SALAXY.NG1.WorkerDetailsComponent.language\"></salaxy-input-enum>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.paymentDetails\"></legend>\r\n          <salaxy-input-enum label=\"SALAXY.NG1.WorkerDetailsComponent.salaryPaymentMethod\" name=\"employmentRelationSalaryPaymentMethod\" ng-model=\"$ctrl.current.info.salaryPaymentMethod\" enum=\"EmploymentRelationSalaryPaymentMethod\" required placeholder=\"SALAXY.UI_Terms.selectAlt\"></salaxy-input-enum>\r\n          <salaxy-input ng-if=\"$ctrl.current.info.salaryPaymentMethod === 'bankAccount'\" name=\"ibanNumber\" label=\"SALAXY.NG1.WorkerDetailsComponent.ibanNumber\" sxy-iban\r\n            require=\"$ctrl.isRequired('ibanNumber')\" ng-model=\"$ctrl.current.info.ibanNumber\" tooltip-html=\"{{ $ctrl.getInputTooltip('ibanNumber') }}\"></salaxy-input>\r\n        </fieldset>\r\n      </div>\r\n      <div class=\"col-md-6\">\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.contactInfo\"></legend>\r\n          <salaxy-input name=\"email\" label=\"SALAXY.NG1.WorkerDetailsComponent.email\" sxy-email ng-model=\"$ctrl.getContact().email\" tooltip-html=\"{{ $ctrl.getInputTooltip('email') }}\"></salaxy-input>\r\n          <salaxy-input name=\"telephone\" label=\"SALAXY.NG1.WorkerDetailsComponent.tel\" sxy-mobile-phone ng-model=\"$ctrl.getContact().telephone\" tooltip-html=\"{{ $ctrl.getInputTooltip('telephone') }}\"></salaxy-input>\r\n        </fieldset>\r\n        <fieldset>\r\n          <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.address\"></legend>\r\n          <p ng-if=\"!$ctrl.isOtherIdentifier\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.addressInfo\"></p>\r\n          <p ng-if=\"$ctrl.isOtherIdentifier\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.addressInfoOtherIdentifier\"></p>\r\n          <salaxy-input name=\"street\" label=\"SALAXY.NG1.WorkerDetailsComponent.street\" require=\"$ctrl.isRequired('street')\" ng-model=\"$ctrl.getContact().street\" tooltip-html=\"{{ $ctrl.getInputTooltip('street') }}\">\r\n          </salaxy-input>\r\n          <salaxy-input name=\"postalCode\" label=\"SALAXY.NG1.WorkerDetailsComponent.postalCode\" require=\"$ctrl.isRequired('postalCode')\" ng-model=\"$ctrl.getContact().postalCode\" tooltip-html=\"{{ $ctrl.getInputTooltip('postalCode') }}\">\r\n          </salaxy-input>\r\n          <salaxy-input name=\"city\" label=\"SALAXY.NG1.WorkerDetailsComponent.city\" require=\"$ctrl.isRequired('city')\" ng-model=\"$ctrl.getContact().city\" tooltip-html=\"{{ $ctrl.getInputTooltip('city') }}\">\r\n          </salaxy-input>\r\n        </fieldset>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.isModal\">\r\n      <button sxy-if-role=\"test\" ng-click=\"$ctrl.delete()\" type=\"button\" class=\"btn btn-danger\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n      <button ng-click=\"$ctrl.save()\" ng-disabled=\"basicForm.$invalid\" class=\"btn btn-primary pull-right\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details_Calc.html\",`\r\n\r\n<div>\r\n  <div class=\"pull-right\" ng-if=\"!$ctrl.isModal\">\r\n    <salaxy-json-formatter key=\"'Debug'\" sxy-if-role=\"test\" json=\"$ctrl.current.work.salaryDefaults\" open=\"1\" type=\"dialog\"></salaxy-json-formatter>\r\n    <button ng-click=\"$ctrl.save()\" ng-disabled=\"workerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n  </div>\r\n  <p>Oletuspalkkarivit kopioidaan uudelle laskelmalle sellaisenaan. Päivämäärärajaukset huomioidaan vain tuntien sisääntuonnissa.</p>  \r\n  <salaxy-calc-rows-editor rows=\"$ctrl.current.work.salaryDefaults\" row-sources=\"thisproperty will be removed, just a marker until refactoring\"\r\n    title=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.defaultCalcRows' | sxyTranslate }}\" type=\"salary-defaults-temp2\" mode=\"{{ $ctrl.isReadOnlyForced ? 'read-only' : 'edit'}}\"></salaxy-calc-rows-editor>\r\n  <hr>\r\n  <p>Hintoja käytetään tällä hetkellä tuntien sisään tuonnissa. Myöhemmissä versioissa oletushintoja käytetään myös laskurissa.</p>\r\n  <salaxy-row-types-settings ng-ref=\"$ctrl.$prices\" mode=\"prices\" model=\"$ctrl.current\"></salaxy-row-types-settings>\r\n</div>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<div class=\"row form-horizontal\" ng-if=\"!$ctrl.isHousehold && ('employments.defaultCalcRows.features' | sxyShow: 'workers.details')\">\r\n  <div class=\"col-sm-6\">\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerDetailsCalc.payrollDetails\"></legend>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.WorkerDetailsCalc.wageBasis\" name=\"wageBases\" ng-model=\"$ctrl.current.work.wageBasis\" enum=\"WageBasis\" type=\"select\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-input-enum>\r\n      <salaxy-input-number label=\"SALAXY.NG1.WorkerDetailsCalc.monthlyHours\" name=\"monthlyHours\" unit=\"hour\" ng-model=\"$ctrl.current.work.monthlyHours\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-input-number>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.WorkerDetailsCalc.irIncomeEarnerTypes\" label-type=\"basic\" name=\"wageBases\" ng-model=\"$ctrl.current.info.irIncomeEarnerTypes\" enum=\"IncomeEarnerType\" type=\"multi-select\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-input-enum>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-sm-6\">\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerDetailsCalc.integrations\"></legend>\r\n      <salaxy-input label=\"SALAXY.NG1.WorkerDetailsCalc.ssNumber\" name=\"sourceId\" ng-model=\"$ctrl.current.info.sourceId\" read-only=\"$ctrl.isReadOnlyForced\"></salaxy-input>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-sm-6\">\r\n    <salaxy-cost-accounting read-only=\"$ctrl.isReadOnlyForced\" ng-init=\"$ctrl.current.work.accounting = $ctrl.current.work.accounting ? $ctrl.current.work.accounting : { dimensions: []}\" current=\"$ctrl.current.work.accounting.dimensions\"\r\n      scope=\"calculation\"></salaxy-cost-accounting>\r\n  </div>\r\n</div>\r\n<div class=\"text-right\" ng-if=\"!$ctrl.isModal\">\r\n  <button ng-click=\"$ctrl.save()\" ng-disabled=\"workerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details_EmploymentRelation.html\",`﻿<div class=\"salaxy-component salaxy-worker-employment\">\r\n  <form name=\"employmentForm\" class=\"form-horizontal\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n    <ng-include src=\"'salaxy-components/worker/employment/shared-EmploymentRelation.html'\"></ng-include>\r\n    <div class=\"text-right\" ng-if=\"!$ctrl.isModal\">\r\n      <button ng-click=\"$ctrl.save()\" class=\"btn btn-primary\" ng-disabled=\"employmentForm.$invalid\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details_Header.html\",`<div class=\"salaxy-calc-worker-info\">\r\n  <div ng-if=\"$ctrl.status == 'initialLoading'\">\r\n    <div class=\"col-xs-3 col-sm-2 col-xxs-3 \">\r\n      <salaxy-spinner></salaxy-spinner>\r\n    </div>\r\n    <div class=\"col-xs-9 col-sm-10 col-xxs-9 worker-info-col\">\r\n      <h2 sxy-text=\"SALAXY.UI_Terms.loading\"></h2>\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          &nbsp;<br /> &nbsp;\r\n          <br /> &nbsp;\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          &nbsp;<br />\r\n          <div>&nbsp;</div>\r\n          <div>&nbsp;</div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\" ng-if=\"$ctrl.status !== 'initialLoading'\">\r\n    <div class=\"col-xs-3 col-sm-2 col-xxs-3\">\r\n      <salaxy-avatar avatar=\"$ctrl.current.personalInfo.avatar\"></salaxy-avatar>\r\n    </div>\r\n    <div class=\"col-xs-9 col-sm-10 col-xxs-9 worker-info-col\">\r\n      <salaxy-action-button label=\"SALAXY.NG1.WorkerDetailsComponent.newCalculation\" action=\"'newCalcForEmployment'\" ng-if=\"!$ctrl.isModal\" options=\"{'id': $ctrl.currentId }\" button-class=\"btn-default pull-right-xs\"></salaxy-action-button>\r\n      <h2>{{ $ctrl.current.personalInfo.avatar.displayName || (\"SALAXY.NG1.WorkerInfo.noSelection\" | sxyTranslate) }}</h2>\r\n      <div class=\"row\" ng-if=\"$ctrl.current\">\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          <div ng-class=\"$ctrl.current.personalInfo.officialId ? '' : 'text-danger'\">\r\n            {{ $ctrl.current.personalInfo.officialId || ( \"SALAXY.NG1.PaymentDialogComponent.noSSNumber\" | sxyTranslate ) }}\r\n            &nbsp;\r\n            <div class=\"btn-group\" uib-dropdown ng-if=\"$ctrl.otherEmployments.length > 0\">\r\n              <button id=\"single-button\" type=\"button\" class=\"btn btn-default btn-xs\" uib-dropdown-toggle>\r\n                {{ $ctrl.otherEmployments.length }} muuta työsuhdetta <span class=\"caret\"></span>\r\n              </button>\r\n              <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n                <li role=\"menuitem\" ng-repeat=\"item in $ctrl.otherEmployments\">\r\n                  <a ng-href=\"{{$ctrl.isModal ? '' : ('#/employments/details/' + item.id)}}\">\r\n                    {{ $ctrl.getEmploymentDescription(item) }}\r\n                    ({{ $ctrl.getActiveText(item) }})\r\n                  </a>\r\n                </li>\r\n              </ul>\r\n            </div>\r\n            <span ng-if=\"!$ctrl.otherEmployments\">Tarkistetaan muita työsuhteita...</span>\r\n          </div>\r\n          <div>{{ $ctrl.getEmploymentDescription($ctrl.current) }}</div>\r\n          <div>{{ $ctrl.getActiveText($ctrl.current) }}</div>\r\n          <div><small>{{ $ctrl.current.id }}</small></div>\r\n        </div>\r\n        <div class=\"col-xs-12 col-sm-6 \">\r\n          \r\n          <div ng-if=\"$ctrl.readOnlyDefaultContact.email\">\r\n            <a href=\"{{ 'mailto:' + $ctrl.readOnlyDefaultContact.email }}\">{{ $ctrl.readOnlyDefaultContact.email }}</a>\r\n          </div>\r\n          <div ng-if=\"!$ctrl.readOnlyDefaultContact.email\">\r\n            <span sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noEmail\"></span>\r\n            <span class=\"text-warning\" sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noEmailInfo\"></span>\r\n          </div>\r\n          <div ng-if=\"!$ctrl.current.info.ibanNumber\" class=\"text-danger\" sxy-text=\"SALAXY.NG1.WorkerInfo.noIbanNumber\"></div>\r\n          <div ng-if=\"$ctrl.current.info.ibanNumber\">IBAN: {{ $ctrl.current.info.ibanNumber | sxyIban }}</div>\r\n          <div ng-class=\"{ 'text-danger': $ctrl.getTaxCardInfo().isMissing }\">\r\n            {{ $ctrl.getTaxCardInfo().text }}</div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/Details_Tax.html\",`<form name=\"employmentTaxcardForm\" class=\"form-horizontal\" ng-readonly=\"$ctrl.isReadOnlyForced\">\r\n  <salaxy-input-enum label=\"SALAXY.NG1.WorkerDetailsComponent.employmentTaxcard\" name=\"employmentTaxcard\" ng-model=\"$ctrl.taxcardType\"\r\n    enum=\"EmploymentRelationTaxcard\" label-cols=\"col-sm-5\"></salaxy-input-enum>\r\n</form>\r\n<div ng-switch=\"$ctrl.current.info.taxcard\">\r\n  <div ng-switch-when=\"taxAtSource\">\r\n    <fieldset>\r\n      <legend>{{'SALAXY.NG1.EmploymentDetails.taxAtSource.title' | sxyTranslate}}</legend>\r\n      <div class=\"alert alert-danger\" ng-if=\"!$ctrl.socSec.isInternational\" sxy-html=\"SALAXY.NG1.EmploymentDetails.taxAtSource.info.html\"></div>\r\n      <salaxy-input-number name=\"percent\" unit=\"percent\" minimum=\"0\" maximum=\"100\" label=\"SALAXY.NG1.EmploymentDetails.percent\" label-cols=\"col-sm-8\" ng-model=\"$ctrl.current.international.taxAtSource.percent\" require=\"true\"></salaxy-input-number>\r\n      <salaxy-input-number name=\"deductionMonthly\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentDetails.monthlyDeduction\" label-cols=\"col-sm-8\" ng-model=\"$ctrl.current.international.taxAtSource.deductionMonthly\"></salaxy-input-number>\r\n      <salaxy-input-number name=\"deductionDaily\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentDetails.deductionDaily\" label-cols=\"col-sm-8\" ng-model=\"$ctrl.current.international.taxAtSource.deductionDaily\"></salaxy-input-number>\r\n    </fieldset>\r\n  </div>\r\n  <div ng-switch-when=\"noTaxCard\">\r\n    <fieldset>\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.taxCard.noTaxCard\"></legend>\r\n      <p sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.taxCard.noTaxCardText\"></p>\r\n    </fieldset>\r\n  </div>\r\n  <div ng-switch-default>\r\n    <salaxy-employment-taxcards employment-id=\"$ctrl.current.id\" on-save=\"$ctrl.reload()\" is-read-only-forced=\"$ctrl.isReadOnlyForced\" hide-buttons=\"$ctrl.isReadOnlyForced\"\r\n      ng-ref=\"$ctrl.taxcardsController\"></salaxy-employment-taxcards>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/employment/shared-EmploymentRelation.html\",`<div class=\"row\">\r\n  <div class=\"col-md-6\" ng-if=\"!$ctrl.isHousehold\">\r\n    <salaxy-input-enum ng-required=\"true\" hidden-options=\"undefined\" name=\"type\" ng-model=\"$ctrl.current.info.type\" ng-change=\"$ctrl.employmentTypeChange()\"\r\n      enum=\"EmploymentRelationType\" type=\"{{ $ctrl.socSec.isInternational ? 'select' : 'radio'}}\" label=\"Työsuhteen tyyppi\"\r\n      label-type=\"{{ $ctrl.current.info.type == 'foreignWorker' ? 'basic' : 'plain'}}\"\r\n      filter=\"entrepreneur,farmer,monthlySalary,hourlySalary,salary,employedByStateEmploymentFund,compensation,boardMember,athlete,performingArtist,foreignWorker\"></salaxy-input-enum>\r\n    <p>&nbsp;</p>\r\n    <div ng-if=\"( $ctrl.current.info.type == 'entrepreneur' ||  $ctrl.current.employment.type == 'farmer')\">\r\n      <div class=\"alert alert-danger\" ng-if=\"$ctrl.session.currentAccount.companyType =='fiTm'\" sxy-text=\"SALAXY.NG1.WorkerWizardComponent.workerType.entrepreneurTmiWarning\"></div>\r\n      <div class=\"alert alert-danger\" ng-if=\"$ctrl.session.currentAccount.companyType =='fiRy'\" sxy-text=\"SALAXY.NG1.WorkerWizardComponent.workerType.entrepreneurRyWarning\"></div>\r\n      <div class=\"alert alert-danger\" ng-if=\"$ctrl.session.currentAccount.entityType !='company'\" sxy-text=\"SALAXY.NG1.WorkerWizardComponent.workerType.entrepreneurPrivateWarning\"></div>\r\n    </div>\r\n    <fieldset ng-if=\"$ctrl.current.info.type == 'compensation'\">\r\n      <legend sxy-text=\"SALAXY.ENUM.EmploymentRelationType.compensation.label\"></legend>\r\n      <p>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerWizardComponent.workerType.compensationDescription\"></span><br>\r\n        <a href=\"{{'SALAXY.NG1.WorkerWizardComponent.workerType.compensationLink' | sxyTranslate}}\" target=\"_blank\" sxy-text=\"SALAXY.NG1.WorkerWizardComponent.workerType.compensationCta\"></a>\r\n      </p>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.socSec.isInternational\">\r\n      <legend>{{'SALAXY.NG1.EmploymentRelation.isInternational.title' | sxyTranslate}}</legend>\r\n      <p sxy-html=\"SALAXY.NG1.EmploymentRelation.isInternational.info.html\"></p>\r\n      <salaxy-input-enum type=\"select\" ng-model=\"$ctrl.country\" label=\"SALAXY.MODEL.EmploymentRelationInternational.country.title\" name=\"country\" require=\"true\" enum=\"Country\"\r\n        hidden-options=\"fi\"></salaxy-input-enum>\r\n      <salaxy-input-enum type=\"select\" ng-model=\"$ctrl.current.international.idType\" label=\"SALAXY.MODEL.EmploymentRelationInternational.idType.title\" name=\"idType\" require=\"true\"\r\n        enum=\"InternationalIdentifier\"></salaxy-input-enum>\r\n      <salaxy-input ng-model=\"$ctrl.current.international.foreignId\" label=\"SALAXY.MODEL.EmploymentRelationInternational.foreignId.title\" name=\"foreignId\"\r\n        require=\"true\"></salaxy-input>\r\n      <salaxy-input name=\"street\" label=\"SALAXY.NG1.WorkerDetailsComponent.street\" ng-model=\"$ctrl.getContact('foreign').street\" require=\"true\"></salaxy-input>\r\n      <salaxy-input name=\"postalCode\" label=\"SALAXY.NG1.WorkerDetailsComponent.postalCode\" ng-model=\"$ctrl.getContact('foreign').postalCode\" require=\"true\"></salaxy-input>\r\n      <salaxy-input name=\"city\" label=\"SALAXY.NG1.WorkerDetailsComponent.city\" ng-model=\"$ctrl.getContact('foreign').city\" require=\"true\"></salaxy-input>\r\n      <salaxy-input-enum type=\"select\" ng-model=\"$ctrl.getContact('foreign').country\" label=\"SALAXY.MODEL.EmploymentRelationInternational.contactCountry.title\"\r\n        name=\"contactCountry\" read-only=\"true\" enum=\"Country\"></salaxy-input-enum>\r\n      <salaxy-input ng-if=\"$ctrl.getContact('foreign').country == 'other'\" ng-model=\"$ctrl.getContact('foreign').countryOtherName\"\r\n        label=\"SALAXY.MODEL.EmploymentRelationInternational.country.title\" name=\"countryOtherName\" require=\"true\"></salaxy-input>\r\n      <salaxy-input-enum type=\"select\" name=\"taxation\"\r\n        options=\"{ taxAtSource: ('SALAXY.NG1.EmploymentRelation.taxation.taxAtSource' | sxyTranslate), auto: ('SALAXY.NG1.EmploymentRelation.taxation.auto' | sxyTranslate), manual: ('SALAXY.NG1.EmploymentRelation.taxation.manual' | sxyTranslate) }\"\r\n        label=\"SALAXY.NG1.EmploymentRelation.taxation.label\" ng-model=\"$ctrl.current.info.taxcard\"></salaxy-input-enum>\r\n    </fieldset>\r\n    <fieldset ng-if=\"false && $ctrl.current.info.taxcard == 'taxAtSource'\">\r\n      <legend>{{'SALAXY.NG1.EmploymentRelation.taxAtSourceInfo' | sxyTranslate}}</legend>\r\n      <salaxy-input-number name=\"percent\" unit=\"percent\" minimum=\"0\" maximum=\"100\" label=\"SALAXY.NG1.EmploymentRelation.percent\" label-cols=\"col-sm-8\"\r\n        ng-model=\"$ctrl.current.international.taxAtSource.percent\" require=\"true\"></salaxy-input-number>\r\n      <salaxy-input-number name=\"deductionMonthly\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentRelation.monthlyDeduction\" label-cols=\"col-sm-8\"\r\n        ng-model=\"$ctrl.current.international.taxAtSource.deductionMonthly\"></salaxy-input-number>\r\n      <salaxy-input-number name=\"deductionDaily\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentRelation.deductionDaily\" label-cols=\"col-sm-8\"\r\n        ng-model=\"$ctrl.current.international.taxAtSource.deductionDaily\"></salaxy-input-number>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-md-6\">\r\n    <fieldset ng-if=\"!$ctrl.isHousehold\">\r\n      <legend>{{'SALAXY.NG1.EmploymentRelation.socSec'|sxyTranslate}}</legend>\r\n      <salaxy-input-enum type=\"select\" name=\"socialSecurity\" ng-if=\"$ctrl.socSec.isInternational\" enum=\"InternationalSocialSecurityType\"\r\n        label=\"SALAXY.MODEL.EmploymentRelationInternational.socialSecurity.title\" ng-model=\"$ctrl.current.international.socialSecurity\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.current.international.socialSecurity == 'mixed'\" type=\"multi-select\" name=\"irIncomeEarnerTypes\" disable-cache=\"true\"\r\n        enum=\"InternationalSocialSecurityException\" label=\"SALAXY.MODEL.EmploymentRelationInternational.socialSecurityExceptions.title\"\r\n        ng-model=\"$ctrl.current.international.socialSecurityExceptions\" label-type=\"basic\" hidden-options=\"voluntaryEarningsRelatedPensionInsurance\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.pensionCalculationOptions\" type=\"select\" name=\"pensionCalculation\" disable-cache=\"true\"\r\n        options=\"$ctrl.socSec.pensionCalculationOptions\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.pension.title\" ng-model=\"$ctrl.current.info.pensionCalculation\"\r\n        ng-change=\"$ctrl.pensionCalculationChange()\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.showPensionCompanySelection\" type=\"select\" name=\"pensionCompany\" placeholder=\"SALAXY.UI_Terms.notChosen\" disable-cache=\"true\"\r\n        options=\"$ctrl.socSec.pensionCompanies\" label=\"SALAXY.MODEL.PensionContract.title\" ng-model=\"$ctrl.current.info.pensionCompany\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.pensionContractNumbers\" type=\"select\" name=\"pensionContractNumber\" placeholder=\"SALAXY.UI_Terms.notChosen\" disable-cache=\"true\"\r\n        options=\"$ctrl.socSec.pensionContractNumbers\" label=\"SALAXY.MODEL.PensionContract.contractNumber.title\"\r\n        ng-model=\"$ctrl.current.info.pensionContractNumber\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.showPension && ('test,admin,pro' | sxyIsInRole)\" type=\"select\" name=\"pensionRule\" enum=\"PensionRule\"\r\n        label=\"SALAXY.NG1.WorkerWizardComponent.employment.pensionRule\" ng-model=\"$ctrl.current.info.pensionRule\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.showInsuranceCompanySelection\" type=\"select\" name=\"insuranceCompany\" placeholder=\"SALAXY.UI_Terms.notChosen\" disable-cache=\"true\"\r\n        options=\"$ctrl.socSec.insuranceCompanies\" label=\"SALAXY.NG1.InsuranceSettingsComponent.insurance.title\" ng-model=\"$ctrl.current.info.insuranceCompany\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.socSec.insuranceContractNumbers\" type=\"select\" name=\"insuranceContractNumber\" placeholder=\"SALAXY.UI_Terms.notChosen\" disable-cache=\"true\"\r\n        options=\"$ctrl.socSec.insuranceContractNumbers\" label=\"SALAXY.MODEL.InsuranceContract.contractNumber.title\"\r\n        ng-model=\"$ctrl.current.info.insuranceContractNumber\"></salaxy-input-enum>\r\n    </fieldset>\r\n    <fieldset>\r\n      <legend ng-if=\"!$ctrl.isHousehold\">{{'SALAXY.NG1.EmploymentRelation.employmentRelation'|sxyTranslate}}</legend>\r\n      <salaxy-input ng-model=\"$ctrl.current.work.description\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.work.description\" name=\"description\"></salaxy-input>\r\n      <salaxy-input-occupation-type  name=\"occupationType\" ng-model=\"$ctrl.current.work.occupationCode\"\r\n        label=\"SALAXY.NG1.WorkerWizardComponent.employment.work.occupationCode\"></salaxy-input-occupation-type>\r\n      <salaxy-input tooltip-html=\"&lt;a target=&#39;_blank&#39; href=&#39;https://www.keva.fi/tyonantajalle/elakemaksut/ammattinimikkeiden-haku/&#39;&gt;Info&lt;/a&gt;\" ng-if=\"$ctrl.current.info.pensionCalculation == 'publicSector'\" name=\"occupationCode2\" ng-model=\"$ctrl.current.work.occupationCode2\"\r\n        label=\"SALAXY.NG1.WorkerWizardComponent.employment.work.occupationCode2\"></salaxy-input>\r\n      <salaxy-form-group label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.title\" name=\"contract\">\r\n        <salaxy-datepicker-popup name=\"startDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.startDate\"\r\n          ng-model=\"$ctrl.current.info.startDate\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"endDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.endDate\"\r\n          disabled=\"!$ctrl.current.info.isFixedTerm && !$ctrl.current.info.isTerminated\" ng-model=\"$ctrl.current.info.endDate\"></salaxy-datepicker-popup>\r\n        <salaxy-input-boolean type=\"checkbox\" ng-model=\"$ctrl.current.info.isFixedTerm\" name=\"isFixedTerm\" id=\"isFixedTerm\" label-type=\"no-label\" label-true=\"SALAXY.NG1.WorkerWizardComponent.employment.isFixedTerm\"></salaxy-input-boolean>\r\n        <salaxy-input-boolean type=\"checkbox\" ng-model=\"$ctrl.current.info.isTerminated\" name=\"isTerminated\" id=\"isTerminated\" label-type=\"no-label\" label-true=\"SALAXY.NG1.WorkerWizardComponent.employment.isTerminated\"></salaxy-input-boolean>\r\n\r\n      </salaxy-form-group>\r\n      <salaxy-input-enum ng-if=\"$ctrl.current.info.pensionCalculation == 'publicSector'\" type=\"select\" name=\"employmentRegCodes\" disable-cache=\"true\"\r\n      options=\"$ctrl.socSec.employmentRegCodes\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.employmentRegCode\" ng-model=\"$ctrl.current.info.employmentRegCode\"></salaxy-input-enum>\r\n      <salaxy-input-enum ng-if=\"$ctrl.current.isReadOnly\" label=\"SALAXY.NG1.WorkerDetailsComponent.salaryPaymentMethod\" name=\"employmentRelationSalaryPaymentMethod\"\r\n        ng-model=\"$ctrl.current.info.salaryPaymentMethod\" enum=\"EmploymentRelationSalaryPaymentMethod\" required placeholder=\"SALAXY.UI_Terms.selectAlt\"></salaxy-input-enum>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentEditModal.html\",`﻿<div class=\"modal-worker-edit\">\r\n  <div class=\"modal-header\">\r\n    <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h2 class=\"modal-title\">{{$ctrl.logic.title}}</h2>\r\n  </div>\r\n  <div class=\"modal-body\">\r\n    <salaxy-employment-details model=\"$ctrl.current\" current-tab=\"{{$ctrl.logic.initialTab}}\" is-read-only-forced=\"$ctrl.route.readOnly\" is-modal=\"true\"></salaxy-employment-details>\r\n  </div>\r\n  <div class=\"modal-footer text-right\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" ng-if=\"$ctrl.logic.buttonTypes != 'updateCalc'\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    <button type=\"submit\" class=\"btn btn-default\" ng-click=\"$close('ok-no-rows')\" ng-if=\"$ctrl.logic.buttonTypes == 'updateCalc'\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.workerEdit.updateWorkerInfo\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" ng-if=\"$ctrl.logic.buttonTypes == 'updateCalc'\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.workerEdit.updateWorkerInfoAndSalaryRows\"></button>\r\n  </div>\r\n</div>\r\n`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentList.html\",`<div class=\"salaxy-component salaxy-worker-list\">\r\n  <salaxy-odata-table logic=\"{showToolbar: $ctrl.showToolbar}\" url=\"/v03/api/employments?activeDate=today\"\r\n    options=\"{$top: $ctrl.limitTo}\"\r\n    ng-if=\"($ctrl.mode || 'default') == 'default'\"\r\n    read-only=\"$ctrl.readOnly\" crud-controller=\"EmploymentCrudController as $crud\"\r\n    template-url=\"salaxy-components/odata/lists/Employments.html\"></salaxy-odata-table>\r\n  <salaxy-odata-table select-mode=\"$ctrl.mode\" url=\"/v03/api/employments?activeDate=today\"\r\n    options=\"{$top: $ctrl.limitTo }\"\r\n    ng-if=\"$ctrl.mode == 'select' || $ctrl.mode == 'multiselect'\"\r\n     template-url=\"salaxy-components/odata/lists/Employments-select.html\"\r\n    items=\"$ctrl.items\" selected-items=\"$ctrl.selectedItems\"\r\n    on-list-select=\"$ctrl.onListSelect({ value: value, item: item, allItems: allItems });\"\r\n    crud-controller=\"EmploymentCrudController as $crud\"></salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/identity.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid  }}</span>\r\n    <div class=\"row\">\r\n    <div class=\"col-xs-12 col-sm-6 margin-top-sm margin-xs\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.details\"></legend>\r\n        <salaxy-input name=\"officialPersonId\" label=\"SALAXY.NG1.WorkerDetailsComponent.ssNumber\" sxy-personal-id-fi ng-required=\"true\" ng-model=\"$ctrl.current.identity.personalId\">\r\n        </salaxy-input>\r\n        <salaxy-input name=\"firstName\" label=\"SALAXY.NG1.WorkerDetailsComponent.firstName\" ng-required=\"true\" ng-model=\"$ctrl.current.identity.firstName\"></salaxy-input>\r\n        <salaxy-input name=\"lastName\" label=\"SALAXY.NG1.WorkerDetailsComponent.lastName\" ng-required=\"true\" ng-model=\"$ctrl.current.identity.lastName\"></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-6 margin-top-sm margin-xs\">\r\n      <fieldset ng-if=\"$ctrl.otherEmployments.length > 0\">\r\n        <legend>Henkilötunnuksella on jo {{ $ctrl.otherEmployments.length }} työsuhdetta</legend>\r\n        <div class=\"list-group\">\r\n          <a ng-href=\"#/employments/details/{{ item.id }}\" ng-click=\"$close()\" class=\"list-group-item\" ng-repeat=\"item in $ctrl.otherEmployments\">\r\n            <strong>{{ $ctrl.getEmploymentDescription(item) }}</strong><br>\r\n            {{ $ctrl.getActiveText(item) }}\r\n          </a>\r\n        </div>\r\n      </fieldset>\r\n      <fieldset salaxy-if-role=\"test\">\r\n        <legend>Vain TESTI</legend>\r\n        <p>\r\n          <strong>Vain testiympäristö:</strong> Täytä loput tiedot nimen perusteella (syötä ensin etu- ja sukunimi).\r\n        </p>\r\n        <div class=\"text-right\">\r\n          <button ng-disabled=\"!$ctrl.current.identity.firstName || !$ctrl.current.identity.lastName\" ng-click=\"$ctrl.populateWithTestData(true)\" class=\"btn btn-danger\">\r\n            Täytä tiedot</button>\r\n          <button ng-disabled=\"!$ctrl.current.identity.firstName || !$ctrl.current.identity.lastName\" ng-click=\"$ctrl.populateWithTestData(false)\" class=\"btn btn-default\">...keinohetu</button>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/index.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\" sxy-text=\"SALAXY.NG1.WorkerWizardComponent.wizard.title\"></h2>\r\n</div>\r\n<div class=\"modal-body salaxy-wizard\">\r\n  <div class=\"visible-xs visible-sm\">\r\n    <h4><span sxy-text=\"SALAXY.NG1.WorkerWizardComponent.wizard.step\"></span> {{$ctrl.currentStep.number}}/{{$ctrl.steps.length}}</h4>\r\n  </div>\r\n  <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n      <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n        <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n      </span>\r\n      <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n        <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n      </a>\r\n    </div>\r\n  </div>\r\n  <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n      <span>{{ step.title | sxyTranslate}}</span>\r\n    </div>\r\n  </div>\r\n  <div class=\"worker-wizard-content\">\r\n    <ng-include src=\"$ctrl.currentStep.view\"></ng-include>\r\n  </div>\r\n</div>\r\n<div class=\"modal-footer\">\r\n  <button ng-if=\"$ctrl.step &lt; 2\" ng-click=\"$close('cancel')\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n  <button ng-if=\"$ctrl.step >= 2\" ng-click=\"$ctrl.goPrevious()\" ng-disabled=\"!$ctrl.canGoPrevious\" class=\"btn pull-left btn-default\" sxy-text=\"SALAXY.UI_Terms.previous\"></button>\r\n  <button ng-if=\"$ctrl.step &lt; $ctrl.steps.length\" ng-click=\"$ctrl.goNext()\" ng-disabled=\"!$ctrl.canGoNext\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.next\"></button>\r\n  <button ng-if=\"$ctrl.step == $ctrl.steps.length\" ng-click=\"$ctrl.saveAndClose($close)\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.formDataValidity\" sxy-text=\"SALAXY.UI_Terms.done\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/person.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid  }}</span>\r\n    <div class=\"row\">\r\n    <div class=\"col-xs-12 col-sm-6 margin-top-sm margin-xs\">\r\n      <fieldset>\r\n        <legend>Yhteystiedot</legend>\r\n        <salaxy-input name=\"email\" label=\"SALAXY.NG1.WorkerDetailsComponent.email\" sxy-email ng-model=\"$ctrl.getContact().email\"></salaxy-input>\r\n        <salaxy-input name=\"telephone\" label=\"SALAXY.NG1.WorkerDetailsComponent.tel\" sxy-mobile-phone ng-model=\"$ctrl.getContact().telephone\"></salaxy-input>\r\n      </fieldset>\r\n      <fieldset ng-if=\"$ctrl.isOtherIdentifier\">\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.address\"></legend>\r\n        <p class=\"small\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.unRealPersonalIndenficationNumer\"></p>\r\n        <salaxy-input name=\"street\" label=\"SALAXY.NG1.WorkerDetailsComponent.street\" ng-required=\"true\" ng-model=\"$ctrl.getContact().street\">\r\n        </salaxy-input>\r\n        <salaxy-input name=\"postalCode\" label=\"SALAXY.NG1.WorkerDetailsComponent.postalCode\" ng-required=\"true\" ng-model=\"$ctrl.getContact().postalCode\">\r\n        </salaxy-input>\r\n        <salaxy-input name=\"city\" label=\"SALAXY.NG1.WorkerDetailsComponent.city\" ng-required=\"true\" ng-model=\"$ctrl.getContact().city\">\r\n        </salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-xs-12 col-sm-6 margin-top-sm margin-xs\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.paymentDetails\"></legend>\r\n        <salaxy-input-enum label=\"SALAXY.NG1.WorkerDetailsComponent.salaryPaymentMethod\" name=\"employmentRelationSalaryPaymentMethod\" ng-model=\"$ctrl.current.info.salaryPaymentMethod\" enum=\"EmploymentRelationSalaryPaymentMethod\" required placeholder=\"SALAXY.UI_Terms.selectAlt\"></salaxy-input-enum>\r\n        <salaxy-input ng-if=\"$ctrl.current.info.salaryPaymentMethod === 'bankAccount'\" name=\"ibanNumber\" label=\"SALAXY.NG1.WorkerDetailsComponent.ibanNumber\" sxy-iban ng-required=\"true\" ng-model=\"$ctrl.current.info.ibanNumber\"></salaxy-input>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/tax.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-6\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.employmentTaxcard\"></legend>\r\n        <salaxy-input-enum label=\"\" name=\"employmentTaxcard\" ng-model=\"$ctrl.current.info.taxcard\" enum=\"EmploymentRelationTaxcard\"\r\n          label-cols=\"col-sm-5\" label-type=\"plain\" type=\"radio\"></salaxy-input-enum>\r\n      </fieldset>\r\n    </div>\r\n    <div ng-switch=\"$ctrl.current.info.taxcard\" class=\"col-xs-6\">\r\n      <fieldset ng-switch-when=\"taxAtSource\">\r\n        <legend>{{'SALAXY.NG1.EmploymentDetails.taxAtSource.title' | sxyTranslate}}</legend>\r\n        <div class=\"alert alert-danger\" ng-if=\"!$ctrl.socSec.isInternational\" sxy-html=\"SALAXY.NG1.EmploymentDetails.taxAtSource.info.html\"></div>\r\n        <salaxy-input-number name=\"percent\" unit=\"percent\" minimum=\"0\" maximum=\"100\" label=\"SALAXY.NG1.EmploymentDetails.percent\" label-cols=\"col-sm-8\"\r\n          ng-model=\"$ctrl.current.international.taxAtSource.percent\" require=\"true\"></salaxy-input-number>\r\n        <salaxy-input-number name=\"deductionMonthly\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentDetails.monthlyDeduction\" label-cols=\"col-sm-8\"\r\n          ng-model=\"$ctrl.current.international.taxAtSource.deductionMonthly\"></salaxy-input-number>\r\n        <salaxy-input-number name=\"deductionDaily\" unit=\"eur\" label=\"SALAXY.NG1.EmploymentDetails.deductionDaily\" label-cols=\"col-sm-8\"\r\n          ng-model=\"$ctrl.current.international.taxAtSource.deductionDaily\"></salaxy-input-number>\r\n      </fieldset>\r\n      <fieldset ng-switch-when=\"noTaxCard\">\r\n        <legend>Ei verokorttia (60%)</legend>\r\n        <p class=\"lead\">Ennakonpidätys tehdään 60%:n mukaan.</p>\r\n      </fieldset>\r\n      <fieldset ng-switch-when=\"auto\">\r\n        <legend sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCards.taxCardDetails.automaticTaxcard.legend\"></legend>\r\n        <!--\r\n        TODO: Consider implementing this\r\n        <button class=\"btn btn-default pull-right\" ng-click=\"$ctrl.getTaxCard()\">Hae verokortti</button>\r\n        -->\r\n        <p sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCards.taxCardDetails.automaticTaxcard.mainTaxPercentApi\"></p>\r\n        <span sxy-html=\"SALAXY.NG1.CurrentTaxCardComponent.taxCards.taxCardDetails.automaticTaxcard.taxPercentInfoText.html\"></span>\r\n      </fieldset>\r\n      <div ng-switch-default>\r\n        <span class=\"hidden\">{{ $ctrl.formDataValidity = $edit.isFormValid  }}</span>\r\n        <salaxy-taxcard-manual-edit ng-ref=\"$edit\" current=\"$ctrl.taxcard\"></salaxy-taxcard-manual-edit>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/type.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid }}</span>\r\n  <ng-include src=\"'salaxy-components/worker/employment/shared-EmploymentRelation.html'\"></ng-include>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/EmploymentWizard/work.html\",`<form name=\"currentForm\" class=\"form-horizontal\">\r\n  <span class=\"hidden\">{{ $ctrl.formDataValidity = currentForm.$valid  }}</span>\r\n  <div class=\"row\">\r\n    <div class=\"col-xs-12 margin-top-sm margin-xs\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerWizardComponent.employment.work.salaryDefaults.title\"></legend>\r\n        <div sxy-html=\"SALAXY.NG1.WorkerWizardComponent.employment.work.salaryDefaults.info.md\"></div>\r\n        <div class=\"table-responsive\">\r\n          <salaxy-calc-rows-2019-editor rows=\"$ctrl.current.work.salaryDefaults\" title=\"{{ 'SALAXY.NG1.WorkerDetailsComponent.defaultCalcRows' | sxyTranslate }}\" condensed=\"true\" mode=\"edit\"></salaxy-calc-rows-2019-editor>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayParametersForm.html\",`<form class=\"form-horizontal\" name=\"holidayForm\">\r\n  <div class=\"row form-horizontal\">\r\n    <div class=\"col-sm-4\">\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.legendSelectHolidayType\"></legend>\r\n        <div class=\"radio\">\r\n          <label>\r\n            <input type=\"radio\" ng-model=\"$ctrl.current.spec.code\" name=\"code\" id=\"permanent14Days\" value=\"permanent14Days\">\r\n            <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.permanent14Days.html\"></span>\r\n          </label>\r\n        </div>\r\n        <div class=\"radio\">\r\n          <label>\r\n            <input type=\"radio\" ng-model=\"$ctrl.current.spec.code\" name=\"code\" id=\"permanent35Hours\" value=\"permanent35Hours\">\r\n            <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.permanent35Hours.html\"></span>\r\n          </label>\r\n        </div>\r\n        <div class=\"radio\">\r\n          <label>\r\n            <input type=\"radio\" ng-model=\"$ctrl.current.spec.code\" name=\"code\" id=\"holidayCompensation\" value=\"holidayCompensation\">\r\n            <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.holidayCompensation.html\"></span>\r\n          </label>\r\n        </div>\r\n        <div class=\"radio\">\r\n          <label>\r\n            <input type=\"radio\" ng-model=\"$ctrl.current.spec.code\" name=\"code\" id=\"temporaryTimeOff\" value=\"temporaryTimeOff\">\r\n            <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.temporaryTimeOff.html\"></span>\r\n          </label>\r\n        </div>\r\n        <div class=\"radio\">\r\n          <label>\r\n            <input type=\"radio\" ng-model=\"$ctrl.current.spec.code\" name=\"code\" id=\"noHolidays\" value=\"noHolidays\">\r\n            <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.noHolidays.html\"></span>\r\n          </label>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-sm-8\">\r\n      <fieldset >\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.legendDetails\"></legend>\r\n        <div ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'accrualFixed')\" ng-init=\"$holidayLogic = $ctrl.getHolidayLogic($ctrl.current.spec)\">\r\n          <salaxy-input-boolean type=\"checkbox\" name=\"accrualByLaw\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualByLaw\" label-true=\"{{ 'SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualByLawLabelTrue' + ($ctrl.current.spec.code == 'temporaryTimeOff' ? '2' : '') }}\"\r\n            ng-change=\"$holidayLogic.accrualByLawChanged($ctrl.current.spec)\" ng-model=\"$holidayLogic.accrualByLaw\"></salaxy-input-boolean>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.spec.accrualFixed\" name=\"accrualFixed\" ng-if=\"$ctrl.current.spec.accrualFixed\" ng-change=\"$holidayLogic.accrualFixedChanged($ctrl.current.spec)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualFixed\" unit=\"days\">\r\n          </salaxy-input-number>\r\n        </div>\r\n        <salaxy-input-number ng-model=\"$ctrl.current.spec.compensation\" name=\"compensation\" ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'compensation')\" required label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.compensation\" unit=\"percent\"></salaxy-input-number>\r\n        <salaxy-input-enum name=\"bonusMethod\" ng-model=\"$ctrl.current.spec.bonusMethod\" ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'bonusMethod')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethod\" filter=\"none,payForHolidaySalary,paySelectedDays\" enum=\"HolidayBonusPaymentMethod\"></salaxy-input-enum>\r\n        <salaxy-input-enum name=\"bonusMethod\" ng-model=\"$ctrl.current.spec.bonusMethod\" ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'compensation')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethod\" options=\"{ 'none': ('SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethodNone' | sxyTranslate), 'payForHolidaySalary': ('SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethodPayForHolidaySalary' | sxyTranslate)  }\">\r\n        </salaxy-input-enum>\r\n        <salaxy-input-number ng-model=\"$ctrl.current.spec.bonus\" name=\"bonus\" ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'bonusPercent')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusPercent\" unit=\"percent\"></salaxy-input-number>\r\n        <div ng-if=\"$ctrl.getHolidayLogic($ctrl.current.spec).getVisibility($ctrl.current.spec, 'accrualFixed')\">\r\n          <salaxy-input-enum  required name=\"wageBasis\" ng-model=\"$ctrl.current.spec.wageBasis\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.wageBasis\" enum=\"WageBasis\" hidden-options=\"undefined,other\"></salaxy-input-enum>\r\n          <salaxy-input-enum name=\"holidayPayCalculation\" ng-model=\"$ctrl.current.spec.holidayPayCalculation\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayCalculation.title\" options=\"$ctrl.getHolidayLogic($ctrl.current.spec).getholidayPayCalculationOptions($ctrl.current.spec)\" required disable-cache=\"true\"></salaxy-input-enum>\r\n          <salaxy-form-group name=\"holidayPayReport\" ng-if=\"$ctrl.current.spec.holidayPayCalculation && $ctrl.current.spec.holidayPayCalculation != 'undefined' && $ctrl.current.spec.holidayPayCalculation != 'otherPay'\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.holidayPayCalculationReport\">\r\n            <a ng-href=\"#/reports/holiday-pay-report-query/{{$ctrl.current.year}}/{{$ctrl.current.employmentId}}\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.calculationReport\"></a>\r\n          </salaxy-form-group>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.otherPay\" ng-if=\"$ctrl.current.spec.holidayPayCalculation == 'otherPay'\" name=\"otherPay\"  label=\"SALAXY.MODEL.HolidayPay.otherPay.title\" ></salaxy-input-number>\r\n  \r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.normalMonthlyPayDailySalary\" name=\"normalMonthlyPayDailySalary\" ng-if=\"($ctrl.current.spec.code == 'permanent14Days' || $ctrl.current.spec.code == 'permanent35Hours') && $ctrl.current.spec.wageBasis =='monthly' && $ctrl.current.spec.holidayPayCalculation == 'normalMonthlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPayDailySalary.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.normalMonthlyPayManual\" name=\"normalMonthlyPayManual\" ng-if=\"($ctrl.current.spec.code == 'permanent14Days' || $ctrl.current.spec.code == 'permanent35Hours') && $ctrl.current.spec.wageBasis =='monthly' && $ctrl.current.spec.holidayPayCalculation == 'normalMonthlyPay'\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPayManual.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.normalMonthlyPay\" name=\"normalMonthlyPay\" ng-if=\"($ctrl.current.spec.code == 'permanent14Days' || $ctrl.current.spec.code == 'permanent35Hours') && $ctrl.current.spec.wageBasis =='monthly' && $ctrl.current.spec.holidayPayCalculation == 'normalMonthlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.normalMonthlyPay.title\" ></salaxy-input-number>\r\n\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPayDailySalary\" name=\"averageDailyPayDailySalary\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayDailySalary.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPayManual\" name=\"averageDailyPayManual\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayManual.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPay\" name=\"averageDailyPay\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPay.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPayBase\" name=\"averageDailyPayBase\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayBase.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPayDays\" name=\"averageDailyPayDays\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayDays.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageDailyPayMultiplier\" name=\"averageDailyPayMultiplier\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageDailyPayMultiplier.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.accrual\" name=\"averageDailyPayAccrual\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageDailyPay'\"disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.accrual.title\" ></salaxy-input-number>\r\n\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPayDailySalary\" name=\"averageHourlyPayDailySalary\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayDailySalary.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPayManual\" name=\"averageHourlyPayManual\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayManual.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPay\" name=\"averageHourlyPay\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPay.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPayBase\" name=\"averageHourlyPayBase\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\"  label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayBase.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPayHours\" name=\"averageHourlyPayHours\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayHours.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.averageHourlyPayMultiplier\" name=\"averageHourlyPayMultiplier\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.averageHourlyPayMultiplier.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.accrual\" name=\"averageHourlyPayAccrual\" ng-if=\"$ctrl.current.spec.code == 'permanent14Days' && ($ctrl.current.spec.wageBasis =='hourly' || $ctrl.current.spec.wageBasis =='performanceBased' || $ctrl.current.spec.wageBasis =='other') && $ctrl.current.spec.holidayPayCalculation == 'averageHourlyPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.accrual.title\"></salaxy-input-number>\r\n\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.percentageBasedPayDailySalary\" name=\"percentageBasedPayDailySalary\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayDailySalary.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.percentageBasedPayManual\" name=\"percentageBasedPayManual\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayManual.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.percentageBasedPay\" name=\"percentageBasedPay\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPay.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.percentageBasedPayBase\" name=\"percentageBasedPayBase\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\"  disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.percentageBasedPayBase.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.spec.holidayPayPercent\" name=\"holidayPayPercent\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\" required unit=\"percent\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayPercent.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.accrual\" name=\"percentageBasedPayAccrual\" ng-if=\"$ctrl.current.spec.code == 'permanent35Hours' && $ctrl.current.spec.holidayPayCalculation == 'percentageBasedPay'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.accrual.title\"></salaxy-input-number>\r\n\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.compensationPayDailySalary\" name=\"compensationPayDailySalary\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPayDailySalary.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.compensationPayManual\" name=\"compensationPayManual\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" label=\"SALAXY.MODEL.HolidayPay.compensationPayManual.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.compensationPay\" name=\"compensationPay\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPay.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.compensationPayBase\" name=\"compensationPayBase\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.compensationPayBase.title\" ></salaxy-input-number>          \r\n          <salaxy-input-number ng-model=\"$ctrl.current.spec.compensation\" name=\"compensation\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" unit=\"percent\" required label=\"SALAXY.MODEL.HolidaySpecificationForYear.compensation.title\" ></salaxy-input-number>\r\n          <salaxy-input-number ng-model=\"$ctrl.current.holidayPay.accrual\" name=\"compensationPayAccrual\" ng-if=\"$ctrl.current.spec.code == 'temporaryTimeOff' && $ctrl.current.spec.holidayPayCalculation == 'holidayCompensation'\" disabled=\"true\" label=\"SALAXY.MODEL.HolidayPay.accrual.title\"></salaxy-input-number>          \r\n\r\n\r\n          <salaxy-form-group label=\"SALAXY.MODEL.HolidaySpecificationForYear.employmentPeriod.title\" name=\"contract\">\r\n            <salaxy-datepicker-popup required name=\"startDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.startDate\" ng-model=\"$ctrl.current.spec.employmentPeriod.start\"></salaxy-datepicker-popup>\r\n            <salaxy-datepicker-popup name=\"endDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.endDate\" ng-model=\"$ctrl.current.spec.employmentPeriod.end\"></salaxy-datepicker-popup>\r\n          </salaxy-form-group>\r\n        </div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-12\">\r\n      <button class=\"btn btn-primary pull-right\" ng-disabled=\"holidayForm.$invalid\" ng-click=\"$ctrl.saveYear($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    </div>\r\n</form>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayYearAccrual.html\",`<salaxy-chart config=\"$ctrl.getChartConfig($ctrl.list)\"></salaxy-chart>\r\n<table class=\"table table-striped table-condensed\">\r\n  <thead>\r\n    <tr>\r\n      <th sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableHead.month\"></th>\r\n      <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableHead.daysCount\"></th>\r\n    </tr>\r\n  </thead>\r\n  <tbody>\r\n    <tr>\r\n      <td>\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: $ctrl.getRowColor('start'), initials: 'saldo', entityType: 'company' }\"></salaxy-avatar>\r\n        <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.startSaldo\"></strong>\r\n        <br />\r\n        <small>\r\n          <div class=\"truncate\" style=\"max-width: 300px;\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.startSaldoMore\"></div>\r\n        </small>\r\n      </td>\r\n      <td class=\"right\" style=\"width: 100px\">\r\n        <salaxy-input-number name=\"startSaldo\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.startSaldo\" label-type=\"plain\" unit=\"days\" ng-model=\"$ctrl.parent.accrual.startSaldo\"></salaxy-input-number>\r\n      </td>\r\n    </tr>\r\n    <tr ng-repeat=\"row in $ctrl.list\">\r\n      <td>\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: $ctrl.getRowColor(row), initials: (row.month | date : 'MM'), entityType: 'company' }\"></salaxy-avatar>\r\n        <strong>{{ \"SALAXY.ENUM.CalendarMonth.month\" + (row.month | date : 'M') + \".label\" | sxyTranslate }}</strong>\r\n        <br />\r\n        <small>\r\n          <div class=\"truncate\" style=\"max-width: 300px;\">{{ $ctrl.getAccrualNotes(row) }}</div>\r\n        </small>\r\n      </td>\r\n      <td class=\"right\" style=\"width: 100px\">\r\n        <salaxy-input-number name=\"{{ 'daysAccrued' + $index }}\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.daysAccruedLabel\" label-type=\"plain\" unit=\"days\" ng-model=\"row.daysAccrued\" ng-change=\"row.daysAccrued == null ? row.source='initial': row.source = 'manual'\"></salaxy-input-number>\r\n      </td>\r\n    </tr>\r\n    <tr class=\"total\">\r\n      <td>\r\n        <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: $ctrl.getRowColor('total'), initials: 'Yht.', entityType: 'company' }\"></salaxy-avatar>\r\n        <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.daysAccrued\"></strong><br />\r\n        <strong ng-if=\"$ctrl.getAccrualCalculations().totalToday != $ctrl.getAccrualCalculations().accrualToday\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.total\"></strong>\r\n        <div ng-if=\"$ctrl.getAccrualCalculations().total != $ctrl.getAccrualCalculations().totalToday\" class=\"truncate\" style=\"max-width: 300px;\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearAccrual.tableBody.estimatedHolidaysNexYear\"></div>\r\n      </td>\r\n      <td class=\"right\" style=\"width: 100px\">\r\n        <strong>{{ $ctrl.getAccrualCalculations().accrualToday | sxyCount : 'day' }}</strong><br />\r\n        <strong ng-if=\"$ctrl.getAccrualCalculations().totalToday != $ctrl.getAccrualCalculations().accrualToday\">{{ $ctrl.getAccrualCalculations().totalToday | sxyCount : 'day' }}</strong>\r\n        <div ng-if=\"$ctrl.getAccrualCalculations().total != $ctrl.getAccrualCalculations().totalToday\">{{ $ctrl.getAccrualCalculations().total | sxyCount : 'day' }}</div>\r\n      </td>\r\n    </tr>\r\n  </tbody>\r\n</table>\r\n<div class=\"text-right\">\r\n  <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.saveParent()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayYearHolidays.html\",`<div class=\"salaxy-component salaxy-holiday-year-holidays\">\r\n  <table class=\"table table-striped {{ $ctrl.condensed ? 'table-condensed' : ''}}\">\r\n    <thead>\r\n      <tr>\r\n        <th sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.period\"></th>\r\n        <th class=\"right\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableHead.daysCount\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-if=\"!$ctrl.condensed\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'saldo', entityType: 'company' }\"></salaxy-avatar>\r\n          <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.availableHolidays\"></strong>\r\n          <br />\r\n          <small>\r\n            <div  sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.availableHolidaysMore\"></div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ $ctrl.getTotalDays(\"holidaysSaldoStart\") | sxyCount : \"day\" }}</strong>\r\n        </td>\r\n      </tr>\r\n      <tr ng-repeat=\"row in $ctrl.list | filter : $ctrl.filter\" ng-click=\"$ctrl.showEditDialog(row)\" class=\"clickable\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: (row.period.daysCount + 'pv'), entityType: 'company' }\"></salaxy-avatar>\r\n          <strong>{{ row.period | sxyDateRange }}</strong>\r\n          <br />\r\n          <small>\r\n            <div>{{ $ctrl.getDescription(row) }}</div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ row.period.daysCount | sxyCount : \"day\"  }}</strong>\r\n        </td>\r\n      </tr>\r\n      <tr class=\"total\" ng-if=\"$ctrl.condensed\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n          <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.total\"></strong>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ $ctrl.getTotalDays(\"filtered\") | sxyCount : \"day\" }}</strong>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"$ctrl.list.length == 0 && !$ctrl.condensed\">\r\n        <td colspan=\"2\" style=\"padding-left: 48px\">\r\n          <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.noHolidaysTitle\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.noHolidaysDescription\"></p>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.noHolidaysDescription2\"></p>\r\n          <button type=\"button\" class=\"btn btn-primary btn-block\" ng-click=\"$ctrl.showEditDialog('new')\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.addFirstHolidayButtonText\"></button>\r\n        </td>\r\n      </tr>\r\n      <tr class=\"total\" ng-if=\"!$ctrl.condensed\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'sum', entityType: 'company' }\"></salaxy-avatar>\r\n          <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.total2\"></strong>\r\n          <br />\r\n          <small>\r\n            <div sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.total2More\"></div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ $ctrl.getTotalDays(\"all\") | sxyCount : \"day\" }}</strong>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"!$ctrl.condensed\">\r\n        <td>\r\n          <salaxy-avatar class=\"salaxy-calc-row-type-avatar pull-left\" avatar=\"{ color: '#2b507c', initials: 'saldo', entityType: 'company' }\"></salaxy-avatar>\r\n          <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.unusedHolidays\"></strong>\r\n          <br />\r\n          <small>\r\n            <div sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.tableBody.unusedHolidaysMore\"></div>\r\n          </small>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ $ctrl.getTotalDays(\"holidaysSaldoEnd\") | sxyCount : \"day\" }}</strong>\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <div class=\"text-right\">\r\n    <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.showEditDialog('new')\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidays.addHolidayButtonText\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayYearHolidaysEditDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.panelHeading\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <form class=\"form-horizontal\">\r\n      <salaxy-datepicker-popup name=\"start\" min-date=\"$ctrl.logic.minDate\" max-date=\"$ctrl.logic.maxDate\" ng-model=\"$ctrl.current.period.start\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelStartDate\"></salaxy-datepicker-popup>\r\n      <salaxy-datepicker-popup name=\"end\" min-date=\"$ctrl.logic.minDate\" max-date=\"$ctrl.logic.maxDate\" ng-model=\"$ctrl.current.period.end\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelEndDate\"></salaxy-datepicker-popup>\r\n      <salaxy-form-group name=\"daysCount\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelHolidaysCount\" ng-if=\"!$ctrl.current.period.days || $ctrl.current.period.days.length == 0\">\r\n        <div class=\"input-group\">\r\n          <input class=\"form-control\" type=\"text\" autocomplete=\"off\" id=\"daysCount\" name=\"daysCount\" ng-model=\"$ctrl.current.period.daysCount\" disabled>\r\n          <span class=\"input-group-btn\">\r\n            <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.logic.setDaysSelection($ctrl.current)\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.editDatesButtonText\"></button>\r\n          </span>\r\n        </div>\r\n      </salaxy-form-group>\r\n      <salaxy-date-range ng-model=\"$ctrl.current.period\" name=\"days\" mode=\"multiple\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelHolidaysCount\" min-date=\"$ctrl.current.period.start\" max-date=\"$ctrl.current.period.end\" ng-if=\"$ctrl.current.period.days.length > 0\"></salaxy-date-range>\r\n      <salaxy-input name=\"notes\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearHolidaysEditDialog.labelDescription\" ng-model=\"$ctrl.current.notes\"></salaxy-input>\r\n      <div>\r\n        <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n        <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n        <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayYearPaid.html\",`<div class=\"salaxy-component salaxy-holiday-year-paid\">\r\n  <div ng-if=\"!$ctrl.list\">\r\n    <salaxy-spinner></salaxy-spinner>\r\n  </div>\r\n  <div ng-if=\"$ctrl.list\">\r\n    <table class=\"table table-condensed\">\r\n      <thead>\r\n        <tr>\r\n          <th colspan=\"2\">\r\n            &nbsp; <br />\r\n            <span class=\"uppercase\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.paidHolidays\"></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.holidaysCount\"></span>\r\n            <br />\r\n            <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.holidaySalary\"></span>\r\n          </th>\r\n          <th class=\"right\">\r\n            <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.compensation\"></span>\r\n            <br />\r\n            <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.bonus\"></span>\r\n          </th>\r\n        </tr>\r\n      </thead>\r\n      <tbody>\r\n\r\n        <tr ng-repeat=\"row in $ctrl.list\" class=\"clickable\" ng-click=\"$ctrl.showEditDialog(row)\" ng-style=\"row.isDisabled ? {opacity: 0.5, 'text-decoration': 'line-through'}: ''\">\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"row.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ row.avatar.displayName }}</strong>\r\n            <span ng-if=\"row.kind =='manualSalary' || row.kind =='manualCompensation' || row.kind =='manualBonus'\" class=\"badge bg-primary\" sxy-text=\"Manual\"></span>\r\n            <div>{{ row.avatar.description }}</div>\r\n          </td>\r\n         \r\n          <td class=\"right\">\r\n            <div>{{ (row.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ (row.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ (row.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ (row.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        \r\n        <tr>\r\n          <th colspan=\"4\">\r\n            &nbsp; <br />\r\n            <span class=\"uppercase\"> <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.holidaySalary\"></span>, <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.compensation\"></span></span>\r\n          </th>\r\n        </tr>\r\n        <tr>\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.totals.startSaldo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.totals.startSaldo.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.totals.startSaldo.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.startSaldo.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.startSaldo.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.startSaldo.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.startSaldo.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        <tr class=\"total\">\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.totals.total.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.totals.total.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.totals.total.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.total.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.total.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.total.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.total.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        <tr>\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.totals.endSaldo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.totals.endSaldo.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.totals.endSaldo.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.endSaldo.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.endSaldo.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.totals.endSaldo.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.totals.endSaldo.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        <tr>\r\n          <th colspan=\"4\">\r\n            &nbsp; <br />\r\n            <span class=\"uppercase\"> <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaid.tableHead.bonus\"></span></span>\r\n          </th>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.shoudPayBonus\">\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.bonusTotals.startSaldo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.bonusTotals.startSaldo.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.bonusTotals.startSaldo.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.startSaldo.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.startSaldo.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.startSaldo.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.startSaldo.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        <tr class=\"total\">\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.bonusTotals.total.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.bonusTotals.total.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.bonusTotals.total.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.total.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.total.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.total.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.total.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n        <tr ng-if=\"$ctrl.shoudPayBonus\">\r\n          <td width=\"42px\">\r\n            <salaxy-avatar class=\"salaxy-calc-row-type-avatar\" avatar=\"$ctrl.bonusTotals.endSaldo.avatar\"></salaxy-avatar>\r\n          </td>\r\n          <td>\r\n            <strong>{{ $ctrl.bonusTotals.endSaldo.avatar.displayName }}</strong>\r\n            <div>{{ $ctrl.bonusTotals.endSaldo.avatar.description }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.endSaldo.holidayDays | sxyCount : 'day') || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.endSaldo.holidaySalary | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n          <td class=\"right\">\r\n            <div>{{ ($ctrl.bonusTotals.endSaldo.holidayCompensation | currency) || \"&nbsp;\" }}</div>\r\n            <div>{{ ($ctrl.bonusTotals.endSaldo.holidayBonus | currency) || \"&nbsp;\" }}</div>\r\n          </td>\r\n        </tr>\r\n      </tbody>\r\n    </table>\r\n    <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.showEditDialog('new', true)\" sxy-text=\"SALAXY.UI_Terms.add\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/HolidayYearPaidEditDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.panelHeading\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <form class=\"form-horizontal\">      \r\n      <div ng-switch=\"$ctrl.current.kind\">\r\n        <div ng-switch-when=\"manualSalary\">\r\n          <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.title\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.description\"></p>\r\n        </div>\r\n        <div ng-switch-when=\"manualCompensation\">\r\n          <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualCompensation.title\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualCompensation.description\"></p>\r\n        </div>\r\n        <div ng-switch-when=\"manualBonus\">\r\n          <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualBonus.title\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualBonus.description\"></p>\r\n        </div>\r\n        <div ng-switch-when=\"paidCalc\">\r\n          <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.paidCalc.title\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.paidCalc.description\"></p>\r\n        </div>\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.kind == 'undefined'\">\r\n        <p class=\"lead\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.undefined.labelAnnualLeavePaymentKind\"></p>\r\n        <salaxy-input-enum ng-model=\"$ctrl.current.kind\" name=\"typeRadio\" enum=\"AnnualLeavePaymentKind\" type=\"radio\" filter=\"manualSalary,manualCompensation,manualBonus\" label-type=\"plain\"></salaxy-input-enum>\r\n        <p>&nbsp;</p>\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.kind != 'undefined'\">\r\n        <salaxy-input-enum  disabled=\"true\" ng-if=\"$ctrl.current.kind == 'paidCalc'\" ng-model=\"$ctrl.current.kind\" enum=\"AnnualLeavePaymentKind\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.kind\" filter=\"paidCalc\" name=\"typeSelect\" type=\"select\"></salaxy-input-enum>\r\n        <salaxy-input-enum  ng-if=\"$ctrl.current.kind != 'paidCalc'\" ng-model=\"$ctrl.current.kind\" enum=\"AnnualLeavePaymentKind\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.kind\" filter=\"manualSalary,manualCompensation,manualBonus\" name=\"typeSelect\" type=\"select\"></salaxy-input-enum>\r\n \r\n        <salaxy-datepicker-popup disabled=\"$ctrl.current.kind =='paidCalc'\" name=\"date\" ng-model=\"$ctrl.current.date\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelPaidAt\" ></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup disabled=\"$ctrl.current.kind =='paidCalc'\" name=\"myDatepickerPopup\" ng-model=\"$ctrl.current.period.start\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelStartDate\" >\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup disabled=\"$ctrl.current.kind =='paidCalc'\" name=\"myDatepickerPopup\" ng-model=\"$ctrl.current.period.end\" ng-change=\"$ctrl.logic.updatePeriodDays($ctrl.current)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelEndDate\">\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-input-number disabled=\"true\" name=\"days\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelDaysCount\" ng-model=\"$ctrl.current.period.daysCount\" ></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.kind =='paidCalc'\" name=\"holidayDays\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelUsedHolidays\" ng-model=\"$ctrl.current.holidayDays\" ng-change=\"$ctrl.logic.updateDaysCount($ctrl.current)\"></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.kind =='paidCalc'\" ng-if=\"$ctrl.current.kind =='paidCalc' || $ctrl.current.kind =='manualSalary'\" name=\"holidaySalary\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelHolidaySalary\" ng-model=\"$ctrl.current.holidaySalary\" ></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.kind =='paidCalc'\" ng-if=\"$ctrl.current.kind =='paidCalc' || $ctrl.current.kind =='manualCompensation'\" name=\"holidayCompensation\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualCompensation.labelCompensation\" ng-model=\"$ctrl.current.holidayCompensation\"></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.kind =='paidCalc'\" ng-if=\"$ctrl.current.kind =='paidCalc' || $ctrl.current.kind =='manualBonus'\" name=\"holidayBonus\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelBonus\" ng-model=\"$ctrl.current.holidayBonus\"></salaxy-input-number>\r\n        <salaxy-input-boolean ng-if=\"$ctrl.current.kind =='paidCalc'\" type=\"switch\" name=\"isDisabled\" ng-model=\"$ctrl.current.isDisabled\" label=\"Poista käytöstä\" label-true=\"on\"\r\n          label-false=\"off\"></salaxy-input-boolean>\r\n        <salaxy-form-group name=\"calc\" label=\"SALAXY.ENUM.AnnualLeavePaymentKind.paidCalc.label\" ng-if=\"$ctrl.current.calcId\">\r\n            <a ng-href=\"{{$ctrl.logic.getPdfUrl($ctrl.current.calcId)}}\" target=\"_blank\" title=\"{{ 'SALAXY.UI_Terms.printable' | sxyTranslate}}\" class=\"btn btn-sm btn-secondary\"><i class=\"fa fa-file-pdf-o\"></i></a>\r\n        </salaxy-form-group>\r\n        <salaxy-input disabled=\"$ctrl.current.kind =='paidCalc'\" name=\"notes\" label=\"SALAXY.NG1.WorkerHolidaysComponent.HolidayYearPaidEditDialog.manualSalary.labelDescription\" ng-model=\"$ctrl.current.notes\"></salaxy-input>\r\n      </div>\r\n      <div>\r\n        <button ng-disabled=\"$ctrl.current.kind == 'undefined'\" type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n        <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n        <button ng-disabled=\"$ctrl.current.kind == 'paidCalc' || $ctrl.current.kind == 'undefined'\" type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.UI_Terms.delete\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidays-accrual.html\",`<div class=\"row\">\r\n  <div class=\"col-sm-9\">\r\n    <fieldset ng-if=\"$ctrl.viewType == 'overview'\">\r\n      <legend><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.legend\"></span> {{ $ctrl.current.year }}</legend>\r\n      <table class=\"salaxy-holidays-overview-table\">\r\n        <thead>\r\n          <tr>\r\n            <th class=\"year bg-{{year.style}}\" ng-repeat=\"year in $ctrl.getYearVisualisation().years\" colspan=\"{{ year.months }}\">{{ year.text }}</th>\r\n          </tr>\r\n          <tr>\r\n            <th ng-class=\"{ 'month': true, 'bg-primary': month%2, 'bg-danger': $index == $ctrl.getYearVisualisation().currentMonthIx }\" ng-repeat=\"month in $ctrl.getYearVisualisation().months track by $index\" class=\"text-right\">{{ month }}</th>\r\n          </tr>\r\n        </thead>\r\n        <tr ng-repeat=\"item in $ctrl.getYearVisualisation().items\">\r\n          <td class=\"month-empty\" ng-repeat=\"x in [].constructor(item.start) track by $index\"></td>\r\n          <td colspan=\"{{ item.months }}\">\r\n            <button class=\"btn btn-{{ item.style }} btn-block btn-sm\" ng-click=\"$ctrl.viewType = item.view\">{{ item.text }}</button>\r\n          </td>\r\n          <td class=\"month-empty\" ng-repeat=\"x in [].constructor(25 - item.start - item.months) track by $index\"></td>\r\n        </tr>\r\n      </table>\r\n      <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.introTitle\"></h3>\r\n      <ol class=\"lead\">\r\n        <li sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.introList.html\"></li>\r\n        <li sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.introList2.html\"></li>\r\n        <li ng-if=\"$ctrl.getVisibility('hourly')\" sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.introList3.html\"></li>\r\n        <li sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.overview.introList4.html\"></li>\r\n      </ol>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'parameters'\">\r\n      <ng-include src=\"'salaxy-components/worker/holidays/HolidayParametersForm.html'\"></ng-include>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays-summer'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonSummer\"></button>\r\n        <span class=\"pull-right\">&nbsp;</span>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays-winter'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonWinter\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.calendarTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-holiday-year-holidays on-commit=\"$ctrl.save()\" parent=\"$ctrl.current\"></salaxy-holiday-year-holidays>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays-summer'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonAll\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.summerHolidaysTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-calendar data=\"[$ctrl.current]\" mapper=\"$ctrl.mapToCalendar\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" start=\"$ctrl.current.year + '-05-01'\" end=\"$ctrl.current.year + '-09-01'\"></salaxy-calendar>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays-winter'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonAll\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.winterHolidaysTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-calendar data=\"[$ctrl.current]\" mapper=\"$ctrl.mapToCalendar\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" start=\"$ctrl.current.year + '-10-01'\" end=\"(1 * $ctrl.current.year + 1) + '-04-01'\"></salaxy-calendar>\r\n    </fieldset>\r\n\r\n    <fieldset ng-if=\"$ctrl.viewType == 'paidHolidays'\">\r\n      <legend>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.paidSalaries.legend\"></span> {{ $ctrl.current.period | sxyDateRange }}\r\n      </legend>\r\n      <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.paidSalaries.description\"></p>\r\n\r\n      <ul sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.paidSalaries.descriptionList.html\"></ul>\r\n      <salaxy-holiday-year-paid parent=\"$ctrl.current\" on-commit=\"$ctrl.save()\"></salaxy-holiday-year-paid>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'accrual'\">\r\n      <legend>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.accrualHolidays.legend\"></span> {{ $ctrl.current.accrual.period | sxyDateRange }}\r\n      </legend>\r\n      <p>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.accrualHolidays.description\"></span> {{ $ctrl.current.year - 1 }}.\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.accrualHolidays.description2\"></span> {{ $ctrl.current.year }}.\r\n      </p>\r\n      <salaxy-holiday-year-accrual parent=\"$ctrl.current\"></salaxy-holiday-year-accrual>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'hourlySalaries'\">\r\n      <legend>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.hourlySalaries.legend\"></span> {{ $ctrl.current.period | sxyDateRange }}\r\n      </legend>\r\n      <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.hourlySalaries.description\"></p>\r\n      <ul sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.hourlySalaries.descriptionList.html\"></ul>\r\n      <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.accrual.hourlySalaries.description2\"></p>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-sm-3\">\r\n    <div class=\"btn-group btn-block\" uib-dropdown>\r\n      <button id=\"year-selection\" type=\"button\" class=\"btn btn-primary btn-block\" uib-dropdown-toggle>\r\n        {{ $ctrl.current ? ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectedYear' | sxyTranslate) + \" \" + $ctrl.current.year : ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectYear' | sxyTranslate)  }}\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.model = year\" ng-repeat=\"year in $ctrl.employmentHolidayYears\">{{ year.year }}</a></li>\r\n        <li role=\"menuitem\"><a ng-href=\"#{{ $ctrl.getDefaults().listUrl }}\" ng-if=\"!($ctrl.employmentHolidayYears.length > 0)\" sxy-text=\"SALAXY.UI_Terms.back\"></a></li>\r\n        <li class=\"divider\"></li>\r\n        <li role=\"menuitem\" ng-if=\"$ctrl.missingHolidayYear\">\r\n          <a href=\"\" ng-click=\"$ctrl.showInitHolidays()\">{{\"SALAXY.UI_Terms.add\" | sxyTranslate}} {{\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.legendYear\" | sxyTranslate}} {{$ctrl.missingHolidayYear}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <p>&nbsp;</p>\r\n    <div class=\"btn-group-vertical btn-block\">\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'overview'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonOverview\"></label>\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'parameters'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonSettings\"></label>\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(true)\" uib-btn-radio=\"'accrual'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonAccrual\"></label>\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'holidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonHolidays\"></label>\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'paidHolidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonPaidHolidays\"></label>\r\n    </div>\r\n    <p>&nbsp;</p>\r\n    <fieldset ng-if=\"$ctrl.current\">\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.info\"></legend>\r\n      <div>{{ \"WageBasis.\" + $ctrl.current.spec.wageBasis | sxyEnum }}</div>\r\n      <div>{{ \"HolidayCode.\" + $ctrl.current.spec.code | sxyEnum }}</div>\r\n      <div ng-if=\"$ctrl.getVisibility('accrual')\">\r\n        {{'SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.periodAccrual' | sxyTranslate}}<br />{{ $ctrl.current.accrual.period | sxyDateRange }}</div>\r\n      <div><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.periodSelectedYear\"></span>\r\n        <br />{{ $ctrl.current.period | sxyDateRange }}\r\n      </div>\r\n      <div ng-if=\"$ctrl.getVisibility('accrual')\">\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.periodDefaultAccrual\"></span> {{ $ctrl.current.accrual.defaultAccrual | sxyCount : 'day' }}\r\n      </div>\r\n      <div ng-if=\"$ctrl.getVisibility('compensation')\">\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.compensation\"></span> {{ $ctrl.current.spec.compensation | sxyCount : 'percent' }}\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.spec.bonusMethod != 'none'\">\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.bonus\"></span> {{ $ctrl.current.spec.bonus | sxyCount : 'percent' }}\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.spec.bonusMethod == 'none'\">{{ \"HolidayBonusPaymentMethod.\" + $ctrl.current.spec.bonusMethod | sxyEnum }} </div>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidays-holidayCompensation.html\",`<div class=\"row\">\r\n  <div class=\"col-sm-9\">\r\n    <fieldset ng-if=\"$ctrl.viewType == 'overview'\">\r\n      <legend>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.legend\"></span> (\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.legendYear\"></span> {{$ctrl.current.year}})\r\n      </legend>\r\n      <p class=\"lead\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.intro\"></p>\r\n      <ul class=\"lead\">\r\n        <li>\r\n          <strong sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.intro2\"></strong>\r\n          <ul>\r\n            <li> <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.introCompensation\"></span>{{ $ctrl.current.spec.compensation | sxyCount : 'percent' }}</li>\r\n            <li ng-if=\"$ctrl.current.spec.bonusMethod != 'none'\"><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.introBonus\"></span> {{ $ctrl.current.spec.bonus | sxyCount : 'percent' }}</li>\r\n            <li ng-if=\"$ctrl.current.spec.bonusMethod == 'none'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.introNoBonus\"></li>\r\n          </ul>\r\n        </li>\r\n      </ul>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'parameters'\">\r\n      <ng-include src=\"'salaxy-components/worker/holidays/HolidayParametersForm.html'\"></ng-include>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays-summer'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonSummer\"></button>\r\n        <span class=\"pull-right\">&nbsp;</span>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays-winter'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonWinter\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.calendarTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-holiday-year-holidays on-commit=\"$ctrl.save()\" parent=\"$ctrl.current\"></salaxy-holiday-year-holidays>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays-summer'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonAll\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.summerHolidaysTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-calendar data=\"[$ctrl.current]\" mapper=\"$ctrl.mapToCalendar\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" start=\"$ctrl.current + '-05-01'\" end=\"$ctrl.current + '-09-01'\"></salaxy-calendar>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'holidays-winter'\">\r\n      <legend>\r\n        <button class=\"btn btn-primary btn-sm pull-right\" ng-click=\"$ctrl.viewType = 'holidays'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.buttonAll\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.winterHolidaysTitle\"></span> {{ $ctrl.current.year}}\r\n      </legend>\r\n      <salaxy-calendar data=\"[$ctrl.current]\" mapper=\"$ctrl.mapToCalendar\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" start=\"$ctrl.current + '-10-01'\" end=\"(1 * $ctrl.current + 1) + '-04-01'\"></salaxy-calendar>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-sm-3\">\r\n    <div class=\"btn-group btn-block\" uib-dropdown>\r\n      <button id=\"year-selection\" type=\"button\" class=\"btn btn-primary btn-block\" uib-dropdown-toggle>\r\n          {{ $ctrl.current ? ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectedYear' | sxyTranslate) + \" \" +  $ctrl.current.year : ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectYear' | sxyTranslate) }} <span class=\"caret\"></span>\r\n        </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.model = year\" ng-repeat=\"year in $ctrl.employmentHolidayYears\">{{ year.year }}</a></li>\r\n        <li role=\"menuitem\"><a ng-href=\"#{{ $ctrl.getDefaults().listUrl }}\" ng-if=\"!($ctrl.employmentHolidayYears.length > 0)\" sxy-text=\"SALAXY.UI_Terms.back\"></a></li>\r\n        <li class=\"divider\"></li>\r\n        <li role=\"menuitem\" ng-if=\"$ctrl.missingHolidayYear\">\r\n          <a href=\"\" ng-click=\"$ctrl.showInitHolidays()\">{{\"SALAXY.UI_Terms.add\" | sxyTranslate}} {{\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.legendYear\" | sxyTranslate}} {{$ctrl.missingHolidayYear}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <p>&nbsp;</p>\r\n    <div class=\"btn-group-vertical btn-block\">\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'overview'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonOverview\"></label>\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'parameters'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonSettings\"></label>\r\n    </div>\r\n    <p>&nbsp;</p>\r\n    <fieldset ng-if=\"$ctrl.current\">\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.info\"></legend>\r\n      <div>{{ \"HolidayCode.\" + $ctrl.current.spec.code | sxyEnum }}</div>\r\n      <div><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.periodSelectedYear\"></span><br />{{ $ctrl.current.period | sxyDateRange }}</div>\r\n      <div><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.compensation\"></span> {{ $ctrl.current.spec.compensation | sxyCount : 'percent' }}</div>\r\n      <div ng-if=\"$ctrl.current.spec.bonusMethod != 'none'\">\r\n        <span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.bonus\"></span> {{ $ctrl.current.spec.bonus | sxyCount : 'percent' }}\r\n      </div>\r\n      <div ng-if=\"$ctrl.current.spec.bonusMethod == 'none'\">{{ \"HolidayBonusPaymentMethod.\" + $ctrl.current.spec.bonusMethod | sxyEnum }} </div>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidays-noHolidays.html\",`<div class=\"row\">\r\n  <div class=\"col-sm-9\">\r\n    <fieldset ng-if=\"$ctrl.viewType == 'overview'\">\r\n      <legend><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.noHolidays.legend\"></span>{{ $ctrl.current.year }}</legend>\r\n      <p class=\"lead\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.noHolidays.intro\"></p>\r\n    </fieldset>\r\n    <fieldset ng-if=\"$ctrl.viewType == 'parameters'\">\r\n      <ng-include src=\"'salaxy-components/worker/holidays/HolidayParametersForm.html'\"></ng-include>\r\n    </fieldset>\r\n  </div>\r\n  <div class=\"col-sm-3\">\r\n    <div class=\"btn-group btn-block\" uib-dropdown>\r\n      <button id=\"year-selection\" type=\"button\" class=\"btn btn-primary btn-block\" uib-dropdown-toggle>\r\n        {{ $ctrl.current ? ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectedYear' | sxyTranslate) + \" \" + $ctrl.current.year : ('SALAXY.NG1.WorkerHolidaysComponent.UI.dropdown.selectYear' | sxyTranslate) }} <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n        <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.model = year\" ng-repeat=\"year in $ctrl.employmentHolidayYears\">{{ year.year }}</a></li>\r\n        <li role=\"menuitem\"><a ng-href=\"#{{ $ctrl.getDefaults().listUrl }}\" ng-if=\"!($ctrl.employmentHolidayYears.length > 0)\" sxy-text=\"SALAXY.UI_Terms.back\"></a></li>\r\n        <li class=\"divider\"></li>\r\n        <li role=\"menuitem\" ng-if=\"$ctrl.missingHolidayYear\">\r\n          <a href=\"\" ng-click=\"$ctrl.showInitHolidays()\">{{\"SALAXY.UI_Terms.add\" | sxyTranslate}} {{\"SALAXY.NG1.WorkerHolidaysComponent.holidayCompensation.overview.legendYear\" | sxyTranslate}} {{$ctrl.missingHolidayYear}}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <p>&nbsp;</p>\r\n    <div class=\"btn-group-vertical btn-block\">\r\n      <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" ng-click=\"$ctrl.setAccrualView(false)\" uib-btn-radio=\"'parameters'\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.buttonSettings\"></label>\r\n \r\n    </div>\r\n    <fieldset ng-if=\"$ctrl.current\">\r\n      <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.info\"></legend>\r\n      <div>{{ \"HolidayCode.\" + $ctrl.current.spec.code | sxyEnum }}</div>\r\n      <div><span sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.UI.sidebar.periodSelectedYear\"></span><br />{{ $ctrl.current.period | sxyDateRange }}</div>\r\n    </fieldset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidays-undefined.html\",`<div class=\"salaxy-placeholder-empty placeholder-md\">\r\n  <h3 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.undefined.title\"></h3>\r\n  <button class=\"btn btn-primary\" ng-click=\"$ctrl.showInitHolidays()\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.undefined.showInitHolidaysButtonText\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidays.html\",`<div class=\"salaxy-component salaxy-worker-holidays\">\r\n  <ng-include ng-if=\"!$ctrl.current || !$ctrl.current.spec.code || $ctrl.current.spec.code == 'undefined'\" src=\"'salaxy-components/worker/holidays/WorkerHolidays-undefined.html'\"></ng-include>\r\n  <ng-include ng-if=\"$ctrl.current.spec.code == 'holidayCompensation'\" src=\"'salaxy-components/worker/holidays/WorkerHolidays-holidayCompensation.html'\"></ng-include>\r\n  <ng-include ng-if=\"$ctrl.current.spec.code == 'permanent14Days' || $ctrl.current.spec.code == 'permanent35Hours' || $ctrl.current.spec.code == 'temporaryTimeOff'\" src=\"'salaxy-components/worker/holidays/WorkerHolidays-accrual.html'\"></ng-include>\r\n  <ng-include ng-if=\"$ctrl.current.spec.code == 'noHolidays'\" src=\"'salaxy-components/worker/holidays/WorkerHolidays-noHolidays.html'\"></ng-include>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/holidays/WorkerHolidaysInitDialog.html\",`<div class=\"salaxy-component salaxy-holidays-init-dialog\">\r\n  <form class=\"form-horizontal\" name=\"holidayForm\">\r\n    <div class=\"panel panel-primary\">\r\n      <div class=\"panel-heading\">\r\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\" ng-click=\"$close('cancel')\"><span aria-hidden=\"true\">&times;</span></button>\r\n        <h2 sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.panelHeading\"></h2>\r\n        <p sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.intro\"></p>\r\n      </div>\r\n      <div class=\"panel-body\">\r\n        <div class=\"row form-horizontal\">\r\n          <div class=\"col-sm-6\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.legendSelectHolidayType\"></legend>\r\n              <div class=\"radio\">\r\n                <label>\r\n                  <input type=\"radio\" ng-model=\"$ctrl.current.code\" name=\"code\" id=\"permanent14Days\" value=\"permanent14Days\">\r\n                  <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.permanent14Days.html\"></span>\r\n                </label>\r\n              </div>\r\n              <div class=\"radio\">\r\n                <label>\r\n                  <input type=\"radio\" ng-model=\"$ctrl.current.code\" name=\"code\" id=\"permanent35Hours\" value=\"permanent35Hours\">\r\n                  <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.permanent35Hours.html\"></span>\r\n                </label>\r\n              </div>\r\n              <div class=\"radio\">\r\n                <label>\r\n                  <input type=\"radio\" ng-model=\"$ctrl.current.code\" name=\"code\" id=\"holidayCompensation\" value=\"holidayCompensation\">\r\n                  <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.holidayCompensation.html\"></span>\r\n                </label>\r\n              </div>\r\n              <div class=\"radio\">\r\n                <label>\r\n                  <input type=\"radio\" ng-model=\"$ctrl.current.code\" name=\"code\" id=\"temporaryTimeOff\" value=\"temporaryTimeOff\">\r\n                  <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.temporaryTimeOff.html\"></span>\r\n                </label>\r\n              </div>\r\n              <div class=\"radio\">\r\n                <label>\r\n                  <input type=\"radio\" ng-model=\"$ctrl.current.code\" name=\"code\" id=\"noHolidays\" value=\"noHolidays\">\r\n                  <span sxy-html=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.noHolidays.html\"></span>\r\n                </label>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n          <div class=\"col-sm-6\">\r\n            <fieldset>\r\n              <legend sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.legendDetails\"></legend>\r\n              <div ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'accrualFixed')\">\r\n                <salaxy-input-boolean type=\"checkbox\" name=\"accrualByLaw\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualByLaw\" label-true=\"{{ 'SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualByLawLabelTrue' + ($ctrl.current.code == 'temporaryTimeOff' ? '2' : '') }}\"\r\n                  ng-change=\"$ctrl.logic.accrualByLawChanged($ctrl.current)\" ng-model=\"$ctrl.logic.accrualByLaw\"></salaxy-input-boolean>\r\n                <salaxy-input-number ng-model=\"$ctrl.current.accrualFixed\" name=\"accrualFixed\" ng-if=\"$ctrl.current.accrualFixed\" ng-change=\"$ctrl.logic.accrualFixedChanged($ctrl.current)\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.accrualFixed\" unit=\"days\">\r\n                </salaxy-input-number>\r\n              </div>\r\n              <salaxy-input-number ng-model=\"$ctrl.current.compensation\" name=\"compensation\" ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'compensation')\" required label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.compensation\" unit=\"percent\"></salaxy-input-number>\r\n              <salaxy-input-enum name=\"bonusMethod\" ng-model=\"$ctrl.current.bonusMethod\" ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'bonusMethod')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethod\" filter=\"none,payForHolidaySalary,paySelectedDays\" enum=\"HolidayBonusPaymentMethod\"></salaxy-input-enum>\r\n              <salaxy-input-enum name=\"bonusMethod\" ng-model=\"$ctrl.current.bonusMethod\" ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'compensation')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethod\" options=\"{ 'none': ('SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethodNone' | sxyTranslate), 'payForHolidaySalary': ('SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusMethodPayForHolidaySalary' | sxyTranslate)  }\">\r\n              </salaxy-input-enum>\r\n              <salaxy-input-number ng-model=\"$ctrl.current.bonus\" name=\"bonus\" ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'bonusPercent')\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.bonusPercent\" unit=\"percent\"></salaxy-input-number>\r\n              <div ng-if=\"$ctrl.logic.getVisibility($ctrl.current, 'accrualFixed')\">\r\n                <salaxy-input-enum required name=\"wageBasis\" ng-model=\"$ctrl.current.wageBasis\" label=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.label.wageBasis\" enum=\"WageBasis\" hidden-options=\"undefined,other\"></salaxy-input-enum>\r\n                <salaxy-input-enum name=\"holidayPayCalculation\" ng-model=\"$ctrl.current.holidayPayCalculation\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayCalculation.title\" options=\"$ctrl.logic.getholidayPayCalculationOptions($ctrl.current)\" required disable-cache=\"true\"></salaxy-input-enum>\r\n\r\n                <salaxy-input-number ng-model=\"$ctrl.current.compensation\" name=\"compensation\" ng-if=\"$ctrl.current.code == 'temporaryTimeOff' && $ctrl.current.holidayPayCalculation == 'holidayCompensation'\" unit=\"percent\" required label=\"SALAXY.MODEL.HolidaySpecificationForYear.compensation.title\" ></salaxy-input-number>\r\n                <salaxy-input-number ng-model=\"$ctrl.current.holidayPayPercent\" name=\"holidayPayPercent\" ng-if=\"$ctrl.current.code == 'permanent35Hours' && $ctrl.current.holidayPayCalculation == 'percentageBasedPay'\" required unit=\"percent\" label=\"SALAXY.MODEL.HolidaySpecificationForYear.holidayPayPercent.title\" ></salaxy-input-number>\r\n              \r\n                <salaxy-form-group label=\"SALAXY.MODEL.HolidaySpecificationForYear.employmentPeriod.title\" name=\"contract\">\r\n                  <salaxy-datepicker-popup required name=\"startDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.startDate\" ng-model=\"$ctrl.current.employmentPeriod.start\"></salaxy-datepicker-popup>\r\n                  <salaxy-datepicker-popup name=\"endDate\" label=\"SALAXY.NG1.WorkerWizardComponent.employment.group.endDate\" ng-model=\"$ctrl.current.employmentPeriod.end\"></salaxy-datepicker-popup>\r\n                </salaxy-form-group>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <div class=\"panel-footer\">\r\n        <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-disabled=\"holidayForm.$invalid\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.NG1.WorkerHolidaysComponent.InitDialog.submitButtonText\"></button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.cancel\"></button>\r\n      </div>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/HourlyReportEditDialog.html\",`<div class=\"salaxy-component salaxy-timer-dialog\">\r\n  <div>\r\n    <div class=\"modal-header\">\r\n      <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h2 sxy-text=\"Muokkaa tuntikirjausta\"></h2>\r\n    </div>\r\n    <div class=\"modal-body\">\r\n      <form class=\"form-horizontal\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-enum ng-if=\"$ctrl.logic.costAccountingSettings\" type=\"typeahead\" label-format=\"text-value\" name=\"options_project\" ng-model=\"$ctrl.current.contentData.project\" options=\"$ctrl.logic.costAccountingSettings.options\" label=\"{{($ctrl.logic.costAccountingSettings.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" required=\"true\"></salaxy-input-enum>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input name=\"message\" ng-model=\"$ctrl.current.contentData.projectText\" label=\"Kommentti\"></salaxy-input>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-time name=\"startTime\" label=\"Työaika\" type=\"minutes\" ng-model=\"$ctrl.current.contentData.totalTime\"></salaxy-input-time>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-number label=\"Työaika\" type=\"slider\" name=\"slider\" minimum=\"10\" maximum=\"720\" slider-step=\"5\" ng-model=\"$ctrl.current.contentData.totalTime\"></salaxy-input-number>\r\n          </div>\r\n        </div>\r\n      </form>\r\n    </div>\r\n    <div class=\"modal-footer\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n\r\n      <button type=\"button\" class=\"btn btn-danger pull-left\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.deleteButtonText\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/EmploymentTaxcards.html\",`﻿<div class=\"salaxy-component salaxy-employment-taxcards\">\r\n  <div ng-if=\"!$ctrl.current\">\r\n    <div class=\"alert alert-warning\" ng-if=\"!$ctrl.employmentId\">\r\n      <p sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.instruction\"></p>\r\n    </div>\r\n    <salaxy-spinner ng-if=\"$ctrl.employmentId\"></salaxy-spinner>\r\n  </div>\r\n  <div ng-if=\"$ctrl.current\">\r\n    <div class=\"alert alert-warning\" ng-if=\"!$ctrl.current.personalId\">\r\n      <p sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.error\"></p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.mode != 'list'\">\r\n      <uib-tabset active=\"$ctrl.currentTab\">\r\n        <uib-tab heading=\"{{'SALAXY.NG1.WorkerDetailsComponent.currentTaxCard' | sxyTranslate}}\" index=\"'details'\">\r\n          <salaxy-taxcard-details model=\"$ctrl.current.active\" ng-ref=\"$ctrl.$active\" personal-id=\"$ctrl.current.personalId\" on-save=\"$ctrl.reload();$ctrl.onSave()\" hide-buttons=\"$ctrl.hideButtons\" employment-relation-taxcard-type=\"$ctrl.current.employmentTaxcard\"></salaxy-taxcard-details>\r\n        </uib-tab>\r\n        <uib-tab heading=\"{{'SALAXY.NG1_PagesPersonal.taxcards.calcsPaidForCardTabHeading' |sxyTranslate}}\" index=\"'calcs'\" ng-if=\"$ctrl.current.active\">\r\n          <div class=\"alert alert-info\" ng-if=\"$ctrl.$incomeLog.hasDiff\">\r\n            <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.$active.commitDiff()\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addSalaries\"></button>\r\n            <span sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addSalariesToTaxCard\" params=\"{validity: ($ctrl.current.active.card.validity | sxyDateRange)}\">\r\n            </span>\r\n          </div>\r\n          <salaxy-taxcard-income-log parent=\"$ctrl.current.active\" editable=\"false\" ng-ref=\"$ctrl.$incomeLog\"></salaxy-taxcard-income-log>\r\n          <div class=\"text-right\">\r\n            <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$ctrl.editIncomeLog()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.edit\"></button>\r\n          </div>\r\n        </uib-tab>\r\n      </uib-tabset>\r\n    </div>\r\n    <div class=\"row form-horizontal\" sxy-if-role=\"test\">\r\n      <div class=\"col-xs-8\">\r\n        <salaxy-datepicker-popup name=\"today\" ng-model=\"$ctrl.today\" label=\"Maksupäivän testaus\" ng-change=\"\"></salaxy-datepicker-popup>\r\n      </div>\r\n      <div class=\"col-xs-4\">\r\n        <button type=\"button\" class=\"btn btn-primary\" style=\"margin-top: 7px;\" ng-click=\"$ctrl.reload()\">Vaihda (TEST)</button>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.mode != 'active' && $ctrl.list.length > 0\">\r\n      <h3 ng-if=\"$ctrl.mode != 'list'\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.historyTaxCard\"></h3>\r\n      <div class=\"table-responsive\">\r\n        <table class=\"table table-striped\">\r\n          <thead>\r\n            <tr>\r\n              <th class=\"th-xxs\">\r\n                <span sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.type\"></span>\r\n                <span class=\"visible-xs visible-sm\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.taxPercent\"></span>\r\n                <span class=\"visible-xs visible-sm\" sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.percentAfterIncomeLimit\"></span>\r\n              </th>\r\n              <th class=\"hidden-xs hidden-sm\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.year\"></th>\r\n              <th class=\"hidden-xs hidden-sm tax-percentage right\" sxy-text=\"SALAXY.NG1.WorkerDetailsComponent.taxPercent\"></th>\r\n              <th class=\"th-xxs salaries-paid right\">\r\n                <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></span>\r\n                <span class=\"visible-xs visible-sm\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.incomeLimit\"></span>\r\n              </th>\r\n              <th class=\"hidden-xs hidden-sm income-limit right\">\r\n                <span sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.incomeLimit\"></span><br /><span sxy-text=\"SALAXY.NG1.WorkerTaxCardsComponent.incomeLimitSpan\"></span>\r\n\r\n              </th>\r\n              <th class=\"th-xxs right\" sxy-html=\"SALAXY.NG1.WorkerDetailsComponent.validHtml\"></th>\r\n              <th></th>\r\n              <th sxy-if-role=\"test,admin\"></th>\r\n            </tr>\r\n          </thead>\r\n          <tbody>\r\n            <tr ng-repeat=\"taxCard in $ctrl.list\">\r\n              <td>\r\n                <span class=\"visible-xs visible-sm\">\r\n                  <i>{{ \"TaxcardKind.\" + taxCard.data.kind | sxyEnum }} {{ taxCard.data.forYear }}</i>\r\n                  {{taxCard.data.taxPercent}} %\r\n                  <span ng-if=\"taxCard.data.taxPercent2 != null\">({{ taxCard.data.taxPercent2 }} %)</span>\r\n                </span>\r\n                <span class=\"hidden-xs hidden-sm\">\r\n                  <b>{{ \"TaxcardKind.\" + taxCard.data.kind | sxyEnum }}</b>\r\n                </span>\r\n              </td>\r\n              <td class=\"hidden-xs hidden-sm\">{{ taxCard.data.forYear }}</td>\r\n              <td class=\"hidden-xs hidden-sm tax-percentage right\">{{taxCard.data.taxPercent}} %</td>\r\n              <td class=\"salaries-paid right\">\r\n                {{ taxCard.data.totalIncome | currency: ' €' : 0 }}\r\n                <span class=\"visible-xs visible-sm\">{{(taxCard.data.incomeLimit | currency: ' €' : 0) || '-'}}</span>\r\n              </td>\r\n              <td class=\"hidden-xs hidden-sm income-limit right\">\r\n                {{(taxCard.data.incomeLimit | currency: '€' : 0) || '-'}}<br />\r\n                <span>{{taxCard.data.taxPercent2 != null ? (taxCard.data.taxPercent2 + ' %') : '-'}}</span>\r\n              </td>\r\n              <td class=\"right\">\r\n                {{ taxCard.data | sxyDateRange }}<br /> {{ taxCard.createdAt | sxyDate }}\r\n              </td>\r\n              <td class=\"middle-align\">\r\n                <span ng-if=\"!taxCard.isReadOnly && !$ctrl.hideButtons\">\r\n                  <button class=\"btn btn-danger btn-sm\" ng-click=\"$ctrl.deleteTaxCard(taxCard.id)\">\r\n                    <span class=\"hidden-xs\" sxy-text=\"SALAXY.UI_Terms.delete\"></span>\r\n                    <span class=\"visible-xs\">&times;</span>\r\n                  </button>\r\n                </span>\r\n              </td>\r\n              <td class=\"middle-align\" sxy-if-role=\"test,admin,pro\">\r\n                <a type=\"button\" class=\"edit btn btn-sm btn-default\" href=\"#/taxcards/details/{{taxCard.id}}\"><i class=\"fa fa-edit\"></i></a>\r\n              </td>\r\n            </tr>\r\n          </tbody>\r\n        </table>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardDetails.html\",`<div class=\"salaxy-component salaxy-taxcard-details\">\r\n\r\n  <form name=\"editForm\">\r\n    <div ng-show=\"false\" ng-init=\"$ctrl.editForm = editForm\"></div>\r\n    <!-- TODO: See if this is in use in pro. It is probably in use in Admin. -->\r\n    <div ng-if=\"$ctrl.getMode() == 'pro'\" ng-include=\"'salaxy-components/worker/taxcard/TaxcardDetails_Pro.html'\"></div>\r\n    <div ng-if=\"$ctrl.getMode() == 'new'\" class=\"alert alert-danger\">\r\n      <h3>Error: Disabled</h3>\r\n      <p>Adding a new taxcard in details view is diabled.</p>\r\n    </div>\r\n    <div ng-if=\"$ctrl.getMode() == 'default'\" ng-include=\"'salaxy-components/worker/taxcard/TaxcardDetails_Info.html'\"></div>\r\n    <div ng-if=\"$ctrl.getMode() == 'null'\" class=\"salaxy-placeholder-empty placeholder-md text-center\">\r\n      <div ng-if=\"$ctrl.employmentRelationTaxcardType != 'auto'\">\r\n        <h4 sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noTaxCardAddedWorker\" ng-if=\"$ctrl.employmentId == 'self'\"></h4>\r\n        <h4 sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noTaxCardAdded\" ng-if=\"$ctrl.employmentId != 'self'\"></h4>\r\n        <button class=\"btn btn-primary\" ng-if=\"!$ctrl.hideButtons\" ng-disabled=\"$ctrl.loaders['showAddNew']\" ng-click=\"$ctrl.showAddNew()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.addTaxCard\"></button>\r\n      </div>\r\n      <div ng-if=\"$ctrl.employmentRelationTaxcardType == 'auto'\">\r\n        <button class=\"btn btn-primary\" ng-if=\"!$ctrl.hideButtons\" ng-disabled=\"$ctrl.loaders['showSetAuto']\" ng-click=\"$ctrl.setAuto()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.searchTaxCard\"></button>  \r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.getMode() == 'no-personal-id'\" class=\"alert alert-danger\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noPersonalIdError\"></div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardDetails_Info.html\",`<div>\r\n  <div ng-if=\"$ctrl.isTaxCardExpired($ctrl.current)\" class=\"salaxy-placeholder-empty placeholder-md placeholder-danger text-center\">\r\n    <h4 sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardExpired\"></h4>\r\n    <button class=\"btn btn-primary\" ng-if=\"!$ctrl.hideButtons\" ng-disabled=\"$ctrl.loaders['showAddNew']\" ng-click=\"$ctrl.showAddNew()\"\r\n      sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.newTaxCard\"></button>\r\n  </div>\r\n  <div class=\"row\">\r\n\r\n    <div class=\"col-md-7 col-lg-7\" ng-switch=\"$ctrl.chartType\">\r\n      <div ng-switch-when=\"full\" class=\"salaxy-tax-card-chart chart-container\">    \r\n          <salaxy-chart custom-height=\"400px\" config=\"$ctrl.getMainChartConfig($ctrl.current)\"></salaxy-chart>\r\n      </div>\r\n\r\n      <div ng-switch-when=\"pie\" class=\"salaxy-tax-card-chart chart-container text-center\">      \r\n          <salaxy-chart style=\"height: 400px; position: relative;\" config=\"$ctrl.getPieChartConfig($ctrl.current)\"></salaxy-chart>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-md-5 col-lg-5\">\r\n      <div class=\"row current-taxcard-row table-row\">\r\n        <div class=\"col-xs-12\">\r\n          <div class=\"btn-group pull-right\">\r\n            <a ng-if=\"$ctrl.getTaxcardPreviewUrl($ctrl.current)\" ng-href=\"{{$ctrl.getTaxcardPreviewUrl($ctrl.current)}}\" target=\"_blank\" class=\"btn btn-xs btn-default\"\r\n              sxy-text=\"SALAXY.UI_Terms.open\"></a>\r\n            <a ng-if=\"$ctrl.getTaxcardDownloadUrl($ctrl.current)\" ng-href=\"{{$ctrl.getTaxcardDownloadUrl($ctrl.current)}}\" target=\"_blank\" class=\"btn btn-xs btn-default\"\r\n              sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n          </div>\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardKind\"></strong><br /> {{ 'TaxcardKind.' + $ctrl.current.card.kind | sxyEnum }}\r\n          ({{$ctrl.current.card.forYear}})\r\n        </div>\r\n      </div>\r\n      <div class=\"row current-taxcard-row table-row\">\r\n        <div class=\"col-xs-8\">\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.validDate\"></strong><br /> {{$ctrl.current.card.validity.start | date}} - {{$ctrl.current.card.validity.end | date}}\r\n        </div>\r\n        <div class=\"col-xs-4 text-right\">\r\n          <strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardAdded\"></strong><br />\r\n          <span title=\"{{ $ctrl.current.createdAt | date : 'short' }}\">{{ $ctrl.current.createdAt | sxyDate }}</span>\r\n        </div>\r\n      </div>\r\n      <table class=\"table table-condensed\" style=\"margin-bottom: 0; margin-top: 6px\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\" style=\"padding-left: 0;\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.mainTaxPercent2\"></span></th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.basicPercent\"></td>\r\n            <td class=\"right\">{{ $ctrl.current.card.taxPercent }} %</td>\r\n          </tr>\r\n          <tr ng-if=\"!$ctrl.current.card.incomeLimit\">\r\n            <td colspan=\"2\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noIncomeLimit\"></span></td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.card.incomeLimit\">\r\n            <td><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercent2.name\"></span> <small>(tulorajan {{ $ctrl.current.card.incomeLimit | currency : '€' : 0 }}\r\n                {{'SALAXY.NG1.CurrentTaxCardComponent.after' | sxyTranslate}})</small></td>\r\n            <td class=\"right\">{{ $ctrl.current.card.taxPercent2 || \"-\" }} %</td>\r\n          </tr>\r\n          <tr>\r\n            <td>\r\n              <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercentMin.title\"></span>\r\n              <button\r\n                ng-if=\"$ctrl.current.card.kind == 'auto' && ( $ctrl.current.card.state == 'shared' || $ctrl.current.card.state == 'employerAdded' || $ctrl.current.card.state == 'verifiedVero' || $ctrl.current.card.state == 'sharedApproved')\"\r\n                type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$ctrl.editTaxPercentMin()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.edit\"></button>\r\n            </td>\r\n            <td class=\"right\">\r\n              <span>{{ $ctrl.current.card.taxPercentMin || \"-\" }} %</span>\r\n            </td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.card.kind == 'auto'\">\r\n            <td colspan=\"2\">\r\n              <span class=\"text-info\" ng-if=\"$ctrl.current.card.lastChecked != '2000-01-01T00:00:00Z'\"><small>{{'SALAXY.NG1.CurrentTaxCardComponent.taxCardChecked' | sxyTranslate}}\r\n                  {{$ctrl.current.card.lastChecked | date: \"dd.MM.yyyy HH:mm\"}}</small></span>\r\n              <br />\r\n              <button type=\"button\" ng-disabled=\"$ctrl.loaders['showRefreshAutoTaxcardDialog']\" ng-click=\"$ctrl.showRefreshAutoTaxcardDialog()\"\r\n                class=\"btn btn-info\">{{'SALAXY.NG1.CurrentTaxCardComponent.checkAutomaticTaxCard' | sxyTranslate}}</button>\r\n            </td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.card.kind != 'auto'\">\r\n            <td colspan=\"2\">\r\n              <button class=\"btn btn-primary\" ng-if=\"!$ctrl.isTaxCardExpired($ctrl.current) && !$ctrl.hideButtons\" ng-disabled=\"$ctrl.loaders['showAddNew']\"\r\n                ng-click=\"$ctrl.showAddNew()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.newTaxCard\"></button>\r\n            </td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n      <table class=\"table table-condensed\" style=\"margin-top: 6px\" ng-if=\"$ctrl.current.card.incomeLimit\">\r\n        <thead>\r\n          <tr>\r\n            <th colspan=\"2\" style=\"padding-left: 0;\"><strong sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.incomeLimit\"></strong></th>\r\n            <th class=\"right\">{{ $ctrl.current.card.incomeLimit | currency : '€' : 0 }}</th>\r\n          </tr>\r\n        </thead>\r\n        <tbody>\r\n          <tr>\r\n            <td style=\"width: 20px;\" class=\"text-center\">-</td>\r\n            <td>\r\n              <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.salariesPaid\"></span>\r\n              <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$ctrl.editIncomeLog()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.edit\"></button>\r\n            </td>\r\n            <td class=\"right\">{{ $ctrl.current.result.totalIncome | currency }}</td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.result.totalIncomeJanuary\">\r\n            <td></td>\r\n            <td>...<span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.inJanuary\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.result.totalIncomeJanuary | currency }}</td>\r\n          </tr>\r\n          <tr>\r\n            <td></td>\r\n            <td><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.inPalkkaus\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.result.payment | currency }}</td>\r\n          </tr>\r\n          <tr ng-if=\"$ctrl.current.result.paymentJanuary\">\r\n            <td></td>\r\n            <td>...<span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.inJanuary\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.result.paymentJanuary | currency }}</td>\r\n          </tr>\r\n          <tr class=\"total\">\r\n            <td colspan=\"2\"><span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.beforeIncomeLimit\"></span></td>\r\n            <td class=\"right\">{{ $ctrl.current.card.incomeLimit - $ctrl.current.result.totalIncome | currency }}</td>\r\n          </tr>\r\n        </tbody>\r\n      </table>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardDetails_Pro.html\",`<div class=\"salaxy-calc-worker-info row\" ng-if=\"$ctrl.status !== 'initialLoading'\">\r\n  <div class=\"col-xs-3 col-sm-2 col-xxs-3 \">\r\n    <salaxy-avatar avatar=\"$ctrl.current.worker\"></salaxy-avatar>\r\n  </div>\r\n  <div class=\"col-xs-9 col-sm-10 col-xxs-9 worker-info-col\">\r\n    <button class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.save()\" ng-disabled=\"!$ctrl.hasChanges\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n    <button class=\"btn btn-default pull-right\" ng-disabled=\"$ctrl.loaders['showAddNew']\" ng-click=\"$ctrl.showAddNew()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.newTaxCard\"></button>\r\n    <h2>{{ $ctrl.current.worker.displayName || ('SALAXY.NG1.WorkerInfo.noSelection'| sxyTranslate) }}</h2>\r\n    <div class=\"row\">\r\n      <div class=\"col-xs-12 col-sm-6 \">\r\n        <span ng-if=\"!$ctrl.current.card.personalId\" sxy-text=\"SALAXY.NG1.PaymentDialogComponent.noSSNumber\" class=\"text-danger\"></span>\r\n        <span ng-if=\"$ctrl.current.card.personalId\">{{ $ctrl.current.card.personalId }}</span>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n<hr />\r\n<div ng-if=\"$ctrl.current\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-6\">\r\n      <div class=\"form-horizontal\">\r\n        <salaxy-input-enum disabled=\"true\" label=\"SALAXY.NG1.WorkerDetailsComponent.taxCard.cardType\" ng-required=\"true\" name=\"kind\" enum=\"TaxcardKind\" ng-model=\"$ctrl.current.card.kind\">\r\n        </salaxy-input-enum>\r\n        <salaxy-input-number disabled=\"$ctrl.current.card.kind == 'auto'\" label=\"SALAXY.NG1.CurrentTaxCardComponent.taxCards.year\" name=\"year\" ng-model=\"$ctrl.current.card.forYear\" require=\"true\"></salaxy-input-number>\r\n        <salaxy-datepicker-popup disabled=\"$ctrl.current.card.kind == 'auto'\" name=\"validityStart\" ng-model=\"$ctrl.current.card.validity.start\" popup-placement=\"bottom\" require=\"true\" label=\"SALAXY.NG1.CurrentTaxCardComponent.validFromDate2\">\r\n        </salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup disabled=\"$ctrl.current.card.kind == 'auto'\" name=\"validityEnd\" ng-model=\"$ctrl.current.card.validity.end\" popup-placement=\"bottom\" require=\"true\" label=\"SALAXY.NG1.CurrentTaxCardComponent.validTillDate\"></salaxy-datepicker-popup>\r\n        <salaxy-input-number disabled=\"$ctrl.current.card.kind == 'auto'\" label=\"SALAXY.NG1.CurrentTaxCardComponent.mainTaxPercent\" name=\"taxPercent\" ng-model=\"$ctrl.current.card.taxPercent\" require=\"true\" sxy-tax-percent></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.card.kind == 'auto'\" name=\"incomeLimit\" label=\"SALAXY.NG1.CurrentTaxCardComponent.incomeLimit2\" ng-model=\"$ctrl.current.card.incomeLimit\" sxy-currency></salaxy-input-number>\r\n        <salaxy-input-number disabled=\"$ctrl.current.card.kind == 'auto'\" name=\"taxPercent2\" label=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercent2.name\" ng-model=\"$ctrl.current.card.taxPercent2\" sxy-tax-percent></salaxy-input-number>\r\n        <div class=\"row\" ng-if=\"$ctrl.current.card.kind != 'auto'\">\r\n          <div class=\"col-xs-12\">\r\n            <div class=\"pull-right\">\r\n              <a ng-href=\"{{ $ctrl.getTaxcardDownloadUrl($ctrl.current) }}\" ng-if=\"$ctrl.getTaxcardDownloadUrl($ctrl.current)\" target=\"_blank\" sxy-text=\"SALAXY.UI_Terms.download\"></a>\r\n            </div>\r\n            <legend style=\"text-align:left\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardAsFile\"></legend>\r\n            <div ng-include=\"'salaxy-components/worker/taxcard/TaxcardDetails_Upload.html'\"></div>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <div class=\"alert alert-info\" ng-if=\"$ctrl.$incomeLog.hasDiff\">\r\n        <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.commitDiff()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.commitDiffBtn\"></button>\r\n        <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.commitDiffNote\"></span>\r\n      </div>\r\n      <salaxy-taxcard-income-log parent=\"$ctrl.current\" editable=\"false\" ng-ref=\"$ctrl.$incomeLog\"></salaxy-taxcard-income-log>\r\n      <div class=\"text-right\">\r\n        <button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"$ctrl.editIncomeLog()\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.edit\"></button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardDetails_Upload.html\",`<div name=\"taxCardFile\" ng-model=\"taxCardFile\" ngf-drop=\"$ctrl.uploadTaxCard($file)\" \r\n  ngf-select=\"$ctrl.uploadTaxCard($file)\" class=\"salaxy-drop-box\" ngf-drag-over-class=\"'salaxy-drag-over'\" \r\n  ngf-multiple=\"false\" ngf-min-size=\"5KB\" ngf-max-size=\"10MB\"\r\n  ngf-pattern=\"'image/*,application/pdf'\" ngf-model-invalid=\"invalidFile\" ng-class=\"invalidFile.$error != null ? 'error' : ''\"\r\n  ng-required=\"$ctrl.addNewUi.upload == 'required'\">\r\n  <span ng-if=\"$ctrl.uploadProgress && $ctrl.uploadProgress != 100\">\r\n    <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.loading\"></span> {{ $ctrl.uploadProgress }}% {{'SALAXY.NG1.CurrentTaxCardComponent.taxCards.taxCardDetails.downloaded' | sxyTranslate}}\r\n  </span>\r\n  <span ng-if=\"$ctrl.uploadProgress == 100\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.progressPreview\"></span>\r\n  <span class=\"text-danger\" ng-if=\"$ctrl.getInvalidFileDescription(invalidFile)\">{{$ctrl.getInvalidFileDescription(invalidFile)}}</span>\r\n  <span ng-if=\"!$ctrl.uploadProgress && !$ctrl.current.card.fileUri\" sxy-html=\"SALAXY.NG1.CurrentTaxCardComponent.uploadTaxCard.html\"></span>\r\n  <span ng-if=\"!$ctrl.uploadProgress && $ctrl.current.card.fileUri\">\r\n    <img class=\"img-responsive\" ng-src=\"{{$ctrl.getUploadPreviewUrl($ctrl.current)}}\" />\r\n  </span>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardIncomeLog.html\",`<div class=\"salaxy-component salaxy-taxcard-income-log\">\r\n  <table class=\"table table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th>\r\n          <strong sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.addedForTaxCard\"></strong><br />\r\n          <span sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.salaryPeriod\"></span>\r\n        </th>\r\n        <th class=\"right\">\r\n          <strong sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.mainTaxPercent\"></strong><br />\r\n          <span sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.salaryAmount\"></span>\r\n        </th>\r\n        <th ng-if=\"$ctrl.editable\" style=\"width: 20px;\"></th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.list\" class=\"\" ng-style=\"row.diff == 'removed' ? 'text-decoration: line-through' : ''\" ng-class=\"{ 'success': row.diff == 'new', 'text-primary': row.diff == 'changed', 'text-danger': row.diff == 'removed' }\">\r\n        <td>\r\n          <strong>\r\n            <span ng-if=\"row.id && row.diff != 'removed'\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.calculation\"></span>\r\n            <span ng-if=\"row.id && row.diff == 'removed'\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.removedCalc\"></span>\r\n            <span ng-if=\"!row.id\">{{ \"TaxCardIncomeType.\" + row.type | sxyEnum }}</span ng-if=\"row.id\">\r\n            {{ row.paidAt | sxyDate }}\r\n            <button ng-if=\"row.diff == 'new'\" uib-popover=\"{{'SALAXY.NG1.TaxCardIncomeLogComponent.newCalcPopover'| sxyTranslate}}\" popover-trigger=\"'mouseenter'\" type=\"button\" class=\"btn btn-xs btn-success\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.newCalcBtn\"></button>\r\n            <button ng-if=\"row.diff == 'changed' && row.type != 'diff'\" uib-popover=\"{{'SALAXY.NG1.TaxCardIncomeLogComponent.taxCardChangedPopover'| sxyTranslate}}\" \r\n              popover-trigger=\"'mouseenter'\" type=\"button\" class=\"btn btn-xs btn-primary\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.taxCardChangedBtn\"></button>\r\n            <button ng-if=\"row.diff == 'changed' && row.type == 'diff'\" uib-popover=\"{{'SALAXY.NG1.TaxCardIncomeLogComponent.calcChangedPopover'| sxyTranslate}}\"\r\n              popover-trigger=\"'mouseenter'\" type=\"button\" class=\"btn btn-xs btn-primary\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.calcChangedBtn\"></button>\r\n            <button ng-if=\"row.diff == 'removed'\" uib-popover=\"{{'SALAXY.NG1.TaxCardIncomeLogComponent.calcRemovedPopover'| sxyTranslate}}\" popover-trigger=\"'mouseenter'\" type=\"button\" class=\"btn btn-xs btn-danger\" sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.calcRemovedBtn\"></button>\r\n          </strong><br />\r\n          <div class=\"pull-left\" style=\"padding: 0px;\">\r\n            {{ { start: row.startDate, end: row.endDate } | sxyDateRange }}\r\n          </div>\r\n          <div class=\"truncate\" style=\"max-width: 250px; padding: 0px;\">\r\n            &nbsp;{{ row.description }}\r\n          </div>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>{{ row.tax ? (row.tax | currency) : \"-\" }}</strong><br /> {{ row.income | currency }}\r\n        </td>\r\n        <td ng-if=\"$ctrl.editable\" style=\"width: 20px;\">\r\n          <button type=\"button\" class=\"btn btn-default\" ng-if=\"!$ctrl.isReadOnly(row)\" ng-click=\"$ctrl.showEditDialog(row)\"><i class=\"fa fa-edit\"></i></button>\r\n        </td>\r\n      </tr>\r\n      <tr ng-if=\"!($ctrl.list.length > 0)\">\r\n        <td colspan=\"2\">\r\n          <h3 sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.noCalcsTitle\"></h3>\r\n          <p sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.noCalcsDescription\"></p>\r\n        </td>\r\n      </tr>\r\n      <tr class=\"total\">\r\n        <td>\r\n          <strong>\r\n         <span sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.totalTaxes\"></span> <br />\r\n            <span sxy-text=\"SALAXY.NG1.TaxCardIncomeLogComponent.totalIncome\"></span>\r\n          </strong>\r\n        </td>\r\n        <td class=\"right\">\r\n          <strong>\r\n            {{ $ctrl.getSum(\"tax\") | currency }}<br />\r\n            {{ $ctrl.getSum(\"income\") | currency }}\r\n          </strong>\r\n        </td>\r\n        <td ng-if=\"$ctrl.editable\" style=\"width: 20px;\"></td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n  <div class=\"text-right\" ng-if=\"$ctrl.editable\">\r\n    <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showEditDialog('new')\" sxy-text=\"SALAXY.NG1.EmploymentTaxcardsComponent.taxCardIncomeLog.addElseWherePaidSalary\"></button>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardIncomeLogEditDialog.html\",`<div class=\"panel panel-primary\">\r\n  <div class=\"panel-heading \">\r\n    <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n    <h1 sxy-text=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.title\"></h1>\r\n  </div>\r\n  <div class=\"panel-body\">\r\n    <form class=\"form-horizontal\">\r\n      <fieldset>\r\n        <legend>Tulorajaan vaikuttavat tiedot</legend>\r\n        <salaxy-input-enum name=\"causeCode\" ng-model=\"$ctrl.current.type\" read-only=\"true\" enum=\"TaxCardIncomeType\" filter=\"externalSalaries\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.incomeType\" type=\"select\"></salaxy-input-enum>\r\n        <salaxy-datepicker-popup name=\"paidAt\" ng-model=\"$ctrl.current.paidAt\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.paymentDate\"></salaxy-datepicker-popup>\r\n        <salaxy-input-number name=\"income\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.taxableIncome\" ng-model=\"$ctrl.current.income\"></salaxy-input-number>\r\n      </fieldset>\r\n      <fieldset>\r\n        <legend>Lisätiedot</legend>\r\n        <salaxy-datepicker-popup name=\"startDate\" ng-model=\"$ctrl.current.startDate\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.periodStart\"></salaxy-datepicker-popup>\r\n        <salaxy-datepicker-popup name=\"endDate\" ng-model=\"$ctrl.current.endDate\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.periodEnd\"></salaxy-datepicker-popup>\r\n        <salaxy-input-number name=\"tax\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.tax\" ng-model=\"$ctrl.current.tax\"></salaxy-input-number>\r\n        <salaxy-input name=\"description\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.notes\" ng-model=\"$ctrl.current.description\"></salaxy-input>\r\n        <salaxy-input name=\"id\" read-only=\"true\" label=\"SALAXY.NG1.TaxCardIncomeLogEditDialogComponent.calcId\" ng-model=\"$ctrl.current.id\"></salaxy-input>\r\n      </fieldset>\r\n      <div>\r\n        <button type=\"submit\" class=\"btn btn-primary pull-right\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n        <button type=\"reset\" class=\"btn btn-default pull-right\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n        <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.deleteButtonText\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxcardManualEdit.html\",`<div class=\"salaxy-component salaxy-manual-edit\">\r\n  <form name=\"editForm\">\r\n    <div ng-show=\"false\" ng-init=\"$ctrl.editForm = editForm\"></div>\r\n    <div class=\"form-horizontal\">\r\n      <legend>\r\n        <span sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.newTaxCardTitle\"></span>\r\n        <button class=\"btn btn-primary btn-xs pull-right\" sxy-if-role=\"test\" ng-click=\"$ctrl.showToday=!$ctrl.showToday\">test</button>\r\n      </legend>\r\n      <salaxy-datepicker-popup ng-if=\"$ctrl.showToday\" name=\"todayTest\" ng-model=\"$ctrl.today\" popup-placement=\"top\"\r\n        ng-change=\"$ctrl.current.card.forYear = null;$ctrl.resetAsNew()\" label-cols=\"col-sm-7\"\r\n        label=\"SALAXY.NG1.CurrentTaxCardComponent.taxCards.taxCardDetails.changeThisDate\"></salaxy-datepicker-popup>\r\n      <salaxy-input-enum label=\"SALAXY.NG1.CurrentTaxCardComponent.taxCardKind\" label-cols=\"col-sm-7\" require=\"true\" name=\"verokortinTyyppi\" enum=\"TaxcardKind\"\r\n        type=\"{{ (!$ctrl.current.card.kind || $ctrl.current.card.kind == 'undefined' || $ctrl.current.card.kind == 'auto') ? 'radio' : 'select' }}\"\r\n        ng-model=\"$ctrl.current.card.kind\" ng-change=\"$ctrl.resetAsNew($ctrl.current.card.kind)\" options=\"$ctrl.taxcardKindOptions\"\r\n        placeholder=\"SALAXY.NG1.CurrentTaxCardComponent.selectCardKind\">\r\n      </salaxy-input-enum>\r\n      <p ng-if=\"$ctrl.current.card.kind == 'noTaxCard'\" class=\"text-danger\" style=\"margin-top:5px; margin-bottom:0;\"\r\n        sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noTaxCard.description\"></p>\r\n      <p ng-if=\"$ctrl.current.card.kind == 'noWithholdingHousehold'\" class=\"text-danger\" style=\"margin-top:5px; margin-bottom:0;\"\r\n        sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.noWithholdingHousehold.description\"></p>\r\n      <salaxy-form-group label=\"SALAXY.NG1.CurrentTaxCardComponent.year\" require=\"true\" name=\"year\" label-cols=\"col-sm-7\" ng-if=\"$ctrl.addNewUi.yearsAllowed\">\r\n        <select ng-model=\"$ctrl.current.card.forYear\" class=\"form-control\" ng-options=\"i for i in $ctrl.addNewUi.yearsAllowed\" ng-change=\"$ctrl.yearChanged()\"></select>\r\n      </salaxy-form-group>\r\n      <salaxy-input label=\"SALAXY.NG1.CurrentTaxCardComponent.mainTaxPercent3\" name=\"veroprosentti\" label-cols=\"col-sm-7\" ng-model=\"$ctrl.current.card.taxPercent\"\r\n        disabled=\"$ctrl.addNewUi.readonly\" require=\"true\" sxy-tax-percent ng-if=\"$ctrl.addNewUi.showTaxPercent\"></salaxy-input>\r\n      <salaxy-input name=\"tuloraja\" label=\"SALAXY.NG1.CurrentTaxCardComponent.incomeLimit2\" ng-model=\"$ctrl.current.card.incomeLimit\" maxlength=\"10\"\r\n        ng-if=\"$ctrl.addNewUi.showIncomeLimit\" label-cols=\"col-sm-7\" require=\"$ctrl.addNewUi.requireIncomeLimit || $ctrl.current.card.taxPercent2\" sxy-currency></salaxy-input>\r\n      <salaxy-input name=\"lisaveroprosentti\" label=\"SALAXY.NG1.CurrentTaxCardComponent.taxPercent2.name\" label-cols=\"col-sm-7\" ng-model=\"$ctrl.current.card.taxPercent2\"\r\n        ng-if=\"$ctrl.addNewUi.showIncomeLimit\" require=\"$ctrl.addNewUi.requireIncomeLimit || $ctrl.current.card.incomeLimit\" sxy-tax-percent></salaxy-input>\r\n      <salaxy-form-group label-cols=\"col-sm-5\" label=\"SALAXY.NG1.CurrentTaxCardComponent.validDate\" name=\"validityStart\" class=\"salaxy-read-only\"\r\n        ng-if=\"$ctrl.current.card.kind =='defaultYearly' || $ctrl.current.card.kind == 'replacement'\">\r\n        <div class=\"salaxy-read-only-value text-right\">{{ $ctrl.current.card.validity.start | date : \"dd.MM.yyyy\" }} – {{ $ctrl.current.card.validity.end | date :\r\n          \"dd.MM.yyyy\" }}</div>\r\n      </salaxy-form-group>\r\n      <salaxy-datepicker-popup name=\"voimaantuloPvm\" ng-model=\"$ctrl.current.card.validity.start\" popup-placement=\"bottom\" ng-if=\"$ctrl.addNewUi.startDateOptions\"\r\n        datepicker-options=\"$ctrl.addNewUi.startDateOptions\" label-cols=\"col-sm-7\" require=\"true\"\r\n        label=\"SALAXY.NG1.CurrentTaxCardComponent.validFromDate2\"></salaxy-datepicker-popup>\r\n      <salaxy-input name=\"previousSalariesRow\" label=\"SALAXY.NG1.CurrentTaxCardComponent.previousSalariesForTaxCard.label\" ng-model=\"$ctrl.previousSalariesRow.income\"\r\n        ng-if=\"$ctrl.addNewUi.showPreviousSalariesPaid\" tooltip-html=\"{{'SALAXY.NG1.CurrentTaxCardComponent.previousSalariesForTaxCard.tooltip' | sxyTranslate}}\"\r\n        tooltip-placement=\"top-right\" label-cols=\"col-sm-7\" sxy-currency></salaxy-input>\r\n    </div>\r\n  </form>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/taxcard/TaxCardsList.html\",`<div class=\"salaxy-component salaxy-tax-cards-list\">\r\n  <div class=\"row form-horizontal\" sxy-if-role=\"test\" ng-init=\"$ctrl.today = 'today'\">\r\n    <div class=\"col-xs-6\">\r\n      <salaxy-datepicker-popup name=\"today\" ng-model=\"$ctrl.today\" label=\"SALAXY.NG1.CurrentTaxCardComponent.salaryDate\"\r\n        ng-change=\"\"></salaxy-datepicker-popup>\r\n    </div>\r\n    <div class=\"col-xs-6\">\r\n      <button type=\"button\" class=\"btn btn-primary\" \r\n        ng-click=\"$ctrl.$odata.setUrl('/v03/api/taxcards/current/' + $ctrl.today || 'null')\" sxy-text=\"SALAXY.NG1.CurrentTaxCardComponent.changePaymentDate\"></button>\r\n    </div>\r\n  </div>\r\n  <salaxy-odata-table url=\"/v03/api/taxcards/current/null\" crud-controller=\"TaxcardCrudController as $crud\"\r\n    ng-ref=\"$ctrl.$odata\"\r\n    template-url=\"salaxy-components/odata/lists/Taxcards.html\"></salaxy-odata-table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/TimerEditDialog.html\",`<div class=\"salaxy-component salaxy-timer-dialog\">\r\n  <div>\r\n    <div class=\"modal-header\">\r\n      <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h2 sxy-text=\"Muokkaa kellokorttimerkintää\"></h2>\r\n    </div>\r\n    <div class=\"modal-body\">\r\n      <form class=\"form-horizontal\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6  col-xs-12\">\r\n            <salaxy-datepicker-popup name=\"start\" ng-model=\"$ctrl.current.contentData.period.start\" label=\"Aloituspäivä\"></salaxy-datepicker-popup>\r\n          </div>\r\n          <div class=\"col-sm-6  col-xs-12\">\r\n            <salaxy-input-time name=\"startTime\" label=\"Alkoi\" type=\"time\" ng-model=\"$ctrl.current.contentData.startTime\"></salaxy-input-time>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6  col-xs-12\">\r\n            <salaxy-datepicker-popup name=\"start\" ng-model=\"$ctrl.current.contentData.period.end\" label=\"Lopetuspäivä\"></salaxy-datepicker-popup>\r\n          </div>\r\n          <div class=\"col-sm-6  col-xs-12\">\r\n            <salaxy-input-time name=\"endTime\" label=\"Loppui\" type=\"time\" ng-model=\"$ctrl.current.contentData.endTime\"></salaxy-input-time>\r\n          </div>\r\n        </div>\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-enum ng-if=\"$ctrl.logic.costAccountingSettings\" type=\"typeahead\" label-format=\"text-value\"\r\n              name=\"options_project\" ng-model=\"$ctrl.current.contentData.project\" options=\"$ctrl.logic.costAccountingSettings.options\"\r\n              label=\"{{($ctrl.logic.costAccountingSettings.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" required=\"true\"></salaxy-input-enum>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input label=\"Kommentti\" placeholder=\"Kommentti\"  name=\"comment\" ng-model=\"$ctrl.current.contentData.projectText\">\r\n            </salaxy-input>\r\n          </div>\r\n        </div>\r\n    </div>\r\n    </form>\r\n  </div>\r\n  <div class=\"modal-footer\">\r\n    <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n    <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n\r\n    <button type=\"button\" class=\"btn btn-danger pull-left\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.deleteButtonText\"></button>\r\n  </div>\r\n</div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/TimeReportEditDialog.html\",`<div class=\"salaxy-component salaxy-timer-dialog\">\r\n  <div>\r\n    <div class=\"modal-header\">\r\n      <button type=\"button\" class=\"close pull-right\" ng-click=\"$dismiss()\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n      <h2 sxy-text=\"Muokkaa aikakirjausta\"></h2>\r\n    </div>\r\n    <div class=\"modal-body\">\r\n      <form class=\"form-horizontal\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-enum ng-if=\"$ctrl.logic.costAccountingSettings\" type=\"typeahead\" label-format=\"text-value\" name=\"options_project\" ng-model=\"$ctrl.current.contentData.project\" options=\"$ctrl.logic.costAccountingSettings.options\" label=\"{{($ctrl.logic.costAccountingSettings.label || 'SALAXY.NG1.CalcCostAccountingComponent.defaultLabel') | sxyTranslate}}\" required=\"true\"></salaxy-input-enum>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input name=\"message\" ng-model=\"$ctrl.current.contentData.projectText\" label=\"Kommentti\"></salaxy-input>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-time name=\"startTime\" label=\"Aloitusaika\" type=\"time\" ng-model=\"$ctrl.current.contentData.startTime\"></salaxy-input-time>\r\n          </div>\r\n          <div class=\"col-sm-6 col-xs-12\">\r\n            <salaxy-input-time name=\"endTime\" label=\"Lopetusaika\" type=\"time\" ng-model=\"$ctrl.current.contentData.endTime\"></salaxy-input-time>\r\n          </div>\r\n        </div>\r\n      </form>\r\n    </div>\r\n    <div class=\"modal-footer\">\r\n      <button type=\"reset\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.cancelButtonText\"></button>\r\n      <button type=\"submit\" class=\"btn btn-primary\" ng-click=\"$close('ok')\" sxy-text=\"SALAXY.UI_Terms.ok\"></button>\r\n\r\n      <button type=\"button\" class=\"btn btn-danger pull-left\" ng-click=\"$close('delete')\" sxy-text=\"SALAXY.NG1.AbsencePeriodsEditDialog.deleteButtonText\"></button>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/WorkerAbsences.html\",`<div class=\"salaxy-component salaxy-worker-absences\">\r\n  <salaxy-spinner ng-if=\"$ctrl.isLoading\"></salaxy-spinner>\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-8\">\r\n      <fieldset ng-if=\"$ctrl.viewType == 'overview'\">\r\n        <salaxy-absence-periods on-commit=\"$ctrl.save()\" parent=\"$ctrl.current\" mode=\"calendar\"\r\n          filter-start=\"$ctrl.currentYear + '-01-01'\" filter-end=\"$ctrl.currentYear + '-12-31'\"\r\n          ></salaxy-absence-periods>\r\n      </fieldset>\r\n      <fieldset ng-if=\"$ctrl.viewType == 'list'\">\r\n        <salaxy-absence-periods on-commit=\"$ctrl.save()\" parent=\"$ctrl.current\"></salaxy-absence-periods>\r\n      </fieldset>\r\n    </div>\r\n    <div class=\"col-sm-4\">\r\n      <div class=\"btn-group btn-block\" uib-dropdown>\r\n        <button id=\"year-selection\" type=\"button\" class=\"btn btn-primary btn-block\" uib-dropdown-toggle>\r\n          {{ $ctrl.currentYear  }}\r\n          <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"single-button\">\r\n          <li role=\"menuitem\"><a href=\"\" ng-click=\"$ctrl.currentYear = year\" ng-repeat=\"year in $ctrl.years\">{{ year }}</a></li>\r\n        </ul>\r\n      </div>\r\n      <div class=\"btn-group-vertical btn-block\">\r\n        <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" uib-btn-radio=\"'overview'\" sxy-text=\"SALAXY.NG1.WorkerAbsencesComponent.calendarButtonText\"></label>\r\n        <label class=\"btn btn-default btn-block\" ng-model=\"$ctrl.viewType\" uib-btn-radio=\"'list'\" sxy-text=\"SALAXY.NG1.WorkerAbsencesComponent.listButtonText\"></label>\r\n      </div>\r\n      <p>&nbsp;</p>\r\n      <fieldset>\r\n        <legend sxy-text=\"SALAXY.NG1.WorkerAbsencesComponent.legendInstructions\"></legend>\r\n        <div sxy-html=\"SALAXY.NG1.WorkerAbsencesComponent.instructions.html\"></div>\r\n      </fieldset>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/WorkerAssure.html\",`<div class=\"salaxy-component salaxy-worker-assure\">\r\n  <div class=\"col col-md-12 col-lg-12\">\r\n    <form name=\"assureWorkerForm\" class=\"form-horizontal\">\r\n      <h3>Luo uusi työntekijä (Partner, BETA)</h3>\r\n      <salaxy-input sxy-personal-id-fi ng-model=\"$ctrl.assureWorkerAccountReq.officialId\" label=\"Henkilötunnus\" name=\"officialId\" require=\"true\"></salaxy-input>\r\n      <salaxy-input ng-model=\"$ctrl.assureWorkerAccountReq.firstName\" label=\"Etunimi\" name=\"firstName\" require=\"true\"></salaxy-input>\r\n      <salaxy-input ng-model=\"$ctrl.assureWorkerAccountReq.lastName\" label=\"Sukunimi\" name=\"lastName\" require=\"true\"></salaxy-input>\r\n      <salaxy-input sxy-email ng-model=\"$ctrl.assureWorkerAccountReq.email\" label=\"Sähköposti\" name=\"email\" require=\"true\"></salaxy-input>\r\n      <salaxy-input sxy-mobile-phone ng-model=\"$ctrl.assureWorkerAccountReq.telephone\" label=\"Puhelin\" name=\"telephone\" require=\"true\"></salaxy-input>\r\n      <salaxy-input sxy-iban ng-model=\"$ctrl.assureWorkerAccountReq.bankAccountIban\" label=\"Pankkitili\" name=\"bankAccountIban\" require=\"true\"></salaxy-input>\r\n      <salaxy-datepicker-popup name=\"startDate\" label=\"Työsuhteen alkamispäivä\" ng-model=\"$ctrl.assureWorkerAccountReq.startDate\"></salaxy-datepicker-popup>\r\n      <salaxy-datepicker-popup name=\"endDate\" label=\"Työsuhteen päättymispäivä\" ng-model=\"$ctrl.assureWorkerAccountReq.endDate\"></salaxy-datepicker-popup>\r\n\r\n      <div class=\"text-right\">\r\n        <button type=\"reset\" ng-click=\"assureWorkerForm.$setPristine(); $ctrl.resetAssureWorkerAccount()\" class=\"btn btn-default\">Tyhjennä</button>\r\n        <button ng-click=\"assureWorkerForm.$setPristine(); $ctrl.submitAssureWorkerAccount($employmentDetails, $employmentsList);\" ng-disabled=\"assureWorkerForm.$invalid\" class=\"btn btn-primary\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </div>\r\n    </form>\r\n  </div>\r\n\r\n  <div class=\"col col-md-5 col-lg-5\">\r\n    <hr />\r\n    <salaxy-employment-list limit-to=\"10\" ng-ref=\"$employmentsList\" mode=\"select\" on-list-select=\"$employmentDetails.model = (value == true ? item.id : null); $employmentsList.selectedItems = []\"></salaxy-employment-list>\r\n  </div>\r\n  <div class=\"col-md-7 col-lg-7\">\r\n    <hr />\r\n    <salaxy-employment-details ng-ref=\"$employmentDetails\"></salaxy-employment-details>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/worker/WorkerDetails.html\",`<div ng-if=\"$ctrl.status == 'initialLoading'\">\r\n  <p sxy-text=\"SALAXY.UI_Terms.loading\"></p>\r\n</div>\r\n<div ng-if=\"$ctrl.current\">\r\n  <div class=\"alert alert-warning\">\r\n    <div><strong>WARNING: This page is depricated!</strong></div>\r\n    <div>Tämä on vanha sivu, joka ei pitäisi enää olle näkyvissä. \r\n      <strong>Ilmoita asiakaspalvelulle</strong>, jos tämä sivu on vielä näkyvissä sivustollasi.</div>\r\n  </div>\r\n  <salaxy-employment-details model=\"$ctrl.current.employmentId\"></salaxy-employment-details>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/calendar/Occurences-daily.html\",`<salaxy-calendar data=\"$ctrl.calendarPeriods\" on-list-select=\"$ctrl.currentDay = date\"\r\n  today=\"$ctrl.currentDay\" start=\"$ctrl.range.start\" end=\"$ctrl.range.end\"></salaxy-calendar>\r\n<div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>Otsikko</th>\r\n        <th>Tyyppi</th>\r\n        <th class=\"right\">Periodi</th>\r\n        <th class=\"right\">Kesto</th>\r\n        <th class=\"right\">{{ $ctrl.todayOccurences.length | sxyCount : \"count\" }}</th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.todayOccurences\">\r\n        <td>\r\n          <i ng-if=\"row.data.actionId\" class=\"fa fa-bell\" aria-hidden=\"true\"></i>\r\n          <i ng-if=\"row.data.isRecurring\" class=\"fa fa-refresh\" aria-hidden=\"true\"></i>\r\n          {{ row.shortText }}\r\n        </td>\r\n        <td>\r\n          <small ng-if=\"row.data.type != 'undefined'\">{{ \"ApiItemType.\" + row.data.type | sxyEnum }}</small>\r\n          <small ng-if=\"row.data.type == 'undefined'\">-</small>\r\n          <i ng-if=\"row.data.isRecurring\" class=\"fa fa-repeat\" aria-hidden=\"true\" title=\"Toistuva\"></i>\r\n        </td>\r\n        <td class=\"right\">{{ row | sxyDateRange }}</td>\r\n        <td class=\"right\">{{ row.data.duration | sxyDuration }}</td>\r\n        <td><button type=\"button\" ng-click=\"$ctrl.showEditDialog(row)\" class=\"btn btn-default\">Näytä</button></td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/calendar/Occurences-details.html\",`<div class=\"modal-header\">\r\n  <button type=\"button\" class=\"close\" ng-click=\"$close('cancel')\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\r\n  <h2 class=\"modal-title\">{{ $ctrl.current.shortText }}</h2>\r\n</div>\r\n<div class=\"modal-body\">\r\n  <uib-tabset>\r\n    <uib-tab index=\"'basic'\" heading=\"Perustiedot\">\r\n      <div class=\"row form-horizontal\">\r\n        <div class=\"col-sm-6\">\r\n          <fieldset>\r\n            <legend>Kalenteritapahtuma</legend>\r\n            <salaxy-form-group name=\"start\" class=\"salaxy-component salaxy-read-only\" label=\"Alku\">\r\n              <div class=\"salaxy-read-only-value\">{{ $ctrl.current.startAt | sxyDate }}</div>\r\n            </salaxy-form-group>\r\n            <salaxy-form-group name=\"duration\" class=\"salaxy-component salaxy-read-only\" label=\"Kesto\">\r\n              <div class=\"salaxy-read-only-value\">{{ $ctrl.current.data.duration | sxyDuration }}</div>\r\n            </salaxy-form-group>\r\n            <salaxy-form-group name=\"end\" class=\"salaxy-component salaxy-read-only\" label=\"Loppu\">\r\n              <div class=\"salaxy-read-only-value\">{{ $ctrl.current.endAt | sxyDate }}</div>\r\n            </salaxy-form-group>\r\n            <salaxy-input-boolean name=\"isAllDay\" ng-model=\"$ctrl.current.data.isAllDay\" type=\"checkbox\" label=\"Koko päivän\" read-only=\"true\"></salaxy-input-boolean>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <fieldset>\r\n            <legend>Lisätietoja</legend>\r\n            <salaxy-input-enum name=\"priority\" enum=\"CalendarEventStatus\" ng-model=\"$ctrl.current.status\" label=\"Status\" read-only=\"true\"></salaxy-input-enum>\r\n            <salaxy-form-group name=\"start\" class=\"salaxy-component salaxy-read-only\" label=\"Kategoriat\">\r\n              <div class=\"salaxy-read-only-value\">\r\n                <div ng-repeat=\"cat in $ctrl.current.flags\"><span>{{ cat + ($last ? \"\" : \", \") }}</span></div>\r\n                <div ng-if=\"!$ctrl.current.flags.length\">-</div>\r\n              </div>\r\n            </salaxy-form-group>\r\n            <salaxy-input-number name=\"priority\" ng-model=\"$ctrl.current.data.priority\" label=\"Prioriteetti\" read-only=\"true\"></salaxy-input-number>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'debug'\" heading=\"Debug\">\r\n      <salaxy-json-formatter key=\"'Occurence'\" json=\"$ctrl.current\" open=\"1\"></salaxy-json-formatter>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>\r\n<div class=\"modal-footer text-left\">\r\n  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$close('cancel')\" sxy-text=\"SALAXY.UI_Terms.close\"></button>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/calendar/Occurences-list.html\",`<div>\r\n  <table class=\"table\">\r\n    <thead>\r\n      <tr>\r\n        <th>Otsikko</th>\r\n        <th>Tyyppi</th>\r\n        <th class=\"right\">Periodi</th>\r\n        <th class=\"right\">Kesto</th>\r\n        <th class=\"right\">{{ $ctrl.list.length | sxyCount : \"count\" }}</th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"row in $ctrl.list\">\r\n        <td>{{ row.shortText }}</td>\r\n        <td>\r\n          <small ng-if=\"row.data.type != 'undefined'\">{{ \"ApiItemType.\" + row.data.type | sxyEnum }}</small>\r\n          <small ng-if=\"row.data.type == 'undefined'\">-</small>\r\n          <i ng-if=\"row.data.isRecurring\" class=\"fa fa-repeat\" aria-hidden=\"true\" title=\"Toistuva\"></i>\r\n        </td>\r\n        <td class=\"right\">{{ row | sxyDateRange }}</td>\r\n        <td class=\"right\">{{ row.data.duration | sxyDuration }}</td>\r\n        <td class=\"right\"><button type=\"button\" ng-click=\"$ctrl.showEditDialog(row)\" class=\"btn btn-default\">Näytä</button></td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/calendar/Occurences-week.html\",`<style>\r\n  .salaxy-calendar-weekly {\r\n    padding-right: 28px;\r\n  }\r\n  .salaxy-calendar-week-header,\r\n  .salaxy-calendar-weekday,\r\n  .salaxy-calendar-weekend-day {\r\n    padding: 6px;\r\n    margin-right: -28px;\r\n  }\r\n\r\n  .salaxy-calendar-weekly .list-group {\r\n    margin-right: -28px;\r\n    min-height: 332px;\r\n    border: lightgrey solid 1px;\r\n  }\r\n\r\n  .salaxy-calendar-weekly .list-group.weekend {\r\n    min-height: 165px;\r\n    margin-bottom: 2px;\r\n  }\r\n\r\n  .salaxy-calendar-weekly .list-group-item {\r\n    white-space: nowrap;\r\n    overflow: hidden;\r\n    text-overflow: ellipsis;\r\n    padding: 4px 8px;\r\n  }\r\n\r\n  .salaxy-calendar-weekly .list-group-item.active {\r\n    font-weight: bold;\r\n  }\r\n\r\n  .salaxy-calendar-week-header {\r\n    height: 32px;\r\n    background-color: #009fd8;\r\n    color: white;\r\n    font-weight: bold;\r\n  }\r\n\r\n  .salaxy-calendar-weekday {\r\n    min-height: 332px;\r\n    border: lightgrey solid 1px;\r\n  }\r\n\r\n  .salaxy-calendar-weekend-day {\r\n    min-height: 150px;\r\n    border: lightgrey solid 1px;\r\n  }\r\n</style>\r\n<salaxy-calendar data=\"$ctrl.calendarPeriods\" on-list-select=\"$ctrl.currentDay = date\"\r\n  today=\"$ctrl.currentDay\" start=\"$ctrl.range.start\" end=\"$ctrl.range.end\"></salaxy-calendar>\r\n<div class=\"salaxy-component salaxy-calendar-weekly\" style=\"margin-top: 2px\">\r\n  <div class=\"row\">\r\n    <div class=\"col-sm-2 col-xs-4\" ng-repeat=\"day in $ctrl.currentWeek\">\r\n      <div class=\"list-group\" ng-class=\"{ 'weekend': $index &gt; 4 }\">\r\n        <button type=\"button\" class=\"list-group-item active\"\r\n          ng-click=\"$ctrl.currentDay = day.date;$ctrl.currentTab = 'daily'\">{{ \"SALAXY.ENUM.Weekday.day\" + ($index + 1) + \".label\" | sxyTranslate }} {{ day.date | date : \"d.M.\" }}</button>\r\n        <button type=\"button\" class=\"list-group-item\" ng-click=\"$ctrl.showEditDialog(occ)\"\r\n          ng-repeat=\"occ in day.occurences | limitTo: 10 \" title=\"{{ occ.shortText }}\">\r\n          <i ng-if=\"occ.data.actionId\" class=\"fa fa-bell\" aria-hidden=\"true\"></i>\r\n          <i ng-if=\"occ.data.isRecurring\" class=\"fa fa-refresh\" aria-hidden=\"true\"></i>\r\n          {{ occ.shortText }}</button>\r\n        <button type=\"button\" class=\"list-group-item\" ng-click=\"$ctrl.currentDay = day.date;$ctrl.currentTab = 'daily'\"\r\n          ng-if=\"day.occurences.length > 10\" title=\"{{ occ.shorttext }}\">+ {{ day.occurences.length - 10 }} tapahtumaa...</button>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/CalendarEventDetails-payroll.html\",`<div class=\"salaxy-component salaxy-calendar-event-details\">\r\n  <div ng-if=\"$ctrl.current\">\r\n    <div ng-if=\"!$ctrl.current.occurenceInfo.isRecurring\">\r\n      <div class=\"alert alert-info\">\r\n        <button style=\"margin-top: -7px;\" class=\"btn btn-default btn-labeled-right pull-right\" ng-click=\"$ctrl.showEditEvent()\">\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.createSchedule\"></span>\r\n          <i class=\"fa fa-calendar\"></i>\r\n        </button>\r\n        Tämä tietue ei ole ajastettu toistuvaksi\r\n      </div>\r\n      <salaxy-calendar data=\"$ctrl.current\" mapper=\"$ctrl.calendarMapper\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" today=\"$ctrl.currentDay\"\r\n        start=\"$ctrl.calendarView.start\" end=\"$ctrl.calendarView.end\"></salaxy-calendar>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current.occurenceInfo.isRecurring\">\r\n      <div class=\"btn-toolbar\">\r\n        <button class=\"btn btn-default btn-labeled-right\" ng-click=\"$ctrl.showEditEvent()\">\r\n          <span sxy-text=\"SALAXY.NG1.PayrollComponent.payrollEdit.toolbar.editSchedule\"></span>\r\n          <i class=\"fa fa-calendar\"></i>\r\n        </button>\r\n        <button type=\"button\" class=\"btn btn-danger\" ng-click=\"$ctrl.delete(null, 'Haluatko varmasti poistaa ajastuksen?')\">Poista ajastus</button>\r\n      </div>\r\n      <div ng-init=\"$ctrl.reloadPreview()\" class=\"row\">\r\n        <div class=\"col-sm-9\">\r\n          <salaxy-spinner ng-if=\"!$ctrl.preview\"></salaxy-spinner>\r\n          <salaxy-calendar data=\"$ctrl.preview\" ng-if=\"$ctrl.preview\" mapper=\"$ctrl.calendarMapper\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\"\r\n            today=\"$ctrl.currentDay\" start=\"$ctrl.preview.start\" end=\"$ctrl.preview.end\"></salaxy-calendar>\r\n        </div>\r\n        <div class=\"col-sm-3\">\r\n          <table>\r\n            <tr>\r\n              <td><i class=\"fa fa-star fa-fw event-single-day\"></i></td>\r\n              <td>Palkkalista luodaan</td>\r\n            </tr>\r\n            <tr>\r\n              <td><i class=\"fa fa-envelope fa-fw event-single-day\"></i></td>\r\n              <td>Viesti / muistutus</td>\r\n            </tr>\r\n            <tr>\r\n              <td>\r\n                <div style=\"width: 14px; background-color: #333333; margin: 1px 2px; font-size: 0.9em\">&nbsp;</div>\r\n              </td>\r\n              <td>Palkkapäivä</td>\r\n            </tr>\r\n            <tr>\r\n              <td>\r\n                <div style=\"width: 14px; background-color: #d55552; margin: 1px 2px; font-size: 0.9em\">&nbsp;</div>\r\n              </td>\r\n              <td>Tänään</td>\r\n            </tr>\r\n          </table>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <!--\r\n    <hr />\r\n    <salaxy-json-formatter key=\"'Event'\" json=\"$ctrl.current\" open=\"1\"></salaxy-json-formatter>\r\n    -->\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/CalendarEventDetails-simplified.html\",`<div class=\"salaxy-component salaxy-calendar-event-details salaxy-wizard\">\r\n  <div class=\"row wizard-icon-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\" ng-click=\"$ctrl.step = step.number\">\r\n      <span ng-show=\"step.disabled && !step.active\" class=\"salaxy-avatar disabled\">\r\n        <i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i>\r\n      </span>\r\n      <a ng-hide=\"step.disabled && !step.active\" href=\"\" ng-click=\"\">\r\n        <span class=\"salaxy-avatar\"><i class=\"fa\" ng-class=\"{'fa-circle': step.active, 'fa-circle-o': !step.active }\"><strong>{{ step.number }}</strong></i></span>\r\n      </a>\r\n    </div>\r\n  </div>\r\n  <div class=\"row wizard-text-row hidden-sm hidden-xs\">\r\n    <div ng-class=\"$ctrl.style.colWidthClass\" ng-repeat=\"step in $ctrl.steps\">\r\n      <span>{{ step.title | sxyTranslate}}</span>\r\n    </div>\r\n  </div>\r\n  <div class=\"worker-wizard-content\" style=\"min-height: 360px\">\r\n    <div ng-if=\"$ctrl.step == 1\">\r\n      <div class=\"row\">\r\n        <div class=\"col-sm-6 form-horizontal\">\r\n          <fieldset>\r\n            <legend>Toistuvuus</legend>\r\n            <salaxy-datepicker-popup ng-model=\"$ctrl.current.event.start\" name=\"start\" label=\"Palkkakauden alku\" required=\"true\"\r\n              ng-change=\"$ctrl.current.event.end = $ctrl.current.event.start\" label-cols=\"col-sm-6\">\r\n            </salaxy-datepicker-popup>\r\n            <salaxy-form-group name=\"duration\" class=\"salaxy-component salaxy-read-only\" label=\"Kesto\" label-cols=\"col-sm-6\">\r\n              <div class=\"salaxy-read-only-value\">{{ $ctrl.current.event.duration | sxyDuration }}</div>\r\n            </salaxy-form-group>\r\n            <div ng-repeat=\"rule in $ctrl.current.event.recurrenceRules track by $index\">\r\n              <salaxy-input-rrule name=\"rule{{$index}}\" ng-model=\"$ctrl.current.event.recurrenceRules[$index]\" label=\"Toistuvuus {{ $index ? ($index + 1) : '' }}\">\r\n              </salaxy-input-rrule>\r\n            </div>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <fieldset class=\"form-horizontal\">\r\n            <legend>Tapahtumat</legend>\r\n            <p>Palkkalistan luonti ja palkkapäivän määrittely tehdään suhteessa palkkakauden alkuun (päiviä ennen/jälkeen).</p>\r\n            <salaxy-input-duration ng-model=\"$ctrl.current.event.actions[0].triggerDuration\" name=\"payrollCreateDays\" label=\"{{ $ctrl.current.event.actions[0].summary }}\"\r\n              label-cols=\"col-sm-6\"></salaxy-input-duration>\r\n            <salaxy-input-duration ng-model=\"$ctrl.current.event.actions[1].triggerDuration\" name=\"payrollCreateDays\" label=\"{{ $ctrl.current.event.actions[1].summary }}\"\r\n              label-cols=\"col-sm-6\"></salaxy-input-duration>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.step == 2\">\r\n      <p class=\"lead\">\r\n        Voit määrittää muistutusviestin sähköpostilla.\r\n        Viestin lähetys määritetään päivinä palkkakauden alusta.\r\n      </p>\r\n      <salaxy-input-boolean ng-model=\"$ctrl.notificationEnabled\" type=\"switch\" label-true=\"on\" label-false=\"off\" name=\"notificationEnabled\" label=\"Muistutus sähköpostilla\">\r\n      </salaxy-input-boolean>\r\n      <div ng-if=\"$ctrl.notificationEnabled\">\r\n        <salaxy-input-duration ng-model=\"$ctrl.notification.triggerDuration\" name=\"notificationDays\" label=\"Ajastus, päiviä palkkakauden alusta\"></salaxy-input-duration>\r\n        <salaxy-input ng-model=\"$ctrl.notification.attendees[0].email\" require=\"true\" name=\"notificationEmail\" label=\"Vastaanottajan sähköposti\" sxy-email></salaxy-input>\r\n        <salaxy-input name=\"title\" label=\"Sähköpostin otsikko\" require=\"true\" ng-model=\"$ctrl.notification.summary\"></salaxy-input>\r\n        <salaxy-textarea ng-model=\"$ctrl.notification.description\" name=\"notificationText\" label=\"Muistutuksen teksti\"></salaxy-textarea>\r\n      </div>\r\n      <div ng-if=\"!$ctrl.notificationEnabled\">\r\n        <salaxy-input-number ng-model=\"none1\" name=\"notificationDays\" label=\"Ajastus, päivää ennen\" negative=\"true\" unit=\"day\" disabled=\"true\"></salaxy-input-number>\r\n        <salaxy-input ng-model=\"none2\" name=\"notificationEmail\" label=\"Vastaanottajan sähköposti\" sxy-email disabled=\"true\"></salaxy-input>\r\n        <salaxy-input name=\"title\" label=\"Sähköpostin otsikko\" ng-model=\"none3\" disabled=\"true\"></salaxy-input>\r\n        <salaxy-textarea ng-model=\"none4\" name=\"notificationText\" label=\"Muistutuksen teksti\" disabled=\"true\"></salaxy-textarea>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"$ctrl.step == 3\">\r\n      <div ng-init=\"$ctrl.reloadPreview()\" class=\"row\">\r\n        <div class=\"col-sm-9\">\r\n          <salaxy-spinner ng-if=\"!$ctrl.preview\"></salaxy-spinner>\r\n          <salaxy-calendar data=\"$ctrl.preview\" ng-if=\"$ctrl.preview\" mapper=\"$ctrl.calendarMapper\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\"\r\n            today=\"$ctrl.currentDay\" start=\"$ctrl.preview.start\" end=\"$ctrl.preview.end\"></salaxy-calendar>\r\n        </div>\r\n        <div class=\"col-sm-3\">\r\n          <table>\r\n            <tr>\r\n              <td><i class=\"fa fa-file fa-fw event-single-day text-warning\"></i></td>\r\n              <td>Palkkalista luodaan heti</td>\r\n            </tr>\r\n            <tr>\r\n              <td><i class=\"fa fa-file fa-fw event-single-day text-info\"></i></td>\r\n              <td>...luodaan ajastuksella</td>\r\n            </tr>\r\n            <tr>\r\n              <td><i class=\"fa fa-envelope fa-fw event-single-day text-warning\"></i></td>\r\n              <td>Viesti / muistutus heti</td>\r\n            </tr>\r\n            <tr>\r\n              <td><i class=\"fa fa-envelope fa-fw event-single-day text-info\"></i></td>\r\n              <td>...ajastuksella</td>\r\n            </tr>\r\n            <tr>\r\n              <td>\r\n                <div style=\"width: 14px; background-color: #009fd8; margin: 1px 2px; font-size: 0.9em\">&nbsp;</div>\r\n              </td>\r\n              <td>Palkkapäivä</td>\r\n            </tr>\r\n            <tr>\r\n              <td>\r\n                <div style=\"width: 14px; background-color: #d55552; margin: 1px 2px; font-size: 0.9em\">&nbsp;</div>\r\n              </td>\r\n              <td>Tänään</td>\r\n            </tr>\r\n          </table>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <!--\r\n      <salaxy-json-formatter key=\"'Event'\" json=\"$ctrl.current\" open=\"1\"></salaxy-json-formatter>\r\n    -->\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/CalendarEventDetails.html\",`<div class=\"salaxy-component salaxy-calendar-event-details\">\r\n  <uib-tabset active=\"$ctrl.currentDetailsTab\" style=\"min-height: 360px\" ng-if=\"$ctrl.current\">\r\n    <uib-tab index=\"'basic'\" heading=\"Perustiedot\">\r\n      <div class=\"row\">\r\n        <div class=\"col-sm-6 form-horizontal\">\r\n          <fieldset>\r\n            <legend>Tapahtuma-aika</legend>\r\n            <salaxy-datepicker-popup ng-model=\"$ctrl.current.event.start\" name=\"start\" label=\"Alku\" required=\"true\" ng-change=\"$ctrl.current.event.end = $ctrl.current.event.start\">\r\n            </salaxy-datepicker-popup>\r\n            <salaxy-datepicker-popup ng-model=\"$ctrl.current.event.end\" name=\"end\" label=\"Loppu\" ng-change=\"$ctrl.current.event.duration = null\" min-date=\"$ctrl.current.event.start\"></salaxy-datepicker-popup>\r\n            <salaxy-form-group name=\"duration\" class=\"salaxy-component salaxy-read-only\" label=\"Kesto\">\r\n              <div class=\"salaxy-read-only-value\">{{ $ctrl.getEventDuration() }}</div>\r\n            </salaxy-form-group>\r\n            <div class=\"alert alert-warning\" ng-if=\"!$ctrl.current.event.isAllDay\">\r\n              Kalenteritapahtuma määrittää kellonaikoja. Tämä käyttöliittymä on suunniteltu vain koko päivän kestäviin tapahtumiin ja muokkaukset saattavat johtaa virheellisiin tuloksiin.\r\n            </div>\r\n          </fieldset>\r\n          <fieldset>\r\n            <legend>Lisätietoja</legend>\r\n            <salaxy-input-enum name=\"status\" enum=\"CalendarEventStatus\" ng-model=\"$ctrl.current.event.status\" label=\"Status\" read-only=\"true\"></salaxy-input-enum>\r\n            <salaxy-form-group name=\"categories\" class=\"salaxy-component salaxy-read-only\" label=\"Kategoriat\">\r\n              <div class=\"salaxy-read-only-value\">\r\n                <div ng-repeat=\"cat in $ctrl.current.event.categories\"><span>{{ cat + ($last ? \"\" : \", \") }}</span></div>\r\n                <div ng-if=\"!$ctrl.current.event.categories.length\">-</div>\r\n              </div>\r\n            </salaxy-form-group>\r\n            <salaxy-input-number name=\"priority\" ng-model=\"$ctrl.current.event.priority\" label=\"Prioriteetti\" read-only=\"true\"></salaxy-input-number>\r\n          </fieldset>\r\n        </div>\r\n        <div class=\"col-sm-6\">\r\n          <fieldset class=\"form-horizontal\">\r\n            <legend>Kuvaus</legend>\r\n            <salaxy-input ng-model=\"$ctrl.current.event.summary\" name=\"summary\" required=\"true\" label=\"Lyhyt kuvaus\"></salaxy-input>\r\n            <salaxy-textarea ng-model=\"$ctrl.current.event.description\" name=\"description\" label=\"Kuvaus\" rows=\"5\" label-type=\"basic\"></salaxy-textarea>\r\n          </fieldset>\r\n        </div>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'recurrence'\" heading=\"Toistuvuus ({{ $ctrl.current.event.recurrenceRules.length || 'ei toistu' }})\">\r\n      <p class=\"lead\">\r\n        <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.addRecurrenceRule()\">Lisää sääntö</button> Voit määrittää tapahtumalle toistuvuussääntöjä: Esim. kuukausittain, viikottain jne. Toistuvuus perustuu alkupäivämäärään <strong>{{ $ctrl.current.event.start | sxyDate }}</strong>        aivan kuten Outlookissa tai Google kalenterissa.\r\n      </p>\r\n      <fieldset ng-repeat=\"rule in $ctrl.current.event.recurrenceRules track by $index\">\r\n        <legend>\r\n          <button ng-click=\"$ctrl.deleteRecurrence($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n            <i class=\"fa fa-trash\"></i>\r\n          </button> Toistuvuus {{ $index + 1 }}\r\n        </legend>\r\n        <salaxy-input ng-model=\"$ctrl.current.event.recurrenceRules[$index]\" name=\"rule{{$index}}\" required=\"true\" label=\"iCalendar sääntö (rrule)\"></salaxy-input>\r\n      </fieldset>\r\n    </uib-tab>\r\n    <uib-tab index=\"'actions'\" heading=\"Tehtävät / ilmoitukset ({{ $ctrl.current.event.actions.length || 0 }})\">\r\n      <p class=\"lead\">\r\n        <button type=\"button\" class=\"btn btn-primary pull-right\" ng-click=\"$ctrl.addAction()\">Lisää tehtävä / muistutus</button> Voit määrittää sähköpostihälytyksiä tai notifikaatioita tapahtumalle. Samoin voit määrittää, että laskelma tai palkkalista\r\n        luodaan tiettynä aikana. Säännöt määritetään päivinä ennen tai jälkeen alkupäivän <strong>{{ $ctrl.current.event.start | sxyDate }}</strong> (+ mahd. toistuvuus).\r\n      </p>\r\n      <fieldset ng-repeat=\"action in $ctrl.current.event.actions | orderBy: 'triggerDuration'\" class=\"form-horizontal\" ng-switch=\"action.type\">\r\n        <div class=\"row\">\r\n          <div class=\"col-xs-2 text-center\">\r\n            <div style=\"font-size:5em; font-weight: bold\">{{ $index + 1 }}.</div>\r\n          </div>\r\n          <div ng-switch-when=\"createItem\" class=\"col-xs-10\">\r\n            <legend>\r\n              <button ng-click=\"$ctrl.deleteAction($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n                <i class=\"fa fa-trash\"></i>\r\n              </button> Tietue syntyy\r\n            </legend>\r\n            <salaxy-input-enum name=\"boType\" enum=\"ApiItemType\" ng-model=\"$ctrl.current.bo.type\" label=\"Tyyppi\"></salaxy-input-enum>\r\n            <div ng-switch=\"$ctrl.current.bo.type || 'undefined'\">\r\n              <div ng-switch-when=\"undefined\">\r\n                <div class=\"alert alert-info\">\r\n                  Luodaksesi uuden tietueen ajastetusti, valitse tietueen tyyppi.\r\n                </div>\r\n              </div>\r\n              <div ng-switch-when=\"calculation|calculationPaid\" ng-switch-when-separator=\"|\">\r\n                <div class=\"alert alert-info\">\r\n                  Laskelmasta tehdään kopio ja alkupäivämäärästä (+toistuvuus) tulee uuden laskelman palkkapäivä. Valitse laskelma alta.\r\n                </div>\r\n                <salaxy-form-group name=\"start\" class=\"salaxy-component salaxy-read-only\" label=\"Malli (template)\">\r\n                  <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.selectBo()\">Valitse...</button>\r\n                </salaxy-form-group>\r\n                <salaxy-input ng-model=\"$ctrl.current.bo.id\" name=\"boId\" required=\"true\" label=\"Template ID\" read-only=\"true\"></salaxy-input>\r\n                <salaxy-input-number name=\"duration\" ng-model=\"action.triggerDuration\" label=\"Luodaan päivää ennen\" unit=\"day\" negative=\"true\"></salaxy-input-number>\r\n              </div>\r\n              <div ng-switch-when=\"payrollDetails\">\r\n                <div class=\"alert alert-info\">\r\n                  Palkkalistan voit ajastaa Palkkalistat-osiosta => Uusi palkkalista.\r\n                </div>\r\n                <salaxy-input ng-model=\"$ctrl.current.bo.id\" name=\"boId\" required=\"true\" label=\"Template ID\" read-only=\"true\"></salaxy-input>\r\n                <salaxy-input-number name=\"duration\" ng-model=\"action.triggerDuration\" label=\"Luodaan päivää ennen\" unit=\"day\" negative=\"true\"></salaxy-input-number>\r\n              </div>\r\n              <div class=\"alert alert-info\" ng-switch-default>\r\n                Näiden tietueiden ajastaminen on tulossa vast myöhemmin syksyllä. Kerro meille mikä käyttötapauksesi on, jotta osaamme kehittää toiminnallisuutta pidemmälle.\r\n              </div>\r\n            </div>\r\n          </div>\r\n          <div ng-switch-when=\"email\" class=\"col-xs-10\">\r\n            <legend>\r\n              <button ng-click=\"$ctrl.deleteAction($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n                <i class=\"fa fa-trash\"></i>\r\n              </button> Sähköpostin lähetys\r\n            </legend>\r\n            <salaxy-input-enum name=\"type\" enum=\"CalendarActionType\" ng-model=\"action.type\" label=\"Tyyppi\" hidden-options=\"undefined,createItem,audio\"></salaxy-input-enum>\r\n            <salaxy-input-boolean name=\"isAfter\" ng-model=\"action.triggerIsAfterTemp\" ng-init=\"action.triggerIsAfterTemp = action.triggerDuration > 0\" ng-change=\"action.triggerDuration = action.triggerDuration * -1\" type=\"radio\" label=\"Ennen vai jälkeen\" label-true=\"Jälkeen\"\r\n              label-false=\"Ennen\">\r\n            </salaxy-input-boolean>\r\n            <salaxy-input-number name=\"duration\" ng-model=\"action.triggerDuration\" label=\"Päiviä {{ action.triggerIsAfterTemp ? ' jälkeen' : ' ennen' }}\" unit=\"day\" negative=\"!action.triggerIsAfterTemp\"></salaxy-input-number>\r\n            <!--\r\n                TODO: Ei vaikuta toimivan. Fiksaa tai poista mallista.\r\n                <salaxy-input-number name=\"repeat\" ng-model=\"action.repeat\" label=\"Toistuu (kpl)\"></salaxy-input-number>\r\n              -->\r\n            <salaxy-input name=\"title\" label=\"Sähköpostin otsikko\" require=\"true\" ng-model=\"action.summary\"></salaxy-input>\r\n            <salaxy-textarea ng-model=\"action.description\" name=\"notificationText\" label=\"Sisältöteksti\"></salaxy-textarea>\r\n            <salaxy-input ng-model=\"action.attendees[0].email\" name=\"notificationEmail\" label=\"Vastaanottajan sähköposti\" sxy-email></salaxy-input>\r\n          </div>\r\n          <div ng-switch-when=\"display\" class=\"col-xs-10\">\r\n            <legend>\r\n              <button ng-click=\"$ctrl.deleteAction($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n                <i class=\"fa fa-trash\"></i>\r\n              </button> Notifikaatio\r\n            </legend>\r\n            <div class=\"alert alert-info\">\r\n              <strong>HUOM: </strong> Tässä vaiheessa muistutukset tulevat aina tilitoimistolle / palkanlaskijalle. Loppuvuonna julkaistavassa versiossa on tarkoitus mahdollistaa notifikaation kohteen valinta (yritys, työntekijä jne.)\r\n            </div>\r\n            <salaxy-input-enum name=\"type\" enum=\"CalendarActionType\" ng-model=\"action.type\" label=\"Tyyppi\" hidden-options=\"undefined,createItem,audio\"></salaxy-input-enum>\r\n            <salaxy-input-boolean name=\"isAfter\" ng-model=\"action.triggerIsAfterTemp\" ng-init=\"action.triggerIsAfterTemp = action.triggerDuration > 0\" ng-change=\"action.triggerDuration = action.triggerDuration * -1\" type=\"radio\" label=\"Ennen vai jälkeen\" label-true=\"Jälkeen\"\r\n              label-false=\"Ennen\">\r\n            </salaxy-input-boolean>\r\n            <salaxy-input-number name=\"duration\" ng-model=\"action.triggerDuration\" label=\"Päiviä {{ action.triggerIsAfterTemp ? ' jälkeen' : ' ennen' }}\" unit=\"day\" negative=\"!action.triggerIsAfterTemp\"></salaxy-input-number>\r\n            <salaxy-input-number name=\"repeat\" ng-model=\"action.repeat\" label=\"Toistuu (kpl)\"></salaxy-input-number>\r\n            <salaxy-textarea ng-model=\"action.description\" name=\"notificationText\" label=\"Muistutuksen teksti\"></salaxy-textarea>\r\n          </div>\r\n          <div ng-switch-when=\"script\" class=\"col-xs-10\">\r\n            <legend>\r\n              <button ng-click=\"$ctrl.deleteAction($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n                <i class=\"fa fa-trash\"></i>\r\n              </button> Skripti\r\n            </legend>\r\n            <salaxy-input-enum name=\"type\" enum=\"CalendarActionType\" ng-model=\"action.type\" label=\"Tyyppi\" hidden-options=\"undefined,createItem,audio\"></salaxy-input-enum>\r\n            <div class=\"alert alert-danger\">\r\n              <strong>HUOM: </strong> Skriptit ovat rajatussa testikäytössä. Ota yhteyttä asiakaspalveluun, jos tarvitse skriptejä.\r\n            </div>\r\n          </div>\r\n          <div ng-switch-default>\r\n            <legend>\r\n              <button ng-click=\"$ctrl.deleteAction($index)\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\" class=\"btn btn-danger btn-sm pull-right\">\r\n                <i class=\"fa fa-trash\"></i>\r\n              </button> Tehtävätyyppi ei tuettu\r\n            </legend>\r\n            <div class=\"alert alert-danger\">\r\n              Tehtävätyyppi ei tuettu: {{ \"CalendarActionType.\" + action.type | sxyEnum }}\r\n            </div>\r\n            <salaxy-input-enum name=\"type\" enum=\"CalendarActionType\" ng-model=\"action.type\" label=\"Tyyppi\"></salaxy-input-enum>\r\n          </div>\r\n        </div>\r\n      </fieldset>\r\n    </uib-tab>\r\n    <uib-tab index=\"'preview'\" heading=\"Esikatselu\">\r\n      <div ng-if=\"$ctrl.currentDetailsTab == 'preview'\" ng-init=\"$ctrl.reloadPreview()\">\r\n        <salaxy-spinner ng-if=\"!$ctrl.preview\"></salaxy-spinner>\r\n        <salaxy-calendar data=\"$ctrl.preview\" ng-if=\"$ctrl.preview\" mapper=\"$ctrl.calendarMapper\" on-list-select=\"$ctrl.calendarClick(type, date, calEvent)\" today=\"$ctrl.currentDay\" start=\"$ctrl.preview.start\" end=\"$ctrl.preview.end\"></salaxy-calendar>\r\n      </div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'attendees'\" heading=\"Henkilöt ({{ $ctrl.current.event.attendees.length || '-' }})\" disable=\"!$ctrl.current.event.attendees.length\">\r\n      <ul class=\"list-group\">\r\n        <li ng-repeat=\"avatar in $ctrl.current.event.attendees\" class=\"list-group-item\">\r\n          <salaxy-avatar style=\"font-size: 3em\" class=\"pull-left\" avatar=\"avatar\"></salaxy-avatar>\r\n          <div>{{ avatar.displayName }}</div>\r\n          <div><a ng-if=\"avatar.email\" ng-href=\"{{'mailto:' + avatar.email}}\" target=\"_blank\">{{ avatar.email }}</a></div>\r\n        </li>\r\n      </ul>\r\n      <div ng-if=\"!$ctrl.current.event.attendees.length\">Ei henkilöitä</div>\r\n    </uib-tab>\r\n    <uib-tab index=\"'attachments'\" heading=\"Liitteet ({{ $ctrl.current.event.attachments.length || '-' }})\" disable=\"!$ctrl.current.event.attachments.length\">\r\n      <ul>\r\n        <li ng-repeat=\"attach in $ctrl.current.event.attachments\">TODO: {{ attach.uri || attach.formatType || attach.valueEncoding }}</li>\r\n      </ul>\r\n    </uib-tab>\r\n    <uib-tab index=\"'debug'\" heading=\"Debug\">\r\n      <salaxy-json-formatter key=\"'Event'\" json=\"$ctrl.current\" open=\"1\"></salaxy-json-formatter>\r\n    </uib-tab>\r\n  </uib-tabset>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/dataset/DatasetDetails.html\",`<div class=\"salaxy-component salaxy-dataset-details\" ng-switch=\"$ctrl.getMode()\">\r\n  <salaxy-spinner ng-switch-when=\"loading\"></salaxy-spinner>\r\n  <div ng-switch-when=\"usecase\">\r\n    <div ng-if=\"$ctrl.usecase && !$ctrl.usecase.defaultView\" class=\"alert alert-danger\">\r\n      ERROR: This usecase {{ $ctrl.usecase.uri }} does not have user interface (view) defined.\r\n    </div>\r\n    <div ng-if=\"$ctrl.usecase.defaultView\">\r\n      <ng-include src=\"$ctrl.usecase.defaultView\"></ng-include>\r\n    </div>\r\n  </div>\r\n  <div ng-switch-when=\"data-edit\">\r\n    <ng-include src=\"'salaxy-components/workflow/dataset/DatasetDetails_data.html'\"></ng-include>\r\n  </div>\r\n  <div ng-switch-when=\"full-edit\">\r\n    <ng-include src=\"'salaxy-components/workflow/dataset/DatasetDetails_full.html'\"></ng-include>\r\n  </div>\r\n  <div ng-switch-default class=\"alert alert-danger\">ERROR: Unable to load Dataset</div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/dataset/DatasetDetails_data.html\",`<div>\r\n  <div class=\"btn-toolbar\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </button>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <div class=\"form-inline\">\r\n        <div class=\"form-group\" style=\"line-height: 34px;\">\r\n          <strong> &nbsp; Nimi:</strong> {{$ctrl.current.info.label}}\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn\" ng-class=\"'btn-' + (action.uiColor || 'default')\" ng-repeat=\"action in $ctrl.usecase.actions\" ng-click=\"$ctrl.executeAction(action)\">{{\r\n        action.uiText }}</button>\r\n    </div>\r\n  </div>\r\n  <div style=\"height: calc(100vh - 200px);\" class=\"form-horizontal\">\r\n    <style>\r\n      /* TODO: Move to less */\r\n      .salaxy-tab-height100 {\r\n        height: 100%;\r\n      }\r\n\r\n      .salaxy-tab-height100 .tab-content {\r\n        height: calc(100% - 43px);\r\n      }\r\n\r\n      .salaxy-tab-height100 .tab-pane {\r\n        height: 100%;\r\n      }\r\n    </style>\r\n    <uib-tabset class=\"salaxy-tab-height100\">\r\n      <uib-tab ng-repeat=\"table in $ctrl.current.data\" heading=\"{{ table.label || table.name }}\">\r\n        <div class=\"height100\">\r\n          <sxy-grid ng-if=\"$ctrl.getSchamaDef($index)\" data=\"$ctrl.current.data[$index].content\" schema-def=\"$ctrl.getSchamaDef($index)\" schema=\"{{$ctrl.current.data[$index].schema}}\" ng-ref=\"grid\"></sxy-grid>\r\n        </div>\r\n      </uib-tab>\r\n    </uib-tabset>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/dataset/DatasetDetails_full.html\",`<div>\r\n  <div class=\"btn-toolbar\" style=\"margin-left: 195px; margin-bottom: 2px;\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n      <button class=\"btn btn-default\" ng-click=\"$ctrl.reload()\"><i class=\"fa fa-refresh\" aria-hidden=\"true\"></i></button>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.addDataObject()\" sxy-text=\"Lisää dataobjekti\"></button>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <div class=\"form-inline\">\r\n        <div class=\"form-group\" style=\"line-height: 34px;\">\r\n          <strong> &nbsp; Nimi:</strong> {{$ctrl.current.info.label}}\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn\" ng-class=\"'btn-' + (action.uiColor || 'default')\" ng-repeat=\"action in $ctrl.usecase.actions\" ng-click=\"$ctrl.executeAction(action)\">{{ action.uiText }}</button>\r\n    </div>\r\n    <div class=\"btn-group pull-right\">\r\n      <button type=\"button\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly\" ng-click=\"$ctrl.delete($ctrl.current)\"\r\n        sxy-text=\"SALAXY.UI_Terms.delete\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\">\r\n    </div>\r\n  </div>\r\n  <div ng-init=\"$ctrl.currentSection = 'basicInfo'\" style=\"display: flex\">\r\n    <div style=\"flex: 0 0 200px;\">\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'basicInfo'\" ng-class=\"$ctrl.currentSection == 'basicInfo' ? 'btn-primary' : 'btn-default'\"\r\n        ng-model=\"$ctrl.currentSection\">Perustiedot</label>\r\n      <div style=\"margin-top: 8px;\">Dataobjektit:</div>\r\n      <label class=\"btn btn-block\" ng-repeat=\"table in $ctrl.current.data\" uib-btn-radio=\"'table' + $index\"\r\n        ng-class=\"$ctrl.currentSection == ('table' + $index) ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">{{ table.label }}</label>\r\n      <div>&nbsp;</div>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'debugger'\" ng-class=\"$ctrl.currentSection == 'debugger' ? 'btn-primary' : 'btn-default'\"\r\n        ng-model=\"$ctrl.currentSection\">Debugger</label>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current\" style=\"flex: 1 1 100%;margin-left: -1px; height: calc(100vh - 200px); overflow-y: auto; border: solid 1px #009fd8; padding: 10px;\">\r\n      <div ng-if=\"$ctrl.currentSection == 'basicInfo'\" class=\"form-horizontal\">\r\n        <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"Dataset\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n          <div class=\"row\">\r\n            <div class=\"col-sm-6\">\r\n              <fieldset>\r\n                <legend>Perustiedot</legend>\r\n                <sxy-input label=\"Id\" model=\"form.id\"></sxy-input>\r\n                <sxy-input label=\"Nimi\" model=\"form.info.label\"></sxy-input>\r\n                <sxy-input label=\"Status\" model=\"form.info.status\"></sxy-input>\r\n                <sxy-input label=\"Tyyppi\" model=\"form.info.type\"></sxy-input>\r\n              </fieldset>\r\n            </div>\r\n            <div class=\"col-sm-6\">\r\n              <fieldset>\r\n                <legend>Räätälöinti</legend>\r\n                <div ng-if=\"$ctrl.usecase == 'none'\">\r\n                  <salaxy-input-enum label=\"Valitse räätälöinti\" ng-if=\"$ctrl.usecases\" name=\"uri\" ng-model=\"$ctrl.current.usecase.uri\" options=\"$ctrl.usecases\"></salaxy-input-enum>\r\n                  <div ng-if=\"!$ctrl.current.usecase.uri\" class=\"alert alert-danger\">\r\n                    Tälle datasetille ei ole määritetty räätälöintiä (datamalli ja toiminnallisuudet).\r\n                  </div>\r\n                  <div ng-if=\"$ctrl.current.usecase.uri\" class=\"alert alert-info\">\r\n                    <p>\r\n                      Räätälöintiä ei löytynyt tai ei vielä ladattu (tallenna ladataksesi): {{ $ctrl.current.usecase.uri }}\r\n                    </p>\r\n                  </div>\r\n                </div>\r\n                <div ng-if=\"$ctrl.usecase != 'none'\">\r\n                  <p><strong>URI:</strong> <code>{{ $ctrl.current.usecase.uri }}</code></p>\r\n                  <sxy-input label=\"Nimi\" model=\"form.usecase.label\" read-only=\"true\"></sxy-input>\r\n                  <sxy-input label=\"Kuvaus\" model=\"form.usecase.description\" read-only=\"true\"></sxy-input>\r\n                  <salaxy-form-group name=\"btnEdit\" label=\"Muokkaa\">\r\n                    <a ng-href=\"#/usecases/details/{{ $ctrl.usecase.id }}@{{ $ctrl.usecase.owner }}\" target=\"_blank\" ng-disabled=\"!$ctrl.usecase || $ctrl.usecase.isReadOnly\"\r\n                      class=\"btn btn-default btn-sm\">Muokkaa (uuteen ikkunaan)...</a>\r\n                  </salaxy-form-group>\r\n                  <salaxy-json-formatter json=\"$ctrl.usecase\" key=\"'Yksityiskohdat...'\" open=\"0\"></salaxy-json-formatter>\r\n                </div>\r\n              </fieldset>\r\n            </div>\r\n          </div>\r\n        </sxy-form>\r\n      </div>\r\n      <div ng-repeat=\"dataObj in $ctrl.current.data\" ng-if=\"$ctrl.currentSection == ('table' + $index)\" class=\"height100 form-horizontal\">\r\n        <style>\r\n          /* TODO: Move to less */\r\n          .salaxy-tab-height100 {\r\n            height: 100%;\r\n          }\r\n\r\n          .salaxy-tab-height100 .tab-content {\r\n            height: calc(100% - 43px);\r\n          }\r\n\r\n          .salaxy-tab-height100 .tab-pane {\r\n            height: 100%;\r\n          }\r\n        </style>\r\n        <uib-tabset class=\"salaxy-tab-height100\">\r\n          <uib-tab heading=\"Grid\" index=\"'grid'\">\r\n            <div style=\"height: 100%\">\r\n              <sxy-grid data=\"dataObj.content\" schema-def=\"$ctrl.getSchamaDef($index)\"\r\n                schema=\"{{$ctrl.current.data[$index].schema}}\"\r\n                include=\"dataObj.views[0].include\"\r\n                exclude=\"dataObj.views[0].exclude\"></sxy-grid>\r\n            </div>\r\n          </uib-tab>\r\n          <uib-tab heading=\"Ominaisuudet\" index=\"'properties'\">\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-6\">\r\n                <salaxy-input label=\"Label\" name=\"label\" ng-model=\"dataObj.label\"></salaxy-input>\r\n                <salaxy-input label=\"Technical name\" name=\"name\" ng-model=\"dataObj.name\"></salaxy-input>\r\n                <salaxy-form-group name=\"btnDeleteIndex\" label=\"Remove\">\r\n                  <button type=\"button\" ng-click=\"$ctrl.deleteObject($index)\" class=\"btn btn-danger btn-sm\" ng-disabled=\"$ctrl.usecase.isReadOnly\">Remove object</button>\r\n                </salaxy-form-group>\r\n              </div>\r\n              <div class=\"col-sm-6\">\r\n                <salaxy-input-enum label=\"Schema document\" name=\"schemaDoc\" ng-model=\"dataObj.schemaDoc\" disable-cache=\"true\"\r\n                  options=\"$ctrl.getSchemaDocs()\"></salaxy-input-enum>\r\n                <salaxy-input-enum label=\"Schema\" name=\"schema\" ng-model=\"dataObj.schema\" disable-cache=\"true\"\r\n                  type=\"typeahead\"\r\n                  options=\"$ctrl.getSchemas(dataObj.schemaDoc)\" disabled=\"(dataObj.schemaDoc || 'any') == 'any'\"></salaxy-input-enum>\r\n                <!-- TODO: isArray -->\r\n              </div>\r\n            </div>\r\n            <div class=\"row\">\r\n              <div class=\"col-sm-6\">\r\n                <fieldset>\r\n                  <legend>Include fields (default view)</legend>\r\n                  <ul class=\"list-group\">\r\n                    <li class=\"list-group-item\" ng-repeat=\"incl in dataObj.views[0].include track by $index\">\r\n                      {{ incl }}\r\n                      <div class=\"pull-right\">\r\n                        <button class=\"btn btn-primary btn-xs\" title=\"Move up\" ng-click=\"$ctrl.arraymove($ctrl.current.data[$parent.$index].views[0].include, $index, -1)\">&#9650;</button>\r\n                        <button class=\"btn btn-primary btn-xs\" title=\"Move down\" ng-click=\"$ctrl.arraymove($ctrl.current.data[$parent.$index].views[0].include, $index, +1)\">&#9660;</button>\r\n                        <button class=\"btn btn-default btn-xs\" title=\"Delete\" ng-click=\"$ctrl.current.data[$parent.$index].views[0].include.splice($index, 1)\">&#10060;</button>\r\n                      </div>\r\n                    </li>\r\n                    <li class=\"list-group-item\" ng-if=\"!dataObj.views[0].include.length\">No rows selected: All columns</li>\r\n                  </ul>\r\n                  <div style=\"display: inline-block;\">\r\n                    <salaxy-input-enum label=\"Add new property\" name=\"addProp\" label-type=\"plain\"\r\n                      ng-model=\"$ctrl.tempNewProperty\" disable-cache=\"true\"\r\n                      ng-change=\"$ctrl.addViewItem($index, 'include', $ctrl.tempNewProperty);$ctrl.tempNewProperty=null\"\r\n                      type=\"typeahead\" options=\"$ctrl.getAllPropertiesOfSchema($index)\"></salaxy-input-enum>\r\n                  </div>\r\n                  <button type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.addViewItem($index, 'include', $ctrl.tempNewProperty);$ctrl.tempNewProperty=null\">Add</button>\r\n                </fieldset>\r\n              </div>\r\n              <div class=\"col-sm-6\">\r\n                <fieldset>\r\n                  <legend>Exclude fields (default view)</legend>\r\n                  <ul class=\"list-group\">\r\n                    <li class=\"list-group-item\" ng-repeat=\"incl in dataObj.views[0].exclude track by $index\">\r\n                      {{ incl }}\r\n                      <div class=\"pull-right\">\r\n                        <button class=\"btn btn-primary btn-xs\" title=\"Move up\" ng-click=\"$ctrl.arraymove($ctrl.current.data[$parent.$index].views[0].exclude, $index, -1)\">&#9650;</button>\r\n                        <button class=\"btn btn-primary btn-xs\" title=\"Move down\" ng-click=\"$ctrl.arraymove($ctrl.current.data[$parent.$index].views[0].exclude, $index, +1)\">&#9660;</button>\r\n                        <button class=\"btn btn-default btn-xs\" title=\"Delete\" ng-click=\"$ctrl.current.data[$parent.$index].views[0].exclude.splice($index, 1)\">&#10060;</button>\r\n                      </div>\r\n                    </li>\r\n                    <li class=\"list-group-item\" ng-if=\"!dataObj.views[0].exclude.length\">No rows selected: All columns</li>\r\n                  </ul>\r\n                  <div style=\"display: inline-block;\">\r\n                    <salaxy-input-enum label=\"Add new property\" name=\"addProp\" label-type=\"plain\"\r\n                      ng-model=\"$ctrl.tempNewProperty\" disable-cache=\"true\"\r\n                      ng-change=\"$ctrl.addViewItem($index, 'exclude', $ctrl.tempNewProperty);$ctrl.tempNewProperty=null\"\r\n                      type=\"typeahead\" options=\"$ctrl.getAllPropertiesOfSchema($index)\"></salaxy-input-enum>\r\n                  </div>\r\n                  <button type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"$ctrl.addViewItem($index, 'exclude', $ctrl.tempNewProperty);$ctrl.tempNewProperty=null\">Add</button>\r\n                </fieldset>\r\n              </div>\r\n            </div>\r\n          </uib-tab>\r\n          <uib-tab heading=\"Validation\" index=\"'validation'\">\r\n            <p>TODO: Validation</p>\r\n          </uib-tab>\r\n        </uib-tabset>\r\n      </div>\r\n      <div ng-if=\"$ctrl.currentSection == 'debugger'\">\r\n        <salaxy-json-formatter json=\"$ctrl.current\" key=\"'Data'\" open=\"1\"></salaxy-json-formatter>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/usecases/UsecaseDetails.html\",`<main class=\"salaxy-content sxytpl-usecases-details\">\r\n  <div class=\"btn-toolbar\" style=\"margin-left: 195px; margin-bottom: 2px;\">\r\n    <div class=\"btn-group\">\r\n      <button type=\"button\" class=\"btn btn-primary\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly\" ng-click=\"$ctrl.save()\" sxy-text=\"SALAXY.UI_Terms.save\"></button>\r\n      </button>\r\n      <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.showCopyAsNew($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.copyAsNew\"></button>\r\n      <button class=\"btn btn-default\" ng-click=\"$ctrl.reload()\"><i class=\"fa fa-refresh\" aria-hidden=\"true\"></i></button>\r\n    </div>\r\n    <div class=\"btn-group pull-right\">\r\n      <button type=\"button\" class=\"btn btn-danger\" ng-disabled=\"!$ctrl.current || $ctrl.current.isReadOnly\" ng-click=\"$ctrl.delete($ctrl.current)\" sxy-text=\"SALAXY.UI_Terms.delete\" title=\"{{ 'SALAXY.UI_Terms.delete' | sxyTranslate}}\"></div>\r\n    <div class=\"btn-group\">\r\n      <div class=\"form-inline\">\r\n        <div class=\"form-group\" style=\"line-height: 34px;\">\r\n          <strong> &nbsp; Nimi:</strong> {{$ctrl.current.label}}\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n  <div ng-init=\"$ctrl.currentSection = 'basicInfo'\" style=\"display: flex\">\r\n    <div style=\"flex: 0 0 200px;\">\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'basicInfo'\" ng-class=\"$ctrl.currentSection == 'basicInfo' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Perustiedot</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'schemas'\" ng-class=\"$ctrl.currentSection == 'dataModel' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Datamalli</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'scripts'\" ng-class=\"$ctrl.currentSection == 'scripts' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Skriptit</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'schema'\" ng-class=\"$ctrl.currentSection == 'schema' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Schema</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'views'\" ng-class=\"$ctrl.currentSection == 'views' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Käyttöliittymä</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'tester'\" ng-class=\"$ctrl.currentSection == 'tester' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Testaa</label>\r\n      <label class=\"btn btn-block\" uib-btn-radio=\"'debugger'\" ng-class=\"$ctrl.currentSection == 'debugger' ? 'btn-primary' : 'btn-default'\" ng-model=\"$ctrl.currentSection\">Debugger</label>\r\n    </div>\r\n    <div ng-if=\"$ctrl.current\" style=\"flex: 1 1 100%;margin-left: -1px; height: calc(100vh - 200px); overflow-y: auto; border: solid 1px #009fd8; padding: 10px;\">\r\n      <div ng-if=\"$ctrl.currentSection == 'basicInfo'\" class=\"form-horizontal\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6\">\r\n            <sxy-form open-api=\"salaxy-secure/schemas/v02.json\" type=\"Usecase\" auto-gen=\"false\" debugger=\"false\" model=\"$ctrl.current\">\r\n              <div>\r\n                <fieldset>\r\n                  <legend>Perustiedot</legend>\r\n                  <p ng-if=\"$ctrl.current.id\"><strong>URI:</strong> <code>{{ $ctrl.current.uri }}</code></p>\r\n                  <sxy-input label=\"Id\" model=\"form.id\"></sxy-input>\r\n                  <sxy-input label=\"Nimi\" model=\"form.label\"></sxy-input>\r\n                  <sxy-input label=\"Kuvaus\" model=\"form.description\"></sxy-input>\r\n                  <sxy-input label=\"Ikoni / kuva\" model=\"form.icon\"></sxy-input>\r\n                  <sxy-input label=\"Objektin tyyppi\" model=\"form.itemType\"></sxy-input>\r\n                  <sxy-input label=\"Tila\" model=\"form.status\"></sxy-input>\r\n                  <sxy-input label=\"Järjestysnumero\" model=\"form.order\"></sxy-input>\r\n                </fieldset>\r\n              </div>\r\n            </sxy-form>\r\n          </div>\r\n          <div class=\"col-sm-6 col-md-4\">\r\n            <fieldset>\r\n              <legend>Perustietojen esikatselu</legend>\r\n              <div class=\"thumbnail\">\r\n                <div class=\"text-center thumbnail-pic-fixed\" style=\"height: 150px;\">\r\n                  <img ng-if=\"$ctrl.current.icon[0] == 'h'\" ng-src=\"{{$ctrl.current.icon}}\">\r\n                  <div ng-if=\"$ctrl.current.icon[0] != 'h'\" class=\"bg-primary thumbnail-pic-icon\">\r\n                    <i class=\"fa\" ng-class=\"($ctrl.current.icon || 'fa') == 'fa' ? 'fa-euro' : $ctrl.current.icon\" aria-hidden=\"true\"></i>\r\n                  </div>\r\n                  <span class=\"badge pull-right\" ng-class=\"$ctrl.getStatusBgColor($ctrl.current.status)\">{{ \"UsecaseStatus.\" + $ctrl.current.status | sxyEnum }}</span>\r\n                </div>\r\n                <div class=\"caption\">\r\n                  <h3 class=\"truncate\">{{ $ctrl.current.label }}</h3>\r\n                  <p style=\"height: 80px;overflow: hidden\">{{ $ctrl.current.description }}</p>\r\n                  <p>\r\n                    <a ng-href=\"#/calc/usecase/new?usecase=%2FUsecaseDefinition%2F{{ $ctrl.current.owner }}%2F{{ $ctrl.current.id }}\" class=\"btn btn-primary\" role=\"button\" style=\"color: white\" sxy-text=\"SALAXY.UI_Terms.createNew\" ps=\"...\"></a>\r\n                  </p>\r\n                </div>\r\n              </div>\r\n            </fieldset>\r\n          </div>\r\n        </div>\r\n      </div>\r\n      <ng-include src=\"'salaxy-components/workflow/usecases/UsecaseDetails_schemas.html'\"></ng-include>\r\n      <ng-include src=\"'salaxy-components/workflow/usecases/UsecaseDetails_scripts.html'\"></ng-include>\r\n      <ng-include src=\"'salaxy-components/workflow/usecases/UsecaseDetails_views.html'\"></ng-include>\r\n      <div ng-if=\"$ctrl.currentSection == 'schema'\" class=\"height100\">\r\n        <sxy-code-editor read-only=\"$ctrl.current.isReadOnly\" lang=\"json\" ng-model=\"$ctrl.editableSchema\"></sxy-code-editor>\r\n      </div>\r\n      <ng-include src=\"'salaxy-components/workflow/usecases/UsecaseDetails_tester.html'\"></ng-include>\r\n      <div ng-if=\"$ctrl.currentSection == 'debugger'\">\r\n        <div class=\"row\">\r\n          <div class=\"col-sm-6\">\r\n            <salaxy-json-formatter json=\"$ctrl.current\" key=\"'Usecase'\" open=\"1\"></salaxy-json-formatter>\r\n          </div>\r\n          <div class=\"col-sm-6\">\r\n            <salaxy-json-formatter json=\"$ctrl.currentItem\" key=\"'Current item'\" open=\"1\"></salaxy-json-formatter>\r\n          </div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</main>`);\n\n $templateCache.put(\"salaxy-components/workflow/usecases/UsecaseDetails_schemas.html\",`<div ng-if=\"$ctrl.currentSection == 'schemas'\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <button type=\"button\" ng-click=\"$ctrl.createSchema()\" class=\"btn btn-primary\">Lisää uusi</button>\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"selectAction\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle>\r\n        <span ng-if=\"!$ctrl.currentSchema\">Valitse datamalli...</span>\r\n        <span ng-if=\"$ctrl.currentSchema\">{{ $ctrl.currentSchema.title || (\"Ei nimeä \" + ($index + 1)) }}</span>\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"selectAction\">\r\n        <li ng-repeat=\"(key, schema) in $ctrl.current.schema.components.schemas\" ng-click=\"$ctrl.setCurrentSchema(key)\" role=\"menuitem\">\r\n          <a href=\"\">{{ schema.title || (\"Ei nimeä \" + ($index + 1)) }} ({{ key }})</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" ng-click=\"$ctrl.deleteSchema($ctrl.currentSchemaKey)\" ng-disabled=\"!$ctrl.currentSchema\" class=\"btn btn-danger\">Poista</button>\r\n  </div>\r\n  <hr />\r\n  <div ng-if=\"!$ctrl.currentSchema\" class=\"alert alert-info\">\r\n    Lisää uusi datamalli tai valitse yksi muokattavista.\r\n  </div>\r\n  <div class=\"row form-horizontal\" ng-if=\"$ctrl.currentSchema\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input label=\"Nimi\" name=\"{{ 'schemaTitle' + $index }}\" ng-model=\"$ctrl.currentSchema.title\"></salaxy-input>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input label=\"Tekninen nimi\" name=\"{{ 'schemaKey' + $index }}\" ng-model=\"$ctrl.currentSchemaKey\" readonly=\"true\"></salaxy-input>\r\n    </div>\r\n    <div class=\"col-xs-12\">\r\n      <h4>Datamallin muokkaus</h4>\r\n      <sxy-schema-editor model=\"$ctrl.currentSchema.properties\"></sxy-schema-editor>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/usecases/UsecaseDetails_scripts.html\",`<div ng-if=\"$ctrl.currentSection == 'scripts'\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <button type=\"button\" ng-click=\"$ctrl.createAction()\" class=\"btn btn-primary\">Lisää uusi</button>\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"selectAction\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"$ctrl.current.actions.length == 0\">\r\n        <span ng-if=\"!$ctrl.currentAction\">Valitse skripti...</span>\r\n        <span ng-if=\"$ctrl.currentAction\">{{ $ctrl.currentAction.label || (\"Ei nimeä \" + ($index + 1)) }}</span>\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"selectAction\">\r\n        <li ng-repeat=\"action in $ctrl.current.actions\" ng-click=\"$ctrl.currentAction = action\" role=\"menuitem\">\r\n          <a href=\"\">{{ action.label || (\"Ei nimeä \" + ($index + 1)) }}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" ng-click=\"$ctrl.deleteAction($ctrl.currentAction)\" ng-disabled=\"!$ctrl.currentAction\" class=\"btn btn-danger\">Poista</button>\r\n    <button type=\"button\" ng-click=\"$ctrl.executeAction()\" class=\"btn pull-right\" ng-class=\"'btn-' + ($ctrl.currentAction.uiColor || 'default')\"\r\n      ng-disabled=\"!$ctrl.currentAction.content\">\r\n      {{ $ctrl.currentAction.uiText || \"Käynnistä\" }}\r\n    </button>\r\n  </div>\r\n  <hr />\r\n  <div ng-if=\"!$ctrl.currentAction\" class=\"alert alert-info\">\r\n    Lisää uusi skripti tai valitse yksi muokattavista.\r\n  </div>\r\n  <div class=\"row\" ng-if=\"$ctrl.currentAction\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input label=\"Nimi\" name=\"actionTitle\" ng-model=\"$ctrl.currentAction.label\"></salaxy-input>\r\n      <salaxy-input label=\"Kuvaus\" name=\"actionDescription\" ng-model=\"$ctrl.currentAction.description\"></salaxy-input>\r\n      <salaxy-input-enum label=\"Tyyppi\" name=\"actionType\" ng-model=\"$ctrl.currentAction.actionType\" enum=\"UsecaseActionType\"></salaxy-input-enum>\r\n    </div>\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input label=\"Napin teksti\" name=\"actionUiText\" ng-model=\"$ctrl.currentAction.uiText\"></salaxy-input>\r\n      <salaxy-input-enum label=\"Napin väri\" name=\"actionUiColor\" ng-model=\"$ctrl.currentAction.uiColor\" enum=\"WorkflowEventUi\"></salaxy-input-enum>\r\n    </div>\r\n    <div class=\"col-xs-12\">\r\n      <div><small>Globals in this script:\r\n          <code>item: <span>{{ $ctrl.itemType || 'any / unknown' }}</span></code>,\r\n          <code>session: UserSession</code>, <code>core: @salaxy/core</code>\r\n          <span ng-if=\"$ctrl.currentExecutor.isAsync\">, <code>ajax: Ajax</code></span>\r\n        </small></div>\r\n      <sxy-code-editor read-only=\"$ctrl.current.isReadOnly\" item-type=\"$ctrl.itemType || 'any'\" ng-model=\"$ctrl.currentAction.content\"></sxy-code-editor>\r\n      <pre class=\"alert\" ng-class=\"'alert-' + ($ctrl.currentExecutor.status || 'default')\">{{ $ctrl.currentExecutor.result | json }}</pre>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/usecases/UsecaseDetails_tester.html\",`<div ng-if=\"$ctrl.currentSection == 'tester'\" ng-init=\"$ctrl.refreshCurrentInCache();$ctrl.currentView=$ctrl.currentView\">\r\n  <div>\r\n    <div class=\"btn-toolbar\">\r\n      <div class=\"btn-group\">\r\n        <button type=\"button\" class=\"btn btn-primary\" ng-click=\"$ctrl.selectItem('new')\">Luo uusi</button>\r\n        <button type=\"button\" class=\"btn btn-default\" ng-click=\"$ctrl.selectItem('select')\">Valitse testitietue..</button>\r\n        <button type=\"button\" class=\"btn btn-default pull-right\" ng-click=\"$ctrl.selectItem(null)\">Tyhjennä</button>\r\n      </div>\r\n      <div class=\"btn-group\" uib-dropdown>\r\n        <button id=\"selectView\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"$ctrl.current.views.length == 0\">\r\n          <span ng-if=\"!$ctrl.currentView\">Oletusnäkymä</span>\r\n          <span ng-if=\"$ctrl.currentView\">{{ $ctrl.currentView.label || (\"Ei nimeä \" + ($index + 1)) }}</span>\r\n          <span class=\"caret\"></span>\r\n        </button>\r\n        <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"selectView\">\r\n          <li ng-click=\"$ctrl.currentView = null\" role=\"menuitem\">\r\n            <a href=\"\">Oletusnäkymä</a>\r\n          </li>\r\n          <li ng-repeat=\"view in $ctrl.current.views\" ng-click=\"$ctrl.currentView = view\" role=\"menuitem\">\r\n            <a href=\"\">{{ view.label || (\"Ei nimeä \" + ($index + 1)) }}</a>\r\n          </li>\r\n        </ul>\r\n      </div>\r\n    </div>\r\n    <div ng-if=\"!$ctrl.currentItem\" class=\"container alert alert-info\">\r\n      <p>Valitse testitietue ja näkymä, jota haluat testata.</p>\r\n    </div>\r\n    <div class=\"container\" ng-if=\"$ctrl.currentItem\" ng-switch=\"$ctrl.current.itemType\" ng-init=\"temp = $ctrl.currentItem\">\r\n      <div ng-switch-when=\"calculation\">\r\n        <div ng-if=\"$ctrl.currentView\">\r\n          <div ng-controller=\"Calculator2022Controller as $ctrl\" ng-init=\"$ctrl.model = temp\">\r\n            <ng-include src=\"'salaxy-dynamic-templates/usecase-custom-view.html'\"></ng-include>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"!$ctrl.currentView\">\r\n          <salaxy-calc model=\"$ctrl.currentItem\"></salaxy-calc>\r\n        </div>\r\n      </div>\r\n      <div ng-switch-when=\"dataset\">\r\n        <div ng-if=\"$ctrl.currentView\">\r\n          <div ng-controller=\"DatasetsCrudController as $ctrl\" ng-init=\"$ctrl.model = temp\">\r\n            <ng-include src=\"'salaxy-dynamic-templates/usecase-custom-view.html'\"></ng-include>\r\n          </div>\r\n        </div>\r\n        <div ng-if=\"!$ctrl.currentView\">\r\n          <salaxy-dataset-details mode=\"data-edit\" model=\"$ctrl.currentItem\"></salaxy-dataset-details>\r\n        </div>\r\n      </div>\r\n      <div ng-switch-default>\r\n        <p>\r\n          TODO: Testinäkymää ei ole toteutettu datatyypille\r\n          <strong>{{$ctrl.current.itemType}}</strong>.\r\n        </p>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/usecases/UsecaseDetails_views.html\",`<div ng-if=\"$ctrl.currentSection == 'views'\">\r\n  <div class=\"btn-toolbar\" role=\"toolbar\">\r\n    <button type=\"button\" ng-click=\"$ctrl.createView()\" class=\"btn btn-primary\">Lisää uusi</button>\r\n    <div class=\"btn-group\" uib-dropdown>\r\n      <button id=\"selectView\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"$ctrl.current.views.length == 0\">\r\n        <span ng-if=\"!$ctrl.currentView\">Valitse käyttöliittymä...</span>\r\n        <span ng-if=\"$ctrl.currentView\">{{ $ctrl.currentView.label || (\"Ei nimeä \" + ($index + 1)) }}</span>\r\n        <span class=\"caret\"></span>\r\n      </button>\r\n      <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"selectView\">\r\n        <li ng-repeat=\"view in $ctrl.current.views\" ng-click=\"$ctrl.currentView = view\" role=\"menuitem\">\r\n          <a href=\"\">{{ view.label || (\"Ei nimeä \" + ($index + 1)) }}</a>\r\n        </li>\r\n      </ul>\r\n    </div>\r\n    <button type=\"button\" ng-click=\"$ctrl.deleteView($ctrl.currentView)\" ng-disabled=\"!$ctrl.currentView\" class=\"btn btn-danger\">Poista</button>\r\n  </div>\r\n  <hr />\r\n  <div ng-if=\"!$ctrl.currentView\" class=\"alert alert-info\">\r\n    Lisää uusi näkymä tai valitse yksi muokattavista.\r\n  </div>\r\n  <div class=\"row\" ng-if=\"$ctrl.currentView\">\r\n    <div class=\"col-sm-6\">\r\n      <salaxy-input label=\"Nimi\" name=\"viewTitle\" ng-model=\"$ctrl.currentView.label\"></salaxy-input>\r\n      <salaxy-input label=\"Kuvaus\" name=\"viewDescription\" ng-model=\"$ctrl.currentView.description\"></salaxy-input>\r\n    </div>\r\n    <div class=\"col-sm-6\"></div>\r\n    <div class=\"col-xs-12\">\r\n      <sxy-code-editor read-only=\"$ctrl.current.isReadOnly\" lang=\"html\" ng-model=\"$ctrl.currentView.content\"></sxy-code-editor>\r\n    </div>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/WorkflowBadge.html\",`<div ng-if=\"$ctrl.mode != 'horizontal'\" class=\"salaxy-component salaxy-workflow-badge\">\r\n  <div ng-repeat=\"event in $ctrl.events\">\r\n    <span ng-click=\"$ctrl.showEventDetails(event)\" class=\"clickable\" ng-class=\"'badge bg-' + event.ui\" title=\"{{ event.message + ' (' + (event.time | sxyTime)  + ')' }}\">\r\n      {{event.message}}\r\n    </span>\r\n  </div>\r\n</div>\r\n<span ng-if=\"$ctrl.mode == 'horizontal' && $ctrl.events.length\" class=\"salaxy-component salaxy-workflow-badge\">\r\n  <span ng-repeat=\"event in $ctrl.events\" ng-click=\"$ctrl.showEventDetails(event)\" class=\"clickable\" ng-class=\"'badge bg-' + event.ui\"\r\n    title=\"{{ event.message + ' (' + (event.time | sxyTime)  + ')' }}\" style=\"margin-right: 4px;\">{{event.message}}</span>\r\n</span>`);\n\n $templateCache.put(\"salaxy-components/workflow/WorkflowButtons.html\",`<div class=\"btn-group salaxy-workflow-buttons\">\r\n  <button class=\"btn btn-icon btn-transparent\" ng-class=\"$ctrl.hasWorkflowEvent('PartnerMessageClosed') ? 'text-success' : 'text-muted'\" ng-disabled=\"$ctrl.disabled\"\r\n    ng-click=\"$ctrl.buttonClick('close')\" title=\"{{ $ctrl.getWorkflowEvent('PartnerMessageClosed').message || ('SALAXY.UI_Terms.markChecked' | sxyTranslate)}}\">\r\n    <i class=\"fa fa-2x fa-check-circle\" ng-class=\"{ 'text-muted': $ctrl.isUpdating }\"></i>\r\n  </button>\r\n  <button ng-disabled=\"$ctrl.disabled\"\r\n    title=\"{{ $ctrl.getWorkflowEvent('PartnerMessageIssue').message || ('SALAXY.NG1.WorkFlowIssueComponent.buttons.showEditor' | sxyTranslate) }}\"\r\n    ng-click=\"$ctrl.buttonClick('issue')\" class=\"btn btn-icon btn-transparent\" ng-class=\"$ctrl.hasWorkflowEvent('PartnerMessageIssue') ? 'text-danger' : 'text-muted'\">\r\n    <i class=\"fa fa-2x fa-exclamation-circle\" ng-class=\"{ 'text-muted': $ctrl.isUpdating }\"></i>\r\n  </button>\r\n  <div class=\"btn-group workflow-assign\" uib-dropdown>\r\n    <button id=\"workflowAssign\" type=\"button\" class=\"btn btn-default\" uib-dropdown-toggle ng-disabled=\"$ctrl.disabled\">\r\n      <salaxy-avatar ng-if=\"$ctrl.getAssignedTo().id\" avatar=\"$ctrl.getAssignedTo().avatar\"></salaxy-avatar>\r\n      <div class=\"workflow-assign-title\">{{ $ctrl.getAssignedTo().email ||\r\n        $ctrl.getAssignedTo().avatar.displayName || \"Osoita henkilölle...\" }}</div>\r\n      <div><i class=\"fa fa-caret-down\" aria-hidden=\"true\"></i></div>\r\n    </button>\r\n    <ul class=\"dropdown-menu\" uib-dropdown-menu role=\"menu\" aria-labelledby=\"workflowAssign\">\r\n      <li role=\"menuitem\" ng-if=\"$ctrl.getAssignedTo().id\">\r\n        <a href=\"\"ng-click=\"$ctrl.buttonClick('assign', undefined)\">Poista valinta</a>\r\n      </li>\r\n      <li role=\"menuitem\" ng-repeat=\"credential in $ctrl.credentials\" ng-class=\"{ active: credential == $ctrl.getAssignedTo() }\">\r\n        <a href=\"\" ng-click=\"$ctrl.buttonClick('assign', credential)\">\r\n          <salaxy-avatar avatar=\"credential.avatar\"></salaxy-avatar>\r\n          &nbsp; {{ credential.email || credential.avatar.displayName }}\r\n        </a>\r\n      </li>\r\n    </ul>\r\n  </div>\r\n</div>`);\n\n $templateCache.put(\"salaxy-components/workflow/WorkflowReopen.html\",`<button class=\"btn btn-sm btn-secondary\" ng-disabled=\"$ctrl.disabled\" ng-class=\"{muted : $ctrl.isUpdating}\" ng-if=\"$ctrl.hasWorkflowEvent('PartnerMessageClosed') && $ctrl.apiCtrl.role === 'owner'\" ng-click=\"$ctrl.deleteWorkflowEvent('PartnerMessageClosed')\">\r\n  Avaa keskustelu\r\n</button>`);\n\n      }\n    }]);\n    ","import angular from \"angular\";\r\n\r\nimport { Ajax } from \"@salaxy/core\";\r\nimport { SessionService } from \"../services\";\r\n\r\n/**\r\n * Declaration of salaxy global variable.\r\n * @ignore\r\n */\r\ndeclare let salaxy;\r\n\r\n/**\r\n * User interaction with the current session: UserCredentials, Current Account(s) and Login/Logout.\r\n */\r\nexport class PersonalWebLegacyController implements angular.IController {\r\n\r\n  /**\r\n   * For NG-dependency injection\r\n   * @ignore\r\n   */\r\n  public static $inject = [\r\n    \"AjaxNg1\",\r\n    \"$sce\",\r\n    \"$window\",\r\n    \"$location\",\r\n    \"$timeout\",\r\n    \"SessionService\"\r\n  ];\r\n\r\n  constructor(\r\n    private ajax: Ajax,\r\n\r\n    private $sce: angular.ISCEService,\r\n    private $window: angular.IWindowService,\r\n    private $location: angular.ILocationService,\r\n    private $timeout: angular.ITimeoutService,\r\n\r\n    private sessionService: SessionService,\r\n  ) {\r\n\r\n  }\r\n\r\n  /**\r\n   * Implement IController\r\n   */\r\n  public $onInit() {\r\n    //\r\n    this.$window.addEventListener(\"message\", (event) => this.receiveUrl(event), false);\r\n  }\r\n\r\n  /** Get Archive page (in iframe) */\r\n  public getArchivePage() {\r\n    const url = `${salaxy.config.wwwServer}/YearlyLegacy/Open?access_token=${this.ajax.getCurrentToken()}`;\r\n    return this.$sce.trustAsResourceUrl(url);\r\n  }\r\n\r\n  /** TODO */\r\n  public receiveUrl(event) {\r\n    if (event && event.data && event.data.eventType === \"legacyRedirect\" && event.data.calcId) {\r\n      this.$timeout(() => { this.$location.path(\"/calc/details/\" + event.data.calcId); });\r\n    }\r\n  }\r\n\r\n  /** Get logout url */\r\n  public signOut() {\r\n    const url = `${salaxy.config.wwwServer}`;\r\n    this.sessionService.signOut(url);\r\n  }\r\n}\r\n","import { SitemapNode } from \"@salaxy/core\";\r\n\r\n/** Sitemap for the Palkkaus.fi personal web site (Household and Worker) */\r\nexport class PersonalWebSiteMap {\r\n  /** The sitemap */\r\n  public static sitemap: SitemapNode[] = [\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.home\",\r\n      url: \"#/\",\r\n      id: \"home\",\r\n      isFullWidth: true,\r\n      cssClass: \"double-sidebar\",\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.taxcards\",\r\n      url: \"#/taxcards\",\r\n      id: \"taxcards\",\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.main\",\r\n      url: \"#/calc\",\r\n      id: \"calc\",\r\n      children: [\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.paid\",\r\n          url: \"#/calc/paid\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.sent\",\r\n          url: \"#/calc/sent\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.draft\",\r\n          url: \"#/calc/draft\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.error\",\r\n          url: \"#/calc/error\",\r\n          id: \"error\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.new\",\r\n          url: \"#/calc/details/new\",\r\n          id: \"new\",\r\n          visibility: \"hidden\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.calc\",\r\n          url: \"#/calc/details/*\",\r\n          id: \"calc\",\r\n          visibility: \"hidden\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.calculations.share\",\r\n          url: \"#/calc/sharing/*\",\r\n          id: \"calcSharing\",\r\n          visibility: \"hidden\",\r\n        },\r\n      ],\r\n    },\r\n    {\r\n      title:\"Työnantajat\",\r\n      url:\"#/employers\",\r\n      id:\"employers\",\r\n      roles:\"test\"\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.archive.main\",\r\n      url: \"#/archive/worker-report\",\r\n      id: \"archive\",\r\n      children: [\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.archive.workerReport\",\r\n          url: \"#/archive/worker-report\",\r\n        },\r\n        {\r\n          title: \"SALAXY.NG1_Sitemap.personalWeb.employerArchive.main\",\r\n          url: \"#/archive/employer-archive\",\r\n          id: \"employer-archive\",\r\n          children: [\r\n            {\r\n              title: \"SALAXY.NG1_Sitemap.personalWeb.employerArchive.employerPaid\",\r\n              url: \"#/archive/employer-paid\",\r\n            },\r\n            {\r\n              title: \"SALAXY.NG1_Sitemap.personalWeb.employerArchive.employerReport\",\r\n              url: \"#/archive/employer-report\",\r\n            },\r\n            {\r\n              title: \"SALAXY.NG1_Sitemap.personalWeb.employerArchive.householdYears.main\",\r\n              url: \"#/household-years/active\",\r\n              id: \"householdYears\",\r\n              children: [\r\n                {\r\n                  title: \"SALAXY.NG1_Sitemap.personalWeb.employerArchive.householdYears.details\",\r\n                  url: \"#/household-years/details/*\",\r\n                  visibility: \"hidden\",\r\n                  id: \"details\",\r\n                },\r\n              ],\r\n            },\r\n            {\r\n              title: \"SALAXY.NG1_Sitemap.personalWeb.archive.householdDeductionReport\",\r\n              url: \"#/archive/household-deduction-report\",\r\n              id: \"householdDeductionReport\",\r\n              visibility: \"hidden\",\r\n            },\r\n          ]\r\n        },\r\n      ]\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.account\",\r\n      url: \"#/account\",\r\n      id: \"account\",\r\n    },\r\n    {\r\n      title: \"SALAXY.NG1_Sitemap.personalWeb.abc\",\r\n      url: \"https://help.palkkaus.fi/hc/fi\",\r\n      id: \"abc\",\r\n      isFullWidth: true,\r\n    },\r\n  ];\r\n}\r\n","import angular from \"angular\";\r\n\r\nimport { Translations, WebSiteUserRole } from \"@salaxy/core\";\r\n\r\nimport { AppInsightExceptionTracking, RouteHelperProvider } from \"../helpers\";\r\nimport { TemplateInterceptor } from \"../interceptors\";\r\nimport { SessionService, UiHelpers } from \"../services\";\r\nimport { PersonalWebLegacyController } from \"./PersonalWebLegacyController\";\r\nimport { PersonalWebSiteMap } from \"./PersonalWebSiteMap\";\r\n\r\n/** The main angular module configuration. */\r\nangular.module(\"palkkaus.web.personal\", [\"ngRoute\", \"salaxy.ng1.components.all\"])\r\n\r\n  // Set sitemap for navigation\r\n  .constant(\"SITEMAP\", PersonalWebSiteMap.sitemap)\r\n  // Set routes to pages\r\n  .config([\"RouteHelperProvider\", (routeHelperProvider: RouteHelperProvider) => {\r\n    const personalRoot = \"salaxy-components/pages-personal/\";\r\n    routeHelperProvider\r\n      .setCustomSectionRoot(\"salaxy-components/pages-personal\")\r\n      .homeDefault(\"home\")\r\n      .defaultSection(\"home\", [\"timeline-tester\"], \"./app/views/ng1/pages-undercon\", personalRoot + \"home\")\r\n\r\n      // [], \"./app/views/ng1/pages-undercon\" is a method for temporarily moving some pages to web where view changes require no build.\r\n      .defaultSection(\"calc\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"calc\")\r\n      .defaultSection(\"workers\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"workers\")\r\n      .defaultSection(\"account\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"account\")\r\n      .defaultSection(\"archive\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"archive\")\r\n      .defaultSection(\"taxcards\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"taxcards\")\r\n      .defaultSection(\"employers\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"employers\")\r\n      /** Temporary until the household site is shut down (02/2021) */\r\n      .defaultSection(\"employment\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"employment\")\r\n      .defaultSection(\"calc-household\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"calc\")\r\n      .defaultSection(\"workers-household\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"workers\")\r\n      .defaultSection(\"account-household\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"account\")\r\n      .defaultSection(\"taxcards-household\", [], \"./app/views/ng1/pages-undercon\", personalRoot + \"taxcards\")\r\n\r\n      // Not currenlty in use\r\n      .defaultSection(\"payroll\")\r\n      .customSection(\"messages\")\r\n      .defaultSection(\"reports\")\r\n\r\n      .otherwiseDefault();\r\n  }])\r\n  .config(AppInsightExceptionTracking)\r\n  .config([\"$httpProvider\", ($httpProvider: angular.IHttpProvider) => {\r\n    // Clear cached templates in browser every hour\r\n    $httpProvider.interceptors.push(TemplateInterceptor.factory(/views\\//, \"YYYYMMDDHH\"));\r\n  }])\r\n  .controller({PersonalWebLegacyController})\r\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n  .run([\"UiHelpers\", (uiHelpers: UiHelpers) => {\r\n    // UiHelpers is required for url detection (access token & return url)\r\n  }])\r\n  .run([\"SessionService\", \"$rootScope\", (sessionService: SessionService, $rootScope: angular.IRootScopeService) => {\r\n    Translations.setLocalesPath(\"/locales\");\r\n    sessionService.onAuthenticatedSession($rootScope, () => {\r\n      if (sessionService.isInRole(\"household\")) {\r\n        // Override household => worker role.\r\n        (sessionService.personAccount as any).lastLoginAsServer = sessionService.personAccount.lastLoginAs;\r\n        sessionService.personAccount.lastLoginAs = WebSiteUserRole.Worker;\r\n      }\r\n    });\r\n  }])\r\n  ;\r\n"],"names":["_AjaxNg1","$http","$q","config","globalConfig","Configs","apiServer","useCredentials","useCookie","method","request","token","response","error","data","Cookies","Token","errorThrown","msg","AjaxNg1","_WizardController","$scope","wizardService","stepNumber","WizardController","_CustomerOnboardingController","onboardingService","sessionService","authorizedAccountService","ajax","$location","steps","reason","link","body","currentAccountId","PensionCompany","pensionCompany","SettingsLogic","accountId","CustomerOnboardingController","_WorkerOnboardingController","uiHelpers","checkFunction","key","x","ssn","id","WorkerOnboardingController","_HouseholdOnboardingController","HouseholdOnboardingController","_CompanyOnboardingController","r","Role","rawUrl","baseUrl","accessToken","urlParam","cancelUrl","successUrl","Translations","businessId","searchType","onBoardingId","skin","origin","url","result","start","end","CompanyOnboardingController","_SigningController","signatureService","$sce","$timeout","onboarding","authMethod","value","arr","WebSiteUserRole","SigningController","_SignatureController","methodGroup","SignatureController","_CrudControllerBase","crudService","$attrs","copySourceId","copySource","selectedItem","selectedItemId","confirmMessage","newItem","copy","item","loading","CrudControllerBase","_AccountAuthorizationController","partnerSite","authorizedAccount","callback","avatar","role","AccountAuthorizationController","_CertificateController","certificateService","certificateApi","f","certificate","CertificateController","window","minErrConfig","errorHandlingConfig","isObject","isDefined","isValidObjectMaxDepth","isBoolean","maxDepth","isNumber","minErr","module","ErrorConstructor","regex","errRegExp","code","template","message","templateArgs","sliceArgs","arg","toDebugString","paramPrefix","i","match","index","REGEX_STRING_REGEXP","VALIDITY_STATE_PROPERTY","hasOwnProperty","lowercase","string","isString","uppercase","msie","jqLite","jQuery","slice","splice","push","toString","getPrototypeOf","ngMinErr","angular","angularModule","uid","isArrayLike","obj","isWindow","isArray","length","forEach","iterator","context","isFunction","isPrimitive","isBlankObject","forEachSorted","keys","reverseParams","iteratorFn","nextUid","setHashKey","h","baseExtend","dst","objs","deep","ii","j","jj","src","isDate","isRegExp","isElement","extend","merge","toInt","str","isNumberNaN","num","inherit","parent","extra","noop","identity","$","valueFn","hasCustomToString","isUndefined","isError","tag","isScope","isFile","isFormData","isBlob","isPromiseLike","TYPED_ARRAY_REGEXP","isTypedArray","isArrayBuffer","trim","escapeForRegexp","s","node","makeMap","items","nodeName_","element","includes","array","arrayRemove","source","destination","stackSource","stackDest","copyRecurse","copyElement","needsRecurse","copyType","copied","re","simpleCompare","a","b","equals","o1","o2","t1","t2","keySet","createMap","csp","ngCspElement","ngCspAttribute","noUnsafeEval","jq","el","ngAttrPrefixes","prefix","name","concat","array1","array2","args","startIndex","bind","self","fn","curryArgs","toJsonReplacer","val","toJson","pretty","fromJson","json","ALL_COLONS","timezoneToOffset","timezone","fallback","requestedTimezoneOffset","addDateMinutes","date","minutes","convertTimezoneToLocal","reverse","dateTimezoneOffset","timezoneOffset","startingTag","elemHtml","NODE_TYPE_TEXT","nodeName","tryDecodeURIComponent","parseKeyValue","keyValue","splitPoint","toKeyValue","parts","arrayValue","encodeUriQuery","encodeUriSegment","pctEncodeSpaces","getNgAttribute","ngAttr","attr","allowAutoBootstrap","document","script","attributes","srcs","isAutoBootstrapAllowed","angularInit","bootstrap","appElement","candidate","modules","defaultConfig","doBootstrap","$provide","$compileProvider","injector","createInjector","scope","compile","NG_ENABLE_DEBUG_INFO","NG_DEFER_BOOTSTRAP","extraModules","reloadWithDebugInfo","getTestability","rootElement","SNAKE_CASE_REGEXP","snake_case","separator","letter","pos","bindJQueryFired","bindJQuery","originalCleanData","jqName","JQLitePrototype","JQLite","elems","events","elem","UNSAFE_restoreLegacyJqLiteXHTMLReplacement","assertArg","assertArgFn","acceptArrayAnnotation","assertNotHasOwnProperty","getter","path","bindFnToScope","lastInstance","len","getBlockNodes","nodes","endNode","blockNodes","stringify","NODE_TYPE_ELEMENT","NODE_TYPE_ATTRIBUTE","NODE_TYPE_COMMENT","NODE_TYPE_DOCUMENT","NODE_TYPE_DOCUMENT_FRAGMENT","setupModuleLoader","$injectorMinErr","ensure","factory","requires","configFn","info","invokeQueue","configBlocks","runBlocks","invokeLater","moduleInstance","invokeLaterAndSetModuleName","block","provider","insertMethod","queue","recipeName","factoryFunction","shallowCopy","serializeObject","seen","version","publishExternalAPI","$$SanitizeUriProvider","$CompileProvider","htmlAnchorDirective","inputDirective","formDirective","scriptDirective","selectDirective","optionDirective","ngBindDirective","ngBindHtmlDirective","ngBindTemplateDirective","ngClassDirective","ngClassEvenDirective","ngClassOddDirective","ngCloakDirective","ngControllerDirective","ngFormDirective","ngHideDirective","ngIfDirective","ngIncludeDirective","ngInitDirective","ngNonBindableDirective","ngPluralizeDirective","ngRefDirective","ngRepeatDirective","ngShowDirective","ngStyleDirective","ngSwitchDirective","ngSwitchWhenDirective","ngSwitchDefaultDirective","ngOptionsDirective","ngTranscludeDirective","ngModelDirective","ngListDirective","ngChangeDirective","patternDirective","requiredDirective","minlengthDirective","maxlengthDirective","ngValueDirective","ngModelOptionsDirective","ngIncludeFillContentDirective","hiddenInputBrowserCacheDirective","ngAttributeAliasDirectives","ngEventDirectives","$AnchorScrollProvider","$AnimateProvider","$CoreAnimateCssProvider","$$CoreAnimateJsProvider","$$CoreAnimateQueueProvider","$$AnimateRunnerFactoryProvider","$$AnimateAsyncRunFactoryProvider","$BrowserProvider","$CacheFactoryProvider","$ControllerProvider","$DocumentProvider","$$IsDocumentHiddenProvider","$ExceptionHandlerProvider","$FilterProvider","$$ForceReflowProvider","$InterpolateProvider","$IntervalProvider","$$IntervalFactoryProvider","$HttpProvider","$HttpParamSerializerProvider","$HttpParamSerializerJQLikeProvider","$HttpBackendProvider","$xhrFactoryProvider","$jsonpCallbacksProvider","$LocationProvider","$LogProvider","$ParseProvider","$RootScopeProvider","$QProvider","$$QProvider","$SceProvider","$SceDelegateProvider","$SnifferProvider","$$TaskTrackerFactoryProvider","$TemplateCacheProvider","$TemplateRequestProvider","$$TestabilityProvider","$TimeoutProvider","$WindowProvider","$$RAFProvider","$$jqLiteProvider","$$MapProvider","$$CookieReaderProvider","jqCache","jqId","jqNextId","DASH_LOWERCASE_REGEXP","MS_HACK_REGEXP","MOUSE_EVENT_MAP","jqLiteMinErr","cssKebabToCamel","kebabToCamel","fnCamelCaseReplace","all","SINGLE_TAG_REGEXP","HTML_REGEXP","TAG_NAME_REGEXP","XHTML_TAG_REGEXP","wrapMap","wrapMapIE9","wrapMapValueClosing","wrapMapValue","jqLiteIsTextNode","html","jqLiteAcceptsData","nodeType","jqLiteHasData","jqLiteBuildFragment","tmp","wrap","finalHtml","fragment","jqLiteParseHTML","parsed","jqLiteWrapNode","wrapper","jqLiteContains","argIsString","jqLiteAddNodes","jqLiteReady","jqLiteClone","jqLiteDealoc","onlyDescendants","isEmptyObject","removeIfEmptyData","expandoId","expandoStore","jqLiteOff","type","unsupported","jqLiteExpandoStore","handle","removeHandler","listenerFns","jqLiteRemoveData","createIfNecessary","jqLiteData","prop","isSimpleSetter","isSimpleGetter","massGetter","jqLiteHasClass","selector","jqLiteRemoveClass","cssClasses","existingClasses","newClasses","cssClass","jqLiteAddClass","root","elements","jqLiteController","jqLiteInheritedData","names","jqLiteEmpty","jqLiteRemove","keepData","jqLiteDocumentLoaded","action","win","trigger","e","BOOLEAN_ATTR","BOOLEAN_ELEMENTS","ALIASED_ATTR","getBooleanAttrName","booleanAttr","getAliasedAttrName","ret","lowercasedName","isBooleanAttr","getText","option","arg1","arg2","nodeCount","nodeValue","createEventHandler","eventHandler","event","eventFns","eventFnsLength","originalStopImmediatePropagation","handlerWrapper","defaultHandlerWrapper","handler","specialMouseHandlerWrapper","target","related","types","addHandler","specialHandlerWrapper","noEventListener","onFn","replaceNode","children","child","wrapNode","newElement","condition","className","classCondition","extraParameters","dummyEvent","eventFnsCopy","handlerArgs","eventName","arg3","classes","hashKey","nextUidFn","objType","nanKey","NgMapShim","idx","NgMap","ARROW_ARG","FN_ARGS","FN_ARG_SPLIT","FN_ARG","STRIP_COMMENTS","stringifyFn","extractArgs","fnText","anonFn","annotate","strictDi","$inject","argDecl","last","underscore","modulesToLoad","INSTANTIATING","providerSuffix","loadedModules","providerCache","supportObject","service","constant","decorator","providerInjector","createInternalInjector","serviceName","caller","instanceCache","protoInstanceInjector","instanceInjector","loadModules","mods","delegate","provider_","enforceReturnValue","factoryFn","enforce","constructor","$injector","decorFn","origProvider","orig$get","origInstance","moduleFn","runInvokeQueue","invokeArgs","cache","getService","err","injectionArgs","locals","isClass","func","invoke","instantiate","Type","ctor","autoScrollingEnabled","$window","$rootScope","getFirstAnchor","list","getYOffset","offset","scroll","style","scrollTo","elemTop","hash","elm","newVal","oldVal","$animateMinErr","ELEMENT_NODE","NG_ANIMATE_CLASSNAME","mergeClasses","extractElementNode","splitClasses","klass","prepareAnimateOptions","options","postDigestQueue","postDigestElements","$$AnimateRunner","domOperation","addRemoveClassesPostDigest","runner","updateData","changed","handleCSSClassChanges","existing","toAdd","toRemove","status","hasClass","add","remove","classesAdded","classesRemoved","classNameFilter","customFilter","filterFn","expression","reservedRegex","$$animateQueue","domInsert","parentElement","afterElement","afterNode","after","from","to","$$rAF","waitQueue","waitForTick","passed","$sniffer","$$animateAsyncRun","$$isDocumentHidden","INITIAL_STATE","DONE_PENDING_STATE","DONE_COMPLETE_STATE","AnimateRunner","chain","next","runners","count","onProgress","host","rafTick","timeoutTick","resolve","reject","resolveHandler","rejectHandler","initialOptions","closed","run","applyAnimationContents","getHash","trimEmptyHash","Browser","$log","$$taskTrackerFactory","location","history","setTimeout","clearTimeout","pendingDeferIds","taskTracker","cachedState","lastHistoryState","lastBrowserUrl","baseElement","pendingLocation","getCurrentState","cacheState","replace","state","sameState","urlResolve","sameBase","stripHash","urlChangeListeners","urlChangeInit","cacheStateAndFireUrlChange","fireStateOrUrlChange","lastCachedState","prevLastHistoryState","listener","href","delay","taskType","timeoutId","deferId","$document","caches","cacheFactory","cacheId","size","stats","capacity","lruHash","freshEnd","staleEnd","lruEntry","refresh","entry","nextEntry","prevEntry","$cacheFactory","$compileMinErr","UNINITIALIZED_VALUE","_UNINITIALIZED_VALUE","$$sanitizeUriProvider","hasDirectives","Suffix","COMMENT_DIRECTIVE_REGEXP","CLASS_DIRECTIVE_REGEXP","ALL_OR_NOTHING_ATTRS","REQUIRE_PREFIX_REGEXP","EVENT_HANDLER_ATTR_REGEXP","bindingCache","parseIsolateBindings","directiveName","isController","LOCAL_REGEXP","bindings","definition","scopeName","parseDirectiveBindings","directive","assertValidDirectiveName","getDirectiveRequire","require","getDirectiveRestrict","restrict","registerDirective","directiveFactory","$exceptionHandler","directives","registerComponent","controller","makeInjectable","tElement","tAttrs","ddo","identifierForController","regexp","debugInfoEnabled","enabled","strictComponentBindingsEnabled","TTL","commentDirectivesEnabledConfig","cssClassDirectivesEnabledConfig","PROP_CONTEXTS","elementName","propertyName","ctx","registerContext","values","v","SCE_CONTEXTS","$interpolate","$templateRequest","$parse","$controller","$animate","SIMPLE_ATTR_NAME","specialAttrHolder","commentDirectivesEnabled","cssClassDirectivesEnabled","onChangesTtl","onChangesQueue","flushOnChangesQueue","sanitizeSrcset","invokeType","trimmedSrcset","srcPattern","pattern","rawUris","nbrUrisWith2parts","innerIdx","lastTuple","Attributes","attributesToCopy","l","directiveNormalize","classVal","oldClasses","tokenDifference","writeAttr","attrName","booleanKey","aliasedKey","observer","setSpecialAttr","$$observers","attrs","listeners","attribute","safeAddClass","$element","startSymbol","endSymbol","denormalizeTemplate","NG_PREFIX_BINDING","MULTI_ELEMENT_DIR_RE","binding","isolated","noTemplate","dataName","comment","content","$compileNodes","transcludeFn","maxPriority","ignoreDirective","previousCompileContext","compositeLinkFn","compileNodes","namespace","cloneConnectFn","parentBoundTranscludeFn","transcludeControllers","futureParentElement","detectNamespaceForChildElements","$linkNode","wrapTemplate","controllerName","nodeList","$rootElement","linkFns","notLiveList","nodeLinkFn","childNodes","childLinkFn","linkFnFound","nodeLinkFnFound","mergeConsecutiveTextNodes","collectDirectives","applyDirectivesToNode","childScope","childBoundTranscludeFn","stableNodeList","nodeListLength","createBoundTranscludeFn","sibling","previousBoundTranscludeFn","boundTranscludeFn","transcludedScope","cloneFn","controllers","containingScope","boundSlots","slotName","attrsMap","addDirective","nName","ngPrefixMatch","nAttrs","attrStartName","attrEndName","isNgAttr","isNgProp","isNgEvent","multiElementMatch","PREFIX_REGEXP","directiveIsMultiElement","addPropertyDirective","addEventDirective","addAttrInterpolateDirective","addTextInterpolateDirective","collectCommentDirectives","byPriority","groupScan","attrStart","attrEnd","depth","groupElementsLinkFnWrapper","linkFn","compilationGenerator","eager","compiled","compileNode","templateAttrs","jqCollection","originalReplaceDirective","preLinkFns","postLinkFns","terminalPriority","newScopeDirective","controllerDirectives","newIsolateScopeDirective","templateDirective","nonTlbTranscludeDirective","hasTranscludeDirective","hasTemplate","hasElementTranscludeDirective","$compileNode","$template","replaceDirective","childTranscludeFn","didScanForMultipleTransclusion","mightHaveMultipleTransclusionError","directiveValue","assertNoDuplicate","candidateDirective","scanningIndex","replaceWith","slots","slotMap","filledSlots","elementSelector","optional","filled","slotCompileNodes","removeComments","newTemplateAttrs","templateDirectives","unprocessedDirectives","markDirectiveScope","mergeTemplateAttributes","compileTemplateUrl","addLinkFns","pre","post","cloneAndAnnotateFn","linkNode","isolateScope","controllerScope","elementControllers","scopeBindingInfo","controllersBoundTransclude","setupControllers","initializeDirectiveBindings","controllerDirective","getControllers","controllerInstance","invokeLinkFn","scopeToChild","cloneAttachFn","slotTranscludeFn","inheritType","property","controllerKey","newScope","tDirectives","startAttrName","endAttrName","srcAttr","dstAttr","linkQueue","afterTemplateNodeLinkFn","afterTemplateChildLinkFn","beforeTemplateCompileNode","origAsyncDirective","derivedSyncDirective","templateUrl","templateNamespace","tempTemplateAttrs","beforeTemplateLinkNode","linkRootElement","ignoreChildLinkFn","diff","what","previousDirective","wrapModuleNameIfDefined","moduleName","text","interpolateFn","templateNode","templateNodeParent","hasCompileParent","getTrustedAttrContext","attrNormalizedName","getTrustedPropContext","propNormalizedName","sanitizeSrcsetPropertyValue","propName","trustedContext","sanitizer","_","ngPropGetter","ngPropWatch","applyPropValue","propValue","createEventDirective","mustHaveExpression","allOrNothing","newValue","oldValue","elementsToRemove","newNode","firstElementToRemove","removeCount","j2","annotation","strictBindingsCheck","removeWatchCollection","initialChanges","changes","mode","lastValue","parentGet","parentSet","compare","removeWatch","recordChanges","SimpleChange","parentValueWatch","parentValue","isLiteral","initialValue","currentValue","previousValue","triggerOnChangesHook","previous","current","SPECIAL_CHARS_REGEXP","str1","str2","tokens1","tokens2","outer","jqNodes","$controllerMinErr","CNTRL_REG","ident","later","instance","identifier","controllerPrototype","addIdentifier","doc","hidden","changeListener","exception","cause","domNode","APPLICATION_JSON","CONTENT_TYPE_APPLICATION_JSON","JSON_START","JSON_ENDS","JSON_PROTECTION_PREFIX","$httpMinErr","serializeValue","params","serialize","toSerialize","topLevel","defaultHttpResponseTransform","headers","tempData","contentType","hasJsonContentType","isJsonLike","jsonStart","parseHeaders","fillInParsed","line","headerVal","headerKey","headersGetter","headersObj","transformData","fns","isSuccess","defaults","d","useApplyAsync","interceptorFactories","xsrfTrustedOrigins","origins","$browser","$httpBackend","$$cookieReader","defaultCache","reversedInterceptors","interceptorFactory","urlIsAllowedOrigin","urlIsAllowedOriginFactory","requestConfig","mergeHeaders","requestInterceptors","responseInterceptors","promise","interceptor","chainInterceptors","serverRequest","completeOutstandingRequest","interceptors","thenFn","rejectFn","executeHeaderFns","headerContent","processedHeaders","headerFn","header","defHeaders","reqHeaders","defHeaderName","lowercaseDefHeaderName","reqHeaderName","defaultHeadersIteration","reqData","sendReq","transformResponse","resp","createShortMethods","createShortMethodsWithData","deferred","cachedResp","isJsonp","buildUrl","sanitizeJsonpCallbackParam","removePendingReq","resolvePromiseWithResult","resolvePromise","xsrfValue","done","createApplyHandlers","eventHandlers","applyHandlers","callEventHandler","headersString","statusText","xhrStatus","resolveHttpPromise","serializedParams","cbKey","$jsonpCallbacks","$xhrFactory","createHttpBackend","createXhr","$browserDefer","callbacks","rawDocument","timeout","withCredentials","responseType","uploadEventHandlers","callbackPath","jsonpDone","jsonpReq","completeRequest","xhr","abortedByTimeout","requestError","requestAborted","requestTimeout","timeoutRequest","$interpolateMinErr","startSymbolLength","endSymbolLength","escapedStartRegexp","escape","escapedEndRegexp","ch","unescapeText","constantWatchDelegate","objectEquality","constantInterp","unwatch","contextAllowsConcatenation","unescapedText","endIndex","expressions","parseFns","textLength","exp","expressionPositions","singleExpression","parseStringifyInterceptor","compute","oldValues","currValue","$intervalMinErr","$$intervalFactory","intervals","setIntervalFn","tick","clearIntervalFn","interval","markQExceptionHandled","$$q","invokeApply","hasParams","iteration","skipApply","callbackMap","createCallback","callbackId","PATH_MATCH","DEFAULT_PORTS","$locationMinErr","encodePath","segments","decodePath","html5Mode","normalizePath","pathValue","searchValue","hashValue","search","parseAbsoluteUrl","absoluteUrl","locationObj","parsedUrl","DOUBLE_SLASH_REGEX","parseAppUrl","prefixed","startsWith","stripBaseUrl","base","stripFile","serverBase","LocationHtml5Url","appBase","appBaseNoFile","basePrefix","pathUrl","relHref","appUrl","prevAppUrl","rewrittenUrl","LocationHashbangUrl","hashPrefix","withoutBaseUrl","withoutHashUrl","removeWindowsDriveName","windowsFilePathExp","firstPathSegmentMatch","LocationHashbangInHtml5Url","locationPrototype","locationGetter","locationGetterSetter","paramValue","Location","preprocess","LocationMode","baseHref","initialUrl","IGNORE_URI_REGEXP","urlsEqual","setBrowserUrlWithFallback","oldUrl","oldState","rewriteLinks","absHref","initializing","newUrl","newState","defaultPrevented","afterLocationChange","currentReplace","urlOrStateChanged","debug","flag","formatStackTrace","consoleLog","formatError","console","logFn","$parseMinErr","objectValueOf","getStringValue","OPERATORS","operator","ESCAPE","Lexer","ch2","ch3","op1","op2","op3","chars","cp","peek","cp1","cp2","colStr","number","peekCh","quote","rawString","hex","rep","AST","lexer","left","isAssignable","test","alternate","consequent","primary","baseExpression","properties","e1","e2","e3","e4","t","ifDefined","plusFn","isStateless","$filter","filterName","PURITY_ABSOLUTE","PURITY_RELATIVE","isPure","parentIsPure","findConstantAndWatchExpressions","ast","allConstants","argsToWatch","isStatelessFilter","astIsPure","expr","getInputs","lastExpression","assignableAST","isConstant","ASTCompiler","assignable","toWatch","watch","fnKey","intoId","fnString","inputs","input","filter","section","nameId","recursionFn","create","skipWatchIdCheck","right","computed","argument","own","defaultValue","SAFE_IDENTIFIER","UNSAFE_CHARACTERS","c","skip","init","ASTInterpreter","assign","rhs","lhs","watchId","Parser","oneTime","getValueOf","literals","identStart","identContinue","literalName","literalValue","identifierStart","identifierContinue","$parseOptions","$$getAst","interceptorFn","parsedExpression","cacheKey","parser","addWatchDelegate","addInterceptor","expressionInputDirtyCheck","oldValueOfValue","compareObjectIdentity","inputsWatchDelegate","prettyPrintExpression","inputExpressions","lastResult","oldInputValueOf","newInputValue","oldInputValueOfValues","oldInputValues","oneTimeWatchDelegate","isDone","isAllDefined","useInputs","oneTimeWatch","unwatchIfDone","allDefined","first","second","chainedInterceptor","errorOnUnhandledRejections","qFactory","nextTick","exceptionHandler","$qMinErr","queueSize","checkQueue","defer","Deferred","Promise","rejectPromise","progress","notifyPromise","onFulfilled","onRejected","progressBack","scheduleProcessQueue","handleCallback","processQueue","pending","markQStateExceptionHandled","processChecks","toCheck","isStateExceptionHandled","errorMessage","$$reject","$$resolve","then","doResolve","doReject","doNotify","resolver","callbackOutput","when","errback","promises","counter","results","race","$Q","resolveFn","q","requestAnimationFrame","cancelAnimationFrame","rafSupported","raf","timer","$rootScopeMinErr","lastDirtyWatch","applyAsyncId","createChildScopeClass","ChildScope","destroyChildScope","$event","cleanUpScope","Scope","isolate","watchExp","get","watcher","initWatchVal","incrementWatchersCount","watchExpressions","newValues","deregisterFns","changeReactionScheduled","firstRun","shouldCall","unwatchFn","watchGroupAction","$watchCollectionInterceptor","veryOldValue","trackVeryOldValue","changeDetected","changeDetector","internalArray","internalObject","initRun","oldLength","_value","newLength","bothNaN","oldItem","$watchCollectionAction","watchers","dirty","ttl","asyncQueue","watchLog","logIdx","asyncTask","beginPhase","flushApplyAsync","asyncQueuePosition","traverseScopesLoop","clearPhase","postDigestQueuePosition","decrementListenerCount","applyAsyncQueue","$applyAsyncExpression","scheduleApplyAsync","namedListeners","indexOfListener","empty","stopPropagation","listenerArgs","phase","aHrefSanitizationTrustedUrlList","imgSrcSanitizationTrustedUrlList","uri","isMediaUrl","normalizedVal","$sceMinErr","UNDERSCORE_LOWERCASE_REGEXP","snakeToCamel","adjustMatcher","matcher","adjustMatchers","matchers","adjustedMatchers","trustedResourceUrlList","bannedResourceUrlList","$$sanitizeUri","htmlSanitizer","matchUrl","urlIsSameOrigin","urlIsSameOriginAsBaseUrl","isResourceUrlAllowedByPolicy","n","allowed","generateHolderType","Base","holderType","trustedValue","trustedValueHolderBase","byType","trustAs","Constructor","valueOf","maybeTrusted","getTrusted","$sceDelegate","sce","parse","enumValue","lName","eventSupport","isNw","isChromePackagedApp","hasHistoryPushState","android","boxee","bodyStyle","transitions","animations","divElm","log","TaskTracker","taskCounts","taskCallbacks","ALL_TASKS_TYPE","DEFAULT_TASK_TYPE","completeTask","incTaskCount","notifyWhenNoPendingTasks","decTaskCount","countForType","countForAll","getNextCallback","getLastCallbackForType","getLastCallback","nextCb","cbInfo","$templateRequestMinErr","httpOptions","$templateCache","handleRequestFn","tpl","ignoreRequestError","transformer","handleError","testability","opt_exactMatch","matches","dataBinding","bindingName","prefixes","p","attributeEquals","$timeoutMinErr","deferreds","urlParsingNode","originUrl","baseUrlParsingNode","ipv6InBrackets","hostname","requestUrl","urlsAreSameOrigin","getBaseUrl","trustedOriginUrls","parsedAllowedOriginUrls","url1","url2","$$CookieReader","lastCookies","lastCookieString","safeGetCookie","safeDecodeURIComponent","cookieArray","cookie","currentCookieString","suffix","register","filters","currencyFilter","dateFilter","filterFilter","jsonFilter","limitToFilter","lowercaseFilter","numberFilter","orderByFilter","uppercaseFilter","comparator","anyPropertyKey","expressionType","getTypeForFilter","predicateFn","matchAgainstAnyProp","createPredicateFn","shouldMatchPrimitives","actual","expected","deepCompare","dontMatchWholeObject","actualType","expectedType","expectedVal","matchAnyProperty","actualVal","MAX_DIGITS","DECIMAL_SEP","ZERO_CHAR","$locale","formats","amount","currencySymbol","fractionSize","currencySymbolRe","formatNumber","numStr","exponent","digits","numberOfIntegerDigits","zeros","roundNumber","parsedNumber","minFrac","maxFrac","fractionLen","roundAt","digit","k","carry","groupSep","decimalSep","isInfinity","isZero","formattedText","integerLen","decimals","groups","padNumber","negWrap","neg","dateGetter","dateStrGetter","shortForm","standAlone","propPrefix","timeZoneGetter","zone","paddedZone","getFirstThursdayOfYear","year","dayOfWeekOnFirst","getThursdayThisWeek","datetime","weekGetter","firstThurs","thisThurs","ampmGetter","eraGetter","longEraGetter","DATE_FORMATS","DATE_FORMATS_SPLIT","NUMBER_STRING","R_ISO8601_STR","jsonStringToDate","tzHour","tzMin","dateSetter","timeSetter","m","ms","format","object","spacing","limit","begin","sliceFn","sortPredicate","reverseOrder","compareFn","predicates","processPredicates","descending","defaultCompare","compareValues","getComparisonObject","doComparison","predicate","getPredicateValue","v1","v2","sortPredicates","objectValue","type1","type2","value1","value2","ngDirective","defaultLinkFn","normalized","htmlAttr","nullFormCtrl","nullFormRenameControl","PENDING_CLASS","SUBMITTED_CLASS","control","FormController","setupValidity","newName","oldName","PRISTINE_CLASS","DIRTY_CLASS","rootForm","addSetValidityMethod","formDirectiveFactory","isNgForm","formElement","VALID_CLASS","nameAttr","ctrls","handleFormSubmission","parentFormCtrl","setter","getSetter","INVALID_CLASS","clazz","set","unset","validationErrorKey","createAndSet","unsetAndCleanup","cachedToggleClass","toggleValidationCss","isObjectEmpty","combinedState","ctrl","switchValue","isValid","ISO_DATE_REGEXP","URL_REGEXP","EMAIL_REGEXP","NUMBER_REGEXP","DATE_REGEXP","DATETIMELOCAL_REGEXP","WEEK_REGEXP","MONTH_REGEXP","TIME_REGEXP","PARTIAL_VALIDATION_EVENTS","PARTIAL_VALIDATION_TYPES","inputType","textInputType","createDateInputType","createDateParser","weekParser","numberInputType","urlInputType","emailInputType","radioInputType","rangeInputType","checkboxInputType","stringBasedInputType","baseInputType","composing","ev","deferListener","origValue","validity","origBadInput","origTypeMismatch","isoWeek","existingDate","week","hours","seconds","milliseconds","addDays","mapping","iso","previousDate","map","part","parseDate","badInputChecker","isTimeType","previousTimezone","parseDateAndConvertTimeZoneToLocal","ngModelMinErr","isValidDate","formatter","minVal","parsedMinVal","parseObservedDateValue","maxVal","parsedMaxVal","parsedDate","targetFormat","formatted","parserName","nativeValidation","numberFormatterParser","parseNumberAttrVal","isNumberInteger","countDecimals","numString","decimalSymbolIndex","isValidForStep","viewValue","stepBase","step","isNonIntegerValue","isNonIntegerStepBase","isNonIntegerStep","valueDecimals","stepBaseDecimals","stepDecimals","decimalCount","multiplier","modelValue","stepVal","parsedStepVal","supportsRange","hasMinAttr","hasMaxAttr","hasStepAttr","originalRender","setInitialValueAndObserver","minChange","maxChange","stepChange","htmlAttrName","changeFn","elVal","doTrim","parseConstantExpr","parseFn","trueValue","falseValue","valueProperty","CONSTANT_VALUE_REGEXP","updateElementValue","tplAttr","$compile","templateElement","ngBindHtmlGetter","ngBindHtmlWatch","classDirective","indexWatchExpression","classCounts","oldModulo","oldClassString","$index","ngClassIndexWatchAction","toClassString","ngClassWatchAction","addClasses","classString","digestClassCounts","split","removeClasses","updateClasses","newClassString","oldClassArray","newClassArray","toRemoveArray","arrayDifference","toAddArray","toRemoveString","toAddString","classArray","classesToUpdate","newModulo","classValue","forceAsyncEvents","forceAsync","$attr","$transclude","previousElements","clone","$anchorScroll","srcExp","onloadExp","autoScrollExp","changeCounter","currentScope","previousElement","currentElement","cleanupLastIncludeContent","afterAnimation","thisChangeId","ngList","trimValues","UNTOUCHED_CLASS","TOUCHED_CLASS","EMPTY_CLASS","NOT_EMPTY_CLASS","NgModelController","defaultModelOptions","setupModelWatcher","invokeModelGetter","invokeModelSetter","prevValid","prevModelValue","allowInvalid","that","allValid","doneCallback","localValidationRunId","processParseErrors","validationDone","processSyncValidators","processAsyncValidators","errorKey","setValidity","syncValidatorsValid","validator","validatorPromises","writeToModelIfNeeded","debounceDelay","formatters","modelCtrl","formCtrl","optionsCtrl","setTouched","DEFAULT_REGEXP","ModelOptions","inheritAll","NgModelOptionsController","parentOptions","modelOptionsDefinition","ngOptionsMinErr","NG_OPTIONS_REGEXP","parseOptionsExpression","optionsExp","selectElement","valueName","keyName","selectAs","trackBy","selectAsFn","viewValueFn","trackByFn","getTrackByValueFn","getTrackByValue","getLocals","displayFn","groupByFn","disableWhenFn","valuesFn","Option","selectValue","label","group","disabled","getOptionValuesKeys","optionValues","optionValuesKeys","itemKey","watchedArray","optionValuesLength","disableWhen","optionItems","selectValueMap","optionItem","optionTemplate","optGroupTemplate","ngOptionsPostLink","selectCtrl","ngModelCtrl","multiple","providedEmptyOption","unknownOption","ngOptions","listFragment","selectedOptions","getAndUpdateSelectedOption","selectedValues","selections","selectedOption","optionScope","optionEl","needsRerender","updateOptions","addOptionElement","optionElement","updateOptionElement","groupElementMap","groupElement","nextValue","isNotPrimitive","BRACE","IS_WHEN","numberExp","whenExp","whens","whensExpFns","braceReplacement","watchRemover","lastCount","attributeName","tmpMatch","whenKey","countIsNaN","whenExpFn","updateElementText","newText","ngRefMinErr","refValue","NG_REMOVED","ngRepeatMinErr","updateScope","valueIdentifier","keyIdentifier","arrayLength","getBlockStart","getBlockEnd","trackByIdArrayFn","trackByIdObjFn","ngRepeatEndComment","aliasAs","trackByExp","trackByIdExpFn","hashFnLocals","trackByExpGetter","lastBlockMap","collection","previousNode","nextNode","nextBlockMap","collectionLength","trackById","trackByIdFn","collectionKeys","nextBlockOrder","blockKey","NG_HIDE_CLASS","NG_HIDE_IN_PROGRESS_CLASS","newStyles","oldStyles","ngSwitchController","watchExpr","selectedTranscludes","selectedElements","previousLeaveAnimations","selectedScopes","spliceFactory","selected","selectedTransclude","caseElement","selectedScope","anchor","cases","whenCase","ngTranscludeMinErr","fallbackLinkFn","ngTranscludeCloneAttachFn","useFallbackContent","notWhitespace","noopNgModelController","setOptionSelectedStatus","SelectController","optionsMap","unknownVal","realVal","currentlySelectedOption","hashedVal","scheduleRender","renderScheduled","updateScheduled","scheduleViewValueUpdate","renderAfter","optionAttrs","interpolateValueFn","interpolateTextFn","removal","previouslySelected","removeValue","selectPreLink","selectPostLink","shouldBeSelected","currentlySelected","lastView","lastViewRef","selectCtrlName","tElm","tAttr","patternExp","attrVal","parsePatternAttr","oldRegexp","maxlength","maxlengthParsed","parseLength","minlength","minlengthParsed","intVal","PLURAL_CATEGORY","getDecimals","getVF","opt_precision","vf","angular_1","ApiCrudObjectController","api","$routeParams","crudItemIdArr","wasNew","loader","resetOriginal","keepOriginalAsIs","loadAction","wfEvent","wfIdOrType","wfId","ApiCrudObjectControllerBindings","ListControllerBase","isNew","ListControllerBaseBindings","_ODataHelperController","ODataHelperController","_ODataQueryController","cacheService","queryOptions","column","direction","operation","andFilters","valueType","unit","ix","exists","columnName","columns","colSpec","colArr","append","queryString","searchParams","OData","maxCount","notify","ODataQueryController","_CertificateCrudController","fullApi","CertificateCrudController","EditDialogKnownActions","EditDialogParameters","EditDialogResult","_AlertService","alertType","alert","container","hiddenAlerts","currentList","alertElementId","AlertService","Z_NO_FLUSH","Z_PARTIAL_FLUSH","Z_SYNC_FLUSH","Z_FULL_FLUSH","Z_FINISH","Z_BLOCK","Z_OK","Z_STREAM_END","Z_NEED_DICT","Z_STREAM_ERROR","Z_DATA_ERROR","Z_BUF_ERROR","Z_DEFAULT_COMPRESSION","Z_FILTERED","Z_HUFFMAN_ONLY","Z_RLE","Z_FIXED","Z_DEFAULT_STRATEGY","Z_BINARY","Z_TEXT","Z_UNKNOWN","Z_DEFLATED","_has","sources","shrinkBuf","buf","fnTyped","dest","src_offs","dest_offs","chunks","chunk","fnUntyped","typedOK","supported","arraySet","flattenChunks","Buf8","Buf16","Buf32","strApplyOK","strApplyUintOK","utf8len","table","string2buf","c2","m_pos","str_len","buf_len","_buf2binstring","buf2binstring","binstring2buf","buf2string","max","out","c_len","utf16buf","utf8border","adler32","adler","s1","s2","makeTable","crcTable","crc32","crc","BAD","TYPE","inflate_fast","strm","_in","_out","beg","dmax","wsize","whave","wnext","s_window","hold","bits","lcode","dcode","lmask","dmask","here","op","dist","from_source","output","top","dolen","dodist","MAXBITS","ENOUGH_LENS","ENOUGH_DISTS","CODES","LENS","DISTS","lbase","lext","dbase","dext","inflate_table","lens","lens_index","codes","table_index","work","opts","sym","min","curr","drop","used","huff","incr","fill","low","mask","base_index","offs","extra_index","here_bits","here_op","here_val","CODES$1","LENS$1","DISTS$1","Z_FINISH$1","Z_BLOCK$1","Z_TREES$1","Z_OK$1","Z_STREAM_END$1","Z_NEED_DICT$1","Z_STREAM_ERROR$1","Z_DATA_ERROR$1","Z_MEM_ERROR","Z_BUF_ERROR$1","Z_DEFLATED$1","HEAD","FLAGS","TIME","OS","EXLEN","EXTRA","NAME","COMMENT","HCRC","DICTID","DICT","TYPE$1","TYPEDO","STORED","COPY_","COPY","TABLE","LENLENS","CODELENS","LEN_","LEN","LENEXT","DIST","DISTEXT","MATCH","LIT","CHECK","LENGTH","DONE","BAD$1","MEM","SYNC","ENOUGH_LENS$1","ENOUGH_DISTS$1","zswap32","InflateState","inflateResetKeep","inflateReset","inflateReset2","windowBits","inflateInit2","virgin","lenfix","distfix","fixedtables","updatewindow","inflate","flush","put","have","last_bits","last_op","last_val","hbuf","order","inf_leave","inflateEnd","inflateGetHeader","head","inflateSetDictionary","dictionary","dictLength","dictid","ZStream","GZheader","Inflate","opt","chunkSize","_mode","next_out_utf8","tail","utf8str","dict","allowBufError","zero","STORED_BLOCK","STATIC_TREES","DYN_TREES","MIN_MATCH","MAX_MATCH","LENGTH_CODES","LITERALS","L_CODES","D_CODES","BL_CODES","HEAP_SIZE","MAX_BITS","Buf_size","MAX_BL_BITS","END_BLOCK","REP_3_6","REPZ_3_10","REPZ_11_138","extra_lbits","extra_dbits","extra_blbits","bl_order","DIST_CODE_LEN","static_ltree","static_dtree","_dist_code","_length_code","base_length","base_dist","StaticTreeDesc","static_tree","extra_bits","extra_base","max_length","static_l_desc","static_d_desc","static_bl_desc","TreeDesc","dyn_tree","stat_desc","d_code","put_short","w","send_bits","send_code","tree","bi_reverse","res","bi_flush","gen_bitlen","desc","max_code","stree","has_stree","xbits","overflow","gen_codes","bl_count","next_code","tr_static_init","init_block","bi_windup","copy_block","smaller","_n2","_m2","pqdownheap","compress_block","ltree","dtree","lc","lx","build_tree","scan_tree","prevlen","curlen","nextlen","max_count","min_count","send_tree","build_bl_tree","max_blindex","send_all_trees","lcodes","dcodes","blcodes","rank","detect_data_type","black_mask","static_init_done","_tr_init","_tr_stored_block","stored_len","_tr_align","_tr_flush_block","opt_lenb","static_lenb","_tr_tally","MAX_MEM_LEVEL","LENGTH_CODES$1","LITERALS$1","L_CODES$1","D_CODES$1","BL_CODES$1","HEAP_SIZE$1","MAX_BITS$1","MIN_MATCH$1","MAX_MATCH$1","MIN_LOOKAHEAD","PRESET_DICT","INIT_STATE","EXTRA_STATE","NAME_STATE","COMMENT_STATE","HCRC_STATE","BUSY_STATE","FINISH_STATE","BS_NEED_MORE","BS_BLOCK_DONE","BS_FINISH_STARTED","BS_FINISH_DONE","OS_CODE","errorCode","zero$1","flush_pending","flush_block_only","put_byte","putShortMSB","read_buf","longest_match","cur_match","chain_length","scan","best_len","nice_match","_win","wmask","prev","strend","scan_end1","scan_end","fill_window","_w_size","more","deflate_stored","max_block_size","max_start","deflate_fast","hash_head","bflush","deflate_slow","max_insert","deflate_rle","deflate_huff","Config","good_length","max_lazy","nice_length","max_chain","configurationTable","lm_init","DeflateState","deflateResetKeep","deflateReset","deflateSetHeader","deflateInit2","level","memLevel","strategy","deflate","old_flush","level_flags","bstate","deflateEnd","deflateSetDictionary","avail","tmpDict","toString$1","Deflate","external","support","blob","buffer","_keyStr","encode","chr1","chr2","chr3","enc1","enc2","enc3","enc4","remainingBytes","decode","resultIndex","dataUrlPrefix","totalLength","string2binary","stringToArrayLike","newBlob","checkSupport","stringifyByChunk","stringifyByChar","resultStr","fromCharCodeSupportsTypedArrays","arrayLikeToString","getTypeOf","canUseApply","applyFromCharCode","arrayLikeToArrayLike","arrayFrom","arrayTo","transform","transformTo","outputType","MAX_VALUE_16BITS","MAX_VALUE_32BITS","arguments$1","prepareContent","inputData","isBinary","isOptimizedBinaryString","isBase64","reader","dataType","GenericWorker","withError","me","_utf8len","utf8encode","utf8decode","Utf8DecodeWorker","previousData","nextBoundary","usableData","Utf8EncodeWorker","ConvertWorker","destType","transformZipOutput","mimeType","dataArray","accumulate","helper","updateCallback","chunkType","resultType","meta","StreamHelper","worker","internalType","updateCb","evt","base64","binary","dir","createFolders","compression","compressionOptions","unixPermissions","dosPermissions","DEFAULT_BLOCK_SIZE","DataWorker","dataP","nextIndex","DataLengthProbe","crc32str","crc32wrapper","Crc32Probe","CompressedObject","compressedSize","uncompressedSize","uncompressedWorker","ZipObject","askUnicodeString","isUnicodeString","onUpdate","arrayType","useTypedArray","resolved","FlateWorker","this$1$1","DEFLATE","STORE","compressions","LOCAL_FILE_HEADER","CENTRAL_FILE_HEADER","CENTRAL_DIRECTORY_END","ZIP64_CENTRAL_DIRECTORY_LOCATOR","ZIP64_CENTRAL_DIRECTORY_END","DATA_DESCRIPTOR","decToHex","dec","bytes","generateUnixExternalFileAttr","isDir","generateDosExternalFileAttr","generateZipParts","streamInfo","streamedContent","streamingEnded","platform","encodeFileName","file","useCustomEncoding","encodedFileName","utfEncodedFileName","encodedComment","utfEncodedComment","useUTF8ForFileName","useUTF8ForComment","dosTime","dosDate","extraFields","unicodePathExtraField","unicodeCommentExtraField","dataInfo","bitflag","extFileAttr","versionMadeBy","fileRecord","dirRecord","generateCentralDirectoryEnd","entriesCount","centralDirLength","localDirLength","dirEnd","generateDataDescriptors","descriptor","ZipFileWorker","streamFiles","currentFilePercent","remainingFiles","record","getCompression","fileCompression","zipCompression","compressionName","generateWorker","zip","zipFileWorker","relativePath","DataReader","newIndex","sig","dostime","ArrayReader","sig0","sig1","sig2","sig3","StringReader","Uint8ArrayReader","readerFor","MADE_BY_DOS","MADE_BY_UNIX","findCompression","compressionMethod","ZipEntry","loadOptions","localExtraFieldsLength","fileNameLength","madeBy","extraReader","extraFieldId","extraFieldLength","extraFieldValue","decodeParamType","upath","fileNameByteArray","ucomment","commentByteArray","upathField","ucommentField","ZipEntries","expectedSignature","signature","askedIndex","currentIndex","zipComment","decodeContent","extraDataSize","isGarbage","endOfCentralDirOffset","expectedEndOfCentralDirOffset","extraBytes","checkEntryCRC32","zipEntry","load","zipEntries","files","fileAdd","originalOptions","o","forceTrailingSlash","parentFolder","folderAdd","isCompressedEmpty","zipObjectContent","lastSlash","createFolders$1","JSZip","newObj","staticAccessors","cb","filename","newFolder","kids","this","g","global","Zipcelx","xl","worksheet","colIndex","rowNumber","rowIndex","Texts","cell","row","rowCells","cellIndex","rows","col","cols","xmlCols","xmlRows","_ExcelHelpers","tableData","fileName","rowMapper","FileSaver.saveAs","tablesData","zipName","fieldMapper","Dates","ExcelHelpers","_FileService","alertService","ExportMethod","locale","tabbedData","Tables","TableFormat","csvData","csvFileData","FileService","GravatarHelpers","email","rotateLeft","lValue","iShiftBits","addUnsigned","lX","lY","lX8","lY8","lX4","lY4","lResult","y","z","ff","ac","gg","hh","convertToWordArray","lWordCount","lMessageLength","lNumberOfWordsTemp1","lNumberOfWords","lWordArray","lBytePosition","lByteCount","wordToHex","wordToHexValue","wordToHexValueTemp","lByte","lCount","utf8Encode","utftext","aa","bb","cc","dd","_JsonSchemaService","JsonSchemaCache","openApiUrl","throwIfNotFound","schemaName","schema","JsonSchemaUtils","JsonSchemaService","_AppInsightExceptionTracking","$delegate","appInsights","AppInsightExceptionTracking","CalendarHelper","description","p1","sitemap_PersonLeafs","sitemap_Company","SitemapHelper","evaluateFor","SitemapVisibility","site","parentId","i18Prefix","hasChildrenChanges","isOpen","sectionPostFix","Arrays","session","sitemapProps","sitemap","currentPath","newPath","sectionId","nodeId","CurrentRoute","visibility","Objects","flagValue","_PromisePolyfill","PromisePolyfill","_RouteHelperProvider","$routeProvider","defaultViews","defaultViewsFolder","customViewsFolder","view","customViews","customSectionRoot","homePage","route","skipDefaults","RouteHelperProvider","RRuleFinnish","_NaviService","newSitemap","siteMapNode","targetNode","targetNodePath","main","appStatus","RoleLogic","urlFromPath","checkSession","nodeUrl","newNodeUrl","rule","childMatch","isInSomeRole","roles","filteredNodes","rolesWithoutTest","childNode","childParent","NaviService","_UiCrudHelpers","taxcards","employments","employmentId","buttonTypes","initialTab","employment","savedEmployment","innerResult","personalId","EmploymentRelationTaxcard","TaxCard2019Logic","TaxcardKind","kind","savedTaxcard","incomeLogResult","commitResult","taxcardId","salaryDate","UiCrudHelpers","_UiHelpers","$uibModal","$uibModalStack","logic","modalOptions","modal","modalResult","hasChanges","browserWindow","width","height","windowFeatures","hostUrl","popupBaseUrl","windowTemplateUrl","backdrop","heading","okText","cancelText","title","dateRange","calc","dialogResult","EmploymentLogic","taxcard","calEvent","isSimplified","category","calculations","workerList","dataMethod","dataDiffMethod","batchParamsTemplateUrl","autoStart","autoClose","silent","itemToProcess","byteArray","char","returnUrlParameters","dialog","returnUrl","UiHelpers","_WizardService","newSteps","skipNotify","Numeric","WizardService","BaseService","owner","_AuthorizedAccountService","authorizedAccountsApi","sites","AuthorizedAccountService","CacheService","cacheItem","expiresSeconds","_CertificateService","CertificateService","_CredentialService","credentialsApi","credentialId","CredentialService","PayrollLogic","payroll","calcs","Payrolls","CalculatorLogic","_InvoicesService","invoicesApi","settingsService","defaultChannel","channelsForRole","PaymentChannel","InvoicesLogic","paymentObject","channel","saveForPreview","CalculationStatus","savedCalculation","paymentObjectForCfa","Payrolls4","listItemResult","paramsTemplate","itemIds","payrollCalcs","newPaymentObject","reportingPaymentObject","pObj","InvoiceStatus","calculation","ok","LegalEntityType","isPaid","PayrollStatus","SalaryDateKind","SalaryDateLogic","officialDate","expiresAt","previewInvoices","coll","createNewInvoice","createInvoice","previews","grossInvoicePreview","InvoiceType","invoices","navigateToPaymentObject","businessObjectId","invoice","grossInvoice","settingsReceiver","settingsIntermediator","showAddressSelection","sendEInvoice","address","sendLoader","settings","freeText","ft","eInvoiceLogic","itemRef","cfaReferenceCalculations","cfaReferenceTotalResultCalculation","CalculationResultLogic","referenceLogic","pcls","holviResult","talenomResult","paytrailUrl","updateInvoiceStatus","newStatus","netAndTaxInvoices","netInvoicePreview","taxInvoicePreview","getNetInvoice","netInvoice","getTaxInvoice","taxInvoice","rowLength","remaining","InvoicesService","_OnboardingService","onboardingsApi","authService","signerPersonalId","testSignerPersonalId","asUntrusted","isModelLoaded","close","onboardingType","OnboardingService","_PartnerService","PartnerService","_ReportsService","reportsApi","id2","ReportsLogic","reportType","calcId","inline","ids","preview","refDate","tableType","AccountingReportTableType","periodType","PeriodType","endDate","calculationIds","calculationId","ReportsService","_RowTypeService","CalcRowsLogic","categories","obsolete","CalculationRowType","CalculationRowSource","specialKnownRowTypes","customRow","yearlyNumbers","Years","RowTypeService","_SessionService","sessionApi","accountApi","workers","commaSeparatedRolesList","accountRoles","cssUrl","isDev","entityType","redirectUrl","urlPostfix","OAuthSalaxyAuthorizeMode","getOrigin","regEx","isTestData","clientRoles","useDevelopmentFolder","urlParams","workerId","lang","Language","workerLang","channelAccounts","splits","roleList","scopes","partner","removeTokensFromPath","tt","rg","cleanPath","errorDescription","errorUri","SessionService","_SettingsService","accountSettings","reportOptions","reporting","logoMarkup","check","SettingsService","SignatureMethod","_SignatureService","OnboardingLogic","SignatureService","UiTranslatorService","_UploadService","angularUpload","fileId","invalidFile","UploadService","_UsecasesService","usecases","defaultOnly","filteredList","UsecaseStatus","defaultUri","usecase","ApiItemType","considerEmpty","newVersion","sessionUsecase","StorageLogic","UsecasesService","UserSettingsService","_VarmaPensionService","partnerServicesApi","getEmptyOrder","VarmaPensionService","_WorkflowService","credentialService","apiCtrl","WorkflowService","_CredentialController","uploadService","AvatarPictureType","credential","CredentialController","_EmbeddedUiController","userSettingsService","EmbeddedUiController","_PartnerController","partnerService","PartnerController","_SessionController","resultRole","SessionController","_CompanyAccountController","accounts","company","originalAvatar","editType","CompanyAccountController","_CalcEmploymentController","uiCrudHelpers","CalcEmploymentController","_CalculationCrudController","calculationsApi","reportsService","invoicesService","newCalc","reloaded","updateRows","eprWarningMessage","eprText","SystemRole","CalculationCrudController","_Calculator2022Controller","calcApi","usecasesService","usecaseUri","uc","Calculator2022Controller","_SalaryBasesController","employmentsApi","jsonSchemaService","datasetsApi","datasetToLoad","HrSuuntiImportLogic","payrollEmployments","mapper","DataMapper","FileParser","validation","ValidationHelper","SalaryBasesController","round","lim","p2b","n2b","b2n","n2p","map$1","h1","h2","eq","isShort","hexParse","alpha","hexString","HUE_RE","hsl2rgbn","hsv2rgbn","hwb2rgbn","rgb","hueValue","rgb2hsl","calln","hsl2rgb","hwb2rgb","hsv2rgb","hue","hueParse","p2","rotate","deg","hslString","names$1","unpack","unpacked","tkeys","nk","nameParse","RGB_RE","rgbParse","rgbString","interpolate","rgb1","rgb2","modHSL","ratio","proto","fromObject","functionParse","Color","color","weight","c1","w2","w1","isNullOrUndef","isNumberFinite","finiteOrDefault","valueOrDefault","toPercentage","dimension","toDimension","thisArg","each","loopable","_elementsEqual","a0","a1","ilen","v0","klen","isValidKey","_merger","tval","sval","merger","mergeIf","_mergerIf","keyResolvers","_splitKey","_getKeyResolver","resolveObjectKey","_capitalize","defined","setsEqual","_isClickEvent","PI","TAU","PITAU","INFINITY","RAD_PER_DEG","HALF_PI","QUARTER_PI","TWO_THIRDS_PI","log10","sign","almostEquals","epsilon","niceNum","range","roundedRange","niceRange","fraction","_factorize","sqrt","almostWhole","rounded","_setMinAndMaxByKey","toRadians","degrees","toDegrees","radians","_decimalPlaces","getAngleFromPoint","centrePoint","anglePoint","distanceFromXCenter","distanceFromYCenter","radialDistanceFromCenter","angle","distanceBetweenPoints","pt1","pt2","_angleDiff","_normalizeAngle","_angleBetween","sameAngleIsFullCircle","angleToStart","angleToEnd","startToAngle","endToAngle","_limitValue","_int16Range","_isBetween","_lookup","cmp","hi","lo","mid","_lookupByKey","ti","_rlookupByKey","_filterBetween","arrayEvents","listenArrayEvents","unlistenArrayEvents","stub","_arrayUnique","requestAnimFrame","throttled","argsToUse","ticking","debounce","_toLeftRightCenter","align","_alignStartEnd","_textX","rtl","_getStartAndCountOfVisiblePoints","points","animationsDisabled","pointCount","iScale","_parsed","axis","minDefined","maxDefined","_scaleRangesChanged","xScale","yScale","_scaleRanges","newRanges","atEdge","elasticIn","elasticOut","effects","isPatternOrGradient","getHoverColor","numbers","colors","applyAnimationsDefaults","applyLayoutsDefaults","intlCache","getNumberFormat","tickValue","ticks","notation","delta","maxTick","calculateDelta","logDelta","numDecimal","remain","Ticks","applyScaleDefaults","_ctx","overrides","descriptors","getScope$1","Defaults","_descriptors","_appliers","targetScope","targetName","scopeObject","targetScopeObject","privateName","local","appliers","apply","toFontString","font","_measureText","gc","longest","textWidth","_longestText","arrayOfThings","jlen","thing","nestedThing","gcLen","_alignPixel","chart","pixel","devicePixelRatio","halfWidth","clearCanvas","canvas","drawPoint","drawPointLegend","xOffset","yOffset","cornerRadius","xOffsetW","yOffsetW","rotation","radius","rad","_isPointInArea","point","area","margin","clipArea","unclipArea","_steppedLineTo","flip","midpoint","_bezierCurveTo","setRenderOpts","decorateText","metrics","bottom","yDecoration","drawBackdrop","oldColor","renderText","lines","stroke","addRoundedRectPath","rect","LINE_HEIGHT","FONT_STYLE","toLineHeight","numberOrZero","_readValueToProps","props","objProps","read","toTRBL","toTRBLCorners","toPadding","toFont","cacheable","_addGrace","minmax","grace","beginAtZero","change","keepZero","createContext","parentContext","_createResolver","rootScopes","getTarget","finalRootScopes","_resolve","_cached","_resolveWithPrefixes","getKeysFromAllScopes","storage","_attachContext","proxy","subProxy","descriptorDefaults","receiver","_resolveWithContext","_scriptable","_indexable","_allKeys","readKey","needsSubResolver","_proxy","_context","_subProxy","_resolveScriptable","_resolveArray","getValue","_stack","createSubResolver","isIndexable","resolveFallback","getScope","addScopes","parentScopes","parentFallback","allScopes","addScopesFromKey","subGetTarget","resolveKeysFromAllScopes","_parseObjectDataRadialScale","EPSILON","getPoint","getValueAxis","indexAxis","splineCurve","firstPoint","middlePoint","afterPoint","d01","d12","s01","s12","fa","fb","monotoneAdjust","deltaK","mK","pointsLen","alphaK","betaK","tauK","squaredMagnitude","pointCurrent","pointAfter","monotoneCompute","valueAxis","pointBefore","iPixel","vPixel","splineCurveMonotone","slopeDelta","capControlPoint","pt","capBezierPoints","inArea","inAreaPrev","inAreaNext","_updateBezierControlPoints","loop","controlPoints","_isDomSupported","_getParentNode","parseMaxStyle","styleValue","parentProperty","valueInPixels","getComputedStyle","getStyle","positions","getPositionedStyle","styles","useOffsetPos","getCanvasPosition","touches","offsetX","offsetY","box","getRelativePosition","currentDevicePixelRatio","borderBox","paddings","borders","getContainerSize","maxWidth","maxHeight","containerStyle","containerBorder","containerPadding","round1","getMaximumSize","bbWidth","bbHeight","aspectRatio","margins","containerSize","retinaScale","forceRatio","forceStyle","pixelRatio","deviceHeight","deviceWidth","supportsEventListenerOptions","passiveSupported","readUsedSize","_pointInLine","_steppedInterpolation","_bezierInterpolation","getRightToLeftAdapter","rectX","itemWidth","getLeftToRightAdapter","_itemWidth","getRtlAdapter","overrideTextDirection","original","restoreTextDirection","propertyFn","normalizeSegment","getSegment","segment","bounds","startBound","endBound","between","normalize","_boundSegment","inside","subStart","prevValue","startIsBefore","endIsBefore","shouldStart","shouldStop","_boundSegments","sub","findStartAndEnd","spanGaps","solidSegments","cur","_computeSegments","segmentOptions","splitByStyles","completeLoop","doSplitByStyles","chartContext","baseStyle","readStyle","datasetIndex","prevStyle","addStyle","st","styleChanged","replacer","Animator","anims","numSteps","draw","charts","acc","animator","transparent","interpolators","factor","c0","Animation","cfg","elapsed","duration","rej","Animations","animationOptions","animatedProps","newOptions","resolveTargetOptions","awaitAll","running","animation","anim","scaleClip","scale","allowedOverflow","defaultClip","toClip","getSortedDatasetIndices","filterVisible","metasets","applyStack","stack","dsIndex","singleMode","otherValue","convertObjectDataToArray","adata","isStacked","stacked","getStackKey","indexScale","valueScale","getUserBounds","getOrCreateStack","stacks","stackKey","indexValue","subStack","getLastIndexInStack","vScale","positive","updateStacks","iAxis","vAxis","itemStacks","visualValues","getFirstScaleId","scales","createDatasetContext","createDataContext","clearStacks","isDirectUpdateMode","cloneIfNotShared","cached","shared","createStack","canStack","DatasetController","dataset","chooseId","xid","yid","rid","iid","vid","scaleID","_data","resetNewElements","stackChanged","oldStacked","scopeKeys","_stacked","sorted","isNotInOrderComparedToPrev","labels","singleScale","xAxisKey","yAxisKey","parsedValue","otherScale","otherMin","otherMax","_skip","active","drawActiveElementsOnTop","elementType","sharing","transition","sharedOptions","firstOpts","previouslySharedOptions","includeOptions","numMeta","numData","move","removed","newCount","__publicField","getAllScaleValues","visibleMetas","computeMinSampleSize","updateMinAndPrev","computeFitCategoryTraits","ruler","stackCount","thickness","computeFlexCategoryTraits","pixels","percent","parseFloatBar","startValue","endValue","barStart","barEnd","parseValue","parseArrayOrPrimitive","isFloatBar","custom","barSign","actualBase","borderProps","setBorderSkipped","edge","parseEdge","swap","startEnd","orig","setInflateAmount","inflateAmount","BarController","iAxisKey","vAxisKey","bars","reset","horizontal","vpixels","ipixels","dataIndex","skipNull","barThickness","baseValue","minBarLength","floating","startPixel","endPixel","halfGrid","maxBarThickness","center","stackIndex","rects","BubbleController","getRatioAndOffset","circumference","cutout","ratioX","ratioY","startAngle","endAngle","startX","startY","endX","endY","calcMax","calcMin","maxX","maxY","minX","minY","DoughnutController","chartArea","arcs","maxSize","chartWeight","maxRadius","outerRadius","innerRadius","radiusLength","animationOpts","centerX","centerY","animateScale","arc","metaData","total","ringWeightOffset","pointStyle","legendItem","legend","LineController","_dataset","maxGapLength","directUpdate","pointsCount","prevParsed","nullData","border","lastPoint","PolarAreaController","minSize","datasetStartAngle","defaultAngle","PieController","RadarController","pointPosition","ScatterController","showLine","abstract","DateAdapterBase","members","adapters","binarySearch","metaset","intersect","_sorted","lookupMethod","evaluateInteractionItems","position","getDistanceMetricForAxis","useX","useY","deltaX","deltaY","getIntersectItems","useFinalPosition","includeInvisible","getNearestRadialItems","evaluationFunc","getNearestCartesianItems","distanceMetric","minDistance","inRange","distance","getNearestItems","getAxisItems","rangeMethod","intersectsItem","Interaction","STATIC_POSITIONS","filterByPosition","filterDynamicPositionByAxis","sortByWeight","wrapBoxes","boxes","layoutBoxes","stackWeight","buildStacks","layouts","setLayoutDims","vBoxMaxWidth","hBoxMaxHeight","layout","fullSize","buildLayoutBoxes","centerHorizontal","centerVertical","getCombinedMax","maxPadding","updateMaxPadding","boxPadding","updateDims","newWidth","newHeight","widthChanged","heightChanged","handleMaxPadding","updatePos","getMargins","marginForPositions","fitBoxes","refitBoxes","refit","same","other","setBoxDims","placeBoxes","userPadding","layoutItem","minPadding","padding","availableWidth","availableHeight","verticalBoxes","horizontalBoxes","visibleVerticalBoxCount","BasePlatform","BasicPlatform","EXPANDO_KEY","EVENT_TYPES","isNullOrEmpty","initCanvas","renderHeight","renderWidth","displayWidth","displayHeight","eventListenerOptions","addListener","removeListener","fromNativeEvent","nodeListContains","createAttachObserver","entries","createDetachObserver","drpListeningCharts","oldDevicePixelRatio","onWindowResize","dpr","resize","listenDevicePixelRatioChanges","unlistenDevicePixelRatioChanges","createResizeObserver","releaseObserver","createProxyAndListen","DomPlatform","initial","proxies","_detectPlatform","Element","final","autoSkip","tickOpts","determinedMaxTicks","determineMaxTicks","ticksLimit","majorIndices","getMajorIndices","numMajorIndices","newTicks","skipMajors","calculateSpacing","avgMajorSpacing","tickLength","maxScale","maxChart","evenMajorSpacing","getEvenSpacing","factors","majorStart","majorEnd","reverseAlign","offsetFromEdge","getTicksLimit","ticksLength","maxTicksLimit","sample","numItems","increment","getPixelForGridLine","offsetGridLines","validIndex","lineValue","garbageCollect","getTickMarkLength","getTitleHeight","createScaleContext","createTickContext","titleAlign","titleArgs","titleX","titleY","positionAxisID","Scale","raw","_userMin","_userMax","_suggestedMin","_suggestedMax","metas","sampleSize","samplingEnabled","reversePixels","numTicks","minRotation","maxRotation","labelRotation","tickWidth","maxLabelDiagonal","labelSizes","maxLabelWidth","maxLabelHeight","titleOpts","gridOpts","display","isHorizontal","titleHeight","widest","highest","tickPadding","angleRadians","cos","sin","labelHeight","labelWidth","isRotated","labelsBelowTicks","offsetLeft","offsetRight","paddingLeft","paddingRight","paddingTop","paddingBottom","widths","heights","widestLabelSize","highestLabelSize","tickFont","fontString","lineHeight","nestedLabel","valueAt","decimal","optionTicks","rot","grid","tl","borderOpts","axisWidth","axisHalfWidth","alignBorderValue","borderValue","alignedLineValue","tx1","ty1","tx2","ty2","x1","y1","x2","y2","optsAtIndex","optsAtIndexBorder","lineWidth","lineColor","borderDash","borderDashOffset","tickColor","tickBorderDash","tickBorderDashOffset","crossAlign","mirror","tickAndPadding","hTickAndPadding","textAlign","lineCount","textOffset","textBaseline","halfCount","strokeColor","strokeWidth","tickTextAlign","labelPadding","backgroundColor","drawLine","lastLineWidth","renderTextOptions","tz","gz","bz","axisID","fontSize","TypedRegistry","override","parentScope","isIChartComponent","registerDefaults","itemDefaults","routeDefaults","routes","propertyParts","sourceName","sourceScope","Registry","typedRegistry","reg","itemReg","registry","component","camelMethod","PluginService","hook","plugin","plugins","allPlugins","createDescriptors","previousDescriptors","localIds","getOpts","pluginOpts","getIndexAxis","datasetDefaults","getAxisFromDefaultScaleID","getDefaultScaleIDFromAxis","idMatchesAxis","axisFromPosition","determineAxis","scaleOptions","getAxisFromDataset","retrieveAxisFromDatasets","boundDs","mergeScaleConfig","chartDefaults","configScales","chartIndexAxis","scaleConf","defaultId","defaultScaleOptions","defaultID","initOptions","initData","initConfig","keyCache","keysCached","cachedKeys","generate","addIfFound","datasetType","mainScope","resetCache","_scopeCache","keyLists","subPrefixes","getResolver","needContext","subResolver","resolverCache","hasFunction","isScriptable","scriptable","indexable","KNOWN_POSITIONS","positionIsHorizontal","compare2Level","l1","l2","onAnimationsComplete","onAnimationProgress","getCanvas","instances","getChart","moveNumericKeys","intKey","determineLastEvent","lastEvent","inChartArea","isClick","getSizeForArea","field","getDatasetArea","Chart$1","_a","invalidatePlugins","userConfig","initialCanvas","existingChart","maintainAspectRatio","_aspectRatio","newSize","newRatio","scalesOptions","axisOptions","scaleOpts","updated","isRadial","scaleType","scaleClass","hasUpdated","datasets","newControllers","ControllerClass","datasetElementType","dataElementType","animsDisabled","_active","_lastEvent","existingEvents","newEvents","_hiddenIndices","_dataChanges","datasetCount","makeSet","changeSet","noArea","layers","clip","useClip","visible","_add","_remove","detached","attached","activeElements","lastActive","pluginId","replay","hoverOptions","deactivated","activated","eventFilter","Chart","clipArc","pixelMargin","angleMargin","toRadiusCorners","parseBorderRadius$1","angleDelta","halfThickness","innerLimit","computeOuterLimit","outerArcLimit","rThetaToXY","theta","pathArc","circular","innerR","spacingOffset","noSpacingInnerRadius","noSpacingOuterRadius","avNogSpacingRadius","adjustedAngle","beta","angleOffset","outerStart","outerEnd","innerStart","innerEnd","outerStartAdjustedRadius","outerEndAdjustedRadius","outerStartAdjustedAngle","outerEndAdjustedAngle","innerStartAdjustedRadius","innerEndAdjustedRadius","innerStartAdjustedAngle","innerEndAdjustedAngle","outerMidAdjustedAngle","pCenter","p4","innerMidAdjustedAngle","p8","outerStartX","outerStartY","outerEndX","outerEndY","drawArc","fullCircles","drawBorder","borderWidth","borderJoinStyle","inner","ArcElement","chartX","chartY","rAdjust","betweenAngles","withinRadius","halfAngle","halfRadius","fix","radiusOffset","setStyle","lineTo","getLineMethod","pathVars","paramsStart","paramsEnd","segmentStart","segmentEnd","outside","pathSegment","lineMethod","fastPathSegment","avgX","countX","prevX","lastY","pointIndex","drawX","truncX","_getSegmentMethod","_getInterpolationMethod","strokePathWithCache","strokePathDirect","segmentMethod","usePath2D","LineElement","_interpolate","interpolated","inRange$1","PointElement","mouseX","mouseY","getBarBounds","bar","half","skipOrLimit","parseBorderWidth","maxW","maxH","parseBorderRadius","enableBorderRadius","maxR","enableBorder","boundingRects","skipX","skipY","hasRadius","addNormalRectPath","inflateRect","refRect","BarElement","borderColor","addRectPath","BORDER_COLORS","BACKGROUND_COLORS","getBorderColor","getBackgroundColor","colorizeDefaultDataset","colorizeDoughnutDataset","colorizePolarAreaDataset","getColorizer","containsColorsDefinitions","containsColorsDefinition","plugin_colors","_args","chartOptions","colorizer","lttbDecimation","samples","decimated","bucketWidth","sampledIndex","maxAreaPoint","maxArea","nextA","avgY","avgRangeStart","avgRangeEnd","avgRangeLength","rangeOffs","rangeTo","pointAx","pointAy","minMaxDecimation","minIndex","maxIndex","xMin","dx","lastIndex","intermediateIndex1","intermediateIndex2","cleanDecimatedDataset","cleanDecimatedData","getStartAndCountOfVisiblePointsSimplified","plugin_decimation","xAxis","threshold","_segments","tpoints","_findSegmentEnd","_getBounds","targetSegments","tgt","subBounds","fillSources","fillSource","_getEdge","_pointsFromSegments","boundary","linePoints","_createBoundaryLine","_loop","_shouldApplyFill","_resolveTarget","propagate","visited","_decodeFill","parseFillOption","decodeTargetIndex","firstCh","_getTargetPixel","_getTargetValue","fillOption","_buildStackLine","sourcePoints","linesBelow","getLinesBelow","addPointsBelow","below","sourcePoint","postponed","findPoint","pointValue","firstValue","simpleArc","_getTarget","getLineByIndex","computeBoundary","computeCircularBoundary","computeLinearBoundary","_drawfill","lineOpts","above","doFill","clipVertical","clipY","lineLoop","notShape","clipBounds","interpolatedLineTo","targetLoop","interpolatedPoint","getBoxSize","labelOpts","boxHeight","boxWidth","itemsEqual","Legend","legendItems","labelFont","itemHeight","hitboxes","lineWidths","totalHeight","_itemHeight","columnSizes","heightLimit","totalWidth","currentColWidth","currentColHeight","calculateItemSize","rtlHelper","hitbox","defaultColor","halfFontSize","cursor","drawLegendBox","drawOptions","yBoxTop","xBoxLeft","borderRadius","fillText","realX","fontLineHeight","calculateLegendItemHeight","titleFont","titlePadding","topPaddingPlusHalfFontSize","hitBox","lh","isListened","hoveredItem","sameItem","calculateItemWidth","calculateItemHeight","legendItemText","plugin_legend","ci","usePointStyle","useBorderRadius","Title","textSize","fontOpts","createTitle","plugin_title","titleBlock","plugin_subtitle","positioners","xSet","eventPosition","nearestElement","tp","pushOrConcat","toPush","splitNewlines","createTooltipItem","getTooltipSize","tooltip","footer","bodyFont","footerFont","titleLineCount","footerLineCount","bodyLineItemCount","combinedBodyLength","bodyItem","bodyLineHeight","widthPadding","maxLineWidth","determineYAlign","doesNotFitWithAlign","xAlign","caret","determineXAlign","yAlign","chartWidth","determineAlignment","alignX","alignY","paddingAndSize","getBackgroundPoint","alignment","caretSize","caretPadding","topLeft","topRight","bottomLeft","bottomRight","getAlignedX","getBeforeAfterBodyLines","createTooltipContext","tooltipItems","overrideCallbacks","defaultCallbacks","labelCount","tooltipItem","invokeCallbackWithFallback","_b","beforeTitle","afterTitle","bodyItems","scoped","beforeFooter","afterFooter","labelColors","labelPointStyles","labelTextColors","positionAndSize","backgroundPoint","tooltipPoint","caretPosition","ptX","ptY","x3","y3","titleSpacing","labelColor","labelPointStyle","colorX","rtlColorX","yOffSet","colorY","outerX","innerX","bodySpacing","bodyAlign","displayColors","xLinePadding","fillLineOfText","bodyAlignForCalculation","textColor","tooltipSize","animX","animY","opacity","hasTooltipContent","positionChanged","caretX","caretY","plugin_tooltip","Tooltip","addIfString","addedLabels","findOrAddLabel","_getLabelForValue","CategoryScale","added","generateTicks$1","generationOptions","dataRange","precision","maxTicks","maxDigits","includeBounds","maxSpaces","rmin","rmax","countDefined","minSpacing","niceMin","niceMax","numSpaces","decimalPlaces","relativeLabelSize","LinearScaleBase","setMin","setMax","minSign","maxSign","stepSize","numericGeneratorOptions","LinearScale","log10Floor","changeExponent","isMajor","tickVal","rangeExp","rangeStep","startExp","generateTicks","minExp","significand","lastTick","LogarithmicScale","getTickBackdropHeight","measureLabelSize","determineLimits","fitWithPointLabels","limits","valueCount","pointLabelOpts","additionalAngle","plFont","hLimits","vLimits","updateLimits","buildPointLabelItems","createPointLabelItem","itemOpts","outerDistance","pointLabelPosition","yForAngle","getTextAlignForAngle","leftForTextAlign","isNotOverlapped","centerPointLabels","drawPointLabelBox","backdropColor","backdropLeft","backdropTop","backdropWidth","backdropHeight","drawPointLabels","pointLabels","pathRadiusLine","drawRadiusLine","gridLineOpts","createPointLabelContext","RadialLinearScale","leftMovement","rightMovement","topMovement","bottomMovement","angleMultiplier","scalingFactor","scaledDistance","pointLabel","distanceFromCenter","angleLines","INTERVALS","UNITS","sorter","adapter","isoWeekday","determineUnitForAutoTicks","minUnit","determineUnitForFormatting","determineMajorUnit","addTick","time","timestamps","timestamp","setMajorTicks","majorUnit","major","ticksFromTimestamps","TimeScale","_applyBounds","timeOpts","minor","weekday","hasWeekday","fmt","minorFormat","majorFormat","offsets","ticksOpts","tickLabelWidth","cosRotation","sinRotation","tickFontSize","exampleTime","displayFormats","exampleLabel","prevSource","nextSource","prevTarget","nextTarget","span","TimeSeriesScale","registerables","_CalcChartController","times","getColorSet","Brand","CalcChartController","_CalcHouseholdUsecaseController","workersApi","HouseholdUsecasesLogic","calcResult","CalculationRowUnit","framework","noPeriodStartDateUpdate","currentMonth","CalcHouseholdUsecaseController","CalculatorSection","isActive","isSelectionDone","CalculatorSections","expenses","benefits","deductions","isHouseholdDeductible","unionPaymentType","UnionPaymentType","allSalary","salaryAdditions","isResultsActive","Calculator2019ControllerCrudBindings","_Calculator2019Controller","workerCalc","isOverview","BootstrapStyle","AbsenceCauseCode","Calculator2019Controller","_CalcIrRowsController","IncomeTypesLogic","IrRowSourceType","Unit","CalcIrRowsController","_CalcReportController","templates","ReportType","renderingLang","TotalsReportConfigGenerator","xml","ESalaryMapper","xsltProcessor","xslDoc","xmlDoc","resultDocument","cumulativeCalc","CalculationMapper","Templates","optionsInput","CalcReportController","_CalcReportsController","getExportData","RowsReportConfigGenerator","IrRowsReportConfigGenerator","fileNames","getFileName","accountingData","payload","CalcReportsController","_CalcReportsDisplayController","CalcReportsDisplayController","_CalcRowTypeController","rowTypeService","valueArr","searchText","ignoreTop","showChildren","toOption","rowConfig","isParentAdded","isParentAddedAsSelf","rowTypeKey","rowTypeName","kindName","rowType","_result","rowsLogic","rowConfigsByCategory","irIncomeType","CalcRowTypeController","_CalcWorktimeController","anonCalcApi","HolidaysLogic","holidaysCtrl","absencesCtrl","HolidayCode","WageBasis","HolidayPayCalculation","detailsModel","month","monthlyAccrual","holiday","absenceDay","workdays","CalcWorktimeController","_CalcRowDimensionInputController","truncate","singleValue","CostAccountingDimensionScope","dimensions","CalcRowDimensionInputController","CalcRows2019ControllerBindings","_CalcRows2019Controller","editDialogParams","currentYear","previousYear","typesToShow","statuses","rowSources","cat","UserDefinedRowLogic","RowsUsecaseLogic","compRow","price","showEdit","vehicleTypes","vehicleAdditions","irCode","$close","EnumerationsLogic","defaultDimension","ordered","CalcRows2019Controller","_CalcSharingReceiptActionController","CalcSharingReceiptActionController","_CalcsIrRowsController","CalcsIrRowsController","CalculatorPanels","calcAsAny","panels","positionOfLastPanel","panel","_CreditTransferController","qrCode","getDocumentAndSvgNode","Barcodes","QrCodes","iban","BicHelper","Iban","CreditTransferController","_PayrollCrudController","payrollsApi","calcsApi","calendarEvents","taxcardsApi","oldCalc","originalCalc","actions","recalcs","apiCalc","worktime","resultCalc","oldId","empl","ui","noReloadValidation","forceSave","result2","resultInner","unlink","savedPayroll","removeImportedRows","payrolls","targetEmployments","newEmployments","calcsToSave","srcCalc","targetCalc","newRows","$msg","model","MessageThreadStatus","MessageFrom","ThreadedMessageType","calcsEmploymentIds","fetchedEmploymenIds","missingIds","calls","callIds","PayrollCrudController","_Payroll4CrudController","calcIds","odataResult","headerChangeInfo","doChangePeriod","apiCalcs","calcsResult","listItem","currentPage","loadedCalc","preCalc","page","truly","showCanvas","launcher","ContactType","calcToSave","pageSize","totalCalcCount","pageTotal","calcRange","preOriginalCalc","changedCalcs","isMerge","applyEmploymentDefaultRows","payrollItems","calcPromises","payrollItem","calcPromise","excludePeriodic","infoCalcs","hasException","Payroll4CrudController","_PaymentController","newChannel","PaymentController","_CalculationEditorController","ruleSet","ApiValidationErrorType","targetId","accountingReports","confirmationDescription","kevaEmploymentRegCodes","regCode","originalAccountingData","modifiedAccountingData","modified","removedAccount","CalculationEditorController","_CostAccountingController","dimensionForOptions","CostAccountingController","_CalcCostAccountingController","CalcCostAccountingController","_CalcRowCostAccountingController","CalcRowCostAccountingController","_PalkkausPersonalPaymentOverviewController","editDialogParameters","PalkkausPersonalPaymentOverviewController","_SalaryDateKindController","newSalaryDateKind","isCfa","SalaryDateKindController","_CalcLeavesController","periodStart","holidayYear","leave","absence","HolidayBonusPaymentMethod","period","dt","CalcLeavesController","ContactInfoController","_MessageThreadCrudController","messageApi","thread","endUserService","subject","totalMinutes","newMessage","calculationListItem","payrollListItem","readBy","readByValue","flagFor","startFrom","relevantMessages","messages","MessageThreadCrudController","_OmapalkkaController","embeddedUrl","OmapalkkaController","_VarmaBannerController","dialogData","pension","PensionCalculation","VarmaBannerController","_WelcomeController","overview","searchString","avatarId","taxCard","userSession","WelcomeController","_InputBase","hasRequiredValidator","readOnlyValue","validationErrors","InputBase","_DatepickerController","DatepickerController","_DatepickerPopupController","DatepickerPopupController","_DateRangeController","dayToCheck","newvalue","DateRangeController","_FormGroupController","legacyRequiredValue","forElement","colsCount","FormGroupController","_InputController","InputController","_InputAccountingTargetController","accountingTargets","accountingTargetId","refresher","InputAccountingTargetController","_InputBooleanController","InputBooleanController","InputEnumController","allValues","selectedValue","enums","matchingHiddenValue","hiddenValue","filterArr","inputName","storageKey","_InputCredentialController","workflowService","newCredentials","InputCredentialController","_InputDurationController","InputDurationController","_InputIncomeTypeController","InputIncomeTypeController","InputNumberController","valueNum","_InputOccupationTypeController","defaultList","Occupations","occupationId","occupation","InputOccupationTypeController","ALL_WEEKDAYS","Weekday","isPresent","isWeekdayStr","rang","repeat","toArray","padStart","targetLength","padString","sep","pymod","divmod","notEmpty","MONTH_DAYS","ONE_DAY","MAXYEAR","ORDINAL_BASE","PY_WEEKDAYS","isLeapYear","daysBetween","date1","date2","date1ms","date2ms","differencems","toOrdinal","fromOrdinal","ordinal","getMonthDays","getWeekday","monthRange","combine","dolly","cloneDates","dates","clones","sort","timeToUntilString","utc","untilStringToDate","until","dateTZtoISO8601","timeZone","dateStr","dateInTimeZone","localTimeZone","dateInLocalTZ","dateInTargetTZ","tzOffset","IterResult","tooEarly","tooLate","extendStatics","__extends","__","__assign","__spreadArray","pack","ar","CallbackIterResult","_super","_this","ENGLISH","contains","defaultGetText","defaultDateFormatter","day","ToText","rrule","gettext","language","dateFormatter","bymonthday","bynmonthday","byweekday","days","sortWeekDays","canConvert","RRule","nth","npos","wday","finalDelim","delim","delimJoin","delimiter","finalDelimiter","realCallback","rules","best","bestSymbol","name_1","parseText","ttr","S","AT","F","ON","wkd","decodeWKD","MDAYs","decodeM","on","the","decodeNTH","at","Frequency","freqIsDailyOrGreater","freq","fromText","common","toText","isFullyConvertible","Time","hour","minute","millisecond","DateTime","years","months","yearDiv","monthMod","wkst","filtered","byhour","dayDiv","hourMod","byminute","hourDiv","minuteMod","bysecond","minuteDiv","secondMod","daysinmonth","initializeOptions","invalid","_i","keys_1","defaultKeys","parseOptions","DEFAULT_OPTIONS","bynweekday","buildTimeset","millisecondModulo","timeset","parseString","rfcString","parseLine","parseDtstart","dtstartWithZone","tzid","dtstart","parseRrule","strippedLine","Days","parseNumber","optionKey","parseWeekday","parseIndividualNumber","wdaypart","DateWithZone","datestr","optionsToString","outValue","buildDtstart","strValues","ruleString","argsMatch","Cache","argsKeys","findCacheDiff","cachedObject","iterResult","M365MASK","M366MASK","M28","M29","M30","M31","MDAY366MASK","MDAY365MASK","NM28","NM29","NM30","NM31","NMDAY366MASK","NMDAY365MASK","M366RANGE","M365RANGE","WDAYMASK","wdaymask","rebuildYear","firstyday","yearlen","nextyearlen","yearordinal","yearweekday","baseYearMasks","firstwkst","wyearlen","no1wkst","div","mod","numweeks","lnumweeks","lyearweekday","lno1wkst","lyearlen","weekst","rebuildMonth","mrange","ranges","easter","yearStart","Iterinfo","buildPoslist","bysetpos","dayset","poslist","daypos","timepos","iter","emitResult","counterDate","makeTimeset","removeFilteredDays","rezonedDate","rezoneIfNeeded","currentDay","isFiltered","bymonth","byweekno","byeaster","byyearday","dayCounter","noCache","parsedOptions","before","inc","iterSet","_rrule","_exrule","_rdate","_exdate","_exdateHash","_accept","evalExdate","zonedDate","parseInput","rrulevals","rdatevals","exrulevals","exdatevals","parsedDtstart","splitIntoLines","breakDownLine","parms","_c","rdateTzid","parseRDate","buildRule","rset_1","RRuleSet","groomRruleOptions","rrulestr","extractName","unfold","validateDateParm","parm","rdateval","createGetterSetter","fieldName","field_1","_addRule","_addDate","exrule","rdatesToString","rrs","param","rdates","isUTC","dateString","rdate","_InputRruleController","InputRruleController","_ValidationSummaryController","errors","labelKey","descriptionKey","ValidationSummaryController","InputTimeController","DateTimes","InputHolidayMultipliersController","newKey","_InputHolidayRowTypeController","incomeType","isExclusive","baseType","nameParts","InputHolidayRowTypeController","_ActionButtonController","ActionButtonController","_AlertController","AlertController","_AvatarController","AvatarController","_BatchProcessController","$uibModalInstance","openApiDoc","remainingItems","itemsToProcess","defaultCols","statusEnum","party","infoProp","CellRenderingLogic","enumType","BatchProcessController","_CalendarController","dayEventsCount","series","startDay","endDay","currentMonthDay","daysInMonth","firstDayDayOfWeek","periods","singleDays","allEvents","dataRows","finalResult","isEventOnDay","defaultSeries","CalendarController","interaction","filterElements","getNearestItem","getElements","inRangeByAxis","getPointByAxis","nearestItems","evenPoint","isOlderPart","act","req","clamp","clampAll","inPointRange","hBorderWidth","inBoxRange","inRangeX","inRangeY","getElementCenterPoint","requireVersion","pkg","ver","strict","isPercentString","toPercent","toPositivePercent","boxAppering","defaultInitAnimation","getSize","positivePercent","calculateTextAlignment","toPosition","isBoundToPoint","initAnimationProperties","initAnim","applyDefault","execCallback","loadHooks","hooks","hooksContainer","widthCache","notRadius","fontsKey","fonts","isImageOrCanvas","translate","setBorderStyle","setShadowStyle","optFont","mapKey","calculateLabelSize","drawBox","drawLabel","getOpacity","optColor","setTextStrokeStyle","applyLabelDecoration","applyLabelContent","drawPointStyle","elementValue","limitedLineScale","scaleValue","isFinite","retrieveScaleID","axes","getDimensionByScale","getChartPoint","resolveBoxProperties","xDim","getChartDimensionByScale","yDim","resolvePointProperties","adjustCenterX","adjustCenterY","getChartCircle","resolveLineProperties","resolveFullLineProperties","resolveLimitedLineProperties","resolveBoxAndLabelProperties","resolveLabelElementProperties$1","scaleId","startProp","endProp","dim","calculateX","labelSize","calculatePosition$1","calculateY","boxOpts","padEnd","adjust","availableSize","rotated","cx","cy","moveHooks","eventHooks","updateListeners","handleEvent","handleMoveEvents","handleClickEvents","dispatchMoveEvents","checkElements","dispatchEvent","elementHooks","updateHooks","visibleElements","invokeHook","callbackHook","adjustScaleRange","annotations","getScaleLimits","changeScaleLimit","verifyScaleOptions","verifyScaleIDs","suggestedLimit","scaleLimitDefined","verifyProperties","scaleIDOption","BoxAnnotation","LabelAnnotation","drawCallout","getLabelSize","boxSize","measureRect","calculatePosition","pointX","pointY","callout","calloutPosition","resolveCalloutPosition","isPointInRange","separatorStart","separatorEnd","getCalloutSeparatorCoord","sideStart","sideEnd","getCalloutSideCoord","rotatedPoint","getCalloutSeparatorAdjust","side","getCalloutSideAdjust","resolveCalloutAutoPosition","xAdjust","yAdjust","xPoints","yPoints","pointInLine","interpolateX","interpolateY","sqr","rangeLimit","coordInCurve","pointInCurve","coordAngleInCurve","angleInCurve","LineAnnotation","mx","my","isOnLabel","intersects","inAxisRange","drawCurve","startOpts","endOpts","startAdjust","endAdjust","getArrowHeads","drawArrowHead","isLineInArea","limitLineToArea","getControlPoint","labelProperties","resolveLabelElementProperties","arrowHeadsDefaults","limitPointToArea","dy","lenSq","xx","yy","calculateLabelPosition","calculateAutoRotation","sizes","rotatedSize","calculateT","xCoordinateSizes","yCoordinateSizes","adjustLabelCoordinate","space","spaceAround","calculateTAdjust","lineSize","lineW","lineH","coordinate","halfSize","arrowStartOpts","arrowEndOpts","getLineAdjust","arrowOpts","arrowOffsetX","drawArrowHeadOnCurve","ps","pe","EllipseAnnotation","pointInEllipse","ellipse","xRadius","yRadius","cosAngle","sinAngle","PointAnnotation","PolygonAnnotation","pointIsInPolygon","axisPoints","sides","elProps","buildPointElement","halfBorder","isInside","A","B","annotationTypes","directUpdater","hooks$1","optDefs","resolveObj","resolveType","updateElements","resolveAnimations","resyncElements","annotationOptions","getOrCreateElement","getContext","toSkip","updateSubElements","resolveAnnotationOptions","animOpts","mainElement","subElements","subElement","initProperties","elementClass","defs","chartStates","drawableElements","getDrawableElements","drawElement","u","M","D","O","Y","dayjs","AdvancedFormat","QuarterOfYear","LocalizedFormat","CustomParseFormat","FORMATS","_adapters","_format","validatedWeekday","annotationPlugin","_ChartController","ChartController","_JsonFormatterController","isUrl","kvs","ellipsis","currentKeys","ck","icon","JsonFormatterController","_NaviController","naviService","show","NaviController","_SpinnerController","knownTerms","defaultText","SpinnerController","_TabController","slot","found","salaxyTabNode","salaxyTabsNode","salaxyTabNodes","tagName","TabController","_TabsController","tab","newActiveTabIndex","selectedTab","newTab","resort","TabsController","_UiTranslatorController","uiTranslatorService","fullkey","fullKey","baseDictionary","texts","serviceModelTranslation","newFullKey","fullPath","allKeyValues","splitKeys","diffBase","subKeys","currentNode","UiTranslatorController","_ODataActionsController","fileService","Calculations","DataMappersLogic","ODataActionsController","_ImportController","Culture","ImportBatch","parserGuess","isDebug","ImportController","_ExportController","exporterId","ExportLogic","newMapper","ExportController","CoreFeature","columnsChanged","force","oldOption","newOption","convert","Helpers","structure","objectProto","arrayProto","Popup","touch","parentOffset","containerOffset","parentEl","coords","scrollTop","Module","priority","lookupIndex","renderInPosition","menuEl","menuContainer","defaultAccessors","Accessor","accessor","rowComponent","colComponent","generateParamsList","serializeParams","encoded","urlBuilder","defaultLoaderPromise","generateParamsList$1","defaultContentTypeFormatters","form","Ajax","ajaxParams","ajaxConfig","defaultPasteActions","singleCell","startCell","startRow","rowWidth","dataLength","defaultPasteParsers","clipboard","headerFindSuccess","columnMap","colWidth","startCol","itemLength","Clipboard","plain","rowData","internal","sel","textRange","valid","blocked","CalcComponent","cells","CellComponent","mutate","Cell","vertAligns","hozAligns","classNames","containerOnly","ColumnComponent","Column","ifVisible","toColumn","nextCol","prevCol","updates","defaultColumnOptions","def","newCol","contentElement","titleHolderElement","titleElement","contents","dataObj","parentHeight","traverse","updateBranches","colDefs","responsiveToggle","childWidth","minWidth","cellCount","setTo","RowComponent","Row","inFragment","minHeight","updatedData","newRowData","attrname","findCell","toRow","blockRedraw","defaultCalculations","calcParams","sum","unique","ColumnCalcs","viewable","paramKey","groupObj","subGroups","subGroupResults","subgroup","DataTree","dummyEl","firstCol","childArray","oldControl","allChildren","subChildren","childData","childRow","childIndex","recurse","csv","setFileContents","fileContents","pdf","autoTableParams","rowGroupStyles","rowCalcStyles","jsPDFParams","parseRow","xlsx","sheetName","workbook","tableFeatures","writeOptions","generateSheet","merges","sheet","s2ab","jsonLines","defaultDownloaders","Download","interceptCallback","downloadFunc","buildLink","mime","groupHeader","maskInput","maskLetter","maskNumber","maskWildcard","fillSymbols","symbol","onRendered","success","cancel","editorParams","cellValue","onChange","textarea","vertNav","scrollHeight","heightNow","blurFunc","inputFormat","DT","convertDate","newDatetime","luxDate","luxTime","luxDateTime","Edit","editor","cellEl","clickStop","listEl","attribs","valueKeys","valueCheck","character","responseValues","placeholder","term","inputValues","as","bs","b1","L","rx","rd","emptyAlign","filterFunc","startVis","blur","select","autocomplete","star","maxStars","stars","starsHolder","starChange","buildStar","starHolder","nextStar","changeValue","mouseDrag","mouseDragWidth","updateValue","calcVal","tickCross","tristate","indetermValue","indetermState","trueValueSet","falseValueSet","setValue","checkedValue","defaultEditors","Edit$1","newRow","nextCell","prevRow","nextRow","prevCell","forceEdit","topEdge","bottomEdge","rowEl","leftEdge","rightEdge","allowEdit","rendered","editFinished","cellEditor","editIndex","ExportRow","indent","ExportColumn","Export","colVisProp","colData","groupData","subGroup","subGroupData","visProp","headerDepth","exportRows","parseColumnGroup","exportCols","headerEl","bodyEl","rowFormatter","setup","cellStyle","cellWrapper","formatComponent","holder","lookup","fromStyle","defaultFilters","filterVal","rowVal","filterParams","keywords","keyword","Filter","filterType","filterChangeCheck","fieldVal","colVal","reinitialize","filterElement","editorElement","typingTimer","searchTrigger","onRenderedCallback","headerPos","filterList","activeRows","rowList","activeRowComponents","subFilter","plaintext","formatterParams","html$1","textarea$1","money","floatVal","integer","rgx","decimalSym","thousandSym","negativeSign","urlPrefix","download","labelTraverse","image","tickCross$1","truthy","cross","datetime$1","outputFormat","datetimediff","humanize","star$1","starActive","starInactive","traffic","percentValue","progress$1","legendAlign","legendColor","barEl","barContainer","legendEl","holderEl","buttonTick","buttonCross","rownum","responsiveCollapse","toggleList","collapseEl","rowSelection","checkbox","defaultFormatters","Format","mockCell","entityMap","FrozenColumns","allCells","leftParents","leftMargin","rightMargin","visibleRows","otherRows","FrozenRows","frozenRows","GroupComponent","Group","groupManager","generator","oldGroup","elementsOnly","arrow","toggleElement","groupID","groupKey","toIndex","includeChildren","GroupRows","groupBy","startOpen","langValue","lookupFunc","groupRows","groupValues","toGroup","fromGroup","groupComponents","groupList","groupListData","oldGroups","newGroupNeeded","oldRowGroup","oldGroupPath","newGroupPath","samePath","groupPath","groupId","onlyGroupHeaders","defaultUndoers","defaultRedoers","History","oldRow","HtmlTableImport","defaultOptions","optionsArr","optionsList","attrib","csvImporter","inQuote","nextChar","json$1","arrayImporter","defaultImporters","Import","importFormat","importer","extension","extensions","parsedData","noTouch","componentObj","defaultBindings","defaultActions","rowManager","newPos","scrollMax","Keybindings","mergedBindings","bindingList","symbolsList","symbols","Menu","headerMenuEl","menu","parentPopup","popup","itemEl","MoveColumns","colEl","startXMove","nextColWidth","prevColWidth","nextColWidthLast","prevColWidthLast","moveToCol","headerElement","headersElement","movingCells","columnHolder","scrollLeft","xPos","scrollPos","MoveRows","startYMove","nextRowHeight","prevRowHeight","nextRowHeightLast","prevRowHeightLast","moveToRow","pageX","pageY","rowHolder","yPos","connectionTables","query","dropEvent","sender","fromRow","fromTable","toTable","defaultMutators","Mutator","mutator","links","linkCell","currentRow","totalRows","totalPages","showingEl","valueEl","ofEl","totalEl","rowsEl","pages","defaultPageCounters","Page","displayRows","testElRow","testElCell","button","pageSizes","pageCounter","pageSelectLabel","paginationCounterHolder","rowCount","leftSize","rightSize","actualRowPageSize","actualStartRow","actualRows","defaultReaders","cookiePos","defaultWriters","expireDate","Persistence","testKey","retrievedData","sorters","headerFilters","oldCols","newCols","mergeAllNew","definitions","excludedKeys","defStore","colDef","Popup$1","headerPopupEl","renderedCallback","contentsEl","Print","scrollX","scrollY","footerEl","tableEl","footerContent","ReactiveData","oldRows","childField","origFuncs","update","ResizeColumns","frozenOffset","variableHeight","nearestColumn","handleDown","oldWidth","handleEl","mouseMove","startDiff","moveDiff","blockedBefore","blockedAfter","mouseUp","ResizeRows","prevHandle","prevHandleDown","ResizeTable","tableStyle","nodeHeight","nodeWidth","ResponsiveLayout","colCount","working","mockCellComponent","titleData","valueData","node_content","titleHighlight","SelectRow","prevSelected","selectable","endSelect","lastClickedRowIdx","rowIdx","fromRowIdx","toRowIdx","toggledRows","toggledRow","rowMatch","rowInfo","selectedRow","deselected","number$1","aRow","bRow","alignEmptyValues","thousand","datetime$2","date$1","time$1","boolean","el1","el2","alphanum","defaultSorters","Sort","sortList","arrowEl","newSortList","sortListActual","rowComponents","sortObj","sortEl","sorterCount","sortItem","el1Comp","el2Comp","RangeComponent","Range","rangeManager","rowsCount","isRowHeader","_vDomTop","_vDomBottom","_vDomLeft","_vDomRight","topLeftCell","bottomRightCell","structured","clearValue","SelectRange","selectedColumns","selectedColumn","rangeIdx","jump","expand","moved","rangeEdge","emptyStart","emptySide","currentCell","rowPos","colPos","isStartingCellEmpty","isLeftOfStartingCellEmpty","jumpCol","targetCells","isRightOfStartingCellEmpty","isTopOfStartingCellEmpty","jumpRow","isBottomOfStartingCellEmpty","tableHolder","rowHeader","withinHorizontalView","withinVerticalView","occupied","activeCell","colIdx","defaultValidators","parameters","cellData","Validate","cancelled","validators","failedValidators","invalidIndex","OptionsList","msgType","userOptions","warn","Renderer","includingBuffer","BasicHorizontal","rowFrag","VirtualDomHorizontal","old","colEnd","ex","widthDiff","ColumnManager","renderClass","renderers","nextToColumn","topColumn","parentIndex","nextEl","fieldRoot","fromIndex","fixedWidth","BasicVertical","tableFrag","rowTop","VirtualDomVertical","topRow","topOffset","topDiff","bottomDiff","topFound","bottomRow","forceMove","topPad","rowsHeight","rowHeight","heightOccupied","topPadHeight","rowFragment","renderedRows","totalRowsRendered","rowsToRender","fixedHeight","containerHeight","avgRowHeight","resized","fillableSpace","addedRows","paddingAdjust","initialized","removableRows","RowManager","leftDir","topDir","allIndex","activeIndex","displayIndex","refreshDisplayOnly","chainResult","rowOnly","skipStage","stage","cascadeOrder","scrollbarWidth","initialHeight","otherHeight","FooterManager","InteractionManager","listenerMap","leaveList","linkedKeys","components","comp","targets","componentMap","classList","elTargets","targetMatches","previousTarget","ComponentFunctionBinder","funcName","DataLoader","requestNo","shouldLoad","ExternalEventBus","subscribed","notifiers","callResult","InternalEventBus","subscriber","confirmed","DeprecationAdvisor","TableRegistry","Tabulator","fitData","forced","fitDataGeneral","fitDataStretch","colsWidth","tableWidth","gap","lastCol","fitColumns","flexWidth","flexGrowUnits","flexColWidth","flexColumns","fixedShrinkColumns","flexShrinkUnits","overflowWidth","gapFill","calcWidth","scaleColumns","freeSpace","shrinkCols","oversizeCols","oversizeSpace","remainingSpace","remainingFlexGrowUnits","changeUnits","undersizeCols","calcGrow","calcShrink","defaultModes","Layout","dataChanged","defaultLangs","Localize","desiredLocale","traverseLang","trans","fillPath","pathArray","rootPath","Comms","selectors","connections","connection","con","coreModules","ModuleBinder","tabulator","orderedStartMods","orderedEndMods","unOrderedMods","core","Alert","ua","responses","foundRows","fromColumn","required","TabulatorFull","XLSX","DataImportControllerBase","helpData","emptyRow","helpSheet","fileData","sheetData","sheetRow","setData","isValidRow","ApiImportStatus","fieldSchema","enumMetadata","y1900","lowerValue","dataOk","_CompanyImportController","importsApi","sourceRow","getTargetKey","getSourceKey","importObj","sourceRows","addresses","selectionDialog","CompanyImportController","_CalcImportController","imports","groupCalcs","firstCalc","rowMap","rowSelector","DataMapperSelector","workerGroups","workerChecks","workerGroupKey","checkObj","ApiCheckStatus","CalcImportController","_ImportStagingController","WorktimeApiConnector","commitSingle","payrollId","totals","committedCalc","ipt","incoming","ImportStagingController","_WorkerImportController","salaryDefaultSelector","WorkerImportController","_CustomerInvoiceCrudController","CustomerInvoiceCrudController","_InvoiceCrudController","InvoiceCrudController","_InvoicesCreateController","inProgress","exceptions","paid","payrolls4Api","salaryDateKind","closeFunc","idsToPay","refreshCurrentCalculation","InvoicePaymentType","calcController","payrollController","invoiceCreate","InvoicesCreateController","_PaymentChannelController","PaymentChannelApi","setChannel","PaymentChannelController","_InvoiceToolsController","fileTypes","fts","hideLoading","withoutContent","pdfArr","sepaData","finvoiceArr","invoiceType","fileTypeId","fileType","payerIbanNumber","InvoiceToolsController","_InvoiceSepaController","invoicesFullApi","invService","sepaAjax","warning","Promises","sepaChannel","loadItems","nextPageLink","available","readInvoice","updatedInvoice","blobs","InvoiceSepaController","_InvoiceReportController","InvoiceMapper","InvoiceReportController","_CompanyInvoicesController","invoiceService","companyAjax","updatePeriodicInvoices","getConfirmText","_arr","oldDateFilterQueryOption","filterInvoices","netInvoices","taxInvoices","unionInvoices","foreclosureInvoices","periodicInvoices","toBeRemoved","periodicInvoice","CompanyInvoicesController","_InvoiceAlertsController","paymentChannels","paymentChannel","paymentChannelItems","getInstructionText","getLinks","urls","InvoiceAlertsController","_EditDialogController","EditDialogController","_ModalGenericDialogController","ModalGenericDialogController","_CalcSharingController","sharingCalculationsApi","SharingUriType","employer","createSharingMessageForEmployer","distinctItems","CalcSharingController","_EmployerListController","employerId","EmployerListController","_EmployerReportController","report","iconComponents","initials","indx","id1","EmployerReportController","_EmployerSelectController","EmployerSelectController","_HouseholdDeductionReportController","employerReport","yearlyReport","deductibleAmount","HouseholdDeductionReportController","_HouseholdYearCrudController","householdYearsApi","updatedCalc","HouseholdYearProcessingStatus","deductibleTotal","maxAmount","sideCosts","now","odata","logicalDate","yearReport","newModel","pdfs","TaxDeductionWorkCategories","HouseholdYearCrudController","_PersonAccountController","person","supportedHashes","PersonAccountController","_WorkerReportController","endYear","WorkerReportController","_TimesheetWorkerDemoController","msgApi","$interval","newUsecase","TimesheetWorkerDemoController","_WorkerTimerController","timerMessage","messageIndex","contentData","TimesheetInputModification","padTo2Digits","lk1","costAccountingSettings","endTime","startTime","entryStartTime","entryEndTime","xStartTime","xEndTime","WorkerTimerController","WorkerHourlyReportControllerBindings","_WorkerHourlyReportController","targetDate","WorkerHourlyReportController","WorkerExpenseReportControllerBindings","_WorkerExpenseReportController","WorkerExpenseReportController","_RecordsController","wfEvents","attachment","attachments","recordAndEvent","serverRecordTypes","wfItem","uploadUrl","orphans","orphan","eventsOfType","RecordsController","_AccountingReportCrudController","filesApi","logicalDateExcluding","currentLoadingId","AccountingReportCrudController","_AccountingReportQueryController","PeriodDateKind","selectedCalculations","selectedCalculation","AccountingReportQueryController","_AccountingReportRowsController","AccountingMapper","ledgerAccount","AccountingReportRowsController","_AccountingReportToolsController","AccountingTargetLogic","targetOption","tabbed","txt","availableMethods","exportMethodId","localeId","schemeId","exportMethod","isFinnish","addPrefix","addQuotes","formatAsText","AccountingChannel","AccountingReportToolsController","_IrEarningsPaymentCrudController","absencesApi","irepr","epr","startAt","aso","nonErrorEntries","workerAbsences","selectedAbsences","absencesStartDate","absencesEndDate","causeCode","IrEarningsPaymentCrudController","_IrPayerSummaryCrudController","irpsr","psr","IrPayerSummaryCrudController","_ReportsController","ReportsController","_SalaryReportCrudController","SalaryReportCrudController","_PayCertificateController","reports","isSelected","weeks","PayCertificateController","ConfigurableGridReportControllerBase","agGridModule","agGrid","eGridDiv","templateId","currentTemplate","saveTemplate","DatasetStatus","DatasetType","saveResult","editedTemplate","newTemplate","savedTemplate","workerPeriod","selectionResult","periodResult","workerIds","dataResult","customerTemplates","_CalculationReportController","sortingDateComparator","mA","mB","filterDateComparator","columnDefs","irGroupDef","typeGroupDef","employerCalcDef","workerCalcDef","totalsDef","totalGroupDef","incomeTypes","filterModel","periodDateKind","preset","calculationDef","dimensionDef","incomeTypeDef","hide","rowTypeDef","workerTotalsDef","employerTotalsDef","totalFields","colId","rowGroup","aggFunc","CalculationReportController","_AccountingRowReportController","holidays","pivot","pivotIndex","AccountingRowReportController","_SummaryReportDisplayController","summaryReportData","SummaryReportDisplayController","_SummaryReportController","SummaryMapper","SummaryReportController","_AccountingReportDisplayController","getAccountingData","AccountingReportDisplayController","_WorkerSummaryReportController","workerSummaryReportData","WorkerSummaryMapper","WorkerSummaryReportController","_WorkerSummaryReportDisplayController","reportUrl","WorkerSummaryReportDisplayController","_HolidayReportController","holidayYears","queryDebt","yearData","resultRow","yearCalc","HolidayReportController","_SalarySlipDownloadController","zipBlob","SalarySlipDownloadController","_AccountingHolidayPayDebtReportQueryController","AccountingHolidayPayDebtReportQueryController","_HolidayPayReportQueryController","holidayYearsApi","crudItemId","irRow","HolidayPayReportQueryController","_SummaryReportQueryController","irReportRows","reportName","hourlySalaryRowIndex","monthlySalaryRowIndex","salaryPaymentHoursRow","hourlySalariesCals","salaryPaymentMonthsRow","monthlySalariesCals","AllowanceCode","DailyAllowanceKind","EmploymentTerminationKind","WorkingTimeCompensationKind","RemunerationKind","OtherCompensationKind","NonProfitOrgKind","TrainingKind","PaidSickLeaveKind","SummaryReportQueryController","_AccountantController","removalDisabled","accountant","AccountantType","AccountantController","_AccountingChannelSettingsController","closeFn","coa","ownerId","AccountingTargets","targetToSave","AccountingChannelSettingsController","_AccountingTargetCrudController","EmploymentRelationType","isCredit","account","selectedAccount","getKey","sortKeys","debit","credit","isDebet","addToEnd","copyRow","removeFromTargetCoa","addToStart","flags","FileLogic","fileDelimeter","FileDelimiter","firstRow","mappingResult","targetCoaAccount","rulesetAccount","accountCandidate","digitsArr","firstKey","secondKey","AccountingTargetCrudController","_CompanySettingsController","contract","allContracts","SettingsStatus","methods","WorkerSalarySlipDeliveryMethod","allItems","logo","dataUri","contracts","today","CompanySettingsController","_InsuranceWizardController","partnerServices","insuranceAction","LocalTapiolaInsuranceOrderType","asap","firstDate","secondDate","thirdDate","fourthDate","orderTypes","InsuranceWizardController","_OwnerSettingsController","beneficialOwnersApi","$timoeut","numberOfShares","percentOfShares","singleOwner","OwnerSettingsController","_PaymentChannelSettingsController","isExternal","channelInEdit","supportedCompanies","isPensionIncludedSupported","channelSettings","saveSettings","channelToSave","PaymentChannelSettingsController","_RowTypesSettingsController","nextId","settingsRow","editableType","RowTypesSettingsController","_ServiceModelCrudController","open","level1","level2","objToStore","TranslationsInstance","resetCommitted","schemas","ServiceModelCrudController","_SxyCodeEditorController","iFrame","clonedElement","SxyCodeEditorController","_SxyFormController","FormHelpers","propPath","rawErrors","SxyFormController","_SxyFormElementController","SxyFormElementController","_SxyGridController","selectedRows","fullMapper","exptMapper","mappers","itemToValidate","schemaDoc","fields","excludeArr","headerName","enumValues","salaxyGridModule","gridWrapper","SxyGridController","_SxyInputController","childName","arrayItemsType","childType","childvalue","defaultLabel","readOnlyFormValue","requireValue","disableValue","defaultTop","includeArr","transEl","transScope","textOrElem","enumArr","enumName","enumFormat","SxyInputController","_SxySchemaEditorController","SxySchemaEditorController","_SxyTableController","colDefOrKey","tableOptions","keyString","arrayCandidate","_formatterParams","_onRendered","SxyTableController","_AccountResetController","testApi","AccountResetController","_SmokeTestController","sessionSrv","jsonTest","calcReport","SmokeTestController","_ReferenceObjectCrudController","ReferenceObjectCrudController","AbsencePeriodsControllerBindings","_AbsencePeriodsController","abs","AbsencePeriodsController","_EmploymentCrudController","taxcardData","createIfNotExists","contact","cardType","employmentList","fullEmployment","Country","socialSecurity","pensionCalculation","insuranceCompany","socSecExceptions","workerAccount","workerAccountValue","EmploymentRelationSalaryPaymentMethod","EmploymentCrudController","_EmploymentTaxcardsController","EmploymentTaxcardsController","_EmploymentWizardController","useRealPersonaIdRange","commonSteps","closeFunction","card","Validation","EmploymentWizardController","_HolidayYearAccrualController","saved","cumulative","startOfMonth","HolidayAccrualSource","startSaldo","HolidayYearAccrualController","_HolidayYearCrudController","hy","thisYear","spec","itemData","missingYear","itemToSave","savedValue","keepView","obj1","obj2","isAccrualView","HolidayYearCrudController","HolidayYearHolidaysControllerBindings","_HolidayYearHolidaysController","handleResult","confirmResult","HolidayYearHolidaysController","_HolidayYearPaidController","paidLeave","AnnualLeavePaymentKind","HolidayYearPaidController","_MyTaxcardsController","_taxcards","MyTaxcardsController","_TaxcardManualEditController","TaxCardIncomeType","todayYear","yearsAllowed","forYear","TaxcardManualEditController","_TaxcardCrudController","savedCard","TaxcardCrudController","_TaxcardIncomeLogController","TaxcardIncomeLogController","_WorkerAbsencesCrudController","todayDay","monthStart","monthEnd","previousMonthStart","previousMonthEnd","absences","WorkerAbsencesCrudController","_WorkerAccountCrudController","WorkerAccountCrudController","_WorkerAssureController","detailsCtrl","listCtrl","WorkerAssureController","_CalendarEventsCrudController","icons","occ","RecurringEventCreateMode","newAction","CalendarActionType","previewRange","startMonth","CalendarEventsCrudController","_CalendarOccurencesController","occurence","nextDay","mondayDay","CalendarOccurencesController","_DatasetsCrudController","executor","ActionExecutor","dataObjectIndex","docUrl","schemaKey","DatasetsCrudController","_UsecasesCrudController","chr","schemaNames","UsecaseActionType","calcType","UsecasesCrudController","_WorkflowController","wfType","assignedTo","workflowData","WorkflowController","isWorkflowPayload","isMessagesListItem","_WorkflowBadgeController","records","eventsOfTypes","eventOfType","ensureItem","messageString","uiStartX","uiEndX","rest","messageEndX","aIdx","tIdx","WorkflowBadgeController","ComponentBase","AccountInfo","AssurePartner","AuthCard","AuthorizedAccounts","AuthorizingAccounts","Certificates","Credentials","LanguageSelector","LoginButton","Signing","UserInfo","AccountAvatarEdit","AccountContactEdit","CalcEmployment","CalcRowsEditor","CalcUsecase","PayrollDetails","PayrollDetailsList","PayrollEdit","PayrollList","PayrollSelectList","PayrollDetailsSelectList","CalcIrRows","CalcRows2019Editor","CalcRowCostAccounting","CalcRowDimensionInput","CalcsIrRows","Calc","CalcChart","CalcDashboard","CalcList","CalcNewIntro","CalcReport","CalcReports","CalcResults","CalcRowType","CalcSharingReceiptAction","CalcLeaves","CalcWorkerInfo","CalcWorktime","PayButton","CalcEditor","CalcCostAccounting","CostAccounting","SalaryDateKindButton","ContactInfo","MessageThread","VarmaBanner","Welcome","HourlyReport","TimerBindings","Timer","ExpenseReport","MessageThreadList","Datepicker","DatepickerPopup","DateRange","FormGroup","Input","InputBoolean","InputEnum","InputCredential","InputDuration","InputIncomeType","InputNumber","InputRrule","InputOccupationType","Textarea","ValidationSummary","InputAccountingTarget","InputTime","InputHolidayRowType","InputHolidayMultipliers","ActionButton","Avatar","Calendar","JsonFormatter","NaviSitemap","NaviStarterLayout","Spinner","Tab","Tabs","UiTranslator","DataImportComponentBase","CalcImport","CompanyImport","ImportStaging","WorkerImport","CreditTransfer","InvoiceEdit","InvoiceList","InvoicePreview","InvoicesCreate","PaymentChannelInvoicePreview","InvoiceTools","InvoiceReport","CompanyInvoices","InvoiceAlerts","WorkerAssure","OdataFooter","OdataTable","OdataActions","AccountAuthorizationPerson","AccountAvatarEditPerson","AccountContactEditPerson","AccountDetailsPerson","AccountDetailsEditPerson","AccountInfoPerson","AccountInsuranceEditPerson","EmployerList","EmployerReport","EmployerSelect","CalcHouseholdUsecase","CalcSharing","CalcSharingInfo","HouseholdDeductionReport","WorkerReport","HouseholdYearList","HouseholdYearDetails","AccountingReportList","AccountingReportQuery","AccountingReportRows","AccountingReportTools","AccountingReportViewer","CalculationReport","HolidayReport","IrEarningsPayment","IrEarningsPaymentList","IrPayerSummary","IrPayerSummaryList","PayCertificate","ReportList","SalaryReportList","AccountingRowReport","SummaryReport","WorkerSummaryReport","AccountingHolidayPayDebtReportQuery","HolidayPayReportQuery","SummaryReportQuery","Accountant","AccountingSettings","AccountingTargetDetails","AccountingTargetSettings","CostAccountingSettings","HolidaySettings","Insurance","InsuranceSettings","OwnerSettings","PaymentChannelSettings","PaymentSettings","ProSettings","RowTypesSettings","ServiceModelDetails","SxyAlert","SxyCodeEditor","SxyFieldset","SxyForm","SxyGrid","SxyInput","SxySchemaEditor","SxyTable","AccountReset","SmokeTest","HolidayYearAccrual","HolidayYearHolidays","HolidayYearPaid","WorkerHolidays","EmploymentTaxcards","TaxcardDetails","TaxcardIncomeLogBindings","TaxcardIncomeLog","TaxcardManualEdit","TaxCardsList","AbsencePeriods","EmploymentDetails","WorkerAbsences","WorkerDetails","EmploymentList","CalendarEventDetails","DatasetDetails","UsecaseDetails","Records","WorkflowButtons","WorkflowReopen","WorkflowBadge","ComponentsRegistration","routeToRegExp","slash","ngRouteModule","$RouteProvider","instantiateRoute","$routeMinErr","isEagerInstantiationEnabled","routeCopy","redirectPath","forceReload","preparedRoute","preparedRouteIsUpdateOnly","$route","fakeLocationEvent","prepareRoute","commitRoute","newParams","switchRouteMatcher","$locationEvent","lastRoute","parseRoute","isNavigationUpdateOnly","nextRoute","nextRoutePromise","getRedirectionData","handlePossibleRedirection","keepProcessingRoute","resolveLocals","oldPath","oldSearch","getTemplateFor","newRoute","oldRoute","segmentMatch","$RouteParamsProvider","ngViewFactory","ngViewFillContentFactory","previousLeaveAnimation","cleanupLastView","angularRoute","$animateCss","expandingExpr","expandedExpr","collapsingExpr","collapsedExpr","css","cssTo","getScrollFromElement","expandDone","collapse","collapseDone","shouldCollapse","accordionConfig","openGroup","closeOthers","groupScope","accordionCtrl","accordionGroupCtrl","transclude","getHeaderSelectors","dismissOnTimeout","buttonConfig","buttonsCtrl","uncheckableExpr","uncheckable","getTrueValue","getCheckboxValue","getFalseValue","slides","SLIDE_DIRECTION","currentInterval","isPlaying","destroyed","slide","setActive","findSlideIndex","nextSlide","goNext","resetTimer","restartTimer","noTransition","resetTransition","currentIdx","timerFn","carouselCtrl","removeClass","directionClass","removeClassFn","SPECIAL_CHARACTERS_REGEXP","formatCodeToRegex","_date","getFormatCodeToRegex","createParser","quoteIndex","inLiteral","createFormatter","literalIdx","constructLiteralFormatter","constructFormatterFromIdx","endIdx","currentPosStr","baseDate","datesetter","timesetter","toTimezone","fromTimezone","ON_REGEXP","IS_REGEXP","linkedScopes","expToData","onExpMatches","onExp","expsStr","exps","addForExp","removeScope","compareWithExp","watchFn","compareWithVal","newActivated","thisVal","removedScope","newWatchScope","datepickerConfig","$datepickerLiteralWarning","$datepickerSuppressError","dateParser","ngModelOptions","watchListeners","dateObject","ngModelCtrl_","extractOptions","initDate","arrays","setMode","focusElement","DAYS_IN_MONTH","getDaysInMonth","startDate","firstDayOfMonth","difference","numDisplayedFromPreviousMonth","thursdayIndex","numWeeks","curWeek","getISO8601WeekNumber","_date1","_date2","checkDate","getStartingYear","datepickerCtrl","daypickerCtrl","monthpickerCtrl","SCROLLBAR_WIDTH","BODY_SCROLLBAR_WIDTH","OVERFLOW_REGEX","PLACEMENT_REGEX","BODY_REGEX","offsetParent","isStaticPositioned","isBody","bodyElem","scrollElem","elemStyle","scrollParent","includeHidden","overflowRegex","includeSelf","documentEl","excludeStatic","spStyle","includeMagins","elemOffset","elemBCR","useDocument","includePadding","offsetBCR","offsetParentBCR","offsetParentStyle","placement","autoPlace","hostElem","targetElem","appendToBody","targetWidth","targetHeight","hostElemPos","targetElemPos","viewportOffset","targetElemStyle","adjustedSize","xOverflow","yOverflow","placementClasses","containerPosition","currentHeight","innerElem","isTooltip","arrowElem","arrowCss","borderProp","borderRadiusProp","$position","datepickerPopupConfig","$datepickerPopupLiteralWarning","isHtml5DateInput","dateFormat","closeOnDateSelection","onOpenFocus","datepickerPopupTemplateUrl","datepickerTemplateUrl","popupEl","datepickerEl","scrollParentEl","ngModel","$popup","altInputFormats","_ngModel_","newDateFormat","parseDateString","inputKeydownBind","documentClickBind","positionPopup","dpContainsTarget","popupContainsTarget","dpElement","debounceTime","timeoutPromise","$$multiMap","openScope","openedContainers","dropdownScope","appendTo","openedDropdowns","openDropdown","toClose","dropdown","closeDropdown","openedScopes","dropdownToClose","dropdownElement","dropdownElementTargeted","toggleElementTargeted","dropdownConfig","uibDropdownService","templateScope","appendToOpenClass","openClass","getIsOpen","setIsOpen","toggleInvoker","keynavEnabled","keyCode","removeDropdownMenu","wasOpen","appendToEl","appendToBodyValue","rightalign","scrollbarPadding","appendOffset","openContainer","dropdownOpenClass","hasOpenClass","isOnlyOpen","toggleClass","tplContent","newEl","dropdownCtrl","tplUrl","toggleDropdown","invocables","resolves","resolveIter","$modalStack","setIsAsync","modalRenderDeferObj","animationPromise","inputWithAutofocus","$$stackedMap","$uibPosition","OPENED_MODAL_CLASS","backdropDomEl","backdropScope","openedWindows","openedClasses","topModalIndex","previousTopOpenedModal","ARIA_HIDDEN_ATTRIBUTE_NAME","tabbableSelector","isVisible","backdropIndex","topBackdropIndex","opened","newBackdropIndex","removeModalWindow","modalInstance","elementToReceiveFocus","modalWindow","appendToElement","removeAfterAnimate","modalBodyClass","areAnyOpen","toggleTopWindowClass","checkRemoveBackdrop","toggleSwitch","domEl","closedDeferred","asyncDeferred","asyncPromise","afterAnimating","keydownListener","focusChanged","modalOpener","currBackdropIndex","angularDomEl","applyAriaHidden","getSiblings","elemIsAlreadyHidden","ariaHiddenCount","broadcastClosing","resultOrReason","closing","unhideBackgroundElements","hiddenEl","newHiddenCount","topModal","modalDomEl","modalDomE1","$modalProvider","$uibResolve","$modal","getTemplatePromise","promiseChain","modalResultDeferred","modalOpenedDeferred","modalClosedDeferred","modalRenderDeferred","templateAndResolvePromise","resolveWithTemplate","samePromise","tplAndVars","providedScope","modalScope","ctrlInstance","ctrlInstantiate","ctrlLocals","constructLocals","instanceOnScope","injectable","newTotal","oldTotal","clickAllowed","uibPaging","uibPagerConfig","paginationCtrl","uibPaginationConfig","forceEllipses","boundaryLinkNumbers","pageLabel","makePage","getPages","startPage","endPage","isMaxSized","previousPageSet","secondPageLink","firstPageLink","nextPageSet","secondToLastPageLink","lastPageLink","triggerMap","globalOptions","triggers","openedTooltips","keypressListener","ttType","defaultTriggerShow","getTriggers","startSym","endSym","tElem","tooltipLinker","tooltipCtrl","tooltipLinkedScope","transitionTimeout","showTimeout","hideTimeout","positionTimeout","adjustmentTimeout","hasEnableExp","ttScope","repositionScheduled","isOpenParse","contentParse","observers","lastPlacement","positionTooltip","ttPosition","elementPos","adjustment","toggleTooltipBind","hideTooltipBind","showTooltipBind","cancelHide","prepareTooltip","cancelShow","createTooltip","assignIsOpen","removeTooltip","prepObservers","unregisterObservers","closeDelay","bodyHideTooltipBind","hideOnEscapeKey","unregisterTriggers","prepTriggers","showTriggers","hideTriggers","appendToBodyVal","appendKey","origScope","$uibTooltip","progressConfig","animate","getMaxOrDefault","totalPercentage","maxParam","progressCtrl","ratingConfig","tmpTitles","ratingStates","states","newViewValue","ratingCtrl","oldIndex","previousIndex","findTabIndex","previousSelected","newActiveIndex","tabsetCtrl","isTabHeading","timepickerConfig","hoursModelCtrl","minutesModelCtrl","secondsModelCtrl","meridians","padHours","hoursInputEl","minutesInputEl","secondsInputEl","mousewheel","arrowkeys","hourStep","minuteStep","incrementedSelected","addMinutes","decrementedSelected","addSeconds","secondStep","getHoursFromTemplate","getMinutesFromTemplate","updateTemplate","getSecondsFromTemplate","pad","noPad","isScrollingUp","invalidate","invalidHours","invalidMinutes","invalidSeconds","modelIsEmpty","makeValid","keyboardChange","addSecondsToSelected","newDate","uibTimepickerConfig","timepickerCtrl","TYPEAHEAD_REGEXP","originalScope","$$debounce","typeaheadParser","HOT_KEYS","eventDebounceTime","minLength","waitTime","isEditable","isLoadingSetter","isSelectEvent","vals","onSelectCallback","isSelectOnBlur","isNoResultsSetter","inputFormatter","focusFirst","selectOnExact","isOpenSetter","showHint","parsedModel","$setModelValue","parserResult","hasFocus","offDestroy","popupId","inputsContainer","hintInputElem","popUpEl","resetHint","resetMatches","getMatchId","inputIsExactMatch","inputValue","getMatchesAsync","onCurrentRequest","recalculatePosition","firstLabel","fireRecalculating","debouncedRecalculate","scheduleSearchWithTimeout","cancelPreviousTimeout","activeIdx","shouldSelect","dismissClickHandler","_modelCtrl","candidateViewValue","emptyViewValue","isDropdownOpen","matchIdx","tplEl","isSanitizePresent","escapeRegexp","queryToEscape","containsHtml","matchItem","angularUiBootstrap","$sanitizeMinErr","nodeContains","htmlParser","htmlSanitizeWriter","$SanitizeProvider","hasBeenInstantiated","svgEnabled","validElements","svgElements","isImage","enableSvg","addElementsTo","voidElements","validAttrs","arrayToMap","htmlParserImpl","htmlSanitizeWriterImpl","SURROGATE_PAIR_REGEXP","NON_ALPHANUMERIC_REGEXP","stringToMap","optionalEndTagBlockElements","optionalEndTagInlineElements","optionalEndTagElements","blockElements","inlineElements","blockedElements","uriAttrs","htmlAttrs","svgAttrs","lowercaseKeys","elementsMap","newElements","getInertBodyElement","isDOMParserAvailable","getInertBodyElement_DOMParser","inertDocument","inertBodyElement","getInertBodyElement_InertDocument","stripCustomNsAttrs","mXSSAttempts","attrToMap","getNonDescendant","encodeEntities","uriValidator","ignoreCurrentElement","lkey","attrNode","sanitizeText","writer","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","linkyMinErr","attributesFn","addText","addLink","linkAttributes","angularSanitize","patchXHR","fnName","newFn","redefineProp","initializeUploadListener","origAddEventListener","formData","fileApiXHR","isInputTypeFile","hasFlash","fo","getOffset","jsUrl","basePath","allScripts","fileElem","fixInputStyle","fileApiChangeFn","disable","loadStarted","constructEvent","ngFileUpload","upload","resumeSupported","sendHttp","notifyProgress","getNotifyEvent","uploadWithAngular","fileSize","origXhrFn","toResumeFile","addFieldToFormData","objectKey","digestConfig","arrayBufferView","ngFileUpload$1","UploadExif","modelOptions","applyExifRotations","fixedFile","resizeFile","resizeVal","resizeWithParams","handleFile","resizedFile","fileChange","noDelay","invalidFiles","newFiles","dupFiles","isSingleModel","invalidModel","allNewFiles","prevValidFiles","prevInvalidFiles","invalids","valids","removeDuplicates","f1","f2","isInPrevFiles","resizeAndUpdate","updateModel","keep","resizingFiles","validateAfterResize","validationResult","Upload","generatedElems","isDelayedClickSupported","linkFileSelect","attrGetter","fileChangeAttr","fileList","unwatches","bindAttrToFileInput","updateId","createFileInput","clickHandler","detectSwipe","resetModel","initialTouchStartY","initialTouchStartX","currentX","currentY","ie10SameFileSelectFix","UploadBase","disallowObjectUrl","URL","maxMemory","maxLength","fileReader","getTagType","linkFileDirective","resizeParams","isBackground","constructDataUrl","UploadDataUrl","trustedUrl","globStringToRegex","excludes","exclude","xIndex","filesArray","markModelAsDirty","validationName","dName","prevLength","ignoredErrors","runAllValidation","validateSync","totalSize","validateAsync","asyncFn","resolveResult","resolveInternal","deffer","dataUrl","img","secondsCounter","checkLoadErrorInCaseOfNoCallback","checkLoadError","UploadValidate","calculateAspectRatioFit","srcWidth","srcHeight","centerCrop","imagen","quality","resizeIf","canvasElement","imageElement","imgWidth","imgHeight","ratioFloat","imgRatio","dataurl","origSize","bstr","u8arr","linkDrop","dropAvailable","isDisabled","leaveTimeout","dragOverDelay","actualDragOverClass","calculateDragOverClass","extractFilesAndUpdateModel","updateOnType","extractFiles","extractFilesFromHtml","updateOn","dClass","allowDir","maxFiles","maxTotalSize","includeDir","traverseFileTree","dirReader","readEntries","UploadResize","applyTransform","orientation","slicedFile","marker","little","tags","arrayBufferToBase64","ExifRestorer","origFileBase64","resizedFileBase64","rawImage","exifArray","newImageArray","seg","imageData","separatePoint","mae","ato","rawImageArray","endPoint","base64test","runTranslate","$translate","$translateDefaultInterpolation","translateDirective","translateAttrDirective","translateCloakDirective","translateFilterFactory","$translationCache","fallbackFromIncorrectStorageValue","preferred","$translateSanitizationProvider","currentStrategy","hasConfiguredStrategy","hasShownNoStrategyConfiguredWarning","strategies","htmlSanitizeValue","htmlEscapeValue","mapInterpolationParameters","htmlTrustValue","strategyName","strategyFunction","cachedStrategyMap","applyStrategies","selectedStrategies","selectedStrategy","showNoStrategyConfiguredWarning","iteratee","propertyValue","propertyKey","$STORAGE_KEY","$windowProvider","pascalprechtTranslateOverrider","$translationTable","$preferredLanguage","$availableLanguageKeys","$languageKeyAliases","$fallbackLanguage","$fallbackWasString","$uses","$nextLang","$storageFactory","$storageKey","$storagePrefix","$missingTranslationHandlerFactory","$interpolationFactory","$interpolatorFactories","$loaderFactory","$cloakClassName","$loaderOptions","$notFoundIndicatorLeft","$notFoundIndicatorRight","$postCompilingEnabled","$forceAsyncReloadEnabled","$allowNamespaces","$nestedObjectDelimeter","$isReady","$keepContent","loaderCache","directivePriority","statefulFilter","postProcessFn","uniformLanguageTagResolver","languageTagResolver","temp","getFirstBrowserLanguage","nav","browserLanguagePropertyKeys","getLocale","indexOf","searchElement","negotiateLocale","alias","langKeyAlias","hasWildcardKey","hasExactKey","translations","langKey","translationTable","flatObject","namespacesEnabled","prevKey","keyWithPath","keyWithShortPath","setupPreferredLanguage","indicator","fallbackStack","loaderFactory","storageFactory","languageKeys","aliases","Storage","defaultInterpolator","pendingLoader","interpolatorHashMap","langPromises","fallbackIndex","startFallbackIteration","translationId","interpolateParams","interpolationId","defaultTranslationText","forceLanguage","sanitizeStrategy","uses","loadTranslationsIfMissing","translateAll","translationIds","regardless","promiseToWaitFor","determineTranslation","promiseResolved","applyNotFoundIndicators","useLanguage","eachInterpolator","interpolator","loadAsync","loaderOptions","onLoaderSuccess","onLoaderError","eachInterpolationFactory","interpolatorFactory","getTranslationTable","onResolve","getFallbackTranslation","Interpolator","translation","interpolatedValue","applyPostProcessing","getFallbackTranslationInstant","translateByHandler","resolveForFallbackLanguage","fallbackLanguageIndex","missingTranslationHandlerTranslation","resolveForFallbackLanguageInstant","fallbackTranslation","fallbackTranslationInstant","resolvedTranslation","_translationId","determineTranslationInstant","clearNextLangAndPromise","langKeyPosition","updatedLanguages","loadNewData","languageKey","languagesToReload","possibleLangKeys","possibleLangKey","$onReadyDeferred","globalOnReadyListener","globalOnChangeListener","processAsyncResult","fallbackLanguageId","$translateSanitization","$translateInterpolator","$identifier","interpolationParams","interpolatedText","translateValuesExist","translateInterpolation","translateSanitizeStrategyExist","translateValueExist","interpolateRegExp","watcherRegExp","iElement","iAttr","getTranslateNamespace","initInterpolationParams","observeElementTranslation","iElementText","interpolateMatches","watcherMatches","updateTranslations","observeAttributeTranslation","translateAttr","firstAttributeChangedEvent","observeValueAttribute","updateTranslation","translateNamespace","applyTranslation","successful","globallyEnabled","locallyDefined","locallyEnabled","unbind","translateValues","translateSanitizeStrategy","previousAttributes","watchAttribute","valueCallback","changeCallback","applyCloak","removeCloak","iRemoveCloak","iApplyCloak","translateNamespaceDirective","iAttrs","_getTranslateNamespace","translateLanguageDirective","newTranslateLanguage","translateFilter","interpolation","ControllersRegistration","AppendNodeDirective","Bs5","EnumParserFunctions","IfRoleDirective","IfSitemapDirective","compareTo","LoaderDirective","OrderbyDirective","ValidatorFunctions","attrValue","validationFunction","validationFunctions","DatepickerInputValidationDirective","datepickerOptions","modelValueDay","minDateDay","maxDateDay","_getDefaults","_defaults","changeDefaults","newDefaults","escapeTest","escapeReplace","escapeTestNoEncode","escapeReplaceNoEncode","escapeReplacements","getEscapeReplacement","escape$1","unescapeTest","unescape","edit","valSource","cleanUrl","noopTest","splitCells","tableRow","escaped","rtrim","invert","suffLen","currChar","findClosingBracket","outputLink","cap","indentCodeCompensation","matchIndentToCode","indentToCode","matchIndentInNode","indentInNode","_Tokenizer","trimmed","tokens","bull","isordered","itemRegex","itemContents","endsWithBlankLine","endEarly","nextLine","blankLine","nextBulletRegex","hrRegex","fencesBeginRegex","headingBeginRegex","rawLine","istask","ischecked","spacers","hasMultipleLineBreaks","aligns","trimmedUrl","rtrimSlash","lastParenIndex","linkLen","linkString","maskedSrc","prevChar","lLength","rDelim","rLength","delimTotal","midDelimTotal","endReg","lastCharLength","hasNonSpaceChars","hasSpaceCharsOnBothEnds","prevCapZero","newline","blockCode","fences","hr","bullet","lheading","_paragraph","blockText","_blockLabel","_tag","_comment","paragraph","blockNormal","gfmTable","blockGfm","blockPedantic","inlineCode","br","inlineText","_punctuation","punctuation","blockSkip","emStrongLDelim","emStrongRDelimAst","emStrongRDelimUnd","anyPunctuation","autolink","_inlineComment","_inlineLabel","reflink","nolink","reflinkSearch","inlineNormal","inlinePedantic","inlineGfm","inlineBreaks","_Lexer","leading","tabs","lastToken","cutSrc","lastParagraphClipped","extTokenizer","tempSrc","tempStart","getStartIndex","errMsg","keepPrevChar","_Renderer","infostring","startatt","task","checked","cleanHref","_TextRenderer","_Parser","genericToken","headingToken","codeToken","tableToken","blockquoteToken","listToken","loose","itemBody","htmlToken","paragraphToken","textToken","renderer","escapeToken","tagToken","linkToken","imageToken","strongToken","emToken","codespanToken","delToken","_Hooks","markdown","Marked","__privateAdd","_parseMarkdown","_onError","__privateMethod","parseMarkdown_fn","childTokens","ext","prevRenderer","extLevel","rendererProp","rendererFunc","tokenizer","tokenizerProp","tokenizerFunc","prevTokenizer","hooksProp","hooksFunc","prevHook","walkTokens","packWalktokens","origOpt","throwError","onError_fn","async","markedInstance","marked","HtmlDirective","cElement","cAttr","endsWith","sxyHtml","TextDirective","wsTranslate","getUntrimmedAttributeValue","DirectivesRegistration","_FilterFunctions","splitValues","employmentData","nullText","zeroText","addWorkDays","messageTypes","uiClassMarker","uiClassEndMarker","uiClass","fullMessage","dtReg","shortMessage","sectionToCheck","sitemapPath","splitPaths","companySite","resultSitemapNode","currentSection","visibilityToEvaluate","FilterFunctions","FiltersRegistration","LoaderInterceptor","rejection","TemplateInterceptor","views","ServicesRegistration","CustomerInvoices","Absences","Accounts","AccountSettings","BeneficialOwnersApi","Calculator","CalendarEvents","Client","Datasets","Employments","Files","HolidayYears","Imports","Invoices","IrEarningsPayments","IrPayerSummaries","MessageThreads","OAuth2","Onboardings","Overview","PartnerServices","ProApi","ReferenceObjects","Reports","Session","Taxcards","Test","Usecases","Workers","ServiceModels","HouseholdYears","SalaxyNg1ComponentsModule","ngBs","sco","tx","$httpProvider","$translateProvider","$locationProvider","SalaxyNg1BootstrapTemplatesModule","_PersonalWebLegacyController","PersonalWebLegacyController","_PersonalWebSiteMap","PersonalWebSiteMap","routeHelperProvider","personalRoot"],"mappings":"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B,MAAO,CAAC,EAAGrc,EAAG,EAAG3tB,CAAC,CACpB,CAEAsM,EAAS,MAAM,UAAW,CACxB,iBAAoB,CAClB,MAAS,CACP,KACA,IACD,EACD,IAAO,CACL,SACA,SACA,UACA,YACA,WACA,SACA,UACD,EACD,SAAY,CACV,gBACA,aACD,EACD,KAAQ,CACN,KACA,IACD,EACD,eAAkB,EAClB,MAAS,CACP,UACA,WACA,QACA,QACA,MACA,OACA,OACA,SACA,YACA,UACA,WACA,UACD,EACD,SAAY,CACV,MACA,MACA,MACA,MACA,MACA,MACA,KACD,EACD,WAAc,CACZ,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,KACD,EACD,gBAAmB,CACjB,UACA,WACA,QACA,QACA,MACA,OACA,OACA,SACA,YACA,UACA,WACA,UACD,EACD,aAAgB,CACd,EACA,CACD,EACD,SAAY,kBACZ,SAAY,YACZ,OAAU,qBACV,WAAc,WACd,WAAc,YACd,MAAS,gBACT,UAAa,SACb,UAAa,QACd,EACD,eAAkB,CAChB,aAAgB,IAChB,YAAe,IACf,UAAa,IACb,SAAY,CACV,CACE,MAAS,EACT,OAAU,EACV,QAAW,EACX,QAAW,EACX,OAAU,EACV,OAAU,IACV,OAAU,GACV,OAAU,GACV,OAAU,EACX,EACD,CACE,MAAS,EACT,OAAU,EACV,QAAW,EACX,QAAW,EACX,OAAU,EACV,OAAU,KACV,OAAU,GACV,OAAU,IACV,OAAU,EACX,CACF,CACF,EACD,GAAM,QACN,SAAY,QACZ,UAAa,SAAS4wC,EAAG4lB,EAAe,CAAG,IAAIrhE,EAAIy7C,EAAI,EAAQ6lB,EAAKF,EAAM3lB,EAAG4lB,CAAa,EAAI,OAAIrhE,GAAK,GAAKshE,EAAG,GAAK,EAAeJ,EAAgB,IAAgBA,EAAgB,KAAM,CAC3L,CAAC,CACD,CAAC,CAAC,EAEAvgE,EAAO,UAAW,CAChB2J,GAAY5L,EAAO,SAAU6L,EAAS,CAC1C,CAAG,CAEH,GAAG,MAAM,EAET,CAAC,OAAO,QAAQ,MAAO,EAAC,eAAiB,OAAO,QAAQ,Q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7E,CAAI,CACtC,CAEH,CCvBO,MAAMw7E,GAAqC,CAChD,CACE,MAAO,sBACP,IAAK,gBACL,GAAI,aACJ,MAAO,SACP,SAAU,CACR,CACE,MAAO,eACP,IAAK,SACL,GAAI,OACN,EACA,CACE,MAAO,aACP,IAAK,eACL,GAAI,OACN,EACA,CACE,MAAO,YACP,IAAK,gBACL,GAAI,QACN,EACA,CACE,MAAO,iBACP,IAAK,mBACL,WAAY,SACZ,GAAI,SACN,EACA,CACE,MAAO,gBACP,IAAK,kCACL,WAAY,SACZ,GAAI,cACN,EACA,CACE,MAAO,kBACP,IAAK,+BACL,WAAY,SACZ,GAAI,WACN,EACA,CACE,MAAO,yBACP,IAAK,4BACL,GAAI,aACJ,MAAO,QACT,EACA,CACE,MAAO,wBACP,IAAK,+BACL,GAAI,gBACJ,MAAO,QACT,EACA,CACE,MAAO,wBACP,IAAK,qBACL,MAAO,SACP,GAAI,MACN,EACA,CACE,MAAO,qBACP,IAAK,eACL,MAAO,SACP,GAAI,OACN,CACF,CACF,EACA,CACE,MAAO,qBACP,IAAK,mCACL,GAAI,UACJ,MAAO,SACP,SAAU,CACR,CACE,MAAO,8BACP,IAAK,mCACL,GAAI,sBACN,EACA,CACE,MAAO,qBACP,IAAK,2BACL,GAAI,iBACJ,MAAO,mBACP,SAAU,CACR,CACE,MAAO,+BACP,IAAK,8BACL,WAAY,SACZ,MAAO,mBACP,GAAI,SACN,CACF,CACF,EACA,CACE,MAAO,gCACP,IAAK,iCACL,GAAI,oBACN,EACA,CACE,IAAK,2BACL,GAAI,eACN,EACA,CACE,IAAK,4BACL,MAAO,OACP,GAAI,gBACN,EACA,CACE,MAAO,SACP,IAAK,aACL,GAAI,WACJ,SAAU,CACR,CACE,MAAO,gBACP,IAAK,uBACL,WAAY,SACZ,GAAI,SACN,CACF,CACF,EACA,CACE,MAAO,yBACP,IAAK,UACL,SAAU,CAAC,CACT,MAAO,sBACP,IAAK,mBAAA,CACN,CACH,EACA,CACE,MAAO,qBACP,IAAK,UACL,GAAI,QACJ,SAAU,CAAC,CACT,MAAO,kBACP,IAAK,oBA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CACxD,CACF,CACF,CACF,CACF,CACF,EACA,CACE,IAAK,2BACL,GAAI,gBACJ,WAAY,UACZ,YAAa,EACf,EACA,CACE,IAAK,uCACL,YAAa,GACb,GAAI,wBACJ,WAAY,QACd,EACA,CACE,IAAK,UACL,GAAI,QACJ,MAAO,MACP,SAAU,CAAC,CACT,IAAK,oBACL,GAAI,SAAA,CACL,CACH,EACA,CACE,IAAK,UACL,GAAI,QACJ,MAAO,MACP,SAAU,CAAC,CACT,IAAK,oBACL,GAAI,SAAA,CACL,CACH,CACF,CACF,EACA,CACE,IAAK,aACL,GAAI,WACJ,MAAO,UACP,SAAU,CACR,CACE,IAAK,aACL,GAAI,QACJ,OAAQ,CACN,SAAU,CACR,MAAO,WACP,KAAM,QACN,QAAS,CAAC,UAAW,aAAc,aAAc,iBAAiB,EAClE,MAAO,CACL,KAAM,SACN,KAAO,CAAC,UAAW,aAAc,aAAc,iBAAiB,CAClE,CACF,CACF,CACF,EACA,CACE,IAAK,8BACL,GAAI,kBACJ,KAAM,CAAE,qCAAqC,CAE/C,EACA,CACE,IAAK,wBACL,GAAI,aACJ,KAAM,CAAE,uCAAuC,CACjD,EACA,CACE,IAAK,gCACL,MAAO,OACP,GAAI,kBACN,EACA,CACE,IAAK,sCACL,GAAI,wBACN,EACA,CACE,IAAK,wCACL,GAAI,0BACN,EACA,CACE,IAAK,4BACL,GAAI,eACN,EACA,CACE,IAAK,8BACL,GAAI,iBACN,EACA,CACE,IAAK,4BACL,GAAI,gBACN,EACA,CACE,GAAI,cACJ,IAAK,yBACL,MAAO,UACP,KAAK,CAAC,iCAAiC,yCAAyC,EAChF,OAAQ,CACN,0BAA6B,CAC3B,MAAO,oCACP,KAAM,SACR,CACF,CACF,EACA,CACE,GAAI,eACJ,IAAK,yBACP,EACA,CACE,GAAI,eACJ,IAAK,2BACL,MAAO,MACT,EACA,CACE,GAAI,iBACJ,IAAK,oBACL,WAAY,QACd,CACF,CACF,EACA,CACE,IAAK,yBACL,GAAI,cACJ,MAAO,gBACP,SAAU,CACR,CACE,IAAK,6BACL,GAAI,UACJ,WAAY,SACZ,YAAa,EACf,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AClB,MAAS,CACP,MACA,KACD,EACD,IAAO,CACL,cACA,cACA,YACA,gBACA,YACA,cACA,YACD,EACD,SAAY,CACV,4BACA,6BACD,EACD,KAAQ,CACN,OACA,MACD,EACD,eAAkB,EAClB,MAAS,CACP,aACA,aACA,cACA,aACA,aACA,YACA,aACA,WACA,YACA,YACA,cACA,YACD,EACD,SAAY,CACV,KACA,KACA,KACA,KACA,KACA,KACA,IACD,EACD,WAAc,CACZ,UACA,UACA,WACA,UACA,UACA,SACA,UACA,QACA,SACA,SACA,WACA,SACD,EACD,gBAAmB,CACjB,WACA,WACA,YACA,WACA,WACA,UACA,WACA,SACA,UACA,UACA,YACA,UACD,EACD,aAAgB,CACd,EACA,CACD,EACD,SAAY,iBACZ,SAAY,YACZ,OAAU,gBACV,WAAc,QACd,WAAc,UACd,MAAS,aACT,UAAa,QACb,UAAa,MACd,EACD,eAAkB,CAChB,aAAgB,IAChB,YAAe,IACf,UAAa,IACb,SAAY,CACV,CACE,MAAS,EACT,OAAU,EACV,QAAW,EACX,QAAW,EACX,OAAU,EACV,OAAU,IACV,OAAU,GACV,OAAU,GACV,OAAU,EACX,EACD,CACE,MAAS,EACT,OAAU,EACV,QAAW,EACX,QAAW,EACX,OAAU,EACV,OAAU,IACV,OAAU,KACV,OAAU,GACV,OAAU,IACX,CACF,CACF,EACD,GAAM,KACN,SAAY,KACZ,UAAa,SAAS,EAAGw2D,EAAe,CAAG,IAAIrhE,EAAI,EAAI,EAAQshE,EAAKF,EAAM,EAAGC,CAAa,EAAI,OAAIrhE,GAAK,GAAKshE,EAAG,GAAK,EAAeJ,EAAgB,IAAgBA,EAAgB,KAAM,CAC3L,CAAC,CACD,CAAC,CAAC,ECxIC,QAAQ,OAAO,eAAgB,CAAC,oBAAqB,wBAAwB,wBAAwB,yBAAyB,qBAAqB,uBAAuB,wBAAwB,0BAA0B,uBAAuB,0BAA0B,wBAAwB,+BAA+B,wBAAwB,wBAAwB,wBAAwB,0BAA0B,qBAAqB,sBAAsB,qBAAqB,0BAA0B,uBAAuB,uBAAuB,2BAA2B,sBAAsB,oBAAoB,0BAA0B,wBA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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAkW/D,EAENA,EAAe,IAAI,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiH5D,EAENA,EAAe,IAAI,mCAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAqNhD,EAENA,EAAe,IAAI,wCAAwC;AAAA;AAAA;AAAA;AAAA,CAI3D,EAEAA,EAAe,IAAI,iDAAiD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAqD9D,EAENA,EAAe,IAAI,4CAA4C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAYzD,EAENA,EAAe,IAAI,yCAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAqXtD,EAENA,EAAe,IAAI,yCAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAgKtD,EAENA,EAAe,IAAI,uCAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6BpD,EAENA,EAAe,IAAI,2CAA2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiCxD,EAENA,EAAe,IAAI,yCAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQtD,EAENA,EAAe,IAAI,0CAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsIvD,EAENA,EAAe,IAAI,0CAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiJvD,EAENA,EAAe,IAAI,0CAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoFvD,EAENA,EAAe,IAAI,8CAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAU7D,EAEJA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAanE,EAEPA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiC1D,EAENA,EAAe,IAAI,2CAA2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoPxD,EAENA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+I1D,EAENA,EAAe,IAAI,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAgB3D,EAEPA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWzD,EAEPA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAqEzD,EAEPA,EAAe,IAAI,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4JhE,EAENA,EAAe,IAAI,wCAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAwBrD,EAENA,EAAe,IAAI,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAuM3D,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAgDtE,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuD5E,EAEAA,EAAe,IAAI,uEAAuE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAqJ7E,EAEbA,EAAe,IAAI,0DAA0D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA8oBvE,EAENA,EAAe,IAAI,sDAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,IAAI,wDAAwD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4GrE,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4BnE,EAENA,EAAe,IAAI,iEAAiE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAwD7E,EAEPA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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,EAENA,EAAe,IAAI,6DAA6D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0K1E,EAENA,EAAe,IAAI,wDAAwD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAqBpE,EAEPA,EAAe,IAAI,wDAAwD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+FpE,EAENA,EAAe,IAAI,4DAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0DzE,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6DpE,EAENA,EAAe,IAAI,4DAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+F1E,EAENA,EAAe,IAAI,sDAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiFnE,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4LpE,EAENA,EAAe,IAAI,qEAAqE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoClF,EAENA,EAAe,IAAI,0DAA0D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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AAAA,OAqDjE,EAENA,EAAe,IAAI,8CAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAyE3D,EAENA,EAAe,IAAI,qDAAqD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA8MlE,EAENA,EAAe,IAAI,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4ChE,EAENA,EAAe,IAAI,4DAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoGzE,EAENA,EAAe,IAAI,oDAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoHjE,EAENA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAoP1D,EAEPA,EAAe,IAAI,mDAAmD;AAAA;AAAA;AAAA;AAAA,QAI/D,EAEPA,EAAe,IAAI,qDAAqD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA8C3D,EAENA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAuJ/D,EAENA,EAAe,IAAI,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiI5D,EAENA,EAAe,IAAI,iDAAiD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAmO9D,EAENA,EAAe,IAAI,iDAAiD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAmC9D,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4KxE,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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e,IAAI,oDAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA8BvE,EAEAA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA8BrE,EAEAA,EAAe,IAAI,sDAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuLzE,EAEAA,EAAe,IAAI,8CAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+K3D,EAENA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAsV5D,EAETA,EAAe,IAAI,sDAAsD;AAAA;AAAA;AAAA,OAGnE,EAENA,EAAe,IAAI,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0RvE,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4E3E,EAENA,EAAe,IAAI,oEAAoE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0GjF,EAENA,EAAe,IAAI,oEAAoE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAkIjF,EAENA,EAAe,IAAI,oEAAoE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4LjF,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsDxE,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0CtE,EAENA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA2D/D,EAENA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0K1D,EAENA,EAAe,IAAI,gDAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoK7D,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAgEtE,EAENA,EAAe,IAAI,kDAAkD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0M/D,EAENA,EAAe,IAAI,8CAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAqV3D,EAENA,EAAe,IAAI,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAyJhE,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6EtE,EAENA,EAAe,IAAI,sDAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAubnE,EAENA,EAAe,IAAI,gDAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsD7D,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoKtE,EAENA,EAAe,IAAI,mEAAmE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0DhF,EAENA,EAAe,IAAI,gEAAgE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiI7E,EAENA,EAAe,IAAI,4EAA4E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6EzF,EAENA,EAAe,IAAI,mEAAmE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAmChF,EAENA,EAAe,IAAI,kEAAkE;AAAA;AAAA;AAAA,OAG/E,EAENA,EAAe,IAAI,wDAAwD;AAAA;AAAA;AAAA;AAAA;AAAA,OAKrE,EAENA,EAAe,IAAI,kEAAkE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiF/E,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+BpE,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAyGxE,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAuBpE,EAENA,EAAe,IAAI,4DAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6HzE,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoDxE,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAc3E,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsEtE,EAENA,EAAe,IAAI,mEAAmE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4BhF,EAENA,EAAe,IAAI,0DAA0D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0CvE,EAENA,EAAe,IAAI,qDAAqD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAclE,EAENA,EAAe,IAAI,gDAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6C7D,EAENA,EAAe,IAAI,qDAAqD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+BlE,EAENA,EAAe,IAAI,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAkC5D,EAENA,EAAe,IAAI,6CAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA4B1D,EAENA,EAAe,IAAI,8CAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAU3D,EAENA,EAAe,IAAI,4DAA4D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+BzE,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6C3E,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAyBxE,EAENA,EAAe,IAAI,2DAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoExE,EAENA,EAAe,IAAI,+DAA+D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA0D5E,EAENA,EAAe,IAAI,kEAAkE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA+G/E,EAENA,EAAe,IAAI,uDAAuD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAsLpE,EAENA,EAAe,IAAI,yDAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAiBtE,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAyC3E,EAENA,EAAe,IAAI,8DAA8D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAoL3E,EAENA,EAAe,IAAI,0DAA0D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","x_google_ignoreList":[11,12,24,25,26,73,74,75,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,160,161,162,163,164,165,166,167,178,458,459,460,461,462,463,464,465,466,467,478]}